Applied clang-format

This commit is contained in:
Eyck Jentzsch 2017-09-22 11:23:23 +02:00
parent 39150b68c0
commit b38319f9c2
34 changed files with 5579 additions and 6723 deletions

97
.clang-format Normal file
View File

@ -0,0 +1,97 @@
---
Language: Cpp
# BasedOnStyle: LLVM
# should be in line with IndentWidth
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: false
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '$'
IndentCaseLabels: false
IndentWidth: 4
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: true
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 4
UseTab: Never
...

View File

@ -516,7 +516,6 @@
<buildTargets> <buildTargets>
<target name="all VERBOSE=1" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder"> <target name="all VERBOSE=1" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand> <buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>all VERBOSE=1</buildTarget> <buildTarget>all VERBOSE=1</buildTarget>
<stopOnError>true</stopOnError> <stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand> <useDefaultCommand>true</useDefaultCommand>
@ -524,7 +523,6 @@
</target> </target>
<target name="clean" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder"> <target name="clean" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand> <buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>clean</buildTarget> <buildTarget>clean</buildTarget>
<stopOnError>true</stopOnError> <stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand> <useDefaultCommand>true</useDefaultCommand>
@ -532,12 +530,35 @@
</target> </target>
<target name="all" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder"> <target name="all" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand> <buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>all</buildTarget> <buildTarget>all</buildTarget>
<stopOnError>true</stopOnError> <stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand> <useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders> <runAllBuilders>true</runAllBuilders>
</target> </target>
<target name="clangformat" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>clangformat</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="riscv" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>riscv</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="riscv.sc" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>riscv.sc</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
</buildTargets> </buildTargets>
</storageModule> </storageModule>
</cproject> </cproject>

View File

@ -27,6 +27,9 @@ endif()
FIND_PACKAGE(Threads) FIND_PACKAGE(Threads)
set(PROJECT_3PARTY_DIRS external sr_report sr_signal)
include(sc-components/cmake/clang-format.cmake)
add_subdirectory(external) add_subdirectory(external)
add_subdirectory(dbt-core) add_subdirectory(dbt-core)
add_subdirectory(sc-components) add_subdirectory(sc-components)

@ -1 +1 @@
Subproject commit f23a45ab77d25ac42fd8df3e3f7206baad122c67 Subproject commit 7902b61b2cb504defdbb48baf74c7facfa7c249c

View File

@ -35,16 +35,15 @@
#ifndef _CLI_OPTIONS_H_ #ifndef _CLI_OPTIONS_H_
#define _CLI_OPTIONS_H_ #define _CLI_OPTIONS_H_
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#include <util/logging.h>
#include <iostream>
#include <cstdio> #include <cstdio>
#include <iostream>
#include <util/logging.h>
namespace { namespace {
const size_t ERROR_IN_COMMAND_LINE = 1; const size_t ERROR_IN_COMMAND_LINE = 1;
const size_t SUCCESS = 0; const size_t SUCCESS = 0;
const size_t ERROR_UNHANDLED_EXCEPTION = 2; const size_t ERROR_UNHANDLED_EXCEPTION = 2;
inline void enable_log_level(int level) { inline void enable_log_level(int level) {
switch (level) { switch (level) {
case 0: case 0:
@ -71,15 +70,18 @@ inline void enable_log_level(int level){
inline void configure_default_logger(boost::program_options::variables_map &vm) { inline void configure_default_logger(boost::program_options::variables_map &vm) {
// el::Configurations defaultConf; // el::Configurations defaultConf;
// defaultConf.setToDefault(); // defaultConf.setToDefault();
// defaultConf.set(el::Level::Error, el::ConfigurationType::Format, "%datetime{%H:%m:%s.%g} %level %msg"); // defaultConf.set(el::Level::Error, el::ConfigurationType::Format,
// defaultConf.set(el::Level::Warning, el::ConfigurationType::Format, "%datetime{%H:%m:%s.%g} %level %msg"); //"%datetime{%H:%m:%s.%g} %level %msg");
// defaultConf.set(el::Level::Info, el::ConfigurationType::Format, "%datetime{%H:%m:%s.%g} %level %msg"); // defaultConf.set(el::Level::Warning, el::ConfigurationType::Format,
// defaultConf.set(el::Level::Debug, el::ConfigurationType::Format, "%datetime{%H:%m:%s.%g} %level %msg"); //"%datetime{%H:%m:%s.%g} %level %msg");
// defaultConf.set(el::Level::Trace, el::ConfigurationType::Format, "%datetime{%H:%m:%s.%g} %level %msg"); // defaultConf.set(el::Level::Info, el::ConfigurationType::Format,
if(vm.count("verbose")) //"%datetime{%H:%m:%s.%g} %level %msg");
enable_log_level(vm["verbose"].as<int>()); // defaultConf.set(el::Level::Debug, el::ConfigurationType::Format,
if(vm.count("log-file")) //"%datetime{%H:%m:%s.%g} %level %msg");
logging::Output2FILE::stream() = fopen(vm["log-file"].as<std::string>().c_str(), "w"); // defaultConf.set(el::Level::Trace, el::ConfigurationType::Format,
//"%datetime{%H:%m:%s.%g} %level %msg");
if (vm.count("verbose")) enable_log_level(vm["verbose"].as<int>());
if (vm.count("log-file")) logging::Output2FILE::stream() = fopen(vm["log-file"].as<std::string>().c_str(), "w");
// default logger uses default configurations // default logger uses default configurations
// el::Loggers::reconfigureLogger("default", defaultConf); // el::Loggers::reconfigureLogger("default", defaultConf);
} }
@ -113,10 +115,12 @@ inline void configure_disass_logger(boost::program_options::variables_map& vm) {
// disassConf.set(el::Level::Global, el::ConfigurationType::ToFile, // disassConf.set(el::Level::Global, el::ConfigurationType::ToFile,
// std::string("true")); // std::string("true"));
// disassConf.set(el::Level::Global, // disassConf.set(el::Level::Global,
// el::ConfigurationType::ToStandardOutput, std::string("false")); // el::ConfigurationType::ToStandardOutput,
// std::string("false"));
// disassConf.set(el::Level::Global, el::ConfigurationType::Format, // disassConf.set(el::Level::Global, el::ConfigurationType::Format,
// std::string("%msg")); // std::string("%msg"));
// disassConf.set(el::Level::Global, el::ConfigurationType::Filename, // disassConf.set(el::Level::Global,
// el::ConfigurationType::Filename,
// file_name); // file_name);
// std::ofstream str(file_name); // just to clear the file // std::ofstream str(file_name); // just to clear the file
// } else { // } else {
@ -134,24 +138,22 @@ inline void configure_disass_logger(boost::program_options::variables_map& vm) {
inline int parse_cli_options(boost::program_options::variables_map &vm, int argc, char *argv[]) { inline int parse_cli_options(boost::program_options::variables_map &vm, int argc, char *argv[]) {
namespace po = boost::program_options; namespace po = boost::program_options;
po::options_description desc("Options"); po::options_description desc("Options");
desc.add_options() desc.add_options()("help,h", "Print help message")("verbose,v", po::value<int>()->implicit_value(0),
("help,h", "Print help message") "Sets logging verbosity")("vmodule", po::value<std::string>(),
("verbose,v", po::value<int>()->implicit_value(0), "Sets logging verbosity") "Defines the module(s) to be logged")(
("vmodule", po::value<std::string>(),"Defines the module(s) to be logged") "logging-flags", po::value<int>(), "Sets logging flag(s).")("log-file", po::value<std::string>(),
("logging-flags", po::value<int>(),"Sets logging flag(s).") "Sets default log file.")(
("log-file", po::value<std::string>(),"Sets default log file.") "disass,d", po::value<std::string>()->implicit_value(""),
("disass,d", po::value<std::string>()->implicit_value(""),"Enables disassembly") "Enables disassembly")("elf,l", po::value<std::vector<std::string>>(), "ELF file(s) to load")(
("elf,l", po::value< std::vector<std::string> >(), "ELF file(s) to load") "gdb-port,g", po::value<unsigned>(), "enable gdb server and specify port to use")(
("gdb-port,g", po::value<unsigned>(), "enable gdb server and specify port to use") "input,i", po::value<std::string>(), "the elf file to load (instead of hex files)")(
("input,i", po::value<std::string>(), "the elf file to load (instead of hex files)") "dump-ir", "dump the intermediate representation")("cycles,c", po::value<int64_t>()->default_value(-1),
("dump-ir", "dump the intermediate representation") "number of cycles to run")(
("cycles,c", po::value<int64_t>()->default_value(-1), "number of cycles to run") "systemc,s", "Run as SystemC simulation")("time", po::value<int>(), "SystemC siimulation time in ms")(
("systemc,s", "Run as SystemC simulation") "reset,r", po::value<std::string>(), "reset address")(
("time", po::value<int>(), "SystemC siimulation time in ms") "trace", po::value<uint8_t>(), "enable tracing, or cmbintation of 1=signals and 2=TX text, 4=TX "
("reset,r", po::value<std::string>(), "reset address") "compressed text, 6=TX in SQLite")("mem,m", po::value<std::string>(),
("trace", po::value<uint8_t>(), "enable tracing, or cmbintation of 1=signals and 2=TX text, 4=TX compressed text, 6=TX in SQLite")\ "the memory input file")("rv64", "run RV64");
("mem,m", po::value<std::string>(), "the memory input file")
("rv64", "run RV64");
try { try {
po::store(po::parse_command_line(argc, argv, desc), vm); // can throw po::store(po::parse_command_line(argc, argv, desc), vm); // can throw
// --help option // --help option

View File

@ -37,25 +37,21 @@
#ifndef _SYSC_SIFIVE_FE310_H_ #ifndef _SYSC_SIFIVE_FE310_H_
#define _SYSC_SIFIVE_FE310_H_ #define _SYSC_SIFIVE_FE310_H_
#include <iss/arch/rv32imac.h>
#include <iss/arch/riscv_hart_msu_vp.h> #include <iss/arch/riscv_hart_msu_vp.h>
#include <tlm> #include <iss/arch/rv32imac.h>
#include <sysc/utilities.h> #include <sysc/utilities.h>
#include <tlm>
namespace sysc { namespace sysc {
namespace SiFive { namespace SiFive {
class core_complex: class core_complex : public iss::arch::riscv_hart_msu_vp<iss::arch::rv32imac>, public sc_core::sc_module {
public iss::arch::riscv_hart_msu_vp<iss::arch::rv32imac>,
public sc_core::sc_module {
public: public:
tlm::tlm_initiator_socket<32> initiator; tlm::tlm_initiator_socket<32> initiator;
sc_core::sc_in<bool> rst_i; sc_core::sc_in<bool> rst_i;
core_complex(sc_core::sc_module_name name); core_complex(sc_core::sc_module_name name);
virtual ~core_complex(); virtual ~core_complex();
}; };
} /* namespace SiFive */ } /* namespace SiFive */

View File

@ -1,6 +1,7 @@
#ifndef _E300_PLAT_MAP_H_ #ifndef _E300_PLAT_MAP_H_
#define _E300_PLAT_MAP_H_ #define _E300_PLAT_MAP_H_
// need double braces, see https://stackoverflow.com/questions/6893700/how-to-construct-stdarray-object-with-initializer-list#6894191 // need double braces, see
// https://stackoverflow.com/questions/6893700/how-to-construct-stdarray-object-with-initializer-list#6894191
const std::array<sysc::target_memory_map_entry<32>, 4> e300_plat_map = {{ const std::array<sysc::target_memory_map_entry<32>, 4> e300_plat_map = {{
{&i_plic, 0xc000000, 0x1000}, {&i_plic, 0xc000000, 0x1000},
{&i_gpio, 0x10012000, 0x1000}, {&i_gpio, 0x10012000, 0x1000},

View File

@ -36,17 +36,14 @@
#ifndef _GPIO_REGS_H_ #ifndef _GPIO_REGS_H_
#define _GPIO_REGS_H_ #define _GPIO_REGS_H_
#include <sysc/utilities.h>
#include <util/bit_field.h>
#include <sysc/register.h> #include <sysc/register.h>
#include <sysc/tlm_target.h> #include <sysc/tlm_target.h>
#include <sysc/utilities.h>
#include <util/bit_field.h>
namespace sysc { namespace sysc {
class gpio_regs : class gpio_regs : public sc_core::sc_module, public sysc::resetable {
public sc_core::sc_module,
public sysc::resetable
{
protected: protected:
// storage declarations // storage declarations
uint32_t r_value; uint32_t r_value;
@ -105,8 +102,7 @@ protected:
public: public:
gpio_regs(sc_core::sc_module_name nm); gpio_regs(sc_core::sc_module_name nm);
template<unsigned BUSWIDTH=32> template <unsigned BUSWIDTH = 32> void registerResources(sysc::tlm_target<BUSWIDTH> &target);
void registerResources(sysc::tlm_target<BUSWIDTH>& target);
}; };
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -114,29 +110,14 @@ public:
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
inline sysc::gpio_regs::gpio_regs(sc_core::sc_module_name nm) inline sysc::gpio_regs::gpio_regs(sc_core::sc_module_name nm)
: sc_core::sc_module(nm) : sc_core::sc_module(nm), NAMED(value, r_value, 0, *this), NAMED(input_en, r_input_en, 0, *this),
, NAMED(value, r_value, 0, *this) NAMED(output_en, r_output_en, 0, *this), NAMED(port, r_port, 0, *this), NAMED(pue, r_pue, 0, *this),
, NAMED(input_en, r_input_en, 0, *this) NAMED(ds, r_ds, 0, *this), NAMED(rise_ie, r_rise_ie, 0, *this), NAMED(rise_ip, r_rise_ip, 0, *this),
, NAMED(output_en, r_output_en, 0, *this) NAMED(fall_ie, r_fall_ie, 0, *this), NAMED(fall_ip, r_fall_ip, 0, *this), NAMED(high_ie, r_high_ie, 0, *this),
, NAMED(port, r_port, 0, *this) NAMED(high_ip, r_high_ip, 0, *this), NAMED(low_ie, r_low_ie, 0, *this), NAMED(low_ip, r_low_ip, 0, *this),
, NAMED(pue, r_pue, 0, *this) NAMED(iof_en, r_iof_en, 0, *this), NAMED(iof_sel, r_iof_sel, 0, *this), NAMED(out_xor, r_out_xor, 0, *this) {}
, NAMED(ds, r_ds, 0, *this)
, NAMED(rise_ie, r_rise_ie, 0, *this)
, NAMED(rise_ip, r_rise_ip, 0, *this)
, NAMED(fall_ie, r_fall_ie, 0, *this)
, NAMED(fall_ip, r_fall_ip, 0, *this)
, NAMED(high_ie, r_high_ie, 0, *this)
, NAMED(high_ip, r_high_ip, 0, *this)
, NAMED(low_ie, r_low_ie, 0, *this)
, NAMED(low_ip, r_low_ip, 0, *this)
, NAMED(iof_en, r_iof_en, 0, *this)
, NAMED(iof_sel, r_iof_sel, 0, *this)
, NAMED(out_xor, r_out_xor, 0, *this)
{
}
template<unsigned BUSWIDTH> template <unsigned BUSWIDTH> inline void sysc::gpio_regs::registerResources(sysc::tlm_target<BUSWIDTH> &target) {
inline void sysc::gpio_regs::registerResources(sysc::tlm_target<BUSWIDTH>& target) {
target.addResource(value, 0x0UL); target.addResource(value, 0x0UL);
target.addResource(input_en, 0x4UL); target.addResource(input_en, 0x4UL);
target.addResource(output_en, 0x8UL); target.addResource(output_en, 0x8UL);

View File

@ -36,17 +36,14 @@
#ifndef _PLIC_REGS_H_ #ifndef _PLIC_REGS_H_
#define _PLIC_REGS_H_ #define _PLIC_REGS_H_
#include <sysc/utilities.h>
#include <util/bit_field.h>
#include <sysc/register.h> #include <sysc/register.h>
#include <sysc/tlm_target.h> #include <sysc/tlm_target.h>
#include <sysc/utilities.h>
#include <util/bit_field.h>
namespace sysc { namespace sysc {
class plic_regs : class plic_regs : public sc_core::sc_module, public sysc::resetable {
public sc_core::sc_module,
public sysc::resetable
{
protected: protected:
// storage declarations // storage declarations
BEGIN_BF_DECL(priority_t, uint32_t); BEGIN_BF_DECL(priority_t, uint32_t);
@ -74,8 +71,7 @@ protected:
public: public:
plic_regs(sc_core::sc_module_name nm); plic_regs(sc_core::sc_module_name nm);
template<unsigned BUSWIDTH=32> template <unsigned BUSWIDTH = 32> void registerResources(sysc::tlm_target<BUSWIDTH> &target);
void registerResources(sysc::tlm_target<BUSWIDTH>& target);
}; };
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -83,17 +79,11 @@ public:
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
inline sysc::plic_regs::plic_regs(sc_core::sc_module_name nm) inline sysc::plic_regs::plic_regs(sc_core::sc_module_name nm)
: sc_core::sc_module(nm) : sc_core::sc_module(nm), NAMED(priority, r_priority, 0, *this), NAMED(pending, r_pending, 0, *this),
, NAMED(priority, r_priority, 0, *this) NAMED(enabled, r_enabled, 0, *this), NAMED(threshold, r_threshold, 0, *this),
, NAMED(pending, r_pending, 0, *this) NAMED(claim_complete, r_claim_complete, 0, *this) {}
, NAMED(enabled, r_enabled, 0, *this)
, NAMED(threshold, r_threshold, 0, *this)
, NAMED(claim_complete, r_claim_complete, 0, *this)
{
}
template<unsigned BUSWIDTH> template <unsigned BUSWIDTH> inline void sysc::plic_regs::registerResources(sysc::tlm_target<BUSWIDTH> &target) {
inline void sysc::plic_regs::registerResources(sysc::tlm_target<BUSWIDTH>& target) {
target.addResource(priority, 0x4UL); target.addResource(priority, 0x4UL);
target.addResource(pending, 0x1000UL); target.addResource(pending, 0x1000UL);
target.addResource(enabled, 0x2000UL); target.addResource(enabled, 0x2000UL);

View File

@ -36,17 +36,14 @@
#ifndef _SPI_REGS_H_ #ifndef _SPI_REGS_H_
#define _SPI_REGS_H_ #define _SPI_REGS_H_
#include <sysc/utilities.h>
#include <util/bit_field.h>
#include <sysc/register.h> #include <sysc/register.h>
#include <sysc/tlm_target.h> #include <sysc/tlm_target.h>
#include <sysc/utilities.h>
#include <util/bit_field.h>
namespace sysc { namespace sysc {
class spi_regs : class spi_regs : public sc_core::sc_module, public sysc::resetable {
public sc_core::sc_module,
public sysc::resetable
{
protected: protected:
// storage declarations // storage declarations
BEGIN_BF_DECL(sckdiv_t, uint32_t); BEGIN_BF_DECL(sckdiv_t, uint32_t);
@ -147,8 +144,7 @@ protected:
public: public:
spi_regs(sc_core::sc_module_name nm); spi_regs(sc_core::sc_module_name nm);
template<unsigned BUSWIDTH=32> template <unsigned BUSWIDTH = 32> void registerResources(sysc::tlm_target<BUSWIDTH> &target);
void registerResources(sysc::tlm_target<BUSWIDTH>& target);
}; };
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -156,28 +152,14 @@ public:
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
inline sysc::spi_regs::spi_regs(sc_core::sc_module_name nm) inline sysc::spi_regs::spi_regs(sc_core::sc_module_name nm)
: sc_core::sc_module(nm) : sc_core::sc_module(nm), NAMED(sckdiv, r_sckdiv, 0, *this), NAMED(sckmode, r_sckmode, 0, *this),
, NAMED(sckdiv, r_sckdiv, 0, *this) NAMED(csid, r_csid, 0, *this), NAMED(csdef, r_csdef, 0, *this), NAMED(csmode, r_csmode, 0, *this),
, NAMED(sckmode, r_sckmode, 0, *this) NAMED(delay0, r_delay0, 0, *this), NAMED(delay1, r_delay1, 0, *this), NAMED(fmt, r_fmt, 0, *this),
, NAMED(csid, r_csid, 0, *this) NAMED(txdata, r_txdata, 0, *this), NAMED(rxdata, r_rxdata, 0, *this), NAMED(txmark, r_txmark, 0, *this),
, NAMED(csdef, r_csdef, 0, *this) NAMED(rxmark, r_rxmark, 0, *this), NAMED(fctrl, r_fctrl, 0, *this), NAMED(ffmt, r_ffmt, 0, *this),
, NAMED(csmode, r_csmode, 0, *this) NAMED(ie, r_ie, 0, *this), NAMED(ip, r_ip, 0, *this) {}
, NAMED(delay0, r_delay0, 0, *this)
, NAMED(delay1, r_delay1, 0, *this)
, NAMED(fmt, r_fmt, 0, *this)
, NAMED(txdata, r_txdata, 0, *this)
, NAMED(rxdata, r_rxdata, 0, *this)
, NAMED(txmark, r_txmark, 0, *this)
, NAMED(rxmark, r_rxmark, 0, *this)
, NAMED(fctrl, r_fctrl, 0, *this)
, NAMED(ffmt, r_ffmt, 0, *this)
, NAMED(ie, r_ie, 0, *this)
, NAMED(ip, r_ip, 0, *this)
{
}
template<unsigned BUSWIDTH> template <unsigned BUSWIDTH> inline void sysc::spi_regs::registerResources(sysc::tlm_target<BUSWIDTH> &target) {
inline void sysc::spi_regs::registerResources(sysc::tlm_target<BUSWIDTH>& target) {
target.addResource(sckdiv, 0x0UL); target.addResource(sckdiv, 0x0UL);
target.addResource(sckmode, 0x4UL); target.addResource(sckmode, 0x4UL);
target.addResource(csid, 0x10UL); target.addResource(csid, 0x10UL);

View File

@ -36,17 +36,14 @@
#ifndef _UART_REGS_H_ #ifndef _UART_REGS_H_
#define _UART_REGS_H_ #define _UART_REGS_H_
#include <sysc/utilities.h>
#include <util/bit_field.h>
#include <sysc/register.h> #include <sysc/register.h>
#include <sysc/tlm_target.h> #include <sysc/tlm_target.h>
#include <sysc/utilities.h>
#include <util/bit_field.h>
namespace sysc { namespace sysc {
class uart_regs : class uart_regs : public sc_core::sc_module, public sysc::resetable {
public sc_core::sc_module,
public sysc::resetable
{
protected: protected:
// storage declarations // storage declarations
BEGIN_BF_DECL(txdata_t, uint32_t); BEGIN_BF_DECL(txdata_t, uint32_t);
@ -98,8 +95,7 @@ protected:
public: public:
uart_regs(sc_core::sc_module_name nm); uart_regs(sc_core::sc_module_name nm);
template<unsigned BUSWIDTH=32> template <unsigned BUSWIDTH = 32> void registerResources(sysc::tlm_target<BUSWIDTH> &target);
void registerResources(sysc::tlm_target<BUSWIDTH>& target);
}; };
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -107,19 +103,11 @@ public:
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
inline sysc::uart_regs::uart_regs(sc_core::sc_module_name nm) inline sysc::uart_regs::uart_regs(sc_core::sc_module_name nm)
: sc_core::sc_module(nm) : sc_core::sc_module(nm), NAMED(txdata, r_txdata, 0, *this), NAMED(rxdata, r_rxdata, 0, *this),
, NAMED(txdata, r_txdata, 0, *this) NAMED(txctrl, r_txctrl, 0, *this), NAMED(rxctrl, r_rxctrl, 0, *this), NAMED(ie, r_ie, 0, *this),
, NAMED(rxdata, r_rxdata, 0, *this) NAMED(ip, r_ip, 0, *this), NAMED(div, r_div, 0, *this) {}
, NAMED(txctrl, r_txctrl, 0, *this)
, NAMED(rxctrl, r_rxctrl, 0, *this)
, NAMED(ie, r_ie, 0, *this)
, NAMED(ip, r_ip, 0, *this)
, NAMED(div, r_div, 0, *this)
{
}
template<unsigned BUSWIDTH> template <unsigned BUSWIDTH> inline void sysc::uart_regs::registerResources(sysc::tlm_target<BUSWIDTH> &target) {
inline void sysc::uart_regs::registerResources(sysc::tlm_target<BUSWIDTH>& target) {
target.addResource(txdata, 0x0UL); target.addResource(txdata, 0x0UL);
target.addResource(rxdata, 0x4UL); target.addResource(rxdata, 0x4UL);
target.addResource(txctrl, 0x8UL); target.addResource(txctrl, 0x8UL);

View File

@ -30,6 +30,7 @@ public:
sc_core::sc_in<bool> rst_i; sc_core::sc_in<bool> rst_i;
gpio(sc_core::sc_module_name nm); gpio(sc_core::sc_module_name nm);
virtual ~gpio(); virtual ~gpio();
protected: protected:
void clock_cb(); void clock_cb();
void reset_cb(); void reset_cb();

View File

@ -23,18 +23,17 @@
#ifndef SIMPLESYSTEM_H_ #ifndef SIMPLESYSTEM_H_
#define SIMPLESYSTEM_H_ #define SIMPLESYSTEM_H_
#include "uart.h"
#include "spi.h"
#include "gpio.h" #include "gpio.h"
#include "plic.h" #include "plic.h"
#include "spi.h"
#include "uart.h"
#include <sysc/router.h>
#include <sysc/kernel/sc_module.h>
#include <array> #include <array>
#include <sysc/kernel/sc_module.h>
#include <sysc/router.h>
#include "core_complex.h" #include "core_complex.h"
namespace sysc { namespace sysc {
class platform : public sc_core::sc_module { class platform : public sc_core::sc_module {
@ -51,6 +50,7 @@ public:
sc_core::sc_signal<bool> s_rst; sc_core::sc_signal<bool> s_rst;
platform(sc_core::sc_module_name nm); platform(sc_core::sc_module_name nm);
protected: protected:
void gen_reset(); void gen_reset();

View File

@ -30,6 +30,7 @@ public:
sc_core::sc_in<bool> rst_i; sc_core::sc_in<bool> rst_i;
plic(sc_core::sc_module_name nm); plic(sc_core::sc_module_name nm);
virtual ~plic(); virtual ~plic();
protected: protected:
void clock_cb(); void clock_cb();
void reset_cb(); void reset_cb();

View File

@ -30,6 +30,7 @@ public:
sc_core::sc_in<bool> rst_i; sc_core::sc_in<bool> rst_i;
spi(sc_core::sc_module_name nm); spi(sc_core::sc_module_name nm);
virtual ~spi(); virtual ~spi();
protected: protected:
void clock_cb(); void clock_cb();
void reset_cb(); void reset_cb();

View File

@ -30,6 +30,7 @@ public:
sc_core::sc_in<bool> rst_i; sc_core::sc_in<bool> rst_i;
uart(sc_core::sc_module_name nm); uart(sc_core::sc_module_name nm);
virtual ~uart(); virtual ~uart();
protected: protected:
void clock_cb(); void clock_cb();
void reset_cb(); void reset_cb();

View File

@ -20,13 +20,13 @@
* Author: eyck@minres.com * Author: eyck@minres.com
*/ */
#include <sysc/tracer.h>
#include <sysc/scv_tr_db.h>
#include <sr_report/sr_report.h>
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#include <sysc/report.h> #include <sr_report/sr_report.h>
#include <sstream> #include <sstream>
#include <sysc/SiFive/platform.h> #include <sysc/SiFive/platform.h>
#include <sysc/report.h>
#include <sysc/scv_tr_db.h>
#include <sysc/tracer.h>
using namespace sysc; using namespace sysc;
namespace po = boost::program_options; namespace po = boost::program_options;
@ -43,11 +43,9 @@ int sc_main(int argc, char* argv[]){
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// CLI argument parsing // CLI argument parsing
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
po::options_description desc("Options");\ po::options_description desc("Options");
desc.add_options()\ desc.add_options()("help,h", "Print help message")("debug,d", po::value<int>(),
("help,h", "Print help message")\ "set debug level")("trace,t", "trace SystemC signals");
("debug,d", po::value<int>(), "set debug level")\
("trace,t", "trace SystemC signals");
po::variables_map vm; po::variables_map vm;
try { try {
po::store(po::parse_command_line(argc, argv, desc), vm); // can throw po::store(po::parse_command_line(argc, argv, desc), vm); // can throw
@ -71,7 +69,8 @@ int sc_main(int argc, char* argv[]){
// instantiate top level // instantiate top level
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
platform i_simple_system("i_simple_system"); platform i_simple_system("i_simple_system");
//sr_report_handler::add_sc_object_to_filter(&i_simple_system.i_master, sc_core::SC_WARNING, sc_core::SC_MEDIUM); // sr_report_handler::add_sc_object_to_filter(&i_simple_system.i_master,
// sc_core::SC_WARNING, sc_core::SC_MEDIUM);
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// run simulation // run simulation
@ -80,4 +79,3 @@ int sc_main(int argc, char* argv[]){
if (!sc_end_of_simulation_invoked()) sc_stop(); if (!sc_end_of_simulation_invoked()) sc_stop();
return 0; return 0;
} }

View File

@ -39,12 +39,8 @@
namespace sysc { namespace sysc {
namespace SiFive { namespace SiFive {
core_complex::core_complex(sc_core::sc_module_name name) core_complex::core_complex(sc_core::sc_module_name name) : sc_core::sc_module(name), NAMED(initiator), NAMED(rst_i) {
:sc_core::sc_module(name)
, NAMED(initiator)
, NAMED(rst_i){
// TODO Auto-generated constructor stub // TODO Auto-generated constructor stub
} }
core_complex::~core_complex() { core_complex::~core_complex() {

View File

@ -21,12 +21,7 @@
namespace sysc { namespace sysc {
gpio::gpio(sc_core::sc_module_name nm) gpio::gpio(sc_core::sc_module_name nm)
: sc_core::sc_module(nm) : sc_core::sc_module(nm), tlm_target<>(clk), NAMED(clk_i), NAMED(rst_i), NAMEDD(gpio_regs, regs) {
, tlm_target<>(clk)
, NAMED(clk_i)
, NAMED(rst_i)
, NAMEDD(gpio_regs, regs)
{
regs->registerResources(*this); regs->registerResources(*this);
SC_METHOD(clock_cb); SC_METHOD(clock_cb);
sensitive << clk_i; sensitive << clk_i;
@ -34,11 +29,9 @@ gpio::gpio(sc_core::sc_module_name nm)
sensitive << rst_i; sensitive << rst_i;
} }
gpio::~gpio() { gpio::~gpio() {}
}
void gpio::clock_cb() { void gpio::clock_cb() {}
}
void gpio::reset_cb() { void gpio::reset_cb() {
if (rst_i.read()) if (rst_i.read())

View File

@ -25,16 +25,8 @@
namespace sysc { namespace sysc {
platform::platform(sc_core::sc_module_name nm) platform::platform(sc_core::sc_module_name nm)
: sc_core::sc_module(nm) : sc_core::sc_module(nm), NAMED(i_master), NAMED(i_router, 4, 1), NAMED(i_uart), NAMED(i_spi), NAMED(i_gpio),
, NAMED(i_master) NAMED(i_plic), NAMED(s_clk), NAMED(s_rst) {
, NAMED(i_router, 4, 1)
, NAMED(i_uart)
, NAMED(i_spi)
, NAMED(i_gpio)
, NAMED(i_plic)
, NAMED(s_clk)
, NAMED(s_rst)
{
i_master.initiator(i_router.target[0]); i_master.initiator(i_router.target[0]);
size_t i = 0; size_t i = 0;
for (const auto &e : e300_plat_map) { for (const auto &e : e300_plat_map) {

View File

@ -21,12 +21,7 @@
namespace sysc { namespace sysc {
plic::plic(sc_core::sc_module_name nm) plic::plic(sc_core::sc_module_name nm)
: sc_core::sc_module(nm) : sc_core::sc_module(nm), tlm_target<>(clk), NAMED(clk_i), NAMED(rst_i), NAMEDD(plic_regs, regs) {
, tlm_target<>(clk)
, NAMED(clk_i)
, NAMED(rst_i)
, NAMEDD(plic_regs, regs)
{
regs->registerResources(*this); regs->registerResources(*this);
SC_METHOD(clock_cb); SC_METHOD(clock_cb);
sensitive << clk_i; sensitive << clk_i;
@ -34,12 +29,9 @@ plic::plic(sc_core::sc_module_name nm)
sensitive << rst_i; sensitive << rst_i;
} }
plic::~plic() { plic::~plic() {}
}
void plic::clock_cb() { void plic::clock_cb() { this->clk = clk_i.read(); }
this->clk=clk_i.read();
}
void plic::reset_cb() { void plic::reset_cb() {
if (rst_i.read()) if (rst_i.read())

View File

@ -21,12 +21,7 @@
namespace sysc { namespace sysc {
spi::spi(sc_core::sc_module_name nm) spi::spi(sc_core::sc_module_name nm)
: sc_core::sc_module(nm) : sc_core::sc_module(nm), tlm_target<>(clk), NAMED(clk_i), NAMED(rst_i), NAMEDD(spi_regs, regs) {
, tlm_target<>(clk)
, NAMED(clk_i)
, NAMED(rst_i)
, NAMEDD(spi_regs, regs)
{
regs->registerResources(*this); regs->registerResources(*this);
SC_METHOD(clock_cb); SC_METHOD(clock_cb);
sensitive << clk_i; sensitive << clk_i;
@ -34,12 +29,9 @@ spi::spi(sc_core::sc_module_name nm)
sensitive << rst_i; sensitive << rst_i;
} }
spi::~spi() { spi::~spi() {}
}
void spi::clock_cb() { void spi::clock_cb() { this->clk = clk_i.read(); }
this->clk=clk_i.read();
}
void spi::reset_cb() { void spi::reset_cb() {
if (rst_i.read()) if (rst_i.read())

View File

@ -21,12 +21,7 @@
namespace sysc { namespace sysc {
uart::uart(sc_core::sc_module_name nm) uart::uart(sc_core::sc_module_name nm)
: sc_core::sc_module(nm) : sc_core::sc_module(nm), tlm_target<>(clk), NAMED(clk_i), NAMED(rst_i), NAMEDD(uart_regs, regs) {
, tlm_target<>(clk)
, NAMED(clk_i)
, NAMED(rst_i)
, NAMEDD(uart_regs, regs)
{
regs->registerResources(*this); regs->registerResources(*this);
SC_METHOD(clock_cb); SC_METHOD(clock_cb);
sensitive << clk_i; sensitive << clk_i;
@ -34,12 +29,9 @@ uart::uart(sc_core::sc_module_name nm)
sensitive << rst_i; sensitive << rst_i;
} }
uart::~uart() { uart::~uart() {}
}
void uart::clock_cb() { void uart::clock_cb() { this->clk = clk_i.read(); }
this->clk=clk_i.read();
}
void uart::reset_cb() { void uart::reset_cb() {
if (rst_i.read()) if (rst_i.read())

View File

@ -35,9 +35,9 @@
#ifndef _CLI_OPTIONS_H_ #ifndef _CLI_OPTIONS_H_
#define _CLI_OPTIONS_H_ #define _CLI_OPTIONS_H_
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#include <util/logging.h>
#include <iostream>
#include <cstdio> #include <cstdio>
#include <iostream>
#include <util/logging.h>
const size_t ERROR_IN_COMMAND_LINE = 1; const size_t ERROR_IN_COMMAND_LINE = 1;
const size_t SUCCESS = 0; const size_t SUCCESS = 0;
@ -46,24 +46,22 @@ const size_t ERROR_UNHANDLED_EXCEPTION = 2;
inline int parse_cli_options(boost::program_options::variables_map &vm, int argc, char *argv[]) { inline int parse_cli_options(boost::program_options::variables_map &vm, int argc, char *argv[]) {
namespace po = boost::program_options; namespace po = boost::program_options;
po::options_description desc("Options"); po::options_description desc("Options");
desc.add_options() desc.add_options()("help,h", "Print help message")("verbose,v", po::value<int>()->implicit_value(0),
("help,h", "Print help message") "Sets logging verbosity")("vmodule", po::value<std::string>(),
("verbose,v", po::value<int>()->implicit_value(0), "Sets logging verbosity") "Defines the module(s) to be logged")(
("vmodule", po::value<std::string>(),"Defines the module(s) to be logged") "logging-flags", po::value<int>(), "Sets logging flag(s).")("log-file", po::value<std::string>(),
("logging-flags", po::value<int>(),"Sets logging flag(s).") "Sets default log file.")(
("log-file", po::value<std::string>(),"Sets default log file.") "disass,d", po::value<std::string>()->implicit_value(""),
("disass,d", po::value<std::string>()->implicit_value(""),"Enables disassembly") "Enables disassembly")("elf,l", po::value<std::vector<std::string>>(), "ELF file(s) to load")(
("elf,l", po::value< std::vector<std::string> >(), "ELF file(s) to load") "gdb-port,g", po::value<unsigned>(), "enable gdb server and specify port to use")(
("gdb-port,g", po::value<unsigned>(), "enable gdb server and specify port to use") "input,i", po::value<std::string>(), "the elf file to load (instead of hex files)")(
("input,i", po::value<std::string>(), "the elf file to load (instead of hex files)") "dump-ir", "dump the intermediate representation")("cycles,c", po::value<int64_t>()->default_value(-1),
("dump-ir", "dump the intermediate representation") "number of cycles to run")(
("cycles,c", po::value<int64_t>()->default_value(-1), "number of cycles to run") "systemc,s", "Run as SystemC simulation")("time", po::value<int>(), "SystemC siimulation time in ms")(
("systemc,s", "Run as SystemC simulation") "reset,r", po::value<std::string>(), "reset address")(
("time", po::value<int>(), "SystemC siimulation time in ms") "trace", po::value<uint8_t>(), "enable tracing, or cmbintation of 1=signals and 2=TX text, 4=TX "
("reset,r", po::value<std::string>(), "reset address") "compressed text, 6=TX in SQLite")("mem,m", po::value<std::string>(),
("trace", po::value<uint8_t>(), "enable tracing, or cmbintation of 1=signals and 2=TX text, 4=TX compressed text, 6=TX in SQLite")\ "the memory input file")("rv64", "run RV64");
("mem,m", po::value<std::string>(), "the memory input file")
("rv64", "run RV64");
try { try {
po::store(po::parse_command_line(argc, argv, desc), vm); // can throw po::store(po::parse_command_line(argc, argv, desc), vm); // can throw
// --help option // --help option

View File

@ -35,23 +35,21 @@
#ifndef _RISCV_CORE_H_ #ifndef _RISCV_CORE_H_
#define _RISCV_CORE_H_ #define _RISCV_CORE_H_
#include <iss/vm_if.h> #include <elfio/elfio.hpp>
#include <iomanip>
#include <iss/arch/traits.h>
#include <iss/arch_if.h> #include <iss/arch_if.h>
#include <iss/log_categories.h>
#include <iss/vm_if.h>
#include <sstream>
#include <unordered_map>
#include <util/ities.h> #include <util/ities.h>
#include <util/sparse_array.h> #include <util/sparse_array.h>
#include <elfio/elfio.hpp>
#include <iss/log_categories.h>
#include <sstream>
#include <iomanip>
#include <unordered_map>
namespace iss { namespace iss {
namespace arch { namespace arch {
enum { enum { tohost_dflt = 0xF0001000, fromhost_dflt = 0xF0001040 };
tohost_dflt = 0xF0001000,
fromhost_dflt = 0xF0001040
};
enum csr_name { enum csr_name {
/* user-level CSR */ /* user-level CSR */
@ -162,8 +160,7 @@ namespace {
const char lvl[] = {'U', 'S', 'H', 'M'}; const char lvl[] = {'U', 'S', 'H', 'M'};
const char* trap_str[] = { const char *trap_str[] = {"Instruction address misaligned",
"Instruction address misaligned",
"Instruction access fault", "Instruction access fault",
"Illegal instruction", "Illegal instruction",
"Breakpoint", "Breakpoint",
@ -178,22 +175,11 @@ const char* trap_str[] = {
"Instruction page fault", "Instruction page fault",
"Load page fault", "Load page fault",
"Reserved", "Reserved",
"Store/AMO page fault" "Store/AMO page fault"};
};
const char *irq_str[] = { const char *irq_str[] = {
"User software interrupt", "User software interrupt", "Supervisor software interrupt", "Reserved", "Machine software interrupt",
"Supervisor software interrupt", "User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt",
"Reserved", "User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"};
"Machine software interrupt",
"User timer interrupt",
"Supervisor timer interrupt",
"Reserved",
"Machine timer interrupt",
"User external interrupt",
"Supervisor external interrupt",
"Reserved",
"Machine external interrupt"
};
enum { enum {
PGSHIFT = 12, PGSHIFT = 12,
@ -210,11 +196,7 @@ enum {
PTE_SOFT = 0x300 // Reserved for Software PTE_SOFT = 0x300 // Reserved for Software
}; };
template<typename T> template <typename T> inline bool PTE_TABLE(T PTE) { return (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V); }
inline bool PTE_TABLE(T PTE){
return (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V);
}
enum { PRIV_U = 0, PRIV_S = 1, PRIV_M = 3 }; enum { PRIV_U = 0, PRIV_S = 1, PRIV_M = 3 };
@ -231,7 +213,8 @@ enum {
ISA_N = 1 << 13, ISA_N = 1 << 13,
ISA_Q = 1 << 16, ISA_Q = 1 << 16,
ISA_S = 1 << 18, ISA_S = 1 << 18,
ISA_U=1<<20}; ISA_U = 1 << 20
};
struct vm_info { struct vm_info {
int levels; int levels;
@ -240,7 +223,6 @@ struct vm_info {
uint64_t ptbase; uint64_t ptbase;
}; };
struct trap_load_access_fault : public trap_access { struct trap_load_access_fault : public trap_access {
trap_load_access_fault(uint64_t badaddr) : trap_access(5 << 16, badaddr) {} trap_load_access_fault(uint64_t badaddr) : trap_access(5 << 16, badaddr) {}
}; };
@ -261,8 +243,9 @@ struct trap_store_page_fault: public trap_access {
typedef union { typedef union {
uint32_t val; uint32_t val;
struct /*mstatus*/ { struct /*mstatus*/ {
uint32_t uint32_t SD : 1, // SD bit is read-only and is set when either the FS or XS
SD:1, //SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR (XS==11))) // bits encode a Dirty state (i.e., SD=((FS==11) OR
// (XS==11)))
_WPRI3 : 8, // unused _WPRI3 : 8, // unused
TSR : 1, // Trap SRET TSR : 1, // Trap SRET
TW : 1, // Timeout Wait TW : 1, // Timeout Wait
@ -270,7 +253,9 @@ typedef union {
MXR : 1, // Make eXecutable Readable MXR : 1, // Make eXecutable Readable
SUM : 1, // permit Supervisor User Memory access SUM : 1, // permit Supervisor User Memory access
MPRV : 1, // Modify PRiVilege MPRV : 1, // Modify PRiVilege
XS:2, //status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty XS : 2, // status of additional user-mode extensions and associated
// state, All off/None dirty or clean, some on/None dirty, some
// clean/Some dirty
FS : 2, // floating-point unit status Off/Initial/Clean/Dirty FS : 2, // floating-point unit status Off/Initial/Clean/Dirty
MPP : 2, // machine previous privilege MPP : 2, // machine previous privilege
_WPRI2 : 2, // unused _WPRI2 : 2, // unused
@ -285,35 +270,11 @@ typedef union {
UIE : 1; // user interrupt-enable UIE : 1; // user interrupt-enable
} m; } m;
struct /*sstatus*/ { struct /*sstatus*/ {
uint32_t uint32_t SD : 1, _WPRI4 : 11, MXR : 1, SUM : 1, _WPRI3 : 1, XS : 2, FS : 2, _WPRI2 : 4, SPP : 1, _WPRI1 : 2,
SD:1, SPIE : 1, UPIE : 1, _WPRI0 : 2, SIE : 1, UIE : 1;
_WPRI4:11,
MXR:1,
SUM:1,
_WPRI3:1,
XS:2,
FS:2,
_WPRI2:4,
SPP:1,
_WPRI1:2,
SPIE:1,
UPIE:1,
_WPRI0:2,
SIE:1,
UIE:1;
} s; } s;
struct /*ustatus*/ { struct /*ustatus*/ {
uint32_t uint32_t SD : 1, _WPRI4 : 11, MXR : 1, SUM : 1, _WPRI3 : 1, XS : 2, FS : 2, _WPRI2 : 8, UPIE : 1, _WPRI0 : 3,
SD:1,
_WPRI4:11,
MXR:1,
SUM:1,
_WPRI3:1,
XS:2,
FS:2,
_WPRI2:8,
UPIE:1,
_WPRI0:3,
UIE : 1; UIE : 1;
} u; } u;
} mstatus32_t; } mstatus32_t;
@ -321,8 +282,9 @@ typedef union {
typedef union { typedef union {
uint64_t val; uint64_t val;
struct /*mstatus*/ { struct /*mstatus*/ {
uint64_t uint64_t SD : 1, // SD bit is read-only and is set when either the FS or XS
SD:1, // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR (XS==11))) // bits encode a Dirty state (i.e., SD=((FS==11) OR
// (XS==11)))
_WPRI4 : 27, // unused _WPRI4 : 27, // unused
SXL : 2, // value of XLEN for S-mode SXL : 2, // value of XLEN for S-mode
UXL : 2, // value of XLEN for U-mode UXL : 2, // value of XLEN for U-mode
@ -333,7 +295,9 @@ typedef union {
MXR : 1, // Make eXecutable Readable MXR : 1, // Make eXecutable Readable
SUM : 1, // permit Supervisor User Memory access SUM : 1, // permit Supervisor User Memory access
MPRV : 1, // Modify PRiVilege MPRV : 1, // Modify PRiVilege
XS:2, // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty XS : 2, // status of additional user-mode extensions and associated
// state, All off/None dirty or clean, some on/None dirty, some
// clean/Some dirty
FS : 2, // floating-point unit status Off/Initial/Clean/Dirty FS : 2, // floating-point unit status Off/Initial/Clean/Dirty
MPP : 2, // machine previous privilege MPP : 2, // machine previous privilege
_WPRI2 : 2, // unused _WPRI2 : 2, // unused
@ -348,48 +312,23 @@ typedef union {
UIE : 1; // user interrupt-enable UIE : 1; // user interrupt-enable
} m; } m;
struct /*sstatus*/ { struct /*sstatus*/ {
uint64_t uint64_t SD : 1,
SD:1,
_WPRI5 : 29, // unused _WPRI5 : 29, // unused
UXL : 2, // value of XLEN for U-mode UXL : 2, // value of XLEN for U-mode
_WPRI4:12, _WPRI4 : 12, MXR : 1, SUM : 1, _WPRI3 : 1, XS : 2, FS : 2, _WPRI2 : 4, SPP : 1, _WPRI1 : 2, SPIE : 1,
MXR:1, UPIE : 1, _WPRI0 : 2, SIE : 1, UIE : 1;
SUM:1,
_WPRI3:1,
XS:2,
FS:2,
_WPRI2:4,
SPP:1,
_WPRI1:2,
SPIE:1,
UPIE:1,
_WPRI0:2,
SIE:1,
UIE:1;
} s; } s;
struct /*ustatus*/ { struct /*ustatus*/ {
uint32_t uint32_t SD : 1,
SD:1,
_WPRI4 : 29, // unused _WPRI4 : 29, // unused
UXL : 2, // value of XLEN for U-mode UXL : 2, // value of XLEN for U-mode
_WPRI3:12, _WPRI3 : 12, MXR : 1, SUM : 1, _WPRI2 : 1, XS : 2, FS : 2, _WPRI1 : 8, UPIE : 1, _WPRI0 : 3, UIE : 1;
MXR:1,
SUM:1,
_WPRI2:1,
XS:2,
FS:2,
_WPRI1:8,
UPIE:1,
_WPRI0:3,
UIE:1;
} u; } u;
} mstatus64_t; } mstatus64_t;
template<unsigned L> template <unsigned L> inline vm_info decode_vm_info(uint32_t state, uint64_t sptbr);
inline vm_info decode_vm_info(uint32_t state, uint64_t sptbr);
template<> template <> inline vm_info decode_vm_info<32u>(uint32_t state, uint64_t sptbr) {
inline vm_info decode_vm_info<32u>(uint32_t state, uint64_t sptbr){
if (state == PRIV_M) { if (state == PRIV_M) {
return {0, 0, 0, 0}; return {0, 0, 0, 0};
} else if (state <= PRIV_S) { } else if (state <= PRIV_S) {
@ -398,7 +337,8 @@ inline vm_info decode_vm_info<32u>(uint32_t state, uint64_t sptbr){
return {0, 0, 0, 0}; return {0, 0, 0, 0};
case 1: // SV32 case 1: // SV32
return {2, 10, 4, bit_sub<0, 22>(sptbr) << PGSHIFT}; return {2, 10, 4, bit_sub<0, 22>(sptbr) << PGSHIFT};
default: abort(); default:
abort();
} }
} else { } else {
abort(); abort();
@ -406,8 +346,7 @@ inline vm_info decode_vm_info<32u>(uint32_t state, uint64_t sptbr){
return {0, 0, 0, 0}; // dummy return {0, 0, 0, 0}; // dummy
} }
template<> template <> inline vm_info decode_vm_info<64u>(uint32_t state, uint64_t sptbr) {
inline vm_info decode_vm_info<64u>(uint32_t state, uint64_t sptbr){
if (state == PRIV_M) { if (state == PRIV_M) {
return {0, 0, 0, 0}; return {0, 0, 0, 0};
} else if (state <= PRIV_S) { } else if (state <= PRIV_S) {
@ -422,7 +361,8 @@ inline vm_info decode_vm_info<64u>(uint32_t state, uint64_t sptbr){
return {5, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; return {5, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};
case 11: // SV64 case 11: // SV64
return {6, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; return {6, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};
default: abort(); default:
abort();
} }
} else { } else {
abort(); abort();
@ -430,7 +370,6 @@ inline vm_info decode_vm_info<64u>(uint32_t state, uint64_t sptbr){
return {0, 0, 0, 0}; // dummy return {0, 0, 0, 0}; // dummy
} }
constexpr uint32_t get_mask(unsigned priv_lvl, uint32_t mask) { constexpr uint32_t get_mask(unsigned priv_lvl, uint32_t mask) {
switch (priv_lvl) { switch (priv_lvl) {
case PRIV_U: case PRIV_U:
@ -445,24 +384,22 @@ constexpr uint32_t get_mask(unsigned priv_lvl, uint32_t mask){
constexpr uint64_t get_mask(unsigned priv_lvl, uint64_t mask) { constexpr uint64_t get_mask(unsigned priv_lvl, uint64_t mask) {
switch (priv_lvl) { switch (priv_lvl) {
case PRIV_U: case PRIV_U:
return mask&0x8000000000000011ULL; //0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 return mask & 0x8000000000000011ULL; // 0b1...0 1111 0000 0000 0111 1111
// 1111 1001 1011 1011
case PRIV_S: case PRIV_S:
return mask&0x80000003000de133ULL; //0b1...0 0011 0000 0000 0000 1101 1110 0001 0011 0011 return mask & 0x80000003000de133ULL; // 0b1...0 0011 0000 0000 0000 1101
// 1110 0001 0011 0011
default: default:
return mask&0x8000000f007ff9ddULL; //0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 return mask & 0x8000000f007ff9ddULL; // 0b1...0 1111 0000 0000 0111 1111
// 1111 1001 1011 1011
} }
} }
constexpr uint32_t get_misa(uint32_t mask){ constexpr uint32_t get_misa(uint32_t mask) { return (1UL << 30) | ISA_I | ISA_M | ISA_A | ISA_U | ISA_S | ISA_M; }
return (1UL<<30)| ISA_I | ISA_M | ISA_A | ISA_U | ISA_S | ISA_M ;
}
constexpr uint64_t get_misa(uint64_t mask){ constexpr uint64_t get_misa(uint64_t mask) { return (2ULL << 62) | ISA_I | ISA_M | ISA_A | ISA_U | ISA_S | ISA_M; }
return (2ULL<<62)| ISA_I | ISA_M | ISA_A | ISA_U | ISA_S | ISA_M ;
}
template<typename BASE> template <typename BASE> struct riscv_hart_msu_vp : public BASE {
struct riscv_hart_msu_vp: public BASE {
using super = BASE; using super = BASE;
using this_class = riscv_hart_msu_vp<BASE>; using this_class = riscv_hart_msu_vp<BASE>;
using virt_addr_t = typename super::virt_addr_t; using virt_addr_t = typename super::virt_addr_t;
@ -503,7 +440,8 @@ struct riscv_hart_msu_vp: public BASE {
virtual std::string get_additional_disass_info() { virtual std::string get_additional_disass_info() {
std::stringstream s; std::stringstream s;
s<<"[p:"<<lvl[this->reg.machine_state]<<";s:0x"<<std::hex<<std::setfill('0')<<std::setw(sizeof(reg_t)*2)<<mstatus_r<<std::dec<<";c:"<<this->reg.icount<<"]"; s << "[p:" << lvl[this->reg.machine_state] << ";s:0x" << std::hex << std::setfill('0')
<< std::setw(sizeof(reg_t) * 2) << mstatus_r << std::dec << ";c:" << this->reg.icount << "]";
return s.str(); return s.str();
}; };
@ -545,16 +483,13 @@ private:
void check_interrupt(); void check_interrupt();
}; };
template<typename BASE> template <typename BASE> riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp() : mstatus_r(csr[mstatus]), satp_r(csr[satp]) {
riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp() : mstatus_r(csr[mstatus]), satp_r(csr[satp]) {
csr[misa] = traits<BASE>::XLEN == 32 ? 1ULL << (traits<BASE>::XLEN - 2) : 2ULL << (traits<BASE>::XLEN - 2); csr[misa] = traits<BASE>::XLEN == 32 ? 1ULL << (traits<BASE>::XLEN - 2) : 2ULL << (traits<BASE>::XLEN - 2);
uart_buf.str(""); uart_buf.str("");
// read-only registers // read-only registers
csr_wr_cb[misa] = nullptr; csr_wr_cb[misa] = nullptr;
for(unsigned addr=mcycle; addr<=hpmcounter31; ++addr) for (unsigned addr = mcycle; addr <= hpmcounter31; ++addr) csr_wr_cb[addr] = nullptr;
csr_wr_cb[addr]=nullptr; for (unsigned addr = mcycleh; addr <= hpmcounter31h; ++addr) csr_wr_cb[addr] = nullptr;
for(unsigned addr=mcycleh; addr<=hpmcounter31h; ++addr)
csr_wr_cb[addr]=nullptr;
// special handling // special handling
csr_rd_cb[mcycle] = &riscv_hart_msu_vp<BASE>::read_cycle; csr_rd_cb[mcycle] = &riscv_hart_msu_vp<BASE>::read_cycle;
csr_rd_cb[mcycleh] = &riscv_hart_msu_vp<BASE>::read_cycle; csr_rd_cb[mcycleh] = &riscv_hart_msu_vp<BASE>::read_cycle;
@ -582,12 +517,9 @@ riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp() : mstatus_r(csr[mstatus]), satp_r(c
csr_wr_cb[satp] = &riscv_hart_msu_vp<BASE>::write_satp; csr_wr_cb[satp] = &riscv_hart_msu_vp<BASE>::write_satp;
} }
template<typename BASE> template <typename BASE> riscv_hart_msu_vp<BASE>::~riscv_hart_msu_vp() {}
riscv_hart_msu_vp<BASE>::~riscv_hart_msu_vp() {
}
template<typename BASE> template <typename BASE> void riscv_hart_msu_vp<BASE>::load_file(std::string name, int type) {
void riscv_hart_msu_vp<BASE>::load_file(std::string name, int type) {
FILE *fp = fopen(name.c_str(), "r"); FILE *fp = fopen(name.c_str(), "r");
if (fp) { if (fp) {
char buf[5]; char buf[5];
@ -602,15 +534,19 @@ void riscv_hart_msu_vp<BASE>::load_file(std::string name, int type) {
if (!reader.load(name)) throw std::runtime_error("could not process elf file"); if (!reader.load(name)) throw std::runtime_error("could not process elf file");
// check elf properties // check elf properties
// TODO: fix ELFCLASS like: // TODO: fix ELFCLASS like:
// if ( reader.get_class() != ELFCLASS32 ) throw std::runtime_error("wrong elf class in file"); // if ( reader.get_class() != ELFCLASS32 ) throw std::runtime_error("wrong
// elf class in file");
if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file"); if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file");
// TODO: fix machine type like: // TODO: fix machine type like:
// if ( reader.get_machine() != EM_RISCV ) throw std::runtime_error("wrong elf machine in file"); // if ( reader.get_machine() != EM_RISCV ) throw std::runtime_error("wrong
// elf machine in file");
for (const auto pseg : reader.segments) { for (const auto pseg : reader.segments) {
const auto fsize = pseg->get_file_size(); // 0x42c/0x0 const auto fsize = pseg->get_file_size(); // 0x42c/0x0
const auto seg_data = pseg->get_data(); const auto seg_data = pseg->get_data();
if (fsize > 0) { if (fsize > 0) {
this->write(typed_addr_t<PHYSICAL>(iss::DEBUG_WRITE, traits<BASE>::MEM, pseg->get_virtual_address()), fsize, reinterpret_cast<const uint8_t* const>(seg_data)); this->write(
typed_addr_t<PHYSICAL>(iss::DEBUG_WRITE, traits<BASE>::MEM, pseg->get_virtual_address()), fsize,
reinterpret_cast<const uint8_t *const>(seg_data));
} }
} }
for (const auto sec : reader.sections) { for (const auto sec : reader.sections) {
@ -637,8 +573,7 @@ iss::status riscv_hart_msu_vp<BASE>::read(const iss::addr_t& addr, unsigned leng
case traits<BASE>::MEM: { case traits<BASE>::MEM: {
if ((addr.type & (iss::ACCESS_TYPE - iss::DEBUG)) == iss::FETCH && (addr.val & 0x1) == 1) { if ((addr.type & (iss::ACCESS_TYPE - iss::DEBUG)) == iss::FETCH && (addr.val & 0x1) == 1) {
fault_data = addr.val; fault_data = addr.val;
if((addr.type&iss::DEBUG)) if ((addr.type & iss::DEBUG)) throw trap_access(0, addr.val);
throw trap_access(0, addr.val);
this->reg.trap_state = (1 << 31); // issue trap 0 this->reg.trap_state = (1 << 31); // issue trap 0
return iss::Err; return iss::Err;
} }
@ -660,34 +595,24 @@ iss::status riscv_hart_msu_vp<BASE>::read(const iss::addr_t& addr, unsigned leng
case 0x0200BFF8: { // CLINT base, mtime reg case 0x0200BFF8: { // CLINT base, mtime reg
uint64_t mtime = this->reg.icount >> 12 /*12*/; uint64_t mtime = this->reg.icount >> 12 /*12*/;
std::copy((uint8_t *)&mtime, ((uint8_t *)&mtime) + length, data); std::copy((uint8_t *)&mtime, ((uint8_t *)&mtime) + length, data);
} } break;
break;
case 0x10008000: { case 0x10008000: {
const mem_type::page_type &p = mem(paddr.val / mem.page_size); const mem_type::page_type &p = mem(paddr.val / mem.page_size);
uint64_t offs = paddr.val & mem.page_addr_mask; uint64_t offs = paddr.val & mem.page_addr_mask;
std::copy( std::copy(p.data() + offs, p.data() + offs + length, data);
p.data() + offs, if (this->reg.icount > 30000) data[3] |= 0x80;
p.data() + offs+length, } break;
data); default: { return read_mem(paddr, length, data); }
if(this->reg.icount>30000)
data[3]|=0x80;
}
break;
default:{
return read_mem(paddr, length, data);
}
} }
} catch (trap_access &ta) { } catch (trap_access &ta) {
this->reg.trap_state = (1 << 31) | ta.id; this->reg.trap_state = (1 << 31) | ta.id;
return iss::Err; return iss::Err;
} }
} } break;
break;
case traits<BASE>::CSR: { case traits<BASE>::CSR: {
if (length != sizeof(reg_t)) return iss::Err; if (length != sizeof(reg_t)) return iss::Err;
return read_csr(addr.val, *reinterpret_cast<reg_t *const>(data)); return read_csr(addr.val, *reinterpret_cast<reg_t *const>(data));
} } break;
break;
case traits<BASE>::FENCE: { case traits<BASE>::FENCE: {
if ((addr.val + length) > mem.size()) return iss::Err; if ((addr.val + length) > mem.size()) return iss::Err;
switch (addr.val) { switch (addr.val) {
@ -703,8 +628,7 @@ iss::status riscv_hart_msu_vp<BASE>::read(const iss::addr_t& addr, unsigned leng
return iss::Ok; return iss::Ok;
} }
} }
} } break;
break;
case traits<BASE>::RES: { case traits<BASE>::RES: {
auto it = atomic_reservation.find(addr.val); auto it = atomic_reservation.find(addr.val);
if (it != atomic_reservation.end() && (*it).second != 0) { if (it != atomic_reservation.end() && (*it).second != 0) {
@ -712,8 +636,7 @@ iss::status riscv_hart_msu_vp<BASE>::read(const iss::addr_t& addr, unsigned leng
atomic_reservation.erase(addr.val); atomic_reservation.erase(addr.val);
} else } else
memset(data, 0, length); memset(data, 0, length);
} } break;
break;
default: default:
return iss::Err; // assert("Not supported"); return iss::Err; // assert("Not supported");
} }
@ -726,16 +649,20 @@ iss::status riscv_hart_msu_vp<BASE>::write(const iss::addr_t& addr, unsigned len
const char *prefix = addr.type & iss::DEBUG ? "debug " : ""; const char *prefix = addr.type & iss::DEBUG ? "debug " : "";
switch (length) { switch (length) {
case 8: case 8:
LOG(DEBUG)<<prefix<<"write of "<<length<<" bytes (0x"<<std::hex<<*(uint64_t*)&data[0]<<std::dec<<") @addr "<<addr; LOG(DEBUG) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec
<< ") @addr " << addr;
break; break;
case 4: case 4:
LOG(DEBUG)<<prefix<<"write of "<<length<<" bytes (0x"<<std::hex<<*(uint32_t*)&data[0]<<std::dec<<") @addr "<<addr; LOG(DEBUG) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t *)&data[0] << std::dec
<< ") @addr " << addr;
break; break;
case 2: case 2:
LOG(DEBUG)<<prefix<<"write of "<<length<<" bytes (0x"<<std::hex<<*(uint16_t*)&data[0]<<std::dec<<") @addr "<<addr; LOG(DEBUG) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t *)&data[0] << std::dec
<< ") @addr " << addr;
break; break;
case 1: case 1:
LOG(DEBUG)<<prefix<<"write of "<<length<<" bytes (0x"<<std::hex<<(uint16_t)data[0]<<std::dec<<") @addr "<<addr; LOG(DEBUG) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec
<< ") @addr " << addr;
break; break;
default: default:
LOG(DEBUG) << prefix << "write of " << length << " bytes @addr " << addr; LOG(DEBUG) << prefix << "write of " << length << " bytes @addr " << addr;
@ -751,7 +678,8 @@ iss::status riscv_hart_msu_vp<BASE>::write(const iss::addr_t& addr, unsigned len
case 0x10023000: // UART1 base, TXFIFO reg case 0x10023000: // UART1 base, TXFIFO reg
uart_buf << (char)data[0]; uart_buf << (char)data[0];
if (((char)data[0]) == '\n' || data[0] == 0) { if (((char)data[0]) == '\n' || data[0] == 0) {
// LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send '"<<uart_buf.str()<<"'"; // LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send
// '"<<uart_buf.str()<<"'";
std::cout << uart_buf.str(); std::cout << uart_buf.str();
uart_buf.str(""); uart_buf.str("");
} }
@ -771,19 +699,14 @@ iss::status riscv_hart_msu_vp<BASE>::write(const iss::addr_t& addr, unsigned len
uint8_t &x = *(p.data() + offs + 3); uint8_t &x = *(p.data() + offs + 3);
x |= 0x80; // set pll lock upon writing x |= 0x80; // set pll lock upon writing
return iss::Ok; return iss::Ok;
} break;
default: { return write_mem(paddr, length, data); }
} }
break; } break;
default:{
return write_mem(paddr, length, data);
}
}
}
break;
case traits<BASE>::CSR: { case traits<BASE>::CSR: {
if (length != sizeof(reg_t)) return iss::Err; if (length != sizeof(reg_t)) return iss::Err;
return write_csr(addr.val, *reinterpret_cast<const reg_t *>(data)); return write_csr(addr.val, *reinterpret_cast<const reg_t *>(data));
} } break;
break;
case traits<BASE>::FENCE: { case traits<BASE>::FENCE: {
if ((addr.val + length) > mem.size()) return iss::Err; if ((addr.val + length) > mem.size()) return iss::Err;
switch (addr.val) { switch (addr.val) {
@ -800,12 +723,10 @@ iss::status riscv_hart_msu_vp<BASE>::write(const iss::addr_t& addr, unsigned len
return iss::Ok; return iss::Ok;
} }
} }
} } break;
break;
case traits<BASE>::RES: { case traits<BASE>::RES: {
atomic_reservation[addr.val] = data[0]; atomic_reservation[addr.val] = data[0];
} } break;
break;
default: default:
return iss::Err; return iss::Err;
} }
@ -816,8 +737,7 @@ iss::status riscv_hart_msu_vp<BASE>::write(const iss::addr_t& addr, unsigned len
} }
} }
template<typename BASE> template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_csr(unsigned addr, reg_t &val) {
iss::status riscv_hart_msu_vp<BASE>::read_csr(unsigned addr, reg_t& val){
if (addr >= csr.size()) return iss::Err; if (addr >= csr.size()) return iss::Err;
auto it = csr_rd_cb.find(addr); auto it = csr_rd_cb.find(addr);
if (it == csr_rd_cb.end()) { if (it == csr_rd_cb.end()) {
@ -825,13 +745,11 @@ iss::status riscv_hart_msu_vp<BASE>::read_csr(unsigned addr, reg_t& val){
return iss::Ok; return iss::Ok;
} }
rd_csr_f f = it->second; rd_csr_f f = it->second;
if(f==nullptr) if (f == nullptr) throw illegal_instruction_fault(this->fault_data);
throw illegal_instruction_fault(this->fault_data);
return (this->*f)(addr, val); return (this->*f)(addr, val);
} }
template<typename BASE> template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_csr(unsigned addr, reg_t val) {
iss::status riscv_hart_msu_vp<BASE>::write_csr(unsigned addr, reg_t val){
if (addr >= csr.size()) return iss::Err; if (addr >= csr.size()) return iss::Err;
auto it = csr_wr_cb.find(addr); auto it = csr_wr_cb.find(addr);
if (it == csr_wr_cb.end()) { if (it == csr_wr_cb.end()) {
@ -839,14 +757,11 @@ iss::status riscv_hart_msu_vp<BASE>::write_csr(unsigned addr, reg_t val){
return iss::Ok; return iss::Ok;
} }
wr_csr_f f = it->second; wr_csr_f f = it->second;
if(f==nullptr) if (f == nullptr) throw illegal_instruction_fault(this->fault_data);
throw illegal_instruction_fault(this->fault_data);
return (this->*f)(addr, val); return (this->*f)(addr, val);
} }
template<typename BASE> template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_cycle(unsigned addr, reg_t &val) {
iss::status riscv_hart_msu_vp<BASE>::read_cycle(unsigned addr, reg_t& val) {
if (addr == mcycle) { if (addr == mcycle) {
val = static_cast<reg_t>(this->reg.icount); val = static_cast<reg_t>(this->reg.icount);
} else if (addr == mcycleh) { } else if (addr == mcycleh) {
@ -856,8 +771,7 @@ iss::status riscv_hart_msu_vp<BASE>::read_cycle(unsigned addr, reg_t& val) {
return iss::Ok; return iss::Ok;
} }
template<typename BASE> template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_status(unsigned addr, reg_t &val) {
iss::status riscv_hart_msu_vp<BASE>::read_status(unsigned addr, reg_t& val) {
auto req_priv_lvl = addr >> 8; auto req_priv_lvl = addr >> 8;
if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data); if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data);
auto mask = get_mask(req_priv_lvl, (reg_t)(std::numeric_limits<reg_t>::max())); auto mask = get_mask(req_priv_lvl, (reg_t)(std::numeric_limits<reg_t>::max()));
@ -865,8 +779,7 @@ iss::status riscv_hart_msu_vp<BASE>::read_status(unsigned addr, reg_t& val) {
return iss::Ok; return iss::Ok;
} }
template<typename BASE> template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_status(unsigned addr, reg_t val) {
iss::status riscv_hart_msu_vp<BASE>::write_status(unsigned addr, reg_t val) {
auto req_priv_lvl = addr >> 8; auto req_priv_lvl = addr >> 8;
if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data); if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data);
auto mask = get_mask(req_priv_lvl, (reg_t)std::numeric_limits<reg_t>::max()); auto mask = get_mask(req_priv_lvl, (reg_t)std::numeric_limits<reg_t>::max());
@ -877,8 +790,7 @@ iss::status riscv_hart_msu_vp<BASE>::write_status(unsigned addr, reg_t val) {
return iss::Ok; return iss::Ok;
} }
template<typename BASE> template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_ie(unsigned addr, reg_t &val) {
iss::status riscv_hart_msu_vp<BASE>::read_ie(unsigned addr, reg_t& val) {
auto req_priv_lvl = addr >> 8; auto req_priv_lvl = addr >> 8;
if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data); if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data);
val = csr[mie]; val = csr[mie];
@ -887,8 +799,7 @@ iss::status riscv_hart_msu_vp<BASE>::read_ie(unsigned addr, reg_t& val) {
return iss::Ok; return iss::Ok;
} }
template<typename BASE> template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_ie(unsigned addr, reg_t val) {
iss::status riscv_hart_msu_vp<BASE>::write_ie(unsigned addr, reg_t val) {
auto req_priv_lvl = addr >> 8; auto req_priv_lvl = addr >> 8;
if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data); if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data);
auto mask = get_irq_mask(req_priv_lvl); auto mask = get_irq_mask(req_priv_lvl);
@ -897,8 +808,7 @@ iss::status riscv_hart_msu_vp<BASE>::write_ie(unsigned addr, reg_t val) {
return iss::Ok; return iss::Ok;
} }
template<typename BASE> template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_ip(unsigned addr, reg_t &val) {
iss::status riscv_hart_msu_vp<BASE>::read_ip(unsigned addr, reg_t& val) {
auto req_priv_lvl = addr >> 8; auto req_priv_lvl = addr >> 8;
if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data); if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data);
val = csr[mie]; val = csr[mie];
@ -907,8 +817,7 @@ iss::status riscv_hart_msu_vp<BASE>::read_ip(unsigned addr, reg_t& val) {
return iss::Ok; return iss::Ok;
} }
template<typename BASE> template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_ip(unsigned addr, reg_t val) {
iss::status riscv_hart_msu_vp<BASE>::write_ip(unsigned addr, reg_t val) {
auto req_priv_lvl = addr >> 8; auto req_priv_lvl = addr >> 8;
if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data); if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data);
auto mask = get_irq_mask(req_priv_lvl); auto mask = get_irq_mask(req_priv_lvl);
@ -917,8 +826,7 @@ iss::status riscv_hart_msu_vp<BASE>::write_ip(unsigned addr, reg_t val) {
return iss::Ok; return iss::Ok;
} }
template<typename BASE> template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_satp(unsigned addr, reg_t &val) {
iss::status riscv_hart_msu_vp<BASE>::read_satp(unsigned addr, reg_t& val){
auto status = csr[mstatus]; auto status = csr[mstatus];
auto tvm = status & (1 << 20); auto tvm = status & (1 << 20);
if (this->reg.machine_state == PRIV_S & tvm != 0) { if (this->reg.machine_state == PRIV_S & tvm != 0) {
@ -930,8 +838,7 @@ iss::status riscv_hart_msu_vp<BASE>::read_satp(unsigned addr, reg_t& val){
return iss::Ok; return iss::Ok;
} }
template<typename BASE> template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_satp(unsigned addr, reg_t val) {
iss::status riscv_hart_msu_vp<BASE>::write_satp(unsigned addr, reg_t val){
auto status = csr[mstatus]; auto status = csr[mstatus];
auto tvm = status & (1 << 20); auto tvm = status & (1 << 20);
if (this->reg.machine_state == PRIV_S & tvm != 0) { if (this->reg.machine_state == PRIV_S & tvm != 0) {
@ -957,17 +864,21 @@ iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t addr, unsigned length
std::copy(data, data + length, p.data() + (addr.val & mem.page_addr_mask)); std::copy(data, data + length, p.data() + (addr.val & mem.page_addr_mask));
// tohost handling in case of riscv-test // tohost handling in case of riscv-test
if ((addr.type & iss::DEBUG) == 0) { if ((addr.type & iss::DEBUG) == 0) {
auto tohost_upper = (traits<BASE>::XLEN==32 && addr.val == (tohost+4)) || (traits<BASE>::XLEN==64 && addr.val == tohost); auto tohost_upper =
auto tohost_lower = (traits<BASE>::XLEN==32 && addr.val == tohost) || (traits<BASE>::XLEN==64 && addr.val == tohost); (traits<BASE>::XLEN == 32 && addr.val == (tohost + 4)) || (traits<BASE>::XLEN == 64 && addr.val == tohost);
auto tohost_lower =
(traits<BASE>::XLEN == 32 && addr.val == tohost) || (traits<BASE>::XLEN == 64 && addr.val == tohost);
if (tohost_lower || tohost_upper) { if (tohost_lower || tohost_upper) {
uint64_t hostvar = *reinterpret_cast<uint64_t *>(p.data() + (tohost & mem.page_addr_mask)); uint64_t hostvar = *reinterpret_cast<uint64_t *>(p.data() + (tohost & mem.page_addr_mask));
if (tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) { if (tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) {
switch (hostvar >> 48) { switch (hostvar >> 48) {
case 0: case 0:
if (hostvar != 0x1) if (hostvar != 0x1)
LOG(FATAL)<<"tohost value is 0x"<<std::hex<<hostvar<<std::dec<<" ("<<hostvar<<"), stopping simulation"; LOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
<< "), stopping simulation";
else else
LOG(INFO)<<"tohost value is 0x"<<std::hex<<hostvar<<std::dec<<" ("<<hostvar<<"), stopping simulation"; LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
<< "), stopping simulation";
throw(iss::simulation_stopped(hostvar)); throw(iss::simulation_stopped(hostvar));
case 0x0101: { case 0x0101: {
char c = static_cast<char>(hostvar & 0xff); char c = static_cast<char>(hostvar & 0xff);
@ -977,14 +888,14 @@ iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t addr, unsigned length
} else } else
uart_buf << c; uart_buf << c;
to_host_wr_cnt = 0; to_host_wr_cnt = 0;
} } break;
break;
default: default:
break; break;
} }
} else } else if (tohost_lower)
if(tohost_lower) to_host_wr_cnt++; to_host_wr_cnt++;
} else if((traits<BASE>::XLEN==32 && addr.val == fromhost+4) || (traits<BASE>::XLEN==64 && addr.val == fromhost)){ } else if ((traits<BASE>::XLEN == 32 && addr.val == fromhost + 4) ||
(traits<BASE>::XLEN == 64 && addr.val == fromhost)) {
uint64_t fhostvar = *reinterpret_cast<uint64_t *>(p.data() + (fromhost & mem.page_addr_mask)); uint64_t fhostvar = *reinterpret_cast<uint64_t *>(p.data() + (fromhost & mem.page_addr_mask));
*reinterpret_cast<uint64_t *>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar; *reinterpret_cast<uint64_t *>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
} }
@ -992,14 +903,15 @@ iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t addr, unsigned length
return iss::Ok; return iss::Ok;
} }
template<typename BASE> template <typename BASE> void riscv_hart_msu_vp<BASE>::check_interrupt() {
void riscv_hart_msu_vp<BASE>::check_interrupt(){
auto status = csr[mstatus]; auto status = csr[mstatus];
auto ip = csr[mip]; auto ip = csr[mip];
auto ie = csr[mie]; auto ie = csr[mie];
auto ideleg = csr[mideleg]; auto ideleg = csr[mideleg];
// Multiple simultaneous interrupts and traps at the same privilege level are handled in the following decreasing priority order: // Multiple simultaneous interrupts and traps at the same privilege level are
// external interrupts, software interrupts, timer interrupts, then finally any synchronous traps. // handled in the following decreasing priority order:
// external interrupts, software interrupts, timer interrupts, then finally
// any synchronous traps.
auto ena_irq = ip & ie; auto ena_irq = ip & ie;
auto mie = (csr[mstatus] >> 3) & 1; auto mie = (csr[mstatus] >> 3) & 1;
@ -1013,11 +925,9 @@ void riscv_hart_msu_vp<BASE>::check_interrupt(){
} }
if (enabled_interrupts != 0) { if (enabled_interrupts != 0) {
int res = 0; int res = 0;
while ((enabled_interrupts & 1) == 0) while ((enabled_interrupts & 1) == 0) enabled_interrupts >>= 1, res++;
enabled_interrupts >>= 1, res++;
this->reg.pending_trap = res << 16 | 1; this->reg.pending_trap = res << 16 | 1;
} }
} }
template <typename BASE> template <typename BASE>
@ -1033,7 +943,8 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::v2p(const
const access_type type = (access_type)(addr.getAccessType() & ~iss::DEBUG); const access_type type = (access_type)(addr.getAccessType() & ~iss::DEBUG);
uint32_t mode = type != iss::FETCH && bit_sub<17, 1>(mstatus_r) ? // MPRV uint32_t mode = type != iss::FETCH && bit_sub<17, 1>(mstatus_r) ? // MPRV
mode = bit_sub<11,2>(mstatus_r):// MPV mode = bit_sub<11, 2>(mstatus_r)
: // MPV
this->reg.machine_state; this->reg.machine_state;
const vm_info vm = decode_vm_info<traits<BASE>::XLEN>(mode, satp_r); const vm_info vm = decode_vm_info<traits<BASE>::XLEN>(mode, satp_r);
@ -1077,9 +988,10 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::v2p(const
// check that physical address of PTE is legal // check that physical address of PTE is legal
reg_t pte = 0; reg_t pte = 0;
const uint8_t res = this->read(phys_addr_t(addr.getAccessType(), traits<BASE>::MEM, base + idx * vm.ptesize), vm.ptesize, (uint8_t*)&pte); const uint8_t res =
if (res!=0) this->read(phys_addr_t(addr.getAccessType(), traits<BASE>::MEM, base + idx * vm.ptesize), vm.ptesize,
throw trap_load_access_fault(addr.val); (uint8_t *)&pte);
if (res != 0) throw trap_load_access_fault(addr.val);
const reg_t ppn = pte >> PTE_PPN_SHIFT; const reg_t ppn = pte >> PTE_PPN_SHIFT;
if (PTE_TABLE(pte)) { // next level of page table if (PTE_TABLE(pte)) { // next level of page table
@ -1088,9 +1000,9 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::v2p(const
break; break;
} else if (!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) { } else if (!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) {
break; break;
} else if (type == iss::FETCH ? !(pte & PTE_X) : } else if (type == iss::FETCH ? !(pte & PTE_X)
type == iss::READ ? !(pte & PTE_R) && !(mxr && (pte & PTE_X)) : : type == iss::READ ? !(pte & PTE_R) && !(mxr && (pte & PTE_X))
!((pte & PTE_R) && (pte & PTE_W))) { : !((pte & PTE_R) && (pte & PTE_W))) {
break; break;
} else if ((ppn & ((reg_t(1) << ptshift) - 1)) != 0) { } else if ((ppn & ((reg_t(1) << ptshift) - 1)) != 0) {
break; break;
@ -1101,8 +1013,7 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::v2p(const
*(uint32_t *)ppte |= ad; *(uint32_t *)ppte |= ad;
#else #else
// take exception if access or possibly dirty bit is not set. // take exception if access or possibly dirty bit is not set.
if ((pte & ad) != ad) if ((pte & ad) != ad) break;
break;
#endif #endif
// for superpage mappings, make a fake leaf PTE for the TLB's benefit. // for superpage mappings, make a fake leaf PTE for the TLB's benefit.
const reg_t vpn = addr.val >> PGSHIFT; const reg_t vpn = addr.val >> PGSHIFT;
@ -1123,12 +1034,12 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::v2p(const
case WRITE: case WRITE:
this->fault_data = addr.val; this->fault_data = addr.val;
throw trap_store_page_fault(addr.val); throw trap_store_page_fault(addr.val);
default: abort(); default:
abort();
} }
} }
template<typename BASE> template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t flags, uint64_t addr) {
uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t flags, uint64_t addr) {
auto cur_priv = this->reg.machine_state; auto cur_priv = this->reg.machine_state;
// calculate and write mcause val // calculate and write mcause val
auto trap_id = flags & 0xffff; auto trap_id = flags & 0xffff;
@ -1143,8 +1054,10 @@ uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t flags, uint64_t addr) {
csr[uepc | (new_priv << 8)] = static_cast<reg_t>(addr); // store actual address instruction of exception csr[uepc | (new_priv << 8)] = static_cast<reg_t>(addr); // store actual address instruction of exception
/* /*
* write mtval if new_priv=M_MODE, spec says: * write mtval if new_priv=M_MODE, spec says:
* When a hardware breakpoint is triggered, or an instruction-fetch, load, or store address-misaligned, * When a hardware breakpoint is triggered, or an instruction-fetch, load,
* access, or page-fault exception occurs, mtval is written with the faulting effective address. * or store address-misaligned,
* access, or page-fault exception occurs, mtval is written with the
* faulting effective address.
*/ */
csr[utval | (new_priv << 8)] = fault_data; csr[utval | (new_priv << 8)] = fault_data;
fault_data = 0; fault_data = 0;
@ -1156,8 +1069,10 @@ uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t flags, uint64_t addr) {
} }
csr[ucause | (new_priv << 8)] = cause; csr[ucause | (new_priv << 8)] = cause;
// update mstatus // update mstatus
// xPP field of mstatus is written with the active privilege mode at the time of the trap; the x PIE field of mstatus // xPP field of mstatus is written with the active privilege mode at the time
// is written with the value of the active interrupt-enable bit at the time of the trap; and the x IE field of mstatus // of the trap; the x PIE field of mstatus
// is written with the value of the active interrupt-enable bit at the time of
// the trap; and the x IE field of mstatus
// is cleared // is cleared
auto status = csr[mstatus]; auto status = csr[mstatus];
auto xie = (status >> cur_priv) & 1; auto xie = (status >> cur_priv) & 1;
@ -1181,22 +1096,22 @@ uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t flags, uint64_t addr) {
csr[mstatus] = status; csr[mstatus] = status;
// get trap vector // get trap vector
auto ivec = csr[utvec | (new_priv << 8)]; auto ivec = csr[utvec | (new_priv << 8)];
// calculate addr// set NEXT_PC to trap addressess to jump to based on MODE bits in mtvec // calculate addr// set NEXT_PC to trap addressess to jump to based on MODE
// bits in mtvec
this->reg.NEXT_PC = ivec & ~0x1UL; this->reg.NEXT_PC = ivec & ~0x1UL;
if((ivec&0x1)==1 && trap_id!=0) if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause;
this->reg.NEXT_PC+=4*cause;
// reset trap state // reset trap state
this->reg.machine_state = new_priv; this->reg.machine_state = new_priv;
this->reg.trap_state = 0; this->reg.trap_state = 0;
char buffer[32]; char buffer[32];
sprintf(buffer, "0x%016lx", addr); sprintf(buffer, "0x%016lx", addr);
CLOG(INFO, disass)<<(trap_id?"Interrupt ":"Trap ")<<trap_id<<" with cause '"<<irq_str[cause]<<"' at address "<<buffer CLOG(INFO, disass) << (trap_id ? "Interrupt " : "Trap ") << trap_id << " with cause '" << irq_str[cause]
<<" occurred, changing privilege level from "<<lvl[cur_priv]<<" to "<<lvl[new_priv]; << "' at address " << buffer << " occurred, changing privilege level from " << lvl[cur_priv]
<< " to " << lvl[new_priv];
return this->reg.NEXT_PC; return this->reg.NEXT_PC;
} }
template<typename BASE> template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::leave_trap(uint64_t flags) {
uint64_t riscv_hart_msu_vp<BASE>::leave_trap(uint64_t flags) {
auto cur_priv = this->reg.machine_state; auto cur_priv = this->reg.machine_state;
auto inst_priv = flags & 0x3; auto inst_priv = flags & 0x3;
auto status = csr[mstatus]; auto status = csr[mstatus];
@ -1234,8 +1149,7 @@ uint64_t riscv_hart_msu_vp<BASE>::leave_trap(uint64_t flags) {
return this->reg.NEXT_PC; return this->reg.NEXT_PC;
} }
template<typename BASE> template <typename BASE> void riscv_hart_msu_vp<BASE>::wait_until(uint64_t flags) {
void riscv_hart_msu_vp<BASE>::wait_until(uint64_t flags) {
auto status = csr[mstatus]; auto status = csr[mstatus];
auto tw = status & (1 << 21); auto tw = status & (1 << 21);
if (this->reg.machine_state == PRIV_S && tw != 0) { if (this->reg.machine_state == PRIV_S && tw != 0) {

View File

@ -36,19 +36,30 @@
#ifndef _RV32IMAC_H_ #ifndef _RV32IMAC_H_
#define _RV32IMAC_H_ #define _RV32IMAC_H_
#include <iss/arch/traits.h>
#include <iss/arch_if.h> #include <iss/arch_if.h>
#include <iss/vm_if.h> #include <iss/vm_if.h>
#include <iss/arch/traits.h>
namespace iss { namespace iss {
namespace arch { namespace arch {
struct rv32imac; struct rv32imac;
template<> template <> struct traits<rv32imac> {
struct traits<rv32imac> {
enum constants {XLEN=32,XLEN2=64,XLEN_BIT_MASK=31,PCLEN=32,fence=0,fencei=1,fencevmal=2,fencevmau=3,MISA_VAL=1075056897,PGSIZE=4096,PGMASK=4095}; enum constants {
XLEN = 32,
XLEN2 = 64,
XLEN_BIT_MASK = 31,
PCLEN = 32,
fence = 0,
fencei = 1,
fencevmal = 2,
fencevmau = 3,
MISA_VAL = 1075056897,
PGSIZE = 4096,
PGMASK = 4095
};
enum reg_e { enum reg_e {
X0, X0,
@ -103,19 +114,22 @@ struct traits<rv32imac> {
typedef iss::typed_addr_t<iss::PHYSICAL> phys_addr_t; typedef iss::typed_addr_t<iss::PHYSICAL> phys_addr_t;
constexpr static unsigned reg_bit_width(unsigned r) { constexpr static unsigned reg_bit_width(unsigned r) {
const uint32_t RV32IMAC_reg_size[] = {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,64}; const uint32_t RV32IMAC_reg_size[] = {32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 64};
return RV32IMAC_reg_size[r]; return RV32IMAC_reg_size[r];
} }
constexpr static unsigned reg_byte_offset(unsigned r) { constexpr static unsigned reg_byte_offset(unsigned r) {
const uint32_t RV32IMAC_reg_byte_offset[] = {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,152,160}; const uint32_t RV32IMAC_reg_byte_offset[] = {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48,
52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 100,
104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 152, 160};
return RV32IMAC_reg_byte_offset[r]; return RV32IMAC_reg_byte_offset[r];
} }
enum sreg_flag_e { FLAGS }; enum sreg_flag_e { FLAGS };
enum mem_type_e { MEM, CSR, FENCE, RES }; enum mem_type_e { MEM, CSR, FENCE, RES };
}; };
struct rv32imac : public arch_if { struct rv32imac : public arch_if {
@ -194,7 +208,6 @@ protected:
uint64_t icount; uint64_t icount;
} reg; } reg;
}; };
} }
} }
#endif /* _RV32IMAC_H_ */ #endif /* _RV32IMAC_H_ */

View File

@ -36,19 +36,30 @@
#ifndef _RV64IA_H_ #ifndef _RV64IA_H_
#define _RV64IA_H_ #define _RV64IA_H_
#include <iss/arch/traits.h>
#include <iss/arch_if.h> #include <iss/arch_if.h>
#include <iss/vm_if.h> #include <iss/vm_if.h>
#include <iss/arch/traits.h>
namespace iss { namespace iss {
namespace arch { namespace arch {
struct rv64ia; struct rv64ia;
template<> template <> struct traits<rv64ia> {
struct traits<rv64ia> {
enum constants {XLEN=64,XLEN2=128,XLEN_BIT_MASK=63,PCLEN=64,fence=0,fencei=1,fencevmal=2,fencevmau=3,MISA_VAL=2147750144,PGSIZE=4096,PGMASK=4095}; enum constants {
XLEN = 64,
XLEN2 = 128,
XLEN_BIT_MASK = 63,
PCLEN = 64,
fence = 0,
fencei = 1,
fencevmal = 2,
fencevmau = 3,
MISA_VAL = 2147750144,
PGSIZE = 4096,
PGMASK = 4095
};
enum reg_e { enum reg_e {
X0, X0,
@ -103,19 +114,21 @@ struct traits<rv64ia> {
typedef iss::typed_addr_t<iss::PHYSICAL> phys_addr_t; typedef iss::typed_addr_t<iss::PHYSICAL> phys_addr_t;
constexpr static unsigned reg_bit_width(unsigned r) { constexpr static unsigned reg_bit_width(unsigned r) {
const uint32_t RV64IA_reg_size[] = {64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,32,32,32,64}; const uint32_t RV64IA_reg_size[] = {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 32, 32, 32, 64};
return RV64IA_reg_size[r]; return RV64IA_reg_size[r];
} }
constexpr static unsigned reg_byte_offset(unsigned r) { constexpr static unsigned reg_byte_offset(unsigned r) {
const uint32_t RV64IA_reg_byte_offset[] = {0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,276,280,288,296}; const uint32_t RV64IA_reg_byte_offset[] = {0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96,
104, 112, 120, 128, 136, 144, 152, 160, 168, 176, 184, 192, 200,
208, 216, 224, 232, 240, 248, 256, 264, 272, 276, 280, 288, 296};
return RV64IA_reg_byte_offset[r]; return RV64IA_reg_byte_offset[r];
} }
enum sreg_flag_e { FLAGS }; enum sreg_flag_e { FLAGS };
enum mem_type_e { MEM, CSR, FENCE, RES }; enum mem_type_e { MEM, CSR, FENCE, RES };
}; };
struct rv64ia : public arch_if { struct rv64ia : public arch_if {
@ -194,7 +207,6 @@ protected:
uint64_t icount; uint64_t icount;
} reg; } reg;
}; };
} }
} }
#endif /* _RV64IA_H_ */ #endif /* _RV64IA_H_ */

View File

@ -34,18 +34,18 @@
// //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#include <iss/iss.h>
#include <iss/debugger/gdb_session.h>
#include <util/logging.h>
#include <memory>
#include <cstring> #include <cstring>
#include <iss/debugger/gdb_session.h>
#include <iss/iss.h>
#include <memory>
#include <util/logging.h>
#include "iss/vm_base.h"
#include "iss/arch/CORE_DEF_NAME.h" #include "iss/arch/CORE_DEF_NAME.h"
#include "iss/debugger/server.h" #include "iss/debugger/server.h"
#include "iss/vm_base.h"
#include <boost/format.hpp>
#include "iss/arch/riscv_hart_msu_vp.h" #include "iss/arch/riscv_hart_msu_vp.h"
#include <boost/format.hpp>
namespace iss { namespace iss {
namespace CORE_DEF_NAME { namespace CORE_DEF_NAME {
@ -53,17 +53,11 @@ using namespace iss::arch;
using namespace llvm; using namespace llvm;
using namespace iss::debugger; using namespace iss::debugger;
template<typename ARCH> template <typename ARCH> struct vm_impl;
struct vm_impl;
template<typename ARCH> template <typename ARCH> struct target_adapter : public target_adapter_base {
struct target_adapter: public target_adapter_base {
target_adapter(server_if* srv, vm_impl<ARCH>* vm) target_adapter(server_if *srv, vm_impl<ARCH> *vm) : target_adapter_base(srv), vm(vm) {}
: target_adapter_base(srv)
, vm(vm)
{
}
/*============== Thread Control ===============================*/ /*============== Thread Control ===============================*/
@ -92,7 +86,8 @@ struct target_adapter: public target_adapter_base {
target byte order. If register is not available target byte order. If register is not available
corresponding bytes in avail_buf are 0, otherwise corresponding bytes in avail_buf are 0, otherwise
avail buf is 1 */ avail buf is 1 */
status read_single_register(unsigned int reg_no, std::vector<uint8_t>& buf, std::vector<uint8_t>& avail_buf) override; status read_single_register(unsigned int reg_no, std::vector<uint8_t> &buf,
std::vector<uint8_t> &avail_buf) override;
/* Write one register. buf is 4-byte aligned and it is in target byte /* Write one register. buf is 4-byte aligned and it is in target byte
order */ order */
@ -110,7 +105,8 @@ struct target_adapter: public target_adapter_base {
status process_query(unsigned int &mask, const rp_thread_ref &arg, rp_thread_info &info) override; status process_query(unsigned int &mask, const rp_thread_ref &arg, rp_thread_info &info) override;
status thread_list_query(int first, const rp_thread_ref& arg, std::vector<rp_thread_ref>& result, size_t max_num, size_t& num, bool& done) override; status thread_list_query(int first, const rp_thread_ref &arg, std::vector<rp_thread_ref> &result, size_t max_num,
size_t &num, bool &done) override;
status current_thread_query(rp_thread_ref &thread) override; status current_thread_query(rp_thread_ref &thread) override;
@ -133,16 +129,13 @@ struct target_adapter: public target_adapter_base {
status resume_from_addr(bool step, int sig, uint64_t addr) override; status resume_from_addr(bool step, int sig, uint64_t addr) override;
protected: protected:
static inline constexpr addr_t map_addr(const addr_t& i){ static inline constexpr addr_t map_addr(const addr_t &i) { return i; }
return i;
}
vm_impl<ARCH> *vm; vm_impl<ARCH> *vm;
rp_thread_ref thread_idx; rp_thread_ref thread_idx;
}; };
template<typename ARCH> template <typename ARCH> struct vm_impl : public vm::vm_base<ARCH> {
struct vm_impl: public vm::vm_base<ARCH> {
using super = typename vm::vm_base<ARCH>; using super = typename vm::vm_base<ARCH>;
using virt_addr_t = typename super::virt_addr_t; using virt_addr_t = typename super::virt_addr_t;
using phys_addr_t = typename super::phys_addr_t; using phys_addr_t = typename super::phys_addr_t;
@ -153,9 +146,7 @@ struct vm_impl: public vm::vm_base<ARCH> {
vm_impl(ARCH &core, bool dump = false); vm_impl(ARCH &core, bool dump = false);
void enableDebug(bool enable) { void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; }
super::sync_exec=super::ALL_SYNC;
}
target_adapter_if *accquire_target_adapter(server_if *srv) { target_adapter_if *accquire_target_adapter(server_if *srv) {
debugger_if::dbg_enabled = true; debugger_if::dbg_enabled = true;
@ -164,19 +155,18 @@ struct vm_impl: public vm::vm_base<ARCH> {
return vm::vm_base<ARCH>::tgt_adapter; return vm::vm_base<ARCH>::tgt_adapter;
} }
protected: protected:
template <typename T> inline llvm::ConstantInt *size(T type) {
template<typename T> inline
llvm::ConstantInt* size(T type){
return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits())); return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits()));
} }
inline llvm::Value * gen_choose(llvm::Value * cond, llvm::Value * trueVal, llvm::Value * falseVal, unsigned size) const { inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal,
unsigned size) const {
return this->gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size)); return this->gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size));
} }
std::tuple<vm::continuation_e, llvm::BasicBlock*> gen_single_inst_behavior(virt_addr_t&, unsigned int&, llvm::BasicBlock*) override; std::tuple<vm::continuation_e, llvm::BasicBlock *> gen_single_inst_behavior(virt_addr_t &, unsigned int &,
llvm::BasicBlock *) override;
void gen_leave_behavior(llvm::BasicBlock *leave_blk) override; void gen_leave_behavior(llvm::BasicBlock *leave_blk) override;
@ -190,14 +180,13 @@ protected:
void gen_trap_check(llvm::BasicBlock *bb); void gen_trap_check(llvm::BasicBlock *bb);
inline inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) {
void gen_set_pc(virt_addr_t pc, unsigned reg_num){ llvm::Value *next_pc_v = this->builder->CreateSExtOrTrunc(this->gen_const(traits<ARCH>::XLEN, pc.val),
llvm::Value* next_pc_v = this->builder->CreateSExtOrTrunc(this->gen_const(traits<ARCH>::XLEN, pc.val), this->get_type(traits<ARCH>::XLEN)); this->get_type(traits<ARCH>::XLEN));
this->builder->CreateStore(next_pc_v, get_reg_ptr(reg_num), true); this->builder->CreateStore(next_pc_v, get_reg_ptr(reg_num), true);
} }
inline inline llvm::Value *get_reg_ptr(unsigned i) {
llvm::Value* get_reg_ptr(unsigned i){
void *ptr = this->core.get_regs_base_ptr() + traits<ARCH>::reg_byte_offset(i); void *ptr = this->core.get_regs_base_ptr() + traits<ARCH>::reg_byte_offset(i);
llvm::PointerType *ptrType = nullptr; llvm::PointerType *ptrType = nullptr;
switch (traits<ARCH>::reg_bit_width(i) >> 3) { switch (traits<ARCH>::reg_bit_width(i) >> 3) {
@ -218,27 +207,25 @@ protected:
break; break;
} }
return llvm::ConstantExpr::getIntToPtr( return llvm::ConstantExpr::getIntToPtr(
llvm::ConstantInt::get(this->mod->getContext(), llvm::APInt( llvm::ConstantInt::get(this->mod->getContext(),
8/*bits*/ * sizeof(uint8_t*), llvm::APInt(8 /*bits*/ * sizeof(uint8_t *), reinterpret_cast<uint64_t>(ptr))),
reinterpret_cast<uint64_t>(ptr)
)),
ptrType); ptrType);
} }
inline inline llvm::Value *gen_reg_load(unsigned i, unsigned level = 0) {
llvm::Value* gen_reg_load(unsigned i, unsigned level=0){
// if(level){ // if(level){
return this->builder->CreateLoad(get_reg_ptr(i), false); return this->builder->CreateLoad(get_reg_ptr(i), false);
// } else { // } else {
// if(!this->loaded_regs[i]) // if(!this->loaded_regs[i])
// this->loaded_regs[i]=this->builder->CreateLoad(get_reg_ptr(i), false); // this->loaded_regs[i]=this->builder->CreateLoad(get_reg_ptr(i),
// false);
// return this->loaded_regs[i]; // return this->loaded_regs[i];
// } // }
} }
inline inline void gen_set_pc(virt_addr_t pc) {
void gen_set_pc(virt_addr_t pc){ llvm::Value *pc_l = this->builder->CreateSExt(this->gen_const(traits<ARCH>::caddr_bit_width, (unsigned)pc),
llvm::Value* pc_l = this->builder->CreateSExt(this->gen_const(traits<ARCH>::caddr_bit_width, (unsigned)pc), this->get_type(traits<ARCH>::caddr_bit_width)); this->get_type(traits<ARCH>::caddr_bit_width));
super::gen_set_reg(traits<ARCH>::PC, pc_l); super::gen_set_reg(traits<ARCH>::PC, pc_l);
} }
@ -248,7 +235,9 @@ protected:
enum { LUT_SIZE = 1 << bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << bit_count(EXTR_MASK16) }; enum { LUT_SIZE = 1 << bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << bit_count(EXTR_MASK16) };
using this_class = vm_impl<ARCH>; using this_class = vm_impl<ARCH>;
using compile_func = std::tuple<vm::continuation_e, llvm::BasicBlock*> (this_class::*)(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb); using compile_func = std::tuple<vm::continuation_e, llvm::BasicBlock *> (this_class::*)(virt_addr_t &pc,
code_word_t instr,
llvm::BasicBlock *bb);
compile_func lut[LUT_SIZE]; compile_func lut[LUT_SIZE];
std::array<compile_func, LUT_SIZE_C> lut_00, lut_01, lut_10; std::array<compile_func, LUT_SIZE_C> lut_00, lut_01, lut_10;
@ -258,7 +247,8 @@ protected:
const uint32_t lutmasks[4] = {EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}; const uint32_t lutmasks[4] = {EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32};
void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], compile_func f){ void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[],
compile_func f) {
if (pos < 0) { if (pos < 0) {
lut[idx] = f; lut[idx] = f;
} else { } else {
@ -271,17 +261,14 @@ protected:
expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f); expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f);
} else { } else {
auto new_val = idx << 1; auto new_val = idx << 1;
if((value&bitmask)!=0) if ((value & bitmask) != 0) new_val++;
new_val++;
expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f); expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f);
} }
} }
} }
} }
inline uint32_t extract_fields(uint32_t val){ inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); }
return extract_fields(29, val>>2, lutmasks[val&0x3], 0);
}
uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) { uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) {
if (pos >= 0) { if (pos >= 0) {
@ -290,8 +277,7 @@ protected:
lut_val = extract_fields(pos - 1, val, mask, lut_val); lut_val = extract_fields(pos - 1, val, mask, lut_val);
} else { } else {
auto new_val = lut_val << 1; auto new_val = lut_val << 1;
if((val&bitmask)!=0) if ((val & bitmask) != 0) new_val++;
new_val++;
lut_val = extract_fields(pos - 1, val, mask, new_val); lut_val = extract_fields(pos - 1, val, mask, new_val);
} }
} }
@ -315,14 +301,13 @@ private:
/**************************************************************************** /****************************************************************************
* end opcode definitions * end opcode definitions
****************************************************************************/ ****************************************************************************/
std::tuple<vm::continuation_e, llvm::BasicBlock*> illegal_intruction(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ std::tuple<vm::continuation_e, llvm::BasicBlock *> illegal_intruction(virt_addr_t &pc, code_word_t instr,
llvm::BasicBlock *bb) {
// this->gen_sync(iss::PRE_SYNC); // this->gen_sync(iss::PRE_SYNC);
this->builder->CreateStore( this->builder->CreateStore(this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), true),
this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), true),
get_reg_ptr(traits<ARCH>::PC), true); get_reg_ptr(traits<ARCH>::PC), true);
this->builder->CreateStore( this->builder->CreateStore(
this->builder->CreateAdd( this->builder->CreateAdd(this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::ICOUNT), true),
this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::ICOUNT), true),
this->gen_const(64U, 1)), this->gen_const(64U, 1)),
get_reg_ptr(traits<ARCH>::ICOUNT), true); get_reg_ptr(traits<ARCH>::ICOUNT), true);
if (this->debugging_enabled()) this->gen_sync(iss::PRE_SYNC); if (this->debugging_enabled()) this->gen_sync(iss::PRE_SYNC);
@ -332,22 +317,16 @@ private:
this->gen_trap_check(this->leave_blk); this->gen_trap_check(this->leave_blk);
return std::make_tuple(iss::vm::BRANCH, nullptr); return std::make_tuple(iss::vm::BRANCH, nullptr);
} }
}; };
template<typename CODE_WORD> template <typename CODE_WORD> void debug_fn(CODE_WORD insn) {
void debug_fn(CODE_WORD insn){
volatile CODE_WORD x = insn; volatile CODE_WORD x = insn;
insn = 2 * x; insn = 2 * x;
} }
template<typename ARCH> template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
vm_impl<ARCH>::vm_impl(){
this(new ARCH());
}
template<typename ARCH> template <typename ARCH> vm_impl<ARCH>::vm_impl(ARCH &core, bool dump) : vm::vm_base<ARCH>(core, dump) {
vm_impl<ARCH>::vm_impl(ARCH& core, bool dump) : vm::vm_base<ARCH>(core, dump) {
qlut[0] = lut_00.data(); qlut[0] = lut_00.data();
qlut[1] = lut_01.data(); qlut[1] = lut_01.data();
qlut[2] = lut_10.data(); qlut[2] = lut_10.data();
@ -360,7 +339,8 @@ vm_impl<ARCH>::vm_impl(ARCH& core, bool dump) : vm::vm_base<ARCH>(core, dump) {
} }
template <typename ARCH> template <typename ARCH>
std::tuple<vm::continuation_e, llvm::BasicBlock*> vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t& pc, unsigned int& inst_cnt, llvm::BasicBlock* this_block){ std::tuple<vm::continuation_e, llvm::BasicBlock *>
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, llvm::BasicBlock *this_block) {
// we fetch at max 4 byte, alignment is 2 // we fetch at max 4 byte, alignment is 2
code_word_t insn = 0; code_word_t insn = 0;
iss::addr_t paddr; iss::addr_t paddr;
@ -370,21 +350,18 @@ std::tuple<vm::continuation_e, llvm::BasicBlock*> vm_impl<ARCH>::gen_single_inst
paddr = this->core.v2p(pc); paddr = this->core.v2p(pc);
if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
auto res = this->core.read(paddr, 2, data); auto res = this->core.read(paddr, 2, data);
if(res!=iss::Ok) if (res != iss::Ok) throw trap_access(1, pc.val);
throw trap_access(1, pc.val);
if ((insn & 0x3) == 0x3) { // this is a 32bit instruction if ((insn & 0x3) == 0x3) { // this is a 32bit instruction
res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); res = this->core.read(this->core.v2p(pc + 2), 2, data + 2);
} }
} else { } else {
auto res = this->core.read(paddr, 4, data); auto res = this->core.read(paddr, 4, data);
if(res!=iss::Ok) if (res != iss::Ok) throw trap_access(1, pc.val);
throw trap_access(1, pc.val);
} }
} catch (trap_access &ta) { } catch (trap_access &ta) {
throw trap_access(ta.id, pc.val); throw trap_access(ta.id, pc.val);
} }
if(insn==0x0000006f) if (insn == 0x0000006f) throw simulation_stopped(0);
throw simulation_stopped(0);
// curr pc on stack // curr pc on stack
typename vm_impl<ARCH>::processing_pc_entry addr(*this, pc, paddr); typename vm_impl<ARCH>::processing_pc_entry addr(*this, pc, paddr);
++inst_cnt; ++inst_cnt;
@ -396,69 +373,56 @@ std::tuple<vm::continuation_e, llvm::BasicBlock*> vm_impl<ARCH>::gen_single_inst
return (this->*f)(pc, insn, this_block); return (this->*f)(pc, insn, this_block);
} }
template<typename ARCH> template <typename ARCH> void vm_impl<ARCH>::gen_leave_behavior(llvm::BasicBlock *leave_blk) {
void vm_impl<ARCH>::gen_leave_behavior(llvm::BasicBlock* leave_blk){
this->builder->SetInsertPoint(leave_blk); this->builder->SetInsertPoint(leave_blk);
this->builder->CreateRet(this->builder->CreateLoad(get_reg_ptr(arch::traits<ARCH>::NEXT_PC), false)); this->builder->CreateRet(this->builder->CreateLoad(get_reg_ptr(arch::traits<ARCH>::NEXT_PC), false));
} }
template<typename ARCH> template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) {
void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause){
auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id); auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id);
this->builder->CreateStore(TRAP_val, get_reg_ptr(traits<ARCH>::TRAP_STATE), true); this->builder->CreateStore(TRAP_val, get_reg_ptr(traits<ARCH>::TRAP_STATE), true);
} }
template<typename ARCH> template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) {
void vm_impl<ARCH>::gen_leave_trap(unsigned lvl){
std::vector<llvm::Value *> args{ std::vector<llvm::Value *> args{
this->core_ptr, this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, lvl)),
llvm::ConstantInt::get(getContext(), llvm::APInt(64, lvl)),
}; };
this->builder->CreateCall(this->mod->getFunction("leave_trap"), args); this->builder->CreateCall(this->mod->getFunction("leave_trap"), args);
auto *PC_val = this->gen_read_mem(traits<ARCH>::CSR, (lvl << 8) + 0x41, traits<ARCH>::XLEN / 8); auto *PC_val = this->gen_read_mem(traits<ARCH>::CSR, (lvl << 8) + 0x41, traits<ARCH>::XLEN / 8);
this->builder->CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false); this->builder->CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false);
} }
template<typename ARCH> template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) {
void vm_impl<ARCH>::gen_wait(unsigned type){
std::vector<llvm::Value *> args{ std::vector<llvm::Value *> args{
this->core_ptr, this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, type)),
llvm::ConstantInt::get(getContext(), llvm::APInt(64, type)),
}; };
this->builder->CreateCall(this->mod->getFunction("wait"), args); this->builder->CreateCall(this->mod->getFunction("wait"), args);
} }
template<typename ARCH> template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(llvm::BasicBlock *trap_blk) {
void vm_impl<ARCH>::gen_trap_behavior(llvm::BasicBlock* trap_blk){
this->builder->SetInsertPoint(trap_blk); this->builder->SetInsertPoint(trap_blk);
auto *trap_state_val = this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::TRAP_STATE), true); auto *trap_state_val = this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::TRAP_STATE), true);
std::vector<llvm::Value*> args { std::vector<llvm::Value *> args{this->core_ptr, this->adj_to64(trap_state_val),
this->core_ptr, this->adj_to64(this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::PC), false))};
this->adj_to64(trap_state_val),
this->adj_to64(this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::PC), false))
};
this->builder->CreateCall(this->mod->getFunction("enter_trap"), args); this->builder->CreateCall(this->mod->getFunction("enter_trap"), args);
auto *trap_addr_val = this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), false); auto *trap_addr_val = this->builder->CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), false);
this->builder->CreateRet(trap_addr_val); this->builder->CreateRet(trap_addr_val);
} }
template<typename ARCH> inline template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(llvm::BasicBlock *bb) {
void vm_impl<ARCH>::gen_trap_check(llvm::BasicBlock* bb){
auto *v = this->builder->CreateLoad(get_reg_ptr(arch::traits<ARCH>::TRAP_STATE), true); auto *v = this->builder->CreateLoad(get_reg_ptr(arch::traits<ARCH>::TRAP_STATE), true);
this->gen_cond_branch( this->gen_cond_branch(this->builder->CreateICmp(
this->builder->CreateICmp( ICmpInst::ICMP_EQ, v,
ICmpInst::ICMP_EQ,
v,
llvm::ConstantInt::get(getContext(), llvm::APInt(v->getType()->getIntegerBitWidth(), 0))), llvm::ConstantInt::get(getContext(), llvm::APInt(v->getType()->getIntegerBitWidth(), 0))),
bb, bb, this->trap_blk, 1);
this->trap_blk, 1);
} }
} // namespace CORE_DEF_NAME } // namespace CORE_DEF_NAME
#define CREATE_FUNCS(ARCH) \ #define CREATE_FUNCS(ARCH) \
template <> std::unique_ptr<vm_if> create<ARCH>(ARCH * core, unsigned short port, bool dump) { \ template <> std::unique_ptr<vm_if> create<ARCH>(ARCH * core, unsigned short port, bool dump) { \
std::unique_ptr<CORE_DEF_NAME::vm_impl<ARCH> > ret = std::make_unique<CORE_DEF_NAME::vm_impl<ARCH> >(*core, dump);\ std::unique_ptr<CORE_DEF_NAME::vm_impl<ARCH>> ret = \
std::make_unique<CORE_DEF_NAME::vm_impl<ARCH>>(*core, dump); \
debugger::server<debugger::gdb_session>::run_server(ret.get(), port); \ debugger::server<debugger::gdb_session>::run_server(ret.get(), port); \
return ret; \ return ret; \
} \ } \
@ -476,20 +440,17 @@ CREATE_FUNCS(arch::CORE_DEF_NAME)
namespace CORE_DEF_NAME { namespace CORE_DEF_NAME {
template<typename ARCH> template <typename ARCH> status target_adapter<ARCH>::set_gen_thread(rp_thread_ref &thread) {
status target_adapter<ARCH>::set_gen_thread(rp_thread_ref& thread) {
thread_idx = thread; thread_idx = thread;
return Ok; return Ok;
} }
template<typename ARCH> template <typename ARCH> status target_adapter<ARCH>::set_ctrl_thread(rp_thread_ref &thread) {
status target_adapter<ARCH>::set_ctrl_thread(rp_thread_ref& thread) {
thread_idx = thread; thread_idx = thread;
return Ok; return Ok;
} }
template<typename ARCH> template <typename ARCH> status target_adapter<ARCH>::is_thread_alive(rp_thread_ref &thread, bool &alive) {
status target_adapter<ARCH>::is_thread_alive(rp_thread_ref& thread, bool& alive) {
alive = 1; alive = 1;
return Ok; return Ok;
} }
@ -501,8 +462,8 @@ namespace CORE_DEF_NAME {
* set if all threads are processed. * set if all threads are processed.
*/ */
template <typename ARCH> template <typename ARCH>
status target_adapter<ARCH>::thread_list_query(int first, const rp_thread_ref& arg, std::vector<rp_thread_ref>& result, size_t max_num, status target_adapter<ARCH>::thread_list_query(int first, const rp_thread_ref &arg, std::vector<rp_thread_ref> &result,
size_t& num, bool& done) { size_t max_num, size_t &num, bool &done) {
if (first == 0) { if (first == 0) {
result.clear(); result.clear();
result.push_back(thread_idx); result.push_back(thread_idx);
@ -513,8 +474,7 @@ namespace CORE_DEF_NAME {
return NotSupported; return NotSupported;
} }
template<typename ARCH> template <typename ARCH> status target_adapter<ARCH>::current_thread_query(rp_thread_ref &thread) {
status target_adapter<ARCH>::current_thread_query(rp_thread_ref& thread) {
thread = thread_idx; thread = thread_idx;
return Ok; return Ok;
} }
@ -549,24 +509,26 @@ namespace CORE_DEF_NAME {
return Ok; return Ok;
} }
template<typename ARCH> template <typename ARCH> status target_adapter<ARCH>::write_registers(const std::vector<uint8_t> &data) {
status target_adapter<ARCH>::write_registers(const std::vector<uint8_t>& data) {
size_t data_index = 0; size_t data_index = 0;
auto reg_count = arch::traits<ARCH>::NUM_REGS; auto reg_count = arch::traits<ARCH>::NUM_REGS;
std::vector<uint8_t> reg_data; std::vector<uint8_t> reg_data;
for (size_t reg_no = 0; reg_no < reg_count; ++reg_no) { for (size_t reg_no = 0; reg_no < reg_count; ++reg_no) {
auto reg_bit_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)); auto reg_bit_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no));
auto reg_width = reg_bit_width / 8; auto reg_width = reg_bit_width / 8;
vm->get_arch()->set_reg(reg_no, std::vector<uint8_t>(data.begin()+data_index, data.begin()+data_index+reg_width)); vm->get_arch()->set_reg(reg_no,
std::vector<uint8_t>(data.begin() + data_index, data.begin() + data_index + reg_width));
data_index += reg_width; data_index += reg_width;
} }
return Ok; return Ok;
} }
template <typename ARCH> template <typename ARCH>
status target_adapter<ARCH>::read_single_register(unsigned int reg_no, std::vector<uint8_t>& data, std::vector<uint8_t>& avail) { status target_adapter<ARCH>::read_single_register(unsigned int reg_no, std::vector<uint8_t> &data,
std::vector<uint8_t> &avail) {
if (reg_no < 65) { if (reg_no < 65) {
//auto reg_size = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no))/8; // auto reg_size = arch::traits<ARCH>::reg_bit_width(static_cast<typename
// arch::traits<ARCH>::reg_e>(reg_no))/8;
data.resize(0); data.resize(0);
vm->get_arch()->get_reg(reg_no, data); vm->get_arch()->get_reg(reg_no, data);
avail.resize(data.size()); avail.resize(data.size());
@ -592,18 +554,13 @@ namespace CORE_DEF_NAME {
return Ok; return Ok;
} }
template<typename ARCH> template <typename ARCH> status target_adapter<ARCH>::read_mem(uint64_t addr, std::vector<uint8_t> &data) {
status target_adapter<ARCH>::read_mem(uint64_t addr, std::vector<uint8_t>& data) {
auto a = map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); auto a = map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr});
auto f = [&]()->status { auto f = [&]() -> status { return vm->get_arch()->read(a, data.size(), data.data()); };
return vm->get_arch()->read(a, data.size(), data.data());
};
return srv->execute_syncronized(f); return srv->execute_syncronized(f);
} }
template<typename ARCH> template <typename ARCH> status target_adapter<ARCH>::write_mem(uint64_t addr, const std::vector<uint8_t> &data) {
status target_adapter<ARCH>::write_mem(uint64_t addr, const std::vector<uint8_t>& data) {
auto a = map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); auto a = map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr});
return srv->execute_syncronized(&arch_if::write, vm->get_arch(), a, data.size(), data.data()); return srv->execute_syncronized(&arch_if::write, vm->get_arch(), a, data.size(), data.data());
} }
@ -613,26 +570,22 @@ namespace CORE_DEF_NAME {
return NotSupported; return NotSupported;
} }
template<typename ARCH> template <typename ARCH> status target_adapter<ARCH>::offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) {
status target_adapter<ARCH>::offsets_query(uint64_t& text, uint64_t& data, uint64_t& bss) {
text = 0; text = 0;
data = 0; data = 0;
bss = 0; bss = 0;
return Ok; return Ok;
} }
template<typename ARCH> template <typename ARCH> status target_adapter<ARCH>::crc_query(uint64_t addr, size_t len, uint32_t &val) {
status target_adapter<ARCH>::crc_query(uint64_t addr, size_t len, uint32_t& val) {
return NotSupported; return NotSupported;
} }
template<typename ARCH> template <typename ARCH> status target_adapter<ARCH>::raw_query(std::string in_buf, std::string &out_buf) {
status target_adapter<ARCH>::raw_query(std::string in_buf, std::string& out_buf) {
return NotSupported; return NotSupported;
} }
template<typename ARCH> template <typename ARCH> status target_adapter<ARCH>::threadinfo_query(int first, std::string &out_buf) {
status target_adapter<ARCH>::threadinfo_query(int first, std::string& out_buf) {
if (first) { if (first) {
std::stringstream ss; std::stringstream ss;
ss << "m" << std::hex << thread_idx.val; ss << "m" << std::hex << thread_idx.val;
@ -652,29 +605,28 @@ namespace CORE_DEF_NAME {
return Ok; return Ok;
} }
template<typename ARCH> template <typename ARCH> status target_adapter<ARCH>::packetsize_query(std::string &out_buf) {
status target_adapter<ARCH>::packetsize_query(std::string& out_buf) {
out_buf = "PacketSize=1000"; out_buf = "PacketSize=1000";
return Ok; return Ok;
} }
template<typename ARCH> template <typename ARCH> status target_adapter<ARCH>::add_break(int type, uint64_t addr, unsigned int length) {
status target_adapter<ARCH>::add_break(int type, uint64_t addr, unsigned int length) {
auto saddr = map_addr({iss::CODE, iss::PHYSICAL, addr}); auto saddr = map_addr({iss::CODE, iss::PHYSICAL, addr});
auto eaddr = map_addr({iss::CODE, iss::PHYSICAL, addr + length}); auto eaddr = map_addr({iss::CODE, iss::PHYSICAL, addr + length});
target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val - saddr.val); target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val - saddr.val);
LOG(TRACE)<<"Adding breakpoint with handle "<<target_adapter_base::bp_count<<" for addr 0x"<<std::hex<<saddr.val<<std::dec; LOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex
<< saddr.val << std::dec;
LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
return Ok; return Ok;
} }
template<typename ARCH> template <typename ARCH> status target_adapter<ARCH>::remove_break(int type, uint64_t addr, unsigned int length) {
status target_adapter<ARCH>::remove_break(int type, uint64_t addr, unsigned int length) {
auto saddr = map_addr({iss::CODE, iss::PHYSICAL, addr}); auto saddr = map_addr({iss::CODE, iss::PHYSICAL, addr});
unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val); unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val);
// TODO: check length of addr range // TODO: check length of addr range
if (handle) { if (handle) {
LOG(TRACE)<<"Removing breakpoint with handle "<<handle<<" for addr 0x"<<std::hex<<saddr.val<<std::dec; LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val
<< std::dec;
target_adapter_base::bp_lut.removeEntry(handle); target_adapter_base::bp_lut.removeEntry(handle);
LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
return Ok; return Ok;
@ -683,8 +635,7 @@ namespace CORE_DEF_NAME {
return Err; return Err;
} }
template<typename ARCH> template <typename ARCH> status target_adapter<ARCH>::resume_from_addr(bool step, int sig, uint64_t addr) {
status target_adapter<ARCH>::resume_from_addr(bool step, int sig, uint64_t addr) {
unsigned reg_no = arch::traits<ARCH>::PC; unsigned reg_no = arch::traits<ARCH>::PC;
std::vector<uint8_t> data(8); std::vector<uint8_t> data(8);
*(reinterpret_cast<uint64_t *>(&data[0])) = addr; *(reinterpret_cast<uint64_t *>(&data[0])) = addr;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -46,30 +46,26 @@ extern "C" {
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#include <fstream>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <fstream>
using namespace iss::arch; using namespace iss::arch;
rv32imac::rv32imac() { rv32imac::rv32imac() { reg.icount = 0; }
reg.icount=0;
}
rv32imac::~rv32imac(){ rv32imac::~rv32imac() {}
}
void rv32imac::reset(uint64_t address) { void rv32imac::reset(uint64_t address) {
for(size_t i=0; i<traits<rv32imac>::NUM_REGS; ++i) set_reg(i, std::vector<uint8_t>(sizeof(traits<rv32imac>::reg_t),0)); for (size_t i = 0; i < traits<rv32imac>::NUM_REGS; ++i)
set_reg(i, std::vector<uint8_t>(sizeof(traits<rv32imac>::reg_t), 0));
reg.PC = address; reg.PC = address;
reg.NEXT_PC = reg.PC; reg.NEXT_PC = reg.PC;
reg.trap_state = 0; reg.trap_state = 0;
reg.machine_state = 0x3; reg.machine_state = 0x3;
} }
uint8_t* rv32imac::get_regs_base_ptr(){ uint8_t *rv32imac::get_regs_base_ptr() { return reinterpret_cast<uint8_t *>(&reg); }
return reinterpret_cast<uint8_t*>(&reg);
}
rv32imac::phys_addr_t rv32imac::v2p(const iss::addr_t &pc) { rv32imac::phys_addr_t rv32imac::v2p(const iss::addr_t &pc) {
return phys_addr_t(pc); // change logical address to physical address return phys_addr_t(pc); // change logical address to physical address

View File

@ -46,30 +46,26 @@ extern "C" {
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#include <fstream>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <fstream>
using namespace iss::arch; using namespace iss::arch;
rv64ia::rv64ia() { rv64ia::rv64ia() { reg.icount = 0; }
reg.icount=0;
}
rv64ia::~rv64ia(){ rv64ia::~rv64ia() {}
}
void rv64ia::reset(uint64_t address) { void rv64ia::reset(uint64_t address) {
for(size_t i=0; i<traits<rv64ia>::NUM_REGS; ++i) set_reg(i, std::vector<uint8_t>(sizeof(traits<rv64ia>::reg_t),0)); for (size_t i = 0; i < traits<rv64ia>::NUM_REGS; ++i)
set_reg(i, std::vector<uint8_t>(sizeof(traits<rv64ia>::reg_t), 0));
reg.PC = address; reg.PC = address;
reg.NEXT_PC = reg.PC; reg.NEXT_PC = reg.PC;
reg.trap_state = 0; reg.trap_state = 0;
reg.machine_state = 0x0; reg.machine_state = 0x0;
} }
uint8_t* rv64ia::get_regs_base_ptr(){ uint8_t *rv64ia::get_regs_base_ptr() { return reinterpret_cast<uint8_t *>(&reg); }
return reinterpret_cast<uint8_t*>(&reg);
}
rv64ia::phys_addr_t rv64ia::v2p(const iss::addr_t &pc) { rv64ia::phys_addr_t rv64ia::v2p(const iss::addr_t &pc) {
return phys_addr_t(pc); // change logical address to physical address return phys_addr_t(pc); // change logical address to physical address

View File

@ -32,16 +32,15 @@
// eyck@minres.com - initial API and implementation // eyck@minres.com - initial API and implementation
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#include <cli_options.h> #include <cli_options.h>
#include <iss/iss.h>
#include <iostream> #include <iostream>
#include <iss/iss.h>
#include <iss/log_categories.h> #include <boost/lexical_cast.hpp>
#include <iss/arch/rv32imac.h> #include <iss/arch/rv32imac.h>
#include <iss/arch/rv64ia.h> #include <iss/arch/rv64ia.h>
#include <iss/jit/MCJIThelper.h> #include <iss/jit/MCJIThelper.h>
#include <boost/lexical_cast.hpp> #include <iss/log_categories.h>
namespace po = boost::program_options; namespace po = boost::program_options;
@ -81,8 +80,7 @@ int main(int argc, char *argv[]) {
cpu = iss::create<iss::arch::rv32imac>("rv32ima", dump); cpu = iss::create<iss::arch::rv32imac>("rv32ima", dump);
} }
if (vm.count("elf")) { if (vm.count("elf")) {
for(std::string input: vm["elf"].as<std::vector<std::string> >()) for (std::string input : vm["elf"].as<std::vector<std::string>>()) cpu->get_arch()->load_file(input);
cpu->get_arch()->load_file(input);
} else if (vm.count("mem")) { } else if (vm.count("mem")) {
cpu->get_arch()->load_file(vm["mem"].as<std::string>(), iss::arch::traits<iss::arch::rv32imac>::MEM); cpu->get_arch()->load_file(vm["mem"].as<std::string>(), iss::arch::traits<iss::arch::rv32imac>::MEM);
} }
@ -106,8 +104,8 @@ int main(int argc, char *argv[]) {
} }
return cpu->start(vm["cycles"].as<int64_t>()); return cpu->start(vm["cycles"].as<int64_t>());
} catch (std::exception &e) { } catch (std::exception &e) {
LOG(ERROR) << "Unhandled Exception reached the top of main: " LOG(ERROR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit"
<< e.what() << ", application will now exit" << std::endl; << std::endl;
return ERROR_UNHANDLED_EXCEPTION; return ERROR_UNHANDLED_EXCEPTION;
} }
} }

@ -1 +1 @@
Subproject commit 46d79504a8a5a6a9541b19a6774fb8161350a0a4 Subproject commit a5c9101b71da3824af4a54322232de270c5547de