Compare commits
	
		
			8 Commits
		
	
	
		
			836ba269e3
			...
			msvc_compa
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| c8679fca85 | |||
| f0ada1ba8c | |||
| 09b01af3fa | |||
| 9c8b72693e | |||
| c409e7b7ca | |||
| 2f05083cf0 | |||
| e934049dd4 | |||
| 
						 | 
					94f796ebdb | 
@@ -1,9 +1,13 @@
 | 
			
		||||
cmake_minimum_required(VERSION 3.12)
 | 
			
		||||
 | 
			
		||||
###############################################################################
 | 
			
		||||
#
 | 
			
		||||
###############################################################################
 | 
			
		||||
project(dbt-rise-tgc VERSION 1.0.0)
 | 
			
		||||
 | 
			
		||||
include(GNUInstallDirs)
 | 
			
		||||
 | 
			
		||||
find_package(elfio)
 | 
			
		||||
 | 
			
		||||
if(WITH_LLVM)
 | 
			
		||||
    if(DEFINED ENV{LLVM_HOME})
 | 
			
		||||
        find_path (LLVM_DIR LLVM-Config.cmake $ENV{LLVM_HOME}/lib/cmake/llvm)
 | 
			
		||||
@@ -44,16 +48,24 @@ if(WITH_LLVM)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
# Define the library
 | 
			
		||||
add_library(${PROJECT_NAME} SHARED ${LIB_SOURCES})
 | 
			
		||||
add_library(${PROJECT_NAME} ${LIB_SOURCES})
 | 
			
		||||
# list code gen dependencies
 | 
			
		||||
if(TARGET ${CORE_NAME}_cpp)
 | 
			
		||||
    add_dependencies(${PROJECT_NAME} ${CORE_NAME}_cpp)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
target_compile_options(${PROJECT_NAME} PRIVATE -Wno-shift-count-overflow)
 | 
			
		||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
 | 
			
		||||
     target_compile_options(${PROJECT_NAME} PRIVATE -Wno-shift-count-overflow)
 | 
			
		||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
 | 
			
		||||
    target_compile_options(${PROJECT_NAME} PRIVATE /wd4293)
 | 
			
		||||
endif()
 | 
			
		||||
target_include_directories(${PROJECT_NAME} PUBLIC incl)
 | 
			
		||||
target_link_libraries(${PROJECT_NAME} PUBLIC softfloat scc-util jsoncpp)
 | 
			
		||||
target_link_libraries(${PROJECT_NAME} PUBLIC -Wl,--whole-archive dbt-core -Wl,--no-whole-archive)
 | 
			
		||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
 | 
			
		||||
    target_link_libraries(${PROJECT_NAME} PUBLIC -Wl,--whole-archive dbt-core -Wl,--no-whole-archive)
 | 
			
		||||
else()
 | 
			
		||||
    target_link_libraries(${PROJECT_NAME} PUBLIC dbt-core)
 | 
			
		||||
endif()
 | 
			
		||||
if(TARGET CONAN_PKG::elfio)
 | 
			
		||||
    target_link_libraries(${PROJECT_NAME} PUBLIC CONAN_PKG::elfio)
 | 
			
		||||
elseif(TARGET elfio::elfio)
 | 
			
		||||
@@ -61,12 +73,28 @@ elseif(TARGET elfio::elfio)
 | 
			
		||||
else()
 | 
			
		||||
    message(FATAL_ERROR "No elfio library found, maybe a find_package() call is missing")
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
set_target_properties(${PROJECT_NAME} PROPERTIES
 | 
			
		||||
  VERSION ${PROJECT_VERSION}
 | 
			
		||||
  FRAMEWORK FALSE
 | 
			
		||||
  PUBLIC_HEADER "${LIB_HEADERS}" # specify the public headers
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
install(TARGETS ${PROJECT_NAME} COMPONENT ${PROJECT_NAME}
 | 
			
		||||
  EXPORT ${PROJECT_NAME}Targets            # for downstream dependencies
 | 
			
		||||
  ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}  # static lib
 | 
			
		||||
  RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}  # binaries
 | 
			
		||||
  LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}  # shared lib
 | 
			
		||||
  FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} # for mac
 | 
			
		||||
  PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} # headers for mac (note the different component -> different package)
 | 
			
		||||
  INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}             # headers
 | 
			
		||||
)
 | 
			
		||||
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/incl/iss COMPONENT ${PROJECT_NAME}
 | 
			
		||||
        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # target directory
 | 
			
		||||
        FILES_MATCHING # install only matched files
 | 
			
		||||
        PATTERN "*.h" # select header files
 | 
			
		||||
        )
 | 
			
		||||
###############################################################################
 | 
			
		||||
#
 | 
			
		||||
###############################################################################
 | 
			
		||||
project(tgc-sim)
 | 
			
		||||
find_package(Boost COMPONENTS program_options thread REQUIRED)
 | 
			
		||||
 | 
			
		||||
@@ -78,31 +106,32 @@ if(WITH_LLVM)
 | 
			
		||||
    target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
 | 
			
		||||
endif()
 | 
			
		||||
# Links the target exe against the libraries
 | 
			
		||||
target_link_libraries(${PROJECT_NAME} dbt-rise-tgc)
 | 
			
		||||
#target_link_libraries(${PROJECT_NAME} jsoncpp)
 | 
			
		||||
target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc)
 | 
			
		||||
if(TARGET Boost::program_options)
 | 
			
		||||
    target_link_libraries(${PROJECT_NAME} Boost::program_options Boost::thread)
 | 
			
		||||
    target_link_libraries(${PROJECT_NAME} PUBLIC Boost::program_options Boost::thread)
 | 
			
		||||
else()
 | 
			
		||||
    target_link_libraries(${PROJECT_NAME} ${BOOST_program_options_LIBRARY} ${BOOST_thread_LIBRARY})
 | 
			
		||||
    target_link_libraries(${PROJECT_NAME} PUBLIC ${BOOST_program_options_LIBRARY} ${BOOST_thread_LIBRARY})
 | 
			
		||||
endif()
 | 
			
		||||
target_link_libraries(${PROJECT_NAME} ${CMAKE_DL_LIBS})
 | 
			
		||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${CMAKE_DL_LIBS})
 | 
			
		||||
if (Tcmalloc_FOUND)
 | 
			
		||||
    target_link_libraries(${PROJECT_NAME} ${Tcmalloc_LIBRARIES})
 | 
			
		||||
    target_link_libraries(${PROJECT_NAME} PUBLIC ${Tcmalloc_LIBRARIES})
 | 
			
		||||
endif(Tcmalloc_FOUND)
 | 
			
		||||
 | 
			
		||||
install(TARGETS dbt-rise-tgc tgc-sim
 | 
			
		||||
install(TARGETS tgc-sim
 | 
			
		||||
  EXPORT ${PROJECT_NAME}Targets            # for downstream dependencies
 | 
			
		||||
  ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs   # static lib
 | 
			
		||||
  RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT libs   # binaries
 | 
			
		||||
  LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs   # shared lib
 | 
			
		||||
  FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs # for mac
 | 
			
		||||
  PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} COMPONENT devel   # headers for mac (note the different component -> different package)
 | 
			
		||||
  ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}  # static lib
 | 
			
		||||
  RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}  # binaries
 | 
			
		||||
  LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}  # shared lib
 | 
			
		||||
  FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} # for mac
 | 
			
		||||
  PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}  # headers for mac (note the different component -> different package)
 | 
			
		||||
  INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}             # headers
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
###############################################################################
 | 
			
		||||
#
 | 
			
		||||
###############################################################################
 | 
			
		||||
project(dbt-rise-tgc_sc VERSION 1.0.0)
 | 
			
		||||
 | 
			
		||||
include(FindSystemCPackage)
 | 
			
		||||
include(SystemCPackage)
 | 
			
		||||
if(SystemC_FOUND)
 | 
			
		||||
    add_library(${PROJECT_NAME} src/sysc/core_complex.cpp)
 | 
			
		||||
    target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_SYSTEMC)
 | 
			
		||||
@@ -121,18 +150,19 @@ if(SystemC_FOUND)
 | 
			
		||||
        target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
 | 
			
		||||
    endif()
 | 
			
		||||
    
 | 
			
		||||
	set(LIB_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/incl/sysc/core_complex.h)
 | 
			
		||||
    set_target_properties(${PROJECT_NAME} PROPERTIES
 | 
			
		||||
      VERSION ${PROJECT_VERSION}
 | 
			
		||||
      FRAMEWORK FALSE
 | 
			
		||||
      PUBLIC_HEADER "${LIB_HEADERS}" # specify the public headers
 | 
			
		||||
    )
 | 
			
		||||
    install(TARGETS ${PROJECT_NAME}
 | 
			
		||||
    install(TARGETS ${PROJECT_NAME} COMPONENT ${PROJECT_NAME}
 | 
			
		||||
	  EXPORT ${PROJECT_NAME}Targets            # for downstream dependencies
 | 
			
		||||
	  ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs   # static lib
 | 
			
		||||
	  RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT libs   # binaries
 | 
			
		||||
	  LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs   # shared lib
 | 
			
		||||
	  FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs # for mac
 | 
			
		||||
	  PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} COMPONENT devel   # headers for mac (note the different component -> different package)
 | 
			
		||||
	  ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}  # static lib
 | 
			
		||||
	  RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}  # binaries
 | 
			
		||||
	  LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}  # shared lib
 | 
			
		||||
	  FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} # for mac
 | 
			
		||||
	  PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sysc   # headers for mac (note the different component -> different package)
 | 
			
		||||
	  INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}             # headers
 | 
			
		||||
	)    
 | 
			
		||||
endif()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										30
									
								
								contrib/build.tcl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								contrib/build.tcl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
namespace eval Specification {
 | 
			
		||||
    proc buildproc { args } {
 | 
			
		||||
        global env
 | 
			
		||||
        variable installDir
 | 
			
		||||
        variable compiler
 | 
			
		||||
        variable compiler [::scsh::get_backend_compiler]
 | 
			
		||||
        #  set target $machine
 | 
			
		||||
        set target [::scsh::machine]
 | 
			
		||||
        set linkerOptions ""
 | 
			
		||||
        set preprocessorOptions ""
 | 
			
		||||
        set libversion $compiler
 | 
			
		||||
        switch -exact -- $target {
 | 
			
		||||
            "linux" {
 | 
			
		||||
            	set install_dir $::env(TGFS_INSTALL_ROOT)
 | 
			
		||||
                set incldir "${install_dir}/include"
 | 
			
		||||
                set libdir "${install_dir}/lib64"
 | 
			
		||||
                set preprocessorOptions [concat $preprocessorOptions "-I${incldir}"]
 | 
			
		||||
                # Set the Linker paths.
 | 
			
		||||
                set linkerOptions [concat $linkerOptions "-Wl,-rpath,${libdir} -L${libdir} -ldbt-rise-tgc_sc"]
 | 
			
		||||
            }
 | 
			
		||||
            default {
 | 
			
		||||
               puts stderr "ERROR: \"$target\" is not supported, [::scsh::version]"
 | 
			
		||||
               return
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        ::scsh::cwr_append_ipsimbld_opts preprocessor "$preprocessorOptions"
 | 
			
		||||
        ::scsh::cwr_append_ipsimbld_opts linker       "$linkerOptions"
 | 
			
		||||
    }
 | 
			
		||||
    ::scsh::add_build_callback [namespace current]::buildproc
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										4
									
								
								contrib/tgc_import.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								contrib/tgc_import.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
 | 
			
		||||
#include "sysc/core_complex.h"
 | 
			
		||||
 | 
			
		||||
void modules() { sysc::tgfs::core_complex i_core_complex("core_complex"); }
 | 
			
		||||
							
								
								
									
										50
									
								
								contrib/tgc_import.tcl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								contrib/tgc_import.tcl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
#############################################################################
 | 
			
		||||
#
 | 
			
		||||
#############################################################################
 | 
			
		||||
proc getScriptDirectory {} {
 | 
			
		||||
    set dispScriptFile [file normalize [info script]]
 | 
			
		||||
    set scriptFolder [file dirname $dispScriptFile]
 | 
			
		||||
    return $scriptFolder
 | 
			
		||||
}
 | 
			
		||||
if { $::env(SNPS_VP_PRODUCT) == "PAULTRA" } {
 | 
			
		||||
    set hardware /HARDWARE/HW/HW
 | 
			
		||||
} else {
 | 
			
		||||
    set hardware /HARDWARE
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
set scriptDir [getScriptDirectory]
 | 
			
		||||
set top_design_name core_complex
 | 
			
		||||
set clocks clk_i
 | 
			
		||||
set resets rst_i
 | 
			
		||||
set model_prefix "i_"
 | 
			
		||||
set model_postfix ""
 | 
			
		||||
 | 
			
		||||
::pct::new_project
 | 
			
		||||
::pct::open_library TLM2_PL
 | 
			
		||||
::pct::clear_systemc_defines
 | 
			
		||||
::pct::clear_systemc_include_path
 | 
			
		||||
::pct::add_to_systemc_include_path $::env(TGFS_INSTALL_ROOT)/include
 | 
			
		||||
::pct::set_import_protocol_generation_flag false
 | 
			
		||||
::pct::set_update_existing_encaps_flag true
 | 
			
		||||
::pct::set_dynamic_port_arrays_flag true
 | 
			
		||||
::pct::set_import_scml_properties_flag true
 | 
			
		||||
::pct::load_modules --set-category modules tgc_import.cc
 | 
			
		||||
 | 
			
		||||
# Set Port Protocols correctly
 | 
			
		||||
set block ${top_design_name}
 | 
			
		||||
foreach clock ${clocks} {
 | 
			
		||||
	::pct::set_block_port_protocol --set-category SYSTEM_LIBRARY:$block/${clock} SYSTEM_LIBRARY:CLOCK
 | 
			
		||||
}
 | 
			
		||||
foreach reset ${resets} {
 | 
			
		||||
    ::pct::set_block_port_protocol --set-category SYSTEM_LIBRARY:$block/${reset} SYSTEM_LIBRARY:RESET
 | 
			
		||||
}
 | 
			
		||||
::pct::set_encap_port_array_size SYSTEM_LIBRARY:$block/local_irq_i 16
 | 
			
		||||
 | 
			
		||||
# Set compile settings and look
 | 
			
		||||
set block SYSTEM_LIBRARY:${top_design_name}
 | 
			
		||||
::pct::set_encap_build_script $block/${top_design_name} $scriptDir/build.tcl
 | 
			
		||||
::pct::set_background_color_rgb $block 255 255 255 255
 | 
			
		||||
::pct::create_instance SYSTEM_LIBRARY:${top_design_name}  ${hardware} ${model_prefix}${top_design_name}${model_postfix} ${top_design_name} 
 | 
			
		||||
 | 
			
		||||
# export the result as component
 | 
			
		||||
::pct::export_system_library ${top_design_name}  ${top_design_name}.xml
 | 
			
		||||
@@ -388,6 +388,7 @@ template <typename BASE> std::pair<uint64_t, bool> riscv_hart_m_p<BASE>::load_fi
 | 
			
		||||
                if (sizeof(reg_t) == 4) 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_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine in file");
 | 
			
		||||
            auto entry = reader.get_entry();
 | 
			
		||||
            for (const auto pseg : reader.segments) {
 | 
			
		||||
                const auto fsize = pseg->get_file_size(); // 0x42c/0x0
 | 
			
		||||
                const auto seg_data = pseg->get_data();
 | 
			
		||||
@@ -396,18 +397,39 @@ template <typename BASE> std::pair<uint64_t, bool> riscv_hart_m_p<BASE>::load_fi
 | 
			
		||||
                            traits<BASE>::MEM, pseg->get_physical_address(),
 | 
			
		||||
                            fsize, reinterpret_cast<const uint8_t *const>(seg_data));
 | 
			
		||||
                    if (res != iss::Ok)
 | 
			
		||||
                        LOG(ERROR) << "problem writing " << fsize << "bytes to 0x" << std::hex
 | 
			
		||||
                        LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex
 | 
			
		||||
                                   << pseg->get_physical_address();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            for (const auto sec : reader.sections) {
 | 
			
		||||
                if (sec->get_name() == ".tohost") {
 | 
			
		||||
            for(const auto sec : reader.sections) {
 | 
			
		||||
                if(sec->get_name() == ".symtab") {
 | 
			
		||||
                    if ( SHT_SYMTAB == sec->get_type() ||
 | 
			
		||||
                            SHT_DYNSYM == sec->get_type() ) {
 | 
			
		||||
                        ELFIO::symbol_section_accessor symbols( reader, sec );
 | 
			
		||||
                        auto sym_no = symbols.get_symbols_num();
 | 
			
		||||
                        std::string   name;
 | 
			
		||||
                        ELFIO::Elf64_Addr    value   = 0;
 | 
			
		||||
                        ELFIO::Elf_Xword     size    = 0;
 | 
			
		||||
                        unsigned char bind    = 0;
 | 
			
		||||
                        unsigned char type    = 0;
 | 
			
		||||
                        ELFIO::Elf_Half      section = 0;
 | 
			
		||||
                        unsigned char other   = 0;
 | 
			
		||||
                        for ( auto i = 0U; i < sym_no; ++i ) {
 | 
			
		||||
                            symbols.get_symbol( i, name, value, size, bind, type, section, other );
 | 
			
		||||
                            if(name=="tohost") {
 | 
			
		||||
                                tohost = value;
 | 
			
		||||
                            } else if(name=="fromhost") {
 | 
			
		||||
                                fromhost = value;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                } else if (sec->get_name() == ".tohost") {
 | 
			
		||||
                    tohost = sec->get_address();
 | 
			
		||||
                    fromhost = tohost + 0x40;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return std::make_pair(reader.get_entry(), true);
 | 
			
		||||
            }
 | 
			
		||||
            return std::make_pair(entry, true);
 | 
			
		||||
        }
 | 
			
		||||
        throw std::runtime_error("memory load file is not a valid elf file");
 | 
			
		||||
    }
 | 
			
		||||
@@ -519,7 +541,7 @@ iss::status riscv_hart_m_p<BASE>::write(const address_type type, const access_ty
 | 
			
		||||
                return iss::Err;
 | 
			
		||||
            }
 | 
			
		||||
            try {
 | 
			
		||||
                if(length>1 && (addr&(length-1))){
 | 
			
		||||
                if(!(access && iss::access_type::DEBUG) &&  length>1 && (addr&(length-1))){
 | 
			
		||||
                    this->reg.trap_state = 1<<31 | 6<<16;
 | 
			
		||||
                    fault_data=addr;
 | 
			
		||||
                    return iss::Err;
 | 
			
		||||
@@ -926,7 +948,11 @@ template <typename BASE> uint64_t riscv_hart_m_p<BASE>::enter_trap(uint64_t flag
 | 
			
		||||
    this->reg.PRIV = PRIV_M;
 | 
			
		||||
    this->reg.trap_state = 0;
 | 
			
		||||
    std::array<char, 32> buffer;
 | 
			
		||||
#if defined(_MSC_VER)
 | 
			
		||||
    sprintf(buffer.data(), "0x%016llx", addr);
 | 
			
		||||
#else
 | 
			
		||||
    sprintf(buffer.data(), "0x%016lx", addr);
 | 
			
		||||
#endif
 | 
			
		||||
    if((flags&0xffffffff) != 0xffffffff)
 | 
			
		||||
    CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '"
 | 
			
		||||
                       << (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")"
 | 
			
		||||
 
 | 
			
		||||
@@ -531,6 +531,7 @@ template <typename BASE> std::pair<uint64_t, bool> riscv_hart_msu_vp<BASE>::load
 | 
			
		||||
                if (sizeof(reg_t) == 4) 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_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine in file");
 | 
			
		||||
            auto entry = reader.get_entry();
 | 
			
		||||
            for (const auto pseg : reader.segments) {
 | 
			
		||||
                const auto fsize = pseg->get_file_size(); // 0x42c/0x0
 | 
			
		||||
                const auto seg_data = pseg->get_data();
 | 
			
		||||
@@ -543,14 +544,35 @@ template <typename BASE> std::pair<uint64_t, bool> riscv_hart_msu_vp<BASE>::load
 | 
			
		||||
                                   << pseg->get_physical_address();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            for (const auto sec : reader.sections) {
 | 
			
		||||
                if (sec->get_name() == ".tohost") {
 | 
			
		||||
            for(const auto sec : reader.sections) {
 | 
			
		||||
                if(sec->get_name() == ".symtab") {
 | 
			
		||||
                    if ( SHT_SYMTAB == sec->get_type() ||
 | 
			
		||||
                            SHT_DYNSYM == sec->get_type() ) {
 | 
			
		||||
                        ELFIO::symbol_section_accessor symbols( reader, sec );
 | 
			
		||||
                        auto sym_no = symbols.get_symbols_num();
 | 
			
		||||
                        std::string   name;
 | 
			
		||||
                        ELFIO::Elf64_Addr    value   = 0;
 | 
			
		||||
                        ELFIO::Elf_Xword     size    = 0;
 | 
			
		||||
                        unsigned char bind    = 0;
 | 
			
		||||
                        unsigned char type    = 0;
 | 
			
		||||
                        ELFIO::Elf_Half      section = 0;
 | 
			
		||||
                        unsigned char other   = 0;
 | 
			
		||||
                        for ( auto i = 0U; i < sym_no; ++i ) {
 | 
			
		||||
                            symbols.get_symbol( i, name, value, size, bind, type, section, other );
 | 
			
		||||
                            if(name=="tohost") {
 | 
			
		||||
                                tohost = value;
 | 
			
		||||
                            } else if(name=="fromhost") {
 | 
			
		||||
                                fromhost = value;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                } else if (sec->get_name() == ".tohost") {
 | 
			
		||||
                    tohost = sec->get_address();
 | 
			
		||||
                    fromhost = tohost + 0x40;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return std::make_pair(reader.get_entry(), true);
 | 
			
		||||
            }
 | 
			
		||||
            return std::make_pair(entry, true);
 | 
			
		||||
        }
 | 
			
		||||
        throw std::runtime_error("memory load file is not a valid elf file");
 | 
			
		||||
    }
 | 
			
		||||
@@ -1296,9 +1318,6 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
 | 
			
		||||
    // bits in mtvec
 | 
			
		||||
    this->reg.NEXT_PC = ivec & ~0x3UL;
 | 
			
		||||
    if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause;
 | 
			
		||||
    // reset trap state
 | 
			
		||||
    this->reg.PRIV = new_priv;
 | 
			
		||||
    this->reg.trap_state = 0;
 | 
			
		||||
    std::array<char, 32> buffer;
 | 
			
		||||
    sprintf(buffer.data(), "0x%016lx", addr);
 | 
			
		||||
    if((flags&0xffffffff) != 0xffffffff)
 | 
			
		||||
@@ -1306,6 +1325,9 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
 | 
			
		||||
                       << (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")"
 | 
			
		||||
                       << " at address " << buffer.data() << " occurred, changing privilege level from "
 | 
			
		||||
                       << lvl[cur_priv] << " to " << lvl[new_priv];
 | 
			
		||||
    // reset trap state
 | 
			
		||||
    this->reg.PRIV = new_priv;
 | 
			
		||||
    this->reg.trap_state = 0;
 | 
			
		||||
    update_vm_info();
 | 
			
		||||
    return this->reg.NEXT_PC;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -484,6 +484,7 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m
 | 
			
		||||
                if (sizeof(reg_t) == 4) 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_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine in file");
 | 
			
		||||
            auto entry = reader.get_entry();
 | 
			
		||||
            for (const auto pseg : reader.segments) {
 | 
			
		||||
                const auto fsize = pseg->get_file_size(); // 0x42c/0x0
 | 
			
		||||
                const auto seg_data = pseg->get_data();
 | 
			
		||||
@@ -496,14 +497,35 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m
 | 
			
		||||
                                   << pseg->get_physical_address();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            for (const auto sec : reader.sections) {
 | 
			
		||||
                if (sec->get_name() == ".tohost") {
 | 
			
		||||
            for(const auto sec : reader.sections) {
 | 
			
		||||
                if(sec->get_name() == ".symtab") {
 | 
			
		||||
                    if ( SHT_SYMTAB == sec->get_type() ||
 | 
			
		||||
                            SHT_DYNSYM == sec->get_type() ) {
 | 
			
		||||
                        ELFIO::symbol_section_accessor symbols( reader, sec );
 | 
			
		||||
                        auto sym_no = symbols.get_symbols_num();
 | 
			
		||||
                        std::string   name;
 | 
			
		||||
                        ELFIO::Elf64_Addr    value   = 0;
 | 
			
		||||
                        ELFIO::Elf_Xword     size    = 0;
 | 
			
		||||
                        unsigned char bind    = 0;
 | 
			
		||||
                        unsigned char type    = 0;
 | 
			
		||||
                        ELFIO::Elf_Half      section = 0;
 | 
			
		||||
                        unsigned char other   = 0;
 | 
			
		||||
                        for ( auto i = 0U; i < sym_no; ++i ) {
 | 
			
		||||
                            symbols.get_symbol( i, name, value, size, bind, type, section, other );
 | 
			
		||||
                            if(name=="tohost") {
 | 
			
		||||
                                tohost = value;
 | 
			
		||||
                            } else if(name=="fromhost") {
 | 
			
		||||
                                fromhost = value;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                } else if (sec->get_name() == ".tohost") {
 | 
			
		||||
                    tohost = sec->get_address();
 | 
			
		||||
                    fromhost = tohost + 0x40;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return std::make_pair(reader.get_entry(), true);
 | 
			
		||||
            }
 | 
			
		||||
            return std::make_pair(entry, true);
 | 
			
		||||
        }
 | 
			
		||||
        throw std::runtime_error("memory load file is not a valid elf file");
 | 
			
		||||
    }
 | 
			
		||||
@@ -525,8 +547,9 @@ template <typename BASE, features_e FEAT> bool riscv_hart_mu_p<BASE, FEAT>::pmp_
 | 
			
		||||
        reg_t tor = csr[pmpaddr0+i] << PMP_SHIFT;
 | 
			
		||||
        uint8_t cfg = csr[pmpcfg0+(i/4)]>>(i%4);
 | 
			
		||||
        if (cfg & PMP_A) {
 | 
			
		||||
            bool is_tor = (cfg & PMP_A) == PMP_TOR;
 | 
			
		||||
            bool is_na4 = (cfg & PMP_A) == PMP_NA4;
 | 
			
		||||
            auto pmp_a = (cfg & PMP_A) >> 3;
 | 
			
		||||
            bool is_tor = pmp_a == PMP_TOR;
 | 
			
		||||
            bool is_na4 = pmp_a == PMP_NA4;
 | 
			
		||||
 | 
			
		||||
            reg_t mask = (csr[pmpaddr0+i] << 1) | (!is_na4);
 | 
			
		||||
            mask = ~(mask & ~(mask + 1)) << PMP_SHIFT;
 | 
			
		||||
@@ -574,10 +597,10 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
 | 
			
		||||
        switch (space) {
 | 
			
		||||
        case traits<BASE>::MEM: {
 | 
			
		||||
            if(FEAT & FEAT_PMP){
 | 
			
		||||
                if(!pmp_check(access, addr, length)) {
 | 
			
		||||
                if(!pmp_check(access, addr, length) && (access&access_type::DEBUG) != access_type::DEBUG) {
 | 
			
		||||
                    fault_data = addr;
 | 
			
		||||
                    if (access && iss::access_type::DEBUG) throw trap_access(0, addr);
 | 
			
		||||
                    this->reg.trap_state = (1 << 31) | (1 << 16); // issue trap 1
 | 
			
		||||
                    this->reg.trap_state = (1 << 31) | ((access==access_type::FETCH?1:5) << 16); // issue trap 1
 | 
			
		||||
                    return iss::Err;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -669,10 +692,10 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
 | 
			
		||||
        switch (space) {
 | 
			
		||||
        case traits<BASE>::MEM: {
 | 
			
		||||
            if(FEAT & FEAT_PMP){
 | 
			
		||||
                if(!pmp_check(access, addr, length)) {
 | 
			
		||||
                if(!pmp_check(access, addr, length) && (access&access_type::DEBUG) != access_type::DEBUG) {
 | 
			
		||||
                    fault_data = addr;
 | 
			
		||||
                    if (access && iss::access_type::DEBUG) throw trap_access(0, addr);
 | 
			
		||||
                    this->reg.trap_state = (1 << 31) | (1 << 16); // issue trap 1
 | 
			
		||||
                    this->reg.trap_state = (1 << 31) | (7 << 16); // issue trap 1
 | 
			
		||||
                    return iss::Err;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -683,7 +706,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
 | 
			
		||||
                return iss::Err;
 | 
			
		||||
            }
 | 
			
		||||
            try {
 | 
			
		||||
                if(length>1 && (addr&(length-1))){
 | 
			
		||||
                if(length>1 && (addr&(length-1)) && (access&access_type::DEBUG) != access_type::DEBUG){
 | 
			
		||||
                    this->reg.trap_state = 1<<31 | 6<<16;
 | 
			
		||||
                    fault_data=addr;
 | 
			
		||||
                    return iss::Err;
 | 
			
		||||
@@ -1217,9 +1240,6 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::
 | 
			
		||||
    // bits in mtvec
 | 
			
		||||
    this->reg.NEXT_PC = ivec & ~0x3UL;
 | 
			
		||||
    if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause;
 | 
			
		||||
    // reset trap state
 | 
			
		||||
    this->reg.PRIV = new_priv;
 | 
			
		||||
    this->reg.trap_state = 0;
 | 
			
		||||
    std::array<char, 32> buffer;
 | 
			
		||||
    sprintf(buffer.data(), "0x%016lx", addr);
 | 
			
		||||
    if((flags&0xffffffff) != 0xffffffff)
 | 
			
		||||
@@ -1227,6 +1247,9 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::
 | 
			
		||||
                       << (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")"
 | 
			
		||||
                       << " at address " << buffer.data() << " occurred, changing privilege level from "
 | 
			
		||||
                       << lvl[this->reg.PRIV] << " to " << lvl[new_priv];
 | 
			
		||||
    // reset trap state
 | 
			
		||||
    this->reg.PRIV = new_priv;
 | 
			
		||||
    this->reg.trap_state = 0;
 | 
			
		||||
    return this->reg.NEXT_PC;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Copyright (C) 2017, 2018 MINRES Technologies GmbH
 | 
			
		||||
 * Copyright (C) 2017-2021 MINRES Technologies GmbH
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
@@ -30,18 +30,23 @@
 | 
			
		||||
 *
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef _SYSC_SIFIVE_FE310_H_
 | 
			
		||||
#define _SYSC_SIFIVE_FE310_H_
 | 
			
		||||
#ifndef _SYSC_CORE_COMPLEX_H_
 | 
			
		||||
#define _SYSC_CORE_COMPLEX_H_
 | 
			
		||||
 | 
			
		||||
#include "tlm/scc/initiator_mixin.h"
 | 
			
		||||
#include "scc/traceable.h"
 | 
			
		||||
#include "scc/utilities.h"
 | 
			
		||||
#include "tlm/scc/scv/tlm_rec_initiator_socket.h"
 | 
			
		||||
#include <tlm/scc/initiator_mixin.h>
 | 
			
		||||
#include <scc/traceable.h>
 | 
			
		||||
#include <scc/tick2time.h>
 | 
			
		||||
#include <scc/utilities.h>
 | 
			
		||||
#include <tlm/scc/scv/tlm_rec_initiator_socket.h>
 | 
			
		||||
#ifdef CWR_SYSTEMC
 | 
			
		||||
#include <scmlinc/scml_property.h>
 | 
			
		||||
#else
 | 
			
		||||
#include <cci_configuration>
 | 
			
		||||
#endif
 | 
			
		||||
#include <tlm>
 | 
			
		||||
#include <tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_core_ifs.h>
 | 
			
		||||
#include <tlm_utils/tlm_quantumkeeper.h>
 | 
			
		||||
#include <util/range_lut.h>
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
namespace sysc {
 | 
			
		||||
 | 
			
		||||
@@ -63,8 +68,6 @@ class core_complex : public sc_core::sc_module, public scc::traceable {
 | 
			
		||||
public:
 | 
			
		||||
    tlm::scc::initiator_mixin<tlm::scc::scv::tlm_rec_initiator_socket<32>> initiator{"intor"};
 | 
			
		||||
 | 
			
		||||
    sc_core::sc_in<sc_core::sc_time> clk_i{"clk_i"};
 | 
			
		||||
 | 
			
		||||
    sc_core::sc_in<bool> rst_i{"rst_i"};
 | 
			
		||||
 | 
			
		||||
    sc_core::sc_in<bool> global_irq_i{"global_irq_i"};
 | 
			
		||||
@@ -75,6 +78,9 @@ public:
 | 
			
		||||
 | 
			
		||||
    sc_core::sc_vector<sc_core::sc_in<bool>> local_irq_i{"local_irq_i", 16};
 | 
			
		||||
 | 
			
		||||
#ifndef CWR_SYSTEMC
 | 
			
		||||
	sc_core::sc_in<sc_core::sc_time> clk_i{"clk_i"};
 | 
			
		||||
 | 
			
		||||
    sc_core::sc_port<tlm::tlm_peek_if<uint64_t>, 1, sc_core::SC_ZERO_OR_MORE_BOUND> mtime_o;
 | 
			
		||||
 | 
			
		||||
    cci::cci_param<std::string> elf_file{"elf_file", ""};
 | 
			
		||||
@@ -93,7 +99,47 @@ public:
 | 
			
		||||
 | 
			
		||||
    cci::cci_param<uint32_t> mhartid{"mhartid", 0};
 | 
			
		||||
 | 
			
		||||
    core_complex(sc_core::sc_module_name name);
 | 
			
		||||
    core_complex(sc_core::sc_module_name const& name);
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
	sc_core::sc_in<bool> clk_i{"clk_i"};
 | 
			
		||||
 | 
			
		||||
	sc_core::sc_in<uint64_t> mtime_i{"mtime_i"};
 | 
			
		||||
 | 
			
		||||
	scml_property<std::string> elf_file{"elf_file", ""};
 | 
			
		||||
 | 
			
		||||
    scml_property<bool> enable_disass{"enable_disass", false};
 | 
			
		||||
 | 
			
		||||
    scml_property<unsigned long long> reset_address{"reset_address", 0ULL};
 | 
			
		||||
 | 
			
		||||
    scml_property<std::string> core_type{"core_type", "tgc_c"};
 | 
			
		||||
 | 
			
		||||
    scml_property<std::string> backend{"backend", "interp"};
 | 
			
		||||
 | 
			
		||||
    scml_property<unsigned> gdb_server_port{"gdb_server_port", 0};
 | 
			
		||||
 | 
			
		||||
    scml_property<bool> dump_ir{"dump_ir", false};
 | 
			
		||||
 | 
			
		||||
    scml_property<uint32_t> mhartid{"mhartid", 0};
 | 
			
		||||
 | 
			
		||||
    core_complex(sc_core::sc_module_name const& name)
 | 
			
		||||
    : sc_module(name)
 | 
			
		||||
    , local_irq_i{"local_irq_i", 16}
 | 
			
		||||
    , elf_file{"elf_file", ""}
 | 
			
		||||
    , enable_disass{"enable_disass", false}
 | 
			
		||||
    , reset_address{"reset_address", 0ULL}
 | 
			
		||||
    , core_type{"core_type", "tgc_c"}
 | 
			
		||||
    , backend{"backend", "interp"}
 | 
			
		||||
    , gdb_server_port{"gdb_server_port", 0}
 | 
			
		||||
    , dump_ir{"dump_ir", false}
 | 
			
		||||
    , mhartid{"mhartid", 0}
 | 
			
		||||
    , read_lut(tlm_dmi_ext())
 | 
			
		||||
    , write_lut(tlm_dmi_ext())
 | 
			
		||||
    {
 | 
			
		||||
    	init();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    ~core_complex();
 | 
			
		||||
 | 
			
		||||
@@ -119,11 +165,12 @@ public:
 | 
			
		||||
 | 
			
		||||
    bool disass_output(uint64_t pc, const std::string instr);
 | 
			
		||||
 | 
			
		||||
    void set_clock_period(sc_core::sc_time period);
 | 
			
		||||
protected:
 | 
			
		||||
    void before_end_of_elaboration() override;
 | 
			
		||||
    void start_of_simulation() override;
 | 
			
		||||
	void forward();
 | 
			
		||||
    void run();
 | 
			
		||||
    void clk_cb();
 | 
			
		||||
    void rst_cb();
 | 
			
		||||
    void sw_irq_cb();
 | 
			
		||||
    void timer_irq_cb();
 | 
			
		||||
@@ -132,12 +179,14 @@ protected:
 | 
			
		||||
    util::range_lut<tlm_dmi_ext> read_lut, write_lut;
 | 
			
		||||
    tlm_utils::tlm_quantumkeeper quantum_keeper;
 | 
			
		||||
    std::vector<uint8_t> write_buf;
 | 
			
		||||
    std::unique_ptr<core_wrapper> cpu;
 | 
			
		||||
    sc_core::sc_time curr_clk;
 | 
			
		||||
    std::unique_ptr<core_trace> trc;
 | 
			
		||||
    core_wrapper* cpu{nullptr};
 | 
			
		||||
    sc_core::sc_signal<sc_core::sc_time> curr_clk;
 | 
			
		||||
    core_trace* trc{nullptr};
 | 
			
		||||
    std::unique_ptr<scc::tick2time> t2t;
 | 
			
		||||
private:
 | 
			
		||||
    void init();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} /* namespace SiFive */
 | 
			
		||||
} /* namespace sysc */
 | 
			
		||||
 | 
			
		||||
#endif /* _SYSC_SIFIVE_FE310_H_ */
 | 
			
		||||
#endif /* _SYSC_CORE_COMPLEX_H_ */
 | 
			
		||||
 
 | 
			
		||||
@@ -49,7 +49,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
/*----------------------------------------------------------------------------
 | 
			
		||||
*----------------------------------------------------------------------------*/
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
#define SOFTFLOAT_BUILTIN_CLZ 1
 | 
			
		||||
#define SOFTFLOAT_INTRINSIC_INT128 1
 | 
			
		||||
#endif
 | 
			
		||||
#include "opts-GCC.h"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								src/main.cpp
									
									
									
									
									
								
							@@ -47,7 +47,7 @@ using tgc_b_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_b>;
 | 
			
		||||
#ifdef CORE_TGC_D
 | 
			
		||||
#include "iss/arch/riscv_hart_mu_p.h"
 | 
			
		||||
#include "iss/arch/tgc_d.h"
 | 
			
		||||
using tgc_d_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_d, iss::arch::FEAT_PMP>;
 | 
			
		||||
using tgc_d_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_d, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef WITH_LLVM
 | 
			
		||||
#include <iss/llvm/jit_helper.h>
 | 
			
		||||
@@ -78,7 +78,7 @@ int main(int argc, char *argv[]) {
 | 
			
		||||
        ("mem,m", po::value<std::string>(), "the memory input file")
 | 
			
		||||
        ("plugin,p", po::value<std::vector<std::string>>(), "plugin to activate")
 | 
			
		||||
        ("backend", po::value<std::string>()->default_value("interp"), "the memory input file")
 | 
			
		||||
        ("isa", po::value<std::string>()->default_value("tgf_c"), "isa to use for simulation");
 | 
			
		||||
        ("isa", po::value<std::string>()->default_value("tgc_c"), "isa to use for simulation");
 | 
			
		||||
    // clang-format on
 | 
			
		||||
    auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run();
 | 
			
		||||
    try {
 | 
			
		||||
@@ -123,24 +123,24 @@ int main(int argc, char *argv[]) {
 | 
			
		||||
        iss::vm_ptr vm{nullptr};
 | 
			
		||||
        iss::cpu_ptr cpu{nullptr};
 | 
			
		||||
        std::string isa_opt(clim["isa"].as<std::string>());
 | 
			
		||||
        if (isa_opt == "tgf_c") {
 | 
			
		||||
        if (isa_opt == "tgc_c") {
 | 
			
		||||
            std::tie(cpu, vm) =
 | 
			
		||||
                iss::create_cpu<tgc_c_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
 | 
			
		||||
        } else
 | 
			
		||||
#ifdef CORE_TGC_B
 | 
			
		||||
        if (isa_opt == "tgf_b") {
 | 
			
		||||
        if (isa_opt == "tgc_b") {
 | 
			
		||||
            std::tie(cpu, vm) =
 | 
			
		||||
                iss::create_cpu<tgc_b_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
 | 
			
		||||
        } else
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef CORE_TGC_D
 | 
			
		||||
        if (isa_opt == "tgf_d") {
 | 
			
		||||
        if (isa_opt == "tgc_d") {
 | 
			
		||||
            std::tie(cpu, vm) =
 | 
			
		||||
                iss::create_cpu<tgc_d_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
 | 
			
		||||
        } else
 | 
			
		||||
#endif
 | 
			
		||||
        {
 | 
			
		||||
            LOG(ERROR) << "Illegal argument value for '--isa': " << clim["isa"].as<std::string>() << std::endl;
 | 
			
		||||
            LOG(ERR) << "Illegal argument value for '--isa': " << clim["isa"].as<std::string>() << std::endl;
 | 
			
		||||
            return 127;
 | 
			
		||||
        }
 | 
			
		||||
        if (clim.count("plugin")) {
 | 
			
		||||
@@ -161,7 +161,7 @@ int main(int argc, char *argv[]) {
 | 
			
		||||
                    vm->register_plugin(*ce_plugin);
 | 
			
		||||
                    plugin_list.push_back(ce_plugin);
 | 
			
		||||
                } else {
 | 
			
		||||
                    LOG(ERROR) << "Unknown plugin name: " << plugin_name << ", valid names are 'ce', 'ic'" << std::endl;
 | 
			
		||||
                    LOG(ERR) << "Unknown plugin name: " << plugin_name << ", valid names are 'ce', 'ic'" << std::endl;
 | 
			
		||||
                    return 127;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -196,7 +196,7 @@ int main(int argc, char *argv[]) {
 | 
			
		||||
        auto cycles = clim["instructions"].as<uint64_t>();
 | 
			
		||||
        res = vm->start(cycles, dump);
 | 
			
		||||
    } catch (std::exception &e) {
 | 
			
		||||
        LOG(ERROR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit"
 | 
			
		||||
        LOG(ERR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit"
 | 
			
		||||
                   << std::endl;
 | 
			
		||||
        res = 2;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -47,10 +47,10 @@ iss::plugin::cycle_estimate::cycle_estimate(std::string config_file_name)
 | 
			
		||||
            try {
 | 
			
		||||
                is >> root;
 | 
			
		||||
            } catch (Json::RuntimeError &e) {
 | 
			
		||||
                LOG(ERROR) << "Could not parse input file " << config_file_name << ", reason: " << e.what();
 | 
			
		||||
                LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what();
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            LOG(ERROR) << "Could not open input file " << config_file_name;
 | 
			
		||||
            LOG(ERR) << "Could not open input file " << config_file_name;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -77,7 +77,7 @@ bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if&
 | 
			
		||||
    		}
 | 
			
		||||
    	}
 | 
			
		||||
    } else {
 | 
			
		||||
        LOG(ERROR)<<"plugin cycle_estimate: could not find an entry for "<<core_name<<" in JSON file"<<std::endl;
 | 
			
		||||
        LOG(ERR)<<"plugin cycle_estimate: could not find an entry for "<<core_name<<" in JSON file"<<std::endl;
 | 
			
		||||
    }
 | 
			
		||||
	return true;
 | 
			
		||||
 | 
			
		||||
@@ -87,6 +87,8 @@ void iss::plugin::cycle_estimate::callback(instr_info_t instr_info, exec_info co
 | 
			
		||||
    assert(arch_instr && "No instrumentation interface available but callback executed");
 | 
			
		||||
	auto entry = delays[instr_info.instr_id];
 | 
			
		||||
	bool taken = (arch_instr->get_next_pc()-arch_instr->get_pc()) != (entry.size/8);
 | 
			
		||||
    uint32_t delay = taken ? entry.taken : entry.not_taken;
 | 
			
		||||
    if(delay>1) arch_instr->set_curr_instr_cycles(delay);
 | 
			
		||||
    if (taken && entry.taken > 1)
 | 
			
		||||
        arch_instr->set_curr_instr_cycles(entry.taken);
 | 
			
		||||
    else if (entry.not_taken > 1)
 | 
			
		||||
        arch_instr->set_curr_instr_cycles(entry.not_taken);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -46,10 +46,10 @@ iss::plugin::instruction_count::instruction_count(std::string config_file_name)
 | 
			
		||||
            try {
 | 
			
		||||
                is >> root;
 | 
			
		||||
            } catch (Json::RuntimeError &e) {
 | 
			
		||||
                LOG(ERROR) << "Could not parse input file " << config_file_name << ", reason: " << e.what();
 | 
			
		||||
                LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what();
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            LOG(ERROR) << "Could not open input file " << config_file_name;
 | 
			
		||||
            LOG(ERR) << "Could not open input file " << config_file_name;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -85,7 +85,7 @@ bool iss::plugin::instruction_count::registration(const char* const version, vm_
 | 
			
		||||
    	}
 | 
			
		||||
    	rep_counts.resize(delays.size());
 | 
			
		||||
    } else {
 | 
			
		||||
        LOG(ERROR)<<"plugin instruction_count: could not find an entry for "<<core_name<<" in JSON file"<<std::endl;
 | 
			
		||||
        LOG(ERR)<<"plugin instruction_count: could not find an entry for "<<core_name<<" in JSON file"<<std::endl;
 | 
			
		||||
    }
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,13 @@
 | 
			
		||||
 *
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
// clang-format off
 | 
			
		||||
#include "iss/debugger/gdb_session.h"
 | 
			
		||||
#include "iss/debugger/encoderdecoder.h"
 | 
			
		||||
#include "iss/debugger/server.h"
 | 
			
		||||
#include "iss/debugger/target_adapter_if.h"
 | 
			
		||||
#include "iss/iss.h"
 | 
			
		||||
#include "iss/vm_types.h"
 | 
			
		||||
#include "sysc/core_complex.h"
 | 
			
		||||
#ifdef CORE_TGC_B
 | 
			
		||||
#include "iss/arch/riscv_hart_m_p.h"
 | 
			
		||||
@@ -44,16 +51,11 @@ using tgc_c_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_c>;
 | 
			
		||||
#include "iss/arch/tgc_d.h"
 | 
			
		||||
using tgc_d_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_d, iss::arch::FEAT_PMP>;
 | 
			
		||||
#endif
 | 
			
		||||
#include "iss/debugger/encoderdecoder.h"
 | 
			
		||||
#include "iss/debugger/gdb_session.h"
 | 
			
		||||
#include "iss/debugger/server.h"
 | 
			
		||||
#include "iss/debugger/target_adapter_if.h"
 | 
			
		||||
#include "iss/iss.h"
 | 
			
		||||
#include "iss/vm_types.h"
 | 
			
		||||
#include "scc/report.h"
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <array>
 | 
			
		||||
// clang-format on
 | 
			
		||||
 | 
			
		||||
#define STR(X) #X
 | 
			
		||||
#define CREATE_CORE(CN) \
 | 
			
		||||
@@ -66,6 +68,18 @@ if (type == STR(CN)) { std::tie(cpu, vm) = create_core<CN ## _plat_type>(backend
 | 
			
		||||
using namespace scv_tr;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef CWR_SYSTEMC
 | 
			
		||||
#define GET_PROP_VALUE(P) P.get_value()
 | 
			
		||||
#else
 | 
			
		||||
#define GET_PROP_VALUE(P) P.getValue()
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef _MSC_VER
 | 
			
		||||
// not #if defined(_WIN32) || defined(_WIN64) because we have strncasecmp in mingw
 | 
			
		||||
#define strncasecmp _strnicmp
 | 
			
		||||
#define strcasecmp _stricmp
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace sysc {
 | 
			
		||||
namespace tgfs {
 | 
			
		||||
using namespace std;
 | 
			
		||||
@@ -103,11 +117,11 @@ public:
 | 
			
		||||
    sync_type needed_sync() const override { return PRE_SYNC; }
 | 
			
		||||
 | 
			
		||||
    void disass_output(uint64_t pc, const std::string instr) override {
 | 
			
		||||
        if (!owner->disass_output(pc, instr) && INFO <= Log<Output2FILE<disass>>::reporting_level() && Output2FILE<disass>::stream()) {
 | 
			
		||||
        if (!owner->disass_output(pc, instr)) {
 | 
			
		||||
            std::stringstream s;
 | 
			
		||||
            s << "[p:" << lvl[this->reg.PRIV] << ";s:0x" << std::hex << std::setfill('0')
 | 
			
		||||
              << std::setw(sizeof(reg_t) * 2) << (reg_t)this->state.mstatus << std::dec << ";c:" << this->reg.icount << "]";
 | 
			
		||||
            Log<Output2FILE<disass>>().get(INFO, "disass")
 | 
			
		||||
            SCCDEBUG(owner->name())<<"disass: "
 | 
			
		||||
                << "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40)
 | 
			
		||||
                << std::setfill(' ') << std::left << instr << s.str();
 | 
			
		||||
        }
 | 
			
		||||
@@ -137,6 +151,7 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status read_csr(unsigned addr, reg_t &val) override {
 | 
			
		||||
#ifndef CWR_SYSTEMC
 | 
			
		||||
        if((addr==arch::time || addr==arch::timeh) && owner->mtime_o.get_interface(0)){
 | 
			
		||||
            uint64_t time_val;
 | 
			
		||||
            bool ret = owner->mtime_o->nb_peek(time_val);
 | 
			
		||||
@@ -147,6 +162,17 @@ public:
 | 
			
		||||
                val = static_cast<reg_t>(time_val >> 32);
 | 
			
		||||
            }
 | 
			
		||||
            return ret?Ok:Err;
 | 
			
		||||
#else
 | 
			
		||||
		if((addr==arch::time || addr==arch::timeh)){
 | 
			
		||||
			uint64_t time_val = owner->mtime_i.read();
 | 
			
		||||
			if (addr == iss::arch::time) {
 | 
			
		||||
				val = static_cast<reg_t>(time_val);
 | 
			
		||||
			} else if (addr == iss::arch::timeh) {
 | 
			
		||||
				if (sizeof(reg_t) != 4) return iss::Err;
 | 
			
		||||
				val = static_cast<reg_t>(time_val >> 32);
 | 
			
		||||
			}
 | 
			
		||||
			return Ok;
 | 
			
		||||
#endif
 | 
			
		||||
        } else {
 | 
			
		||||
            return PLAT::read_csr(addr, val);
 | 
			
		||||
        }
 | 
			
		||||
@@ -269,7 +295,7 @@ public:
 | 
			
		||||
        CREATE_CORE(tgc_d)
 | 
			
		||||
#endif
 | 
			
		||||
        {
 | 
			
		||||
            LOG(ERROR) << "Illegal argument value for core type: " << type << std::endl;
 | 
			
		||||
            LOG(ERR) << "Illegal argument value for core type: " << type << std::endl;
 | 
			
		||||
        }
 | 
			
		||||
        auto *srv = debugger::server<debugger::gdb_session>::get();
 | 
			
		||||
        if (srv) tgt_adapter = srv->get_target();
 | 
			
		||||
@@ -297,13 +323,19 @@ struct core_trace {
 | 
			
		||||
    scv_tr_handle tr_handle;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
core_complex::core_complex(sc_module_name name)
 | 
			
		||||
SC_HAS_PROCESS(core_complex);// NOLINT
 | 
			
		||||
#ifndef CWR_SYSTEMC
 | 
			
		||||
core_complex::core_complex(sc_module_name const& name)
 | 
			
		||||
: sc_module(name)
 | 
			
		||||
, read_lut(tlm_dmi_ext())
 | 
			
		||||
, write_lut(tlm_dmi_ext())
 | 
			
		||||
, trc(new core_trace)
 | 
			
		||||
{
 | 
			
		||||
    SC_HAS_PROCESS(core_complex);// NOLINT
 | 
			
		||||
	init();
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void core_complex::init(){
 | 
			
		||||
	trc=new core_trace();
 | 
			
		||||
    initiator.register_invalidate_direct_mem_ptr([=](uint64_t start, uint64_t end) -> void {
 | 
			
		||||
        auto lut_entry = read_lut.getEntry(start);
 | 
			
		||||
        if (lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && end <= lut_entry.get_end_address() + 1) {
 | 
			
		||||
@@ -316,8 +348,6 @@ core_complex::core_complex(sc_module_name name)
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    SC_THREAD(run);
 | 
			
		||||
    SC_METHOD(clk_cb);
 | 
			
		||||
    sensitive << clk_i;
 | 
			
		||||
    SC_METHOD(rst_cb);
 | 
			
		||||
    sensitive << rst_i;
 | 
			
		||||
    SC_METHOD(sw_irq_cb);
 | 
			
		||||
@@ -327,29 +357,48 @@ core_complex::core_complex(sc_module_name name)
 | 
			
		||||
    SC_METHOD(global_irq_cb);
 | 
			
		||||
    sensitive << global_irq_i;
 | 
			
		||||
    trc->m_db=scv_tr_db::get_default_db();
 | 
			
		||||
 | 
			
		||||
	SC_METHOD(forward);
 | 
			
		||||
#ifndef CWR_SYSTEMC
 | 
			
		||||
	sensitive<<clk_i;
 | 
			
		||||
#else
 | 
			
		||||
	sensitive<<curr_clk;
 | 
			
		||||
	t2t.reset(new scc::tick2time{"t2t"});
 | 
			
		||||
	t2t->clk_i(clk_i);
 | 
			
		||||
	t2t->clk_o(curr_clk);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
core_complex::~core_complex() = default;
 | 
			
		||||
core_complex::~core_complex(){
 | 
			
		||||
    delete cpu;
 | 
			
		||||
    delete trc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void core_complex::trace(sc_trace_file *trf) const {}
 | 
			
		||||
 | 
			
		||||
void core_complex::before_end_of_elaboration() {
 | 
			
		||||
    SCCDEBUG(SCMOD)<<"instantiating iss::arch::tgf with "<<backend.get_value()<<" backend";
 | 
			
		||||
    cpu = scc::make_unique<core_wrapper>(this);
 | 
			
		||||
    cpu->create_cpu(core_type.get_value(), backend.get_value(), gdb_server_port.get_value(), mhartid.get_value());
 | 
			
		||||
    SCCDEBUG(SCMOD)<<"instantiating iss::arch::tgf with "<<GET_PROP_VALUE(backend)<<" backend";
 | 
			
		||||
    // cpu = scc::make_unique<core_wrapper>(this);
 | 
			
		||||
    cpu = new core_wrapper(this);
 | 
			
		||||
    cpu->create_cpu(GET_PROP_VALUE(core_type), GET_PROP_VALUE(backend), GET_PROP_VALUE(gdb_server_port), GET_PROP_VALUE(mhartid));
 | 
			
		||||
    sc_assert(cpu->vm!=nullptr);
 | 
			
		||||
    cpu->vm->setDisassEnabled(enable_disass.get_value() || trc->m_db != nullptr);
 | 
			
		||||
    cpu->vm->setDisassEnabled(GET_PROP_VALUE(enable_disass) || trc->m_db != nullptr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void core_complex::start_of_simulation() {
 | 
			
		||||
    quantum_keeper.reset();
 | 
			
		||||
    if (elf_file.get_value().size() > 0) {
 | 
			
		||||
        istringstream is(elf_file.get_value());
 | 
			
		||||
    if (GET_PROP_VALUE(elf_file).size() > 0) {
 | 
			
		||||
        istringstream is(GET_PROP_VALUE(elf_file));
 | 
			
		||||
        string s;
 | 
			
		||||
        while (getline(is, s, ',')) {
 | 
			
		||||
            std::pair<uint64_t, bool> start_addr = cpu->load_file(s);
 | 
			
		||||
#ifndef CWR_SYSTEMC
 | 
			
		||||
            if (reset_address.is_default_value() && start_addr.second == true)
 | 
			
		||||
                reset_address.set_value(start_addr.first);
 | 
			
		||||
#else
 | 
			
		||||
            if (start_addr.second == true)
 | 
			
		||||
                reset_address=start_addr.first;
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (trc->m_db != nullptr && trc->stream_handle == nullptr) {
 | 
			
		||||
@@ -371,9 +420,18 @@ bool core_complex::disass_output(uint64_t pc, const std::string instr_str) {
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void core_complex::clk_cb() {
 | 
			
		||||
    curr_clk = clk_i.read();
 | 
			
		||||
    if (curr_clk == SC_ZERO_TIME) cpu->set_interrupt_execution(true);
 | 
			
		||||
void core_complex::forward() {
 | 
			
		||||
#ifndef CWR_SYSTEMC
 | 
			
		||||
	set_clock_period(clk_i.read());
 | 
			
		||||
#else
 | 
			
		||||
	set_clock_period(curr_clk.read());
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void core_complex::set_clock_period(sc_core::sc_time period) {
 | 
			
		||||
	curr_clk = period;
 | 
			
		||||
    if (period == SC_ZERO_TIME) cpu->set_interrupt_execution(true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void core_complex::rst_cb() {
 | 
			
		||||
@@ -390,11 +448,11 @@ void core_complex::run() {
 | 
			
		||||
    wait(SC_ZERO_TIME); // separate from elaboration phase
 | 
			
		||||
    do {
 | 
			
		||||
        if (rst_i.read()) {
 | 
			
		||||
            cpu->reset(reset_address.get_value());
 | 
			
		||||
            cpu->reset(GET_PROP_VALUE(reset_address));
 | 
			
		||||
            wait(rst_i.negedge_event());
 | 
			
		||||
        }
 | 
			
		||||
        while (clk_i.read() == SC_ZERO_TIME) {
 | 
			
		||||
            wait(clk_i.value_changed_event());
 | 
			
		||||
        while (curr_clk.read() == SC_ZERO_TIME) {
 | 
			
		||||
            wait(curr_clk.value_changed_event());
 | 
			
		||||
        }
 | 
			
		||||
        cpu->set_interrupt_execution(false);
 | 
			
		||||
        cpu->start();
 | 
			
		||||
@@ -531,6 +589,5 @@ bool core_complex::write_mem_dbg(uint64_t addr, unsigned length, const uint8_t *
 | 
			
		||||
        return initiator->transport_dbg(gp) == length;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} /* namespace SiFive */
 | 
			
		||||
} /* namespace sysc */
 | 
			
		||||
 
 | 
			
		||||
@@ -30,23 +30,21 @@
 | 
			
		||||
 *
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "../fp_functions.h"
 | 
			
		||||
#include <iss/arch/tgc_c.h>
 | 
			
		||||
#include <iss/arch/riscv_hart_m_p.h>
 | 
			
		||||
// clang-format off
 | 
			
		||||
#include <iss/debugger/gdb_session.h>
 | 
			
		||||
#include <iss/debugger/server.h>
 | 
			
		||||
#include <iss/iss.h>
 | 
			
		||||
#include <iss/arch/tgc_c.h>
 | 
			
		||||
#include <iss/arch/riscv_hart_m_p.h>
 | 
			
		||||
#include <iss/interp/vm_base.h>
 | 
			
		||||
#include "../fp_functions.h"
 | 
			
		||||
#include <util/logging.h>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
 | 
			
		||||
#ifndef FMT_HEADER_ONLY
 | 
			
		||||
#define FMT_HEADER_ONLY
 | 
			
		||||
#endif
 | 
			
		||||
#include <fmt/format.h>
 | 
			
		||||
 | 
			
		||||
#include <array>
 | 
			
		||||
#include <iss/debugger/riscv_target_adapter.h>
 | 
			
		||||
// clang-format on
 | 
			
		||||
 | 
			
		||||
namespace iss {
 | 
			
		||||
namespace interp {
 | 
			
		||||
@@ -4138,8 +4136,8 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
 | 
			
		||||
            this->do_sync(POST_SYNC, std::numeric_limits<unsigned>::max());
 | 
			
		||||
            pc.val = super::core.enter_trap(std::numeric_limits<uint64_t>::max(), pc.val, 0);
 | 
			
		||||
        } else {
 | 
			
		||||
            if (is_jump_to_self_enabled(cond) &&
 | 
			
		||||
                    (insn == 0x0000006f || (insn&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
 | 
			
		||||
            if (is_jump_to_self_enabled(cond) && (insn == 0x0000006f || (insn&0xffff)==0xa001))
 | 
			
		||||
                throw simulation_stopped(0); // 'J 0' or 'C.J 0'
 | 
			
		||||
            auto f = decode_inst(insn);
 | 
			
		||||
            pc = (this->*f)(pc, insn);
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user