diff --git a/.gitignore b/.gitignore index d1b62d9a25..e539b476d3 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,5 @@ CMakeFiles/ **/capstone-config-version.cmake **/capstone-config.cmake + +**/simeng-fileio-test.txt \ No newline at end of file diff --git a/.jenkins/build_arm22.sh b/.jenkins/build_arm22.sh index 99ccee0130..0c5452aac5 100644 --- a/.jenkins/build_arm22.sh +++ b/.jenkins/build_arm22.sh @@ -15,3 +15,7 @@ module load tools/cmake build armclang armclang++ test run + +buildRelease armclang armclang++ +test +run diff --git a/.jenkins/build_gcc10.sh b/.jenkins/build_gcc10.sh index 20ec670795..2886bc4136 100644 --- a/.jenkins/build_gcc10.sh +++ b/.jenkins/build_gcc10.sh @@ -15,3 +15,7 @@ module load tools/cmake build gcc g++ test run + +buildRelease gcc g++ +test +run diff --git a/.jenkins/build_gcc7.sh b/.jenkins/build_gcc7.sh index 512c928706..fcbcf35b3a 100644 --- a/.jenkins/build_gcc7.sh +++ b/.jenkins/build_gcc7.sh @@ -15,3 +15,7 @@ module load tools/cmake build gcc g++ test run + +buildRelease gcc g++ +test +run diff --git a/.jenkins/build_gcc8.sh b/.jenkins/build_gcc8.sh index 729b182895..d12c4b6a25 100644 --- a/.jenkins/build_gcc8.sh +++ b/.jenkins/build_gcc8.sh @@ -15,3 +15,7 @@ module load tools/cmake build gcc g++ test run + +buildRelease gcc g++ +test +run diff --git a/.jenkins/build_gcc9.sh b/.jenkins/build_gcc9.sh index 46422cc872..0597204658 100644 --- a/.jenkins/build_gcc9.sh +++ b/.jenkins/build_gcc9.sh @@ -15,3 +15,7 @@ module load tools/cmake build gcc g++ test run + +buildRelease gcc g++ +test +run diff --git a/.jenkins/build_test_run.sh b/.jenkins/build_test_run.sh index eee31052f6..4b4f237b3c 100644 --- a/.jenkins/build_test_run.sh +++ b/.jenkins/build_test_run.sh @@ -36,6 +36,16 @@ build () { cmake --build build --target install } +# Build common function +buildRelease () { + cd "$SIMENG_TOP" || exit + rm -rf build/* install/* + + cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$SIMENG_INSTALL" -DSIMENG_ENABLE_TESTS=ON -DSIMENG_USE_EXTERNAL_LLVM=ON -DLLVM_DIR=/home/br-simeng/llvm14.0.5/install-gcc7/lib/cmake/llvm/ -DCMAKE_C_COMPILER=$1 -DCMAKE_CXX_COMPILER=$2 + cmake --build build -j + cmake --build build --target install +} + # Run tests test () { cd "$SIMENG_BUILD" || exit @@ -52,16 +62,16 @@ run () { echo "Simulation without configuration file argument:" cat run echo "" - compare_outputs "$(grep "retired:" run | rev | cut -d ' ' -f1 | rev)" "3145731" "retired instructions" - compare_outputs "$(grep "cycles:" run | rev | cut -d ' ' -f1 | rev)" "3145732" "simulated cycles" + compare_outputs "$(grep "retired:" run | rev | cut -d ' ' -f1 | rev)" "6708" "retired instructions" + compare_outputs "$(grep "cycles:" run | rev | cut -d ' ' -f1 | rev)" "7955" "simulated cycles" echo "" ./bin/simeng "$SIMENG_TOP"/configs/tx2.yaml > run echo "Simulation with configuration file argument:" cat run echo "" - compare_outputs "$(grep "retired:" run | rev | cut -d ' ' -f1 | rev)" "3145732" "retired instructions" - compare_outputs "$(grep "cycles:" run | rev | cut -d ' ' -f1 | rev)" "1048588" "simulated cycles" + compare_outputs "$(grep "retired:" run | rev | cut -d ' ' -f1 | rev)" "6724" "retired instructions" + compare_outputs "$(grep "cycles:" run | rev | cut -d ' ' -f1 | rev)" "8677" "simulated cycles" echo "" } diff --git a/CMakeLists.txt b/CMakeLists.txt index 88c0789dc5..542049f2f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,8 +71,8 @@ set(CMAKE_MACOSX_RPATH 1) # Enable PIC for libraries set(CMAKE_POSITION_INDEPENDENT_CODE ON) -# Enable additional compiler warnings for all targets -add_compile_options(-Wall) +# Create variable to enable additional compiler warnings for SimEng targets only +set(SIMENG_COMPILE_OPTIONS -Wall -pedantic -Werror) #-Wextra # Disable RTTI for all targets add_compile_options($<$:-fno-rtti>) @@ -183,6 +183,8 @@ if(SIMENG_ENABLE_TESTS) set(LLVM_ENABLE_BINDINGS OFF) set(LLVM_INSTALL_UTILS OFF) + set(LLVM_ENABLE_WARNINGS OFF) + # XXX all LLVM specific cmake variables must be set BEFORE FetchContent_MakeAvailable otherwise they have no effect FetchContent_MakeAvailable_SubDir_Args(llvm llvm-14.0.5.src EXCLUDE_FROM_ALL) # make sure we get the headers too diff --git a/SimEngDefaultProgram b/SimEngDefaultProgram new file mode 100755 index 0000000000..3e43fbe564 Binary files /dev/null and b/SimEngDefaultProgram differ diff --git a/docs/sphinx/developer/components/coreinstance.rst b/docs/sphinx/developer/components/coreinstance.rst index 02f69a369a..8b9e99a449 100644 --- a/docs/sphinx/developer/components/coreinstance.rst +++ b/docs/sphinx/developer/components/coreinstance.rst @@ -9,7 +9,7 @@ Process the config file Either the passed configuration file path, or default configuration string, is used to generate the model configuration class. All subsequent parameterised instantiations of simulation objects utilise this configuration class. Create the image process - From the passed workload path, or default set of instructions, a process image is created. A region of host memory is populated with workload data (e.g. instructions), a region for the HEAP, and an initial stack frame. References to it are then passed between various simulation objects to serve as the underlying process memory space. + From the passed workload path, or default binary, a process image is created. A region of host memory is populated with workload data (e.g. instructions), a region for the HEAP, and an initial stack frame. References to it are then passed between various simulation objects to serve as the underlying process memory space. Construct on-chip cache interfaces Based on the supplied configuration options, the on-chip cache interfaces are constructed. These interfaces sit on top of a reference to the process memory space constructed prior. Currently, only L1 instruction and data caches are supported and the interfaces are defined under the :ref:`L1-Data-Memory ` and :ref:`L1-Instruction-Memory ` config options. diff --git a/docs/sphinx/user/running_simeng.rst b/docs/sphinx/user/running_simeng.rst index 0413cfbe66..92a9682032 100644 --- a/docs/sphinx/user/running_simeng.rst +++ b/docs/sphinx/user/running_simeng.rst @@ -7,7 +7,7 @@ SimEng uses a configuration file and a program binary to produce a cycle-accurat /bin/simeng -If no arguments are passed to SimEng, default options are used. The default configuration file is tuned to a ThunderX2 processor. The default program binary is defined in ``SimEng/src/include/simeng/CoreInstance.hh`` under the ``hex[]`` array which contains a set of raw instructions in a hexadecimal format. +If no arguments are passed to SimEng, default options are used. The default configuration file is tuned to a ThunderX2 processor. The default program is a binary compiled to AArch64 found at ``SimEng/SimEngDefaultProgram``. This prints a welcome message to the console. Whilst a configuration file can be specified without a program (will use default program), a specified program must be accompanied by a configuration file. diff --git a/src/include/simeng/CoreInstance.hh b/src/include/simeng/CoreInstance.hh index 53e7f28d4e..2dc064fa50 100644 --- a/src/include/simeng/CoreInstance.hh +++ b/src/include/simeng/CoreInstance.hh @@ -21,19 +21,6 @@ #include "simeng/pipeline/A64FXPortAllocator.hh" #include "simeng/pipeline/BalancedPortAllocator.hh" -// Program used when no executable is provided; counts down from -// 1024*1024, with an independent `orr` at the start of each branch. -static uint32_t hex_[] = { - 0x320C03E0, // orr w0, wzr, #1048576 - 0x320003E1, // orr w0, wzr, #1 - 0x71000400, // subs w0, w0, #1 - 0x54FFFFC1, // b.ne -8 - // .exit: - 0xD2800000, // mov x0, #0 - 0xD2800BC8, // mov x8, #94 - 0xD4000001, // svc #0 -}; - namespace simeng { /** A class to create a SimEng core instance from a supplied config. */ @@ -46,7 +33,7 @@ class CoreInstance { /** CoreInstance with source code assembled by LLVM and a model configuration. */ - CoreInstance(char* assembledSource, size_t sourceSize, + CoreInstance(uint8_t* assembledSource, size_t sourceSize, ryml::ConstNodeRef config = config::SimInfo::getConfig()); ~CoreInstance(); @@ -75,10 +62,10 @@ class CoreInstance { std::shared_ptr getProcessImage() const; /** Getter for the size of the created process image. */ - const uint64_t getProcessImageSize() const; + uint64_t getProcessImageSize() const; /* Getter for heap start. */ - const uint64_t getHeapStart() const; + uint64_t getHeapStart() const; private: /** Generate the appropriate simulation objects as parameterised by the @@ -111,7 +98,7 @@ class CoreInstance { simeng::kernel::Linux kernel_; /** Reference to source assembled by LLVM. */ - char* source_ = nullptr; + uint8_t* source_ = nullptr; /** Size of the source code assembled by LLVM. */ size_t sourceSize_ = 0; diff --git a/src/include/simeng/RegisterValue.hh b/src/include/simeng/RegisterValue.hh index e31f748a4c..4faadb301d 100644 --- a/src/include/simeng/RegisterValue.hh +++ b/src/include/simeng/RegisterValue.hh @@ -54,7 +54,7 @@ class RegisterValue { */ RegisterValue(const char* ptr, uint16_t bytes, uint16_t capacity) : bytes(capacity) { - assert(capacity >= bytes && "Capacity is less then requested bytes"); + assert(capacity >= bytes && "Capacity is less than requested bytes"); char* dest; if (isLocal()) { dest = this->value; diff --git a/src/include/simeng/arch/Architecture.hh b/src/include/simeng/arch/Architecture.hh index 12e95687c2..70782c079c 100644 --- a/src/include/simeng/arch/Architecture.hh +++ b/src/include/simeng/arch/Architecture.hh @@ -52,7 +52,7 @@ class Architecture { * Writes into the supplied macro-op vector, and returns the number of bytes * consumed to produce it; a value of 0 indicates too few bytes were present * for a valid decoding. */ - virtual uint8_t predecode(const void* ptr, uint16_t bytesAvailable, + virtual uint8_t predecode(const uint8_t* ptr, uint16_t bytesAvailable, uint64_t instructionAddress, MacroOp& output) const = 0; diff --git a/src/include/simeng/arch/aarch64/ArchInfo.hh b/src/include/simeng/arch/aarch64/ArchInfo.hh index 6f1da3402f..bbd764c757 100644 --- a/src/include/simeng/arch/aarch64/ArchInfo.hh +++ b/src/include/simeng/arch/aarch64/ArchInfo.hh @@ -37,9 +37,9 @@ class ArchInfo : public simeng::arch::ArchInfo { uint16_t predCount = regConfig["Predicate-Count"].as(); uint16_t condCount = regConfig["Conditional-Count"].as(); uint16_t matCount = regConfig["Matrix-Count"].as(); - // Matrix-Count multiplied by (SVL/8) as internal representation of - // ZA is a block of row-vector-registers. Therefore we need to - // convert physical counts from whole-ZA to rows-in-ZA. + // Matrix-Count multiplied by (SVL/8) as internal representation of ZA is a + // block of row-vector-registers. Therefore, we need to convert physical + // counts from whole-ZA to rows-in-ZA. matCount *= zaSize_; physRegStruct_ = {{8, gpCount}, {256, fpCount}, diff --git a/src/include/simeng/arch/aarch64/Architecture.hh b/src/include/simeng/arch/aarch64/Architecture.hh index 196af33ee7..8d4939c991 100644 --- a/src/include/simeng/arch/aarch64/Architecture.hh +++ b/src/include/simeng/arch/aarch64/Architecture.hh @@ -25,7 +25,7 @@ class Architecture : public arch::Architecture { /** Pre-decode instruction memory into a macro-op of `Instruction` * instances. Returns the number of bytes consumed to produce it (always 4), * and writes into the supplied macro-op vector. */ - uint8_t predecode(const void* ptr, uint16_t bytesAvailable, + uint8_t predecode(const uint8_t* ptr, uint16_t bytesAvailable, uint64_t instructionAddress, MacroOp& output) const override; diff --git a/src/include/simeng/arch/aarch64/helpers/float.hh b/src/include/simeng/arch/aarch64/helpers/float.hh index 2b3652d451..454f50070c 100644 --- a/src/include/simeng/arch/aarch64/helpers/float.hh +++ b/src/include/simeng/arch/aarch64/helpers/float.hh @@ -157,6 +157,12 @@ RegisterValue scvtf_FixedPoint( * Returns single value of type D. */ template D fcvtzu_integer(srcValContainer& sourceValues) { + // Ensure types so that we know behaviour of inaccurate type conversions + static_assert((std::is_same() || std::is_same()) && + "N is not a valid type which should be float or double"); + static_assert((std::is_same() || std::is_same()) && + "D is not a valid type which should be int32_t or int64_t"); + N input = sourceValues[0].get(); D result = static_cast(0); @@ -165,7 +171,18 @@ D fcvtzu_integer(srcValContainer& sourceValues) { if (std::isinf(input)) { // Account for Infinity result = std::numeric_limits::max(); - } else if (input > std::numeric_limits::max()) { + } else if (static_cast(input) >= + static_cast(std::numeric_limits::max())) { + // Cast to double to ensure no precision errors. Float can't store uint32 + // or uint64 max values accurately as not enough bits available. This + // causes unwanted comparison behaviour + // + // max() will be either 4294967295 or 18446744073709551615 + // Casting to float results in the following (incorrect) values 4294967296 + // (+1) or 18446744073709551616 (+1) + // + // Casting to double results in no erroneous conversion. + // Account for the source value being larger than the // destination register can support result = std::numeric_limits::max(); diff --git a/src/include/simeng/arch/aarch64/helpers/neon.hh b/src/include/simeng/arch/aarch64/helpers/neon.hh index c2d8f19dcb..0fcf04f03f 100644 --- a/src/include/simeng/arch/aarch64/helpers/neon.hh +++ b/src/include/simeng/arch/aarch64/helpers/neon.hh @@ -146,7 +146,7 @@ RegisterValue vecCountPerByte(srcValContainer& sourceValues) { const uint8_t* n = sourceValues[0].getAsVector(); T out[16 / sizeof(T)] = {0}; for (int i = 0; i < I; i++) { - for (int j = 0; j < (sizeof(T) * 8); j++) { + for (size_t j = 0; j < (sizeof(T) * 8); j++) { // Move queried bit to LSB and extract via an AND operator out[i] += ((n[i] >> j) & 1); } @@ -187,10 +187,10 @@ RegisterValue vecExtVecs_index( const uint64_t index = static_cast(metadata.operands[3].imm); T out[16 / sizeof(T)] = {0}; - for (int i = index; i < I; i++) { + for (uint64_t i = index; i < I; i++) { out[i - index] = n[i]; } - for (int i = 0; i < index; i++) { + for (uint64_t i = 0; i < index; i++) { out[I - index + i] = m[i]; } return {out, 256}; @@ -816,27 +816,27 @@ RegisterValue vecTbl( assert(I == 8 || I == 16); // Vm contains the indices to fetch from table - const int8_t* Vm = + const uint8_t* Vm = sourceValues[metadata.operandCount - 2] - .getAsVector(); // final operand is vecMovi_imm + .getAsVector(); // final operand is vecMovi_imm // All sourceValues except the first and last are the vector registers to // construct the table from const uint8_t n_table_regs = metadata.operandCount - 2; // Create table from vectors. All table sourceValues must be of 16b format. - int tableSize = 16 * n_table_regs; - uint8_t table[tableSize]; - for (int i = 0; i < n_table_regs; i++) { - const int8_t* currentVector = sourceValues[i].getAsVector(); - for (int j = 0; j < 16; j++) { + const uint16_t tableSize = 16 * n_table_regs; + std::vector table(tableSize, 0); + for (uint8_t i = 0; i < n_table_regs; i++) { + const uint8_t* currentVector = sourceValues[i].getAsVector(); + for (uint8_t j = 0; j < 16; j++) { table[16 * i + j] = currentVector[j]; } } - int8_t out[16 / sizeof(int8_t)] = {0}; + uint8_t out[16 / sizeof(uint8_t)] = {0}; for (int i = 0; i < I; i++) { - unsigned int index = Vm[i]; + uint8_t index = Vm[i]; // If an index is out of range for the table, the result for that lookup // is 0 diff --git a/src/include/simeng/arch/aarch64/helpers/sve.hh b/src/include/simeng/arch/aarch64/helpers/sve.hh index 7f46ca10aa..076a2f29c1 100644 --- a/src/include/simeng/arch/aarch64/helpers/sve.hh +++ b/src/include/simeng/arch/aarch64/helpers/sve.hh @@ -508,8 +508,8 @@ RegisterValue sveFcvtPredicated(srcValContainer& sourceValues, // Stores size of largest type out of D and N int lts = std::max(sizeof(D), sizeof(N)); - bool sourceLarger = (sizeof(D) < sizeof(N)) ? true : false; - bool sameDandN = (sizeof(D) == sizeof(N)) ? true : false; + bool sourceLarger = (sizeof(D) < sizeof(N)); + bool sameDandN = (sizeof(D) == sizeof(N)); const uint16_t partition_num = VL_bits / (lts * 8); D out[256 / sizeof(D)] = {0}; @@ -543,14 +543,19 @@ RegisterValue sveFcvtPredicated(srcValContainer& sourceValues, template RegisterValue sveFcvtzsPredicated(srcValContainer& sourceValues, const uint16_t VL_bits) { + static_assert((std::is_same() || std::is_same()) && + "N is not a valid type which should be float or double"); + static_assert((std::is_same() || std::is_same()) && + "D is not a valid type which should be int32_t or int64_t"); + const D* d = sourceValues[0].getAsVector(); const uint64_t* p = sourceValues[1].getAsVector(); const N* n = sourceValues[2].getAsVector(); // Stores size of largest type out of D and N int lts = std::max(sizeof(D), sizeof(N)); - bool sameType = (sizeof(D) == sizeof(N)) ? true : false; - bool sourceLarger = (sizeof(D) < sizeof(N)) ? true : false; + bool sameType = (sizeof(D) == sizeof(N)); + bool sourceLarger = (sizeof(D) < sizeof(N)); const uint16_t partition_num = VL_bits / (lts * 8); D out[256 / sizeof(D)] = {0}; @@ -561,7 +566,21 @@ RegisterValue sveFcvtzsPredicated(srcValContainer& sourceValues, int indexN = ((!sourceLarger) & (!sameType)) ? (2 * i) : i; if (p[i / (64 / lts)] & shifted_active) { - if (n[indexN] > std::numeric_limits::max()) + if (static_cast(n[indexN]) >= + static_cast(std::numeric_limits::max())) + // Cast to double to reduce precision errors. Float can't store int32 + // or int64 max values accurately as not enough bits available. This + // causes unwanted comparison behaviour. Double also can't accurately + // represent int64.MaxValue. Non-strict comparison used to capture this + // case + // + // max() will be either 2147483647 or 9223372036854775807 + // Casting to float results in the following (incorrect) values + // 2147483648 (+1) or 9223372036854775808 (+1) + // + // Casting to double results in 2147483647 (+0) or incorrect + // 9223372036854775808(+1) + out[indexOut] = std::numeric_limits::max(); else if (n[indexN] < std::numeric_limits::lowest()) out[indexOut] = std::numeric_limits::lowest(); diff --git a/src/include/simeng/arch/riscv/ArchInfo.hh b/src/include/simeng/arch/riscv/ArchInfo.hh index 039d8e6ac5..2d3ea0e238 100644 --- a/src/include/simeng/arch/riscv/ArchInfo.hh +++ b/src/include/simeng/arch/riscv/ArchInfo.hh @@ -25,7 +25,7 @@ const uint8_t addressAlignMask = 0x3; const uint8_t addressAlignMaskCompressed = 0x1; const uint8_t minInstWidthBytes = 4; const uint8_t minInstWidthBytesCompressed = 2; -}; // namespace constantsPool +} // namespace constantsPool /** A class to hold and generate riscv specific architecture configuration * options. */ diff --git a/src/include/simeng/arch/riscv/Architecture.hh b/src/include/simeng/arch/riscv/Architecture.hh index 322928347a..b156832e18 100644 --- a/src/include/simeng/arch/riscv/Architecture.hh +++ b/src/include/simeng/arch/riscv/Architecture.hh @@ -24,7 +24,7 @@ class Architecture : public arch::Architecture { /** Pre-decode instruction memory into a macro-op of `Instruction` * instances. Returns the number of bytes consumed to produce it (0 if * failure), and writes into the supplied macro-op vector. */ - uint8_t predecode(const void* ptr, uint16_t bytesAvailable, + uint8_t predecode(const uint8_t* ptr, uint16_t bytesAvailable, uint64_t instructionAddress, MacroOp& output) const override; diff --git a/src/include/simeng/config/ExpectationNode.hh b/src/include/simeng/config/ExpectationNode.hh index 6b89e62c61..187d3ed37a 100644 --- a/src/include/simeng/config/ExpectationNode.hh +++ b/src/include/simeng/config/ExpectationNode.hh @@ -235,7 +235,7 @@ class ExpectationNode { } definedSet_ = true; - for (const T s : set) { + for (const T& s : set) { DataTypeVariant dtv = s; expectedSet_.push_back(dtv); } @@ -311,6 +311,11 @@ class ExpectationNode { } return {true, "Success"}; } + default: + std::cerr << "[SimEng:validateConfigNode] Unexpected ExpectedType" + << std::endl; + + exit(-1); } } } @@ -460,7 +465,8 @@ class ExpectationNode { } } if (!foundInSet) { - // Construct a human readable output denoted expected set failure + // Construct a human-readable output explaining failure to match the + // expected value set retStr << nodeVal << " not in set {"; for (size_t i = 0; i < expectedSet_.size(); i++) { retStr << getByType(expectedSet_[i]); @@ -475,7 +481,8 @@ class ExpectationNode { // Check for value between bounds if (getByType(expectedBounds_.first) > nodeVal || getByType(expectedBounds_.second) < nodeVal) { - // Construct a human readable output denoted expected bounds failure + // Construct a human-readable output explaining failure to be within + // expected bounds retStr << nodeVal << " not in the bounds {" << getByType(expectedBounds_.first) << " to " << getByType(expectedBounds_.second) << "}"; @@ -542,7 +549,9 @@ class ExpectationNode { /** The value bounds the associated config option is expected to lie between. */ - std::pair expectedBounds_; + // TODO needs initialisation in case validation called before setting. Unsure + // whether this is a good solution + std::pair expectedBounds_ = {false, false}; /** The instances of ExpectationNodes held within this node. Considered to be * the children of this node. */ diff --git a/src/include/simeng/config/SimInfo.hh b/src/include/simeng/config/SimInfo.hh index 333014f168..75ee342709 100644 --- a/src/include/simeng/config/SimInfo.hh +++ b/src/include/simeng/config/SimInfo.hh @@ -104,9 +104,7 @@ class SimInfo { /** A getter function to retrieve whether or not the special files * directories should be generated. */ - static const bool getGenSpecFiles() { - return getInstance()->genSpecialFiles_; - } + static bool getGenSpecFiles() { return getInstance()->genSpecialFiles_; } /** A utility function to rebuild/construct member variables/classes. For use * if the configuration used changes during simulation (e.g. during the diff --git a/src/include/simeng/config/yaml/ryml.hh b/src/include/simeng/config/yaml/ryml.hh index f7b672b862..bed8f4620b 100644 --- a/src/include/simeng/config/yaml/ryml.hh +++ b/src/include/simeng/config/yaml/ryml.hh @@ -18383,7 +18383,7 @@ bool is_debugger_attached() // https://stackoverflow.com/questions/2200277/detecting-debugger-on-mac-os-x // Returns true if the current process is being debugged (either // running under the debugger or has a debugger attached post facto). - int junk; + [[maybe_unused]] int junk; int mib[4]; struct kinfo_proc info; size_t size; @@ -20764,7 +20764,7 @@ public: template T as() const { - T val; + T val{}; tree__->cref(id__) >> val; return val; } diff --git a/src/include/simeng/kernel/Linux.hh b/src/include/simeng/kernel/Linux.hh index d997f016a9..a37b96cda5 100644 --- a/src/include/simeng/kernel/Linux.hh +++ b/src/include/simeng/kernel/Linux.hh @@ -89,7 +89,8 @@ struct LinuxProcessState { /** The clear_child_tid value. */ uint64_t clearChildTid = 0; - /** The virtual file descriptor mapping table. */ + /** The virtual file descriptor mapping table. Maps virtual file descriptors + * to host file descriptors */ std::vector fileDescriptorTable; /** Set of deallocated virtual file descriptors available for reuse. */ std::set freeFileDescriptors; @@ -159,7 +160,7 @@ class Linux { int64_t flag); /** close syscall: close a file descriptor. */ - int64_t close(int64_t fd); + int64_t close(int64_t vfd); /** newfstatat syscall: get file status; AKA fstatat. */ int64_t newfstatat(int64_t dfd, const std::string& filename, stat& out, @@ -204,7 +205,7 @@ class Linux { off_t offset); /** openat syscall: open/create a file. */ - int64_t openat(int64_t dirfd, const std::string& path, int64_t flags, + int64_t openat(int64_t vdfd, const std::string& pathname, int64_t flags, uint16_t mode); /** readlinkat syscall: read value of a symbolic link. */ @@ -240,9 +241,11 @@ class Linux { static const size_t LINUX_PATH_MAX = 4096; private: - /** Resturn correct Dirfd depending on given pathname abd dirfd given to - * syscall. */ - uint64_t getDirFd(int64_t dfd, std::string pathname); + /** Return the host directory file descriptor mapped to by the virtual dfd + * given to syscall. If vdfd is Linux::AT_FDCWD (-100) then Host::AT_FDCWD is + * returned + */ + int64_t getHostDirFD(int64_t vdfd); /** If the given filepath points to a special file, the filepath is replaced * to point to the SimEng equivalent. */ diff --git a/src/include/simeng/kernel/LinuxProcess.hh b/src/include/simeng/kernel/LinuxProcess.hh index b256f1cfdd..9d3fcf1c25 100644 --- a/src/include/simeng/kernel/LinuxProcess.hh +++ b/src/include/simeng/kernel/LinuxProcess.hh @@ -67,8 +67,9 @@ class LinuxProcess { ryml::ConstNodeRef config = config::SimInfo::getConfig()); /** Construct a Linux process from region of instruction memory, with the - * entry point fixed at 0. */ - LinuxProcess(span instructions, + * entry point fixed at 0 and source directory set to the default programs'. + * For use in test suites. */ + LinuxProcess(span instructions, ryml::ConstNodeRef config = config::SimInfo::getConfig()); ~LinuxProcess(); diff --git a/src/include/simeng/pipeline/A64FXPortAllocator.hh b/src/include/simeng/pipeline/A64FXPortAllocator.hh index 22261abad2..c713aaeb16 100644 --- a/src/include/simeng/pipeline/A64FXPortAllocator.hh +++ b/src/include/simeng/pipeline/A64FXPortAllocator.hh @@ -39,7 +39,7 @@ class A64FXPortAllocator : public PortAllocator { /** Set function from DispatchIssueUnit to retrieve reservation * station sizes during execution. */ void setRSSizeGetter( - std::function&)> rsSizes) override; + std::function&)> rsSizes) override; /** Tick the port allocator to allow it to process internal tasks. */ void tick() override; @@ -54,13 +54,13 @@ class A64FXPortAllocator : public PortAllocator { uint8_t dispatchSlot_; /** Get the current sizes an capacity of the reservation stations. */ - std::function&)> rsSizes_; + std::function&)> rsSizes_; /** Mapping from reservation station to ports. */ std::vector> rsToPort_; - /** Vector of free entires across all reservation stations. */ - std::vector freeEntries_; + /** Vector of free entries across all reservation stations. */ + std::vector freeEntries_; /** Reservation station classifications as detailed in manual. */ /** RSE with most free entries. */ diff --git a/src/include/simeng/pipeline/BalancedPortAllocator.hh b/src/include/simeng/pipeline/BalancedPortAllocator.hh index ccd550718d..c5ee7a48ce 100644 --- a/src/include/simeng/pipeline/BalancedPortAllocator.hh +++ b/src/include/simeng/pipeline/BalancedPortAllocator.hh @@ -34,7 +34,7 @@ class BalancedPortAllocator : public PortAllocator { /** Set function from DispatchIssueUnit to retrieve reservation * station sizes during execution. */ void setRSSizeGetter( - std::function&)> rsSizes) override; + std::function&)> rsSizes) override; /** Tick the port allocator to allow it to process internal tasks. */ void tick() override; @@ -50,7 +50,7 @@ class BalancedPortAllocator : public PortAllocator { std::vector weights; /** Get the current sizes an capacity of the reservation stations */ - std::function&)> rsSizes_; + std::function&)> rsSizes_; }; } // namespace pipeline diff --git a/src/include/simeng/pipeline/DispatchIssueUnit.hh b/src/include/simeng/pipeline/DispatchIssueUnit.hh index dd8654d921..37068d05ef 100644 --- a/src/include/simeng/pipeline/DispatchIssueUnit.hh +++ b/src/include/simeng/pipeline/DispatchIssueUnit.hh @@ -27,11 +27,11 @@ struct ReservationStationPort { /** A reservation station */ struct ReservationStation { /** Size of reservation station */ - uint16_t capacity; + uint32_t capacity; /** Number of instructions that can be dispatched to this unit per cycle. */ uint16_t dispatchRate; /** Current number of instructions in reservation station */ - uint16_t currentSize; + uint32_t currentSize; /** Issue ports belonging to reservation station */ std::vector ports; }; @@ -94,7 +94,7 @@ class DispatchIssueUnit { uint64_t getPortBusyStalls() const; /** Retrieve the current sizes and capacities of the reservation stations*/ - void getRSSizes(std::vector&) const; + void getRSSizes(std::vector&) const; private: /** A buffer of instructions to dispatch and read operands for. */ diff --git a/src/include/simeng/pipeline/FetchUnit.hh b/src/include/simeng/pipeline/FetchUnit.hh index 0c617a5547..09e8bb31f6 100644 --- a/src/include/simeng/pipeline/FetchUnit.hh +++ b/src/include/simeng/pipeline/FetchUnit.hh @@ -20,7 +20,7 @@ enum class LoopBufferState { // Struct to hold information about a fetched instruction struct loopBufferEntry { // Encoding of the instruction - const uint64_t encoding; + const uint32_t encoding; // Size of the instruction const uint16_t instructionSize; diff --git a/src/include/simeng/pipeline/M1PortAllocator.hh b/src/include/simeng/pipeline/M1PortAllocator.hh index 1139f9bc8a..136c7636fb 100644 --- a/src/include/simeng/pipeline/M1PortAllocator.hh +++ b/src/include/simeng/pipeline/M1PortAllocator.hh @@ -35,7 +35,7 @@ class M1PortAllocator : public PortAllocator { /** Set function from DispatchIssueUnit to retrieve reservation * station sizes during execution. */ void setRSSizeGetter( - std::function&)> rsSizes) override; + std::function&)> rsSizes) override; /** Tick the port allocator to allow it to process internal tasks. */ void tick() override; @@ -50,10 +50,10 @@ class M1PortAllocator : public PortAllocator { * that port. */ std::vector weights; - std::vector rsFreeSpaces; + std::vector rsFreeSpaces; /** Get the current capacity of the reservation stations */ - std::function&)> rsSizes_; + std::function&)> rsSizes_; /** Mapping from port index to reservation station */ std::vector> rsArrangement_; diff --git a/src/include/simeng/pipeline/PortAllocator.hh b/src/include/simeng/pipeline/PortAllocator.hh index 8d6f79a5f8..78e3a0c5c9 100644 --- a/src/include/simeng/pipeline/PortAllocator.hh +++ b/src/include/simeng/pipeline/PortAllocator.hh @@ -33,7 +33,7 @@ class PortAllocator { /** Set function from DispatchIssueUnit to retrieve reservation * station sizes during execution. */ virtual void setRSSizeGetter( - std::function&)> rsSizes) = 0; + std::function&)> rsSizes) = 0; /** Tick the port allocator to allow it to process internal tasks. */ virtual void tick() = 0; diff --git a/src/include/simeng/pipeline/ReorderBuffer.hh b/src/include/simeng/pipeline/ReorderBuffer.hh index b67075af2d..278a0174ca 100644 --- a/src/include/simeng/pipeline/ReorderBuffer.hh +++ b/src/include/simeng/pipeline/ReorderBuffer.hh @@ -44,7 +44,7 @@ class ReorderBuffer { /** Constructs a reorder buffer of maximum size `maxSize`, supplying a * reference to the register alias table. */ ReorderBuffer( - unsigned int maxSize, RegisterAliasTable& rat, LoadStoreQueue& lsq, + uint32_t maxSize, RegisterAliasTable& rat, LoadStoreQueue& lsq, std::function&)> raiseException, std::function sendLoopBoundary, BranchPredictor& predictor, uint16_t loopBufSize, @@ -93,7 +93,7 @@ class ReorderBuffer { LoadStoreQueue& lsq_; /** The maximum size of the ROB. */ - unsigned int maxSize_; + uint32_t maxSize_; /** A function to call upon exception generation. */ std::function)> raiseException_; diff --git a/src/lib/AlwaysNotTakenPredictor.cc b/src/lib/AlwaysNotTakenPredictor.cc index 9ad8d1e2e4..b7f33e6c22 100644 --- a/src/lib/AlwaysNotTakenPredictor.cc +++ b/src/lib/AlwaysNotTakenPredictor.cc @@ -2,9 +2,8 @@ namespace simeng { -BranchPrediction AlwaysNotTakenPredictor::predict(uint64_t address, - BranchType type, - int64_t knownOffset) { +BranchPrediction AlwaysNotTakenPredictor::predict( + [[maybe_unused]] uint64_t address, BranchType type, int64_t knownOffset) { return {false, 0}; } diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 33980aaefc..ffabd8bbca 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -56,6 +56,8 @@ set_target_properties(libsimeng PROPERTIES OUTPUT_NAME simeng) target_include_directories(libsimeng PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(libsimeng PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries(libsimeng capstone) +# Only enable compiler warnings for our code +target_compile_options(libsimeng PRIVATE ${SIMENG_COMPILE_OPTIONS}) set_target_properties(libsimeng PROPERTIES VERSION ${SimEng_VERSION}) set_target_properties(libsimeng PROPERTIES SOVERSION ${SimEng_VERSION_MAJOR}) @@ -66,4 +68,5 @@ install(TARGETS libsimeng DESTINATION lib) get_target_property(SIMENG_COMPILE_OPTIONS libsimeng COMPILE_OPTIONS) get_target_property(SIMENG_COMPILE_DEFINITIONS libsimeng COMPILE_DEFINITIONS) get_target_property(SIMENG_VERSION libsimeng VERSION) +# TODO move this to build folder. Cmake may not reconfigure when rebuilding after a change, therefor version.hh and cmake options can differ. This is happens especially when using an IDEs when changing build types configure_file(${PROJECT_SOURCE_DIR}/src/include/simeng/version.hh.in ${PROJECT_SOURCE_DIR}/src/include/simeng/version.hh) diff --git a/src/lib/CoreInstance.cc b/src/lib/CoreInstance.cc index 510f61a422..45832347ce 100644 --- a/src/lib/CoreInstance.cc +++ b/src/lib/CoreInstance.cc @@ -11,7 +11,7 @@ CoreInstance::CoreInstance(std::string executablePath, generateCoreModel(executablePath, executableArgs); } -CoreInstance::CoreInstance(char* assembledSource, size_t sourceSize, +CoreInstance::CoreInstance(uint8_t* assembledSource, size_t sourceSize, ryml::ConstNodeRef config) : config_(config), kernel_(kernel::Linux( @@ -96,7 +96,7 @@ void CoreInstance::createProcess(std::string executablePath, } else if (assembledSource_) { // Create a process image from the source code assembled by LLVM. process_ = std::make_unique( - span(source_, sourceSize_), config_); + span(source_, sourceSize_), config_); // Raise error if created process is not valid if (!process_->isValid()) { std::cerr << "[SimEng:CoreInstance] Could not create process based on " @@ -105,17 +105,12 @@ void CoreInstance::createProcess(std::string executablePath, exit(1); } } else { - // Create a process image from the set of instructions held in hex_ - process_ = std::make_unique( - span(reinterpret_cast(hex_), sizeof(hex_)), config_); - - // Raise error if created process is not valid - if (!process_->isValid()) { - std::cerr << "[SimEng:CoreInstance] Could not create process based on " - "supplied instruction span" - << std::endl; - exit(1); - } + // This case shouldn't be reached as the default program should always be + // provided + std::cerr << "[SimEng:CoreInstance] Unexpected parameters given to core " + "instance. No default program and no assembled source" + << std::endl; + exit(1); } // Create the process memory space from the generated process image @@ -317,12 +312,10 @@ std::shared_ptr CoreInstance::getProcessImage() const { return processMemory_; } -const uint64_t CoreInstance::getProcessImageSize() const { +uint64_t CoreInstance::getProcessImageSize() const { return processMemorySize_; } -const uint64_t CoreInstance::getHeapStart() const { - return process_->getHeapStart(); -} +uint64_t CoreInstance::getHeapStart() const { return process_->getHeapStart(); } } // namespace simeng diff --git a/src/lib/PerceptronPredictor.cc b/src/lib/PerceptronPredictor.cc index 18ae064d32..8d1202f8d6 100644 --- a/src/lib/PerceptronPredictor.cc +++ b/src/lib/PerceptronPredictor.cc @@ -12,7 +12,7 @@ PerceptronPredictor::PerceptronPredictor(ryml::ConstNodeRef config) btb_.resize(btbSize); // Initialise perceptron values with 0 for the global history weights, and 1 // for the bias weight; and initialise the target with 0 (i.e., unknown) - for (int i = 0; i < btbSize; i++) { + for (uint32_t i = 0; i < btbSize; i++) { btb_[i].first.assign(globalHistoryLength_, 0); btb_[i].first.push_back(1); btb_[i].second = 0; @@ -96,10 +96,11 @@ void PerceptronPredictor::update(uint64_t address, bool taken, // Update the perceptron if the prediction was wrong, or the dot product's // magnitude was not greater than the training threshold - if ((directionPrediction != taken) || (abs(Pout) < trainingThreshold_)) { + if ((directionPrediction != taken) || + (static_cast(std::abs(Pout)) < trainingThreshold_)) { int8_t t = (taken) ? 1 : -1; - for (int i = 0; i < globalHistoryLength_; i++) { + for (uint64_t i = 0; i < globalHistoryLength_; i++) { int8_t xi = ((prevGlobalHistory & (1 << ((globalHistoryLength_ - 1) - i))) == 0) ? -1 @@ -148,7 +149,7 @@ void PerceptronPredictor::flush(uint64_t address) { int64_t PerceptronPredictor::getDotProduct( const std::vector& perceptron, uint64_t history) { int64_t Pout = perceptron[globalHistoryLength_]; - for (int i = 0; i < globalHistoryLength_; i++) { + for (uint64_t i = 0; i < globalHistoryLength_; i++) { // Get branch direction for ith entry in the history bool historyTaken = ((history & (1 << ((globalHistoryLength_ - 1) - i))) != 0); diff --git a/src/lib/SpecialFileDirGen.cc b/src/lib/SpecialFileDirGen.cc index 0acf8984eb..6360eb536b 100644 --- a/src/lib/SpecialFileDirGen.cc +++ b/src/lib/SpecialFileDirGen.cc @@ -4,6 +4,58 @@ namespace simeng { +// Wrapper around calls to "system(command)". Checks that a shell is available +// before calling "system" and checking the output for any issues. +// ensureExitSuccess is used to check for a successful termination status (0) +// from the child shell, defaults to true +int systemWrapper(const std::string& command, + const bool ensureExitSuccess = true) { + // Check that there is a shell available + if (!system(NULL)) { + std::cerr + << "[SimEng:SpecialFileDirGen] Shell unavailable, can't call system" + << std::endl; + exit(EXIT_FAILURE); + } + + int output = system(command.c_str()); + + if (output == -1) { + std::cerr << "[SimEng:SpecialFileDirGen] Child process could not be " + "created, or its status could " + "not be retrieved. errno = " + << errno << std::endl; + exit(EXIT_FAILURE); + } else if (WIFEXITED(output) && WEXITSTATUS(output) == 127) { + std::cerr << "[SimEng:SpecialFileDirGen] Shell command could not be " + "executed in child shell" + << std::endl; + exit(EXIT_FAILURE); + } else { + if (ensureExitSuccess) { + if (WIFEXITED(output) && WEXITSTATUS(output) == 0) { + // Success + return output; + } else if (WIFSIGNALED(output)) { + std::cerr << "[SimEng:SpecialFileDirGen] Child process terminated by " + "signal: " + << WTERMSIG(output) << " when running command: " << command + << std::endl; + } else { + // Macros providing more information can be found in "man 2 waitpid" + std::cerr << "[SimEng:SpecialFileDirGen] Call to system(" << command + << ") returned failure. Return value: " << output + << ", if exited: " << WIFEXITED(output) + << " , exit status: " << WEXITSTATUS(output) << std::endl; + } + exit(EXIT_FAILURE); + } + + // Success + return output; + } +} + SpecialFileDirGen::SpecialFileDirGen(ryml::ConstNodeRef config) : specialFilesDir_( config["CPU-Info"]["Special-File-Dir-Path"].as()), @@ -21,31 +73,31 @@ SpecialFileDirGen::SpecialFileDirGen(ryml::ConstNodeRef config) void SpecialFileDirGen::RemoveExistingSFDir() { const std::string exist_input = "[ ! -d " + specialFilesDir_ + " ]"; - if (system(exist_input.c_str())) { + if (systemWrapper(exist_input, false)) { const std::string rm_input = "rm -r " + specialFilesDir_; - system(rm_input.c_str()); + systemWrapper(rm_input); } return; } void SpecialFileDirGen::GenerateSFDir() { // Create root special files directory - system(("mkdir -p " + specialFilesDir_).c_str()); + systemWrapper("mkdir -p " + specialFilesDir_); // Define frequently accessed root directories in special file tree const std::string proc_dir = specialFilesDir_ + "/proc/"; const std::string online_dir = specialFilesDir_ + "/sys/devices/system/cpu/"; const std::string cpu_base_dir = specialFilesDir_ + "/sys/devices/system/cpu/cpu"; - system(("mkdir " + proc_dir).c_str()); - system(("mkdir " + specialFilesDir_ + "/sys/").c_str()); - system(("mkdir " + specialFilesDir_ + "/sys/devices/").c_str()); - system(("mkdir " + specialFilesDir_ + "/sys/devices/system/").c_str()); - system(("mkdir " + online_dir).c_str()); + systemWrapper("mkdir " + proc_dir); + systemWrapper("mkdir " + specialFilesDir_ + "/sys/"); + systemWrapper("mkdir " + specialFilesDir_ + "/sys/devices/"); + systemWrapper("mkdir " + specialFilesDir_ + "/sys/devices/system/"); + systemWrapper("mkdir " + online_dir); // Create '/proc/cpuinfo' file. std::ofstream cpuinfo_File(proc_dir + "cpuinfo"); - for (int i = 0; i < coreCount_ * socketCount_ * smt_; i++) { + for (uint64_t i = 0; i < coreCount_ * socketCount_ * smt_; i++) { cpuinfo_File << "processor\t: " + std::to_string(i) + "\nBogoMIPS\t: " + std::to_string(bogoMIPS_).erase( std::to_string(bogoMIPS_).length() - 4) + @@ -63,7 +115,7 @@ void SpecialFileDirGen::GenerateSFDir() { // Create '/proc/stat' file. std::ofstream stat_File(proc_dir + "stat"); stat_File << "cpu 0 0 0 0 0 0 0 0 0 0\n"; - for (int i = 0; i < coreCount_ * socketCount_ * smt_; i++) { + for (uint64_t i = 0; i < coreCount_ * socketCount_ * smt_; i++) { stat_File << "cpu" + std::to_string(i) + " 0 0 0 0 0 0 0 0 0 0\n"; } stat_File << "intr 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " @@ -88,22 +140,21 @@ void SpecialFileDirGen::GenerateSFDir() { online_File.close(); // Create sub directory for each CPU core and required files. - for (int i = 0; i < coreCount_ * socketCount_ * smt_; i++) { - system(("mkdir " + cpu_base_dir + std::to_string(i) + "/").c_str()); - system( - ("mkdir " + cpu_base_dir + std::to_string(i) + "/topology/").c_str()); + for (uint64_t i = 0; i < coreCount_ * socketCount_ * smt_; i++) { + systemWrapper("mkdir " + cpu_base_dir + std::to_string(i) + "/"); + systemWrapper("mkdir " + cpu_base_dir + std::to_string(i) + "/topology/"); } // Create '/sys/devices/system/cpu/cpuX/topology/{core_id, // physical_package_id}' files uint64_t cores_per_package = coreCount_ / packageCount_; uint64_t current_package_id = 0; - for (int s = 0; s < socketCount_; s++) { - for (int c = 0; c < coreCount_; c++) { + for (uint64_t s = 0; s < socketCount_; s++) { + for (uint64_t c = 0; c < coreCount_; c++) { if (c % cores_per_package == 0 && c != 0) { current_package_id += 1; } - for (int t = 0; t < smt_; t++) { + for (uint64_t t = 0; t < smt_; t++) { // core_id File generation std::ofstream core_id_file( cpu_base_dir + diff --git a/src/lib/arch/aarch64/Architecture.cc b/src/lib/arch/aarch64/Architecture.cc index 528d7f9a98..e27ea8f0f9 100644 --- a/src/lib/arch/aarch64/Architecture.cc +++ b/src/lib/arch/aarch64/Architecture.cc @@ -65,7 +65,7 @@ Architecture::Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config) if (groupInheritance_.find(groups.front()) != groupInheritance_.end()) { std::vector inheritedGroups = groupInheritance_.at(groups.front()); - for (int k = 0; k < inheritedGroups.size(); k++) { + for (size_t k = 0; k < inheritedGroups.size(); k++) { // Determine if this group has inherited latency values from a // smaller distance if (inheritanceDistance[inheritedGroups[k]] > distance) { @@ -111,7 +111,7 @@ Architecture::Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config) groupInheritance_.end()) { std::vector inheritedGroups = groupInheritance_.at(groups.front()); - for (int k = 0; k < inheritedGroups.size(); k++) { + for (size_t k = 0; k < inheritedGroups.size(); k++) { groupExecutionInfo_[inheritedGroups[k]].ports.push_back(newPort); groups.push(inheritedGroups[k]); } @@ -135,7 +135,7 @@ Architecture::Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config) Architecture::~Architecture() { cs_close(&capstoneHandle_); } -uint8_t Architecture::predecode(const void* ptr, uint16_t bytesAvailable, +uint8_t Architecture::predecode(const uint8_t* ptr, uint16_t bytesAvailable, uint64_t instructionAddress, MacroOp& output) const { // Check that instruction address is 4-byte aligned as required by Armv9.2-a diff --git a/src/lib/arch/aarch64/ExceptionHandler.cc b/src/lib/arch/aarch64/ExceptionHandler.cc index 27183cc4b8..3cc38d655e 100644 --- a/src/lib/arch/aarch64/ExceptionHandler.cc +++ b/src/lib/arch/aarch64/ExceptionHandler.cc @@ -154,14 +154,10 @@ bool ExceptionHandler::init() { return concludeSyscall(stateChange); } - int64_t bytesRemaining = totalRead; // Get pointer and size of the buffer uint64_t iDst = bufPtr; - uint64_t iLength = bytesRemaining; - if (iLength > bytesRemaining) { - iLength = bytesRemaining; - } - bytesRemaining -= iLength; + // totalRead not negative due to above check so cast is safe + uint64_t iLength = static_cast(totalRead); // Write data for this buffer in 128-byte chunks auto iSrc = reinterpret_cast(dataBuffer_.data()); @@ -231,7 +227,8 @@ bool ExceptionHandler::init() { } // Build list of memory write operations - int64_t bytesRemaining = totalRead; + // totalRead not negative due to above check so cast is safe + uint64_t bytesRemaining = static_cast(totalRead); for (int64_t i = 0; i < iovcnt; i++) { // Get pointer and size of the buffer uint64_t iDst = iovdata[i * 2 + 0]; @@ -329,20 +326,21 @@ bool ExceptionHandler::init() { int64_t flag = registerFileSet.get(R3).get(); char* filename = new char[kernel::Linux::LINUX_PATH_MAX]; - return readStringThen( - filename, filenamePtr, kernel::Linux::LINUX_PATH_MAX, - [=](auto length) { - // Invoke the kernel - kernel::stat statOut; - uint64_t retval = linux_.newfstatat(dfd, filename, statOut, flag); - ProcessStateChange stateChange = { - ChangeType::REPLACEMENT, {R0}, {retval}}; - delete[] filename; - stateChange.memoryAddresses.push_back( - {statbufPtr, sizeof(statOut)}); - stateChange.memoryAddressValues.push_back(statOut); - return concludeSyscall(stateChange); - }); + return readStringThen(filename, filenamePtr, + kernel::Linux::LINUX_PATH_MAX, [=](auto length) { + // Invoke the kernel + kernel::stat statOut; + uint64_t retval = linux_.newfstatat( + dfd, filename, statOut, flag); + ProcessStateChange stateChange = { + ChangeType::REPLACEMENT, {R0}, {retval}}; + delete[] filename; + stateChange.memoryAddresses.push_back( + {statbufPtr, sizeof(statOut)}); + stateChange.memoryAddressValues.push_back( + {statOut, sizeof(statOut)}); + return concludeSyscall(stateChange); + }); break; } @@ -615,15 +613,16 @@ bool ExceptionHandler::init() { uint64_t bufPtr = registerFileSet.get(R0).get(); size_t buflen = registerFileSet.get(R1).get(); - char buf[buflen]; + std::vector buf; for (size_t i = 0; i < buflen; i++) { - buf[i] = (uint8_t)rand(); + buf.push_back((uint8_t)rand()); } stateChange = {ChangeType::REPLACEMENT, {R0}, {(uint64_t)buflen}}; stateChange.memoryAddresses.push_back({bufPtr, (uint8_t)buflen}); - stateChange.memoryAddressValues.push_back(RegisterValue(buf, buflen)); + stateChange.memoryAddressValues.push_back( + RegisterValue(buf.data(), buflen)); break; } diff --git a/src/lib/arch/aarch64/InstructionMetadata.cc b/src/lib/arch/aarch64/InstructionMetadata.cc index 59f529e3c6..d041b1435b 100644 --- a/src/lib/arch/aarch64/InstructionMetadata.cc +++ b/src/lib/arch/aarch64/InstructionMetadata.cc @@ -705,6 +705,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) case Opcode::AArch64_INCP_XP_S: operands[0].access = CS_AC_READ | CS_AC_WRITE; operands[1].access = CS_AC_READ; + break; case Opcode::AArch64_LD1i32: [[fallthrough]]; case Opcode::AArch64_LD1i64: diff --git a/src/lib/arch/aarch64/Instruction_decode.cc b/src/lib/arch/aarch64/Instruction_decode.cc index e62e9a6369..2dceee7750 100644 --- a/src/lib/arch/aarch64/Instruction_decode.cc +++ b/src/lib/arch/aarch64/Instruction_decode.cc @@ -239,7 +239,7 @@ void Instruction::decode() { destinationRegisters_.addSMEOperand(regs.size()); sourceValues_.addSMEOperand(regs.size()); results_.addSMEOperand(regs.size()); - for (int i = 0; i < regs.size(); i++) { + for (size_t i = 0; i < regs.size(); i++) { destinationRegisters_[destinationRegisterCount_] = regs[i]; destinationRegisterCount_++; // If WRITE, also need to add to source registers to maintain @@ -266,7 +266,7 @@ void Instruction::decode() { // Update source operand structure sizes sourceRegisters_.addSMEOperand(regs.size()); sourceValues_.addSMEOperand(regs.size()); - for (int i = 0; i < regs.size(); i++) { + for (size_t i = 0; i < regs.size(); i++) { sourceRegisters_[sourceRegisterCount_] = regs[i]; sourceRegisterCount_++; sourceOperandsPending_++; @@ -312,7 +312,7 @@ void Instruction::decode() { results_.addSMEOperand(regs.size()); sourceRegisters_.addSMEOperand(regs.size()); sourceValues_.addSMEOperand(regs.size()); - for (int i = 0; i < regs.size(); i++) { + for (size_t i = 0; i < regs.size(); i++) { // If READ access, we only need to add SME rows to source registers. // If WRITE access, then we need to add SME rows to destination // registers AND source registers. The latter is required to maintain diff --git a/src/lib/arch/aarch64/Instruction_execute.cc b/src/lib/arch/aarch64/Instruction_execute.cc index 6b389a11b0..6da1864eaf 100644 --- a/src/lib/arch/aarch64/Instruction_execute.cc +++ b/src/lib/arch/aarch64/Instruction_execute.cc @@ -110,6 +110,7 @@ void Instruction::execute() { switch (metadata_.opcode) { case Opcode::AArch64_ADCXr: { // adc xd, xn, xm auto [result, nzcv] = addCarry_3ops(sourceValues_); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = result; break; } @@ -207,30 +208,35 @@ void Instruction::execute() { case Opcode::AArch64_ADDWri: { // add wd, wn, #imm{, shift} auto [result, nzcv] = addShift_imm(sourceValues_, metadata_, false); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = {result, 8}; break; } case Opcode::AArch64_ADDWrs: { // add wd, wn, wm{, shift #amount} auto [result, nzcv] = addShift_3ops(sourceValues_, metadata_, false); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = {result, 8}; break; } case Opcode::AArch64_ADDWrx: { // add wd, wn, wm{, extend #amount} auto [result, nzcv] = addExtend_3ops(sourceValues_, metadata_, false); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = {result, 8}; break; } case Opcode::AArch64_ADDXri: { // add xd, xn, #imm{, shift} auto [result, nzcv] = addShift_imm(sourceValues_, metadata_, false); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = result; break; } case Opcode::AArch64_ADDXrs: { // add xd, xn, xm, {shift #amount} auto [result, nzcv] = addShift_3ops(sourceValues_, metadata_, false); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = result; break; } @@ -238,6 +244,7 @@ void Instruction::execute() { case Opcode::AArch64_ADDXrx64: { // add xd, xn, xm{, extend {#amount}} auto [result, nzcv] = addExtend_3ops(sourceValues_, metadata_, false); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = result; break; } @@ -384,6 +391,7 @@ void Instruction::execute() { auto [result, nzcv] = logicOp_imm( sourceValues_, metadata_, false, [](uint32_t x, uint32_t y) -> uint32_t { return x & y; }); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = {result, 8}; break; } @@ -391,6 +399,7 @@ void Instruction::execute() { auto [result, nzcv] = logicOpShift_3ops( sourceValues_, metadata_, false, [](uint32_t x, uint32_t y) -> uint32_t { return x & y; }); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = {result, 8}; break; } @@ -398,6 +407,7 @@ void Instruction::execute() { auto [result, nzcv] = logicOp_imm( sourceValues_, metadata_, false, [](uint64_t x, uint64_t y) -> uint64_t { return x & y; }); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = result; break; } @@ -405,6 +415,7 @@ void Instruction::execute() { auto [result, nzcv] = logicOpShift_3ops( sourceValues_, metadata_, false, [](uint64_t x, uint64_t y) -> uint64_t { return x & y; }); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = result; break; } @@ -502,12 +513,14 @@ void Instruction::execute() { case Opcode::AArch64_BICWrs: { // bic wd, wn, wm{, shift #amount} auto [result, nzcv] = bicShift_3ops(sourceValues_, metadata_, false); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = {result, 8}; break; } case Opcode::AArch64_BICXrs: { // bic xd, xn, xm{, shift #amount} auto [result, nzcv] = bicShift_3ops(sourceValues_, metadata_, false); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = result; break; } @@ -1138,6 +1151,7 @@ void Instruction::execute() { auto [result, nzcv] = logicOp_imm( sourceValues_, metadata_, false, [](uint32_t x, uint32_t y) -> uint32_t { return x ^ y; }); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = {result, 8}; break; } @@ -1145,6 +1159,7 @@ void Instruction::execute() { auto [result, nzcv] = logicOpShift_3ops( sourceValues_, metadata_, false, [](uint32_t x, uint32_t y) -> uint32_t { return x ^ y; }); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = {result, 8}; break; } @@ -1152,6 +1167,7 @@ void Instruction::execute() { auto [result, nzcv] = logicOp_imm( sourceValues_, metadata_, false, [](uint64_t x, uint64_t y) -> uint64_t { return x ^ y; }); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = result; break; } @@ -1159,6 +1175,7 @@ void Instruction::execute() { auto [result, nzcv] = logicOpShift_3ops( sourceValues_, metadata_, false, [](uint64_t x, uint64_t y) -> uint64_t { return x ^ y; }); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = result; break; } @@ -2550,7 +2567,7 @@ void Instruction::execute() { const uint64_t* pg = sourceValues_[partition_num + 1].getAsVector(); - const uint32_t sliceNum = + const uint16_t sliceNum = (ws + metadata_.operands[0].sme_index.disp) % partition_num; const uint64_t* data = memoryData_[0].getAsVector(); @@ -2566,7 +2583,7 @@ void Instruction::execute() { // All Slice vectors are added to results[] so need to update the // correct one - for (int i = 0; i < partition_num; i++) { + for (uint16_t i = 0; i < partition_num; i++) { if (i == sliceNum) results_[i] = {out, 256}; else @@ -2630,7 +2647,7 @@ void Instruction::execute() { // All Slice vectors are added to results[] so need to update the // correct one - for (int i = 0; i < partition_num; i++) { + for (uint32_t i = 0; i < partition_num; i++) { if (i == sliceNum) results_[i] = {out, 256}; else @@ -3927,6 +3944,7 @@ void Instruction::execute() { auto [result, nzcv] = logicOpShift_3ops( sourceValues_, metadata_, false, [](uint32_t x, uint32_t y) -> uint32_t { return x | (~y); }); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = {result, 8}; break; } @@ -3934,6 +3952,7 @@ void Instruction::execute() { auto [result, nzcv] = logicOpShift_3ops( sourceValues_, metadata_, false, [](uint64_t x, uint64_t y) -> uint64_t { return x | (~y); }); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = result; break; } @@ -3941,6 +3960,7 @@ void Instruction::execute() { auto [result, nzcv] = logicOp_imm( sourceValues_, metadata_, false, [](uint32_t x, uint32_t y) -> uint32_t { return x | y; }); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = {result, 8}; break; } @@ -3952,6 +3972,7 @@ void Instruction::execute() { auto [result, nzcv] = logicOp_imm( sourceValues_, metadata_, false, [](uint64_t x, uint64_t y) -> uint64_t { return x | y; }); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = {result, 8}; break; } @@ -5188,24 +5209,28 @@ void Instruction::execute() { case Opcode::AArch64_SUBWri: { // sub wd, wn, #imm{, } auto [result, nzcv] = subShift_imm(sourceValues_, metadata_, false); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = {result, 8}; break; } case Opcode::AArch64_SUBWrs: { // sub wd, wn, wm{, shift #amount} auto [result, nzcv] = subShift_3ops(sourceValues_, metadata_, false); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = {result, 8}; break; } case Opcode::AArch64_SUBXri: { // sub xd, xn, #imm{, } auto [result, nzcv] = subShift_imm(sourceValues_, metadata_, false); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = result; break; } case Opcode::AArch64_SUBXrs: { // sub xd, xn, xm{, shift #amount} auto [result, nzcv] = subShift_3ops(sourceValues_, metadata_, false); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = result; break; } @@ -5213,6 +5238,7 @@ void Instruction::execute() { case Opcode::AArch64_SUBXrx64: { // sub xd, xn, xm{, extend #amount} auto [result, nzcv] = subExtend_3ops(sourceValues_, metadata_, false); + (void)nzcv; // Prevent unused variable warnings in GCC7 results_[0] = result; break; } diff --git a/src/lib/arch/aarch64/MicroDecoder.cc b/src/lib/arch/aarch64/MicroDecoder.cc index 29a6c70ee3..edb4a9a1c2 100644 --- a/src/lib/arch/aarch64/MicroDecoder.cc +++ b/src/lib/arch/aarch64/MicroDecoder.cc @@ -626,7 +626,7 @@ cs_detail MicroDecoder::createDefaultDetail(std::vector opTypes) { cs_detail detail = default_detail; info.op_count = opTypes.size(); - for (int op = 0; op < opTypes.size(); op++) { + for (size_t op = 0; op < opTypes.size(); op++) { info.operands[op] = default_op; switch (opTypes[op].type) { case arm64_op_type::ARM64_OP_REG: { diff --git a/src/lib/arch/riscv/Architecture.cc b/src/lib/arch/riscv/Architecture.cc index 3cb17ae2c8..c600c285d4 100644 --- a/src/lib/arch/riscv/Architecture.cc +++ b/src/lib/arch/riscv/Architecture.cc @@ -84,7 +84,7 @@ Architecture::Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config) if (groupInheritance_.find(groups.front()) != groupInheritance_.end()) { std::vector inheritedGroups = groupInheritance_.at(groups.front()); - for (int k = 0; k < inheritedGroups.size(); k++) { + for (size_t k = 0; k < inheritedGroups.size(); k++) { // Determine if this group has inherited latency values from a // smaller distance if (inheritanceDistance[inheritedGroups[k]] > distance) { @@ -131,7 +131,7 @@ Architecture::Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config) groupInheritance_.end()) { std::vector inheritedGroups = groupInheritance_.at(groups.front()); - for (int k = 0; k < inheritedGroups.size(); k++) { + for (size_t k = 0; k < inheritedGroups.size(); k++) { groupExecutionInfo_[inheritedGroups[k]].ports.push_back(newPort); groups.push(inheritedGroups[k]); } @@ -155,7 +155,7 @@ Architecture::Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config) Architecture::~Architecture() { cs_close(&capstoneHandle_); } -uint8_t Architecture::predecode(const void* ptr, uint16_t bytesAvailable, +uint8_t Architecture::predecode(const uint8_t* ptr, uint16_t bytesAvailable, uint64_t instructionAddress, MacroOp& output) const { // Check that instruction address is 4-byte aligned as required by RISC-V diff --git a/src/lib/arch/riscv/ExceptionHandler.cc b/src/lib/arch/riscv/ExceptionHandler.cc index d12e2bc86d..1e653e9f9d 100644 --- a/src/lib/arch/riscv/ExceptionHandler.cc +++ b/src/lib/arch/riscv/ExceptionHandler.cc @@ -152,14 +152,10 @@ bool ExceptionHandler::init() { return concludeSyscall(stateChange); } - int64_t bytesRemaining = totalRead; // Get pointer and size of the buffer uint64_t iDst = bufPtr; - uint64_t iLength = bytesRemaining; - if (iLength > bytesRemaining) { - iLength = bytesRemaining; - } - bytesRemaining -= iLength; + // totalRead not negative due to above check so cast is safe + uint64_t iLength = static_cast(totalRead); // Write data for this buffer in 128-byte chunks auto iSrc = reinterpret_cast(dataBuffer_.data()); @@ -229,7 +225,8 @@ bool ExceptionHandler::init() { } // Build list of memory write operations - int64_t bytesRemaining = totalRead; + // totalRead not negative due to above check so cast is safe + uint64_t bytesRemaining = static_cast(totalRead); for (int64_t i = 0; i < iovcnt; i++) { // Get pointer and size of the buffer uint64_t iDst = iovdata[i * 2 + 0]; @@ -327,20 +324,21 @@ bool ExceptionHandler::init() { int64_t flag = registerFileSet.get(R3).get(); char* filename = new char[kernel::Linux::LINUX_PATH_MAX]; - return readStringThen( - filename, filenamePtr, kernel::Linux::LINUX_PATH_MAX, - [=](auto length) { - // Invoke the kernel - kernel::stat statOut; - uint64_t retval = linux_.newfstatat(dfd, filename, statOut, flag); - ProcessStateChange stateChange = { - ChangeType::REPLACEMENT, {R0}, {retval}}; - delete[] filename; - stateChange.memoryAddresses.push_back( - {statbufPtr, sizeof(statOut)}); - stateChange.memoryAddressValues.push_back(statOut); - return concludeSyscall(stateChange); - }); + return readStringThen(filename, filenamePtr, + kernel::Linux::LINUX_PATH_MAX, [=](auto length) { + // Invoke the kernel + kernel::stat statOut; + uint64_t retval = linux_.newfstatat( + dfd, filename, statOut, flag); + ProcessStateChange stateChange = { + ChangeType::REPLACEMENT, {R0}, {retval}}; + delete[] filename; + stateChange.memoryAddresses.push_back( + {statbufPtr, sizeof(statOut)}); + stateChange.memoryAddressValues.push_back( + {statOut, sizeof(statOut)}); + return concludeSyscall(stateChange); + }); break; } @@ -447,6 +445,7 @@ bool ExceptionHandler::init() { case 131: { // tgkill // TODO currently returns success without action stateChange = {ChangeType::REPLACEMENT, {R0}, {0}}; + break; } case 134: { // rt_sigaction // TODO: Implement syscall logic. Ignored for now as it's assumed the @@ -612,15 +611,16 @@ bool ExceptionHandler::init() { uint64_t bufPtr = registerFileSet.get(R0).get(); size_t buflen = registerFileSet.get(R1).get(); - char buf[buflen]; + std::vector buf; for (size_t i = 0; i < buflen; i++) { - buf[i] = (uint8_t)rand(); + buf.push_back((uint8_t)rand()); } stateChange = {ChangeType::REPLACEMENT, {R0}, {(uint64_t)buflen}}; stateChange.memoryAddresses.push_back({bufPtr, (uint8_t)buflen}); - stateChange.memoryAddressValues.push_back(RegisterValue(buf, buflen)); + stateChange.memoryAddressValues.push_back( + RegisterValue(buf.data(), buflen)); break; } diff --git a/src/lib/config/ModelConfig.cc b/src/lib/config/ModelConfig.cc index 362abac03b..049c24d04a 100644 --- a/src/lib/config/ModelConfig.cc +++ b/src/lib/config/ModelConfig.cc @@ -707,9 +707,9 @@ void ModelConfig::setExpectations(bool isDefault) { ExpectationNode::createExpectation(0, wildcard)); expectations_["Reservation-Stations"][wildcard].addChild( - ExpectationNode::createExpectation(32, "Size")); + ExpectationNode::createExpectation(32, "Size")); expectations_["Reservation-Stations"][wildcard]["Size"] - .setValueBounds(1, UINT16_MAX); + .setValueBounds(1, UINT32_MAX); expectations_["Reservation-Stations"][wildcard].addChild( ExpectationNode::createExpectation(4, "Dispatch-Rate")); @@ -950,7 +950,7 @@ void ModelConfig::postValidation() { groupInheritance.end()) { std::vector inheritedGroups = groupInheritance.at(blockingGroups.front()); - for (int k = 0; k < inheritedGroups.size(); k++) { + for (size_t k = 0; k < inheritedGroups.size(); k++) { blockingGroups.push(inheritedGroups[k]); node["Blocking-Group-Nums"].append_child() << inheritedGroups[k]; } @@ -999,7 +999,7 @@ void ModelConfig::postValidation() { } else { node.append_child() << ryml::key("Port-Nums") |= ryml::SEQ; } - for (int i = 0; i < node["Ports"].num_children(); i++) { + for (size_t i = 0; i < node["Ports"].num_children(); i++) { std::string portname = node["Ports"][i].as(); std::vector::iterator itr = std::find(portnames.begin(), portnames.end(), portname); @@ -1225,7 +1225,7 @@ void ModelConfig::createGroupMapping() { // uint16_t starting from 0. Therefore, the index of each groupOptions_ // entry is also its ::InstructionGroups value (assuming groupOptions_ // is ordered exactly as ::InstructionGroups is). - for (int grp = 0; grp < groupOptions_.size(); grp++) { + for (size_t grp = 0; grp < groupOptions_.size(); grp++) { groupMapping_[groupOptions_[grp]] = grp; } } diff --git a/src/lib/kernel/Linux.cc b/src/lib/kernel/Linux.cc index 723a9f70b2..780867cdec 100644 --- a/src/lib/kernel/Linux.cc +++ b/src/lib/kernel/Linux.cc @@ -6,9 +6,7 @@ #include #include #include -#include #include -#include #include #include @@ -23,14 +21,11 @@ namespace kernel { void Linux::createProcess(const LinuxProcess& process) { assert(process.isValid() && "Attempted to use an invalid process"); assert(processStates_.size() == 0 && "Multiple processes not yet supported"); - processStates_.push_back( - {.pid = 0, // TODO: create unique PIDs - .path = process.getPath(), - .startBrk = process.getHeapStart(), - .currentBrk = process.getHeapStart(), - .initialStackPointer = process.getInitialStackPointer(), - .mmapRegion = process.getMmapStart(), - .pageSize = process.getPageSize()}); + processStates_.push_back({0, // TODO: create unique PIDs + process.getPath(), process.getHeapStart(), + process.getHeapStart(), + process.getInitialStackPointer(), + process.getMmapStart(), process.getPageSize()}); processStates_.back().fileDescriptorTable.push_back(STDIN_FILENO); processStates_.back().fileDescriptorTable.push_back(STDOUT_FILENO); processStates_.back().fileDescriptorTable.push_back(STDERR_FILENO); @@ -42,31 +37,34 @@ void Linux::createProcess(const LinuxProcess& process) { "/sys/devices/system/cpu/online", "core_id", "physical_package_id"}); } -uint64_t Linux::getDirFd(int64_t dfd, std::string pathname) { - // Resolve absolute path to target file - char absolutePath[LINUX_PATH_MAX]; - realpath(pathname.c_str(), absolutePath); - - int64_t dfd_temp = AT_FDCWD; - if (dfd != -100) { - dfd_temp = dfd; - // If absolute path used then dfd is dis-regarded. Otherwise need to see if - // fd exists for directory referenced - if (strncmp(pathname.c_str(), absolutePath, strlen(absolutePath)) != 0) { - assert(dfd < processStates_[0].fileDescriptorTable.size()); - dfd_temp = processStates_[0].fileDescriptorTable[dfd]; - if (dfd_temp < 0) { - return -1; - } +int64_t Linux::getHostDirFD(int64_t vdfd) { + // -100 = AT_FCWD on linux. Pass back AT_FDCWD for host platform e.g. -2 for + // macOS + if (vdfd == -100) { + // Early return if requesting current working directory + return AT_FDCWD; + } + + if (vdfd < 0) { + // Invalid virtual file descriptor + return -1; + } else { + uint64_t unsignedVdfd = static_cast(vdfd); + if (unsignedVdfd < processStates_[0].fileDescriptorTable.size()) { + // Within bounds of table. Entry will be -1 if invalid + return processStates_[0].fileDescriptorTable[unsignedVdfd]; + } else { + // Outside bounds of table + assert(false && "vdfd outside bounds of file descriptor table"); + return -1; } } - return dfd_temp; } std::string Linux::getSpecialFile(const std::string filename) { for (auto prefix : {"/dev/", "/proc/", "/sys/"}) { if (strncmp(filename.c_str(), prefix, strlen(prefix)) == 0) { - for (int i = 0; i < supportedSpecialFiles_.size(); i++) { + for (size_t i = 0; i < supportedSpecialFiles_.size(); i++) { if (filename.find(supportedSpecialFiles_[i]) != std::string::npos) { std::cerr << "[SimEng:Linux] Using Special File: " << filename.c_str() << std::endl; @@ -141,30 +139,32 @@ int64_t Linux::faccessat(int64_t dfd, const std::string& filename, int64_t mode, // special file) new_pathname = Linux::getSpecialFile(filename); - // Get correct dirfd - int64_t dirfd = Linux::getDirFd(dfd, filename); - if (dirfd == -1) return EBADF; + // Get host dirfd. May return -1 in case of no mapping, pass through to host + // faccessat to deal with this + int64_t hostDfd = Linux::getHostDirFD(dfd); // Pass call through to host - int64_t retval = ::faccessat(dirfd, new_pathname.c_str(), mode, flag); + int64_t retval = ::faccessat(hostDfd, new_pathname.c_str(), mode, flag); return retval; } -int64_t Linux::close(int64_t fd) { +int64_t Linux::close(int64_t vfd) { // Don't close STDOUT or STDERR otherwise no SimEng output is given // afterwards. This includes final results given at the end of execution - if (fd != STDERR_FILENO && fd != STDOUT_FILENO) { - assert(fd < processStates_[0].fileDescriptorTable.size()); - int64_t hfd = processStates_[0].fileDescriptorTable[fd]; + if (vfd != STDERR_FILENO && vfd != STDOUT_FILENO) { + assert(vfd >= 0 && static_cast(vfd) < + processStates_[0].fileDescriptorTable.size()); + int64_t hfd = processStates_[0].fileDescriptorTable[vfd]; if (hfd < 0) { + // Early return, can't deallocate vfd that isn't in fileDescriptorTable return EBADF; } // Deallocate the virtual file descriptor - assert(processStates_[0].freeFileDescriptors.count(fd) == 0); - processStates_[0].freeFileDescriptors.insert(fd); - processStates_[0].fileDescriptorTable[fd] = -1; + assert(processStates_[0].freeFileDescriptors.count(vfd) == 0); + processStates_[0].freeFileDescriptors.insert(vfd); + processStates_[0].fileDescriptorTable[vfd] = -1; return ::close(hfd); } @@ -182,13 +182,13 @@ int64_t Linux::newfstatat(int64_t dfd, const std::string& filename, stat& out, // special file) new_pathname = Linux::getSpecialFile(filename); - // Get correct dirfd - int64_t dirfd = Linux::getDirFd(dfd, filename); - if (dirfd == -1) return EBADF; + // Get host dirfd. May return -1 in case of no mapping, pass through to host + // fstatat to deal with this + int64_t hostDfd = Linux::getHostDirFD(dfd); // Pass call through to host struct ::stat statbuf; - int64_t retval = ::fstatat(dirfd, new_pathname.c_str(), &statbuf, flag); + int64_t retval = ::fstatat(hostDfd, new_pathname.c_str(), &statbuf, flag); // Copy results to output struct out.dev = statbuf.st_dev; @@ -224,7 +224,8 @@ int64_t Linux::newfstatat(int64_t dfd, const std::string& filename, stat& out, } int64_t Linux::fstat(int64_t fd, stat& out) { - assert(fd < processStates_[0].fileDescriptorTable.size()); + assert(fd > 0 && static_cast(fd) < + processStates_[0].fileDescriptorTable.size()); int64_t hfd = processStates_[0].fileDescriptorTable[fd]; if (hfd < 0) { return EBADF; @@ -320,7 +321,8 @@ int64_t Linux::gettimeofday(uint64_t systemTimer, timeval* tv, timeval* tz) { } int64_t Linux::ioctl(int64_t fd, uint64_t request, std::vector& out) { - assert(fd < processStates_[0].fileDescriptorTable.size()); + assert(fd > 0 && static_cast(fd) < + processStates_[0].fileDescriptorTable.size()); int64_t hfd = processStates_[0].fileDescriptorTable[fd]; if (hfd < 0) { return EBADF; @@ -355,7 +357,8 @@ int64_t Linux::ioctl(int64_t fd, uint64_t request, std::vector& out) { } uint64_t Linux::lseek(int64_t fd, uint64_t offset, int64_t whence) { - assert(fd < processStates_[0].fileDescriptorTable.size()); + assert(fd > 0 && static_cast(fd) < + processStates_[0].fileDescriptorTable.size()); int64_t hfd = processStates_[0].fileDescriptorTable[fd]; if (hfd < 0) { return EBADF; @@ -368,15 +371,14 @@ int64_t Linux::munmap(uint64_t addr, size_t length) { if (addr % lps->pageSize != 0) { // addr must be a multiple of the process page size return -1; - } - int i; + }; vm_area_struct alloc; // Find addr in allocations - for (i = 0; i < lps->contiguousAllocations.size(); i++) { + for (size_t i = 0; i < lps->contiguousAllocations.size(); i++) { alloc = lps->contiguousAllocations[i]; if (alloc.vm_start == addr) { if ((alloc.vm_end - alloc.vm_start) < length) { - // length must not be larger than the original allocation + // Length must not be larger than the original allocation return -1; } if (i != 0) { @@ -388,24 +390,25 @@ int64_t Linux::munmap(uint64_t addr, size_t length) { } } - for (int i = 0; i < lps->nonContiguousAllocations.size(); i++) { - alloc = lps->nonContiguousAllocations[i]; + for (size_t j = 0; j < lps->nonContiguousAllocations.size(); j++) { + alloc = lps->nonContiguousAllocations[j]; if (alloc.vm_start == addr) { if ((alloc.vm_end - alloc.vm_start) < length) { - // length must not be larger than the original allocation + // Length must not be larger than the original allocation return -1; } lps->nonContiguousAllocations.erase( - lps->nonContiguousAllocations.begin() + i); + lps->nonContiguousAllocations.begin() + j); return 0; } } - // Not an error if the indicated range does no contain any mapped pages + // Not an error if the indicated range does not contain any mapped pages return 0; } -uint64_t Linux::mmap(uint64_t addr, size_t length, int prot, int flags, int fd, - off_t offset) { +uint64_t Linux::mmap(uint64_t addr, size_t length, [[maybe_unused]] int prot, + [[maybe_unused]] int flags, [[maybe_unused]] int fd, + [[maybe_unused]] off_t offset) { LinuxProcessState* lps = &processStates_[0]; std::shared_ptr newAlloc(new vm_area_struct); if (addr == 0) { // Kernel decides allocation @@ -444,13 +447,11 @@ uint64_t Linux::mmap(uint64_t addr, size_t length, int prot, int flags, int fd, return newAlloc->vm_start; } -int64_t Linux::openat(int64_t dfd, const std::string& filename, int64_t flags, +int64_t Linux::openat(int64_t dfd, const std::string& pathname, int64_t flags, uint16_t mode) { - std::string new_pathname; - - // Alter special file path to point to SimEng one (if filename points to + // Alter special file path to point to SimEng one (if pathname points to // special file) - new_pathname = Linux::getSpecialFile(filename); + std::string new_pathname = Linux::getSpecialFile(pathname); // Need to re-create flag input to correct values for host OS int64_t newFlags = 0; @@ -486,18 +487,22 @@ int64_t Linux::openat(int64_t dfd, const std::string& filename, int64_t flags, // If Special File (or Special File Directory) is being opened then need to // set flags to O_RDONLY and O_CLOEXEC only. - if (new_pathname != filename) { + if (new_pathname != pathname) { newFlags = O_RDONLY | O_CLOEXEC; } - // Get correct dirfd - int64_t dirfd = Linux::getDirFd(dfd, filename); - if (dirfd == -1) return EBADF; + // Get host dirfd. May return -1 in case of no mapping, pass through to host + // openat to deal with this + int64_t hDfd = Linux::getHostDirFD(dfd); // Pass call through to host - int64_t hfd = ::openat(dirfd, new_pathname.c_str(), newFlags, mode); - if (hfd < 0) { - return hfd; + int64_t hostFd = ::openat(hDfd, new_pathname.c_str(), newFlags, mode); + if (hostFd < 0) { + // An error occurred, pass this back to userspace don't allocate virtual + // file descriptor + // TODO possibly need to set errno for simulated program so that it can be + // handled correctly?? This may be relevant throughout + return hostFd; } LinuxProcessState& processState = processStates_[0]; @@ -508,11 +513,11 @@ int64_t Linux::openat(int64_t dfd, const std::string& filename, int64_t flags, // Take virtual descriptor from free pool auto first = processState.freeFileDescriptors.begin(); vfd = processState.freeFileDescriptors.extract(first).value(); - processState.fileDescriptorTable[vfd] = hfd; + processState.fileDescriptorTable[vfd] = hostFd; } else { // Extend file descriptor table for a new virtual descriptor vfd = processState.fileDescriptorTable.size(); - processState.fileDescriptorTable.push_back(hfd); + processState.fileDescriptorTable.push_back(hostFd); } return vfd; @@ -524,7 +529,12 @@ int64_t Linux::readlinkat(int64_t dirfd, const std::string& pathname, char* buf, if (pathname == "/proc/self/exe") { // Resolve absolute path char absolutePath[LINUX_PATH_MAX]; - realpath(processState.path.c_str(), absolutePath); + if (!realpath(processState.path.c_str(), absolutePath)) { + // Something went wrong + std::cerr << "[SimEng:readlinkat] realpath failed with errno = " << errno + << std::endl; + exit(EXIT_FAILURE); + } // Copy executable path to buffer std::strncpy(buf, absolutePath, bufsize); @@ -532,12 +542,14 @@ int64_t Linux::readlinkat(int64_t dirfd, const std::string& pathname, char* buf, return std::min(std::strlen(absolutePath), bufsize); } - // TODO: resolve symbolic link for other paths + // TODO: resolve symbolic link for other paths - get hostfd then pass to real + // readlinkat return -1; } int64_t Linux::getdents64(int64_t fd, void* buf, uint64_t count) { - assert(fd < processStates_[0].fileDescriptorTable.size()); + assert(fd > 0 && static_cast(fd) < + processStates_[0].fileDescriptorTable.size()); int64_t hfd = processStates_[0].fileDescriptorTable[fd]; if (hfd < 0) { return EBADF; @@ -593,7 +605,8 @@ int64_t Linux::getdents64(int64_t fd, void* buf, uint64_t count) { } int64_t Linux::read(int64_t fd, void* buf, uint64_t count) { - assert(fd < processStates_[0].fileDescriptorTable.size()); + assert(fd > 0 && static_cast(fd) < + processStates_[0].fileDescriptorTable.size()); int64_t hfd = processStates_[0].fileDescriptorTable[fd]; if (hfd < 0) { return EBADF; @@ -602,7 +615,8 @@ int64_t Linux::read(int64_t fd, void* buf, uint64_t count) { } int64_t Linux::readv(int64_t fd, const void* iovdata, int iovcnt) { - assert(fd < processStates_[0].fileDescriptorTable.size()); + assert(fd > 0 && static_cast(fd) < + processStates_[0].fileDescriptorTable.size()); int64_t hfd = processStates_[0].fileDescriptorTable[fd]; if (hfd < 0) { return EBADF; @@ -633,7 +647,8 @@ int64_t Linux::setTidAddress(uint64_t tidptr) { } int64_t Linux::write(int64_t fd, const void* buf, uint64_t count) { - assert(fd < processStates_[0].fileDescriptorTable.size()); + assert(fd > 0 && static_cast(fd) < + processStates_[0].fileDescriptorTable.size()); int64_t hfd = processStates_[0].fileDescriptorTable[fd]; if (hfd < 0) { return EBADF; @@ -642,7 +657,8 @@ int64_t Linux::write(int64_t fd, const void* buf, uint64_t count) { } int64_t Linux::writev(int64_t fd, const void* iovdata, int iovcnt) { - assert(fd < processStates_[0].fileDescriptorTable.size()); + assert(fd > 0 && static_cast(fd) < + processStates_[0].fileDescriptorTable.size()); int64_t hfd = processStates_[0].fileDescriptorTable[fd]; if (hfd < 0) { return EBADF; diff --git a/src/lib/kernel/LinuxProcess.cc b/src/lib/kernel/LinuxProcess.cc index 28e5b3afed..795a6e5a8a 100644 --- a/src/lib/kernel/LinuxProcess.cc +++ b/src/lib/kernel/LinuxProcess.cc @@ -62,11 +62,13 @@ LinuxProcess::LinuxProcess(const std::vector& commandLine, processImage_ = std::shared_ptr(unwrappedProcImgPtr, free); } -LinuxProcess::LinuxProcess(span instructions, ryml::ConstNodeRef config) +LinuxProcess::LinuxProcess(span instructions, + ryml::ConstNodeRef config) : STACK_SIZE(config["Process-Image"]["Stack-Size"].as()), HEAP_SIZE(config["Process-Image"]["Heap-Size"].as()) { - // Set program command string to a relative path of "Default" - commandLine_.push_back("Default\0"); + // Set program command string to the full path of the default program even + // though these aren't the instructions being executed + commandLine_.push_back(SIMENG_SOURCE_DIR "/SimEngDefaultProgram\0"); isValid_ = true; @@ -127,7 +129,7 @@ void LinuxProcess::createStack(char** processImage) { initialStackFrame.push_back(commandLine_.size()); // argc for (size_t i = 0; i < commandLine_.size(); i++) { char* argvi = commandLine_[i].data(); - for (int j = 0; j < commandLine_[i].size(); j++) { + for (size_t j = 0; j < commandLine_[i].size(); j++) { stringBytes.push_back(argvi[j]); } stringBytes.push_back(0); @@ -135,7 +137,7 @@ void LinuxProcess::createStack(char** processImage) { // Environment strings std::vector envStrings = {"OMP_NUM_THREADS=1"}; for (std::string& env : envStrings) { - for (int i = 0; i < env.size(); i++) { + for (size_t i = 0; i < env.size(); i++) { stringBytes.push_back(env.c_str()[i]); } // Null entry to separate strings @@ -147,7 +149,7 @@ void LinuxProcess::createStack(char** processImage) { stackPointer_ -= alignToBoundary(stringBytes.size() + 1, 32); uint16_t ptrCount = 1; initialStackFrame.push_back(stackPointer_); // argv[0] ptr - for (int i = 0; i < stringBytes.size(); i++) { + for (size_t i = 0; i < stringBytes.size(); i++) { if (ptrCount == commandLine_.size()) { // null terminator to separate argv and env strings initialStackFrame.push_back(0); diff --git a/src/lib/models/emulation/Core.cc b/src/lib/models/emulation/Core.cc index 274b8bf7c8..3998fa91b5 100644 --- a/src/lib/models/emulation/Core.cc +++ b/src/lib/models/emulation/Core.cc @@ -79,7 +79,7 @@ void Core::tick() { } const auto& instructionBytes = fetched[fetchIndex].data; - auto bytesRead = isa_.predecode(instructionBytes.getAsVector(), + auto bytesRead = isa_.predecode(instructionBytes.getAsVector(), FETCH_SIZE, pc_, macroOp_); // Clear the fetched data @@ -173,7 +173,7 @@ std::map Core::getStats() const { return {{"cycles", std::to_string(ticks_)}, {"retired", std::to_string(instructionsExecuted_)}, {"branch.executed", std::to_string(branchesExecuted_)}}; -}; +} void Core::execute(std::shared_ptr& uop) { uop->execute(); diff --git a/src/lib/models/inorder/Core.cc b/src/lib/models/inorder/Core.cc index ce4339eff0..9d36707b70 100644 --- a/src/lib/models/inorder/Core.cc +++ b/src/lib/models/inorder/Core.cc @@ -36,7 +36,7 @@ Core::Core(memory::MemoryInterface& instructionMemory, // Query and apply initial state auto state = isa.getInitialState(); applyStateChange(state); -}; +} void Core::tick() { ticks_++; diff --git a/src/lib/models/outoforder/Core.cc b/src/lib/models/outoforder/Core.cc index 41fe3fa38c..5c7793f133 100644 --- a/src/lib/models/outoforder/Core.cc +++ b/src/lib/models/outoforder/Core.cc @@ -91,14 +91,14 @@ Core::Core(memory::MemoryInterface& instructionMemory, config["Execution-Units"][i]["Pipelined"].as(), blockingGroups); } // Provide reservation size getter to A64FX port allocator - portAllocator.setRSSizeGetter([this](std::vector& sizeVec) { + portAllocator.setRSSizeGetter([this](std::vector& sizeVec) { dispatchIssueUnit_.getRSSizes(sizeVec); }); // Query and apply initial state auto state = isa.getInitialState(); applyStateChange(state); -}; +} void Core::tick() { ticks_++; diff --git a/src/lib/pipeline/A64FXPortAllocator.cc b/src/lib/pipeline/A64FXPortAllocator.cc index 95a55cdb9b..d7c1057bb3 100644 --- a/src/lib/pipeline/A64FXPortAllocator.cc +++ b/src/lib/pipeline/A64FXPortAllocator.cc @@ -19,22 +19,24 @@ uint16_t A64FXPortAllocator::allocate(const std::vector& ports) { uint16_t rs = 0; uint16_t port = 0; - bool foundRS = false; - bool foundPort = false; + // Both only used in assertions so produces warning in release mode + [[maybe_unused]] bool foundRS = false; + [[maybe_unused]] bool foundPort = false; if (attribute == InstructionAttribute::RSX) { // Get difference between free entries of RSE{0|1} and RSA{0|1} - int diffRSE = (freeEntries_[0] + freeEntries_[1]) - - (freeEntries_[2] + freeEntries_[3]); - int diffRSA = (freeEntries_[2] + freeEntries_[3]) - - (freeEntries_[0] + freeEntries_[1]); + int32_t totalRSE = freeEntries_[0] + freeEntries_[1]; + int32_t totalRSA = freeEntries_[2] + freeEntries_[3]; + int32_t diffRSE = totalRSE - totalRSA; + int32_t diffRSA = totalRSA - totalRSE; + // Set threshold values - int thresholdA = 4; - int thresholdB = 4; - int thresholdC = 4; + int32_t thresholdA = 4; + int32_t thresholdB = 4; + int32_t thresholdC = 4; if (diffRSE >= thresholdA) { - if ((freeEntries_[0] - freeEntries_[1]) >= thresholdB) { + if (((int32_t)freeEntries_[0] - (int32_t)freeEntries_[1]) >= thresholdB) { rs = RSEm_; // Table 1 } else { rs = dispatchSlot_ % 2 == 0 ? RSEm_ : RSEf_; // Table 2 @@ -146,12 +148,13 @@ uint16_t A64FXPortAllocator::allocate(const std::vector& ports) { void A64FXPortAllocator::issued(uint16_t port) {} -void A64FXPortAllocator::deallocate(uint16_t port) { issued(port); }; +void A64FXPortAllocator::deallocate(uint16_t port) { issued(port); } uint8_t A64FXPortAllocator::attributeMapping( const std::vector& ports) { uint8_t attribute = 0; - bool foundAttribute = false; + // Only used in assertion so produces warning in release mode + [[maybe_unused]] bool foundAttribute = false; if (ports == EXA_EXB_EAGA_EAGB) { // EXA,EXB,EAGA,EAGB attribute = InstructionAttribute::RSX; foundAttribute = true; @@ -177,7 +180,7 @@ uint8_t A64FXPortAllocator::attributeMapping( } void A64FXPortAllocator::setRSSizeGetter( - std::function&)> rsSizes) { + std::function&)> rsSizes) { rsSizes_ = rsSizes; } diff --git a/src/lib/pipeline/BalancedPortAllocator.cc b/src/lib/pipeline/BalancedPortAllocator.cc index a3db3f85e4..971755e3f5 100644 --- a/src/lib/pipeline/BalancedPortAllocator.cc +++ b/src/lib/pipeline/BalancedPortAllocator.cc @@ -35,10 +35,10 @@ void BalancedPortAllocator::issued(uint16_t port) { assert(weights[port] > 0); weights[port]--; } -void BalancedPortAllocator::deallocate(uint16_t port) { issued(port); }; +void BalancedPortAllocator::deallocate(uint16_t port) { issued(port); } void BalancedPortAllocator::setRSSizeGetter( - std::function&)> rsSizes) { + std::function&)> rsSizes) { rsSizes_ = rsSizes; } diff --git a/src/lib/pipeline/DecodeUnit.cc b/src/lib/pipeline/DecodeUnit.cc index 5bb497e653..cd152be942 100644 --- a/src/lib/pipeline/DecodeUnit.cc +++ b/src/lib/pipeline/DecodeUnit.cc @@ -8,7 +8,7 @@ namespace pipeline { DecodeUnit::DecodeUnit(PipelineBuffer& input, PipelineBuffer>& output, BranchPredictor& predictor) - : input_(input), output_(output), predictor_(predictor){}; + : input_(input), output_(output), predictor_(predictor) {} void DecodeUnit::tick() { // Stall if output buffer is stalled @@ -91,7 +91,7 @@ void DecodeUnit::tick() { bool DecodeUnit::shouldFlush() const { return shouldFlush_; } uint64_t DecodeUnit::getFlushAddress() const { return pc_; } -uint64_t DecodeUnit::getEarlyFlushes() const { return earlyFlushes_; }; +uint64_t DecodeUnit::getEarlyFlushes() const { return earlyFlushes_; } void DecodeUnit::purgeFlushed() { microOps_.clear(); } diff --git a/src/lib/pipeline/DispatchIssueUnit.cc b/src/lib/pipeline/DispatchIssueUnit.cc index afd7390215..b3712715ed 100644 --- a/src/lib/pipeline/DispatchIssueUnit.cc +++ b/src/lib/pipeline/DispatchIssueUnit.cc @@ -30,9 +30,9 @@ DispatchIssueUnit::DispatchIssueUnit( auto reservation_station = config["Reservation-Stations"][i]; // Create ReservationStation struct to be stored ReservationStation rs = { - reservation_station["Size"].as(), + reservation_station["Size"].as(), reservation_station["Dispatch-Rate"].as(), - 0, + 0ul, {}}; // Resize rs port attribute to match what's defined in config file rs.ports.resize(reservation_station["Port-Nums"].num_children()); @@ -42,7 +42,7 @@ DispatchIssueUnit::DispatchIssueUnit( uint16_t issue_port = reservation_station["Port-Nums"][j].as(); rs.ports[j].issuePort = issue_port; // Add port mapping entry, resizing vector if needed - if ((issue_port + 1) > portMapping_.size()) { + if ((size_t)(issue_port + 1) > portMapping_.size()) { portMapping_.resize((issue_port + 1)); } portMapping_[issue_port] = {i, j}; @@ -257,7 +257,7 @@ uint64_t DispatchIssueUnit::getPortBusyStalls() const { return portBusyStalls_; } -void DispatchIssueUnit::getRSSizes(std::vector& sizes) const { +void DispatchIssueUnit::getRSSizes(std::vector& sizes) const { for (auto& rs : reservationStations_) { sizes.push_back(rs.capacity - rs.currentSize); } diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index a74bf66a05..553c8198f4 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -38,10 +38,17 @@ void FetchUnit::tick() { auto outputSlots = output_.getTailSlots(); for (size_t slot = 0; slot < output_.getWidth(); slot++) { auto& macroOp = outputSlots[slot]; - auto bytesRead = isa_.predecode(&(loopBuffer_.front().encoding), - loopBuffer_.front().instructionSize, - loopBuffer_.front().address, macroOp); - assert(bytesRead != 0 && "predecode failure for loop buffer entry"); + auto bytesRead = isa_.predecode( + reinterpret_cast(&(loopBuffer_.front().encoding)), + loopBuffer_.front().instructionSize, loopBuffer_.front().address, + macroOp); + + if (bytesRead == 0) { + std::cout << "[SimEng:FetchUnit] Predecode returned 0 bytes while loop " + "buffer supplying" + << std::endl; + exit(1); + } // Set prediction to recorded value during loop buffer filling if (macroOp[0]->isBranch()) { @@ -55,7 +62,7 @@ void FetchUnit::tick() { return; } - // Pointer to the instruction data to decode from + // Const pointer to the instruction data to decode from const uint8_t* buffer; uint16_t bufferOffset; @@ -106,6 +113,10 @@ void FetchUnit::tick() { buffer = fetchBuffer_; // Decoding should start from the beginning of the fetchBuffer_. bufferOffset = 0; + } else { + // There is already enough data in the fetch buffer, so use that + buffer = fetchBuffer_; + bufferOffset = 0; } } else { // There is already enough data in the fetch buffer, so use that diff --git a/src/lib/pipeline/LoadStoreQueue.cc b/src/lib/pipeline/LoadStoreQueue.cc index f849f568bf..c262267bd5 100644 --- a/src/lib/pipeline/LoadStoreQueue.cc +++ b/src/lib/pipeline/LoadStoreQueue.cc @@ -36,7 +36,7 @@ LoadStoreQueue::LoadStoreQueue( storeBandwidth_(storeBandwidth), totalLimit_(permittedRequests), // Set per-cycle limits for each request type - reqLimits_{permittedLoads, permittedStores} {}; + reqLimits_{permittedLoads, permittedStores} {} LoadStoreQueue::LoadStoreQueue( unsigned int maxLoadQueueSpace, unsigned int maxStoreQueueSpace, @@ -59,7 +59,7 @@ LoadStoreQueue::LoadStoreQueue( storeBandwidth_(storeBandwidth), totalLimit_(permittedRequests), // Set per-cycle limits for each request type - reqLimits_{permittedLoads, permittedStores} {}; + reqLimits_{permittedLoads, permittedStores} {} unsigned int LoadStoreQueue::getLoadQueueSpace() const { if (combined_) { diff --git a/src/lib/pipeline/M1PortAllocator.cc b/src/lib/pipeline/M1PortAllocator.cc index a8705d9ba7..94a2f18563 100644 --- a/src/lib/pipeline/M1PortAllocator.cc +++ b/src/lib/pipeline/M1PortAllocator.cc @@ -20,11 +20,12 @@ uint16_t M1PortAllocator::allocate(const std::vector& ports) { uint16_t bestWeight = 0xFFFF; uint16_t bestRSQueueSize = 0xFFFF; - bool foundRS = false; + // Only used in assertions so produces warning in release mode + [[maybe_unused]] bool foundRS = false; - // Update the the reference for number of free spaces in the reservation + // Update the reference for number of free spaces in the reservation // stations - std::vector rsFreeSpaces; + rsFreeSpaces.clear(); rsSizes_(rsFreeSpaces); for (const auto& portIndex : ports) { @@ -58,10 +59,10 @@ void M1PortAllocator::issued(uint16_t port) { weights[port]--; } -void M1PortAllocator::deallocate(uint16_t port) { issued(port); }; +void M1PortAllocator::deallocate(uint16_t port) { issued(port); } void M1PortAllocator::setRSSizeGetter( - std::function&)> rsSizes) { + std::function&)> rsSizes) { rsSizes_ = rsSizes; } diff --git a/src/lib/pipeline/RegisterAliasTable.cc b/src/lib/pipeline/RegisterAliasTable.cc index 23bcac3980..2a67585831 100644 --- a/src/lib/pipeline/RegisterAliasTable.cc +++ b/src/lib/pipeline/RegisterAliasTable.cc @@ -39,7 +39,7 @@ RegisterAliasTable::RegisterAliasTable( historyTable_[type].resize(physCount); destinationTable_[type].resize(physCount); } -}; +} Register RegisterAliasTable::getMapping(Register architectural) const { // Asserts to ensure mapping isn't attempted for an out-of-bound index (i.e. diff --git a/src/lib/pipeline/ReorderBuffer.cc b/src/lib/pipeline/ReorderBuffer.cc index 2a3e7dd1ff..32889bf93e 100644 --- a/src/lib/pipeline/ReorderBuffer.cc +++ b/src/lib/pipeline/ReorderBuffer.cc @@ -8,7 +8,7 @@ namespace simeng { namespace pipeline { ReorderBuffer::ReorderBuffer( - unsigned int maxSize, RegisterAliasTable& rat, LoadStoreQueue& lsq, + uint32_t maxSize, RegisterAliasTable& rat, LoadStoreQueue& lsq, std::function&)> raiseException, std::function sendLoopBoundary, BranchPredictor& predictor, uint16_t loopBufSize, @@ -36,18 +36,20 @@ void ReorderBuffer::reserve(const std::shared_ptr& insn) { void ReorderBuffer::commitMicroOps(uint64_t insnId) { if (buffer_.size()) { size_t index = 0; - int firstOp = -1; + uint64_t firstOp = UINT64_MAX; bool validForCommit = false; + bool foundFirstInstance = false; // Find first instance of uop belonging to macro-op instruction for (; index < buffer_.size(); index++) { if (buffer_[index]->getInstructionId() == insnId) { firstOp = index; + foundFirstInstance = true; break; } } - if (firstOp > -1) { + if (foundFirstInstance) { // If found, see if all uops are committable for (; index < buffer_.size(); index++) { if (buffer_[index]->getInstructionId() != insnId) break; @@ -60,6 +62,7 @@ void ReorderBuffer::commitMicroOps(uint64_t insnId) { } if (!validForCommit) return; + assert(firstOp != UINT64_MAX && "firstOp hasn't been populated"); // No early return thus all uops are committable for (; firstOp < buffer_.size(); firstOp++) { if (buffer_[firstOp]->getInstructionId() != insnId) break; @@ -91,7 +94,7 @@ unsigned int ReorderBuffer::commit(uint64_t maxCommitSize) { } const auto& destinations = uop->getDestinationRegisters(); - for (int i = 0; i < destinations.size(); i++) { + for (size_t i = 0; i < destinations.size(); i++) { rat_.commit(destinations[i]); } diff --git a/src/tools/simeng/CMakeLists.txt b/src/tools/simeng/CMakeLists.txt index 0c01bba1ad..c8de0d34a9 100644 --- a/src/tools/simeng/CMakeLists.txt +++ b/src/tools/simeng/CMakeLists.txt @@ -9,4 +9,4 @@ endif() target_include_directories(simeng PUBLIC ${PROJECT_SOURCE_DIR}/src/lib) target_link_libraries(simeng libsimeng) -install(TARGETS simeng DESTINATION bin) +install(TARGETS simeng DESTINATION bin) \ No newline at end of file diff --git a/src/tools/simeng/main.cc b/src/tools/simeng/main.cc index cf2c087544..68ec40e86d 100644 --- a/src/tools/simeng/main.cc +++ b/src/tools/simeng/main.cc @@ -63,11 +63,16 @@ int main(int argc, char** argv) { int numberofArgs = argc - 3; executableArgs = std::vector(startOfArgs, startOfArgs + numberofArgs); + } else { + // Use the default program if not + configFilePath = DEFAULT_STR; + executablePath = SIMENG_SOURCE_DIR "/SimEngDefaultProgram"; } } else { // Without a config file, no executable can be supplied so pass default - // (empty) values for executable information + // values for executable information configFilePath = DEFAULT_STR; + executablePath = SIMENG_SOURCE_DIR "/SimEngDefaultProgram"; } coreInstance = diff --git a/sst/Assemble.cc b/sst/Assemble.cc index 57371a9548..796e311ddb 100644 --- a/sst/Assemble.cc +++ b/sst/Assemble.cc @@ -195,5 +195,5 @@ void Assembler::assemble(const char* source, const char* triple) { } #endif -char* Assembler::getAssembledSource() { return reinterpret_cast(code_); } +uint8_t* Assembler::getAssembledSource() { return code_; } size_t Assembler::getAssembledSourceSize() { return codeSize_; } diff --git a/sst/SimEngCoreWrapper.cc b/sst/SimEngCoreWrapper.cc index b33af204e4..66ff11e54c 100644 --- a/sst/SimEngCoreWrapper.cc +++ b/sst/SimEngCoreWrapper.cc @@ -257,7 +257,7 @@ void SimEngCoreWrapper::initialiseHeapData() { void SimEngCoreWrapper::fabricateSimEngCore() { output_.verbose(CALL_INFO, 1, 0, "Setting up SimEng Core\n"); - char* assembled_source = NULL; + uint8_t* assembled_source = NULL; size_t assembled_source_size = 0; if (assembleWithSource_) { output_.verbose(CALL_INFO, 1, 0, diff --git a/sst/include/Assemble.hh b/sst/include/Assemble.hh index 93b7a999ae..b49e07fe9c 100644 --- a/sst/include/Assemble.hh +++ b/sst/include/Assemble.hh @@ -28,7 +28,7 @@ class Assembler { ~Assembler(); /** Returns the assembled source as a char array. */ - char* getAssembledSource(); + uint8_t* getAssembledSource(); /** Returns the size of the assembled source. */ size_t getAssembledSourceSize(); diff --git a/sst/test/include/framework/expression.hh b/sst/test/include/framework/expression.hh index fa0cdae03e..2ecd7875b3 100644 --- a/sst/test/include/framework/expression.hh +++ b/sst/test/include/framework/expression.hh @@ -158,7 +158,7 @@ class LhsExpr : public BaseExpr { /** * ExprBuilder struct exposes a operator which is used to instantiate an - * LhsExpr of type T without having to explictly define the template argument. + * LhsExpr of type T without having to explicitly define the template argument. */ struct ExprBuilder { template > diff --git a/sst/test/include/framework/macros/eval.hh b/sst/test/include/framework/macros/eval.hh index 2c47629c86..69579e894b 100644 --- a/sst/test/include/framework/macros/eval.hh +++ b/sst/test/include/framework/macros/eval.hh @@ -6,11 +6,11 @@ // This MACRO defines the source code each expression expands into. This MACRO // also adds the line number on which this MACRO is defined in the source code. -#define GENERIC_EXPECT_WITH_LINE(A, OP, B, line, SRC) \ - { \ - ExpressionHandler handler = ExpressionHandler(); \ - handler.handleExpression(ExprBuilder() << A OP B, SRC, \ - static_cast(line)); \ +#define GENERIC_EXPECT_WITH_LINE(A, OP, B, line, SRC) \ + { \ + ExpressionHandler handler = ExpressionHandler(); \ + handler.handleExpression((ExprBuilder() << A) OP B, SRC, \ + static_cast(line)); \ } // This MACRO defines the source code each String expression expands into. This diff --git a/sst/test/include/framework/runner.hh b/sst/test/include/framework/runner.hh index 2ec182c4af..75ef7dee4b 100644 --- a/sst/test/include/framework/runner.hh +++ b/sst/test/include/framework/runner.hh @@ -21,14 +21,6 @@ class Runner { Runner() {} /** Method used to run the test(s) inside a runner. */ virtual void run(){}; - /** - * Returns the current executing TestContext. - * The TestContext for a Group changes everytime a new test is run - */ - virtual std::unique_ptr& getCurrContext() { - std::unique_ptr ptr = std::make_unique(); - return ptr; - }; }; /** GroupConfig used to provide configuration options to a Group. */ @@ -178,9 +170,6 @@ class Group : public Runner { return true; }; - /** Returns the TestContext of the current executing test case. */ - std::unique_ptr& getCurrContext() { return ctx_; }; - /** * This method returns a reference of GroupConfig. This method gets overriden * by TEST_GROUP Macro with the config defined in the source code. diff --git a/test/integration/CMakeLists.txt b/test/integration/CMakeLists.txt index f2db19f570..1abf3dc3e0 100644 --- a/test/integration/CMakeLists.txt +++ b/test/integration/CMakeLists.txt @@ -8,5 +8,6 @@ target_include_directories(integrationtests PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) target_include_directories(integrationtests PUBLIC ${PROJECT_SOURCE_DIR}/src/lib) target_link_libraries(integrationtests libsimeng) target_link_libraries(integrationtests gmock_main) +target_compile_options(integrationtests PRIVATE ${SIMENG_COMPILE_OPTIONS}) add_test(NAME integration_tests COMMAND integrationtests) diff --git a/test/regression/RegressionTest.cc b/test/regression/RegressionTest.cc index f3e3f4a5f3..d4bf8e3a42 100644 --- a/test/regression/RegressionTest.cc +++ b/test/regression/RegressionTest.cc @@ -49,7 +49,7 @@ void RegressionTest::run(const char* source, const char* triple, // The created process image can be accessed via a shared_ptr // returned by the getProcessImage method. process_ = std::make_unique( - simeng::span(reinterpret_cast(code_), codeSize_)); + simeng::span(reinterpret_cast(code_), codeSize_)); ASSERT_TRUE(process_->isValid()); uint64_t entryPoint = process_->getEntryPoint(); diff --git a/test/regression/RegressionTest.hh b/test/regression/RegressionTest.hh index f40a692fd7..86c3252c29 100644 --- a/test/regression/RegressionTest.hh +++ b/test/regression/RegressionTest.hh @@ -8,7 +8,20 @@ #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCCodeEmitter.h" + +#if defined(__clang__) +// Prevent errors due to warnings in included file when using clang +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wall" +#endif + #include "llvm/MC/MCContext.h" + +#if defined(__clang__) +// Allow errors again +#pragma clang diagnostic pop +#endif + #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCObjectWriter.h" diff --git a/test/regression/aarch64/AArch64RegressionTest.hh b/test/regression/aarch64/AArch64RegressionTest.hh index 5fe7d98a7d..70507408b8 100644 --- a/test/regression/aarch64/AArch64RegressionTest.hh +++ b/test/regression/aarch64/AArch64RegressionTest.hh @@ -4,7 +4,7 @@ #include "simeng/arch/aarch64/Architecture.hh" #include "simeng/arch/aarch64/Instruction.hh" -static const char* AARCH64_ADDITIONAL_CONFIG = R"YAML( +[[maybe_unused]] static const char* AARCH64_ADDITIONAL_CONFIG = R"YAML( { Core: { @@ -367,13 +367,13 @@ class AArch64RegressionTest : public RegressionTest { /** Generate an array representing a NEON register from a source vector and a * number of elements defined by a number of bytes used. */ template - std::array fillNeon(std::vector src, - int num_bytes) const { + std::array fillNeon(const std::vector& src, + uint32_t num_bytes) const { // Create array to be returned and fill with a default value of 0 std::array generatedArray; generatedArray.fill(0); // Fill array by cycling through source elements - for (int i = 0; i < (num_bytes / sizeof(T)); i++) { + for (size_t i = 0; i < (num_bytes / sizeof(T)); i++) { generatedArray[i] = src[i % src.size()]; } return generatedArray; @@ -406,7 +406,7 @@ class AArch64RegressionTest : public RegressionTest { std::array generatedArray; generatedArray.fill(0); // Fill array by adding an increasing offset value to the base value - for (int i = 0; i < (num_bytes / sizeof(T)); i++) { + for (size_t i = 0; i < (num_bytes / sizeof(T)); i++) { generatedArray[i] = base + (i * offset); } return generatedArray; diff --git a/test/regression/aarch64/CMakeLists.txt b/test/regression/aarch64/CMakeLists.txt index 648449f590..5746e78495 100644 --- a/test/regression/aarch64/CMakeLists.txt +++ b/test/regression/aarch64/CMakeLists.txt @@ -31,9 +31,10 @@ target_include_directories(regression-aarch64 PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries(regression-aarch64 regression-test-base) +target_compile_options(regression-aarch64 PRIVATE ${SIMENG_COMPILE_OPTIONS}) # Define a macro so that tests can find data files target_compile_definitions(regression-aarch64 PRIVATE "SIMENG_AARCH64_TEST_ROOT=\"${CMAKE_CURRENT_SOURCE_DIR}\"") -add_test(NAME regression-aarch64-test COMMAND regression-aarch64) +add_test(NAME regression-aarch64-test COMMAND regression-aarch64) \ No newline at end of file diff --git a/test/regression/aarch64/Exception.cc b/test/regression/aarch64/Exception.cc index ce1bf59688..1c90371ddc 100644 --- a/test/regression/aarch64/Exception.cc +++ b/test/regression/aarch64/Exception.cc @@ -292,7 +292,7 @@ TEST_P(Exception, svcr) { smstop smstart )"); - for (int i = 0; i < (SVL / 8); i++) { + for (uint64_t i = 0; i < (SVL / 8); i++) { CHECK_MAT_ROW(ARM64_REG_ZA, i, uint32_t, fillNeon({0}, SVL / 8)); } @@ -365,7 +365,7 @@ TEST_P(Exception, svcr) { msr svcr, x5 msr svcr, x4 )"); - for (int i = 0; i < (SVL / 8); i++) { + for (uint64_t i = 0; i < (SVL / 8); i++) { CHECK_MAT_ROW(ARM64_REG_ZA, i, uint32_t, fillNeon({0}, SVL / 8)); } } diff --git a/test/regression/aarch64/Syscall.cc b/test/regression/aarch64/Syscall.cc index e002c97d8e..0866c278e2 100644 --- a/test/regression/aarch64/Syscall.cc +++ b/test/regression/aarch64/Syscall.cc @@ -187,7 +187,13 @@ TEST_P(Syscall, faccessat) { unlink(filepath); char abs_filepath[LINUX_PATH_MAX]; - realpath(SIMENG_AARCH64_TEST_ROOT "/data/input.txt", abs_filepath); + if (!realpath(SIMENG_AARCH64_TEST_ROOT "/data/input.txt", abs_filepath)) { + // Something went wrong + std::cerr << "[SimEng:syscall] realpath failed with errno = " << errno + << std::endl; + exit(EXIT_FAILURE); + } + initialHeapData_.resize(strlen(abs_filepath) + 1); // Copy abs_filepath to heap memcpy(initialHeapData_.data(), abs_filepath, strlen(abs_filepath) + 1); @@ -213,7 +219,12 @@ TEST_P(Syscall, faccessat) { // Check syscall works using dirfd instead of AT_FDCWD const char file[] = "input.txt\0"; char dirPath[LINUX_PATH_MAX]; - realpath(SIMENG_AARCH64_TEST_ROOT "/data/\0", dirPath); + if (!realpath(SIMENG_AARCH64_TEST_ROOT "/data/\0", dirPath)) { + // Something went wrong + std::cerr << "[SimEng:syscall] realpath failed with errno = " << errno + << std::endl; + exit(EXIT_FAILURE); + } initialHeapData_.resize(strlen(dirPath) + strlen(file) + 2); // Copy dirPath to heap @@ -436,14 +447,14 @@ TEST_P(Syscall, file_read) { // Check result of readv operations const char refReadv[] = "ABCD\0UV\0EFGH\0\0\0\0MNOPQRST"; char* dataReadv = processMemory_ + process_->getHeapStart(); - for (int i = 0; i < strlen(refReadv); i++) { + for (size_t i = 0; i < strlen(refReadv); i++) { EXPECT_EQ(dataReadv[i], refReadv[i]) << "at index i=" << i << '\n'; } // Check result of read operation const char refRead[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; char* dataRead = processMemory_ + process_->getInitialStackPointer() - 64; - for (int i = 0; i < strlen(refRead); i++) { + for (size_t i = 0; i < strlen(refRead); i++) { EXPECT_EQ(dataRead[i], refRead[i]) << "at index i=" << i << '\n'; } } @@ -583,11 +594,10 @@ TEST_P(Syscall, filenotfound) { // Test that readlinkat works for supported cases TEST_P(Syscall, readlinkat) { const char path[] = "/proc/self/exe"; - // Get current directory and append the default program's comannd line - // argument 0 value - char cwd[LINUX_PATH_MAX]; - getcwd(cwd, LINUX_PATH_MAX); - std::string reference = std::string(cwd) + std::string("/Default"); + + std::string reference = + SIMENG_SOURCE_DIR + std::string("/SimEngDefaultProgram"); + // Copy path to heap initialHeapData_.resize(strlen(path) + reference.size() + 1); memcpy(initialHeapData_.data(), path, strlen(path) + 1); @@ -610,7 +620,7 @@ TEST_P(Syscall, readlinkat) { EXPECT_EQ(getGeneralRegister(0), reference.size()); char* data = processMemory_ + process_->getHeapStart() + 15; - for (int i = 0; i < reference.size(); i++) { + for (size_t i = 0; i < reference.size(); i++) { EXPECT_EQ(data[i], reference.c_str()[i]) << "at index i=" << i << '\n'; } } @@ -719,7 +729,12 @@ TEST_P(Syscall, newfstatat) { // Check syscall works using dirfd instead of AT_FDCWD const char file[] = "input.txt\0"; char dirPath[LINUX_PATH_MAX]; - realpath(SIMENG_AARCH64_TEST_ROOT "/data/\0", dirPath); + if (!realpath(SIMENG_AARCH64_TEST_ROOT "/data/\0", dirPath)) { + // Something went wrong + std::cerr << "[SimEng:syscall] realpath failed with errno = " << errno + << std::endl; + exit(EXIT_FAILURE); + } initialHeapData_.resize(128 + strlen(dirPath) + strlen(file) + 2); // Copy dirPath to heap @@ -1094,24 +1109,24 @@ TEST_P(Syscall, uname) { // Check utsname struct in memory char* data = processMemory_ + process_->getHeapStart(); const char sysname[] = "Linux"; - for (int i = 0; i < strlen(sysname); i++) EXPECT_EQ(data[i], sysname[i]); + for (size_t i = 0; i < strlen(sysname); i++) EXPECT_EQ(data[i], sysname[i]); // Add 65 to data pointer for reserved length of each string field in Linux data += 65; const char nodename[] = "simeng.hpc.cs.bris.ac.uk"; - for (int i = 0; i < strlen(nodename); i++) EXPECT_EQ(data[i], nodename[i]); + for (size_t i = 0; i < strlen(nodename); i++) EXPECT_EQ(data[i], nodename[i]); data += 65; const char release[] = "4.14.0"; - for (int i = 0; i < strlen(release); i++) EXPECT_EQ(data[i], release[i]); + for (size_t i = 0; i < strlen(release); i++) EXPECT_EQ(data[i], release[i]); data += 65; const char version[] = "#1 SimEng Mon Apr 29 16:28:37 UTC 2019"; - for (int i = 0; i < strlen(version); i++) EXPECT_EQ(data[i], version[i]); + for (size_t i = 0; i < strlen(version); i++) EXPECT_EQ(data[i], version[i]); data += 65; const char machine[] = "aarch64"; - for (int i = 0; i < strlen(machine); i++) EXPECT_EQ(data[i], machine[i]); + for (size_t i = 0; i < strlen(machine); i++) EXPECT_EQ(data[i], machine[i]); } TEST_P(Syscall, getrusage) { diff --git a/test/regression/aarch64/instructions/neon.cc b/test/regression/aarch64/instructions/neon.cc index 8286168110..e23573be9f 100644 --- a/test/regression/aarch64/instructions/neon.cc +++ b/test/regression/aarch64/instructions/neon.cc @@ -719,7 +719,7 @@ TEST_P(InstNeon, cmeq) { TEST_P(InstNeon, cmhs) { // cmhs vd.16b, vn.16b, vm.16b initialHeapData_.resize(32); - int8_t* heap = reinterpret_cast(initialHeapData_.data()); + uint8_t* heap = initialHeapData_.data(); // v0 heap[0] = 0; diff --git a/test/regression/aarch64/instructions/sme.cc b/test/regression/aarch64/instructions/sme.cc index af209949b2..e344cc14ee 100644 --- a/test/regression/aarch64/instructions/sme.cc +++ b/test/regression/aarch64/instructions/sme.cc @@ -70,7 +70,7 @@ TEST_P(InstSme, fmopa) { fmopa za2.s, p0/m, p2/m, z3.s, z4.s )"); - for (int i = 0; i < (SVL / 32); i++) { + for (uint64_t i = 0; i < (SVL / 32); i++) { CHECK_MAT_ROW(ARM64_REG_ZAS0, i, float, fillNeon({10.0f}, (SVL / 8))); CHECK_MAT_ROW(ARM64_REG_ZAS2, i, float, @@ -98,7 +98,7 @@ TEST_P(InstSme, fmopa) { fmopa za2.d, p0/m, p2/m, z3.d, z4.d )"); - for (int i = 0; i < (SVL / 64); i++) { + for (uint64_t i = 0; i < (SVL / 64); i++) { CHECK_MAT_ROW(ARM64_REG_ZAD0, i, double, fillNeon({10.0}, (SVL / 8))); CHECK_MAT_ROW(ARM64_REG_ZAD2, i, double, @@ -299,7 +299,7 @@ TEST_P(InstSme, st1d) { st1d {za0h.d[w12, 0]}, p0, [sp, x1, lsl #3] st1d {za1h.d[w12, 1]}, p0, [x4] )"); - for (int i = 0; i < (SVL / 64); i++) { + for (uint64_t i = 0; i < (SVL / 64); i++) { EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4095 + (i * 8)), src[i % 2]); @@ -329,7 +329,7 @@ TEST_P(InstSme, st1d) { ld1d {za1h.d[w13, 1]}, p1/z, [x0, x3, lsl #3] st1d {za1h.d[w13, 1]}, p1, [x5, x3, lsl #3] )"); - for (int i = 0; i < (SVL / 128); i++) { + for (uint64_t i = 0; i < (SVL / 128); i++) { EXPECT_EQ(getMemoryValue(800 + (i * 8)), src[i % 2]); EXPECT_EQ(getMemoryValue(800 + 16 + (i * 8)), src[i % 2]); } @@ -360,7 +360,7 @@ TEST_P(InstSme, st1d) { st1d {za0v.d[w12, 0]}, p0, [sp, x1, lsl #3] st1d {za1v.d[w12, 1]}, p0, [x4] )"); - for (int i = 0; i < (SVL / 64); i++) { + for (uint64_t i = 0; i < (SVL / 64); i++) { EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4095 + (i * 8)), src_vert[i % 2]); @@ -390,7 +390,7 @@ TEST_P(InstSme, st1d) { ld1d {za1v.d[w13, 1]}, p1/z, [x0, x3, lsl #3] st1d {za1v.d[w13, 1]}, p1, [x5, x3, lsl #3] )"); - for (int i = 0; i < (SVL / 128); i++) { + for (uint64_t i = 0; i < (SVL / 128); i++) { EXPECT_EQ(getMemoryValue(800 + (i * 8)), src_vert[i % 2]); EXPECT_EQ(getMemoryValue(800 + 16 + (i * 8)), src_vert[i % 2]); } @@ -423,7 +423,7 @@ TEST_P(InstSme, st1w) { st1w {za0h.s[w12, 0]}, p0, [sp, x1, lsl #2] st1w {za1h.s[w12, 1]}, p0, [x4] )"); - for (int i = 0; i < (SVL / 32); i++) { + for (uint64_t i = 0; i < (SVL / 32); i++) { EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4095 + (i * 4)), src[i % 4]); @@ -452,7 +452,7 @@ TEST_P(InstSme, st1w) { ld1w {za1h.s[w12, 2]}, p1/z, [x0, x3, lsl #2] st1w {za1h.s[w12, 2]}, p1, [x5, x3, lsl #2] )"); - for (int i = 0; i < (SVL / 64); i++) { + for (uint64_t i = 0; i < (SVL / 64); i++) { EXPECT_EQ(getMemoryValue(800 + (i * 4)), src[i % 4]); EXPECT_EQ(getMemoryValue(800 + 16 + (i * 4)), src[i % 4]); } @@ -484,7 +484,7 @@ TEST_P(InstSme, st1w) { st1w {za0v.s[w12, 0]}, p0, [sp, x1, lsl #2] st1w {za1v.s[w12, 1]}, p0, [x4] )"); - for (int i = 0; i < (SVL / 32); i++) { + for (uint64_t i = 0; i < (SVL / 32); i++) { EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4095 + (i * 4)), src_vert[i % 4]); @@ -513,7 +513,7 @@ TEST_P(InstSme, st1w) { ld1w {za1v.s[w12, 2]}, p1/z, [x0, x3, lsl #2] st1w {za1v.s[w12, 2]}, p1, [x5, x3, lsl #2] )"); - for (int i = 0; i < (SVL / 64); i++) { + for (uint64_t i = 0; i < (SVL / 64); i++) { EXPECT_EQ(getMemoryValue(800 + (i * 4)), src_vert[i % 4]); EXPECT_EQ(getMemoryValue(800 + 16 + (i * 4)), src_vert[i % 4]); } @@ -525,7 +525,7 @@ TEST_P(InstSme, zero) { zero {za} )"); - for (int i = 0; i < (SVL / 8); i++) { + for (uint64_t i = 0; i < (SVL / 8); i++) { CHECK_MAT_ROW(ARM64_REG_ZA, i, uint64_t, fillNeon({0}, SVL / 8)); } @@ -561,7 +561,7 @@ TEST_P(InstSme, zero) { zero {za0.s, za2.s} )"); - for (int i = 0; i < (SVL / 32); i++) { + for (uint64_t i = 0; i < (SVL / 32); i++) { CHECK_MAT_ROW(ARM64_REG_ZAS0, i, uint32_t, fillNeon({0}, SVL / 8)); CHECK_MAT_ROW(ARM64_REG_ZAS2, i, uint32_t, diff --git a/test/regression/aarch64/instructions/sve.cc b/test/regression/aarch64/instructions/sve.cc index 23ffd1823a..702979b2dd 100644 --- a/test/regression/aarch64/instructions/sve.cc +++ b/test/regression/aarch64/instructions/sve.cc @@ -1883,7 +1883,7 @@ TEST_P(InstSve, eor) { CHECK_PREDICATE(2, uint64_t, res_p2); CHECK_PREDICATE(3, uint64_t, {0, 0, 0, 0}); auto res_p4 = fillPred(VL / 8, {0}, 1); - for (int i = 0; i < (VL / 8); i++) { + for (uint64_t i = 0; i < (VL / 8); i++) { uint64_t shifted_active = 1ull << (i % 64); res_p4[i / 64] |= (p1[i / 64] & shifted_active) == shifted_active ? 0 : shifted_active; @@ -1954,7 +1954,7 @@ TEST_P(InstSve, eor) { )"); auto res_0 = fillNeon({0}, VL / 8); int val = 8; - for (int i = 0; i < (VL / 8); i++) { + for (uint64_t i = 0; i < (VL / 8); i++) { res_0[i] = val ^ 15; val += 2; } @@ -1963,7 +1963,7 @@ TEST_P(InstSve, eor) { auto res_3 = fillNeon({0}, VL / 8); val = 8; - for (int i = 0; i < (VL / 16); i++) { + for (uint64_t i = 0; i < (VL / 16); i++) { res_3[i] = val ^ 15; val += 2; } @@ -1972,7 +1972,7 @@ TEST_P(InstSve, eor) { auto res_6 = fillNeon({0}, VL / 8); val = 8; - for (int i = 0; i < (VL / 32); i++) { + for (uint64_t i = 0; i < (VL / 32); i++) { res_6[i] = val ^ 15; val += 2; } @@ -1981,7 +1981,7 @@ TEST_P(InstSve, eor) { auto res_9 = fillNeon({0}, VL / 8); val = 8; - for (int i = 0; i < (VL / 64); i++) { + for (uint64_t i = 0; i < (VL / 64); i++) { res_9[i] = val ^ 15; val += 2; } @@ -2802,7 +2802,7 @@ TEST_P(InstSve, fadda) { )"); float fresultA = 2.75f; float fresultB = 2.75f; - for (int i = 0; i < VL / 64; i++) { + for (uint64_t i = 0; i < VL / 64; i++) { fresultA += fsrc[i % 8]; fresultB += fsrc[(i + VL / 64) % 8]; } @@ -2841,7 +2841,7 @@ TEST_P(InstSve, fadda) { )"); double resultA = 2.75; double resultB = 2.75; - for (int i = 0; i < VL / 128; i++) { + for (uint64_t i = 0; i < VL / 128; i++) { resultA += dsrc[i % 8]; resultB += dsrc[(i + VL / 128) % 8]; } @@ -3800,8 +3800,9 @@ TEST_P(InstSve, fmla_indexed) { )"); std::vector resultsA; std::vector resultsB; - float itemA; - float itemB; + // Redundant initialisation to prevent warnings + float itemA = 0.f; + float itemB = 0.f; for (size_t i = 0; i < (VL / 32); i++) { if (i % 4 == 0) { itemA = 5.0f + (5.0f * static_cast(i + 1)); @@ -3829,8 +3830,9 @@ TEST_P(InstSve, fmla_indexed) { )"); std::vector resultsC; std::vector resultsD; - double itemC; - double itemD; + // Redundant initialisation to prevent warnings + double itemC = 0.f; + double itemD = 0.f; for (size_t i = 0; i < (VL / 64); i++) { if (i % 2 == 0) { itemC = 5.0 + (5.0 * static_cast(i)); @@ -6196,16 +6198,16 @@ TEST_P(InstSve, st1b) { st1b {z1.b}, p1, [sp, #4, mul vl] )"); - for (int i = 0; i < (VL / 8); i++) { + for (uint64_t i = 0; i < (VL / 8); i++) { EXPECT_EQ( getMemoryValue(process_->getInitialStackPointer() - 4095 + i), src[i % 16]); } - for (int i = 0; i < (VL / 16); i++) { + for (uint64_t i = 0; i < (VL / 16); i++) { EXPECT_EQ(getMemoryValue(4 * (VL / 16) + i), src[i % 16]); } uint64_t base = process_->getInitialStackPointer() - 8190 + 4 * (VL / 8); - for (int i = 0; i < (VL / 16); i++) { + for (uint64_t i = 0; i < (VL / 16); i++) { EXPECT_EQ(getMemoryValue(base + i), src[i % 16]); } } @@ -6362,19 +6364,19 @@ TEST_P(InstSve, st1d) { st1d {z1.d}, p1, [x2, x3, lsl #3] )"); - for (int i = 0; i < (VL / 64); i++) { + for (uint64_t i = 0; i < (VL / 64); i++) { EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4095 + (i * 8)), src[i % 4]); } - for (int i = 0; i < (VL / 64); i++) { + for (uint64_t i = 0; i < (VL / 64); i++) { EXPECT_EQ(getMemoryValue(65792 + (i * 8)), src[i % 4]); } std::rotate(src.begin(), src.begin() + 2, src.end()); - for (int i = 0; i < (VL / 128); i++) { + for (uint64_t i = 0; i < (VL / 128); i++) { EXPECT_EQ(getMemoryValue((VL / 128) + 16 + (i * 8)), src[i % 4]); } - for (int i = 0; i < (VL / 128); i++) { + for (uint64_t i = 0; i < (VL / 128); i++) { EXPECT_EQ(getMemoryValue((VL / 128) + (VL / 2) + (i * 8)), src[i % 4]); } @@ -6402,7 +6404,7 @@ TEST_P(InstSve, st2d) { st2d {z2.d, z3.d}, p1, [x6, #4, mul vl] )"); - for (int i = 0; i < (VL / 64); i++) { + for (uint64_t i = 0; i < (VL / 64); i++) { EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4095 + (2 * i * 8)), 3); @@ -6412,7 +6414,7 @@ TEST_P(InstSve, st2d) { } int index = 4 * (VL / 64) * 8; - for (int i = 0; i < (VL / 128); i++) { + for (uint64_t i = 0; i < (VL / 128); i++) { EXPECT_EQ(getMemoryValue(300 + index + (2 * i * 8)), 5); EXPECT_EQ(getMemoryValue(300 + index + (2 * i * 8) + 8), 6); } @@ -6507,12 +6509,12 @@ TEST_P(InstSve, st1w) { st1w {z2.s}, p0, [x4] )"); - for (int i = 0; i < (VL / 32); i++) { + for (uint64_t i = 0; i < (VL / 32); i++) { EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4095 + (i * 4)), src[i % 4]); } - for (int i = 0; i < (VL / 32); i++) { + for (uint64_t i = 0; i < (VL / 32); i++) { EXPECT_EQ(getMemoryValue((VL / 8) + (i * 4)), src[i % 4]); } @@ -6535,11 +6537,11 @@ TEST_P(InstSve, st1w) { st1w {z1.s}, p1, [x2, x3, lsl #2] )"); - for (int i = 0; i < (VL / 64); i++) { + for (uint64_t i = 0; i < (VL / 64); i++) { EXPECT_EQ(getMemoryValue((VL / 64) + (VL / 2) + (i * 4)), src[i % 4]); } - for (int i = 0; i < (VL / 64); i++) { + for (uint64_t i = 0; i < (VL / 64); i++) { EXPECT_EQ(getMemoryValue((VL / 64) + 16 + (i * 4)), src[i % 4]); } @@ -6583,7 +6585,7 @@ TEST_P(InstSve, st1w) { std::array srcC = fillNeonCombined( {0xDEADBEEF, 0x12345678, 0x98765432, 0xABCDEF01}, {0ul}, VL / 16); - for (int i = 0; i < (VL / 64); i++) { + for (uint64_t i = 0; i < (VL / 64); i++) { EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4095 + (i * 4)), srcC[i]); @@ -6593,7 +6595,7 @@ TEST_P(InstSve, st1w) { fillNeonCombined( {0xDEADBEEF, 0x12345678, 0x98765432, 0xABCDEF01}, {0xDEADBEEF, 0x12345678, 0x98765432, 0xABCDEF01}, VL / 16); - for (int i = 0; i < (VL / 64); i++) { + for (uint64_t i = 0; i < (VL / 64); i++) { EXPECT_EQ(getMemoryValue(64 + (3 + i) * 4), srcD[i]); } } @@ -6614,7 +6616,7 @@ TEST_P(InstSve, str_predicate) { ldr p0, [x0, #0, mul vl] str p0, [sp, #0, mul vl] )"); - for (int i = 0; i < (VL / 64); i++) { + for (uint64_t i = 0; i < (VL / 64); i++) { EXPECT_EQ( getMemoryValue(process_->getInitialStackPointer() - 4095 + i), 0xFF); @@ -6632,7 +6634,7 @@ TEST_P(InstSve, str_predicate) { ldr p0, [x0, #0, mul vl] str p0, [sp, #1, mul vl] )"); - for (int i = 0; i < (VL / 64); i++) { + for (uint64_t i = 0; i < (VL / 64); i++) { EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - (4095 - (VL / 64)) + i), 0xDE); @@ -6650,7 +6652,7 @@ TEST_P(InstSve, str_predicate) { ldr p0, [x0, #0, mul vl] str p0, [sp, #2, mul vl] )"); - for (int i = 0; i < (VL / 64); i++) { + for (uint64_t i = 0; i < (VL / 64); i++) { EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - (4095 - (VL / 64) * 2) + i), 0x12); @@ -6668,7 +6670,7 @@ TEST_P(InstSve, str_predicate) { ldr p0, [x0, #0, mul vl] str p0, [sp, #3, mul vl] )"); - for (int i = 0; i < (VL / 64); i++) { + for (uint64_t i = 0; i < (VL / 64); i++) { EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - (4095 - (VL / 64) * 3) + i), 0x98); @@ -6697,12 +6699,12 @@ TEST_P(InstSve, str_vector) { str z0, [sp, #0, mul vl] str z1, [x1, #4, mul vl] )"); - for (int i = 0; i < (VL / 64); i++) { + for (uint64_t i = 0; i < (VL / 64); i++) { EXPECT_EQ(getMemoryValue(process_->getInitialStackPointer() - 4095 + (i * 8)), src[i % 8]); } - for (int i = 0; i < (VL / 64); i++) { + for (uint64_t i = 0; i < (VL / 64); i++) { EXPECT_EQ(getMemoryValue((VL / 8) + (VL / 2) + (i * 8)), src[i % 8]); } @@ -6800,7 +6802,7 @@ TEST_P(InstSve, trn1) { std::vector result8; int i1 = 0; int i2 = 10; - for (int i = 0; i < VL / 16; i++) { + for (uint64_t i = 0; i < VL / 16; i++) { result8.push_back(i1); result8.push_back(i2); i1 += 2; @@ -6818,7 +6820,7 @@ TEST_P(InstSve, trn1) { std::vector result16; i1 = 0; i2 = 10; - for (int i = 0; i < VL / 32; i++) { + for (uint64_t i = 0; i < VL / 32; i++) { result16.push_back(i1); result16.push_back(i2); i1 += 2; @@ -6836,7 +6838,7 @@ TEST_P(InstSve, trn1) { std::vector result32; i1 = 0; i2 = 10; - for (int i = 0; i < VL / 64; i++) { + for (uint64_t i = 0; i < VL / 64; i++) { result32.push_back(i1); result32.push_back(i2); i1 += 2; @@ -6854,7 +6856,7 @@ TEST_P(InstSve, trn1) { std::vector result64; i1 = 0; i2 = 10; - for (int i = 0; i < VL / 128; i++) { + for (uint64_t i = 0; i < VL / 128; i++) { result64.push_back(i1); result64.push_back(i2); i1 += 2; @@ -6874,7 +6876,7 @@ TEST_P(InstSve, trn2) { std::vector result8; int i1 = 1; int i2 = 11; - for (int i = 0; i < VL / 16; i++) { + for (uint64_t i = 0; i < VL / 16; i++) { result8.push_back(i1); result8.push_back(i2); i1 += 2; @@ -6892,7 +6894,7 @@ TEST_P(InstSve, trn2) { std::vector result16; i1 = 1; i2 = 11; - for (int i = 0; i < VL / 32; i++) { + for (uint64_t i = 0; i < VL / 32; i++) { result16.push_back(i1); result16.push_back(i2); i1 += 2; @@ -6910,7 +6912,7 @@ TEST_P(InstSve, trn2) { std::vector result32; i1 = 1; i2 = 11; - for (int i = 0; i < VL / 64; i++) { + for (uint64_t i = 0; i < VL / 64; i++) { result32.push_back(i1); result32.push_back(i2); i1 += 2; @@ -6928,7 +6930,7 @@ TEST_P(InstSve, trn2) { std::vector result64; i1 = 1; i2 = 11; - for (int i = 0; i < VL / 128; i++) { + for (uint64_t i = 0; i < VL / 128; i++) { result64.push_back(i1); result64.push_back(i2); i1 += 2; diff --git a/test/regression/riscv/CMakeLists.txt b/test/regression/riscv/CMakeLists.txt index fc2ddab50b..fdc4826d82 100644 --- a/test/regression/riscv/CMakeLists.txt +++ b/test/regression/riscv/CMakeLists.txt @@ -25,9 +25,10 @@ target_include_directories(regression-riscv PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries(regression-riscv regression-test-base) +target_compile_options(regression-riscv PRIVATE ${SIMENG_COMPILE_OPTIONS}) # Define a macro so that tests can find data files target_compile_definitions(regression-riscv PRIVATE "SIMENG_RISCV_TEST_ROOT=\"${CMAKE_CURRENT_SOURCE_DIR}\"") -add_test(NAME regression-riscv-test COMMAND regression-riscv) +add_test(NAME regression-riscv-test COMMAND regression-riscv) \ No newline at end of file diff --git a/test/regression/riscv/RISCVRegressionTest.hh b/test/regression/riscv/RISCVRegressionTest.hh index ac12a8e6cc..56f8f1bcdd 100644 --- a/test/regression/riscv/RISCVRegressionTest.hh +++ b/test/regression/riscv/RISCVRegressionTest.hh @@ -4,7 +4,7 @@ #include "simeng/arch/riscv/Architecture.hh" #include "simeng/arch/riscv/Instruction.hh" -static const char* RISCV_ADDITIONAL_CONFIG = R"YAML( +[[maybe_unused]] static const char* RISCV_ADDITIONAL_CONFIG = R"YAML( { Core: { diff --git a/test/regression/riscv/Syscall.cc b/test/regression/riscv/Syscall.cc index 4302220d30..c40fc5754a 100644 --- a/test/regression/riscv/Syscall.cc +++ b/test/regression/riscv/Syscall.cc @@ -186,7 +186,14 @@ TEST_P(Syscall, faccessat) { unlink(filepath); char abs_filepath[LINUX_PATH_MAX]; - realpath(SIMENG_RISCV_TEST_ROOT "/data/input.txt", abs_filepath); + + if (!realpath(SIMENG_RISCV_TEST_ROOT "/data/input.txt", abs_filepath)) { + // Something went wrong + std::cerr << "[SimEng:syscall] realpath failed with errno = " << errno + << std::endl; + exit(EXIT_FAILURE); + } + initialHeapData_.resize(strlen(abs_filepath) + 1); // Copy abs_filepath to heap memcpy(initialHeapData_.data(), abs_filepath, strlen(abs_filepath) + 1); @@ -212,7 +219,13 @@ TEST_P(Syscall, faccessat) { // Check syscall works using dirfd instead of AT_FDCWD const char file[] = "input.txt\0"; char dirPath[LINUX_PATH_MAX]; - realpath(SIMENG_RISCV_TEST_ROOT "/data/\0", dirPath); + + if (!realpath(SIMENG_RISCV_TEST_ROOT "/data/\0", dirPath)) { + // Something went wrong + std::cerr << "[SimEng:syscall] realpath failed with errno = " << errno + << std::endl; + exit(EXIT_FAILURE); + } initialHeapData_.resize(strlen(dirPath) + strlen(file) + 2); // Copy dirPath to heap @@ -593,11 +606,9 @@ TEST_P(Syscall, filenotfound) { // Test that readlinkat works for supported cases TEST_P(Syscall, readlinkat) { const char path[] = "/proc/self/exe"; - // Get current directory and append the default program's comannd line - // argument 0 value - char cwd[LINUX_PATH_MAX]; - getcwd(cwd, LINUX_PATH_MAX); - std::string reference = std::string(cwd) + std::string("/Default"); + + std::string reference = + SIMENG_SOURCE_DIR + std::string("/SimEngDefaultProgram"); // Copy path to heap initialHeapData_.resize(strlen(path) + reference.size() + 1); memcpy(initialHeapData_.data(), path, strlen(path) + 1); @@ -620,7 +631,7 @@ TEST_P(Syscall, readlinkat) { EXPECT_EQ(getGeneralRegister(10), reference.size()); char* data = processMemory_ + process_->getHeapStart() + 15; - for (int i = 0; i < reference.size(); i++) { + for (size_t i = 0; i < reference.size(); i++) { EXPECT_EQ(data[i], reference.c_str()[i]) << "at index i=" << i << '\n'; } } @@ -729,7 +740,13 @@ TEST_P(Syscall, newfstatat) { // Check syscall works using dirfd instead of AT_FDCWD const char file[] = "input.txt\0"; char dirPath[LINUX_PATH_MAX]; - realpath(SIMENG_RISCV_TEST_ROOT "/data/\0", dirPath); + + if (!realpath(SIMENG_RISCV_TEST_ROOT "/data/\0", dirPath)) { + // Something went wrong + std::cerr << "[SimEng:syscall] realpath failed with errno = " << errno + << std::endl; + exit(EXIT_FAILURE); + } initialHeapData_.resize(128 + strlen(dirPath) + strlen(file) + 2); // Copy dirPath to heap @@ -1119,28 +1136,28 @@ TEST_P(Syscall, uname) { // Check utsname struct in memory char* data = processMemory_ + process_->getHeapStart(); const char sysname[] = "Linux"; - for (int i = 0; i < strlen(sysname); i++) EXPECT_EQ(data[i], sysname[i]); + for (size_t i = 0; i < strlen(sysname); i++) EXPECT_EQ(data[i], sysname[i]); // Add 65 to data pointer for reserved length of each string field in Linux data += 65; const char nodename[] = "fedora-riscv"; - for (int i = 0; i < strlen(nodename); i++) EXPECT_EQ(data[i], nodename[i]); + for (size_t i = 0; i < strlen(nodename); i++) EXPECT_EQ(data[i], nodename[i]); data += 65; const char release[] = "5.5.0-0.rc5.git0.1.1.riscv64.fc32.riscv64"; - for (int i = 0; i < strlen(release); i++) EXPECT_EQ(data[i], release[i]); + for (size_t i = 0; i < strlen(release); i++) EXPECT_EQ(data[i], release[i]); data += 65; const char version[] = "#1 SMP Mon Jan 6 17:31:22 UTC 2020"; - for (int i = 0; i < strlen(version); i++) EXPECT_EQ(data[i], version[i]); + for (size_t i = 0; i < strlen(version); i++) EXPECT_EQ(data[i], version[i]); data += 65; const char machine[] = "riscv64"; - for (int i = 0; i < strlen(machine); i++) EXPECT_EQ(data[i], machine[i]); + for (size_t i = 0; i < strlen(machine); i++) EXPECT_EQ(data[i], machine[i]); data += 65; const char domainname[] = "(none)"; - for (int i = 0; i < strlen(domainname); i++) + for (size_t i = 0; i < strlen(domainname); i++) EXPECT_EQ(data[i], domainname[i]); } diff --git a/test/regression/riscv/instructions/compressed.cc b/test/regression/riscv/instructions/compressed.cc index 4b68edb76f..90335b1d7d 100644 --- a/test/regression/riscv/instructions/compressed.cc +++ b/test/regression/riscv/instructions/compressed.cc @@ -626,7 +626,8 @@ TEST_P(InstCompressed, nop) { )"); EXPECT_EQ(getGeneralRegister(0), 0); EXPECT_EQ(getGeneralRegister(1), 0); - EXPECT_EQ(getGeneralRegister(2), 199840); + EXPECT_EQ(getGeneralRegister(2), + process_->getInitialStackPointer()); EXPECT_EQ(getGeneralRegister(3), 0); EXPECT_EQ(getGeneralRegister(4), 0); EXPECT_EQ(getGeneralRegister(5), 0); @@ -672,7 +673,8 @@ TEST_P(InstCompressed, nop) { // Ensure state hasn't changed except the number of ticks EXPECT_EQ(getGeneralRegister(0), 0); EXPECT_EQ(getGeneralRegister(1), 0); - EXPECT_EQ(getGeneralRegister(2), 199840); + EXPECT_EQ(getGeneralRegister(2), + process_->getInitialStackPointer()); EXPECT_EQ(getGeneralRegister(3), 0); EXPECT_EQ(getGeneralRegister(4), 0); EXPECT_EQ(getGeneralRegister(5), 0); diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index 9e48a10a43..2826cd0030 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -46,5 +46,6 @@ target_include_directories(unittests PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) target_include_directories(unittests PUBLIC ${PROJECT_SOURCE_DIR}/src/lib) target_link_libraries(unittests libsimeng) target_link_libraries(unittests gmock_main) +target_compile_options(unittests PRIVATE ${SIMENG_COMPILE_OPTIONS}) add_test(NAME unit_tests COMMAND unittests) diff --git a/test/unit/MockArchitecture.hh b/test/unit/MockArchitecture.hh index c89e519ef4..5bdeeb9f18 100644 --- a/test/unit/MockArchitecture.hh +++ b/test/unit/MockArchitecture.hh @@ -10,7 +10,7 @@ class MockArchitecture : public arch::Architecture { public: MockArchitecture(kernel::Linux& kernel) : arch::Architecture(kernel) {} MOCK_CONST_METHOD4(predecode, - uint8_t(const void* ptr, uint16_t bytesAvailable, + uint8_t(const uint8_t* ptr, uint16_t bytesAvailable, uint64_t instructionAddress, MacroOp& output)); MOCK_CONST_METHOD1(canRename, bool(Register reg)); MOCK_CONST_METHOD1(getSystemRegisterTag, int32_t(uint16_t reg)); diff --git a/test/unit/MockPortAllocator.hh b/test/unit/MockPortAllocator.hh index 19d7142b74..c09c605f52 100644 --- a/test/unit/MockPortAllocator.hh +++ b/test/unit/MockPortAllocator.hh @@ -13,7 +13,7 @@ class MockPortAllocator : public pipeline::PortAllocator { MOCK_METHOD1(issued, void(uint16_t port)); MOCK_METHOD1(deallocate, void(uint16_t port)); MOCK_METHOD1(setRSSizeGetter, - void(std::function&)> rsSizes)); + void(std::function&)> rsSizes)); MOCK_METHOD0(tick, void()); }; diff --git a/test/unit/OSTest.cc b/test/unit/OSTest.cc index 98681ec177..7636c25395 100644 --- a/test/unit/OSTest.cc +++ b/test/unit/OSTest.cc @@ -12,8 +12,8 @@ class OSTest : public testing::Test { : os(config::SimInfo::getConfig()["CPU-Info"]["Special-File-Dir-Path"] .as()), proc_elf(simeng::kernel::LinuxProcess(cmdLine)), - proc_hex(simeng::span(reinterpret_cast(demoHex), - sizeof(demoHex))) {} + proc_hex(simeng::span(reinterpret_cast(demoHex), + sizeof(demoHex))) {} protected: ConfigInit configInit = ConfigInit( @@ -23,13 +23,16 @@ class OSTest : public testing::Test { const std::vector cmdLine = { SIMENG_SOURCE_DIR "/test/unit/data/stream-aarch64.elf"}; + std::vector defaultCmdLine = {SIMENG_SOURCE_DIR + "/SimEngDefaultProgram"}; + simeng::kernel::Linux os; simeng::kernel::LinuxProcess proc_elf; simeng::kernel::LinuxProcess proc_hex; // A simple program used to test the functionality of creating a process with // a stream of hex instructions. - uint32_t demoHex[7] = { + const uint32_t demoHex[7] = { 0x320C03E0, // orr w0, wzr, #1048576 0x320003E1, // orr w0, wzr, #1 0x71000400, // subs w0, w0, #1 @@ -67,7 +70,22 @@ TEST_F(OSTest, processElf_stackPointer) { TEST_F(OSTest, processHex_stackPointer) { os.createProcess(proc_hex); - EXPECT_EQ(os.getInitialStackPointer(), 1074790240); + // cmdLine[0] length will change depending on the host system so final stack + // pointer needs to be calculated manually + // cmdLineSize + 1 for null seperator + const uint64_t cmdLineSize = defaultCmdLine[0].size() + 1; + // "OMP_NUM_THREADS=1" + 1 for null seperator + const uint64_t envStringsSize = 18; + // Size of initial stack frame as per LinuxProcess.cc:createStack() + // - (17 push_backs) * 8 + // https://www.win.tue.nl/~aeb/linux/hh/stack-layout.html + const uint64_t stackFrameSize = 17 * 8; + // cmd + Env needs +1 for null seperator + const uint64_t stackPointer = + proc_hex.getStackStart() - + kernel::alignToBoundary(cmdLineSize + envStringsSize + 1, 32) - + kernel::alignToBoundary(stackFrameSize, 32); + EXPECT_EQ(os.getInitialStackPointer(), stackPointer); EXPECT_EQ(os.getInitialStackPointer(), proc_hex.getInitialStackPointer()); } diff --git a/test/unit/ProcessTest.cc b/test/unit/ProcessTest.cc index 4689513d2e..c0401da184 100644 --- a/test/unit/ProcessTest.cc +++ b/test/unit/ProcessTest.cc @@ -19,7 +19,7 @@ class ProcessTest : public testing::Test { // Program used when no executable is provided; counts down from // 1024*1024, with an independent `orr` at the start of each branch. - uint32_t demoHex[7] = { + const uint32_t demoHex[7] = { 0x320C03E0, // orr w0, wzr, #1048576 0x320003E1, // orr w0, wzr, #1 0x71000400, // subs w0, w0, #1 @@ -48,9 +48,9 @@ TEST_F(ProcessTest, createProcess_elf) { // Tests createProcess(), isValid(), and getPath() functions. TEST_F(ProcessTest, createProcess_hex) { kernel::LinuxProcess proc = kernel::LinuxProcess( - span(reinterpret_cast(demoHex), sizeof(demoHex))); + span(reinterpret_cast(demoHex), sizeof(demoHex))); EXPECT_TRUE(proc.isValid()); - EXPECT_EQ(proc.getPath(), "Default\0"); + EXPECT_EQ(proc.getPath(), SIMENG_SOURCE_DIR "/SimEngDefaultProgram\0"); } // Tests get{Heap, Stack, Mmap}Start() functions diff --git a/test/unit/SpecialFileDirGenTest.cc b/test/unit/SpecialFileDirGenTest.cc index 745750b90f..993a650235 100644 --- a/test/unit/SpecialFileDirGenTest.cc +++ b/test/unit/SpecialFileDirGenTest.cc @@ -73,7 +73,7 @@ class SpecialFileDirGenTest : public testing::Test { // (i.e. the one defined in the YAML string above) TEST_F(SpecialFileDirGenTest, genAndDelete) { // Make sure files currently do not exist - for (int i = 0; i < allFiles_names_Lines.size(); i++) { + for (size_t i = 0; i < allFiles_names_Lines.size(); i++) { EXPECT_FALSE( std::ifstream(TEST_SPEC_FILE_DIR + std::get<0>(allFiles_names_Lines[i])) .good()); @@ -83,7 +83,7 @@ TEST_F(SpecialFileDirGenTest, genAndDelete) { specFile.GenerateSFDir(); // Validate files exist and are correct - for (int i = 0; i < allFiles_names_Lines.size(); i++) { + for (size_t i = 0; i < allFiles_names_Lines.size(); i++) { EXPECT_TRUE( std::ifstream(TEST_SPEC_FILE_DIR + std::get<0>(allFiles_names_Lines[i])) .good()); @@ -92,7 +92,7 @@ TEST_F(SpecialFileDirGenTest, genAndDelete) { const std::vector& knownLines = std::get<1>(allFiles_names_Lines[i]); std::string line; - int numOfLines = 0; + size_t numOfLines = 0; while (std::getline(file, line)) { if (numOfLines > knownLines.size()) { break; @@ -107,7 +107,7 @@ TEST_F(SpecialFileDirGenTest, genAndDelete) { specFile.RemoveExistingSFDir(); // Make sure files don't exist - for (int i = 0; i < allFiles_names_Lines.size(); i++) { + for (size_t i = 0; i < allFiles_names_Lines.size(); i++) { EXPECT_FALSE( std::ifstream(TEST_SPEC_FILE_DIR + std::get<0>(allFiles_names_Lines[i])) .good()); diff --git a/test/unit/aarch64/ArchitectureTest.cc b/test/unit/aarch64/ArchitectureTest.cc index 7c4f9195a5..7ad5fcacf4 100644 --- a/test/unit/aarch64/ArchitectureTest.cc +++ b/test/unit/aarch64/ArchitectureTest.cc @@ -79,13 +79,13 @@ class AArch64ArchitectureTest : public testing::Test { })YAML"); // fdivr z1.s, p0/m, z1.s, z0.s - std::array validInstrBytes = {0x01, 0x80, 0x8c, 0x65}; - std::array invalidInstrBytes = {0x20, 0x00, 0x02, 0x8c}; + const std::array validInstrBytes = {0x01, 0x80, 0x8c, 0x65}; + const std::array invalidInstrBytes = {0x20, 0x00, 0x02, 0x8c}; std::unique_ptr arch; kernel::Linux kernel; kernel::LinuxProcess process = kernel::LinuxProcess( - span((char*)validInstrBytes.data(), validInstrBytes.size())); + span(validInstrBytes.data(), validInstrBytes.size())); }; TEST_F(AArch64ArchitectureTest, predecode) { @@ -142,7 +142,7 @@ TEST_F(AArch64ArchitectureTest, handleException) { InstructionException::EncodingUnallocated); // Get Core - std::string executablePath = ""; + std::string executablePath = SIMENG_SOURCE_DIR "/SimEngDefaultProgram"; std::vector executableArgs = {}; std::unique_ptr coreInstance = std::make_unique(executablePath, executableArgs); diff --git a/test/unit/aarch64/ExceptionHandlerTest.cc b/test/unit/aarch64/ExceptionHandlerTest.cc index 3bf1ebfa66..b64e1bfbee 100644 --- a/test/unit/aarch64/ExceptionHandlerTest.cc +++ b/test/unit/aarch64/ExceptionHandlerTest.cc @@ -363,7 +363,7 @@ TEST_F(AArch64ExceptionHandlerTest, readBufferThen) { EXPECT_FALSE(outcome); EXPECT_EQ(retVal, 0); EXPECT_EQ(handler.dataBuffer_.size(), 128); - for (int i = 0; i < handler.dataBuffer_.size(); i++) { + for (size_t i = 0; i < handler.dataBuffer_.size(); i++) { EXPECT_EQ(handler.dataBuffer_[i], 'q'); } @@ -377,7 +377,7 @@ TEST_F(AArch64ExceptionHandlerTest, readBufferThen) { EXPECT_TRUE(outcome); EXPECT_EQ(retVal, 10); EXPECT_EQ(handler.dataBuffer_.size(), length); - for (int i = 0; i < length; i++) { + for (uint64_t i = 0; i < length; i++) { EXPECT_EQ(handler.dataBuffer_[i], static_cast('q')); } } diff --git a/test/unit/aarch64/InstructionTest.cc b/test/unit/aarch64/InstructionTest.cc index 1613262588..92b8e9393a 100644 --- a/test/unit/aarch64/InstructionTest.cc +++ b/test/unit/aarch64/InstructionTest.cc @@ -114,7 +114,7 @@ TEST_F(AArch64InstructionTest, validInsn) { EXPECT_EQ(insn.getBranchType(), BranchType::Unknown); EXPECT_EQ(insn.getData().size(), 0); EXPECT_EQ(insn.getDestinationRegisters().size(), destRegs.size()); - for (int i = 0; i < destRegs.size(); i++) { + for (size_t i = 0; i < destRegs.size(); i++) { EXPECT_EQ(insn.getDestinationRegisters()[i], destRegs[i]); } EXPECT_EQ(insn.getException(), InstructionException::None); @@ -133,7 +133,7 @@ TEST_F(AArch64InstructionTest, validInsn) { // Operands vector resized at decode EXPECT_EQ(insn.getSourceOperands().size(), 3); EXPECT_EQ(insn.getSourceRegisters().size(), srcRegs.size()); - for (int i = 0; i < srcRegs.size(); i++) { + for (size_t i = 0; i < srcRegs.size(); i++) { EXPECT_EQ(insn.getSourceRegisters()[i], srcRegs[i]); EXPECT_FALSE(insn.isOperandReady(i)); } @@ -177,7 +177,7 @@ TEST_F(AArch64InstructionTest, invalidInsn_1) { EXPECT_EQ(insn.getBranchType(), BranchType::Unknown); EXPECT_EQ(insn.getData().size(), 0); EXPECT_EQ(insn.getDestinationRegisters().size(), destRegs.size()); - for (int i = 0; i < destRegs.size(); i++) { + for (size_t i = 0; i < destRegs.size(); i++) { EXPECT_EQ(insn.getDestinationRegisters()[i], destRegs[i]); } EXPECT_EQ(insn.getException(), InstructionException::EncodingUnallocated); @@ -197,7 +197,7 @@ TEST_F(AArch64InstructionTest, invalidInsn_1) { // Operands vector resized at decode EXPECT_EQ(insn.getSourceOperands().size(), 0); EXPECT_EQ(insn.getSourceRegisters().size(), srcRegs.size()); - for (int i = 0; i < srcRegs.size(); i++) { + for (size_t i = 0; i < srcRegs.size(); i++) { EXPECT_EQ(insn.getSourceRegisters()[i], srcRegs[i]); EXPECT_FALSE(insn.isOperandReady(i)); } @@ -243,7 +243,7 @@ TEST_F(AArch64InstructionTest, invalidInsn_2) { EXPECT_EQ(insn.getBranchType(), BranchType::Unknown); EXPECT_EQ(insn.getData().size(), 0); EXPECT_EQ(insn.getDestinationRegisters().size(), destRegs.size()); - for (int i = 0; i < destRegs.size(); i++) { + for (size_t i = 0; i < destRegs.size(); i++) { EXPECT_EQ(insn.getDestinationRegisters()[i], destRegs[i]); } EXPECT_EQ(insn.getException(), InstructionException::HypervisorCall); @@ -263,7 +263,7 @@ TEST_F(AArch64InstructionTest, invalidInsn_2) { // Operands vector resized at decode EXPECT_EQ(insn.getSourceOperands().size(), 0); EXPECT_EQ(insn.getSourceRegisters().size(), srcRegs.size()); - for (int i = 0; i < srcRegs.size(); i++) { + for (size_t i = 0; i < srcRegs.size(); i++) { EXPECT_EQ(insn.getSourceRegisters()[i], srcRegs[i]); EXPECT_FALSE(insn.isOperandReady(i)); } @@ -297,11 +297,11 @@ TEST_F(AArch64InstructionTest, renameRegs) { {RegisterType::VECTOR, 0}}; // Ensure registers decoded correctly EXPECT_EQ(insn.getSourceRegisters().size(), srcRegs.size()); - for (int i = 0; i < srcRegs.size(); i++) { + for (size_t i = 0; i < srcRegs.size(); i++) { EXPECT_EQ(insn.getSourceRegisters()[i], srcRegs[i]); } EXPECT_EQ(insn.getDestinationRegisters().size(), destRegs.size()); - for (int i = 0; i < destRegs.size(); i++) { + for (size_t i = 0; i < destRegs.size(); i++) { EXPECT_EQ(insn.getDestinationRegisters()[i], destRegs[i]); } @@ -314,11 +314,11 @@ TEST_F(AArch64InstructionTest, renameRegs) { insn.renameSource(1, srcRegs_new[1]); // Ensure renaming functionality works as expected EXPECT_EQ(insn.getSourceRegisters().size(), srcRegs_new.size()); - for (int i = 0; i < srcRegs_new.size(); i++) { + for (size_t i = 0; i < srcRegs_new.size(); i++) { EXPECT_EQ(insn.getSourceRegisters()[i], srcRegs_new[i]); } EXPECT_EQ(insn.getDestinationRegisters().size(), destRegs_new.size()); - for (int i = 0; i < destRegs_new.size(); i++) { + for (size_t i = 0; i < destRegs_new.size(); i++) { EXPECT_EQ(insn.getDestinationRegisters()[i], destRegs_new[i]); } } @@ -386,11 +386,11 @@ TEST_F(AArch64InstructionTest, supplyData) { // Check source and destination registers extracted correctly EXPECT_EQ(insn.getSourceRegisters().size(), srcRegs.size()); - for (int i = 0; i < srcRegs.size(); i++) { + for (size_t i = 0; i < srcRegs.size(); i++) { EXPECT_EQ(insn.getSourceRegisters()[i], srcRegs[i]); } EXPECT_EQ(insn.getDestinationRegisters().size(), destRegs.size()); - for (int i = 0; i < destRegs.size(); i++) { + for (size_t i = 0; i < destRegs.size(); i++) { EXPECT_EQ(insn.getDestinationRegisters()[i], destRegs[i]); } @@ -405,7 +405,7 @@ TEST_F(AArch64InstructionTest, supplyData) { insn.generateAddresses(); auto generatedAddresses = insn.getGeneratedAddresses(); EXPECT_EQ(generatedAddresses.size(), 2); - for (int i = 0; i < generatedAddresses.size(); i++) { + for (size_t i = 0; i < generatedAddresses.size(); i++) { EXPECT_EQ(generatedAddresses[i].address, 0x480 + (i * 0x8)); EXPECT_EQ(generatedAddresses[i].size, 8); } @@ -414,12 +414,12 @@ TEST_F(AArch64InstructionTest, supplyData) { EXPECT_FALSE(insn.hasAllData()); std::vector data = {{123, 8}, {456, 8}}; EXPECT_EQ(generatedAddresses.size(), data.size()); - for (int i = 0; i < generatedAddresses.size(); i++) { + for (size_t i = 0; i < generatedAddresses.size(); i++) { insn.supplyData(generatedAddresses[i].address, data[i]); } // Ensure data was supplied correctly auto retrievedData = insn.getData(); - for (int i = 0; i < retrievedData.size(); i++) { + for (size_t i = 0; i < retrievedData.size(); i++) { EXPECT_EQ(retrievedData[i], data[i]); } EXPECT_TRUE(insn.hasAllData()); @@ -449,7 +449,7 @@ TEST_F(AArch64InstructionTest, supplyData_dataAbort) { insn.generateAddresses(); auto generatedAddresses = insn.getGeneratedAddresses(); EXPECT_EQ(generatedAddresses.size(), 2); - for (int i = 0; i < generatedAddresses.size(); i++) { + for (size_t i = 0; i < generatedAddresses.size(); i++) { EXPECT_EQ(generatedAddresses[i].address, 0x480 + (i * 0x8)); EXPECT_EQ(generatedAddresses[i].size, 8); } diff --git a/test/unit/aarch64/OperandContainerTest.cc b/test/unit/aarch64/OperandContainerTest.cc index 6eb2584530..dd0ed1b655 100644 --- a/test/unit/aarch64/OperandContainerTest.cc +++ b/test/unit/aarch64/OperandContainerTest.cc @@ -21,7 +21,7 @@ TEST(AArch64OperandContainerTest, correctInit) { { cont.resize(MAX_SOURCE_REGISTERS * 2); }, "resize can only be called when the active member is std::vector"); } -}; +} TEST(AArch64OperandContainerTest, useVec) { operandContainer cont; diff --git a/test/unit/pipeline/A64FXPortAllocatorTest.cc b/test/unit/pipeline/A64FXPortAllocatorTest.cc index f593788684..f2923f46ba 100644 --- a/test/unit/pipeline/A64FXPortAllocatorTest.cc +++ b/test/unit/pipeline/A64FXPortAllocatorTest.cc @@ -12,16 +12,16 @@ class A64FXPortAllocatorTest : public testing::Test { public: A64FXPortAllocatorTest() : portAllocator(portArrangement) { portAllocator.setRSSizeGetter( - [this](std::vector& sizeVec) { rsSizes(sizeVec); }); + [this](std::vector& sizeVec) { rsSizes(sizeVec); }); } - void rsSizes(std::vector& sizeVec) const { + void rsSizes(std::vector& sizeVec) const { sizeVec = rsFreeEntries; } protected: // Representation of the A64FX reservation station layout - std::vector rsFreeEntries = {20, 20, 10, 10, 19}; + std::vector rsFreeEntries = {20, 20, 10, 10, 19}; // Representation of the A64FX port layout const std::vector> portArrangement = { {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}}; diff --git a/test/unit/pipeline/DispatchIssueUnitTest.cc b/test/unit/pipeline/DispatchIssueUnitTest.cc index 9bd953f567..bd3f981463 100644 --- a/test/unit/pipeline/DispatchIssueUnitTest.cc +++ b/test/unit/pipeline/DispatchIssueUnitTest.cc @@ -80,7 +80,7 @@ class PipelineDispatchIssueUnitTest : public testing::Test { // As per a64fx.yaml const uint16_t EAGA = 5; // Maps to RS index 2 const uint8_t RS_EAGA = 2; // RS associated with EAGA in A64FX - const std::vector refRsSizes = {20, 20, 10, 10, 19}; + const std::vector refRsSizes = {20, 20, 10, 10, 19}; const Register r0 = {0, 0}; const Register r1 = {0, 1}; @@ -90,7 +90,7 @@ class PipelineDispatchIssueUnitTest : public testing::Test { // No instruction issued due to empty input buffer TEST_F(PipelineDispatchIssueUnitTest, emptyTick) { // Ensure empty Reservation stations pre tick() - std::vector rsSizes; + std::vector rsSizes; diUnit.getRSSizes(rsSizes); EXPECT_EQ(rsSizes, refRsSizes); @@ -140,7 +140,7 @@ TEST_F(PipelineDispatchIssueUnitTest, singleInstr) { EXPECT_CALL(portAlloc, allocate(suppPorts)).WillOnce(Return(EAGA)); // Ensure empty reservation stations pre tick() - std::vector rsSizes; + std::vector rsSizes; diUnit.getRSSizes(rsSizes); EXPECT_EQ(rsSizes, refRsSizes); @@ -200,7 +200,7 @@ TEST_F(PipelineDispatchIssueUnitTest, singleInstr_exception) { EXPECT_TRUE(uop->canCommit()); EXPECT_TRUE(uop->exceptionEncountered()); // Ensure all reservation stations are empty post tick() - std::vector rsSizes; + std::vector rsSizes; diUnit.getRSSizes(rsSizes); EXPECT_EQ(rsSizes, refRsSizes); // Ensure input buffer has been emptied @@ -213,7 +213,7 @@ TEST_F(PipelineDispatchIssueUnitTest, singleInstr_exception) { diUnit.getRSSizes(rsSizes); EXPECT_EQ(rsSizes, refRsSizes); // Ensure all output ports are empty - for (int i = 0; i < output.size(); i++) { + for (size_t i = 0; i < output.size(); i++) { EXPECT_EQ(output[i].getTailSlots()[0], nullptr); } // Ensure frontend stall recorded @@ -230,7 +230,7 @@ TEST_F(PipelineDispatchIssueUnitTest, singleInstr_rsFull) { // Artificially fill Reservation station with index 2 std::vector> insns(refRsSizes[RS_EAGA]); - for (int i = 0; i < insns.size(); i++) { + for (size_t i = 0; i < insns.size(); i++) { // Initialise instruction insns[i] = std::make_shared(); // All expected calls to instruction during tick() @@ -248,10 +248,10 @@ TEST_F(PipelineDispatchIssueUnitTest, singleInstr_rsFull) { } // Ensure Reservation station index 2 is full post tick, and all others are // empty - std::vector rsSizes; + std::vector rsSizes; diUnit.getRSSizes(rsSizes); EXPECT_EQ(rsSizes.size(), refRsSizes.size()); - for (int i = 0; i < refRsSizes.size(); i++) { + for (size_t i = 0; i < refRsSizes.size(); i++) { if (i != RS_EAGA) { EXPECT_EQ(rsSizes[i], refRsSizes[i]); } else { @@ -277,7 +277,7 @@ TEST_F(PipelineDispatchIssueUnitTest, singleInstr_rsFull) { rsSizes.clear(); diUnit.getRSSizes(rsSizes); EXPECT_EQ(rsSizes.size(), refRsSizes.size()); - for (int i = 0; i < refRsSizes.size(); i++) { + for (size_t i = 0; i < refRsSizes.size(); i++) { if (i != RS_EAGA) { EXPECT_EQ(rsSizes[i], refRsSizes[i]); } else { @@ -313,10 +313,10 @@ TEST_F(PipelineDispatchIssueUnitTest, singleInstr_portStall) { diUnit.tick(); // Ensure correct RS sizes post tick() - std::vector rsSizes; + std::vector rsSizes; diUnit.getRSSizes(rsSizes); EXPECT_EQ(rsSizes.size(), refRsSizes.size()); - for (int i = 0; i < refRsSizes.size(); i++) { + for (size_t i = 0; i < refRsSizes.size(); i++) { if (i != RS_EAGA) { EXPECT_EQ(rsSizes[i], refRsSizes[i]); } else { @@ -338,7 +338,7 @@ TEST_F(PipelineDispatchIssueUnitTest, singleInstr_portStall) { rsSizes.clear(); diUnit.getRSSizes(rsSizes); EXPECT_EQ(rsSizes.size(), refRsSizes.size()); - for (int i = 0; i < refRsSizes.size(); i++) { + for (size_t i = 0; i < refRsSizes.size(); i++) { if (i != RS_EAGA) { EXPECT_EQ(rsSizes[i], refRsSizes[i]); } else { @@ -346,7 +346,7 @@ TEST_F(PipelineDispatchIssueUnitTest, singleInstr_portStall) { } } // Ensure all output ports are empty - for (int i = 0; i < output.size(); i++) { + for (size_t i = 0; i < output.size(); i++) { EXPECT_EQ(output[i].getTailSlots()[0], nullptr); } // Ensure portBusyStall and backend stall recorded in issue() @@ -403,10 +403,10 @@ TEST_F(PipelineDispatchIssueUnitTest, createdependency_raw) { diUnit.tick(); diUnit.issue(); // Ensure correct RS sizes post tick() & issue() - std::vector rsSizes; + std::vector rsSizes; diUnit.getRSSizes(rsSizes); EXPECT_EQ(rsSizes.size(), refRsSizes.size()); - for (int i = 0; i < refRsSizes.size(); i++) { + for (size_t i = 0; i < refRsSizes.size(); i++) { if (i != RS_EAGA) { EXPECT_EQ(rsSizes[i], refRsSizes[i]); } else { @@ -414,7 +414,7 @@ TEST_F(PipelineDispatchIssueUnitTest, createdependency_raw) { } } // Ensure all output ports are empty - for (int i = 0; i < output.size(); i++) { + for (size_t i = 0; i < output.size(); i++) { EXPECT_EQ(output[i].getTailSlots()[0], nullptr); } // Ensure backend stall recorded in issue() @@ -437,7 +437,7 @@ TEST_F(PipelineDispatchIssueUnitTest, createdependency_raw) { diUnit.getRSSizes(rsSizes); EXPECT_EQ(rsSizes, refRsSizes); // Ensure all output ports are empty except EAGA - for (int i = 0; i < output.size(); i++) { + for (size_t i = 0; i < output.size(); i++) { if (i != EAGA) EXPECT_EQ(output[i].getTailSlots()[0], nullptr); else @@ -495,10 +495,10 @@ TEST_F(PipelineDispatchIssueUnitTest, purgeFlushed) { EXPECT_EQ(input.getHeadSlots()[0], nullptr); // Ensure correct RS sizes post tick() - std::vector rsSizes; + std::vector rsSizes; diUnit.getRSSizes(rsSizes); EXPECT_EQ(rsSizes.size(), refRsSizes.size()); - for (int i = 0; i < refRsSizes.size(); i++) { + for (size_t i = 0; i < refRsSizes.size(); i++) { if (i != RS_EAGA) { EXPECT_EQ(rsSizes[i], refRsSizes[i]); } else { @@ -506,7 +506,7 @@ TEST_F(PipelineDispatchIssueUnitTest, purgeFlushed) { } } // Ensure all output ports are empty - for (int i = 0; i < output.size(); i++) { + for (size_t i = 0; i < output.size(); i++) { EXPECT_EQ(output[i].getTailSlots()[0], nullptr); } // Ensure no stalls recorded @@ -529,7 +529,7 @@ TEST_F(PipelineDispatchIssueUnitTest, purgeFlushed) { // Perform issue to see if `uop` is still present diUnit.issue(); // Ensure all output ports are empty - for (int i = 0; i < output.size(); i++) { + for (size_t i = 0; i < output.size(); i++) { EXPECT_EQ(output[i].getTailSlots()[0], nullptr); } // Ensure frontend stall recorded in issue() @@ -549,7 +549,7 @@ TEST_F(PipelineDispatchIssueUnitTest, purgeFlushed) { diUnit.issue(); // Ensure all output ports are empty - for (int i = 0; i < output.size(); i++) { + for (size_t i = 0; i < output.size(); i++) { EXPECT_EQ(output[i].getTailSlots()[0], nullptr); } // Ensure frontend stall recorded in issue() @@ -561,7 +561,7 @@ TEST_F(PipelineDispatchIssueUnitTest, purgeFlushed) { // Test based on a64fx config file reservation staion configuration TEST_F(PipelineDispatchIssueUnitTest, getRSSizes) { - std::vector rsSizes; + std::vector rsSizes; diUnit.getRSSizes(rsSizes); EXPECT_EQ(rsSizes, refRsSizes); } diff --git a/test/unit/pipeline/M1PortAllocatorTest.cc b/test/unit/pipeline/M1PortAllocatorTest.cc index bdfe4c6cd7..b0adbed8f1 100644 --- a/test/unit/pipeline/M1PortAllocatorTest.cc +++ b/test/unit/pipeline/M1PortAllocatorTest.cc @@ -8,16 +8,16 @@ class M1PortAllocatorTest : public testing::Test { public: M1PortAllocatorTest() : portAllocator(portArrangement, rsArrangement) { portAllocator.setRSSizeGetter( - [this](std::vector& sizeVec) { rsSizes(sizeVec); }); + [this](std::vector& sizeVec) { rsSizes(sizeVec); }); } - void rsSizes(std::vector& sizeVec) const { + void rsSizes(std::vector& sizeVec) const { sizeVec = rsFreeEntries; } protected: // Representation of the M1 Firestorm reservation station layout - std::vector rsFreeEntries = {24, 26, 16, 12, 28, 28, 12, + std::vector rsFreeEntries = {24, 26, 16, 12, 28, 28, 12, 12, 12, 12, 36, 36, 36, 36}; // Representation of the M1 Firestorm port layout const std::vector> portArrangement = { diff --git a/test/unit/pipeline/RenameUnitTest.cc b/test/unit/pipeline/RenameUnitTest.cc index 23a1e3dd71..6b1dc640c5 100644 --- a/test/unit/pipeline/RenameUnitTest.cc +++ b/test/unit/pipeline/RenameUnitTest.cc @@ -44,8 +44,8 @@ class RenameUnitTest : public testing::Test { const Register r1 = {1, 2}; const Register r2 = {2, 4}; - const unsigned int robSize = 8; - const unsigned int lsqQueueSize = 10; + const uint64_t robSize = 8; + const uint64_t lsqQueueSize = 10; PipelineBuffer> input; PipelineBuffer> output; @@ -196,7 +196,7 @@ TEST_F(RenameUnitTest, noFreeRegs) { // Tests that when ROB is full, no renaming occurs TEST_F(RenameUnitTest, fullROB) { // Pre-fill ROB - for (int i = 0; i < robSize; i++) { + for (uint64_t i = 0; i < robSize; i++) { rob.reserve(uopPtr); } EXPECT_EQ(rob.getFreeSpace(), 0); @@ -264,7 +264,7 @@ TEST_F(RenameUnitTest, loadUop) { // Test a LOAD instruction is handled correctly when Load queue is full TEST_F(RenameUnitTest, loadUopQueueFull) { // pre-fill Load Queue - for (int i = 0; i < lsqQueueSize; i++) { + for (uint64_t i = 0; i < lsqQueueSize; i++) { lsq.addLoad(uopPtr); } EXPECT_EQ(lsq.getLoadQueueSpace(), 0); @@ -350,7 +350,7 @@ TEST_F(RenameUnitTest, storeUop) { // Test a STORE instruction is handled correctly when Store queue is full TEST_F(RenameUnitTest, storeUopQueueFull) { // pre-fill Load Queue - for (int i = 0; i < lsqQueueSize; i++) { + for (uint64_t i = 0; i < lsqQueueSize; i++) { lsq.addStore(uopPtr); } EXPECT_EQ(lsq.getStoreQueueSpace(), 0); diff --git a/test/unit/riscv/ArchitectureTest.cc b/test/unit/riscv/ArchitectureTest.cc index 8364dbe692..49e64e42b0 100644 --- a/test/unit/riscv/ArchitectureTest.cc +++ b/test/unit/riscv/ArchitectureTest.cc @@ -61,13 +61,13 @@ class RiscVArchitectureTest : public testing::Test { })YAML"); // addi sp, ra, 2000 - std::array validInstrBytes = {0x13, 0x81, 0x00, 0x7d}; - std::array invalidInstrBytes = {0x7f, 0x00, 0x81, 0xbb}; + const std::array validInstrBytes = {0x13, 0x81, 0x00, 0x7d}; + const std::array invalidInstrBytes = {0x7f, 0x00, 0x81, 0xbb}; std::unique_ptr arch; kernel::Linux kernel; kernel::LinuxProcess process = kernel::LinuxProcess( - span((char*)validInstrBytes.data(), validInstrBytes.size())); + span(validInstrBytes.data(), validInstrBytes.size())); }; TEST_F(RiscVArchitectureTest, predecode) { @@ -116,7 +116,7 @@ TEST_F(RiscVArchitectureTest, handleException) { EXPECT_EQ(insn[0]->exceptionEncountered(), true); // Get Core - std::string executablePath = ""; + std::string executablePath = SIMENG_SOURCE_DIR "/SimEngDefaultProgram"; std::vector executableArgs = {}; std::unique_ptr coreInstance = std::make_unique(executablePath, executableArgs); diff --git a/test/unit/riscv/ExceptionHandlerTest.cc b/test/unit/riscv/ExceptionHandlerTest.cc index bef719c89a..3e9ac92be7 100644 --- a/test/unit/riscv/ExceptionHandlerTest.cc +++ b/test/unit/riscv/ExceptionHandlerTest.cc @@ -362,7 +362,7 @@ TEST_F(RiscVExceptionHandlerTest, readBufferThen) { EXPECT_FALSE(outcome); EXPECT_EQ(retVal, 0); EXPECT_EQ(handler.dataBuffer_.size(), 128); - for (int i = 0; i < handler.dataBuffer_.size(); i++) { + for (size_t i = 0; i < handler.dataBuffer_.size(); i++) { EXPECT_EQ(handler.dataBuffer_[i], 'q'); } @@ -376,7 +376,7 @@ TEST_F(RiscVExceptionHandlerTest, readBufferThen) { EXPECT_TRUE(outcome); EXPECT_EQ(retVal, 10); EXPECT_EQ(handler.dataBuffer_.size(), length); - for (int i = 0; i < length; i++) { + for (size_t i = 0; i < length; i++) { EXPECT_EQ(handler.dataBuffer_[i], static_cast('q')); } } diff --git a/test/unit/riscv/InstructionTest.cc b/test/unit/riscv/InstructionTest.cc index ef5aaf1d66..6103cd4f5c 100644 --- a/test/unit/riscv/InstructionTest.cc +++ b/test/unit/riscv/InstructionTest.cc @@ -112,7 +112,7 @@ TEST_F(RiscVInstructionTest, validInsn) { EXPECT_EQ(insn.getBranchType(), BranchType::Unknown); EXPECT_EQ(insn.getData().size(), 0); EXPECT_EQ(insn.getDestinationRegisters().size(), destRegs.size()); - for (int i = 0; i < destRegs.size(); i++) { + for (size_t i = 0; i < destRegs.size(); i++) { EXPECT_EQ(insn.getDestinationRegisters()[i], destRegs[i]); } EXPECT_EQ(insn.getException(), InstructionException::None); @@ -129,7 +129,7 @@ TEST_F(RiscVInstructionTest, validInsn) { EXPECT_EQ(insn.getSequenceId(), 12); EXPECT_EQ(insn.getSourceOperands().size(), 2); EXPECT_EQ(insn.getSourceRegisters().size(), srcRegs.size()); - for (int i = 0; i < srcRegs.size(); i++) { + for (size_t i = 0; i < srcRegs.size(); i++) { EXPECT_EQ(insn.getSourceRegisters()[i], srcRegs[i]); EXPECT_FALSE(insn.isOperandReady(i)); } @@ -173,7 +173,7 @@ TEST_F(RiscVInstructionTest, invalidInsn_1) { EXPECT_EQ(insn.getBranchType(), BranchType::Unknown); EXPECT_EQ(insn.getData().size(), 0); EXPECT_EQ(insn.getDestinationRegisters().size(), destRegs.size()); - for (int i = 0; i < destRegs.size(); i++) { + for (size_t i = 0; i < destRegs.size(); i++) { EXPECT_EQ(insn.getDestinationRegisters()[i], destRegs[i]); } EXPECT_EQ(insn.getException(), InstructionException::EncodingUnallocated); @@ -191,7 +191,7 @@ TEST_F(RiscVInstructionTest, invalidInsn_1) { EXPECT_EQ(insn.getSequenceId(), 14); EXPECT_EQ(insn.getSourceOperands().size(), 0); EXPECT_EQ(insn.getSourceRegisters().size(), srcRegs.size()); - for (int i = 0; i < srcRegs.size(); i++) { + for (size_t i = 0; i < srcRegs.size(); i++) { EXPECT_EQ(insn.getSourceRegisters()[i], srcRegs[i]); EXPECT_FALSE(insn.isOperandReady(i)); } @@ -237,7 +237,7 @@ TEST_F(RiscVInstructionTest, invalidInsn_2) { EXPECT_EQ(insn.getBranchType(), BranchType::Unknown); EXPECT_EQ(insn.getData().size(), 0); EXPECT_EQ(insn.getDestinationRegisters().size(), destRegs.size()); - for (int i = 0; i < destRegs.size(); i++) { + for (size_t i = 0; i < destRegs.size(); i++) { EXPECT_EQ(insn.getDestinationRegisters()[i], destRegs[i]); } EXPECT_EQ(insn.getException(), InstructionException::HypervisorCall); @@ -255,7 +255,7 @@ TEST_F(RiscVInstructionTest, invalidInsn_2) { EXPECT_EQ(insn.getSequenceId(), 16); EXPECT_EQ(insn.getSourceOperands().size(), 0); EXPECT_EQ(insn.getSourceRegisters().size(), srcRegs.size()); - for (int i = 0; i < srcRegs.size(); i++) { + for (size_t i = 0; i < srcRegs.size(); i++) { EXPECT_EQ(insn.getSourceRegisters()[i], srcRegs[i]); EXPECT_FALSE(insn.isOperandReady(i)); } @@ -288,11 +288,11 @@ TEST_F(RiscVInstructionTest, renameRegs) { {RegisterType::GENERAL, 10}}; // Ensure registers decoded correctly EXPECT_EQ(insn.getSourceRegisters().size(), srcRegs.size()); - for (int i = 0; i < srcRegs.size(); i++) { + for (size_t i = 0; i < srcRegs.size(); i++) { EXPECT_EQ(insn.getSourceRegisters()[i], srcRegs[i]); } EXPECT_EQ(insn.getDestinationRegisters().size(), destRegs.size()); - for (int i = 0; i < destRegs.size(); i++) { + for (size_t i = 0; i < destRegs.size(); i++) { EXPECT_EQ(insn.getDestinationRegisters()[i], destRegs[i]); } @@ -304,11 +304,11 @@ TEST_F(RiscVInstructionTest, renameRegs) { insn.renameSource(1, srcRegs_new[1]); // Ensure renaming functionality works as expected EXPECT_EQ(insn.getSourceRegisters().size(), srcRegs_new.size()); - for (int i = 0; i < srcRegs_new.size(); i++) { + for (size_t i = 0; i < srcRegs_new.size(); i++) { EXPECT_EQ(insn.getSourceRegisters()[i], srcRegs_new[i]); } EXPECT_EQ(insn.getDestinationRegisters().size(), destRegs_new.size()); - for (int i = 0; i < destRegs_new.size(); i++) { + for (size_t i = 0; i < destRegs_new.size(); i++) { EXPECT_EQ(insn.getDestinationRegisters()[i], destRegs_new[i]); } } @@ -367,11 +367,11 @@ TEST_F(RiscVInstructionTest, supplyData) { // Check source and destination registers extracted correctly EXPECT_EQ(insn.getSourceRegisters().size(), srcRegs.size()); - for (int i = 0; i < srcRegs.size(); i++) { + for (size_t i = 0; i < srcRegs.size(); i++) { EXPECT_EQ(insn.getSourceRegisters()[i], srcRegs[i]); } EXPECT_EQ(insn.getDestinationRegisters().size(), destRegs.size()); - for (int i = 0; i < destRegs.size(); i++) { + for (size_t i = 0; i < destRegs.size(); i++) { EXPECT_EQ(insn.getDestinationRegisters()[i], destRegs[i]); } @@ -396,7 +396,7 @@ TEST_F(RiscVInstructionTest, supplyData) { insn.supplyData(generatedAddresses[0].address, data[0]); // Ensure data was supplied correctly auto retrievedData = insn.getData(); - for (int i = 0; i < retrievedData.size(); i++) { + for (size_t i = 0; i < retrievedData.size(); i++) { EXPECT_EQ(retrievedData[i], data[i]); } EXPECT_TRUE(insn.hasAllData());