From 2dfb1a53d029ca88b56b75d38da4d1e37236f441 Mon Sep 17 00:00:00 2001 From: Knute Lingaard Date: Fri, 6 Oct 2023 16:39:38 -0500 Subject: [PATCH] Created the common Allocators class and hooked it up --- CMakeLists.txt | 14 +-- core/CPUFactory.cpp | 5 + core/CPUFactory.hpp | 3 + core/Execute.cpp | 5 + core/Execute.hpp | 1 + core/Inst.cpp | 29 ++++- core/Inst.hpp | 19 +-- core/LSU.cpp | 30 +++-- core/LSU.hpp | 29 +++-- core/MavisUnit.cpp | 8 +- core/MemoryAccessInfo.hpp | 19 ++- sim/OlympiaAllocators.hpp | 61 +++++++++ sim/OlympiaSim.cpp | 12 +- sim/OlympiaSim.hpp | 12 +- test/core/dispatch/Dispatch_test.cpp | 6 + test/core/rename/Rename_test.cpp | 180 ++++++++++++++------------- 16 files changed, 281 insertions(+), 152 deletions(-) create mode 100644 sim/OlympiaAllocators.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ce21aee3..6f7edd1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,25 +55,13 @@ set (SIM_BASE ${PROJECT_SOURCE_DIR}) set (OLYMPIA_VERSION "v0.1.0") add_definitions(-DOLYMPIA_VERSION=\"${OLYMPIA_VERSION}\") -if (CMAKE_BUILD_TYPE MATCHES "^[Rr]elease") - set(SPARTA_BUILD_TYPE "release") -elseif (CMAKE_BUILD_TYPE MATCHES "^[Ff]ast[Dd]ebug") - set(SPARTA_BUILD_TYPE "release") -elseif (CMAKE_BUILD_TYPE MATCHES "^[Dd]ebug") - set(SPARTA_BUILD_TYPE "debug") -elseif (CMAKE_BUILD_TYPE MATCHES "^[Pp]rofile") - set(SPARTA_BUILD_TYPE "release") -else() - message (FATAL_ERROR "Please provide a CMAKE_BUILD_TYPE: -DCMAKE_BUILD_TYPE=Release|FastDebug|Debug|Profile") -endif() - # Profile build flags set(CMAKE_CXX_FLAGS_PROFILE "-O3 -pg -g -ftime-trace") set(CMAKE_CXX_FLAGS_FASTDEBUG "-O3 -g") set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") # Include directories -include_directories (core mss) +include_directories (core mss sim) include_directories (SYSTEM mavis) include_directories (SYSTEM stf_lib) diff --git a/core/CPUFactory.cpp b/core/CPUFactory.cpp index 6a2b682d..012e695b 100644 --- a/core/CPUFactory.cpp +++ b/core/CPUFactory.cpp @@ -123,3 +123,8 @@ auto olympia::CPUFactory::getResourceNames() const -> const std::vector{ auto getResourceNames() const -> const std::vector&; private: + //! Destroy internal components + void deleteSubtree(sparta::ResourceTreeNode*) override; + /** * @brief Implementation : Build the device tree by instantiating resource nodes */ diff --git a/core/Execute.cpp b/core/Execute.cpp index a4cb7b39..872c359b 100644 --- a/core/Execute.cpp +++ b/core/Execute.cpp @@ -39,4 +39,9 @@ namespace olympia } } } + + void ExecuteFactory::deleteSubtree(sparta::ResourceTreeNode*) { + exe_pipe_tns_.clear(); + } + } diff --git a/core/Execute.hpp b/core/Execute.hpp index 30e8b18d..a6e4876f 100644 --- a/core/Execute.hpp +++ b/core/Execute.hpp @@ -49,6 +49,7 @@ namespace olympia { public: void onConfiguring(sparta::ResourceTreeNode* node) override; + void deleteSubtree(sparta::ResourceTreeNode*) override; ~ExecuteFactory() = default; private: diff --git a/core/Inst.cpp b/core/Inst.cpp index 4192b152..96968e03 100644 --- a/core/Inst.cpp +++ b/core/Inst.cpp @@ -4,7 +4,30 @@ namespace olympia { - // This pipeline supports around 250 outstanding instructions. - InstAllocator inst_allocator (3000, 2500); - InstArchInfoAllocator inst_arch_info_allocator(3000, 2500); + + /*! + * \brief Construct an Instruction + * \param opcode_info Mavis Opcode information + * \param inst_arch_info Pointer to the static data of instruction + * \param clk Core clock + * + * Called by Mavis when an opcode is decoded to a particular + * instruction. + */ + Inst::Inst(const mavis::OpcodeInfo::PtrType& opcode_info, + const InstArchInfo::PtrType & inst_arch_info, + const sparta::Clock * clk) : + opcode_info_ (opcode_info), + inst_arch_info_ (inst_arch_info), + is_store_(opcode_info->isInstType(mavis::OpcodeInfo::InstructionTypes::STORE)), + is_transfer_(miscutils::isOneOf(inst_arch_info_->getTargetPipe(), + InstArchInfo::TargetPipe::I2F, + InstArchInfo::TargetPipe::F2I)), + + status_state_(Status::FETCHED) + { + sparta_assert(inst_arch_info_ != nullptr, + "Mavis decoded the instruction, but Olympia has no uarch data for it: " + << getDisasm() << " " << std::hex << " opc: 0x" << getOpCode()); + } } diff --git a/core/Inst.hpp b/core/Inst.hpp index 60cdf545..81560b26 100644 --- a/core/Inst.hpp +++ b/core/Inst.hpp @@ -97,20 +97,7 @@ namespace olympia */ Inst(const mavis::OpcodeInfo::PtrType& opcode_info, const InstArchInfo::PtrType & inst_arch_info, - const sparta::Clock * clk) : - opcode_info_ (opcode_info), - inst_arch_info_ (inst_arch_info), - is_store_(opcode_info->isInstType(mavis::OpcodeInfo::InstructionTypes::STORE)), - is_transfer_(miscutils::isOneOf(inst_arch_info_->getTargetPipe(), - InstArchInfo::TargetPipe::I2F, - InstArchInfo::TargetPipe::F2I)), - - status_state_(Status::FETCHED) - { - sparta_assert(inst_arch_info_ != nullptr, - "Mavis decoded the instruction, but Olympia has no uarch data for it: " - << getDisasm() << " " << std::hex << " opc: 0x" << getOpCode()); - } + const sparta::Clock * clk); // This is needed by Mavis as an optimization. Try NOT to // implement it and let the compiler do it for us for speed. @@ -311,8 +298,4 @@ namespace olympia // Instruction allocators using InstAllocator = sparta::SpartaSharedPointerAllocator; using InstArchInfoAllocator = sparta::SpartaSharedPointerAllocator; - - extern InstAllocator inst_allocator; - extern InstArchInfoAllocator inst_arch_info_allocator; - } diff --git a/core/LSU.cpp b/core/LSU.cpp index d54e50ef..6aff42ed 100644 --- a/core/LSU.cpp +++ b/core/LSU.cpp @@ -2,6 +2,8 @@ #include "CoreUtils.hpp" #include "LSU.hpp" +#include "OlympiaAllocators.hpp" + namespace olympia { const char LSU::name[] = "lsu"; @@ -12,10 +14,12 @@ namespace olympia LSU::LSU(sparta::TreeNode *node, const LSUParameterSet *p) : sparta::Unit(node), - memory_access_allocator(50, 30), // 50 and 30 are arbitrary numbers here. It can be tuned to an exact value. - load_store_info_allocator(50, 30), ldst_inst_queue_("lsu_inst_queue", p->ldst_inst_queue_size, getClock()), - ldst_inst_queue_size_(p->ldst_inst_queue_size) + ldst_inst_queue_size_(p->ldst_inst_queue_size), + load_store_info_allocator_(sparta::notNull(OlympiaAllocators::getOlympiaAllocators(node))-> + load_store_info_allocator), + memory_access_allocator_(sparta::notNull(OlympiaAllocators::getOlympiaAllocators(node))-> + memory_access_allocator) { // Pipeline collection config ldst_pipeline_.enableCollection(node); @@ -79,6 +83,16 @@ namespace olympia } + LSU::~LSU() { + DLOG(getContainer()->getLocation() + << ": " + << load_store_info_allocator_.getNumAllocated() + << " LoadStoreInstInfo objects allocated/created"); + DLOG(getContainer()->getLocation() + << ": " + << memory_access_allocator_.getNumAllocated() + << " MemoryAccessInfo objects allocated/created"); + } //////////////////////////////////////////////////////////////////////////////// // Callbacks @@ -141,12 +155,14 @@ namespace olympia if (all_ready) { // Create load/store memory access info - MemoryAccessInfoPtr mem_info_ptr = sparta::allocate_sparta_shared_pointer(memory_access_allocator, - inst_ptr); + MemoryAccessInfoPtr mem_info_ptr = + sparta::allocate_sparta_shared_pointer(memory_access_allocator_, + inst_ptr); // Create load/store instruction issue info - LoadStoreInstInfoPtr inst_info_ptr = sparta::allocate_sparta_shared_pointer(load_store_info_allocator, - mem_info_ptr); + LoadStoreInstInfoPtr inst_info_ptr = + sparta::allocate_sparta_shared_pointer(load_store_info_allocator_, + mem_info_ptr); lsu_insts_dispatched_++; // Append to instruction issue queue diff --git a/core/LSU.hpp b/core/LSU.hpp index da34d28e..81a94fa5 100644 --- a/core/LSU.hpp +++ b/core/LSU.hpp @@ -58,16 +58,8 @@ namespace olympia */ LSU(sparta::TreeNode* node, const LSUParameterSet* p); - ~LSU() { - DLOG(getContainer()->getLocation() - << ": " - << load_store_info_allocator.getNumAllocated() - << " LoadStoreInstInfo objects allocated/created"); - DLOG(getContainer()->getLocation() - << ": " - << memory_access_allocator.getNumAllocated() - << " MemoryAccessInfo objects allocated/created"); - } + //! Destroy the LSU + ~LSU(); //! name of this resource. static const char name[]; @@ -91,9 +83,6 @@ namespace olympia NUM_STAGES }; - // allocator for this object type - sparta::SpartaSharedPointerAllocator memory_access_allocator; - // Forward declaration of the Pair Definition class is must as we are friending it. class LoadStoreInstInfoPairDef; // Keep record of instruction issue information @@ -186,7 +175,7 @@ namespace olympia }; // class LoadStoreInstInfo - sparta::SpartaSharedPointerAllocator load_store_info_allocator; + using LoadStoreInstInfoAllocator = sparta::SpartaSharedPointerAllocator; /*! * \class LoadStoreInstInfoPairDef @@ -277,11 +266,16 @@ namespace olympia sparta::collection::Collectable cache_busy_collectable_{ getContainer(), "dcache_busy", &cache_busy_}; + // LSInstInfo allocator + LoadStoreInstInfoAllocator & load_store_info_allocator_; + + // allocator for this object type + MemoryAccessInfoAllocator & memory_access_allocator_; + // NOTE: // Depending on which kind of cache (e.g. blocking vs. non-blocking) is being used // This single slot could potentially be extended to a cache pending miss queue - // Load/Store Pipeline using LoadStorePipeline = sparta::Pipeline; LoadStorePipeline ldst_pipeline_ @@ -396,6 +390,11 @@ namespace olympia "Number of BIU reqs", sparta::Counter::COUNT_NORMAL }; + + // When simulation is ending (error or not), this function + // will be called + void onStartingTeardown_() override {} + friend class LSUTester; }; diff --git a/core/MavisUnit.cpp b/core/MavisUnit.cpp index d3b824ce..44ee0d6e 100644 --- a/core/MavisUnit.cpp +++ b/core/MavisUnit.cpp @@ -8,6 +8,8 @@ #include "mavis/Mavis.h" #include "MavisUnit.hpp" +#include "OlympiaAllocators.hpp" + namespace olympia { @@ -67,8 +69,10 @@ namespace olympia mavis_facade_ (new MavisType(getISAFiles(n, p->isa_file_path, pseudo_file_path_), getUArchFiles(n, p, p->uarch_file_path, pseudo_file_path_), mavis_uid_list_, getUArchAnnotationOverrides(p), - InstPtrAllocator (inst_allocator), - InstPtrAllocator(inst_arch_info_allocator))) + InstPtrAllocator + (sparta::notNull(OlympiaAllocators::getOlympiaAllocators(n))->inst_allocator), + InstPtrAllocator + (sparta::notNull(OlympiaAllocators::getOlympiaAllocators(n))->inst_arch_info_allocator))) {} /** diff --git a/core/MemoryAccessInfo.hpp b/core/MemoryAccessInfo.hpp index 3aac0f25..28203d4d 100644 --- a/core/MemoryAccessInfo.hpp +++ b/core/MemoryAccessInfo.hpp @@ -1,7 +1,15 @@ +// -*- C++ -*- + #pragma once -namespace olympia { +#include "sparta/resources/Scoreboard.hpp" +#include "sparta/pairs/SpartaKeyPairs.hpp" +#include "sparta/utils/SpartaSharedPointer.hpp" +#include "sparta/utils/SpartaSharedPointerAllocator.hpp" +#include "Inst.hpp" + +namespace olympia { class MemoryAccessInfoPairDef; @@ -99,9 +107,9 @@ namespace olympia { }; /*! -* \class MemoryAccessInfoPairDef -* \brief Pair Definition class of the Memory Access Information that flows through the example/CoreModel -*/ + * \class MemoryAccessInfoPairDef + * \brief Pair Definition class of the Memory Access Information that flows through the example/CoreModel + */ // This is the definition of the PairDefinition class of MemoryAccessInfo. // This PairDefinition class could be named anything but it needs to inherit @@ -121,5 +129,6 @@ namespace olympia { SPARTA_FLATTEN(&MemoryAccessInfo::getInstPtr)) }; - using MemoryAccessInfoPtr = sparta::SpartaSharedPointer; + using MemoryAccessInfoPtr = sparta::SpartaSharedPointer; + using MemoryAccessInfoAllocator = sparta::SpartaSharedPointerAllocator; }; diff --git a/sim/OlympiaAllocators.hpp b/sim/OlympiaAllocators.hpp new file mode 100644 index 00000000..971df954 --- /dev/null +++ b/sim/OlympiaAllocators.hpp @@ -0,0 +1,61 @@ +// -*- C++ -*- + +#pragma once + +/*! + * \file OlympiaAllocators.hpp + * \brief Defines a general TreeNode that contains all allocators used + * in simulation + */ + +#include "sparta/simulation/TreeNode.hpp" + +#include "Inst.hpp" +#include "MemoryAccessInfo.hpp" +#include "LSU.hpp" // A little heavyweight to include for now... + +namespace olympia +{ + /*! + * \class OlympiaAllocators + * \brief A TreeNode that is actually a functional resource + * containing memory allocators + */ + class OlympiaAllocators : public sparta::TreeNode + { + public: + static constexpr char name[] = "olympia_allocators"; + + OlympiaAllocators(sparta::TreeNode *node) : + sparta::TreeNode(node, name, "Allocators used in simulation") + {} + + static OlympiaAllocators * getOlympiaAllocators(sparta::TreeNode *node) + { + OlympiaAllocators * allocators = nullptr; + if(node) + { + if(node->hasChild(OlympiaAllocators::name)) { + // If this class is converted to a resource, use this line + //allocators = node->getChild(OlympiaAllocators::name)->getResourceAs(); + allocators = node->getChildAs(OlympiaAllocators::name); + } + else { + return getOlympiaAllocators(node->getParent()); + } + } + return allocators; + } + + // Allocators used in simulation. These values can be + // parameterized in the future by converting this class into a + // full-blown sparta::Resource and adding a sparta::ParameterSet + InstAllocator inst_allocator {3000, 2500}; + InstArchInfoAllocator inst_arch_info_allocator{3000, 2500}; + + // For LSU/MSS + LSU::LoadStoreInstInfoAllocator load_store_info_allocator{100, 80}; + MemoryAccessInfoAllocator memory_access_allocator {100, 80}; + + }; +} diff --git a/sim/OlympiaSim.cpp b/sim/OlympiaSim.cpp index d0b28600..622c75c3 100644 --- a/sim/OlympiaSim.cpp +++ b/sim/OlympiaSim.cpp @@ -23,6 +23,8 @@ #include "Preloader.hpp" #include "SimulationConfiguration.hpp" +#include "OlympiaAllocators.hpp" + #include "BIU.hpp" #include "MSS.hpp" @@ -63,6 +65,9 @@ void OlympiaSim::buildTree_() // Set the cpu topology that will be built cpu_factory->setTopology(cpu_topology_, num_cores_); + // Cerate the common Allocators + allocators_tn_.reset(new olympia::OlympiaAllocators(getRoot())); + // Create a single CPU sparta::ResourceTreeNode* cpu_tn = new sparta::ResourceTreeNode(getRoot(), "cpu", @@ -70,7 +75,12 @@ void OlympiaSim::buildTree_() sparta::TreeNode::GROUP_IDX_NONE, "CPU Node", cpu_factory); - to_delete_.emplace_back(cpu_tn); + + // You _can_ use sparta::app::Simulation's to_delete_ vector and + // have the simulation class delete it for you. However, by doing + // that, the Allocators object _will be destroyed_ before the CPU + // TN resulting in a seg fault at the end of simulation. + cpu_tn_to_delete_.reset(cpu_tn); cpu_tn->addExtensionFactory("simulation_configuration", [=](){return new olympia::SimulationConfiguration;}); diff --git a/sim/OlympiaSim.hpp b/sim/OlympiaSim.hpp index c3ada7e2..b1acae31 100644 --- a/sim/OlympiaSim.hpp +++ b/sim/OlympiaSim.hpp @@ -4,7 +4,10 @@ #include "sparta/app/Simulation.hpp" -namespace olympia{ class CPUFactory; } +namespace olympia { + class CPUFactory; + class OlympiaAllocators; +} /*! * \brief OlympiaSim which builds the model and configures it @@ -40,6 +43,13 @@ class OlympiaSim : public sparta::app::Simulation ////////////////////////////////////////////////////////////////////// // Setup + // Allocators. Last thing to delete + std::unique_ptr allocators_tn_; + + // The CPU TN. This must be declared _AFTER_ the allocators so it + // is destroyed first. + std::unique_ptr cpu_tn_to_delete_; + //! Build the tree with tree nodes, but does not instantiate the //! unit yet void buildTree_() override; diff --git a/test/core/dispatch/Dispatch_test.cpp b/test/core/dispatch/Dispatch_test.cpp index e63ace2c..2de04704 100644 --- a/test/core/dispatch/Dispatch_test.cpp +++ b/test/core/dispatch/Dispatch_test.cpp @@ -2,6 +2,7 @@ #include "Dispatch.hpp" #include "MavisUnit.hpp" #include "CoreUtils.hpp" +#include "OlympiaAllocators.hpp" #include "test/core/common/SourceUnit.hpp" #include "test/core/common/SinkUnit.hpp" @@ -69,6 +70,9 @@ class DispatchSim : public sparta::app::Simulation { auto rtn = getRoot(); + // Cerate the common Allocators + allocators_tn_.reset(new olympia::OlympiaAllocators(rtn)); + sparta::ResourceTreeNode * disp = nullptr; // Create a Mavis Unit @@ -193,6 +197,8 @@ class DispatchSim : public sparta::app::Simulation sparta::bind(root_node->getChildAs("dispatch.ports.in_lsu_credits"), root_node->getChildAs("lsu.ports.out_sink_credits")); } + // Allocators. Last thing to delete + std::unique_ptr allocators_tn_; olympia::DispatchFactory dispatch_fact; olympia::MavisFactoy mavis_fact; diff --git a/test/core/rename/Rename_test.cpp b/test/core/rename/Rename_test.cpp index e8461bff..063ff6f2 100644 --- a/test/core/rename/Rename_test.cpp +++ b/test/core/rename/Rename_test.cpp @@ -6,6 +6,7 @@ #include "ExecutePipe.hpp" #include "LSU.hpp" #include "sim/OlympiaSim.hpp" +#include "OlympiaAllocators.hpp" #include "test/core/common/SourceUnit.hpp" #include "test/core/common/SinkUnit.hpp" @@ -39,74 +40,74 @@ olympia::InstAllocator inst_allocator(2000, 1000); class olympia::RenameTester { - public: - void test_clearing_rename_structures(olympia::Rename & rename){ - // after all instructions have retired, we should have: - // num_rename_registers - 32 registers = freelist size - // because we initialize the first 32 registers - if (rename.reference_counter_[0].size() == 34){ - EXPECT_TRUE(rename.freelist_[0].size() == 2); - // in the case of only two free PRFs, they should NOT be equal to each other - EXPECT_TRUE(rename.freelist_[0].front() != rename.freelist_[0].back()); - } - else{ - EXPECT_TRUE(rename.freelist_[0].size() == 96); - } - // we're only expecting one reference - EXPECT_TRUE(rename.reference_counter_[0][1] == 1); - EXPECT_TRUE(rename.reference_counter_[0][2] == 1); - +public: + void test_clearing_rename_structures(olympia::Rename & rename){ + // after all instructions have retired, we should have: + // num_rename_registers - 32 registers = freelist size + // because we initialize the first 32 registers + if (rename.reference_counter_[0].size() == 34){ + EXPECT_TRUE(rename.freelist_[0].size() == 2); + // in the case of only two free PRFs, they should NOT be equal to each other + EXPECT_TRUE(rename.freelist_[0].front() != rename.freelist_[0].back()); } - void test_one_instruction(olympia::Rename & rename){ - // process only one instruction, check that freelist and map_tables are allocated correctly - if (rename.reference_counter_[0].size() == 34){ - EXPECT_TRUE(rename.freelist_[0].size() == 1); - } - else{ - EXPECT_TRUE(rename.freelist_[0].size() == 95); - } - // map table entry is valid, as it's been allocated - - // reference counters should now be 2 because the first instruction is: - // ADD x3 x1 x2 and both x1 -> prf1 and x2 -> prf2 - EXPECT_TRUE(rename.reference_counter_[0][1] == 2); - EXPECT_TRUE(rename.reference_counter_[0][2] == 2); + else{ + EXPECT_TRUE(rename.freelist_[0].size() == 96); + } + // we're only expecting one reference + EXPECT_TRUE(rename.reference_counter_[0][1] == 1); + EXPECT_TRUE(rename.reference_counter_[0][2] == 1); + + } + void test_one_instruction(olympia::Rename & rename){ + // process only one instruction, check that freelist and map_tables are allocated correctly + if (rename.reference_counter_[0].size() == 34){ + EXPECT_TRUE(rename.freelist_[0].size() == 1); } - void test_multiple_instructions(olympia::Rename & rename){ - // first two instructions are RAW - // so the second instruction should increase reference count - EXPECT_TRUE(rename.reference_counter_[0][2] == 2); + else{ + EXPECT_TRUE(rename.freelist_[0].size() == 95); } - void test_startup_rename_structures(olympia::Rename & rename){ - // before starting, we should have: - // num_rename_registers - 32 registers = freelist size - // because we initialize the first 32 registers - if (rename.reference_counter_[0].size() == 34){ - EXPECT_TRUE(rename.freelist_[0].size() == 2); - } - else{ - EXPECT_TRUE(rename.freelist_[0].size() == 96); - } - // we're only expecting a value of 1 for registers x0 -> x31 because we initialize them - EXPECT_TRUE(rename.reference_counter_[0][1] == 1); - EXPECT_TRUE(rename.reference_counter_[0][2] == 1); - EXPECT_TRUE(rename.reference_counter_[0][30] == 1); - EXPECT_TRUE(rename.reference_counter_[0][31] == 1); - // - EXPECT_TRUE(rename.reference_counter_[0][33] == 0); - EXPECT_TRUE(rename.reference_counter_[0][34] == 0); + // map table entry is valid, as it's been allocated + // reference counters should now be 2 because the first instruction is: + // ADD x3 x1 x2 and both x1 -> prf1 and x2 -> prf2 + EXPECT_TRUE(rename.reference_counter_[0][1] == 2); + EXPECT_TRUE(rename.reference_counter_[0][2] == 2); + } + void test_multiple_instructions(olympia::Rename & rename){ + // first two instructions are RAW + // so the second instruction should increase reference count + EXPECT_TRUE(rename.reference_counter_[0][2] == 2); + } + void test_startup_rename_structures(olympia::Rename & rename){ + // before starting, we should have: + // num_rename_registers - 32 registers = freelist size + // because we initialize the first 32 registers + if (rename.reference_counter_[0].size() == 34){ + EXPECT_TRUE(rename.freelist_[0].size() == 2); } - void test_float(olympia::Rename & rename){ - // ensure the correct register file is used - EXPECT_TRUE(rename.freelist_[1].size() == 94); + else{ EXPECT_TRUE(rename.freelist_[0].size() == 96); } + // we're only expecting a value of 1 for registers x0 -> x31 because we initialize them + EXPECT_TRUE(rename.reference_counter_[0][1] == 1); + EXPECT_TRUE(rename.reference_counter_[0][2] == 1); + EXPECT_TRUE(rename.reference_counter_[0][30] == 1); + EXPECT_TRUE(rename.reference_counter_[0][31] == 1); + // + EXPECT_TRUE(rename.reference_counter_[0][33] == 0); + EXPECT_TRUE(rename.reference_counter_[0][34] == 0); + + } + void test_float(olympia::Rename & rename){ + // ensure the correct register file is used + EXPECT_TRUE(rename.freelist_[1].size() == 94); + EXPECT_TRUE(rename.freelist_[0].size() == 96); + } }; class olympia::ExecutePipeTester { - public: +public: void test_dependent_integer_first_instruction(olympia::ExecutePipe & executepipe){ // testing RAW dependency for ExecutePipe // only alu0 should have an issued instruction @@ -123,7 +124,7 @@ class olympia::ExecutePipeTester class olympia::LSUTester { - public: +public: void test_dependent_lsu_instruction(olympia::LSU & lsu){ // testing RAW dependency for LSU // we have an ADD instruction before we destination register 3 @@ -144,10 +145,10 @@ class RenameSim : public sparta::app::Simulation public: RenameSim(sparta::Scheduler * sched, - const std::string & mavis_isa_files, - const std::string & mavis_uarch_files, - const std::string & output_file, - const std::string & input_file) : + const std::string & mavis_isa_files, + const std::string & mavis_uarch_files, + const std::string & output_file, + const std::string & input_file) : sparta::app::Simulation("RenameSim", sched), input_file_(input_file), test_tap_(getRoot(), "info", output_file) @@ -171,6 +172,9 @@ class RenameSim : public sparta::app::Simulation { auto rtn = getRoot(); + // Cerate the common Allocators + allocators_tn_.reset(new olympia::OlympiaAllocators(rtn)); + sparta::ResourceTreeNode * disp = nullptr; // Create a Mavis Unit @@ -183,18 +187,18 @@ class RenameSim : public sparta::app::Simulation // Create a Source Unit tns_to_delete_.emplace_back(new sparta::ResourceTreeNode(rtn, - core_test::SourceUnit::name, - sparta::TreeNode::GROUP_NAME_NONE, - sparta::TreeNode::GROUP_IDX_NONE, - "Source Unit", - &source_fact)); + core_test::SourceUnit::name, + sparta::TreeNode::GROUP_NAME_NONE, + sparta::TreeNode::GROUP_IDX_NONE, + "Source Unit", + &source_fact)); sparta::ResourceTreeNode * decode_unit = nullptr; tns_to_delete_.emplace_back(decode_unit = new sparta::ResourceTreeNode(rtn, - olympia::Decode::name, - sparta::TreeNode::GROUP_NAME_NONE, - sparta::TreeNode::GROUP_IDX_NONE, - "Decode Unit", - &source_fact)); + olympia::Decode::name, + sparta::TreeNode::GROUP_NAME_NONE, + sparta::TreeNode::GROUP_IDX_NONE, + "Decode Unit", + &source_fact)); decode_unit->getParameterSet()->getParameter("input_file")->setValueFromString(input_file_); // Create Dispatch tns_to_delete_.emplace_back(disp = new sparta::ResourceTreeNode(rtn, @@ -203,14 +207,14 @@ class RenameSim : public sparta::app::Simulation sparta::TreeNode::GROUP_IDX_NONE, "Dispatch Unit", &dispatch_fact)); - + // Create Rename sparta::ResourceTreeNode * rename_unit = new sparta::ResourceTreeNode(rtn, - olympia::Rename::name, - sparta::TreeNode::GROUP_NAME_NONE, - sparta::TreeNode::GROUP_IDX_NONE, - "Test Rename", - &rename_fact); + olympia::Rename::name, + sparta::TreeNode::GROUP_NAME_NONE, + sparta::TreeNode::GROUP_IDX_NONE, + "Test Rename", + &rename_fact); tns_to_delete_.emplace_back(rename_unit); // Create SinkUnit that represents the ROB @@ -287,7 +291,7 @@ class RenameSim : public sparta::app::Simulation sparta::bind(root_node->getChildAs("dispatch.ports.in_reorder_buffer_credits"), root_node->getChildAs("rob.ports.out_sink_credits")); - + // Bind the Rename ports sparta::bind(root_node->getChildAs("rename.ports.out_dispatch_queue_write"), root_node->getChildAs("dispatch.ports.in_dispatch_queue_write")); @@ -311,7 +315,7 @@ class RenameSim : public sparta::app::Simulation sparta::bind(root_node->getChildAs("dispatch.ports.out_"+unit_name+"_write"), root_node->getChildAs(unit_name + ".ports.in_sink_retire_inst")); sparta::bind(root_node->getChildAs("rename.ports.in_rename_retire_ack"), - root_node->getChildAs(unit_name+".ports.out_rob_retire_ack")); + root_node->getChildAs(unit_name+".ports.out_rob_retire_ack")); } // Bind the "LSU" SinkUnit to Dispatch @@ -324,9 +328,11 @@ class RenameSim : public sparta::app::Simulation sparta::bind(root_node->getChildAs("rename.ports.in_rename_retire_ack"), root_node->getChildAs("lsu.ports.out_rob_retire_ack")); } + // Allocators. Last thing to delete + std::unique_ptr allocators_tn_; sparta::ResourceFactory decode_fact; + olympia::Decode::DecodeParameterSet> decode_fact; olympia::DispatchFactory dispatch_fact; olympia::RenameFactory rename_fact; olympia::MavisFactoy mavis_fact; @@ -383,11 +389,11 @@ void runTest(int argc, char **argv) uint32_t num_cores = 1; bool show_factories = false; OlympiaSim sim("simple", - scheduler, - num_cores, // cores - input_file, - ilimit, - show_factories); + scheduler, + num_cores, // cores + input_file, + ilimit, + show_factories); if(input_file == "raw_integer.json"){ cls.populateSimulation(&sim); @@ -398,7 +404,7 @@ void runTest(int argc, char **argv) olympia::ExecutePipeTester executepipe_tester; cls.runSimulator(&sim, 7); executepipe_tester.test_dependent_integer_first_instruction(*my_executepipe); - executepipe_tester.test_dependent_integer_second_instruction(*my_executepipe1); + executepipe_tester.test_dependent_integer_second_instruction(*my_executepipe1); } else if(input_file == "i2f.json"){ cls.populateSimulation(&sim);