diff --git a/libs/libvtrutil/src/specrand.cpp b/libs/libvtrutil/src/specrand.cpp index 4440121dcde..edc25145c29 100644 --- a/libs/libvtrutil/src/specrand.cpp +++ b/libs/libvtrutil/src/specrand.cpp @@ -52,32 +52,15 @@ #include "specrand.h" -/* Period parameters */ -#define N 624 -#define M 397 -#define MATRIX_A 0x9908b0dfUL /* constant vector a */ -#define UPPER_MASK 0x80000000UL /* most significant w-r bits */ -#define LOWER_MASK 0x7fffffffUL /* least significant r bits */ - -static unsigned long mt[N]; /* the array for the state vector */ -static int mti = N + 1; /* mti==N+1 means mt[N] is not initialized */ - -void spec_srand(int seed) { - spec_init_genrand((unsigned long)seed); +double SpecRandomNumberGenerator::spec_rand_() { + return spec_genrand_int32_() * (1.0 / 4294967296.0); } -/* Just a copy of spec_genrand_real2() */ -double spec_rand() { - return spec_genrand_int32() * (1.0 / 4294967296.0); +long SpecRandomNumberGenerator::spec_lrand48_() { + return (long)(spec_genrand_int32_() >> 1); } -/* Just a copy of spec_genrand_int31() */ -long spec_lrand48() { - return (long)(spec_genrand_int32() >> 1); -} - -/* initializes mt[N] with a seed */ -void spec_init_genrand(unsigned long s) { +void SpecRandomNumberGenerator::spec_init_genrand_(unsigned long s) { mt[0] = s & 0xffffffffUL; for (mti = 1; mti < N; mti++) { mt[mti] = (1812433253UL * (mt[mti - 1] ^ (mt[mti - 1] >> 30)) + mti); @@ -90,16 +73,11 @@ void spec_init_genrand(unsigned long s) { } } -/* initialize by an array with array-length */ -/* init_key is the array for initializing keys */ -/* key_length is its length */ -/* slight change for C++, 2004/2/26 */ -void spec_init_by_array(unsigned long init_key[], int key_length) { - int i, j, k; - spec_init_genrand(19650218UL); - i = 1; - j = 0; - k = (N > key_length ? N : key_length); +void SpecRandomNumberGenerator::spec_init_by_array_(const unsigned long init_key[], size_t key_length) { + spec_init_genrand_(19650218UL); + size_t i = 1; + size_t j = 0; + size_t k = (N > key_length ? N : key_length); for (; k; k--) { mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1664525UL)) + init_key[j] + j; /* non linear */ @@ -127,22 +105,21 @@ void spec_init_by_array(unsigned long init_key[], int key_length) { } /* generates a random number on [0,0xffffffff]-interval */ -unsigned long spec_genrand_int32() { +unsigned long SpecRandomNumberGenerator::spec_genrand_int32_() { unsigned long y; static unsigned long mag01[2] = {0x0UL, MATRIX_A}; /* mag01[x] = x * MATRIX_A for x=0,1 */ if (mti >= N) { /* generate N words at one time */ - int kk; if (mti == N + 1) /* if init_genrand() has not been called, */ - spec_init_genrand(5489UL); /* a default initial seed is used */ + spec_init_genrand_(5489UL); /* a default initial seed is used */ - for (kk = 0; kk < N - M; kk++) { + for (size_t kk = 0; kk < N - M; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK); mt[kk] = mt[kk + M] ^ (y >> 1) ^ mag01[y & 0x1UL]; } - for (; kk < N - 1; kk++) { + for (size_t kk; kk < N - 1; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK); mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1UL]; } @@ -163,32 +140,45 @@ unsigned long spec_genrand_int32() { return y; } -/* generates a random number on [0,0x7fffffff]-interval */ -long spec_genrand_int31() { - return (long)(spec_genrand_int32() >> 1); +long SpecRandomNumberGenerator::spec_genrand_int31_() { + return (long)(spec_genrand_int32_() >> 1); } -/* generates a random number on [0,1]-real-interval */ -double spec_genrand_real1() { - return spec_genrand_int32() * (1.0 / 4294967295.0); +double SpecRandomNumberGenerator::spec_genrand_real1_() { + return spec_genrand_int32_() * (1.0 / 4294967295.0); /* divided by 2^32-1 */ } -/* generates a random number on [0,1)-real-interval */ -double spec_genrand_real2() { - return spec_genrand_int32() * (1.0 / 4294967296.0); +double SpecRandomNumberGenerator::spec_genrand_real2_() { + return spec_genrand_int32_() * (1.0 / 4294967296.0); /* divided by 2^32 */ } -/* generates a random number on (0,1)-real-interval */ -double spec_genrand_real3() { - return (((double)spec_genrand_int32()) + 0.5) * (1.0 / 4294967296.0); +double SpecRandomNumberGenerator::spec_genrand_real3_() { + return (((double)spec_genrand_int32_()) + 0.5) * (1.0 / 4294967296.0); /* divided by 2^32 */ } -/* generates a random number on [0,1) with 53-bit resolution*/ -double spec_genrand_res53() { - unsigned long a = spec_genrand_int32() >> 5, b = spec_genrand_int32() >> 6; +double SpecRandomNumberGenerator::spec_genrand_res53_() { + unsigned long a = spec_genrand_int32_() >> 5, b = spec_genrand_int32_() >> 6; return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0); } -/* These real versions are due to Isaku Wada, 2002/01/09 added */ + +void SpecRandomNumberGenerator::srandom(int seed) { + spec_init_genrand_((unsigned long)seed); +} + +int SpecRandomNumberGenerator::irand(int imax) { + return (int)(spec_genrand_int31_() % (imax + 1)); +} + +float SpecRandomNumberGenerator::frand() { + return (float)spec_genrand_real2_(); +} + +SpecRandomNumberGenerator::SpecRandomNumberGenerator(int seed) { + spec_init_genrand_((unsigned long)seed); +} + +SpecRandomNumberGenerator::SpecRandomNumberGenerator() + : SpecRandomNumberGenerator(0) {} diff --git a/libs/libvtrutil/src/specrand.h b/libs/libvtrutil/src/specrand.h index 9aff86ccbd1..9a7634e678c 100644 --- a/libs/libvtrutil/src/specrand.h +++ b/libs/libvtrutil/src/specrand.h @@ -52,35 +52,69 @@ /* Slightly modified for use in SPEC CPU by Cloyce D. Spradling (5 Nov 2009) */ -void spec_srand(int seed); -double spec_rand(); -long spec_lrand48(); +#include "vtr_random.h" -/* initializes mt[N] with a seed */ -void spec_init_genrand(unsigned long s); +class SpecRandomNumberGenerator : public vtr::RandomNumberGeneratorInterface { + public: + SpecRandomNumberGenerator(const SpecRandomNumberGenerator&) = delete; + SpecRandomNumberGenerator& operator=(SpecRandomNumberGenerator& other) = delete; -/* initialize by an array with array-length */ -/* init_key is the array for initializing keys */ -/* key_length is its length */ -/* slight change for C++, 2004/2/26 */ -void spec_init_by_array(unsigned long init_key[], int key_length); + SpecRandomNumberGenerator(); + explicit SpecRandomNumberGenerator(int seed); -/* generates a random number on [0,0xffffffff]-interval */ -unsigned long spec_genrand_int32(); + virtual void srandom(int seed) override; + virtual int irand(int imax) override; + virtual float frand() override; -/* generates a random number on [0,0x7fffffff]-interval */ -long spec_genrand_int31(); + private: + /// @brief initializes mt[N] with a seed + void spec_init_genrand_(unsigned long s); -/* generates a random number on [0,1]-real-interval */ -double spec_genrand_real1(); + /** + * @brief initialize by an array with array-length + * @param init_key the array for initializing keys + * @param key_length the length of array + */ + void spec_init_by_array_(const unsigned long init_key[], size_t key_length); -/* generates a random number on [0,1)-real-interval */ -double spec_genrand_real2(); + /// @brief generates a random number on [0,0xffffffff]-interval + unsigned long spec_genrand_int32_(); -/* generates a random number on (0,1)-real-interval */ -double spec_genrand_real3(); + /// @brief Just a copy of spec_genrand_real2() + double spec_rand_(); + /// @brief Just a copy of spec_genrand_int31() + long spec_lrand48_(); -/* generates a random number on [0,1) with 53-bit resolution*/ -double spec_genrand_res53(); + /// @brief generates a random number on [0,0x7fffffff]-interval */ + long spec_genrand_int31_(); + + /// @brief generates a random number on [0,1]-real-interval + double spec_genrand_real1_(); + + /// @brief generates a random number on [0,1)-real-interval + double spec_genrand_real2_(); + + /// @brief generates a random number on (0,1)-real-interval + double spec_genrand_real3_(); + + /// @brief generates a random number on [0,1) with 53-bit resolution + double spec_genrand_res53_(); + + private: + /// Period parameters + static constexpr size_t M = 397; + static constexpr size_t N = 624; + /// constant vector a + static constexpr unsigned long MATRIX_A = 0x9908b0dfUL; + /// most significant w-r bits + static constexpr unsigned long UPPER_MASK = 0x80000000UL; + /// least significant r bits + static constexpr unsigned long LOWER_MASK = 0x7fffffffUL; + /// mti==N+1 means mt[N] is not initialized + size_t mti = N + 1; + /// the array for the state vector + unsigned long mt[N]; + +}; #endif diff --git a/libs/libvtrutil/src/vtr_random.cpp b/libs/libvtrutil/src/vtr_random.cpp index 7e3f8ffb25d..eb1756702da 100644 --- a/libs/libvtrutil/src/vtr_random.cpp +++ b/libs/libvtrutil/src/vtr_random.cpp @@ -1,91 +1,67 @@ -#include #include "vtr_random.h" +#include "specrand.h" #include "vtr_util.h" #include "vtr_error.h" -#include "specrand.h" - -#define CHECK_RAND namespace vtr { -/* Portable random number generator defined below. Taken from ANSI C by * - * K & R. Not a great generator, but fast, and good enough for my needs. */ -constexpr size_t IA = 1103515245u; -constexpr size_t IC = 12345u; -constexpr size_t IM = 2147483648u; - -static RandState random_state = 0; - -/** - * @brief The pseudo-random number generator is initialized using the argument passed as seed. - */ -void srandom(int seed) { - random_state = (unsigned int)seed; -#ifdef SPEC_CPU - /* SPEC CPU requires a different random number generator */ - spec_init_genrand((unsigned long)seed); -#endif +RandomNumberGenerator::RandomNumberGenerator(int seed) { + random_state_ = (unsigned int)seed; } -/* returns the random_state value */ -RandState get_random_state() { - return random_state; +RandomNumberGenerator::RandomNumberGenerator() + : RandomNumberGenerator(0) {} + +void RandomNumberGenerator::srandom(int seed) { + random_state_ = (unsigned int)seed; } -int irand(int imax, RandState& state) { -#ifdef SPEC_CPU - /* SPEC CPU requires a different random number generator */ - return (int)(spec_genrand_int31() % (imax + 1)); -#else - /* Creates a random integer between 0 and imax, inclusive. i.e. [0..imax] */ +int RandomNumberGenerator::irand(int imax) { + // Creates a random integer between 0 and imax, inclusive. i.e. [0..imax] int ival; - /* state = (state * IA + IC) % IM; */ - state = state * IA + IC; /* Use overflow to wrap */ - ival = state & (IM - 1); /* Modulus */ + // state = (state * IA + IC) % IM; + random_state_ = random_state_ * IA + IC; // Use overflow to wrap + ival = random_state_ & (IM - 1); // Modulus ival = (int)((float)ival * (float)(imax + 0.999) / (float)IM); -# ifdef CHECK_RAND - if ((ival < 0) || (ival > imax)) { - if (ival == imax + 1) { - /* Due to random floating point rounding, sometimes above calculation gives number greater than ival by 1 */ - ival = imax; - } else { - throw VtrError(string_fmt("Bad value in my_irand, imax = %d ival = %d", imax, ival), __FILE__, __LINE__); + if constexpr (CHECK_RAND_CONSTEXPR) { + if ((ival < 0) || (ival > imax)) { + if (ival == imax + 1) { + // Due to random floating point rounding, sometimes above calculation gives number greater than ival by 1 + ival = imax; + } else { + throw VtrError(string_fmt("Bad value in my_irand, imax = %d ival = %d", imax, ival), __FILE__, __LINE__); + } } } -# endif return ival; -#endif } -int irand(int imax) { - return irand(imax, random_state); -} +float RandomNumberGenerator::frand() { + random_state_ = random_state_ * IA + IC; /* Use overflow to wrap */ + int ival = random_state_ & (IM - 1); /* Modulus */ + float fval = (float)ival / (float)IM; -float frand() { - /* Creates a random float between 0 and 1. i.e. [0..1). */ -#ifdef SPEC_CPU - /* SPEC CPU requires a different random number generator */ - return (float)spec_genrand_real2(); -#else - float fval; - int ival; + if constexpr (CHECK_RAND_CONSTEXPR) { + if (fval < 0 || fval > 1.) { + throw VtrError(string_fmt("Bad value in my_frand, fval = %g", fval), __FILE__, __LINE__); + } + } - random_state = random_state * IA + IC; /* Use overflow to wrap */ - ival = random_state & (IM - 1); /* Modulus */ - fval = (float)ival / (float)IM; + return fval; +} -# ifdef CHECK_RAND - if ((fval < 0) || (fval > 1.)) { - throw VtrError(string_fmt("Bad value in my_frand, fval = %g", fval), __FILE__, __LINE__); +RngContainer::RngContainer(int seed) { + if constexpr (SPEC_CPU_CONSTEXPR) { + rng_ = std::make_unique(seed); + } else { + rng_ = std::make_unique(seed); } -# endif - - return (fval); -#endif } +RngContainer::RngContainer() + : RngContainer(0) {} } // namespace vtr diff --git a/libs/libvtrutil/src/vtr_random.h b/libs/libvtrutil/src/vtr_random.h index c5a3ce66351..76c8bb37912 100644 --- a/libs/libvtrutil/src/vtr_random.h +++ b/libs/libvtrutil/src/vtr_random.h @@ -1,43 +1,97 @@ #ifndef VTR_RANDOM_H #define VTR_RANDOM_H + #include //For std::swap +#include + +#define CHECK_RAND namespace vtr { -/*********************** Portable random number generators *******************/ -typedef unsigned RandState; -/** - * @brief The pseudo-random number generator is initialized using the argument passed as seed. - */ -void srandom(int seed); +class RandomNumberGeneratorInterface { + public: + virtual ~RandomNumberGeneratorInterface() = default; + + /// @brief Initialize the pseudo-random number generator using the argument passed as seed. + virtual void srandom(int seed) = 0; -///@brief Return The random number generator state -RandState get_random_state(); + ///@brief Return a randomly generated integer less than or equal imax + virtual int irand(int imax) = 0; -///@brief Return a randomly generated integer less than or equal imax -int irand(int imax); + ///@brief Return a randomly generated float number between [0,1] + virtual float frand() = 0; +}; -///@brief Return a randomly generated integer less than or equal imax using the generator (rand_state) -int irand(int imax, RandState& rand_state); +class RandomNumberGenerator : public RandomNumberGeneratorInterface { + private: + typedef unsigned state_t; -///@brief Return a randomly generated float number between [0,1] -float frand(); + public: + RandomNumberGenerator(const RandomNumberGenerator&) = delete; + RandomNumberGenerator& operator=(RandomNumberGenerator& other) = delete; + + RandomNumberGenerator(); + explicit RandomNumberGenerator(int seed); + + virtual void srandom(int seed) override; + virtual int irand(int imax) override; + virtual float frand() override; + + private: + /* Portable random number generator defined below. Taken from ANSI C by * + * K & R. Not a great generator, but fast, and good enough for my needs. */ + static constexpr size_t IA = 1103515245u; + static constexpr size_t IC = 12345u; + static constexpr size_t IM = 2147483648u; + +#ifdef CHECK_RAND + static constexpr bool CHECK_RAND_CONSTEXPR = true; +#else + static constexpr bool CHECK_RAND_CONSTEXPR = false; +#endif + + state_t random_state_ = 0; +}; + + +class RngContainer : public RandomNumberGeneratorInterface { + public: + RngContainer(const RngContainer&) = delete; + RngContainer& operator=(RngContainer& other) = delete; + + RngContainer(); + explicit RngContainer(int seed); + + inline virtual void srandom(int seed) override { rng_->srandom(seed); } + inline virtual int irand(int imax) override { return rng_->irand(imax); } + inline virtual float frand() override { return rng_->frand(); } + + private: + + std::unique_ptr rng_; + +#ifdef SPEC_CPU + static constexpr bool SPEC_CPU_CONSTEXPR = true; +#else + static constexpr bool SPEC_CPU_CONSTEXPR = false; +#endif +}; /** * @brief Portable/invariant version of std::shuffle * * Note that std::shuffle relies on std::uniform_int_distribution - * which can produce different sequences accross different + * which can produce different sequences across different * compilers/compiler versions. * * This version should be deterministic/invariant. However, since * it uses vtr::irand(), may not be as well distributed as std::shuffle. */ template -void shuffle(Iter first, Iter last, RandState& rand_state) { +void shuffle(Iter first, Iter last, RngContainer& rng) { for (auto i = (last - first) - 1; i > 0; --i) { using std::swap; - swap(first[i], first[irand(i, rand_state)]); + swap(first[i], first[rng.irand(i)]); } } diff --git a/libs/libvtrutil/test/test_random.cpp b/libs/libvtrutil/test/test_random.cpp index c2287749f97..c810bf24531 100644 --- a/libs/libvtrutil/test/test_random.cpp +++ b/libs/libvtrutil/test/test_random.cpp @@ -8,8 +8,8 @@ TEST_CASE("shuffle", "[vtr_random/shuffle]") { std::vector numbers = {1, 2, 3, 4, 5}; - vtr::RandState rand_state = 1; - vtr::shuffle(numbers.begin(), numbers.end(), rand_state); + vtr::RngContainer rng(1); + vtr::shuffle(numbers.begin(), numbers.end(), rng); std::vector numbers_shuffled_1 = {5, 2, 4, 1, 3}; REQUIRE(numbers == numbers_shuffled_1); diff --git a/vpr/src/base/CheckArch.cpp b/vpr/src/base/CheckArch.cpp index b8a324bb14f..ee9204e96bf 100644 --- a/vpr/src/base/CheckArch.cpp +++ b/vpr/src/base/CheckArch.cpp @@ -1,5 +1,3 @@ -#include - #include "vpr_types.h" #include "vpr_error.h" #include "globals.h" @@ -20,14 +18,12 @@ void CheckArch(const t_arch& Arch) { } static void CheckSwitches(const t_arch& Arch) { - t_arch_switch_inf* CurSwitch; - int i; int ipin_cblock_switch_index = UNDEFINED; int ipin_cblock_switch_index_between_dice = UNDEFINED; /* Check transistors in switches won't be less than minimum size */ - CurSwitch = Arch.Switches; - for (i = 0; i < Arch.num_switches; i++) { + t_arch_switch_inf* CurSwitch = Arch.Switches; + for (int i = 0; i < Arch.num_switches; i++) { /* This assumes all segments have the same directionality */ if (CurSwitch->buffered() && Arch.Segments[0].directionality == BI_DIRECTIONAL) { @@ -82,10 +78,9 @@ static void CheckSwitches(const t_arch& Arch) { } static void CheckSegments(const t_arch& Arch) { - auto& CurSeg = Arch.Segments; + const auto& CurSeg = Arch.Segments; for (size_t i = 0; i < (Arch.Segments).size(); i++) { - if (CurSeg[i].directionality == UNI_DIRECTIONAL - && CurSeg[i].longline == true) { + if (CurSeg[i].directionality == UNI_DIRECTIONAL && CurSeg[i].longline) { vpr_throw(VPR_ERROR_ARCH, get_arch_file_name(), 0, "Long lines not supported for unidirectional architectures.\n" "Refer to segmentlist of '%s'\n", diff --git a/vpr/src/base/CheckSetup.cpp b/vpr/src/base/CheckSetup.cpp index 13c98a0fe91..e4a5ab8c8e7 100644 --- a/vpr/src/base/CheckSetup.cpp +++ b/vpr/src/base/CheckSetup.cpp @@ -1,43 +1,44 @@ -#include "vtr_log.h" +#include "CheckSetup.h" + +#include "vtr_log.h" #include "vpr_types.h" #include "vpr_error.h" #include "globals.h" -#include "echo_files.h" #include "read_xml_arch_file.h" -#include "CheckSetup.h" -void CheckSetup(const t_packer_opts& PackerOpts, - const t_placer_opts& PlacerOpts, - const t_ap_opts& APOpts, - const t_router_opts& RouterOpts, - const t_server_opts& ServerOpts, - const t_det_routing_arch& RoutingArch, - const std::vector& Segments, - const t_timing_inf& Timing, - const t_chan_width_dist Chans) { - int i; - int Tmp; - - if (!Timing.timing_analysis_enabled && PackerOpts.timing_driven) { + +static constexpr int DYMANIC_PORT_RANGE_MIN = 49152; +static constexpr int DYNAMIC_PORT_RANGE_MAX = 65535; + +void CheckSetup(const t_packer_opts& packer_opts, + const t_placer_opts& placer_opts, + const t_ap_opts& ap_opts, + const t_router_opts& router_opts, + const t_server_opts& server_opts, + const t_det_routing_arch& routing_arch, + const std::vector& segments, + const t_timing_inf& timing, + const t_chan_width_dist& chans) { + if (!timing.timing_analysis_enabled && packer_opts.timing_driven) { VPR_FATAL_ERROR(VPR_ERROR_OTHER, "Packing cannot be timing driven without timing analysis enabled\n"); } - if (PackerOpts.load_flat_placement) { - if (PackerOpts.device_layout == "auto") { + if (packer_opts.load_flat_placement) { + if (packer_opts.device_layout == "auto") { VPR_FATAL_ERROR(VPR_ERROR_OTHER, "Legalization requires a fixed device layout.\n"); } - if (!PlacerOpts.constraints_file.empty()) { + if (!placer_opts.constraints_file.empty()) { VPR_FATAL_ERROR(VPR_ERROR_OTHER, "Cannot specify a fixed clusters file when running legalization.\n"); } } - if ((GLOBAL == RouterOpts.route_type) - && (PlacerOpts.place_algorithm.is_timing_driven())) { + if ((GLOBAL == router_opts.route_type) + && (placer_opts.place_algorithm.is_timing_driven())) { /* Works, but very weird. Can't optimize timing well, since you're * not doing proper architecture delay modelling. */ VTR_LOG_WARN( @@ -45,43 +46,43 @@ void CheckSetup(const t_packer_opts& PackerOpts, "This is allowed, but strange, and circuit speed will suffer.\n"); } - if (!Timing.timing_analysis_enabled - && (PlacerOpts.place_algorithm.is_timing_driven())) { + if (!timing.timing_analysis_enabled + && (placer_opts.place_algorithm.is_timing_driven())) { /* May work, not tested */ VPR_FATAL_ERROR(VPR_ERROR_OTHER, "Timing analysis must be enabled for timing-driven placement.\n"); } - if (!PlacerOpts.doPlacement && (!PlacerOpts.constraints_file.empty())) { + if (!placer_opts.doPlacement && (!placer_opts.constraints_file.empty())) { VPR_FATAL_ERROR(VPR_ERROR_OTHER, "A block location file requires that placement is enabled.\n"); } - if (PlacerOpts.place_algorithm.is_timing_driven() && - PlacerOpts.place_static_move_prob.size() > NUM_PL_MOVE_TYPES) { + if (placer_opts.place_algorithm.is_timing_driven() && + placer_opts.place_static_move_prob.size() > NUM_PL_MOVE_TYPES) { VPR_FATAL_ERROR(VPR_ERROR_OTHER, "The number of provided placer move probabilities (%d) should equal or less than the total number of supported moves (%d).\n", - PlacerOpts.place_static_move_prob.size(), + placer_opts.place_static_move_prob.size(), NUM_PL_MOVE_TYPES); } - if (!PlacerOpts.place_algorithm.is_timing_driven() && - PlacerOpts.place_static_move_prob.size() > NUM_PL_NONTIMING_MOVE_TYPES) { + if (!placer_opts.place_algorithm.is_timing_driven() && + placer_opts.place_static_move_prob.size() > NUM_PL_NONTIMING_MOVE_TYPES) { VPR_FATAL_ERROR(VPR_ERROR_OTHER, "The number of placer non timing move probabilities (%d) should equal to or less than the total number of supported moves (%d).\n", - PlacerOpts.place_static_move_prob.size(), + placer_opts.place_static_move_prob.size(), NUM_PL_MOVE_TYPES); } // Rules for doing Analytical Placement - if (APOpts.doAP) { + if (ap_opts.doAP) { // Make sure that the --place option was not set. - if (PlacerOpts.doPlacement) { + if (placer_opts.doPlacement) { VPR_FATAL_ERROR(VPR_ERROR_OTHER, "Cannot perform both analytical and non-analytical placement.\n"); } // Make sure that the --pack option was not set. - if (PackerOpts.doPacking) { + if (packer_opts.doPacking) { VPR_FATAL_ERROR(VPR_ERROR_OTHER, "Analytical placement should skip packing.\n"); } @@ -95,58 +96,58 @@ void CheckSetup(const t_packer_opts& PackerOpts, // goes with ensuring that some blocks are fixed. } - if (RouterOpts.doRouting) { - if (!Timing.timing_analysis_enabled - && (DEMAND_ONLY != RouterOpts.base_cost_type && DEMAND_ONLY_NORMALIZED_LENGTH != RouterOpts.base_cost_type)) { + if (router_opts.doRouting) { + if (!timing.timing_analysis_enabled + && (DEMAND_ONLY != router_opts.base_cost_type && DEMAND_ONLY_NORMALIZED_LENGTH != router_opts.base_cost_type)) { VPR_FATAL_ERROR(VPR_ERROR_OTHER, "base_cost_type must be demand_only or demand_only_normalized_length when timing analysis is disabled.\n"); } } - if (DETAILED == RouterOpts.route_type) { - if ((Chans.chan_x_dist.type != UNIFORM) - || (Chans.chan_y_dist.type != UNIFORM)) { + if (DETAILED == router_opts.route_type) { + if ((chans.chan_x_dist.type != UNIFORM) + || (chans.chan_y_dist.type != UNIFORM)) { VPR_FATAL_ERROR(VPR_ERROR_OTHER, "Detailed routing currently only supported on FPGAs with uniform channel distributions.\n"); } } - for (i = 0; i < (int)Segments.size(); ++i) { - Tmp = Segments[i].arch_opin_switch; + for (int i = 0; i < (int)segments.size(); ++i) { + int opin_switch_idx = segments[i].arch_opin_switch; auto& device_ctx = g_vpr_ctx.device(); - if (!device_ctx.arch_switch_inf[Tmp].buffered()) { + if (!device_ctx.arch_switch_inf[opin_switch_idx].buffered()) { VPR_FATAL_ERROR(VPR_ERROR_OTHER, - "arch_opin_switch (#%d) of segment type #%d is not buffered.\n", Tmp, i); + "arch_opin_switch (#%d) of segment type #%d is not buffered.\n", opin_switch_idx, i); } } - if ((PlacerOpts.place_chan_width != NO_FIXED_CHANNEL_WIDTH) && PlacerOpts.place_chan_width < 0) { + if ((placer_opts.place_chan_width != NO_FIXED_CHANNEL_WIDTH) && placer_opts.place_chan_width < 0) { VPR_FATAL_ERROR(VPR_ERROR_OTHER, "Place channel width must be positive.\n"); } - if ((RouterOpts.fixed_channel_width != NO_FIXED_CHANNEL_WIDTH) && RouterOpts.fixed_channel_width < 0) { + if ((router_opts.fixed_channel_width != NO_FIXED_CHANNEL_WIDTH) && router_opts.fixed_channel_width < 0) { VPR_FATAL_ERROR(VPR_ERROR_OTHER, "Routing channel width must be positive.\n"); } - if (UNI_DIRECTIONAL == RoutingArch.directionality) { - if ((RouterOpts.fixed_channel_width != NO_FIXED_CHANNEL_WIDTH) - && (RouterOpts.fixed_channel_width % 2 > 0)) { + if (UNI_DIRECTIONAL == routing_arch.directionality) { + if ((router_opts.fixed_channel_width != NO_FIXED_CHANNEL_WIDTH) + && (router_opts.fixed_channel_width % 2 > 0)) { VPR_FATAL_ERROR(VPR_ERROR_OTHER, "Routing channel width must be even for unidirectional.\n"); } - if ((PlacerOpts.place_chan_width != NO_FIXED_CHANNEL_WIDTH) - && (PlacerOpts.place_chan_width % 2 > 0)) { + if ((placer_opts.place_chan_width != NO_FIXED_CHANNEL_WIDTH) + && (placer_opts.place_chan_width % 2 > 0)) { VPR_FATAL_ERROR(VPR_ERROR_OTHER, "Place channel width must be even for unidirectional.\n"); } } - if (ServerOpts.is_server_mode_enabled) { - if (ServerOpts.port_num < DYMANIC_PORT_RANGE_MIN || ServerOpts.port_num > DYNAMIC_PORT_RANGE_MAX) { + if (server_opts.is_server_mode_enabled) { + if (server_opts.port_num < DYMANIC_PORT_RANGE_MIN || server_opts.port_num > DYNAMIC_PORT_RANGE_MAX) { VPR_FATAL_ERROR(VPR_ERROR_OTHER, "Specified server port number `--port %d` is out of range [%d-%d]. Please specify a port number within that range.\n", - ServerOpts.port_num, DYMANIC_PORT_RANGE_MIN, DYNAMIC_PORT_RANGE_MAX); + server_opts.port_num, DYMANIC_PORT_RANGE_MIN, DYNAMIC_PORT_RANGE_MAX); } } } diff --git a/vpr/src/base/CheckSetup.h b/vpr/src/base/CheckSetup.h index 6e643bfb972..69ed92cacf1 100644 --- a/vpr/src/base/CheckSetup.h +++ b/vpr/src/base/CheckSetup.h @@ -1,18 +1,16 @@ #ifndef CHECKSETUP_H #define CHECKSETUP_H -#include "vpr_types.h" -const int DYMANIC_PORT_RANGE_MIN = 49152; -const int DYNAMIC_PORT_RANGE_MAX = 65535; +#include "vpr_types.h" -void CheckSetup(const t_packer_opts& PackerOpts, - const t_placer_opts& PlacerOpts, - const t_ap_opts& APOpts, - const t_router_opts& RouterOpts, - const t_server_opts& ServerOpts, - const t_det_routing_arch& RoutingArch, - const std::vector& Segments, - const t_timing_inf& Timing, - const t_chan_width_dist Chans); +void CheckSetup(const t_packer_opts& packer_opts, + const t_placer_opts& placer_opts, + const t_ap_opts& ap_opts, + const t_router_opts& router_opts, + const t_server_opts& server_opts, + const t_det_routing_arch& routing_arch, + const std::vector& segments, + const t_timing_inf& timing, + const t_chan_width_dist& chans); #endif diff --git a/vpr/src/base/SetupVPR.cpp b/vpr/src/base/SetupVPR.cpp index 77fb495014b..583b5d805aa 100644 --- a/vpr/src/base/SetupVPR.cpp +++ b/vpr/src/base/SetupVPR.cpp @@ -1,13 +1,9 @@ -#include #include -#include #include #include "vtr_assert.h" #include "vtr_util.h" -#include "vtr_random.h" #include "vtr_log.h" -#include "vtr_memory.h" #include "vtr_time.h" #include "vpr_types.h" @@ -21,7 +17,6 @@ #include "pb_type_graph.h" #include "pack_types.h" #include "lb_type_rr_graph.h" -#include "rr_graph_area.h" #include "echo_arch.h" #include "read_options.h" #include "echo_files.h" @@ -117,7 +112,7 @@ void SetupVPR(const t_options* options, auto& device_ctx = g_vpr_ctx.mutable_device(); - if (options->CircuitName.value() == "") { + if (options->CircuitName.value().empty()) { VPR_FATAL_ERROR(VPR_ERROR_BLIF_F, "No blif file found in arguments (did you specify an architecture file?)\n"); } @@ -156,7 +151,7 @@ void SetupVPR(const t_options* options, //save the device layout, which is required to parse the architecture file arch->device_layout = options->device_layout; - if (readArchFile == true) { + if (readArchFile) { vtr::ScopedStartFinishTimer t("Loading Architecture Description"); switch (options->arch_format) { case e_arch_format::VTR: @@ -305,9 +300,6 @@ void SetupVPR(const t_options* options, /* init global variables */ vtr::out_file_prefix = options->out_file_prefix; - /* Set seed for pseudo-random placement, default seed to 1 */ - vtr::srandom(placerOpts->seed); - { vtr::ScopedStartFinishTimer t("Building complex block graph"); alloc_and_load_all_pb_graphs(powerOpts->do_power, routerOpts->flat_routing); @@ -348,7 +340,7 @@ void SetupVPR(const t_options* options, static void SetupTiming(const t_options& Options, const bool TimingEnabled, t_timing_inf* Timing) { /* Don't do anything if they don't want timing */ - if (false == TimingEnabled) { + if (!TimingEnabled) { Timing->timing_analysis_enabled = false; return; } @@ -570,7 +562,7 @@ static void SetupAnnealSched(const t_options& Options, } /** - * @brief Sets up the s_packer_opts structure baesd on users inputs and + * @brief Sets up the s_packer_opts structure based on users inputs and * on the architecture specified. * * Error checking, such as checking for conflicting params is assumed diff --git a/vpr/src/place/RL_agent_util.cpp b/vpr/src/place/RL_agent_util.cpp index 19ed06edd9c..e861c7b9407 100644 --- a/vpr/src/place/RL_agent_util.cpp +++ b/vpr/src/place/RL_agent_util.cpp @@ -5,7 +5,8 @@ std::pair, std::unique_ptr> create_move_generators(PlacerState& placer_state, const t_placer_opts& placer_opts, int move_lim, - double noc_attraction_weight) { + double noc_attraction_weight, + vtr::RngContainer& rng) { e_reward_function reward_fun = string_to_reward(placer_opts.place_reward_fun); std::pair, std::unique_ptr> move_generators; @@ -21,8 +22,8 @@ std::pair, std::unique_ptr> create move_name.c_str(), placer_opts.place_static_move_prob[move_type]); } - move_generators.first = std::make_unique(placer_state, reward_fun, placer_opts.place_static_move_prob); - move_generators.second = std::make_unique(placer_state, reward_fun, placer_opts.place_static_move_prob); + move_generators.first = std::make_unique(placer_state, reward_fun, rng, placer_opts.place_static_move_prob); + move_generators.second = std::make_unique(placer_state, reward_fun, rng, placer_opts.place_static_move_prob); } else { //RL based placement /* For the non timing driven placement: the agent has a single state * * - Available moves are (Uniform / Median / Centroid) * @@ -66,26 +67,31 @@ std::pair, std::unique_ptr> create VTR_LOG("Using simple RL 'Epsilon Greedy agent' for choosing move and block types\n"); karmed_bandit_agent1 = std::make_unique(first_state_avail_moves, e_agent_space::MOVE_BLOCK_TYPE, - placer_opts.place_agent_epsilon); + placer_opts.place_agent_epsilon, + rng); } else { VTR_LOG("Using simple RL 'Epsilon Greedy agent' for choosing move types\n"); karmed_bandit_agent1 = std::make_unique(first_state_avail_moves, e_agent_space::MOVE_TYPE, - placer_opts.place_agent_epsilon); + placer_opts.place_agent_epsilon, + rng); } karmed_bandit_agent1->set_step(placer_opts.place_agent_gamma, move_lim); move_generators.first = std::make_unique(placer_state, reward_fun, + rng, karmed_bandit_agent1, noc_attraction_weight, placer_opts.place_high_fanout_net); //agent's 2nd state karmed_bandit_agent2 = std::make_unique(second_state_avail_moves, e_agent_space::MOVE_TYPE, - placer_opts.place_agent_epsilon); + placer_opts.place_agent_epsilon, + rng); karmed_bandit_agent2->set_step(placer_opts.place_agent_gamma, move_lim); move_generators.second = std::make_unique(placer_state, reward_fun, + rng, karmed_bandit_agent2, noc_attraction_weight, placer_opts.place_high_fanout_net); @@ -95,24 +101,29 @@ std::pair, std::unique_ptr> create if (placer_opts.place_agent_space == e_agent_space::MOVE_BLOCK_TYPE) { VTR_LOG("Using simple RL 'Softmax agent' for choosing move and block types\n"); karmed_bandit_agent1 = std::make_unique(first_state_avail_moves, - e_agent_space::MOVE_BLOCK_TYPE); + e_agent_space::MOVE_BLOCK_TYPE, + rng); } else { VTR_LOG("Using simple RL 'Softmax agent' for choosing move types\n"); karmed_bandit_agent1 = std::make_unique(first_state_avail_moves, - e_agent_space::MOVE_TYPE); + e_agent_space::MOVE_TYPE, + rng); } karmed_bandit_agent1->set_step(placer_opts.place_agent_gamma, move_lim); move_generators.first = std::make_unique(placer_state, reward_fun, + rng, karmed_bandit_agent1, noc_attraction_weight, placer_opts.place_high_fanout_net); //agent's 2nd state karmed_bandit_agent2 = std::make_unique(second_state_avail_moves, - e_agent_space::MOVE_TYPE); + e_agent_space::MOVE_TYPE, + rng); karmed_bandit_agent2->set_step(placer_opts.place_agent_gamma, move_lim); move_generators.second = std::make_unique(placer_state, reward_fun, + rng, karmed_bandit_agent2, noc_attraction_weight, placer_opts.place_high_fanout_net); diff --git a/vpr/src/place/RL_agent_util.h b/vpr/src/place/RL_agent_util.h index afe8bf3b6cb..81d09eaa755 100644 --- a/vpr/src/place/RL_agent_util.h +++ b/vpr/src/place/RL_agent_util.h @@ -20,6 +20,7 @@ enum class e_agent_state { * @param move_lim represents the num of moves per temp. * @param noc_attraction_weight The attraction weight by which the NoC-biased centroid move adjust the computed location * towards reachable NoC routers from the moving block. + * @param rng A reference to a random number generator to be used by move generators. * * @return Two unique pointers referring to move generators. These move generators are supposed to be used * in the first and second states of the agent. @@ -28,7 +29,8 @@ enum class e_agent_state { std::pair, std::unique_ptr> create_move_generators(PlacerState& placer_state, const t_placer_opts& placer_opts, int move_lim, - double noc_attraction_weight); + double noc_attraction_weight, + vtr::RngContainer& rng); /** * @brief copy one of the available move_generators to be the current move_generator that would be used in the placement based on the placer_options and the agent state diff --git a/vpr/src/place/centroid_move_generator.cpp b/vpr/src/place/centroid_move_generator.cpp index 7fafa7743f8..9f00a5b89a4 100644 --- a/vpr/src/place/centroid_move_generator.cpp +++ b/vpr/src/place/centroid_move_generator.cpp @@ -17,16 +17,18 @@ std::map CentroidMoveGenerator::noc_router_to_noc_gr CentroidMoveGenerator::CentroidMoveGenerator(PlacerState& placer_state, - e_reward_function reward_function) - : MoveGenerator(placer_state, reward_function) + e_reward_function reward_function, + vtr::RngContainer& rng) + : MoveGenerator(placer_state, reward_function, rng) , noc_attraction_w_(0.0f) , noc_attraction_enabled_(false) {} CentroidMoveGenerator::CentroidMoveGenerator(PlacerState& placer_state, e_reward_function reward_function, + vtr::RngContainer& rng, float noc_attraction_weight, size_t high_fanout_net) - : MoveGenerator(placer_state, reward_function) + : MoveGenerator(placer_state, reward_function, rng) , noc_attraction_w_(noc_attraction_weight) , noc_attraction_enabled_(true) { VTR_ASSERT(noc_attraction_weight > 0.0 && noc_attraction_weight <= 1.0); @@ -59,7 +61,8 @@ e_create_move CentroidMoveGenerator::propose_move(t_pl_blocks_to_be_moved& block /*highly_crit_block=*/false, /*net_from=*/nullptr, /*pin_from=*/nullptr, - placer_state); + placer_state, + rng_); VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, "Centroid Move Choose Block %d - rlim %f\n", @@ -92,7 +95,7 @@ e_create_move CentroidMoveGenerator::propose_move(t_pl_blocks_to_be_moved& block // layer for the centroid location. So if the layer is not valid, we set it to the same layer as from loc. centroid.layer = (centroid.layer < 0) ? from.layer : centroid.layer; /* Find a location near the weighted centroid_loc */ - if (!find_to_loc_centroid(cluster_from_type, from, centroid, range_limiters, to, b_from, blk_loc_registry)) { + if (!find_to_loc_centroid(cluster_from_type, from, centroid, range_limiters, to, b_from, blk_loc_registry, rng_)) { return e_create_move::ABORT; } diff --git a/vpr/src/place/centroid_move_generator.h b/vpr/src/place/centroid_move_generator.h index 01ee259cbc8..86b69ef2f00 100644 --- a/vpr/src/place/centroid_move_generator.h +++ b/vpr/src/place/centroid_move_generator.h @@ -30,7 +30,8 @@ class CentroidMoveGenerator : public MoveGenerator { * of the RL agent. */ CentroidMoveGenerator(PlacerState& placer_state, - e_reward_function reward_function); + e_reward_function reward_function, + vtr::RngContainer& rng); /** * The move generator created by calling this constructor considers both @@ -49,6 +50,7 @@ class CentroidMoveGenerator : public MoveGenerator { */ CentroidMoveGenerator(PlacerState& placer_state, e_reward_function reward_function, + vtr::RngContainer& rng, float noc_attraction_weight, size_t high_fanout_net); diff --git a/vpr/src/place/critical_uniform_move_generator.cpp b/vpr/src/place/critical_uniform_move_generator.cpp index 712e309ca7c..7a1d39ed308 100644 --- a/vpr/src/place/critical_uniform_move_generator.cpp +++ b/vpr/src/place/critical_uniform_move_generator.cpp @@ -5,8 +5,9 @@ #include "move_utils.h" CriticalUniformMoveGenerator::CriticalUniformMoveGenerator(PlacerState& placer_state, - e_reward_function reward_function) - : MoveGenerator(placer_state, reward_function) {} + e_reward_function reward_function, + vtr::RngContainer& rng) + : MoveGenerator(placer_state, reward_function, rng) {} e_create_move CriticalUniformMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_affected, t_propose_action& proposed_action, @@ -26,7 +27,8 @@ e_create_move CriticalUniformMoveGenerator::propose_move(t_pl_blocks_to_be_moved /*highly_crit_block=*/true, &net_from, &pin_from, - placer_state); + placer_state, + rng_); VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, "Critical Uniform Move Choose Block %d - rlim %f\n", size_t(b_from), rlim); @@ -42,7 +44,7 @@ e_create_move CriticalUniformMoveGenerator::propose_move(t_pl_blocks_to_be_moved t_pl_loc to; to.layer = from.layer; - if (!find_to_loc_uniform(cluster_from_type, rlim, from, to, b_from, blk_loc_registry)) { + if (!find_to_loc_uniform(cluster_from_type, rlim, from, to, b_from, blk_loc_registry, rng_)) { return e_create_move::ABORT; } diff --git a/vpr/src/place/critical_uniform_move_generator.h b/vpr/src/place/critical_uniform_move_generator.h index 73fb9717218..dd4e5391474 100644 --- a/vpr/src/place/critical_uniform_move_generator.h +++ b/vpr/src/place/critical_uniform_move_generator.h @@ -18,7 +18,8 @@ class CriticalUniformMoveGenerator : public MoveGenerator { public: CriticalUniformMoveGenerator() = delete; CriticalUniformMoveGenerator(PlacerState& placer_state, - e_reward_function reward_function); + e_reward_function reward_function, + vtr::RngContainer& rng); private: e_create_move propose_move(t_pl_blocks_to_be_moved& blocks_affected, diff --git a/vpr/src/place/feasible_region_move_generator.cpp b/vpr/src/place/feasible_region_move_generator.cpp index 5d4e55f7656..75210dafd43 100644 --- a/vpr/src/place/feasible_region_move_generator.cpp +++ b/vpr/src/place/feasible_region_move_generator.cpp @@ -9,8 +9,9 @@ #include FeasibleRegionMoveGenerator::FeasibleRegionMoveGenerator(PlacerState& placer_state, - e_reward_function reward_function) - : MoveGenerator(placer_state, reward_function) {} + e_reward_function reward_function, + vtr::RngContainer& rng) + : MoveGenerator(placer_state, reward_function, rng) {} e_create_move FeasibleRegionMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_affected, t_propose_action& proposed_action, @@ -31,7 +32,8 @@ e_create_move FeasibleRegionMoveGenerator::propose_move(t_pl_blocks_to_be_moved& /*highly_crit_block=*/true, &net_from, &pin_from, - placer_state); + placer_state, + rng_); VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, "Feasible Region Move Choose Block %di - rlim %f\n", size_t(b_from), rlim); @@ -126,7 +128,7 @@ e_create_move FeasibleRegionMoveGenerator::propose_move(t_pl_blocks_to_be_moved& placer_opts.place_dm_rlim}; // Try to find a legal location inside the feasible region - if (!find_to_loc_median(cluster_from_type, from, &FR_coords, to, b_from, blk_loc_registry)) { + if (!find_to_loc_median(cluster_from_type, from, &FR_coords, to, b_from, blk_loc_registry, rng_)) { /** If there is no legal location in the feasible region, calculate the center of the FR and try to find a legal location * in a range around this center. */ @@ -135,7 +137,7 @@ e_create_move FeasibleRegionMoveGenerator::propose_move(t_pl_blocks_to_be_moved& center.y = (FR_coords.ymin + FR_coords.ymax) / 2; // TODO: Currently, we don't move blocks between different types of layers center.layer = from.layer; - if (!find_to_loc_centroid(cluster_from_type, from, center, range_limiters, to, b_from, blk_loc_registry)) + if (!find_to_loc_centroid(cluster_from_type, from, center, range_limiters, to, b_from, blk_loc_registry, rng_)) return e_create_move::ABORT; } diff --git a/vpr/src/place/feasible_region_move_generator.h b/vpr/src/place/feasible_region_move_generator.h index 29405104aeb..702f8bdd26c 100644 --- a/vpr/src/place/feasible_region_move_generator.h +++ b/vpr/src/place/feasible_region_move_generator.h @@ -22,7 +22,8 @@ class FeasibleRegionMoveGenerator : public MoveGenerator { public: FeasibleRegionMoveGenerator() = delete; FeasibleRegionMoveGenerator(PlacerState& placer_state, - e_reward_function reward_function); + e_reward_function reward_function, + vtr::RngContainer& rng); private: e_create_move propose_move(t_pl_blocks_to_be_moved& blocks_affected, diff --git a/vpr/src/place/initial_noc_placement.cpp b/vpr/src/place/initial_noc_placement.cpp index 9b4a3adeeed..df1352c98ec 100644 --- a/vpr/src/place/initial_noc_placement.cpp +++ b/vpr/src/place/initial_noc_placement.cpp @@ -23,10 +23,12 @@ * the proposed swap is accepted. * @param prob The probability by which a router swap that increases * the cost is accepted. The passed value should be in range [0, 1]. + * @param rng A random number generator used to generate random numbers + * in range [0, 1]. * * @return true if the proposed swap is accepted, false if not. */ -static bool accept_noc_swap(double delta_cost, double prob); +static bool accept_noc_swap(double delta_cost, double prob, vtr::RngContainer& rng); /** * @brief Places a constrained NoC router within its partition region. @@ -34,22 +36,24 @@ static bool accept_noc_swap(double delta_cost, double prob); * @param router_blk_id NoC router cluster block ID * @param blk_loc_registry Placement block location information. To be * filled with the location where pl_macro is placed. + * @param rng A random number generator. */ static void place_constrained_noc_router(ClusterBlockId router_blk_id, - BlkLocRegistry& blk_loc_registry); + BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng); /** * @brief Randomly places unconstrained NoC routers. * * @param unfixed_routers Contains the cluster block ID for all unconstrained * NoC routers. - * @param seed Used for shuffling NoC routers. * @param blk_loc_registry Placement block location information. To be filled * with the location where pl_macro is placed. + * @param rng A random number generator used for shuffling NoC routers. */ static void place_noc_routers_randomly(std::vector& unfixed_routers, - int seed, - BlkLocRegistry& blk_loc_registry); + BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng); /** * @brief Runs a simulated annealing optimizer for NoC routers. @@ -57,10 +61,13 @@ static void place_noc_routers_randomly(std::vector& unfixed_rout * @param noc_opts Contains weighting factors for NoC cost terms. * @param blk_loc_registry Placement block location information. * To be filled with the location where pl_macro is placed. + * @param rng A random number generator used to generate random + * numbers in range [0, 1]. */ static void noc_routers_anneal(const t_noc_opts& noc_opts, BlkLocRegistry& blk_loc_registry, - NocCostHandler& noc_cost_handler); + NocCostHandler& noc_cost_handler, + vtr::RngContainer& rng); /** * @brief Returns the compressed grid of NoC. @@ -82,7 +89,7 @@ static const t_compressed_block_grid& get_compressed_noc_grid() { return compressed_noc_grid; } -static bool accept_noc_swap(double delta_cost, double prob) { +static bool accept_noc_swap(double delta_cost, double prob, vtr::RngContainer& rng) { if (delta_cost <= 0.0) { return true; } @@ -91,7 +98,7 @@ static bool accept_noc_swap(double delta_cost, double prob) { return false; } - float random_num = vtr::frand(); + float random_num = rng.frand(); if (random_num < prob) { return true; } else { @@ -100,7 +107,8 @@ static bool accept_noc_swap(double delta_cost, double prob) { } static void place_constrained_noc_router(ClusterBlockId router_blk_id, - BlkLocRegistry& blk_loc_registry) { + BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng) { auto& cluster_ctx = g_vpr_ctx.clustering(); const auto& floorplanning_ctx = g_vpr_ctx.floorplanning(); @@ -116,7 +124,7 @@ static void place_constrained_noc_router(ClusterBlockId router_blk_id, bool macro_placed = false; for (int i_try = 0; i_try < MAX_NUM_TRIES_TO_PLACE_MACROS_RANDOMLY && !macro_placed; i_try++) { - macro_placed = try_place_macro_randomly(pl_macro, pr, block_type, e_pad_loc_type::FREE, blk_loc_registry); + macro_placed = try_place_macro_randomly(pl_macro, pr, block_type, e_pad_loc_type::FREE, blk_loc_registry, rng); } if (!macro_placed) { @@ -129,8 +137,8 @@ static void place_constrained_noc_router(ClusterBlockId router_blk_id, } static void place_noc_routers_randomly(std::vector& unfixed_routers, - int seed, - BlkLocRegistry& blk_loc_registry) { + BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng) { const auto& compressed_grids = g_vpr_ctx.placement().compressed_block_grids; const auto& noc_ctx = g_vpr_ctx.noc(); const auto& cluster_ctx = g_vpr_ctx.clustering(); @@ -155,8 +163,7 @@ static void place_noc_routers_randomly(std::vector& unfixed_rout vtr::vector noc_phy_routers = noc_ctx.noc_model.get_noc_routers(); // Shuffle physical NoC routers - vtr::RandState rand_state = seed; - vtr::shuffle(noc_phy_routers.begin(), noc_phy_routers.end(), rand_state); + vtr::shuffle(noc_phy_routers.begin(), noc_phy_routers.end(), rng); // Get the logical block type for router const auto router_block_type = cluster_ctx.clb_nlist.block_type(noc_ctx.noc_traffic_flows_storage.get_router_clusters_in_netlist()[0]); @@ -172,7 +179,7 @@ static void place_noc_routers_randomly(std::vector& unfixed_rout // Find a compatible sub-tile const auto& phy_type = device_ctx.grid.get_physical_type(router_phy_loc); const auto& compatible_sub_tiles = compressed_noc_grid.compatible_sub_tiles_for_tile.at(phy_type->index); - int sub_tile = compatible_sub_tiles[vtr::irand((int)compatible_sub_tiles.size() - 1)]; + int sub_tile = compatible_sub_tiles[rng.irand((int)compatible_sub_tiles.size() - 1)]; t_pl_loc loc(router_phy_loc, sub_tile); @@ -203,7 +210,8 @@ static void place_noc_routers_randomly(std::vector& unfixed_rout static void noc_routers_anneal(const t_noc_opts& noc_opts, BlkLocRegistry& blk_loc_registry, - NocCostHandler& noc_cost_handler) { + NocCostHandler& noc_cost_handler, + vtr::RngContainer& rng) { auto& noc_ctx = g_vpr_ctx.noc(); const auto& block_locs = blk_loc_registry.block_locs(); @@ -265,7 +273,10 @@ static void noc_routers_anneal(const t_noc_opts& noc_opts, blocks_affected.clear_move_blocks(); // Shrink the range limit over time float r_lim_decayed = 1.0f + (N_MOVES - i_move) * (max_r_lim / N_MOVES); - e_create_move create_move_outcome = propose_router_swap(blocks_affected, r_lim_decayed, blk_loc_registry); + e_create_move create_move_outcome = propose_router_swap(blocks_affected, + r_lim_decayed, + blk_loc_registry, + rng); if (create_move_outcome != e_create_move::ABORT) { blk_loc_registry.apply_move_blocks(blocks_affected); @@ -275,7 +286,7 @@ static void noc_routers_anneal(const t_noc_opts& noc_opts, double delta_cost = calculate_noc_cost(noc_delta_c, costs.noc_cost_norm_factors, noc_opts); double prob = starting_prob - i_move * prob_step; - bool move_accepted = accept_noc_swap(delta_cost, prob); + bool move_accepted = accept_noc_swap(delta_cost, prob, rng); if (move_accepted) { costs.cost += delta_cost; @@ -299,9 +310,9 @@ static void noc_routers_anneal(const t_noc_opts& noc_opts, } void initial_noc_placement(const t_noc_opts& noc_opts, - const t_placer_opts& placer_opts, BlkLocRegistry& blk_loc_registry, - NocCostHandler& noc_cost_handler) { + NocCostHandler& noc_cost_handler, + vtr::RngContainer& rng) { vtr::ScopedStartFinishTimer timer("Initial NoC Placement"); auto& noc_ctx = g_vpr_ctx.noc(); const auto& block_locs = blk_loc_registry.block_locs(); @@ -319,20 +330,20 @@ void initial_noc_placement(const t_noc_opts& noc_opts, } if (is_cluster_constrained(router_blk_id)) { - place_constrained_noc_router(router_blk_id, blk_loc_registry); + place_constrained_noc_router(router_blk_id, blk_loc_registry, rng); } else { unfixed_routers.push_back(router_blk_id); } } // Place unconstrained NoC routers randomly - place_noc_routers_randomly(unfixed_routers, placer_opts.seed, blk_loc_registry); + place_noc_routers_randomly(unfixed_routers, blk_loc_registry, rng); // populate internal data structures to maintain route, bandwidth usage, and latencies noc_cost_handler.initial_noc_routing({}); // Run the simulated annealing optimizer for NoC routers - noc_routers_anneal(noc_opts, blk_loc_registry, noc_cost_handler); + noc_routers_anneal(noc_opts, blk_loc_registry, noc_cost_handler, rng); // check if there is any cycles bool has_cycle = noc_cost_handler.noc_routing_has_cycle(); diff --git a/vpr/src/place/initial_noc_placment.h b/vpr/src/place/initial_noc_placment.h index bcac134618c..79b062909dd 100644 --- a/vpr/src/place/initial_noc_placment.h +++ b/vpr/src/place/initial_noc_placment.h @@ -7,18 +7,22 @@ struct t_placer_opts; class BlkLocRegistry; class NocCostHandler; +namespace vtr { +class RngContainer; +} + /** * @brief Randomly places NoC routers, then runs a quick simulated annealing * to minimize NoC costs. * * @param noc_opts NoC-related options. Used to calculate NoC-related costs. - * @param placer_opts Contain the placement algorithm options including the seed. * @param blk_loc_registry Placement block location information. To be filled * with the location where pl_macro is placed. + * @param rng A random number generator used during simulated annealing. */ void initial_noc_placement(const t_noc_opts& noc_opts, - const t_placer_opts& placer_opts, BlkLocRegistry& blk_loc_registry, - NocCostHandler& noc_cost_handler); + NocCostHandler& noc_cost_handler, + vtr::RngContainer& rng); #endif //VTR_INITIAL_NOC_PLACEMENT_H diff --git a/vpr/src/place/initial_placement.cpp b/vpr/src/place/initial_placement.cpp index 4cf4f6cc89f..592c8ed0e20 100644 --- a/vpr/src/place/initial_placement.cpp +++ b/vpr/src/place/initial_placement.cpp @@ -49,6 +49,7 @@ static constexpr int SORT_WEIGHT_PER_TILES_OUTSIDE_OF_PR = 100; * @param block_scores The block_scores (ranking of what to place next) for unplaced blocks connected to this macro should be updated. * @param blk_loc_registry Placement block location information. To be filled with the location * where pl_macro is placed. + * @param rng A random number generator. * * @return true if macro was placed, false if not. */ @@ -57,7 +58,8 @@ static bool place_macro(int macros_max_num_tries, e_pad_loc_type pad_loc_type, std::vector* blk_types_empty_locs_in_grid, vtr::vector& block_scores, - BlkLocRegistry& blk_loc_registry); + BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng); /* * Assign scores to each block based on macro size and floorplanning constraints. @@ -169,7 +171,8 @@ static std::vector find_centroid_loc(const t_pl_macro& pl_macro, static bool find_centroid_neighbor(t_pl_loc& centroid_loc, t_logical_block_type_ptr block_type, bool search_for_empty, - const BlkLocRegistry& blk_loc_registry); + const BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng); /** * @brief tries to place a macro at a centroid location of its placed connections. @@ -182,6 +185,7 @@ static bool find_centroid_neighbor(t_pl_loc& centroid_loc, * @param block_scores The block_scores (ranking of what to place next) for unplaced blocks connected to this macro are updated in this routine. * @param blk_loc_registry Placement block location information. To be filled with the location * where pl_macro is placed. + * @param rng A random number generator for choosing a compatible subtile randomly. * * @return true if the macro gets placed, false if not. */ @@ -190,7 +194,8 @@ static bool try_centroid_placement(const t_pl_macro& pl_macro, t_logical_block_type_ptr block_type, e_pad_loc_type pad_loc_type, vtr::vector& block_scores, - BlkLocRegistry& blk_loc_registry); + BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng); /** * @brief Looks for a valid placement location for macro in second iteration, tries to place as many macros as possible in one column @@ -221,12 +226,14 @@ static bool try_dense_placement(const t_pl_macro& pl_macro, * @param constraints_file Used to read block locations if any constraints is available. * @param blk_loc_registry Placement block location information. To be filled with the location * where pl_macro is placed. + * @param rng A random number generator. */ static void place_all_blocks(const t_placer_opts& placer_opts, vtr::vector& block_scores, e_pad_loc_type pad_loc_type, const char* constraints_file, - BlkLocRegistry& blk_loc_registry); + BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng); /** * @brief If any blocks remain unplaced after all initial placement iterations, this routine @@ -329,7 +336,8 @@ static bool is_loc_legal(const t_pl_loc& loc, static bool find_centroid_neighbor(t_pl_loc& centroid_loc, t_logical_block_type_ptr block_type, bool search_for_empty, - const BlkLocRegistry& blk_loc_registry) { + const BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng) { const auto& compressed_block_grid = g_vpr_ctx.placement().compressed_block_grids[block_type->index]; const int num_layers = g_vpr_ctx.device().grid.get_num_layers(); const int centroid_loc_layer_num = centroid_loc.layer; @@ -364,13 +372,14 @@ static bool find_centroid_neighbor(t_pl_loc& centroid_loc, /*is_median=*/false, centroid_loc_layer_num, search_for_empty, - blk_loc_registry); + blk_loc_registry, + rng); if (!legal) { return false; } - compressed_grid_to_loc(block_type, to_compressed_loc, centroid_loc); + compressed_grid_to_loc(block_type, to_compressed_loc, centroid_loc, rng); return legal; } @@ -480,7 +489,8 @@ static bool try_centroid_placement(const t_pl_macro& pl_macro, t_logical_block_type_ptr block_type, e_pad_loc_type pad_loc_type, vtr::vector& block_scores, - BlkLocRegistry& blk_loc_registry) { + BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng) { auto& block_locs = blk_loc_registry.mutable_block_locs(); t_pl_loc centroid_loc(OPEN, OPEN, OPEN, OPEN); @@ -497,7 +507,7 @@ static bool try_centroid_placement(const t_pl_macro& pl_macro, //try to find a near location that meet these requirements bool neighbor_legal_loc = false; if (!is_loc_legal(centroid_loc, pr, block_type)) { - neighbor_legal_loc = find_centroid_neighbor(centroid_loc, block_type, false, blk_loc_registry); + neighbor_legal_loc = find_centroid_neighbor(centroid_loc, block_type, false, blk_loc_registry, rng); if (!neighbor_legal_loc) { //no neighbor candidate found return false; } @@ -516,7 +526,7 @@ static bool try_centroid_placement(const t_pl_macro& pl_macro, const auto& compressed_block_grid = g_vpr_ctx.placement().compressed_block_grids[block_type->index]; const auto& type = device_ctx.grid.get_physical_type({centroid_loc.x, centroid_loc.y, centroid_loc.layer}); const auto& compatible_sub_tiles = compressed_block_grid.compatible_sub_tile_num(type->index); - centroid_loc.sub_tile = compatible_sub_tiles[vtr::irand((int)compatible_sub_tiles.size() - 1)]; + centroid_loc.sub_tile = compatible_sub_tiles[rng.irand((int)compatible_sub_tiles.size() - 1)]; } int width_offset = device_ctx.grid.get_width_offset({centroid_loc.x, centroid_loc.y, centroid_loc.layer}); int height_offset = device_ctx.grid.get_height_offset({centroid_loc.x, centroid_loc.y, centroid_loc.layer}); @@ -642,7 +652,8 @@ bool try_place_macro_randomly(const t_pl_macro& pl_macro, const PartitionRegion& pr, t_logical_block_type_ptr block_type, e_pad_loc_type pad_loc_type, - BlkLocRegistry& blk_loc_registry) { + BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng) { const auto& compressed_block_grid = g_vpr_ctx.placement().compressed_block_grids[block_type->index]; /* @@ -659,7 +670,7 @@ bool try_place_macro_randomly(const t_pl_macro& pl_macro, int region_index; const std::vector& regions = pr.get_regions(); if (regions.size() > 1) { - region_index = vtr::irand(regions.size() - 1); + region_index = rng.irand(regions.size() - 1); } else { region_index = 0; } @@ -668,7 +679,7 @@ bool try_place_macro_randomly(const t_pl_macro& pl_macro, const vtr::Rect& reg_rect = reg.get_rect(); const auto [layer_low, layer_high] = reg.get_layer_range(); - int selected_layer = (layer_low == layer_high) ? layer_low : layer_low + vtr::irand(layer_high - layer_low); + int selected_layer = (layer_low == layer_high) ? layer_low : layer_low + rng.irand(layer_high - layer_low); auto min_compressed_loc = compressed_block_grid.grid_loc_to_compressed_loc_approx({reg_rect.xmin(), reg_rect.ymin(), selected_layer}); @@ -690,7 +701,8 @@ bool try_place_macro_randomly(const t_pl_macro& pl_macro, /*is_median=*/false, selected_layer, /*search_for_empty=*/false, - blk_loc_registry); + blk_loc_registry, + rng); if (!legal) { @@ -699,7 +711,7 @@ bool try_place_macro_randomly(const t_pl_macro& pl_macro, } t_pl_loc loc; - compressed_grid_to_loc(block_type, to_compressed_loc, loc); + compressed_grid_to_loc(block_type, to_compressed_loc, loc, rng); auto& device_ctx = g_vpr_ctx.device(); @@ -882,7 +894,8 @@ static bool place_macro(int macros_max_num_tries, enum e_pad_loc_type pad_loc_type, std::vector* blk_types_empty_locs_in_grid, vtr::vector& block_scores, - BlkLocRegistry& blk_loc_registry) { + BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng) { const auto& block_locs = blk_loc_registry.block_locs(); ClusterBlockId blk_id = pl_macro.members[0].blk_index; VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, "\t\tHead of the macro is Block %d\n", size_t(blk_id)); @@ -916,13 +929,13 @@ static bool place_macro(int macros_max_num_tries, if (!macro_placed) { VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, "\t\t\tTry centroid placement\n"); - macro_placed = try_centroid_placement(pl_macro, pr, block_type, pad_loc_type, block_scores, blk_loc_registry); + macro_placed = try_centroid_placement(pl_macro, pr, block_type, pad_loc_type, block_scores, blk_loc_registry, rng); } VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, "\t\t\tMacro is placed: %d\n", macro_placed); // If macro is not placed yet, try to place the macro randomly for the max number of random tries for (int itry = 0; itry < macros_max_num_tries && !macro_placed; itry++) { VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, "\t\t\tTry random place iter: %d\n", itry); - macro_placed = try_place_macro_randomly(pl_macro, pr, block_type, pad_loc_type, blk_loc_registry); + macro_placed = try_place_macro_randomly(pl_macro, pr, block_type, pad_loc_type, blk_loc_registry, rng); } // Finished all tries if (!macro_placed) { @@ -989,7 +1002,8 @@ static void place_all_blocks(const t_placer_opts& placer_opts, vtr::vector& block_scores, enum e_pad_loc_type pad_loc_type, const char* constraints_file, - BlkLocRegistry& blk_loc_registry) { + BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng) { auto& cluster_ctx = g_vpr_ctx.clustering(); auto& place_ctx = g_vpr_ctx.placement(); auto& device_ctx = g_vpr_ctx.device(); @@ -1049,7 +1063,7 @@ static void place_all_blocks(const t_placer_opts& placer_opts, blocks_placed_since_heap_update++; - bool block_placed = place_one_block(blk_id, pad_loc_type, &blk_types_empty_locs_in_grid[blk_id_type->index], &block_scores, blk_loc_registry); + bool block_placed = place_one_block(blk_id, pad_loc_type, &blk_types_empty_locs_in_grid[blk_id_type->index], &block_scores, blk_loc_registry, rng); //update heap based on update_heap_freq calculated above if (blocks_placed_since_heap_update % (update_heap_freq) == 0) { @@ -1090,7 +1104,8 @@ bool place_one_block(const ClusterBlockId blk_id, enum e_pad_loc_type pad_loc_type, std::vector* blk_types_empty_locs_in_grid, vtr::vector* block_scores, - BlkLocRegistry& blk_loc_registry) { + BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng) { const std::vector& pl_macros = g_vpr_ctx.placement().pl_macros; const auto& block_locs = blk_loc_registry.block_locs(); @@ -1108,7 +1123,7 @@ bool place_one_block(const ClusterBlockId blk_id, if (imacro != -1) { //If the block belongs to a macro, pass that macro to the placement routines VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, "\tBelongs to a macro %d\n", imacro); const t_pl_macro& pl_macro = pl_macros[imacro]; - placed_macro = place_macro(MAX_NUM_TRIES_TO_PLACE_MACROS_RANDOMLY, pl_macro, pad_loc_type, blk_types_empty_locs_in_grid, *block_scores, blk_loc_registry); + placed_macro = place_macro(MAX_NUM_TRIES_TO_PLACE_MACROS_RANDOMLY, pl_macro, pad_loc_type, blk_types_empty_locs_in_grid, *block_scores, blk_loc_registry, rng); } else { //If it does not belong to a macro, create a macro with the one block and then pass to the placement routines //This is done so that the initial placement flow can be the same whether the block belongs to a macro or not @@ -1117,7 +1132,7 @@ bool place_one_block(const ClusterBlockId blk_id, macro_member.offset = t_pl_offset(0, 0, 0, 0); t_pl_macro pl_macro; pl_macro.members.push_back(macro_member); - placed_macro = place_macro(MAX_NUM_TRIES_TO_PLACE_MACROS_RANDOMLY, pl_macro, pad_loc_type, blk_types_empty_locs_in_grid, *block_scores, blk_loc_registry); + placed_macro = place_macro(MAX_NUM_TRIES_TO_PLACE_MACROS_RANDOMLY, pl_macro, pad_loc_type, blk_types_empty_locs_in_grid, *block_scores, blk_loc_registry, rng); } return placed_macro; @@ -1151,7 +1166,8 @@ void initial_placement(const t_placer_opts& placer_opts, const char* constraints_file, const t_noc_opts& noc_opts, BlkLocRegistry& blk_loc_registry, - std::optional& noc_cost_handler) { + std::optional& noc_cost_handler, + vtr::RngContainer& rng) { vtr::ScopedStartFinishTimer timer("Initial Placement"); auto& block_locs = blk_loc_registry.mutable_block_locs(); @@ -1172,21 +1188,18 @@ void initial_placement(const t_placer_opts& placer_opts, // Compute and store compressed floorplanning constraints alloc_and_load_compressed_cluster_constraints(); - // read the constraint file and place fixed blocks if (strlen(constraints_file) != 0) { read_constraints(constraints_file, blk_loc_registry); } - - if(!placer_opts.read_initial_place_file.empty()) { const auto& grid = g_vpr_ctx.device().grid; read_place(nullptr, placer_opts.read_initial_place_file.c_str(), blk_loc_registry, false, grid); } else { if (noc_opts.noc) { // NoC routers are placed before other blocks - initial_noc_placement(noc_opts, placer_opts, blk_loc_registry, noc_cost_handler.value()); + initial_noc_placement(noc_opts, blk_loc_registry, noc_cost_handler.value(), rng); propagate_place_constraints(); } @@ -1194,7 +1207,7 @@ void initial_placement(const t_placer_opts& placer_opts, vtr::vector block_scores = assign_block_scores(); //Place all blocks - place_all_blocks(placer_opts, block_scores, placer_opts.pad_loc_type, constraints_file, blk_loc_registry); + place_all_blocks(placer_opts, block_scores, placer_opts.pad_loc_type, constraints_file, blk_loc_registry, rng); } alloc_and_load_movable_blocks(block_locs); diff --git a/vpr/src/place/initial_placement.h b/vpr/src/place/initial_placement.h index 567978806cb..f2078a3e720 100644 --- a/vpr/src/place/initial_placement.h +++ b/vpr/src/place/initial_placement.h @@ -63,6 +63,7 @@ struct t_grid_empty_locs_block_type { * @param pad_loc_type Used to check whether an io block needs to be marked as fixed. * @param blk_loc_registry Placement block location information. To be filled with the location * where pl_macro is placed. + * @param rng A random number generator for choosing a location randomly. * * @return true if the macro gets placed, false if not. */ @@ -70,7 +71,8 @@ bool try_place_macro_randomly(const t_pl_macro& pl_macro, const PartitionRegion& pr, t_logical_block_type_ptr block_type, e_pad_loc_type pad_loc_type, - BlkLocRegistry& blk_loc_registry); + BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng); /** @@ -134,12 +136,15 @@ bool is_block_placed(ClusterBlockId blk_id, * and NoC-related weighting factors. * @param blk_loc_registry Placement block location information. To be filled with the location * where pl_macro is placed. + * @param rng A random number generator used for random placement and simulated annealing of + * NoC routers. */ void initial_placement(const t_placer_opts& placer_opts, const char* constraints_file, const t_noc_opts& noc_opts, BlkLocRegistry& blk_loc_registry, - std::optional& noc_cost_handler); + std::optional& noc_cost_handler, + vtr::RngContainer& rng); /** * @brief Looks for a valid placement location for block. @@ -150,6 +155,7 @@ void initial_placement(const t_placer_opts& placer_opts, * @param block_scores Scores assign to different blocks to determine which one should be placed first. * @param blk_loc_registry Placement block location information. To be filled with the location * where pl_macro is placed. + * @param rng A random number generator. * * @return true if the block gets placed, false if not. */ @@ -157,7 +163,8 @@ bool place_one_block(const ClusterBlockId blk_id, e_pad_loc_type pad_loc_type, std::vector* blk_types_empty_locs_in_grid, vtr::vector* block_scores, - BlkLocRegistry& blk_loc_registry); + BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng); diff --git a/vpr/src/place/manual_move_generator.cpp b/vpr/src/place/manual_move_generator.cpp index 4146cfb3eeb..04f528025b7 100644 --- a/vpr/src/place/manual_move_generator.cpp +++ b/vpr/src/place/manual_move_generator.cpp @@ -18,8 +18,8 @@ # include "draw.h" #endif //NO_GRAPHICS -ManualMoveGenerator::ManualMoveGenerator(PlacerState& placer_state) - : MoveGenerator(placer_state, e_reward_function::UNDEFINED_REWARD) {} +ManualMoveGenerator::ManualMoveGenerator(PlacerState& placer_state, vtr::RngContainer& rng) + : MoveGenerator(placer_state, e_reward_function::UNDEFINED_REWARD, rng) {} //Manual Move Generator function e_create_move ManualMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_affected, diff --git a/vpr/src/place/manual_move_generator.h b/vpr/src/place/manual_move_generator.h index 6543c2c3a3a..12c71dc0ce9 100644 --- a/vpr/src/place/manual_move_generator.h +++ b/vpr/src/place/manual_move_generator.h @@ -27,7 +27,7 @@ class ManualMoveGenerator : public MoveGenerator { public: ManualMoveGenerator() = delete; - ManualMoveGenerator(PlacerState& placer_state); + ManualMoveGenerator(PlacerState& placer_state, vtr::RngContainer& rng); //Evaluates if move is successful and legal or unable to do. e_create_move propose_move(t_pl_blocks_to_be_moved& blocks_affected, diff --git a/vpr/src/place/median_move_generator.cpp b/vpr/src/place/median_move_generator.cpp index 47646b6f682..64c89df7806 100644 --- a/vpr/src/place/median_move_generator.cpp +++ b/vpr/src/place/median_move_generator.cpp @@ -8,8 +8,9 @@ #include MedianMoveGenerator::MedianMoveGenerator(PlacerState& placer_state, - e_reward_function reward_function) - : MoveGenerator(placer_state, reward_function) {} + e_reward_function reward_function, + vtr::RngContainer& rng) + : MoveGenerator(placer_state, reward_function, rng) {} e_create_move MedianMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_affected, t_propose_action& proposed_action, @@ -29,7 +30,8 @@ e_create_move MedianMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_ /*highly_crit_block=*/false, /*net_from=*/nullptr, /*pin_from=*/nullptr, - placer_state); + placer_state, + rng_); VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, "Median Move Choose Block %d - rlim %f\n", size_t(b_from), rlim); @@ -173,7 +175,7 @@ e_create_move MedianMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_ median_point.y = (limit_coords.ymin + limit_coords.ymax) / 2; median_point.layer = (limit_coords.layer_min + limit_coords.layer_max) / 2; - if (!find_to_loc_centroid(cluster_from_type, from, median_point, range_limiters, to, b_from, blk_loc_registry)) { + if (!find_to_loc_centroid(cluster_from_type, from, median_point, range_limiters, to, b_from, blk_loc_registry, rng_)) { return e_create_move::ABORT; } diff --git a/vpr/src/place/median_move_generator.h b/vpr/src/place/median_move_generator.h index 15bda1dae33..12c5baa2255 100644 --- a/vpr/src/place/median_move_generator.h +++ b/vpr/src/place/median_move_generator.h @@ -19,7 +19,8 @@ class MedianMoveGenerator : public MoveGenerator { public: MedianMoveGenerator() = delete; MedianMoveGenerator(PlacerState& placer_state, - e_reward_function reward_function); + e_reward_function reward_function, + vtr::RngContainer& rng); private: e_create_move propose_move(t_pl_blocks_to_be_moved& blocks_affected, diff --git a/vpr/src/place/move_generator.h b/vpr/src/place/move_generator.h index d14c14312d0..885df010864 100644 --- a/vpr/src/place/move_generator.h +++ b/vpr/src/place/move_generator.h @@ -57,10 +57,12 @@ class MoveGenerator { * be stored in this object. * @param reward_function Specifies the reward function to update q-tables * of the RL agent. + * @param rng A random number generator to be used for block and location selection. */ - MoveGenerator(PlacerState& placer_state, e_reward_function reward_function) + MoveGenerator(PlacerState& placer_state, e_reward_function reward_function, vtr::RngContainer& rng) : placer_state_(placer_state) - , reward_func_(reward_function) {} + , reward_func_(reward_function) + , rng_(rng) {} MoveGenerator() = delete; MoveGenerator(const MoveGenerator&) = delete; @@ -114,6 +116,7 @@ class MoveGenerator { protected: std::reference_wrapper placer_state_; e_reward_function reward_func_; + vtr::RngContainer& rng_; }; #endif diff --git a/vpr/src/place/move_utils.cpp b/vpr/src/place/move_utils.cpp index 67889ca115a..050b1c0bf6d 100644 --- a/vpr/src/place/move_utils.cpp +++ b/vpr/src/place/move_utils.cpp @@ -570,15 +570,16 @@ ClusterBlockId propose_block_to_move(const t_placer_opts& placer_opts, bool highly_crit_block, ClusterNetId* net_from, int* pin_from, - const PlacerState& placer_state) { + const PlacerState& placer_state, + vtr::RngContainer& rng) { ClusterBlockId b_from = ClusterBlockId::INVALID(); auto& cluster_ctx = g_vpr_ctx.clustering(); if (logical_blk_type_index == -1) { //If the block type is unspecified, choose any random block to be swapped with another random block if (highly_crit_block) { - b_from = pick_from_highly_critical_block(*net_from, *pin_from, placer_state); + b_from = pick_from_highly_critical_block(*net_from, *pin_from, placer_state, rng); } else { - b_from = pick_from_block(); + b_from = pick_from_block(rng); } //if a movable block found, set the block type @@ -587,9 +588,9 @@ ClusterBlockId propose_block_to_move(const t_placer_opts& placer_opts, } } else { //If the block type is specified, choose a random block with blk_type to be swapped with another random block if (highly_crit_block) { - b_from = pick_from_highly_critical_block(*net_from, *pin_from, logical_blk_type_index, placer_state); + b_from = pick_from_highly_critical_block(*net_from, *pin_from, logical_blk_type_index, placer_state, rng); } else { - b_from = pick_from_block(logical_blk_type_index); + b_from = pick_from_block(logical_blk_type_index, rng); } } #ifdef VTR_ENABLE_DEBUG_LOGGING @@ -610,17 +611,15 @@ const std::vector& movable_blocks_per_type(const t_logical_block return place_ctx.movable_blocks_per_type[blk_type.index]; } -//Pick a random movable block to be swapped with another random block. -//If none is found return ClusterBlockId::INVALID() -ClusterBlockId pick_from_block() { - auto& place_ctx = g_vpr_ctx.mutable_placement(); +ClusterBlockId pick_from_block(vtr::RngContainer& rng) { + auto& place_ctx = g_vpr_ctx.placement(); // get the number of movable clustered blocks const size_t n_movable_blocks = place_ctx.movable_blocks.size(); if (n_movable_blocks > 0) { //Pick a movable block at random and return it - auto b_from = ClusterBlockId(vtr::irand((int)n_movable_blocks - 1)); + auto b_from = ClusterBlockId(rng.irand((int)n_movable_blocks - 1)); return b_from; } else { //No movable blocks found @@ -628,10 +627,8 @@ ClusterBlockId pick_from_block() { } } -//Pick a random movable block with a specific blk_type to be swapped with another random block. -//If none is found return ClusterBlockId::INVALID() -ClusterBlockId pick_from_block(const int logical_blk_type_index) { - auto& place_ctx = g_vpr_ctx.mutable_placement(); +ClusterBlockId pick_from_block(const int logical_blk_type_index, vtr::RngContainer& rng) { + auto& place_ctx = g_vpr_ctx.placement(); const auto& movable_blocks_of_type = place_ctx.movable_blocks_per_type[logical_blk_type_index]; @@ -639,7 +636,7 @@ ClusterBlockId pick_from_block(const int logical_blk_type_index) { return ClusterBlockId::INVALID(); } - auto b_from = ClusterBlockId(movable_blocks_of_type[vtr::irand((int)movable_blocks_of_type.size() - 1)]); + auto b_from = ClusterBlockId(movable_blocks_of_type[rng.irand((int)movable_blocks_of_type.size() - 1)]); return b_from; } @@ -648,7 +645,8 @@ ClusterBlockId pick_from_block(const int logical_blk_type_index) { //If none is found return ClusterBlockId::INVALID() ClusterBlockId pick_from_highly_critical_block(ClusterNetId& net_from, int& pin_from, - const PlacerState& placer_state) { + const PlacerState& placer_state, + vtr::RngContainer& rng) { auto& cluster_ctx = g_vpr_ctx.clustering(); auto& place_move_ctx = placer_state.move(); auto& block_locs = placer_state.block_locs(); @@ -663,7 +661,7 @@ ClusterBlockId pick_from_highly_critical_block(ClusterNetId& net_from, } //pick a random highly critical pin and find the nets driver block - std::pair crit_pin = place_move_ctx.highly_crit_pins[vtr::irand(place_move_ctx.highly_crit_pins.size() - 1)]; + std::pair crit_pin = place_move_ctx.highly_crit_pins[rng.irand(place_move_ctx.highly_crit_pins.size() - 1)]; ClusterBlockId b_from = cluster_ctx.clb_nlist.net_driver_block(crit_pin.first); if (block_locs[b_from].is_fixed) { @@ -683,7 +681,8 @@ ClusterBlockId pick_from_highly_critical_block(ClusterNetId& net_from, ClusterBlockId pick_from_highly_critical_block(ClusterNetId& net_from, int& pin_from, const int logical_blk_type_index, - const PlacerState& placer_state) { + const PlacerState& placer_state, + vtr::RngContainer& rng) { auto& cluster_ctx = g_vpr_ctx.clustering(); auto& place_move_ctx = placer_state.move(); auto& block_locs = placer_state.block_locs(); @@ -698,7 +697,7 @@ ClusterBlockId pick_from_highly_critical_block(ClusterNetId& net_from, } //pick a random highly critical pin and find the nets driver block - std::pair crit_pin = place_move_ctx.highly_crit_pins[vtr::irand(place_move_ctx.highly_crit_pins.size() - 1)]; + std::pair crit_pin = place_move_ctx.highly_crit_pins[rng.irand(place_move_ctx.highly_crit_pins.size() - 1)]; ClusterBlockId b_from = cluster_ctx.clb_nlist.net_driver_block(crit_pin.first); //Check if picked block type matches with the blk_type specified, and it is not fixed @@ -724,7 +723,8 @@ bool find_to_loc_uniform(t_logical_block_type_ptr type, const t_pl_loc& from, t_pl_loc& to, ClusterBlockId b_from, - const BlkLocRegistry& blk_loc_registry) { + const BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng) { //Finds a legal swap to location for the given type, starting from 'from.x' and 'from.y' // //Note that the range limit (rlim) is applied in a logical sense (i.e. 'compressed' grid space consisting @@ -736,9 +736,9 @@ bool find_to_loc_uniform(t_logical_block_type_ptr type, //case with a physical distance rlim) //Retrieve the compressed block grid for this block type - const auto& compressed_block_grid = g_vpr_ctx.placement().compressed_block_grids[type->index]; + const t_compressed_block_grid& compressed_block_grid = g_vpr_ctx.placement().compressed_block_grids[type->index]; const int num_layers = g_vpr_ctx.device().grid.get_num_layers(); - const int to_layer_num = get_random_layer(type); + const int to_layer_num = get_random_layer(type, rng); VTR_ASSERT(to_layer_num != OPEN); //Determine the coordinates in the compressed grid space of the current block @@ -773,7 +773,8 @@ bool find_to_loc_uniform(t_logical_block_type_ptr type, /*is_median=*/false, to_layer_num, /*search_for_empty=*/false, - blk_loc_registry); + blk_loc_registry, + rng); if (!legal) { //No valid position found @@ -783,7 +784,7 @@ bool find_to_loc_uniform(t_logical_block_type_ptr type, VTR_ASSERT(to_compressed_loc); //Convert to true (uncompressed) grid locations - compressed_grid_to_loc(type, to_compressed_loc, to); + compressed_grid_to_loc(type, to_compressed_loc, to, rng); auto& grid = g_vpr_ctx.device().grid; const auto& to_type = grid.get_physical_type(t_physical_tile_loc(to.x, to.y, to.layer)); @@ -813,7 +814,8 @@ bool find_to_loc_median(t_logical_block_type_ptr blk_type, const t_bb* limit_coords, t_pl_loc& to_loc, ClusterBlockId b_from, - const BlkLocRegistry& blk_loc_registry) { + const BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng) { int num_layers = g_vpr_ctx.device().grid.get_num_layers(); const int to_layer_num = to_loc.layer; VTR_ASSERT(to_layer_num != OPEN); @@ -872,7 +874,8 @@ bool find_to_loc_median(t_logical_block_type_ptr blk_type, /*is_median=*/true, to_layer_num, /*search_for_empty=*/false, - blk_loc_registry); + blk_loc_registry, + rng); if (!legal) { //No valid position found @@ -882,7 +885,7 @@ bool find_to_loc_median(t_logical_block_type_ptr blk_type, VTR_ASSERT(to_compressed_loc); //Convert to true (uncompressed) grid locations - compressed_grid_to_loc(blk_type, to_compressed_loc, to_loc); + compressed_grid_to_loc(blk_type, to_compressed_loc, to_loc, rng); auto& grid = g_vpr_ctx.device().grid; const auto& to_type = grid.get_physical_type(t_physical_tile_loc(to_loc.x, to_loc.y, to_loc.layer)); @@ -904,7 +907,8 @@ bool find_to_loc_centroid(t_logical_block_type_ptr blk_type, const t_range_limiters& range_limiters, t_pl_loc& to_loc, ClusterBlockId b_from, - const BlkLocRegistry& blk_loc_registry) { + const BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng) { //Retrieve the compressed block grid for this block type const auto& compressed_block_grid = g_vpr_ctx.placement().compressed_block_grids[blk_type->index]; const int to_layer_num = centroid.layer; @@ -960,7 +964,8 @@ bool find_to_loc_centroid(t_logical_block_type_ptr blk_type, /*is_median=*/false, to_layer_num, /*search_for_empty=*/false, - blk_loc_registry); + blk_loc_registry, + rng); if (!legal) { //No valid position found @@ -970,7 +975,7 @@ bool find_to_loc_centroid(t_logical_block_type_ptr blk_type, VTR_ASSERT(to_compressed_loc); //Convert to true (uncompressed) grid locations - compressed_grid_to_loc(blk_type, to_compressed_loc, to_loc); + compressed_grid_to_loc(blk_type, to_compressed_loc, to_loc, rng); auto& grid = g_vpr_ctx.device().grid; const auto& to_type = grid.get_physical_type(t_physical_tile_loc(to_loc.x, to_loc.y, to_loc.layer)); @@ -1003,10 +1008,10 @@ const std::string& move_type_to_string(e_move_type move) { return move_type_strings[int(move)]; } -//Convert to true (uncompressed) grid locations void compressed_grid_to_loc(t_logical_block_type_ptr blk_type, t_physical_tile_loc compressed_loc, - t_pl_loc& to_loc) { + t_pl_loc& to_loc, + vtr::RngContainer& rng) { const auto& compressed_block_grid = g_vpr_ctx.placement().compressed_block_grids[blk_type->index]; auto grid_loc = compressed_block_grid.compressed_loc_to_grid_loc(compressed_loc); @@ -1015,21 +1020,22 @@ void compressed_grid_to_loc(t_logical_block_type_ptr blk_type, //Each x/y location contains only a single type, so we can pick a random z (capacity) location auto& compatible_sub_tiles = compressed_block_grid.compatible_sub_tile_num(to_type->index); - int sub_tile = compatible_sub_tiles[vtr::irand((int)compatible_sub_tiles.size() - 1)]; + int sub_tile = compatible_sub_tiles[rng.irand((int)compatible_sub_tiles.size() - 1)]; to_loc = t_pl_loc(grid_loc.x, grid_loc.y, sub_tile, grid_loc.layer_num); } int find_empty_compatible_subtile(t_logical_block_type_ptr type, const t_physical_tile_loc& to_loc, - const GridBlock& grid_blocks) { + const GridBlock& grid_blocks, + vtr::RngContainer& rng) { auto& device_ctx = g_vpr_ctx.device(); const auto& compressed_block_grid = g_vpr_ctx.placement().compressed_block_grids[type->index]; int return_sub_tile = -1; t_pl_loc to_uncompressed_loc; - compressed_grid_to_loc(type, to_loc, to_uncompressed_loc); + compressed_grid_to_loc(type, to_loc, to_uncompressed_loc, rng); const t_physical_tile_loc to_phy_uncompressed_loc{to_uncompressed_loc.x, to_uncompressed_loc.y, to_uncompressed_loc.layer}; const t_physical_tile_type_ptr phy_type = device_ctx.grid.get_physical_type(to_phy_uncompressed_loc); const auto& compatible_sub_tiles = compressed_block_grid.compatible_sub_tiles_for_tile.at(phy_type->index); @@ -1052,7 +1058,8 @@ bool find_compatible_compressed_loc_in_range(t_logical_block_type_ptr type, bool is_median, int to_layer_num, bool search_for_empty, - const BlkLocRegistry& blk_loc_registry) { + const BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng) { //TODO For the time being, the blocks only moved in the same layer. This assertion should be removed after VPR is updated to move blocks between layers VTR_ASSERT(to_layer_num == from_loc.layer_num); const auto& compressed_block_grid = g_vpr_ctx.placement().compressed_block_grids[type->index]; @@ -1068,7 +1075,7 @@ bool find_compatible_compressed_loc_in_range(t_logical_block_type_ptr type, while (!legal && (int)tried_cx_to.size() < possibilities) { //Until legal or all possibilities exhausted //Pick a random x-location within [min_cx, max_cx], //until we find a legal swap, or have exhausted all possibilities - to_loc.x = search_range.xmin + vtr::irand(delta_cx); + to_loc.x = search_range.xmin + rng.irand(delta_cx); VTR_ASSERT(to_loc.x >= search_range.xmin); VTR_ASSERT(to_loc.x <= search_range.xmax); @@ -1118,7 +1125,7 @@ bool find_compatible_compressed_loc_in_range(t_logical_block_type_ptr type, std::unordered_set tried_dy; while (!legal && (int)tried_dy.size() < y_range) { //Until legal or all possibilities exhausted //Randomly pick a y location - int dy = vtr::irand(y_range - 1); + int dy = rng.irand(y_range - 1); //Record this y location as tried auto res2 = tried_dy.insert(dy); @@ -1135,7 +1142,7 @@ bool find_compatible_compressed_loc_in_range(t_logical_block_type_ptr type, if (from_loc.x == to_loc.x && from_loc.y == to_loc.y && from_loc.layer_num == to_layer_num) { continue; //Same from/to location -- try again for new y-position } else if (search_for_empty) { // Check if the location has at least one empty sub-tile - legal = find_empty_compatible_subtile(type, to_loc, blk_loc_registry.grid_blocks()) >= 0; + legal = find_empty_compatible_subtile(type, to_loc, blk_loc_registry.grid_blocks(), rng) >= 0; } else { legal = true; } @@ -1321,14 +1328,14 @@ int find_free_layer(t_logical_block_type_ptr logical_block, return free_layer; } -int get_random_layer(t_logical_block_type_ptr logical_block) { +int get_random_layer(t_logical_block_type_ptr logical_block, vtr::RngContainer& rng) { const auto& compatible_layers = g_vpr_ctx.placement().compressed_block_grids[logical_block->index].get_layer_nums(); VTR_ASSERT(!compatible_layers.empty()); int layer_num = OPEN; if (compatible_layers.size() == 1) { layer_num = compatible_layers[0]; } else { - layer_num = compatible_layers[vtr::irand(compatible_layers.size() - 1)]; + layer_num = compatible_layers[rng.irand(compatible_layers.size() - 1)]; } return layer_num; diff --git a/vpr/src/place/move_utils.h b/vpr/src/place/move_utils.h index 80359dd07a2..1033f8ffe1f 100644 --- a/vpr/src/place/move_utils.h +++ b/vpr/src/place/move_utils.h @@ -7,6 +7,9 @@ class PlacerState; class BlkLocRegistry; +namespace vtr { +class RngContainer; +} /* Cut off for incremental bounding box updates. * * 4 is fastest -- I checked. */ @@ -187,7 +190,8 @@ ClusterBlockId propose_block_to_move(const t_placer_opts& placer_opts, bool highly_crit_block, ClusterNetId* net_from, int* pin_from, - const PlacerState& placer_state); + const PlacerState& placer_state, + vtr::RngContainer& rng); /** * Returns all movable clustered blocks with a specified logical block type. @@ -201,7 +205,7 @@ const std::vector& movable_blocks_per_type(const t_logical_block * * @return BlockId of the selected block, ClusterBlockId::INVALID() if no block with specified block type found */ -ClusterBlockId pick_from_block(); +ClusterBlockId pick_from_block(vtr::RngContainer& rng); /** * @brief Find a block with a specific block type to be swapped with another block @@ -210,7 +214,7 @@ ClusterBlockId pick_from_block(); * * @return BlockId of the selected block, ClusterBlockId::INVALID() if no block with specified block type found */ -ClusterBlockId pick_from_block(int logical_blk_type_index); +ClusterBlockId pick_from_block(int logical_blk_type_index, vtr::RngContainer& rng); /** * @brief Select a random highly critical block to be swapped with another block @@ -219,7 +223,8 @@ ClusterBlockId pick_from_block(int logical_blk_type_index); */ ClusterBlockId pick_from_highly_critical_block(ClusterNetId& net_from, int& pin_from, - const PlacerState& placer_state); + const PlacerState& placer_state, + vtr::RngContainer& rng); /** * @brief Find a block with a specific block type to be swapped with another block @@ -231,14 +236,16 @@ ClusterBlockId pick_from_highly_critical_block(ClusterNetId& net_from, ClusterBlockId pick_from_highly_critical_block(ClusterNetId& net_from, int& pin_from, int logical_blk_type_index, - const PlacerState& placer_state); + const PlacerState& placer_state, + vtr::RngContainer& rng); bool find_to_loc_uniform(t_logical_block_type_ptr type, float rlim, const t_pl_loc& from, t_pl_loc& to, ClusterBlockId b_from, - const BlkLocRegistry& blk_loc_registry); + const BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng); // Accessor f_placer_breakpoint_reached // return true when a placer breakpoint is reached @@ -268,7 +275,8 @@ bool find_to_loc_median(t_logical_block_type_ptr blk_type, const t_bb* limit_coords, t_pl_loc& to_loc, ClusterBlockId b_from, - const BlkLocRegistry& blk_loc_registry); + const BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng); /** * @brief Find a legal swap to location for the given type in a range around a specific location. @@ -290,7 +298,8 @@ bool find_to_loc_centroid(t_logical_block_type_ptr blk_type, const t_range_limiters& range_limiters, t_pl_loc& to_loc, ClusterBlockId b_from, - const BlkLocRegistry& blk_loc_registry); + const BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng); const std::string& move_type_to_string(e_move_type); @@ -305,7 +314,8 @@ const std::string& move_type_to_string(e_move_type); */ void compressed_grid_to_loc(t_logical_block_type_ptr blk_type, t_physical_tile_loc compressed_loc, - t_pl_loc& to_loc); + t_pl_loc& to_loc, + vtr::RngContainer& rng); /** * @brief Tries to find an compatible empty subtile with the given type at @@ -322,7 +332,8 @@ void compressed_grid_to_loc(t_logical_block_type_ptr blk_type, */ int find_empty_compatible_subtile(t_logical_block_type_ptr type, const t_physical_tile_loc& to_loc, - const GridBlock& grid_blocks); + const GridBlock& grid_blocks, + vtr::RngContainer& rng); /** * @brief find compressed location in a compressed range for a specific type in the given layer (to_layer_num) @@ -343,7 +354,8 @@ bool find_compatible_compressed_loc_in_range(t_logical_block_type_ptr type, bool is_median, int to_layer_num, bool search_for_empty, - const BlkLocRegistry& blk_loc_registry); + const BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng); /** * @brief Get the the compressed loc from the uncompressed loc (grid_loc) @@ -436,7 +448,7 @@ int find_free_layer(t_logical_block_type_ptr logical_block, const t_pl_loc& loc, const BlkLocRegistry& blk_loc_registry); -int get_random_layer(t_logical_block_type_ptr logical_block); +int get_random_layer(t_logical_block_type_ptr logical_block, vtr::RngContainer& rng); /** * @brief Iterate over all layers and get the maximum x and y over that layers that have a valid value. set the layer min and max diff --git a/vpr/src/place/noc_place_utils.cpp b/vpr/src/place/noc_place_utils.cpp index 3d67588a532..9f5fbb6045d 100644 --- a/vpr/src/place/noc_place_utils.cpp +++ b/vpr/src/place/noc_place_utils.cpp @@ -34,7 +34,8 @@ static bool select_random_router_cluster(ClusterBlockId& b_from, t_pl_loc& from, t_logical_block_type_ptr& cluster_from_type, - const vtr::vector_map& block_locs); + const vtr::vector_map& block_locs, + vtr::RngContainer& rng); /** * @brief Given two traffic flow routes, finds links that appear @@ -820,20 +821,22 @@ std::vector NocCostHandler::get_top_n_congested_links(int n) { } /* Below are functions related to the feature that forces to the placer to swap router blocks for a certain percentage of the total number of swaps */ -bool check_for_router_swap(int user_supplied_noc_router_swap_percentage) { +bool check_for_router_swap(int user_supplied_noc_router_swap_percentage, + vtr::RngContainer& rng) { /* A random number between 0-100 is generated here and compared to the user * supplied value. If the random number is less than the user supplied * value we indicate that a router block should be swapped. By doing this * we now only swap router blocks for the percentage of time the user * supplied. * */ - return (vtr::irand(99) < user_supplied_noc_router_swap_percentage); + return (rng.irand(99) < user_supplied_noc_router_swap_percentage); } static bool select_random_router_cluster(ClusterBlockId& b_from, t_pl_loc& from, t_logical_block_type_ptr& cluster_from_type, - const vtr::vector_map& block_locs) { + const vtr::vector_map& block_locs, + vtr::RngContainer& rng) { // need to access all the router cluster blocks in the design const auto& noc_ctx = g_vpr_ctx.noc(); auto& cluster_ctx = g_vpr_ctx.clustering(); @@ -849,7 +852,7 @@ static bool select_random_router_cluster(ClusterBlockId& b_from, const int number_of_router_blocks = static_cast(router_clusters.size()); //randomly choose a router block to move - const int random_cluster_block_index = vtr::irand(number_of_router_blocks - 1); + const int random_cluster_block_index = rng.irand(number_of_router_blocks - 1); b_from = router_clusters[random_cluster_block_index]; //check if the block is movable @@ -867,7 +870,8 @@ static bool select_random_router_cluster(ClusterBlockId& b_from, e_create_move propose_router_swap(t_pl_blocks_to_be_moved& blocks_affected, float rlim, - const BlkLocRegistry& blk_loc_registry) { + const BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng) { // block ID for the randomly selected router cluster ClusterBlockId b_from; // current location of the randomly selected router cluster @@ -876,7 +880,11 @@ e_create_move propose_router_swap(t_pl_blocks_to_be_moved& blocks_affected, t_logical_block_type_ptr cluster_from_type; // Randomly select a router cluster - bool random_select_success = select_random_router_cluster(b_from, from, cluster_from_type, blk_loc_registry.block_locs()); + bool random_select_success = select_random_router_cluster(b_from, + from, + cluster_from_type, + blk_loc_registry.block_locs(), + rng); // If a random router cluster could not be selected, no move can be proposed if (!random_select_success) { @@ -886,7 +894,7 @@ e_create_move propose_router_swap(t_pl_blocks_to_be_moved& blocks_affected, // now choose a compatible block to swap with t_pl_loc to; to.layer = from.layer; - if (!find_to_loc_uniform(cluster_from_type, rlim, from, to, b_from, blk_loc_registry)) { + if (!find_to_loc_uniform(cluster_from_type, rlim, from, to, b_from, blk_loc_registry, rng)) { return e_create_move::ABORT; } diff --git a/vpr/src/place/noc_place_utils.h b/vpr/src/place/noc_place_utils.h index ec56c1c5c87..0224ef78af8 100644 --- a/vpr/src/place/noc_place_utils.h +++ b/vpr/src/place/noc_place_utils.h @@ -640,7 +640,8 @@ double calculate_noc_cost(const NocCostTerms& cost_terms, * @return true This indicates that a router block should be swapped * @return false This indicates that a router block should not be swapped */ -bool check_for_router_swap(int user_supplied_noc_router_swap_percentage); +bool check_for_router_swap(int user_supplied_noc_router_swap_percentage, + vtr::RngContainer& rng); /** * @brief Generates a placement move by first choosing a random router cluster @@ -660,7 +661,8 @@ bool check_for_router_swap(int user_supplied_noc_router_swap_percentage); */ e_create_move propose_router_swap(t_pl_blocks_to_be_moved& blocks_affected, float rlim, - const BlkLocRegistry& blk_loc_registry); + const BlkLocRegistry& blk_loc_registry, + vtr::RngContainer& rng); /** * @brief Writes out the locations of the router cluster blocks in the diff --git a/vpr/src/place/place.cpp b/vpr/src/place/place.cpp index 5b7d461e60f..b61df5c603f 100644 --- a/vpr/src/place/place.cpp +++ b/vpr/src/place/place.cpp @@ -209,7 +209,8 @@ static e_move_result try_swap(const t_annealing_state* state, t_swap_stats& swap_stats, PlacerState& placer_state, NetCostHandler& net_cost_handler, - std::optional& noc_cost_handler); + std::optional& noc_cost_handler, + vtr::RngContainer& rng); static void check_place(const t_placer_costs& costs, @@ -250,7 +251,8 @@ static float starting_t(const t_annealing_state* state, t_swap_stats& swap_stats, PlacerState& placer_state, NetCostHandler& net_cost_handler, - std::optional& noc_cost_handler); + std::optional& noc_cost_handler, + vtr::RngContainer& rng); static int count_connections(); @@ -268,7 +270,7 @@ static void invalidate_affected_connections( static float analyze_setup_slack_cost(const PlacerSetupSlacks* setup_slacks, const PlacerState& placer_state); -static e_move_result assess_swap(double delta_c, double t); +static e_move_result assess_swap(double delta_c, double t, vtr::RngContainer& rng); static void update_placement_cost_normalization_factors(t_placer_costs* costs, const t_placer_opts& placer_opts, @@ -312,7 +314,8 @@ static void placement_inner_loop(const t_annealing_state* state, t_swap_stats& swap_stats, PlacerState& placer_state, NetCostHandler& net_cost_handler, - std::optional& noc_cost_handler); + std::optional& noc_cost_handler, + vtr::RngContainer& rng); static void generate_post_place_timing_reports(const t_placer_opts& placer_opts, const t_analysis_opts& analysis_opts, @@ -433,6 +436,7 @@ void try_place(const Netlist<>& net_list, const auto& p_timing_ctx = placer_state.timing(); const auto& p_runtime_ctx = placer_state.runtime(); + vtr::RngContainer rng(placer_opts.seed); std::optional noc_cost_handler; // create cost handler objects @@ -445,7 +449,7 @@ void try_place(const Netlist<>& net_list, } #endif - ManualMoveGenerator manual_move_generator(placer_state); + ManualMoveGenerator manual_move_generator(placer_state, rng); vtr::ScopedStartFinishTimer timer("Placement"); @@ -454,10 +458,10 @@ void try_place(const Netlist<>& net_list, } initial_placement(placer_opts, placer_opts.constraints_file.c_str(), - noc_opts, blk_loc_registry, noc_cost_handler); + noc_opts, blk_loc_registry, noc_cost_handler, rng); //create the move generator based on the chosen strategy - auto [move_generator, move_generator2] = create_move_generators(placer_state, placer_opts, move_lim, noc_opts.noc_centroid_weight); + auto [move_generator, move_generator2] = create_move_generators(placer_state, placer_opts, move_lim, noc_opts.noc_centroid_weight, rng); if (!placer_opts.write_initial_place_file.empty()) { print_place(nullptr, nullptr, placer_opts.write_initial_place_file.c_str(), placer_state.block_locs()); @@ -702,7 +706,7 @@ void try_place(const Netlist<>& net_list, placer_setup_slacks.get(), timing_info.get(), *move_generator, manual_move_generator, pin_timing_invalidator.get(), blocks_affected, placer_opts, noc_opts, move_type_stat, - swap_stats, placer_state, net_cost_handler, noc_cost_handler); + swap_stats, placer_state, net_cost_handler, noc_cost_handler, rng); if (!placer_opts.move_stats_file.empty()) { f_move_stats_file = std::unique_ptr( @@ -776,7 +780,7 @@ void try_place(const Netlist<>& net_list, blocks_affected, timing_info.get(), placer_opts.place_algorithm, move_type_stat, timing_bb_factor, swap_stats, placer_state, - net_cost_handler, noc_cost_handler); + net_cost_handler, noc_cost_handler, rng); //move the update used move_generator to its original variable @@ -844,7 +848,7 @@ void try_place(const Netlist<>& net_list, blocks_affected, timing_info.get(), placer_opts.place_quench_algorithm, move_type_stat, timing_bb_factor, swap_stats, placer_state, - net_cost_handler, noc_cost_handler); + net_cost_handler, noc_cost_handler, rng); //move the update used move_generator to its original variable @@ -1060,7 +1064,8 @@ static void placement_inner_loop(const t_annealing_state* state, t_swap_stats& swap_stats, PlacerState& placer_state, NetCostHandler& net_cost_handler, - std::optional& noc_cost_handler) { + std::optional& noc_cost_handler, + vtr::RngContainer& rng) { //How many times have we dumped placement to a file this temperature? int inner_placement_save_count = 0; @@ -1075,7 +1080,7 @@ static void placement_inner_loop(const t_annealing_state* state, blocks_affected, delay_model, criticalities, setup_slacks, placer_opts, noc_opts, move_type_stat, place_algorithm, timing_bb_factor, manual_move_enabled, swap_stats, - placer_state, net_cost_handler, noc_cost_handler); + placer_state, net_cost_handler, noc_cost_handler, rng); if (swap_result == ACCEPTED) { /* Move was accepted. Update statistics that are useful for the annealing schedule. */ @@ -1177,7 +1182,8 @@ static float starting_t(const t_annealing_state* state, t_swap_stats& swap_stats, PlacerState& placer_state, NetCostHandler& net_cost_handler, - std::optional& noc_cost_handler) { + std::optional& noc_cost_handler, + vtr::RngContainer& rng) { if (annealing_sched.type == USER_SCHED) { return (annealing_sched.init_t); } @@ -1211,7 +1217,7 @@ static float starting_t(const t_annealing_state* state, blocks_affected, delay_model, criticalities, setup_slacks, placer_opts, noc_opts, move_type_stat, placer_opts.place_algorithm, REWARD_BB_TIMING_RELATIVE_WEIGHT, manual_move_enabled, swap_stats, - placer_state, net_cost_handler, noc_cost_handler); + placer_state, net_cost_handler, noc_cost_handler, rng); if (swap_result == ACCEPTED) { @@ -1285,7 +1291,8 @@ static e_move_result try_swap(const t_annealing_state* state, t_swap_stats& swap_stats, PlacerState& placer_state, NetCostHandler& net_cost_handler, - std::optional& noc_cost_handler) { + std::optional& noc_cost_handler, + vtr::RngContainer& rng) { /* Picks some block and moves it to another spot. If this spot is * * occupied, switch the blocks. Assess the change in cost function. * * rlim is the range limiter. * @@ -1317,13 +1324,13 @@ static e_move_result try_swap(const t_annealing_state* state, // Determine whether we need to force swap two router blocks bool router_block_move = false; if (noc_opts.noc) { - router_block_move = check_for_router_swap(noc_opts.noc_swap_percentage); + router_block_move = check_for_router_swap(noc_opts.noc_swap_percentage, rng); } /* Allow some fraction of moves to not be restricted by rlim, */ /* in the hopes of better escaping local minima. */ float rlim; - if (rlim_escape_fraction > 0. && vtr::frand() < rlim_escape_fraction) { + if (rlim_escape_fraction > 0. && rng.frand() < rlim_escape_fraction) { rlim = std::numeric_limits::infinity(); } else { rlim = state->rlim; @@ -1343,7 +1350,7 @@ static e_move_result try_swap(const t_annealing_state* state, #endif //NO_GRAPHICS } else if (router_block_move) { // generate a move where two random router blocks are swapped - create_move_outcome = propose_router_swap(blocks_affected, rlim, placer_state.blk_loc_registry()); + create_move_outcome = propose_router_swap(blocks_affected, rlim, placer_state.blk_loc_registry(), rng); proposed_action.move_type = e_move_type::UNIFORM; } else { //Generate a new move (perturbation) used to explore the space of possible placements @@ -1457,7 +1464,7 @@ static e_move_result try_swap(const t_annealing_state* state, } /* 1 -> move accepted, 0 -> rejected. */ - move_outcome = assess_swap(delta_c, state->t); + move_outcome = assess_swap(delta_c, state->t, rng); //Updates the manual_move_state members and displays costs to the user to decide whether to ACCEPT/REJECT manual move. #ifndef NO_GRAPHICS @@ -1740,7 +1747,7 @@ static float analyze_setup_slack_cost(const PlacerSetupSlacks* setup_slacks, return 1; } -static e_move_result assess_swap(double delta_c, double t) { +static e_move_result assess_swap(double delta_c, double t, vtr::RngContainer& rng) { /* Returns: 1 -> move accepted, 0 -> rejected. */ VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, "\tTemperature is: %e delta_c is %e\n", t, delta_c); if (delta_c <= 0) { @@ -1753,7 +1760,7 @@ static e_move_result assess_swap(double delta_c, double t) { return REJECTED; } - float fnum = vtr::frand(); + float fnum = rng.frand(); float prob_fac = std::exp(-delta_c / t); if (prob_fac > fnum) { VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, "\t\tMove is accepted(hill climbing)\n"); diff --git a/vpr/src/place/simpleRL_move_generator.cpp b/vpr/src/place/simpleRL_move_generator.cpp index 62a6d933bf7..f0ab253c680 100644 --- a/vpr/src/place/simpleRL_move_generator.cpp +++ b/vpr/src/place/simpleRL_move_generator.cpp @@ -37,9 +37,10 @@ void SimpleRLMoveGenerator::process_outcome(double reward, e_reward_function rew * K-Armed bandit agent implementation * * * * */ -KArmedBanditAgent::KArmedBanditAgent(std::vector available_moves, e_agent_space agent_space) +KArmedBanditAgent::KArmedBanditAgent(std::vector available_moves, e_agent_space agent_space, vtr::RngContainer& rng) : available_moves_(std::move(available_moves)) - , propose_blk_type_(agent_space == e_agent_space::MOVE_BLOCK_TYPE) { + , propose_blk_type_(agent_space == e_agent_space::MOVE_BLOCK_TYPE) + , rng_(rng) { std::vector available_logical_block_types = get_available_logical_blk_types_(); num_available_types_ = available_logical_block_types.size(); @@ -191,8 +192,8 @@ int KArmedBanditAgent::agent_to_phy_blk_type(const int idx) { * E-greedy agent implementation * * * * */ -EpsilonGreedyAgent::EpsilonGreedyAgent(std::vector available_moves, e_agent_space agent_space, float epsilon) - : KArmedBanditAgent(std::move(available_moves), agent_space) { +EpsilonGreedyAgent::EpsilonGreedyAgent(std::vector available_moves, e_agent_space agent_space, float epsilon, vtr::RngContainer& rng) + : KArmedBanditAgent(std::move(available_moves), agent_space, rng) { set_epsilon(epsilon); init_q_scores_(); } @@ -217,10 +218,10 @@ void EpsilonGreedyAgent::init_q_scores_() { } t_propose_action EpsilonGreedyAgent::propose_action() { - if (vtr::frand() < epsilon_) { + if (rng_.frand() < epsilon_) { /* Explore * With probability epsilon, choose randomly amongst all move types */ - float p = vtr::frand(); + float p = rng_.frand(); auto itr = std::lower_bound(cumm_epsilon_action_prob_.begin(), cumm_epsilon_action_prob_.end(), p); auto action_type_q_pos = itr - cumm_epsilon_action_prob_.begin(); //Mark the q_table location that agent used to update its value after processing the move outcome @@ -266,8 +267,8 @@ void EpsilonGreedyAgent::set_epsilon_action_prob() { * Softmax agent implementation * * * * */ -SoftmaxAgent::SoftmaxAgent(std::vector available_moves, e_agent_space agent_space) - : KArmedBanditAgent(std::move(available_moves), agent_space) { +SoftmaxAgent::SoftmaxAgent(std::vector available_moves, e_agent_space agent_space, vtr::RngContainer& rng) + : KArmedBanditAgent(std::move(available_moves), agent_space, rng) { init_q_scores_(); } @@ -304,7 +305,7 @@ void SoftmaxAgent::init_q_scores_() { t_propose_action SoftmaxAgent::propose_action() { set_action_prob_(); - float p = vtr::frand(); + float p = rng_.frand(); auto itr = std::lower_bound(cumm_action_prob_.begin(), cumm_action_prob_.end(), p); auto action_type_q_pos = itr - cumm_action_prob_.begin(); //To take care that the last element in cumm_action_prob_ might be less than 1 by a small value diff --git a/vpr/src/place/simpleRL_move_generator.h b/vpr/src/place/simpleRL_move_generator.h index 1f33684d2f8..9bdddc6c800 100644 --- a/vpr/src/place/simpleRL_move_generator.h +++ b/vpr/src/place/simpleRL_move_generator.h @@ -14,7 +14,7 @@ */ class KArmedBanditAgent { public: - KArmedBanditAgent(std::vector available_moves, e_agent_space agent_space); + KArmedBanditAgent(std::vector available_moves, e_agent_space agent_space, vtr::RngContainer& rng); virtual ~KArmedBanditAgent() = default; /** @@ -96,6 +96,7 @@ class KArmedBanditAgent { /* These ratios are useful for different reward functions * * The vector is calculated by averaging many runs on different circuits */ const vtr::vector time_elapsed_{1.0, 3.6, 5.4, 2.5, 2.1, 0.8, 2.2, 5.4}; + vtr::RngContainer& rng_; FILE* agent_info_file_ = nullptr; @@ -121,7 +122,7 @@ class KArmedBanditAgent { */ class EpsilonGreedyAgent : public KArmedBanditAgent { public: - EpsilonGreedyAgent(std::vector available_moves, e_agent_space agent_space, float epsilon); + EpsilonGreedyAgent(std::vector available_moves, e_agent_space agent_space, float epsilon, vtr::RngContainer& rng); ~EpsilonGreedyAgent() override; t_propose_action propose_action() override; //Returns the type of the next action as well as the block type the agent wishes to perform @@ -160,10 +161,9 @@ class EpsilonGreedyAgent : public KArmedBanditAgent { */ class SoftmaxAgent : public KArmedBanditAgent { public: - SoftmaxAgent(std::vector available_moves, e_agent_space agent_space); + SoftmaxAgent(std::vector available_moves, e_agent_space agent_space, vtr::RngContainer& rng); ~SoftmaxAgent() override; - t_propose_action propose_action() override; //Returns the type of the next action as well as the block type the agent wishes to perform private: @@ -218,6 +218,7 @@ class SimpleRLMoveGenerator : public MoveGenerator { class = typename std::enable_if::value || std::is_same::value>::type> explicit SimpleRLMoveGenerator(PlacerState& placer_state, e_reward_function reward_function, + vtr::RngContainer& rng, std::unique_ptr& agent, float noc_attraction_weight, size_t high_fanout_thresh); @@ -236,25 +237,26 @@ class SimpleRLMoveGenerator : public MoveGenerator { template SimpleRLMoveGenerator::SimpleRLMoveGenerator(PlacerState& placer_state, e_reward_function reward_function, + vtr::RngContainer& rng, std::unique_ptr& agent, float noc_attraction_weight, size_t high_fanout_thresh) - : MoveGenerator(placer_state, reward_function) { + : MoveGenerator(placer_state, reward_function, rng) { if (noc_attraction_weight > 0.0f) { all_moves.resize((int)e_move_type::NUMBER_OF_AUTO_MOVES); } else { all_moves.resize((int)e_move_type::NUMBER_OF_AUTO_MOVES - 1); } - all_moves[e_move_type::UNIFORM] = std::make_unique(placer_state, reward_function); - all_moves[e_move_type::MEDIAN] = std::make_unique(placer_state, reward_function); - all_moves[e_move_type::CENTROID] = std::make_unique(placer_state, reward_function); - all_moves[e_move_type::W_CENTROID] = std::make_unique(placer_state, reward_function); - all_moves[e_move_type::W_MEDIAN] = std::make_unique(placer_state, reward_function); - all_moves[e_move_type::CRIT_UNIFORM] = std::make_unique(placer_state, reward_function); - all_moves[e_move_type::FEASIBLE_REGION] = std::make_unique(placer_state, reward_function); + all_moves[e_move_type::UNIFORM] = std::make_unique(placer_state, reward_function, rng); + all_moves[e_move_type::MEDIAN] = std::make_unique(placer_state, reward_function, rng); + all_moves[e_move_type::CENTROID] = std::make_unique(placer_state, reward_function, rng); + all_moves[e_move_type::W_CENTROID] = std::make_unique(placer_state, reward_function, rng); + all_moves[e_move_type::W_MEDIAN] = std::make_unique(placer_state, reward_function, rng); + all_moves[e_move_type::CRIT_UNIFORM] = std::make_unique(placer_state, reward_function, rng); + all_moves[e_move_type::FEASIBLE_REGION] = std::make_unique(placer_state, reward_function, rng); if (noc_attraction_weight > 0.0f) { - all_moves[e_move_type::NOC_ATTRACTION_CENTROID] = std::make_unique(placer_state, reward_function, + all_moves[e_move_type::NOC_ATTRACTION_CENTROID] = std::make_unique(placer_state, reward_function, rng, noc_attraction_weight, high_fanout_thresh); } diff --git a/vpr/src/place/static_move_generator.cpp b/vpr/src/place/static_move_generator.cpp index e48214f8d6a..6a3de5b4a2a 100644 --- a/vpr/src/place/static_move_generator.cpp +++ b/vpr/src/place/static_move_generator.cpp @@ -14,17 +14,18 @@ StaticMoveGenerator::StaticMoveGenerator(PlacerState& placer_state, e_reward_function reward_function, + vtr::RngContainer& rng, const vtr::vector& move_probs) - : MoveGenerator(placer_state, reward_function) { + : MoveGenerator(placer_state, reward_function, rng) { all_moves.resize((int)e_move_type::NUMBER_OF_AUTO_MOVES); - all_moves[e_move_type::UNIFORM] = std::make_unique(placer_state, reward_function); - all_moves[e_move_type::MEDIAN] = std::make_unique(placer_state, reward_function); - all_moves[e_move_type::CENTROID] = std::make_unique(placer_state, reward_function); - all_moves[e_move_type::W_CENTROID] = std::make_unique(placer_state, reward_function); - all_moves[e_move_type::W_MEDIAN] = std::make_unique(placer_state, reward_function); - all_moves[e_move_type::CRIT_UNIFORM] = std::make_unique(placer_state, reward_function); - all_moves[e_move_type::FEASIBLE_REGION] = std::make_unique(placer_state, reward_function); + all_moves[e_move_type::UNIFORM] = std::make_unique(placer_state, reward_function, rng); + all_moves[e_move_type::MEDIAN] = std::make_unique(placer_state, reward_function, rng); + all_moves[e_move_type::CENTROID] = std::make_unique(placer_state, reward_function, rng); + all_moves[e_move_type::W_CENTROID] = std::make_unique(placer_state, reward_function, rng); + all_moves[e_move_type::W_MEDIAN] = std::make_unique(placer_state, reward_function, rng); + all_moves[e_move_type::CRIT_UNIFORM] = std::make_unique(placer_state, reward_function, rng); + all_moves[e_move_type::FEASIBLE_REGION] = std::make_unique(placer_state, reward_function, rng); initialize_move_prob(move_probs); } @@ -47,7 +48,7 @@ e_create_move StaticMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_ float rlim, const t_placer_opts& placer_opts, const PlacerCriticalities* criticalities) { - float rand_num = vtr::frand() * total_prob; + float rand_num = rng_.frand() * total_prob; for (auto move_type : cumm_move_probs.keys()) { if (rand_num <= cumm_move_probs[move_type]) { diff --git a/vpr/src/place/static_move_generator.h b/vpr/src/place/static_move_generator.h index 997782a6cd3..3f831b236f6 100644 --- a/vpr/src/place/static_move_generator.h +++ b/vpr/src/place/static_move_generator.h @@ -20,6 +20,7 @@ class StaticMoveGenerator : public MoveGenerator { StaticMoveGenerator() = delete; StaticMoveGenerator(PlacerState& placer_state, e_reward_function reward_function, + vtr::RngContainer& rng, const vtr::vector& move_probs); e_create_move propose_move(t_pl_blocks_to_be_moved& blocks_affected, diff --git a/vpr/src/place/uniform_move_generator.cpp b/vpr/src/place/uniform_move_generator.cpp index 9f6e844c34d..6c6e283ba94 100644 --- a/vpr/src/place/uniform_move_generator.cpp +++ b/vpr/src/place/uniform_move_generator.cpp @@ -6,8 +6,9 @@ #include "move_utils.h" UniformMoveGenerator::UniformMoveGenerator(PlacerState& placer_state, - e_reward_function reward_function) - : MoveGenerator(placer_state, reward_function) {} + e_reward_function reward_function, + vtr::RngContainer& rng) + : MoveGenerator(placer_state, reward_function, rng) {} e_create_move UniformMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_affected, t_propose_action& proposed_action, @@ -25,7 +26,8 @@ e_create_move UniformMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks /*highly_crit_block=*/false, /*net_from=*/nullptr, /*pin_from=*/nullptr, - placer_state); + placer_state, + rng_); VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, "Uniform Move Choose Block %d - rlim %f\n", size_t(b_from), rlim); @@ -40,7 +42,7 @@ e_create_move UniformMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks VTR_ASSERT(is_tile_compatible(grid_from_type, cluster_from_type)); t_pl_loc to; - if (!find_to_loc_uniform(cluster_from_type, rlim, from, to, b_from, blk_loc_registry)) { + if (!find_to_loc_uniform(cluster_from_type, rlim, from, to, b_from, blk_loc_registry, rng_)) { return e_create_move::ABORT; } diff --git a/vpr/src/place/uniform_move_generator.h b/vpr/src/place/uniform_move_generator.h index e9fd28686dd..02414c3140e 100644 --- a/vpr/src/place/uniform_move_generator.h +++ b/vpr/src/place/uniform_move_generator.h @@ -12,7 +12,8 @@ class UniformMoveGenerator : public MoveGenerator { public: UniformMoveGenerator() = delete; UniformMoveGenerator(PlacerState& placer_state, - e_reward_function reward_function); + e_reward_function reward_function, + vtr::RngContainer& rng); private: e_create_move propose_move(t_pl_blocks_to_be_moved& blocks_affected, diff --git a/vpr/src/place/weighted_centroid_move_generator.cpp b/vpr/src/place/weighted_centroid_move_generator.cpp index b6c6f7683f8..972bbfca4ec 100644 --- a/vpr/src/place/weighted_centroid_move_generator.cpp +++ b/vpr/src/place/weighted_centroid_move_generator.cpp @@ -7,8 +7,9 @@ #include "move_utils.h" WeightedCentroidMoveGenerator::WeightedCentroidMoveGenerator(PlacerState& placer_state, - e_reward_function reward_function) - : MoveGenerator(placer_state, reward_function) {} + e_reward_function reward_function, + vtr::RngContainer& rng) + : MoveGenerator(placer_state, reward_function, rng) {} e_create_move WeightedCentroidMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_affected, t_propose_action& proposed_action, @@ -28,7 +29,8 @@ e_create_move WeightedCentroidMoveGenerator::propose_move(t_pl_blocks_to_be_move /*highly_crit_block=*/false, /*net_from=*/nullptr, /*pin_from=*/nullptr, - placer_state); + placer_state, + rng_); VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, "Weighted Centroid Move Choose Block %d - rlim %f\n", size_t(b_from), rlim); @@ -54,7 +56,7 @@ e_create_move WeightedCentroidMoveGenerator::propose_move(t_pl_blocks_to_be_move // Centroid location is not necessarily a valid location, and the downstream location expect a valid // layer for "to" location. So if the layer is not valid, we set it to the same layer as from loc. centroid.layer = (centroid.layer < 0) ? from.layer : centroid.layer; - if (!find_to_loc_centroid(cluster_from_type, from, centroid, range_limiters, to, b_from, blk_loc_registry)) { + if (!find_to_loc_centroid(cluster_from_type, from, centroid, range_limiters, to, b_from, blk_loc_registry, rng_)) { return e_create_move::ABORT; } diff --git a/vpr/src/place/weighted_centroid_move_generator.h b/vpr/src/place/weighted_centroid_move_generator.h index 30ed146941c..b7c6a6560ce 100644 --- a/vpr/src/place/weighted_centroid_move_generator.h +++ b/vpr/src/place/weighted_centroid_move_generator.h @@ -16,7 +16,8 @@ class WeightedCentroidMoveGenerator : public MoveGenerator { public: WeightedCentroidMoveGenerator() = delete; WeightedCentroidMoveGenerator(PlacerState& placer_state, - e_reward_function reward_function); + e_reward_function reward_function, + vtr::RngContainer& rng); private: e_create_move propose_move(t_pl_blocks_to_be_moved& blocks_affected, diff --git a/vpr/src/place/weighted_median_move_generator.cpp b/vpr/src/place/weighted_median_move_generator.cpp index bdd6285c4cd..586de977130 100644 --- a/vpr/src/place/weighted_median_move_generator.cpp +++ b/vpr/src/place/weighted_median_move_generator.cpp @@ -11,8 +11,9 @@ #define CRIT_MULT_FOR_W_MEDIAN 10 WeightedMedianMoveGenerator::WeightedMedianMoveGenerator(PlacerState& placer_state, - e_reward_function reward_function) - : MoveGenerator(placer_state, reward_function) {} + e_reward_function reward_function, + vtr::RngContainer& rng) + : MoveGenerator(placer_state, reward_function, rng) {} e_create_move WeightedMedianMoveGenerator::propose_move(t_pl_blocks_to_be_moved& blocks_affected, t_propose_action& proposed_action, @@ -31,7 +32,8 @@ e_create_move WeightedMedianMoveGenerator::propose_move(t_pl_blocks_to_be_moved& /*highly_crit_block=*/false, /*net_from=*/nullptr, /*pin_from=*/nullptr, - placer_state); + placer_state, + rng_); VTR_LOGV_DEBUG(g_vpr_ctx.placement().f_placer_debug, "Weighted Median Move Choose Block %d - rlim %f\n", size_t(b_from), rlim); @@ -139,7 +141,7 @@ e_create_move WeightedMedianMoveGenerator::propose_move(t_pl_blocks_to_be_moved& w_median_point.y = (limit_coords.ymin + limit_coords.ymax) / 2; w_median_point.layer = ((limit_coords.layer_min + limit_coords.layer_max) / 2); - if (!find_to_loc_centroid(cluster_from_type, from, w_median_point, range_limiters, to, b_from, blk_loc_registry)) { + if (!find_to_loc_centroid(cluster_from_type, from, w_median_point, range_limiters, to, b_from, blk_loc_registry, rng_)) { return e_create_move::ABORT; } diff --git a/vpr/src/place/weighted_median_move_generator.h b/vpr/src/place/weighted_median_move_generator.h index 6ba0ccc9544..79f53665382 100644 --- a/vpr/src/place/weighted_median_move_generator.h +++ b/vpr/src/place/weighted_median_move_generator.h @@ -16,7 +16,8 @@ class WeightedMedianMoveGenerator : public MoveGenerator { public: WeightedMedianMoveGenerator() = delete; WeightedMedianMoveGenerator(PlacerState& placer_state, - e_reward_function reward_function); + e_reward_function reward_function, + vtr::RngContainer& rng); private: e_create_move propose_move(t_pl_blocks_to_be_moved& blocks_affected, diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index 27e6f58a79c..c203aa001f7 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -212,7 +212,7 @@ static void compute_wire_connections( const t_wire_type_sizes* wire_type_sizes_y, e_directionality directionality, t_sb_connection_map* sb_conns, - vtr::RandState& rand_state, + vtr::RngContainer& rng, t_wireconn_scratchpad* scratchpad); /* ... sb_conn represents the 'coordinates' of the desired switch block connections */ @@ -235,7 +235,7 @@ static void compute_wireconn_connections( const t_switchblock_inf* sb, t_wireconn_inf* wireconn_ptr, t_sb_connection_map* sb_conns, - vtr::RandState& rand_state, + vtr::RngContainer& rng, t_wireconn_scratchpad* scratchpad); static int evaluate_num_conns_formula(t_wireconn_scratchpad* scratchpad, std::string num_conns_formula, int from_wire_count, int to_wire_count); @@ -269,7 +269,7 @@ static void get_switchpoint_wires( const t_wire_type_sizes* wire_type_sizes, bool is_dest, SwitchPointOrder order, - vtr::RandState& rand_state, + vtr::RngContainer& rng, std::vector* output_wires, std::vector* scratch_wires); @@ -404,7 +404,7 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail const std::vector& switchblocks, t_chan_width* nodes_per_chan, e_directionality directionality, - vtr::RandState& rand_state) { + vtr::RngContainer& rng) { /* Holds temporary memory for parsing. */ t_wireconn_scratchpad scratchpad; @@ -452,7 +452,7 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail compute_wire_connections(x_coord, y_coord, layer_coord, from_side, to_side, chan_details_x, chan_details_y, &sb, grid, &wire_type_sizes_x, &wire_type_sizes_y, directionality, sb_conns, - rand_state, &scratchpad); + rng, &scratchpad); } } } @@ -670,7 +670,7 @@ static void get_switchpoint_wires( const t_wire_type_sizes* wire_type_sizes, bool is_dest, SwitchPointOrder switchpoint_order, - vtr::RandState& rand_state, + vtr::RngContainer& rng, std::vector* output_wires, std::vector* scratch_wires) { std::vector& all_collected_wire_switchpoints = *output_wires; @@ -748,14 +748,28 @@ static void get_switchpoint_wires( if (switchpoint_order == SwitchPointOrder::SHUFFLED) { //We new re-order the switchpoints to try to make adjacent switchpoints have different values - vtr::shuffle(all_collected_wire_switchpoints.begin(), all_collected_wire_switchpoints.end(), rand_state); + vtr::shuffle(all_collected_wire_switchpoints.begin(), all_collected_wire_switchpoints.end(), rng); } else { VTR_ASSERT(switchpoint_order == SwitchPointOrder::FIXED); //Already ordered so same switchpoints are adjacent by above collection loop } } -static void compute_wire_connections(int x_coord, int y_coord, int layer_coord, enum e_side from_side, enum e_side to_side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, t_switchblock_inf* sb, const DeviceGrid& grid, const t_wire_type_sizes* wire_type_sizes_x, const t_wire_type_sizes* wire_type_sizes_y, e_directionality directionality, t_sb_connection_map* sb_conns, vtr::RandState& rand_state, t_wireconn_scratchpad* scratchpad) { +static void compute_wire_connections(int x_coord, + int y_coord, + int layer_coord, + enum e_side from_side, + enum e_side to_side, + const t_chan_details& chan_details_x, + const t_chan_details& chan_details_y, + t_switchblock_inf* sb, + const DeviceGrid& grid, + const t_wire_type_sizes* wire_type_sizes_x, + const t_wire_type_sizes* wire_type_sizes_y, + e_directionality directionality, + t_sb_connection_map* sb_conns, + vtr::RngContainer& rng, + t_wireconn_scratchpad* scratchpad) { int from_x, from_y, from_layer; /* index into source channel */ int to_x, to_y, to_layer; /* index into destination channel */ t_rr_type from_chan_type, to_chan_type; /* the type of channel - i.e. CHANX or CHANY */ @@ -808,10 +822,8 @@ static void compute_wire_connections(int x_coord, int y_coord, int layer_coord, * current wireconn */ compute_wireconn_connections(grid, directionality, from_chan_details, to_chan_details, sb_conn, from_x, from_y, from_layer, to_x, to_y, to_layer, from_chan_type, to_chan_type, wire_type_sizes_from, - wire_type_sizes_to, sb, wireconn_ptr, sb_conns, rand_state, scratchpad); + wire_type_sizes_to, sb, wireconn_ptr, sb_conns, rng, scratchpad); } - - return; } /* computes the destination wire segments that a source wire segment at the coordinate 'sb_conn' (in @@ -837,7 +849,7 @@ static void compute_wireconn_connections( const t_switchblock_inf* sb, t_wireconn_inf* wireconn_ptr, t_sb_connection_map* sb_conns, - vtr::RandState& rand_state, + vtr::RngContainer& rng, t_wireconn_scratchpad* scratchpad) { constexpr bool verbose = false; @@ -848,13 +860,13 @@ static void compute_wireconn_connections( /* vectors that will contain indices of the wires belonging to the source/dest wire types/points */ get_switchpoint_wires(grid, from_chan_details[from_x][from_y].data(), from_chan_type, from_x, from_y, from_side, - wireconn_ptr->from_switchpoint_set, wire_type_sizes_from, false, wireconn_ptr->from_switchpoint_order, rand_state, + wireconn_ptr->from_switchpoint_set, wire_type_sizes_from, false, wireconn_ptr->from_switchpoint_order, rng, &scratchpad->potential_src_wires, &scratchpad->scratch_wires); get_switchpoint_wires(grid, to_chan_details[to_x][to_y].data(), to_chan_type, to_x, to_y, to_side, wireconn_ptr->to_switchpoint_set, wire_type_sizes_to, true, - wireconn_ptr->to_switchpoint_order, rand_state, &scratchpad->potential_dest_wires, + wireconn_ptr->to_switchpoint_order, rng, &scratchpad->potential_dest_wires, &scratchpad->scratch_wires); const auto& potential_src_wires = scratchpad->potential_src_wires; @@ -895,7 +907,7 @@ static void compute_wireconn_connections( VTR_LOGV(verbose, " DST_WIRES: %s\n", dst_str.c_str()); #endif - if (potential_src_wires.size() == 0 || potential_dest_wires.size() == 0) { + if (potential_src_wires.empty() || potential_dest_wires.empty()) { //Can't make any connections between empty sets return; } diff --git a/vpr/src/route/build_switchblocks.h b/vpr/src/route/build_switchblocks.h index c0db665b956..d9f283dfd4f 100644 --- a/vpr/src/route/build_switchblocks.h +++ b/vpr/src/route/build_switchblocks.h @@ -116,7 +116,14 @@ typedef std::unordered_map, * * @return creates a map between switch blocks (key) and their corresponding edges (value). */ -t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, const DeviceGrid& grid, const std::vector& inter_cluster_rr, const std::vector& switchblocks, t_chan_width* nodes_per_chan, enum e_directionality directionality, vtr::RandState& rand_state); +t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_details& chan_details_x, + const t_chan_details& chan_details_y, + const DeviceGrid& grid, + const std::vector& inter_cluster_rr, + const std::vector& switchblocks, + t_chan_width* nodes_per_chan, + enum e_directionality directionality, + vtr::RngContainer& rng); /** * @brief deallocates switch block connections sparse array diff --git a/vpr/src/route/cb_metrics.cpp b/vpr/src/route/cb_metrics.cpp index 7dbe0260e42..b10ddc7409b 100644 --- a/vpr/src/route/cb_metrics.cpp +++ b/vpr/src/route/cb_metrics.cpp @@ -105,14 +105,27 @@ static float get_lemieux_cost_func(const int exponent, const bool both_sides, co /* this annealer is used to adjust a desired wire or pin metric while keeping the other type of metric * relatively constant */ -static bool annealer(const e_metric metric, const int nodes_per_chan, const t_physical_tile_type_ptr block_type, const e_pin_type pin_type, const int Fc, const int num_pin_type_pins, const float target_metric, const float target_metric_tolerance, int***** pin_to_track_connections, Conn_Block_Metrics* cb_metrics); +static bool annealer(const e_metric metric, const int nodes_per_chan, const t_physical_tile_type_ptr block_type, const e_pin_type pin_type, const int Fc, const int num_pin_type_pins, const float target_metric, const float target_metric_tolerance, int***** pin_to_track_connections, Conn_Block_Metrics* cb_metrics, vtr::RngContainer& rng); /* updates temperature based on current temperature and the annealer's outer loop iteration */ static double update_temp(const double temp); /* determines whether to accept or reject a proposed move based on the resulting delta of the cost and current temperature */ -static bool accept_move(const double del_cost, const double temp); +static bool accept_move(const double del_cost, const double temp, vtr::RngContainer& rng); /* this function simply moves a switch from one track to another track (with an empty slot). The switch stays on the * same pin as before. */ -static double try_move(const e_metric metric, const int nodes_per_chan, const float initial_orthogonal_metric, const float orthogonal_metric_tolerance, const t_physical_tile_type_ptr block_type, const e_pin_type pin_type, const int Fc, const int num_pin_type_pins, const double cost, const double temp, const float target_metric, int***** pin_to_track_connections, Conn_Block_Metrics* cb_metrics); +static double try_move(const e_metric metric, + const int nodes_per_chan, + const float initial_orthogonal_metric, + const float orthogonal_metric_tolerance, + const t_physical_tile_type_ptr block_type, + const e_pin_type pin_type, + const int Fc, + const int num_pin_type_pins, + const double cost, + const double temp, + const float target_metric, + int***** pin_to_track_connections, + Conn_Block_Metrics* cb_metrics, + vtr::RngContainer& rng); static void print_switch_histogram(const int nodes_per_chan, const Conn_Block_Metrics* cb_metrics); @@ -157,9 +170,11 @@ void adjust_cb_metric(const e_metric metric, const float target, const float tar get_conn_block_metrics(block_type, pin_to_track_connections, num_segments, segment_inf, pin_type, Fc_array, chan_width_inf, &cb_metrics); + + vtr::RngContainer rng(0); /* now run the annealer to adjust the desired metric towards the target value */ bool success = annealer(metric, nodes_per_chan, block_type, pin_type, Fc, num_pin_type_pins, target, - target_tolerance, pin_to_track_connections, &cb_metrics); + target_tolerance, pin_to_track_connections, &cb_metrics, rng); if (!success) { VTR_LOG("Failed to adjust specified connection block metric\n"); } @@ -658,7 +673,20 @@ static void find_tracks_unconnected_to_pin(const std::set* pin_tracks, cons /* this function simply moves a switch from one track to another track (with an empty slot). The switch stays on the * same pin as before. */ -static double try_move(const e_metric metric, const int nodes_per_chan, const float initial_orthogonal_metric, const float orthogonal_metric_tolerance, const t_physical_tile_type_ptr block_type, const e_pin_type pin_type, const int Fc, const int num_pin_type_pins, const double cost, const double temp, const float target_metric, int***** pin_to_track_connections, Conn_Block_Metrics* cb_metrics) { +static double try_move(const e_metric metric, + const int nodes_per_chan, + const float initial_orthogonal_metric, + const float orthogonal_metric_tolerance, + const t_physical_tile_type_ptr block_type, + const e_pin_type pin_type, + const int Fc, + const int num_pin_type_pins, + const double cost, + const double temp, + const float target_metric, + int***** pin_to_track_connections, + Conn_Block_Metrics* cb_metrics, + vtr::RngContainer& rng) { double new_cost = 0; float new_orthogonal_metric = 0; float new_metric = 0; @@ -666,7 +694,7 @@ static double try_move(const e_metric metric, const int nodes_per_chan, const fl /* will determine whether we should revert the attempted move at the end of this function */ bool revert = false; /* indicates whether or not we allow a track to be fully disconnected from all the pins of the connection block - * in the processs of trying a move (to allow this, preserve_tracks is set to false) */ + * in the process of trying a move (to allow this, preserve_tracks is set to false) */ const bool preserve_tracks = true; t_vec_vec_set* pin_to_tracks = &cb_metrics->pin_to_tracks; @@ -694,8 +722,8 @@ static double try_move(const e_metric metric, const int nodes_per_chan, const fl set_of_tracks.clear(); /* choose a random side, random pin, and a random switch */ - int rand_side = vtr::irand(3); - int rand_pin_index = vtr::irand(cb_metrics->pin_locations.at(rand_side).size() - 1); + int rand_side = rng.irand(3); + int rand_pin_index = rng.irand(cb_metrics->pin_locations.at(rand_side).size() - 1); int rand_pin = cb_metrics->pin_locations.at(rand_side).at(rand_pin_index); std::set* tracks_connected_to_pin = &pin_to_tracks->at(rand_side).at(rand_pin_index); @@ -724,12 +752,12 @@ static double try_move(const e_metric metric, const int nodes_per_chan, const fl new_cost = cost; } else { /* now choose a random track from the returned set of qualifying tracks */ - int old_track = vtr::irand(set_of_tracks.size() - 1); + int old_track = rng.irand(set_of_tracks.size() - 1); old_track = set_of_tracks.at(old_track); /* next, get a new track connection i.e. one that is not already connected to our randomly chosen pin */ find_tracks_unconnected_to_pin(tracks_connected_to_pin, &track_to_pins->at(rand_side), &set_of_tracks); - int new_track = vtr::irand(set_of_tracks.size() - 1); + int new_track = rng.irand(set_of_tracks.size() - 1); new_track = set_of_tracks.at(new_track); /* move the rand_pin's connection from the old track to the new track and see what the new cost is */ @@ -781,7 +809,7 @@ static double try_move(const e_metric metric, const int nodes_per_chan, const fl } new_cost = fabs(target_metric - new_metric); delta_cost = new_cost - cost; - if (!accept_move(delta_cost, temp)) { + if (!accept_move(delta_cost, temp, rng)) { revert = true; } } else { @@ -843,7 +871,7 @@ static double try_move(const e_metric metric, const int nodes_per_chan, const fl /* this annealer is used to adjust a desired wire or pin metric while keeping the other type of metric * relatively constant */ -static bool annealer(const e_metric metric, const int nodes_per_chan, const t_physical_tile_type_ptr block_type, const e_pin_type pin_type, const int Fc, const int num_pin_type_pins, const float target_metric, const float target_metric_tolerance, int***** pin_to_track_connections, Conn_Block_Metrics* cb_metrics) { +static bool annealer(const e_metric metric, const int nodes_per_chan, const t_physical_tile_type_ptr block_type, const e_pin_type pin_type, const int Fc, const int num_pin_type_pins, const float target_metric, const float target_metric_tolerance, int***** pin_to_track_connections, Conn_Block_Metrics* cb_metrics, vtr::RngContainer& rng) { bool success = false; double temp = INITIAL_TEMP; @@ -890,7 +918,8 @@ static bool annealer(const e_metric metric, const int nodes_per_chan, const t_ph for (int i_inner = 0; i_inner < MAX_INNER_ITERATIONS; i_inner++) { double new_cost = 0; new_cost = try_move(metric, nodes_per_chan, initial_orthogonal_metric, orthogonal_metric_tolerance, - block_type, pin_type, Fc, num_pin_type_pins, cost, temp, target_metric, pin_to_track_connections, cb_metrics); + block_type, pin_type, Fc, num_pin_type_pins, cost, temp, target_metric, + pin_to_track_connections, cb_metrics, rng); /* update the cost after trying the move */ if (new_cost != cost) { @@ -937,7 +966,7 @@ static double update_temp(const double temp) { } /* determines whether to accept or reject a proposed move based on the resulting delta of the cost and current temperature */ -static bool accept_move(const double del_cost, const double temp) { +static bool accept_move(const double del_cost, const double temp, vtr::RngContainer& rng) { bool accept = false; if (del_cost < 0) { @@ -946,7 +975,7 @@ static bool accept_move(const double del_cost, const double temp) { } else { /* determine probabilistically whether or not to accept */ double probability = pow(2.718, -(del_cost / temp)); - double rand_value = (double)vtr::frand(); + double rand_value = (double)rng.frand(); if (rand_value < probability) { accept = true; } else { diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index dc678d20913..855707bd58a 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -1322,7 +1322,7 @@ static void build_rr_graph(const t_graph_type graph_type, //used when creating custom switchblocks. This ensures that build_rr_graph() //is deterministic -- always producing the same RR graph. constexpr unsigned SWITCHPOINT_RNG_SEED = 1; - vtr::RandState switchpoint_rand_state = SWITCHPOINT_RNG_SEED; + vtr::RngContainer switchpoint_rng(SWITCHPOINT_RNG_SEED); const auto inter_cluster_prog_rr = device_ctx.inter_cluster_prog_routing_resources; if (is_global_graph) { @@ -1332,7 +1332,7 @@ static void build_rr_graph(const t_graph_type graph_type, sb_conn_map = alloc_and_load_switchblock_permutations(chan_details_x, chan_details_y, grid, inter_cluster_prog_rr, switchblocks, &nodes_per_chan, directionality, - switchpoint_rand_state); + switchpoint_rng); } else { switch_block_conn = alloc_and_load_switch_block_conn(&nodes_per_chan, sb_type, Fs); } @@ -1344,7 +1344,7 @@ static void build_rr_graph(const t_graph_type graph_type, grid, inter_cluster_prog_rr, switchblocks, &nodes_per_chan, directionality, - switchpoint_rand_state); + switchpoint_rng); } else { /* it looks like we get unbalanced muxing from this switch block code with Fs > 3 */ VTR_ASSERT(Fs == 3);