3 Commits

10 changed files with 350 additions and 80 deletions

View File

@ -1,5 +1,7 @@
cmake_minimum_required(VERSION 3.12) cmake_minimum_required(VERSION 3.12)
###############################################################################
#
###############################################################################
project(dbt-rise-tgc VERSION 1.0.0) project(dbt-rise-tgc VERSION 1.0.0)
include(GNUInstallDirs) include(GNUInstallDirs)
@ -61,12 +63,28 @@ elseif(TARGET elfio::elfio)
else() else()
message(FATAL_ERROR "No elfio library found, maybe a find_package() call is missing") message(FATAL_ERROR "No elfio library found, maybe a find_package() call is missing")
endif() endif()
set_target_properties(${PROJECT_NAME} PROPERTIES set_target_properties(${PROJECT_NAME} PROPERTIES
VERSION ${PROJECT_VERSION} VERSION ${PROJECT_VERSION}
FRAMEWORK FALSE 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) project(tgc-sim)
find_package(Boost COMPONENTS program_options thread REQUIRED) find_package(Boost COMPONENTS program_options thread REQUIRED)
@ -90,16 +108,18 @@ if (Tcmalloc_FOUND)
target_link_libraries(${PROJECT_NAME} ${Tcmalloc_LIBRARIES}) target_link_libraries(${PROJECT_NAME} ${Tcmalloc_LIBRARIES})
endif(Tcmalloc_FOUND) endif(Tcmalloc_FOUND)
install(TARGETS dbt-rise-tgc tgc-sim install(TARGETS tgc-sim
EXPORT ${PROJECT_NAME}Targets # for downstream dependencies EXPORT ${PROJECT_NAME}Targets # for downstream dependencies
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs # static lib ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # static lib
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT libs # binaries RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # binaries
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs # shared lib LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # shared lib
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs # for mac FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} # for mac
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} COMPONENT devel # headers for mac (note the different component -> different package) PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} # headers for mac (note the different component -> different package)
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers
) )
###############################################################################
#
###############################################################################
project(dbt-rise-tgc_sc VERSION 1.0.0) project(dbt-rise-tgc_sc VERSION 1.0.0)
include(FindSystemCPackage) include(FindSystemCPackage)
@ -121,18 +141,19 @@ if(SystemC_FOUND)
target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs}) target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
endif() endif()
set(LIB_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/incl/sysc/core_complex.h)
set_target_properties(${PROJECT_NAME} PROPERTIES set_target_properties(${PROJECT_NAME} PROPERTIES
VERSION ${PROJECT_VERSION} VERSION ${PROJECT_VERSION}
FRAMEWORK FALSE FRAMEWORK FALSE
PUBLIC_HEADER "${LIB_HEADERS}" # specify the public headers 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 EXPORT ${PROJECT_NAME}Targets # for downstream dependencies
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs # static lib ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # static lib
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT libs # binaries RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # binaries
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs # shared lib LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # shared lib
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs # for mac FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} # for mac
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} COMPONENT devel # headers for mac (note the different component -> different package) PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sysc # headers for mac (note the different component -> different package)
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers
) )
endif() endif()

30
contrib/build.tcl Normal file
View 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
View 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
View 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

View File

@ -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 (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_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"); 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) { 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();
@ -400,14 +401,35 @@ template <typename BASE> std::pair<uint64_t, bool> riscv_hart_m_p<BASE>::load_fi
<< pseg->get_physical_address(); << pseg->get_physical_address();
} }
} }
for (const auto sec : reader.sections) { for(const auto sec : reader.sections) {
if (sec->get_name() == ".tohost") { 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(); tohost = sec->get_address();
fromhost = tohost + 0x40; 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"); throw std::runtime_error("memory load file is not a valid elf file");
} }

View File

@ -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 (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_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"); 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) { 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();
@ -543,14 +544,35 @@ template <typename BASE> std::pair<uint64_t, bool> riscv_hart_msu_vp<BASE>::load
<< pseg->get_physical_address(); << pseg->get_physical_address();
} }
} }
for (const auto sec : reader.sections) { for(const auto sec : reader.sections) {
if (sec->get_name() == ".tohost") { 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(); tohost = sec->get_address();
fromhost = tohost + 0x40; 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"); 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 // bits in mtvec
this->reg.NEXT_PC = ivec & ~0x3UL; this->reg.NEXT_PC = ivec & ~0x3UL;
if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; 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; std::array<char, 32> buffer;
sprintf(buffer.data(), "0x%016lx", addr); sprintf(buffer.data(), "0x%016lx", addr);
if((flags&0xffffffff) != 0xffffffff) 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 << ")" << (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")"
<< " at address " << buffer.data() << " occurred, changing privilege level from " << " at address " << buffer.data() << " occurred, changing privilege level from "
<< lvl[cur_priv] << " to " << lvl[new_priv]; << lvl[cur_priv] << " to " << lvl[new_priv];
// reset trap state
this->reg.PRIV = new_priv;
this->reg.trap_state = 0;
update_vm_info(); update_vm_info();
return this->reg.NEXT_PC; return this->reg.NEXT_PC;
} }

View File

@ -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 (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_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"); 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) { 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();
@ -496,14 +497,35 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m
<< pseg->get_physical_address(); << pseg->get_physical_address();
} }
} }
for (const auto sec : reader.sections) { for(const auto sec : reader.sections) {
if (sec->get_name() == ".tohost") { 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(); tohost = sec->get_address();
fromhost = tohost + 0x40; 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"); 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; reg_t tor = csr[pmpaddr0+i] << PMP_SHIFT;
uint8_t cfg = csr[pmpcfg0+(i/4)]>>(i%4); uint8_t cfg = csr[pmpcfg0+(i/4)]>>(i%4);
if (cfg & PMP_A) { if (cfg & PMP_A) {
bool is_tor = (cfg & PMP_A) == PMP_TOR; auto pmp_a = (cfg & PMP_A) >> 3;
bool is_na4 = (cfg & PMP_A) == PMP_NA4; bool is_tor = pmp_a == PMP_TOR;
bool is_na4 = pmp_a == PMP_NA4;
reg_t mask = (csr[pmpaddr0+i] << 1) | (!is_na4); reg_t mask = (csr[pmpaddr0+i] << 1) | (!is_na4);
mask = ~(mask & ~(mask + 1)) << PMP_SHIFT; mask = ~(mask & ~(mask + 1)) << PMP_SHIFT;
@ -574,7 +597,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
switch (space) { switch (space) {
case traits<BASE>::MEM: { case traits<BASE>::MEM: {
if(FEAT & FEAT_PMP){ 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; fault_data = addr;
if (access && iss::access_type::DEBUG) throw trap_access(0, 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) | (1 << 16); // issue trap 1
@ -669,7 +692,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
switch (space) { switch (space) {
case traits<BASE>::MEM: { case traits<BASE>::MEM: {
if(FEAT & FEAT_PMP){ 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; fault_data = addr;
if (access && iss::access_type::DEBUG) throw trap_access(0, 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) | (1 << 16); // issue trap 1
@ -683,7 +706,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
return iss::Err; return iss::Err;
} }
try { 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; this->reg.trap_state = 1<<31 | 6<<16;
fault_data=addr; fault_data=addr;
return iss::Err; return iss::Err;
@ -1217,9 +1240,6 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::
// bits in mtvec // bits in mtvec
this->reg.NEXT_PC = ivec & ~0x3UL; this->reg.NEXT_PC = ivec & ~0x3UL;
if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; 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; std::array<char, 32> buffer;
sprintf(buffer.data(), "0x%016lx", addr); sprintf(buffer.data(), "0x%016lx", addr);
if((flags&0xffffffff) != 0xffffffff) 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 << ")" << (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")"
<< " at address " << buffer.data() << " occurred, changing privilege level from " << " at address " << buffer.data() << " occurred, changing privilege level from "
<< lvl[this->reg.PRIV] << " to " << lvl[new_priv]; << 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; return this->reg.NEXT_PC;
} }

View File

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (C) 2017, 2018 MINRES Technologies GmbH * Copyright (C) 2017-2021 MINRES Technologies GmbH
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -30,18 +30,23 @@
* *
*******************************************************************************/ *******************************************************************************/
#ifndef _SYSC_SIFIVE_FE310_H_ #ifndef _SYSC_CORE_COMPLEX_H_
#define _SYSC_SIFIVE_FE310_H_ #define _SYSC_CORE_COMPLEX_H_
#include "tlm/scc/initiator_mixin.h" #include <tlm/scc/initiator_mixin.h>
#include "scc/traceable.h" #include <scc/traceable.h>
#include "scc/utilities.h" #include <scc/tick2time.h>
#include "tlm/scc/scv/tlm_rec_initiator_socket.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> #include <cci_configuration>
#endif
#include <tlm> #include <tlm>
#include <tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_core_ifs.h>
#include <tlm_utils/tlm_quantumkeeper.h> #include <tlm_utils/tlm_quantumkeeper.h>
#include <util/range_lut.h> #include <util/range_lut.h>
#include <memory>
namespace sysc { namespace sysc {
@ -63,8 +68,6 @@ class core_complex : public sc_core::sc_module, public scc::traceable {
public: public:
tlm::scc::initiator_mixin<tlm::scc::scv::tlm_rec_initiator_socket<32>> initiator{"intor"}; 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> rst_i{"rst_i"};
sc_core::sc_in<bool> global_irq_i{"global_irq_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}; 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; 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", ""}; cci::cci_param<std::string> elf_file{"elf_file", ""};
@ -93,7 +99,47 @@ public:
cci::cci_param<uint32_t> mhartid{"mhartid", 0}; 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(); ~core_complex();
@ -119,11 +165,12 @@ public:
bool disass_output(uint64_t pc, const std::string instr); bool disass_output(uint64_t pc, const std::string instr);
void set_clock_period(sc_core::sc_time period);
protected: protected:
void before_end_of_elaboration() override; void before_end_of_elaboration() override;
void start_of_simulation() override; void start_of_simulation() override;
void forward();
void run(); void run();
void clk_cb();
void rst_cb(); void rst_cb();
void sw_irq_cb(); void sw_irq_cb();
void timer_irq_cb(); void timer_irq_cb();
@ -132,12 +179,14 @@ protected:
util::range_lut<tlm_dmi_ext> read_lut, write_lut; util::range_lut<tlm_dmi_ext> read_lut, write_lut;
tlm_utils::tlm_quantumkeeper quantum_keeper; tlm_utils::tlm_quantumkeeper quantum_keeper;
std::vector<uint8_t> write_buf; std::vector<uint8_t> write_buf;
std::unique_ptr<core_wrapper> cpu; core_wrapper* cpu{nullptr};
sc_core::sc_time curr_clk; sc_core::sc_signal<sc_core::sc_time> curr_clk;
std::unique_ptr<core_trace> trc; core_trace* trc{nullptr};
std::unique_ptr<scc::tick2time> t2t;
private:
void init();
}; };
} /* namespace SiFive */ } /* namespace SiFive */
} /* namespace sysc */ } /* namespace sysc */
#endif /* _SYSC_SIFIVE_FE310_H_ */ #endif /* _SYSC_CORE_COMPLEX_H_ */

View File

@ -47,7 +47,7 @@ using tgc_b_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_b>;
#ifdef CORE_TGC_D #ifdef CORE_TGC_D
#include "iss/arch/riscv_hart_mu_p.h" #include "iss/arch/riscv_hart_mu_p.h"
#include "iss/arch/tgc_d.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 #endif
#ifdef WITH_LLVM #ifdef WITH_LLVM
#include <iss/llvm/jit_helper.h> #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") ("mem,m", po::value<std::string>(), "the memory input file")
("plugin,p", po::value<std::vector<std::string>>(), "plugin to activate") ("plugin,p", po::value<std::vector<std::string>>(), "plugin to activate")
("backend", po::value<std::string>()->default_value("interp"), "the memory input file") ("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 // clang-format on
auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run(); auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run();
try { try {
@ -123,18 +123,18 @@ int main(int argc, char *argv[]) {
iss::vm_ptr vm{nullptr}; iss::vm_ptr vm{nullptr};
iss::cpu_ptr cpu{nullptr}; iss::cpu_ptr cpu{nullptr};
std::string isa_opt(clim["isa"].as<std::string>()); std::string isa_opt(clim["isa"].as<std::string>());
if (isa_opt == "tgf_c") { if (isa_opt == "tgc_c") {
std::tie(cpu, vm) = std::tie(cpu, vm) =
iss::create_cpu<tgc_c_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>()); iss::create_cpu<tgc_c_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
} else } else
#ifdef CORE_TGC_B #ifdef CORE_TGC_B
if (isa_opt == "tgf_b") { if (isa_opt == "tgc_b") {
std::tie(cpu, vm) = std::tie(cpu, vm) =
iss::create_cpu<tgc_b_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>()); iss::create_cpu<tgc_b_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
} else } else
#endif #endif
#ifdef CORE_TGC_D #ifdef CORE_TGC_D
if (isa_opt == "tgf_d") { if (isa_opt == "tgc_d") {
std::tie(cpu, vm) = std::tie(cpu, vm) =
iss::create_cpu<tgc_d_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>()); iss::create_cpu<tgc_d_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
} else } else

View File

@ -66,6 +66,12 @@ if (type == STR(CN)) { std::tie(cpu, vm) = create_core<CN ## _plat_type>(backend
using namespace scv_tr; using namespace scv_tr;
#endif #endif
#ifndef CWR_SYSTEMC
#define GET_PROP_VALUE(P) P.get_value()
#else
#define GET_PROP_VALUE(P) P.getValue()
#endif
namespace sysc { namespace sysc {
namespace tgfs { namespace tgfs {
using namespace std; using namespace std;
@ -137,6 +143,7 @@ public:
} }
status read_csr(unsigned addr, reg_t &val) override { 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)){ if((addr==arch::time || addr==arch::timeh) && owner->mtime_o.get_interface(0)){
uint64_t time_val; uint64_t time_val;
bool ret = owner->mtime_o->nb_peek(time_val); bool ret = owner->mtime_o->nb_peek(time_val);
@ -147,6 +154,17 @@ public:
val = static_cast<reg_t>(time_val >> 32); val = static_cast<reg_t>(time_val >> 32);
} }
return ret?Ok:Err; 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 { } else {
return PLAT::read_csr(addr, val); return PLAT::read_csr(addr, val);
} }
@ -297,13 +315,19 @@ struct core_trace {
scv_tr_handle tr_handle; 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) : sc_module(name)
, read_lut(tlm_dmi_ext()) , read_lut(tlm_dmi_ext())
, write_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 { initiator.register_invalidate_direct_mem_ptr([=](uint64_t start, uint64_t end) -> void {
auto lut_entry = read_lut.getEntry(start); 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) { if (lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && end <= lut_entry.get_end_address() + 1) {
@ -316,8 +340,6 @@ core_complex::core_complex(sc_module_name name)
}); });
SC_THREAD(run); SC_THREAD(run);
SC_METHOD(clk_cb);
sensitive << clk_i;
SC_METHOD(rst_cb); SC_METHOD(rst_cb);
sensitive << rst_i; sensitive << rst_i;
SC_METHOD(sw_irq_cb); SC_METHOD(sw_irq_cb);
@ -327,29 +349,48 @@ core_complex::core_complex(sc_module_name name)
SC_METHOD(global_irq_cb); SC_METHOD(global_irq_cb);
sensitive << global_irq_i; sensitive << global_irq_i;
trc->m_db=scv_tr_db::get_default_db(); 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::trace(sc_trace_file *trf) const {}
void core_complex::before_end_of_elaboration() { void core_complex::before_end_of_elaboration() {
SCCDEBUG(SCMOD)<<"instantiating iss::arch::tgf with "<<backend.get_value()<<" backend"; SCCDEBUG(SCMOD)<<"instantiating iss::arch::tgf with "<<GET_PROP_VALUE(backend)<<" backend";
cpu = scc::make_unique<core_wrapper>(this); // 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()); 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); 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() { void core_complex::start_of_simulation() {
quantum_keeper.reset(); quantum_keeper.reset();
if (elf_file.get_value().size() > 0) { if (GET_PROP_VALUE(elf_file).size() > 0) {
istringstream is(elf_file.get_value()); istringstream is(GET_PROP_VALUE(elf_file));
string s; string s;
while (getline(is, s, ',')) { while (getline(is, s, ',')) {
std::pair<uint64_t, bool> start_addr = cpu->load_file(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) if (reset_address.is_default_value() && start_addr.second == true)
reset_address.set_value(start_addr.first); 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) { if (trc->m_db != nullptr && trc->stream_handle == nullptr) {
@ -371,9 +412,18 @@ bool core_complex::disass_output(uint64_t pc, const std::string instr_str) {
return true; return true;
} }
void core_complex::clk_cb() { void core_complex::forward() {
curr_clk = clk_i.read(); #ifndef CWR_SYSTEMC
if (curr_clk == SC_ZERO_TIME) cpu->set_interrupt_execution(true); 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() { void core_complex::rst_cb() {
@ -390,11 +440,11 @@ void core_complex::run() {
wait(SC_ZERO_TIME); // separate from elaboration phase wait(SC_ZERO_TIME); // separate from elaboration phase
do { do {
if (rst_i.read()) { if (rst_i.read()) {
cpu->reset(reset_address.get_value()); cpu->reset(GET_PROP_VALUE(reset_address));
wait(rst_i.negedge_event()); wait(rst_i.negedge_event());
} }
while (clk_i.read() == SC_ZERO_TIME) { while (curr_clk.read() == SC_ZERO_TIME) {
wait(clk_i.value_changed_event()); wait(curr_clk.value_changed_event());
} }
cpu->set_interrupt_execution(false); cpu->set_interrupt_execution(false);
cpu->start(); cpu->start();
@ -531,6 +581,5 @@ bool core_complex::write_mem_dbg(uint64_t addr, unsigned length, const uint8_t *
return initiator->transport_dbg(gp) == length; return initiator->transport_dbg(gp) == length;
} }
} }
} /* namespace SiFive */ } /* namespace SiFive */
} /* namespace sysc */ } /* namespace sysc */