Compare commits
4 Commits
8ff55d7b92
...
1672b01e62
Author | SHA1 | Date | |
---|---|---|---|
1672b01e62 | |||
00b0f101ac | |||
54f75f92ea | |||
0304aac9e5 |
19
contrib/README.md
Normal file
19
contrib/README.md
Normal file
@ -0,0 +1,19 @@
|
||||
# requires conan version 1.59
|
||||
# requires decent cmake version 3.23 for instance
|
||||
git clone --recursive -b develop https://git.minres.com/TGFS/TGC-ISS.git
|
||||
cd TGC-ISS/
|
||||
setenv COWAREHOME /scratch/rocco/workarea/tools/synopsys/T-2022.06-3
|
||||
setenv SNPSLMD_LICENSE_FILE 27001@lic02.arteris.com:5285@lic-node0:5285@lic03:5285@lic-node1
|
||||
source $COWAREHOME/SLS/linux/setup.csh pae
|
||||
setenv SNPS_ENABLE_MEM_ON_DEMAND_IN_GENERIC_MEM 1
|
||||
setenv PATH $COWAREHOME/common/bin/:${PATH}
|
||||
setenv LD_LIBRARY_PATH /scratch/rocco/workarea/tools/gcc-9.3.0-install/lib64/
|
||||
setenv CC /scratch/rocco/workarea/tools/synopsys/T-2022.06-3/SLS/linux/common/bin//gcc
|
||||
setenv CXX /scratch/rocco/workarea/tools/synopsys/T-2022.06-3/SLS/linux/common/bin//g++
|
||||
cmake -S . -B build/Debug-PA -DCMAKE_BUILD_TYPE=Debug -DUSE_CWR_SYSTEMC=ON -DBUILD_SHARED_LIBS=ON -DCODEGEN=OFF -DCMAKE_INSTALL_PREFIX=/scratch/rocco/partners/minres/TGC-ISS/install
|
||||
cd build/Debug-PA/
|
||||
make -j 16 install
|
||||
cd ../../dbt-rise-tgc/contrib
|
||||
setenv TGFS_INSTALL_ROOT /scratch/rocco/partners/minres/TGC-ISS/install/
|
||||
# import the TGC core itself
|
||||
pct tgc_import.tcl
|
BIN
contrib/hello.elf
Executable file
BIN
contrib/hello.elf
Executable file
Binary file not shown.
@ -6,13 +6,10 @@ proc getScriptDirectory {} {
|
||||
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 sysc::tgfs::core_complex
|
||||
set top_design_name core_complex
|
||||
set clocks clk_i
|
||||
set resets rst_i
|
||||
@ -38,13 +35,14 @@ foreach clock ${clocks} {
|
||||
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
|
||||
#::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_encap_build_script $block/sysc::tgfs::${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}
|
||||
::pct::create_instance SYSTEM_LIBRARY:${top_design_name} ${hardware} ${model_prefix}${top_design_name}${model_postfix} sysc::tgfs::${top_design_name} sysc::tgfs::${top_design_name}()
|
||||
::pct::set_bounds i_${top_design_name} 200 300 100 400
|
||||
|
||||
# export the result as component
|
||||
::pct::export_system_library ${top_design_name} ${top_design_name}.xml
|
||||
|
61
contrib/tgc_import_tb.tcl
Normal file
61
contrib/tgc_import_tb.tcl
Normal file
@ -0,0 +1,61 @@
|
||||
source tgc_import.tcl
|
||||
set hardware /HARDWARE/HW/HW
|
||||
set FW_name ${scriptDir}/hello.elf
|
||||
|
||||
puts "instantiate testbench elements"
|
||||
::paultra::add_hw_instance GenericIPlib:Memory_Generic -inst_name i_Memory_Generic
|
||||
::pct::set_bounds i_Memory_Generic 1000 300 100 100
|
||||
::paultra::add_hw_instance Bus:Bus -inst_name i_Bus
|
||||
::BLWizard::generateFramework i_Bus SBLTLM2FT * {} \
|
||||
{ common_configuration:BackBone:/advanced/num_resources_per_target:1 }
|
||||
::pct::set_bounds i_Bus 700 300 100 400
|
||||
::pct::create_connection C_init i_core_complex/initiator i_Bus/i_core_complex_initiator
|
||||
::pct::set_location_on_owner i_Bus/i_core_complex_initiator 10
|
||||
::pct::create_connection C_targ i_Bus/i_Memory_Generic_MEM i_Memory_Generic/MEM
|
||||
|
||||
puts "instantiating clock manager"
|
||||
set clock "Clk"
|
||||
::hw::create_hw_instance "" GenericIPlib:ClockGenerator ${clock}_clock
|
||||
::pct::set_bounds ${clock}_clock 100 100 100 100
|
||||
::pct::set_param_value $hardware/${clock}_clock {Constructor Arguments} period 1000
|
||||
::pct::set_param_value $hardware/${clock}_clock {Constructor Arguments} period_unit sc_core::SC_PS
|
||||
|
||||
puts "instantiating reset manager"
|
||||
set reset "Rst"
|
||||
::hw::create_hw_instance "" GenericIPlib:ResetGenerator ${reset}_reset
|
||||
::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} start_time 1000
|
||||
::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} start_time_unit sc_core::SC_PS
|
||||
::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} duration 10000
|
||||
::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} duration_unit sc_core::SC_PS
|
||||
# ::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} active_level true
|
||||
::pct::set_bounds ${reset}_reset 300 100 100 100
|
||||
|
||||
puts "connecting reset/clock"
|
||||
::pct::create_connection C_clk . Clk_clock/CLK i_core_complex/clk_i
|
||||
::pct::add_ports_to_connection C_clk i_Bus/Clk
|
||||
::pct::create_connection C_rst . Rst_reset/RST i_core_complex/rst_i
|
||||
::pct::add_ports_to_connection C_rst i_Bus/Rst
|
||||
|
||||
puts "setting parameters for DBT-RISE-TGC/Bus and memory components"
|
||||
::pct::set_param_value $hardware/i_core_complex {Scml Properties} elf_file ${FW_name}
|
||||
::pct::set_address i_core_complex/initiator:i_Memory_Generic/MEM 0x0
|
||||
|
||||
#::pct::set_main_configuration Default {{#include <scc/report.h>} {::scc::init_logging(::scc::LogConfig().logLevel(::scc::log::INFO).coloredOutput(false).logAsync(false));} {} {} {}}
|
||||
#::pct::set_main_configuration Debug {{#include <scc/report.h>} {::scc::init_logging(::scc::LogConfig().logLevel(::scc::log::DEBUG).coloredOutput(false).logAsync(false));} {} {} {}}
|
||||
#::pct::create_simulation_build_config Debug
|
||||
#::pct::set_simulation_build_project_setting Debug "Main Configuration" Default
|
||||
# add build settings and save design for next steps
|
||||
#::pct::set_simulation_build_project_setting "Debug" "Linker Flags" "-Wl,-z,muldefs $::env(VERILATOR_ROOT)/include/verilated.cpp $::env(VERILATOR_ROOT)/include/verilated_vcd_sc.cpp $::env(VERILATOR_ROOT)/include/verilated_vcd_c.cpp"
|
||||
#::pct::set_simulation_build_project_setting "Debug" "Include Paths" $::env(VERILATOR_ROOT)/include/
|
||||
|
||||
#::simulation::set_simulation_property Simulation [list run_for_duration:200ns results_dir:results/test_0 "TLM Port Trace:true"]
|
||||
#::simulation::run_simulation Simulation
|
||||
|
||||
#::pct::set_simulation_build_project_setting Debug {Export Type} {STATIC NETLIST}
|
||||
#::pct::set_simulation_build_project_setting Debug {Encapsulated Netlist} false
|
||||
#::pct::export_system "export"
|
||||
#::cd "export"
|
||||
#::scsh::open-project
|
||||
#::scsh::build
|
||||
#::scsh::elab sim
|
||||
::pct::save_system testbench.xml
|
@ -146,18 +146,17 @@ protected:
|
||||
|
||||
inline void process_spawn_blocks() {
|
||||
if(spawn_blocks.size()==0) return;
|
||||
std::swap(super::ex_info.branch_taken, super::ex_info.hw_branch_taken);
|
||||
for(auto it = std::begin(spawn_blocks); it!=std::end(spawn_blocks);)
|
||||
if(*it){
|
||||
(*it)();
|
||||
++it;
|
||||
} else
|
||||
spawn_blocks.erase(it);
|
||||
std::swap(super::ex_info.branch_taken, super::ex_info.hw_branch_taken);
|
||||
}
|
||||
<%functions.each{ it.eachLine { %>
|
||||
${it}<%}%>
|
||||
<%}%>
|
||||
|
||||
private:
|
||||
/****************************************************************************
|
||||
* start opcode definitions
|
||||
@ -263,6 +262,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
(instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
||||
auto inst_id = decode_inst_id(instr);
|
||||
// pre execution stuff
|
||||
this->core.last_branch = 0;
|
||||
if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast<unsigned>(inst_id));
|
||||
switch(inst_id){<%instructions.eachWithIndex{instr, idx -> %>
|
||||
case arch::traits<ARCH>::opcode_e::${instr.name}: {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2021 MINRES Technologies GmbH
|
||||
* Copyright (C) 2019 - 2023 MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -316,7 +316,9 @@ protected:
|
||||
|
||||
uint64_t get_total_cycles() override { return arch.icount + arch.cycle_offset; }
|
||||
|
||||
void set_curr_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; };
|
||||
void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; };
|
||||
|
||||
bool is_branch_taken() override { return arch.last_branch; };
|
||||
|
||||
riscv_hart_m_p<BASE, FEAT> &arch;
|
||||
};
|
||||
@ -420,6 +422,15 @@ protected:
|
||||
feature_config cfg;
|
||||
unsigned mcause_max_irq{(FEAT&features_e::FEAT_CLIC)?4096:16};
|
||||
inline bool debug_mode_active() {return this->reg.PRIV&0x4;}
|
||||
std::pair<std::function<mem_read_f>, std::function<mem_write_f>>
|
||||
replace_mem_access(std::function<mem_read_f> rd, std::function<mem_write_f> wr){
|
||||
std::pair<std::function<mem_read_f>, std::function<mem_write_f>> ret{hart_mem_rd_delegate, hart_mem_wr_delegate};
|
||||
hart_mem_rd_delegate = rd;
|
||||
hart_mem_wr_delegate = wr;
|
||||
return ret;
|
||||
}
|
||||
std::function<mem_read_f> hart_mem_rd_delegate;
|
||||
std::function<mem_write_f> hart_mem_wr_delegate;
|
||||
};
|
||||
|
||||
template <typename BASE, features_e FEAT>
|
||||
@ -541,6 +552,12 @@ riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p(feature_config cfg)
|
||||
csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr;
|
||||
csr_rd_cb[dcsr] = &this_class::read_dcsr_reg;
|
||||
}
|
||||
hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status {
|
||||
return this->read_mem(a, l, d);
|
||||
};
|
||||
hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status {
|
||||
return this->write_mem(a, l, d);
|
||||
};
|
||||
}
|
||||
|
||||
template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m_p<BASE, FEAT>::load_file(std::string name, int type) {
|
||||
@ -661,9 +678,9 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const acce
|
||||
auto idx = std::distance(std::begin(memfn_range), it);
|
||||
res = memfn_read[idx](phys_addr, length, data);
|
||||
} else
|
||||
res = read_mem( phys_addr, length, data);
|
||||
res = hart_mem_rd_delegate( phys_addr, length, data);
|
||||
} else {
|
||||
res = read_mem( phys_addr, length, data);
|
||||
res = hart_mem_rd_delegate( phys_addr, length, data);
|
||||
}
|
||||
if (unlikely(res != iss::Ok)){
|
||||
this->trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2017, 2018, 2021 MINRES Technologies GmbH
|
||||
* Copyright (C) 2017 - 2023 MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -340,7 +340,9 @@ protected:
|
||||
|
||||
uint64_t get_total_cycles() override { return arch.icount + arch.cycle_offset; }
|
||||
|
||||
virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; };
|
||||
void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; };
|
||||
|
||||
bool is_branch_taken() override { return arch.last_branch; };
|
||||
|
||||
riscv_hart_msu_vp<BASE> &arch;
|
||||
};
|
||||
@ -843,7 +845,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_reg(unsigned
|
||||
return iss::Ok;
|
||||
}
|
||||
|
||||
template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_cycle(unsigned addr, reg_t &val) {
|
||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_cycle(unsigned addr, reg_t &val) {
|
||||
auto cycle_val = this->icount + cycle_offset;
|
||||
if (addr == mcycle) {
|
||||
val = static_cast<reg_t>(cycle_val);
|
||||
@ -854,7 +856,7 @@ template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_cycle(unsigned a
|
||||
return iss::Ok;
|
||||
}
|
||||
|
||||
template <typename BASE> iss::status riscv_hart_m_p<BASE>::write_cycle(unsigned addr, reg_t val) {
|
||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_cycle(unsigned addr, reg_t val) {
|
||||
if (sizeof(typename traits<BASE>::reg_t) != 4) {
|
||||
if (addr == mcycleh)
|
||||
return iss::Err;
|
||||
@ -870,7 +872,7 @@ template <typename BASE> iss::status riscv_hart_m_p<BASE>::write_cycle(unsigned
|
||||
return iss::Ok;
|
||||
}
|
||||
|
||||
template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_instret(unsigned addr, reg_t &val) {
|
||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_instret(unsigned addr, reg_t &val) {
|
||||
if ((addr&0xff) == (minstret&0xff)) {
|
||||
val = static_cast<reg_t>(this->reg.instret);
|
||||
} else if ((addr&0xff) == (minstreth&0xff)) {
|
||||
@ -880,7 +882,7 @@ template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_instret(unsigned
|
||||
return iss::Ok;
|
||||
}
|
||||
|
||||
template <typename BASE> iss::status riscv_hart_m_p<BASE>::write_instret(unsigned addr, reg_t val) {
|
||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_instret(unsigned addr, reg_t val) {
|
||||
if (sizeof(typename traits<BASE>::reg_t) != 4) {
|
||||
if ((addr&0xff) == (minstreth&0xff))
|
||||
return iss::Err;
|
||||
@ -896,7 +898,7 @@ template <typename BASE> iss::status riscv_hart_m_p<BASE>::write_instret(unsigne
|
||||
return iss::Ok;
|
||||
}
|
||||
|
||||
template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_time(unsigned addr, reg_t &val) {
|
||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_time(unsigned addr, reg_t &val) {
|
||||
uint64_t time_val = this->icount / (100000000 / 32768 - 1); //-> ~3052;
|
||||
if (addr == time) {
|
||||
val = static_cast<reg_t>(time_val);
|
||||
@ -907,7 +909,7 @@ template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_time(unsigned ad
|
||||
return iss::Ok;
|
||||
}
|
||||
|
||||
template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_tvec(unsigned addr, reg_t &val) {
|
||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_tvec(unsigned addr, reg_t &val) {
|
||||
val = csr[addr] & ~2;
|
||||
return iss::Ok;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2021 MINRES Technologies GmbH
|
||||
* Copyright (C) 2017 - 2023 MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -340,7 +340,9 @@ protected:
|
||||
|
||||
uint64_t get_total_cycles() override { return arch.icount + arch.cycle_offset; }
|
||||
|
||||
void set_curr_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; };
|
||||
void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; };
|
||||
|
||||
bool is_branch_taken() override { return arch.last_branch; };
|
||||
|
||||
riscv_hart_mu_p<BASE, FEAT> &arch;
|
||||
};
|
||||
@ -447,6 +449,16 @@ protected:
|
||||
feature_config cfg;
|
||||
unsigned mcause_max_irq{(FEAT&features_e::FEAT_CLIC)?4096:16};
|
||||
inline bool debug_mode_active() {return this->reg.PRIV&0x4;}
|
||||
|
||||
std::pair<std::function<mem_read_f>, std::function<mem_write_f>>
|
||||
replace_mem_access(std::function<mem_read_f> rd, std::function<mem_write_f> wr){
|
||||
std::pair<std::function<mem_read_f>, std::function<mem_write_f>> ret{hart_mem_rd_delegate, hart_mem_wr_delegate};
|
||||
hart_mem_rd_delegate = rd;
|
||||
hart_mem_wr_delegate = wr;
|
||||
return ret;
|
||||
}
|
||||
std::function<mem_read_f> hart_mem_rd_delegate;
|
||||
std::function<mem_write_f> hart_mem_wr_delegate;
|
||||
};
|
||||
|
||||
template <typename BASE, features_e FEAT>
|
||||
@ -610,6 +622,12 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p(feature_config cfg)
|
||||
csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr;
|
||||
csr_rd_cb[dcsr] = &this_class::read_dcsr_reg;
|
||||
}
|
||||
hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status {
|
||||
return this->read_mem(a, l, d);
|
||||
};
|
||||
hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status {
|
||||
return this->write_mem(a, l, d);
|
||||
};
|
||||
}
|
||||
|
||||
template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_mu_p<BASE, FEAT>::load_file(std::string name, int type) {
|
||||
@ -827,9 +845,9 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
|
||||
auto idx = std::distance(std::begin(memfn_range), it);
|
||||
res = memfn_read[idx](phys_addr, length, data);
|
||||
} else
|
||||
res = read_mem( phys_addr, length, data);
|
||||
res = hart_mem_rd_delegate( phys_addr, length, data);
|
||||
} else {
|
||||
res = read_mem( phys_addr, length, data);
|
||||
res = hart_mem_rd_delegate( phys_addr, length, data);
|
||||
}
|
||||
if (unlikely(res != iss::Ok)){
|
||||
this->trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault
|
||||
@ -928,9 +946,9 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
|
||||
auto idx = std::distance(std::begin(memfn_range), it);
|
||||
res = memfn_write[idx]( phys_addr, length, data);
|
||||
} else
|
||||
res = write_mem( phys_addr, length, data);
|
||||
res = hart_mem_wr_delegate( phys_addr, length, data);
|
||||
} else {
|
||||
res = write_mem( phys_addr, length, data);
|
||||
res = hart_mem_wr_delegate( phys_addr, length, data);
|
||||
}
|
||||
if (unlikely(res != iss::Ok)) {
|
||||
this->trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault)
|
||||
|
172
src/iss/arch/wt_cache.h
Normal file
172
src/iss/arch/wt_cache.h
Normal file
@ -0,0 +1,172 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2023 MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Contributors:
|
||||
* eyck@minres.com - initial implementation
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _RISCV_HART_M_P_WT_CACHE_H
|
||||
#define _RISCV_HART_M_P_WT_CACHE_H
|
||||
|
||||
#include <iss/vm_types.h>
|
||||
#include <util/ities.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
namespace iss {
|
||||
namespace arch {
|
||||
namespace cache {
|
||||
|
||||
enum class state { INVALID, VALID};
|
||||
struct line {
|
||||
uint64_t tag_addr{0};
|
||||
state st{state::INVALID};
|
||||
std::vector<uint8_t> data;
|
||||
line(unsigned line_sz): data(line_sz) {}
|
||||
};
|
||||
struct set {
|
||||
std::vector<line> ways;
|
||||
set(unsigned ways_count, line const& l): ways(ways_count, l) {}
|
||||
};
|
||||
struct cache {
|
||||
std::vector<set> sets;
|
||||
|
||||
cache(unsigned size, unsigned line_sz, unsigned ways) {
|
||||
line const ref_line{line_sz};
|
||||
set const ref_set{ways, ref_line};
|
||||
sets.resize(size/(ways*line_sz), ref_set);
|
||||
}
|
||||
};
|
||||
|
||||
struct wt_policy {
|
||||
bool is_cacheline_hit(cache& c );
|
||||
};
|
||||
}
|
||||
|
||||
// write thru, allocate on read, direct mapped or set-associative with round-robin replacement policy
|
||||
template <typename BASE> class wt_cache : public BASE {
|
||||
public:
|
||||
using base_class = BASE;
|
||||
using this_class = wt_cache<BASE>;
|
||||
using reg_t = typename BASE::reg_t;
|
||||
using mem_read_f = typename BASE::mem_read_f;
|
||||
using mem_write_f = typename BASE::mem_write_f;
|
||||
using phys_addr_t = typename BASE::phys_addr_t;
|
||||
|
||||
wt_cache();
|
||||
virtual ~wt_cache() = default;
|
||||
|
||||
unsigned size{4096};
|
||||
unsigned line_sz{32};
|
||||
unsigned ways{1};
|
||||
uint64_t io_address{0xf0000000};
|
||||
uint64_t io_addr_mask{0xf0000000};
|
||||
protected:
|
||||
iss::status read_cache(phys_addr_t addr, unsigned, uint8_t *const);
|
||||
iss::status write_cache(phys_addr_t addr, unsigned, uint8_t const *const);
|
||||
std::function<mem_read_f> cache_mem_rd_delegate;
|
||||
std::function<mem_write_f> cache_mem_wr_delegate;
|
||||
std::unique_ptr<cache::cache> dcache_ptr;
|
||||
std::unique_ptr<cache::cache> icache_ptr;
|
||||
size_t get_way_select() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename BASE>
|
||||
inline wt_cache<BASE>::wt_cache() {
|
||||
auto cb = base_class::replace_mem_access(
|
||||
[this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return read_cache(a, l,d);},
|
||||
[this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return write_cache(a, l,d);});
|
||||
cache_mem_rd_delegate = cb.first;
|
||||
cache_mem_wr_delegate = cb.second;
|
||||
}
|
||||
|
||||
template<typename BASE>
|
||||
iss::status iss::arch::wt_cache<BASE>::read_cache(phys_addr_t a, unsigned l, uint8_t* const d) {
|
||||
if(!icache_ptr) {
|
||||
icache_ptr.reset(new cache::cache(size, line_sz, ways));
|
||||
dcache_ptr.reset(new cache::cache(size, line_sz, ways));
|
||||
}
|
||||
if((a.val&io_addr_mask) != io_address) {
|
||||
auto set_addr=(a.val&(size-1))>>util::ilog2(line_sz*ways);
|
||||
auto tag_addr=a.val>>util::ilog2(line_sz);
|
||||
auto& set = (a.access==access_type::FETCH?icache_ptr:dcache_ptr)->sets[set_addr];
|
||||
for(auto& cl: set.ways) {
|
||||
if(cl.st==cache::state::VALID && cl.tag_addr==tag_addr) {
|
||||
auto start_addr = a.val&(line_sz-1);
|
||||
for(auto i = 0U; i<l; ++i)
|
||||
d[i] = cl.data[start_addr+i];
|
||||
return iss::Ok;
|
||||
}
|
||||
}
|
||||
auto& cl = set.ways[get_way_select()];
|
||||
phys_addr_t cl_addr{a};
|
||||
cl_addr.val=tag_addr<<util::ilog2(line_sz);
|
||||
cache_mem_rd_delegate(cl_addr, line_sz, cl.data.data());
|
||||
cl.tag_addr=tag_addr;
|
||||
cl.st=cache::state::VALID;
|
||||
auto start_addr = a.val&(line_sz-1);
|
||||
for(auto i = 0U; i<l; ++i)
|
||||
d[i] = cl.data[start_addr+i];
|
||||
return iss::Ok;
|
||||
} else
|
||||
return cache_mem_rd_delegate(a, l, d);
|
||||
}
|
||||
|
||||
template<typename BASE>
|
||||
iss::status iss::arch::wt_cache<BASE>::write_cache(phys_addr_t a, unsigned l, const uint8_t* const d) {
|
||||
if(!dcache_ptr)
|
||||
dcache_ptr.reset(new cache::cache(size, line_sz, ways));
|
||||
auto res = cache_mem_wr_delegate(a, l, d);
|
||||
if(res == iss::Ok && ((a.val&io_addr_mask) != io_address)) {
|
||||
auto set_addr=(a.val&(size-1))>>util::ilog2(line_sz*ways);
|
||||
auto tag_addr=a.val>>util::ilog2(line_sz);
|
||||
auto& set = dcache_ptr->sets[set_addr];
|
||||
for(auto& cl: set.ways) {
|
||||
if(cl.st==cache::state::VALID && cl.tag_addr==tag_addr) {
|
||||
auto start_addr = a.val&(line_sz-1);
|
||||
for(auto i = 0U; i<l; ++i)
|
||||
cl.data[start_addr+1] = d[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace arch
|
||||
} // namespace iss
|
||||
|
||||
#endif /* _RISCV_HART_M_P_H */
|
@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2017, MINRES Technologies GmbH
|
||||
* Copyright (C) 2017 - 2023, MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -107,12 +107,12 @@ bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if&
|
||||
|
||||
}
|
||||
|
||||
void iss::plugin::cycle_estimate::callback(instr_info_t instr_info, exec_info const& exc_info) {
|
||||
void iss::plugin::cycle_estimate::callback(instr_info_t instr_info) {
|
||||
assert(instr_if && "No instrumentation interface available but callback executed");
|
||||
auto entry = delays[instr_info.instr_id];
|
||||
bool taken = exc_info.branch_taken;
|
||||
if (exc_info.branch_taken && (entry.taken > 1))
|
||||
instr_if->set_curr_instr_cycles(entry.taken);
|
||||
bool taken = instr_if->is_branch_taken();
|
||||
if (taken && (entry.taken > 1))
|
||||
instr_if->update_last_instr_cycles(entry.taken);
|
||||
else if (entry.not_taken > 1)
|
||||
instr_if->set_curr_instr_cycles(entry.not_taken);
|
||||
instr_if->update_last_instr_cycles(entry.not_taken);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2017, 2018, MINRES Technologies GmbH
|
||||
* Copyright (C) 2017 - 2023, MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -78,7 +78,7 @@ public:
|
||||
|
||||
sync_type get_sync() override { return POST_SYNC; };
|
||||
|
||||
void callback(instr_info_t instr_info, exec_info const&) override;
|
||||
void callback(instr_info_t instr_info) override;
|
||||
|
||||
private:
|
||||
iss::instrumentation_if *instr_if;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2017, MINRES Technologies GmbH
|
||||
* Copyright (C) 2017 - 2023 MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -90,6 +90,6 @@ bool iss::plugin::instruction_count::registration(const char* const version, vm_
|
||||
return true;
|
||||
}
|
||||
|
||||
void iss::plugin::instruction_count::callback(instr_info_t instr_info, exec_info const&) {
|
||||
void iss::plugin::instruction_count::callback(instr_info_t instr_info) {
|
||||
rep_counts[instr_info.instr_id]++;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2017, 2018, MINRES Technologies GmbH
|
||||
* Copyright (C) 2017 - 2023, MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -69,7 +69,7 @@ public:
|
||||
|
||||
sync_type get_sync() override { return POST_SYNC; };
|
||||
|
||||
void callback(instr_info_t, exec_info const&) override;
|
||||
void callback(instr_info_t) override;
|
||||
|
||||
private:
|
||||
Json::Value root;
|
||||
|
@ -1,3 +1,37 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2017 - 2023, MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Contributors:
|
||||
* alex.com - initial implementation
|
||||
******************************************************************************/
|
||||
|
||||
#include <iss/arch_if.h>
|
||||
#include <iss/plugin/pctrace.h>
|
||||
#include <util/logging.h>
|
||||
@ -152,22 +186,22 @@ bool pctrace::registration(const char *const version, vm_if& vm) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void pctrace::callback(instr_info_t iinfo, const exec_info& einfo) {
|
||||
void pctrace::callback(instr_info_t iinfo) {
|
||||
auto delay = 0;
|
||||
size_t id = iinfo.instr_id;
|
||||
auto entry = delays[id];
|
||||
auto instr = instr_if->get_instr_word();
|
||||
auto call = id==65 || id ==86 || ((id==2 || id==3) && bit_sub<7,5>(instr)!=0) ;//not taking care of tail calls (jalr with loading x6)
|
||||
bool taken = einfo.branch_taken;
|
||||
bool taken = instr_if->is_branch_taken();
|
||||
bool compressed = (instr&0x3)!=0x3;
|
||||
if (einfo.branch_taken) {
|
||||
if (taken) {
|
||||
delay = entry.taken;
|
||||
if(entry.taken > 1)
|
||||
instr_if->set_curr_instr_cycles(entry.taken);
|
||||
instr_if->update_last_instr_cycles(entry.taken);
|
||||
} else {
|
||||
delay = entry.not_taken;
|
||||
if (entry.not_taken > 1)
|
||||
instr_if->set_curr_instr_cycles(entry.not_taken);
|
||||
instr_if->update_last_instr_cycles(entry.not_taken);
|
||||
}
|
||||
#ifndef WITH_LZ4
|
||||
output<<std::hex <<"0x" << instr_if->get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <<"\n";
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2017, 2018, MINRES Technologies GmbH
|
||||
* Copyright (C) 2017 - 2023, MINRES Technologies GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -83,7 +83,7 @@ public:
|
||||
|
||||
sync_type get_sync() override { return POST_SYNC; };
|
||||
|
||||
void callback(instr_info_t, exec_info const&) override;
|
||||
void callback(instr_info_t) override;
|
||||
|
||||
private:
|
||||
iss::instrumentation_if *instr_if {nullptr};
|
||||
|
@ -140,16 +140,15 @@ protected:
|
||||
|
||||
inline void process_spawn_blocks() {
|
||||
if(spawn_blocks.size()==0) return;
|
||||
std::swap(super::ex_info.branch_taken, super::ex_info.hw_branch_taken);
|
||||
for(auto it = std::begin(spawn_blocks); it!=std::end(spawn_blocks);)
|
||||
if(*it){
|
||||
(*it)();
|
||||
++it;
|
||||
} else
|
||||
spawn_blocks.erase(it);
|
||||
std::swap(super::ex_info.branch_taken, super::ex_info.hw_branch_taken);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
/****************************************************************************
|
||||
* start opcode definitions
|
||||
@ -341,6 +340,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
(instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
||||
auto inst_id = decode_inst_id(instr);
|
||||
// pre execution stuff
|
||||
this->core.last_branch = 0;
|
||||
if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast<unsigned>(inst_id));
|
||||
switch(inst_id){
|
||||
case arch::traits<ARCH>::opcode_e::LUI: {
|
||||
@ -422,7 +422,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
*(X+rd) = *PC + 4;
|
||||
}
|
||||
*NEXT_PC = *PC + (int32_t)sext<21>(imm);
|
||||
super::ex_info.branch_taken=true;
|
||||
this->core.last_branch = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -457,7 +457,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
*(X+rd) = *PC + 4;
|
||||
}
|
||||
*NEXT_PC = new_pc & ~ 0x1;
|
||||
super::ex_info.branch_taken=true;
|
||||
this->core.last_branch = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -489,7 +489,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
}
|
||||
else {
|
||||
*NEXT_PC = *PC + (int16_t)sext<13>(imm);
|
||||
super::ex_info.branch_taken=true;
|
||||
this->core.last_branch = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -522,7 +522,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
}
|
||||
else {
|
||||
*NEXT_PC = *PC + (int16_t)sext<13>(imm);
|
||||
super::ex_info.branch_taken=true;
|
||||
this->core.last_branch = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -555,7 +555,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
}
|
||||
else {
|
||||
*NEXT_PC = *PC + (int16_t)sext<13>(imm);
|
||||
super::ex_info.branch_taken=true;
|
||||
this->core.last_branch = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -588,7 +588,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
}
|
||||
else {
|
||||
*NEXT_PC = *PC + (int16_t)sext<13>(imm);
|
||||
super::ex_info.branch_taken=true;
|
||||
this->core.last_branch = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -621,7 +621,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
}
|
||||
else {
|
||||
*NEXT_PC = *PC + (int16_t)sext<13>(imm);
|
||||
super::ex_info.branch_taken=true;
|
||||
this->core.last_branch = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -654,7 +654,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
}
|
||||
else {
|
||||
*NEXT_PC = *PC + (int16_t)sext<13>(imm);
|
||||
super::ex_info.branch_taken=true;
|
||||
this->core.last_branch = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2097,7 +2097,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
{
|
||||
*(X+1) = *PC + 2;
|
||||
*NEXT_PC = *PC + (int16_t)sext<12>(imm);
|
||||
super::ex_info.branch_taken=true;
|
||||
this->core.last_branch = 1;
|
||||
}
|
||||
TRAP_CJAL:break;
|
||||
}// @suppress("No break at end of case")
|
||||
@ -2342,7 +2342,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
// execute instruction
|
||||
{
|
||||
*NEXT_PC = *PC + (int16_t)sext<12>(imm);
|
||||
super::ex_info.branch_taken=true;
|
||||
this->core.last_branch = 1;
|
||||
}
|
||||
TRAP_CJ:break;
|
||||
}// @suppress("No break at end of case")
|
||||
@ -2363,7 +2363,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
{
|
||||
if(*(X+rs1 + 8) == 0) {
|
||||
*NEXT_PC = *PC + (int16_t)sext<9>(imm);
|
||||
super::ex_info.branch_taken=true;
|
||||
this->core.last_branch = 1;
|
||||
}
|
||||
}
|
||||
TRAP_CBEQZ:break;
|
||||
@ -2385,7 +2385,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
{
|
||||
if(*(X+rs1 + 8) != 0) {
|
||||
*NEXT_PC = *PC + (int16_t)sext<9>(imm);
|
||||
super::ex_info.branch_taken=true;
|
||||
this->core.last_branch = 1;
|
||||
}
|
||||
}
|
||||
TRAP_CBNEZ:break;
|
||||
@ -2485,7 +2485,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
{
|
||||
if(rs1 && rs1 < traits::RFS) {
|
||||
*NEXT_PC = *(X+rs1 % traits::RFS) & ~ 0x1;
|
||||
super::ex_info.branch_taken=true;
|
||||
this->core.last_branch = 1;
|
||||
}
|
||||
else {
|
||||
raise(0, 2);
|
||||
@ -2553,7 +2553,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
uint32_t new_pc = *(X+rs1);
|
||||
*(X+1) = *PC + 2;
|
||||
*NEXT_PC = new_pc & ~ 0x1;
|
||||
super::ex_info.branch_taken=true;
|
||||
this->core.last_branch = 1;
|
||||
}
|
||||
}
|
||||
TRAP_CJALR:break;
|
||||
|
Reference in New Issue
Block a user