Skip to content

Commit

Permalink
Core class cleanup (#387)
Browse files Browse the repository at this point in the history
* Added headers to ProcessStateChange.hh and moved Register struct to new Register.hh.
* Added memory directory and namespace.
  • Loading branch information
FinnWilkinson authored Feb 16, 2024
1 parent e17ad08 commit f4bd1ef
Show file tree
Hide file tree
Showing 63 changed files with 801 additions and 858 deletions.
90 changes: 86 additions & 4 deletions src/include/simeng/Core.hh
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,31 @@
#include <map>
#include <string>

#include "simeng/ArchitecturalRegisterFileSet.hh"
#include "simeng/arch/ProcessStateChange.hh"
#include "simeng/config/SimInfo.hh"
#include "simeng/memory/MemoryInterface.hh"

namespace simeng {

class ArchitecturalRegisterFileSet;
namespace arch {
// Forward declare Architecture and ExceptionHandler classes.
class Architecture;
class ExceptionHandler;
} // namespace arch

/** An abstract core model. */
class Core {
public:
Core(memory::MemoryInterface& dataMemory, const arch::Architecture& isa,
const std::vector<RegisterFileStructure>& regFileStructure)
: dataMemory_(dataMemory),
isa_(isa),
registerFileSet_(regFileStructure),
clockFrequency_(
config::SimInfo::getConfig()["Core"]["Clock-Frequency-GHz"]
.as<float>()) {}

virtual ~Core() {}

/** Tick the core. */
Expand All @@ -28,11 +44,77 @@ class Core {
/** Retrieve the number of instructions retired. */
virtual uint64_t getInstructionsRetiredCount() const = 0;

/** Retrieve the simulated nanoseconds elapsed since the core started. */
virtual uint64_t getSystemTimer() const = 0;

/** Retrieve a map of statistics to report. */
virtual std::map<std::string, std::string> getStats() const = 0;

/** Retrieve the simulated nanoseconds elapsed since the core started. */
uint64_t getSystemTimer() const {
// TODO: This will need to be changed if we start supporting DVFS.
return (ticks_ / clockFrequency_);
}

protected:
/** Apply changes to the process state. */
void applyStateChange(const arch::ProcessStateChange& change) const {
auto& regFile = const_cast<ArchitecturalRegisterFileSet&>(
getArchitecturalRegisterFileSet());
// Update registers in accordance with the ProcessStateChange type
switch (change.type) {
case arch::ChangeType::INCREMENT: {
for (size_t i = 0; i < change.modifiedRegisters.size(); i++) {
regFile.set(change.modifiedRegisters[i],
regFile.get(change.modifiedRegisters[i]).get<uint64_t>() +
change.modifiedRegisterValues[i].get<uint64_t>());
}
break;
}
case arch::ChangeType::DECREMENT: {
for (size_t i = 0; i < change.modifiedRegisters.size(); i++) {
regFile.set(change.modifiedRegisters[i],
regFile.get(change.modifiedRegisters[i]).get<uint64_t>() -
change.modifiedRegisterValues[i].get<uint64_t>());
}
break;
}
default: { // arch::ChangeType::REPLACEMENT
// If type is ChangeType::REPLACEMENT, set new values
for (size_t i = 0; i < change.modifiedRegisters.size(); i++) {
regFile.set(change.modifiedRegisters[i],
change.modifiedRegisterValues[i]);
}
break;
}
}

// Update memory
// TODO: Analyse if ChangeType::INCREMENT or ChangeType::DECREMENT case is
// required for memory changes
for (size_t i = 0; i < change.memoryAddresses.size(); i++) {
dataMemory_.requestWrite(change.memoryAddresses[i],
change.memoryAddressValues[i]);
}
}

/** A memory interface to access data. */
memory::MemoryInterface& dataMemory_;

/** The currently used ISA. */
const arch::Architecture& isa_;

/** The core's register file set. */
RegisterFileSet registerFileSet_;

/** The active exception handler. */
std::shared_ptr<arch::ExceptionHandler> exceptionHandler_;

/** The number of times this core has been ticked. */
uint64_t ticks_ = 0;

/** Whether or not the core has halted. */
bool hasHalted_ = false;

/** Clock frequency of core in GHz */
float clockFrequency_ = 0.0f;
};

} // namespace simeng
21 changes: 11 additions & 10 deletions src/include/simeng/CoreInstance.hh
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
#include "simeng/AlwaysNotTakenPredictor.hh"
#include "simeng/Core.hh"
#include "simeng/Elf.hh"
#include "simeng/FixedLatencyMemoryInterface.hh"
#include "simeng/FlatMemoryInterface.hh"
#include "simeng/GenericPredictor.hh"
#include "simeng/PerceptronPredictor.hh"
#include "simeng/SpecialFileDirGen.hh"
Expand All @@ -15,6 +13,8 @@
#include "simeng/arch/riscv/Architecture.hh"
#include "simeng/config/SimInfo.hh"
#include "simeng/kernel/Linux.hh"
#include "simeng/memory/FixedLatencyMemoryInterface.hh"
#include "simeng/memory/FlatMemoryInterface.hh"
#include "simeng/models/emulation/Core.hh"
#include "simeng/models/inorder/Core.hh"
#include "simeng/models/outoforder/Core.hh"
Expand Down Expand Up @@ -52,10 +52,11 @@ class CoreInstance {
~CoreInstance();

/** Set the SimEng L1 instruction cache memory. */
void setL1InstructionMemory(std::shared_ptr<simeng::MemoryInterface> memRef);
void setL1InstructionMemory(
std::shared_ptr<simeng::memory::MemoryInterface> memRef);

/** Set the SimEng L1 data cache memory. */
void setL1DataMemory(std::shared_ptr<simeng::MemoryInterface> memRef);
void setL1DataMemory(std::shared_ptr<simeng::memory::MemoryInterface> memRef);

/** Construct the core and all its associated simulation objects after the
* process and memory interfaces have been instantiated. */
Expand All @@ -65,10 +66,10 @@ class CoreInstance {
std::shared_ptr<simeng::Core> getCore() const;

/** Getter for the create data memory object. */
std::shared_ptr<simeng::MemoryInterface> getDataMemory() const;
std::shared_ptr<simeng::memory::MemoryInterface> getDataMemory() const;

/** Getter for the create instruction memory object. */
std::shared_ptr<simeng::MemoryInterface> getInstructionMemory() const;
std::shared_ptr<simeng::memory::MemoryInterface> getInstructionMemory() const;

/** Getter for a shared pointer to the created process image. */
std::shared_ptr<char> getProcessImage() const;
Expand All @@ -95,10 +96,10 @@ class CoreInstance {
void createProcessMemory();

/** Construct the SimEng L1 instruction cache memory. */
void createL1InstructionMemory(const simeng::MemInterfaceType type);
void createL1InstructionMemory(const memory::MemInterfaceType type);

/** Construct the SimEng L1 data cache memory. */
void createL1DataMemory(const simeng::MemInterfaceType type);
void createL1DataMemory(const memory::MemInterfaceType type);

/** Construct the special file directory. */
void createSpecialFileDirectory();
Expand Down Expand Up @@ -146,10 +147,10 @@ class CoreInstance {
std::shared_ptr<simeng::Core> core_ = nullptr;

/** Reference to the SimEng data memory object. */
std::shared_ptr<simeng::MemoryInterface> dataMemory_ = nullptr;
std::shared_ptr<simeng::memory::MemoryInterface> dataMemory_ = nullptr;

/** Reference to the SimEng instruction memory object. */
std::shared_ptr<simeng::MemoryInterface> instructionMemory_ = nullptr;
std::shared_ptr<simeng::memory::MemoryInterface> instructionMemory_ = nullptr;
};

} // namespace simeng
1 change: 1 addition & 0 deletions src/include/simeng/Elf.hh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <cstdint>
#include <string>
#include <vector>

Expand Down
9 changes: 5 additions & 4 deletions src/include/simeng/Instruction.hh
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

#include "capstone/capstone.h"
#include "simeng/BranchPredictor.hh"
#include "simeng/MemoryInterface.hh"
#include "simeng/RegisterFileSet.hh"
#include "simeng/Register.hh"
#include "simeng/RegisterValue.hh"
#include "simeng/memory/MemoryInterface.hh"
#include "simeng/span.hh"

using InstructionException = short;
Expand Down Expand Up @@ -84,13 +84,14 @@ class Instruction {
virtual const span<RegisterValue> getResults() const = 0;

/** Generate memory addresses this instruction wishes to access. */
virtual span<const MemoryAccessTarget> generateAddresses() = 0;
virtual span<const memory::MemoryAccessTarget> generateAddresses() = 0;

/** Provide data from a requested memory address. */
virtual void supplyData(uint64_t address, const RegisterValue& data) = 0;

/** Retrieve previously generated memory addresses. */
virtual span<const MemoryAccessTarget> getGeneratedAddresses() const = 0;
virtual span<const memory::MemoryAccessTarget> getGeneratedAddresses()
const = 0;

/** Retrieve supplied memory data. */
virtual span<const RegisterValue> getData() const = 0;
Expand Down
29 changes: 29 additions & 0 deletions src/include/simeng/Register.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once
#include <iostream>

namespace simeng {

/** A generic register identifier. */
struct Register {
/** An identifier representing the type of register - e.g. 0 = general, 1 =
* vector. Used to determine which register file to access. */
uint8_t type;

/** A tag identifying the register. May correspond to either physical or
* architectural register, depending on point of usage. */
uint16_t tag;

/** A boolean identifier for whether the creation of this register has been a
* result of a register renaming scheme. */
bool renamed = false;

/** Check for equality of two register identifiers. */
bool operator==(const Register& other) const {
return (other.type == type && other.tag == tag);
}

/** Check for inequality of two register identifiers. */
bool operator!=(const Register& other) const { return !(other == *this); }
};

} // namespace simeng
23 changes: 1 addition & 22 deletions src/include/simeng/RegisterFileSet.hh
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,11 @@

#include <vector>

#include "simeng/Register.hh"
#include "simeng/RegisterValue.hh"

namespace simeng {

/** A generic register identifier. */
struct Register {
/** An identifier representing the type of register - e.g. 0 = general, 1 =
* vector. Used to determine which register file to access. */
uint8_t type;

/** A tag identifying the register. May correspond to either physical or
* architectural register, depending on point of usage. */
uint16_t tag;

/** A boolean identifier for whether the creation of this register has been a
* result of a register renaming scheme. */
bool renamed = false;

/** Check for equality of two register identifiers. */
bool operator==(const Register& other) const;

/** Check for inequality of two register identifiers. */
bool operator!=(const Register& other) const;
};
std::ostream& operator<<(std::ostream& os, simeng::Register const& reg);

/** Defines the structure of a register file. */
struct RegisterFileStructure {
/** The number of bytes per register. */
Expand Down
22 changes: 3 additions & 19 deletions src/include/simeng/arch/Architecture.hh
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,16 @@
#include "simeng/BranchPredictor.hh"
#include "simeng/Core.hh"
#include "simeng/Instruction.hh"
#include "simeng/MemoryInterface.hh"
#include "simeng/arch/ProcessStateChange.hh"
#include "simeng/kernel/Linux.hh"
#include "simeng/memory/MemoryInterface.hh"

namespace simeng {

using MacroOp = std::vector<std::shared_ptr<Instruction>>;

namespace arch {

/** The types of changes that can be made to values within the process state. */
enum class ChangeType { REPLACEMENT, INCREMENT, DECREMENT };

/** A structure describing a set of changes to the process state. */
struct ProcessStateChange {
/** Type of changes to be made */
ChangeType type;
/** Registers to modify */
std::vector<Register> modifiedRegisters;
/** Values to set modified registers to */
std::vector<RegisterValue> modifiedRegisterValues;
/** Memory address/width pairs to modify */
std::vector<MemoryAccessTarget> memoryAddresses;
/** Values to write to memory */
std::vector<RegisterValue> memoryAddressValues;
};

/** The result from a handled exception. */
struct ExceptionResult {
/** Whether execution should halt. */
Expand Down Expand Up @@ -82,7 +66,7 @@ class Architecture {
* obtained. */
virtual std::shared_ptr<ExceptionHandler> handleException(
const std::shared_ptr<Instruction>& instruction, const Core& core,
MemoryInterface& memory) const = 0;
memory::MemoryInterface& memory) const = 0;

/** Retrieve the initial process state. */
virtual ProcessStateChange getInitialState() const = 0;
Expand Down
31 changes: 31 additions & 0 deletions src/include/simeng/arch/ProcessStateChange.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

#include <vector>

#include "simeng/Register.hh"
#include "simeng/RegisterValue.hh"
#include "simeng/memory/MemoryAccessTarget.hh"

namespace simeng {

namespace arch {

/** The types of changes that can be made to values within the process state. */
enum class ChangeType { REPLACEMENT, INCREMENT, DECREMENT };

/** A structure describing a set of changes to the process state. */
struct ProcessStateChange {
/** Type of changes to be made */
ChangeType type;
/** Registers to modify */
std::vector<Register> modifiedRegisters;
/** Values to set modified registers to */
std::vector<RegisterValue> modifiedRegisterValues;
/** Memory address/width pairs to modify */
std::vector<memory::MemoryAccessTarget> memoryAddresses;
/** Values to write to memory */
std::vector<RegisterValue> memoryAddressValues;
};

} // namespace arch
} // namespace simeng
2 changes: 1 addition & 1 deletion src/include/simeng/arch/aarch64/Architecture.hh
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class Architecture : public arch::Architecture {
* the exception is resolved, and results then obtained. */
std::shared_ptr<arch::ExceptionHandler> handleException(
const std::shared_ptr<simeng::Instruction>& instruction, const Core& core,
MemoryInterface& memory) const override;
memory::MemoryInterface& memory) const override;

/** Retrieve the initial process state. */
ProcessStateChange getInitialState() const override;
Expand Down
4 changes: 2 additions & 2 deletions src/include/simeng/arch/aarch64/ExceptionHandler.hh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class ExceptionHandler : public simeng::arch::ExceptionHandler {
/** Create an exception handler with references to the instruction that caused
* the exception, along with the core model object and process memory. */
ExceptionHandler(const std::shared_ptr<simeng::Instruction>& instruction,
const Core& core, MemoryInterface& memory,
const Core& core, memory::MemoryInterface& memory,
kernel::Linux& linux);

/** Progress handling of the exception, by calling and returning the result of
Expand Down Expand Up @@ -78,7 +78,7 @@ class ExceptionHandler : public simeng::arch::ExceptionHandler {
const Core& core_;

/** The process memory. */
MemoryInterface& memory_;
memory::MemoryInterface& memory_;

/** The Linux kernel to forward syscalls to. */
kernel::Linux& linux_;
Expand Down
Loading

0 comments on commit f4bd1ef

Please sign in to comment.