Merge branch 'develop' of

https://git.minres.com/DBT-RISE/DBT-RISE-TGC.git into develop
This commit is contained in:
2023-08-30 10:05:42 +02:00
23 changed files with 535 additions and 608 deletions

View File

@@ -666,7 +666,7 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const acce
fault_data=addr;
return iss::Err;
}
auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr});
phys_addr_t phys_addr{access, space, addr};
auto res = iss::Err;
if(access != access_type::FETCH && memfn_range.size()){
auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a){
@@ -759,7 +759,7 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
fault_data=addr;
return iss::Err;
}
auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr});
phys_addr_t phys_addr{access, space, addr};
auto res = iss::Err;
if(access != access_type::FETCH && memfn_range.size()){
auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a){
@@ -784,9 +784,8 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
return iss::Err;
}
phys_addr_t paddr = BASE::v2p(iss::addr_t{access, type, space, addr});
if ((paddr.val + length) > mem.size()) return iss::Err;
switch (paddr.val) {
if ((addr + length) > mem.size()) return iss::Err;
switch (addr) {
case 0x10013000: // UART0 base, TXFIFO reg
case 0x10023000: // UART1 base, TXFIFO reg
uart_buf << (char)data[0];
@@ -798,16 +797,16 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
}
return iss::Ok;
case 0x10008000: { // HFROSC base, hfrosccfg reg
auto &p = mem(paddr.val / mem.page_size);
auto offs = paddr.val & mem.page_addr_mask;
auto &p = mem(addr / mem.page_size);
auto offs = addr & mem.page_addr_mask;
std::copy(data, data + length, p.data() + offs);
auto &x = *(p.data() + offs + 3);
if (x & 0x40) x |= 0x80; // hfroscrdy = 1 if hfroscen==1
return iss::Ok;
}
case 0x10008008: { // HFROSC base, pllcfg reg
auto &p = mem(paddr.val / mem.page_size);
auto offs = paddr.val & mem.page_addr_mask;
auto &p = mem(addr / mem.page_size);
auto offs = addr & mem.page_addr_mask;
std::copy(data, data + length, p.data() + offs);
auto &x = *(p.data() + offs + 3);
x |= 0x80; // set pll lock upon writing

View File

@@ -430,6 +430,7 @@ template <typename BASE>
riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp()
: state()
, instr_if(*this) {
this->_has_mmu = true;
// reset values
csr[misa] = traits<BASE>::MISA_VAL;
csr[mvendorid] = 0x669;
@@ -632,9 +633,7 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
return res;
}
}
auto res = type==iss::address_type::PHYSICAL?
read_mem( BASE::v2p(phys_addr_t{access, space, addr}), length, data):
read_mem( BASE::v2p(iss::addr_t{access, type, space, addr}), length, data);
auto res = read_mem( BASE::v2p(iss::addr_t{access, type, space, addr}), length, data);
if (unlikely(res != iss::Ok)){
this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault
fault_data=addr;
@@ -719,6 +718,7 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
this->reg.trap_state = (1 << 31); // issue trap 0
return iss::Err;
}
phys_addr_t paddr = BASE::v2p(iss::addr_t{access, type, space, addr});
try {
if (unlikely((addr & ~PGMASK) != ((addr + length - 1) & ~PGMASK))) { // we may cross a page boundary
vm_info vm = hart_state_type::decode_vm_info(this->reg.PRIV, state.satp);
@@ -731,9 +731,7 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
return res;
}
}
auto res = type==iss::address_type::PHYSICAL?
write_mem(phys_addr_t{access, space, addr}, length, data):
write_mem(BASE::v2p(iss::addr_t{access, type, space, addr}), length, data);
auto res = write_mem(paddr, length, data);
if (unlikely(res != iss::Ok)) {
this->reg.trap_state = (1UL << 31) | (7UL << 16); // issue trap 7 (Store/AMO access fault)
fault_data=addr;
@@ -745,7 +743,6 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
return iss::Err;
}
phys_addr_t paddr = BASE::v2p(iss::addr_t{access, type, space, addr});
if ((paddr.val + length) > mem.size()) return iss::Err;
switch (paddr.val) {
case 0x10013000: // UART0 base, TXFIFO reg

View File

@@ -834,7 +834,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
fault_data=addr;
return iss::Err;
}
auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr});
phys_addr_t phys_addr{access, space, addr};
auto res = iss::Err;
if(!is_fetch(access) && memfn_range.size()){
auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a){
@@ -935,7 +935,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
fault_data=addr;
return iss::Err;
}
auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr});
phys_addr_t phys_addr{access, space, addr};
auto res = iss::Err;
if(!is_fetch(access) && memfn_range.size()){
auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a){
@@ -960,30 +960,29 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
return iss::Err;
}
phys_addr_t paddr = BASE::v2p(iss::addr_t{access, type, space, addr});
if ((paddr.val + length) > mem.size()) return iss::Err;
switch (paddr.val) {
if ((addr + length) > mem.size()) return iss::Err;
switch (addr) {
case 0x10013000: // UART0 base, TXFIFO reg
case 0x10023000: // UART1 base, TXFIFO reg
uart_buf << (char)data[0];
if (((char)data[0]) == '\n' || data[0] == 0) {
// LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send
// LOG(INFO)<<"UART"<<((addr>>16)&0x3)<<" send
// '"<<uart_buf.str()<<"'";
std::cout << uart_buf.str();
uart_buf.str("");
}
return iss::Ok;
case 0x10008000: { // HFROSC base, hfrosccfg reg
auto &p = mem(paddr.val / mem.page_size);
auto offs = paddr.val & mem.page_addr_mask;
auto &p = mem(addr / mem.page_size);
auto offs = addr & mem.page_addr_mask;
std::copy(data, data + length, p.data() + offs);
auto &x = *(p.data() + offs + 3);
if (x & 0x40) x |= 0x80; // hfroscrdy = 1 if hfroscen==1
return iss::Ok;
}
case 0x10008008: { // HFROSC base, pllcfg reg
auto &p = mem(paddr.val / mem.page_size);
auto offs = paddr.val & mem.page_addr_mask;
auto &p = mem(addr / mem.page_size);
auto offs = addr & mem.page_addr_mask;
std::copy(data, data + length, p.data() + offs);
auto &x = *(p.data() + offs + 3);
x |= 0x80; // set pll lock upon writing

View File

@@ -80,9 +80,17 @@ class core_factory {
public:
static core_factory & instance() { static core_factory bf; return bf; }
bool register_creator(const std::string &, create_fn const&);
bool register_creator(const std::string & className, create_fn const& fn) {
registry[className] = fn;
return true;
}
base_t create(const std::string &, unsigned gdb_port=0, void* init_data=nullptr) const;
base_t create(std::string const& className, unsigned gdb_port=0, void* init_data=nullptr) const {
registry_t::const_iterator regEntry = registry.find(className);
if (regEntry != registry.end())
return regEntry->second(gdb_port, init_data);
return {nullptr, nullptr};
}
std::vector<std::string> get_names() {
std::vector<std::string> keys{registry.size()};
@@ -93,18 +101,6 @@ public:
}
};
inline bool core_factory::register_creator(const std::string & className, create_fn const& fn) {
registry[className] = fn;
return true;
}
inline core_factory::base_t core_factory::create(const std::string &className, unsigned gdb_port, void* data) const {
registry_t::const_iterator regEntry = registry.find(className);
if (regEntry != registry.end())
return regEntry->second(gdb_port, data);
return {nullptr, nullptr};
}
}
#endif /* _ISS_FACTORY_H_ */

View File

@@ -37,7 +37,6 @@
#include <iss/vm_plugin.h>
#include "iss/instrumentation_if.h"
#include <json/json.h>
#include <string>
#include <fstream>

View File

@@ -39,7 +39,7 @@
#include <boost/program_options.hpp>
#include "iss/arch/tgc_mapper.h"
#ifdef WITH_LLVM
#include <iss/llvm/jit_helper.h>
#include <iss/llvm/jit_init.h>
#endif
#include <iss/log_categories.h>
#include "iss/plugin/cycle_estimate.h"

View File

@@ -37,7 +37,7 @@
#include <iss/debugger/target_adapter_if.h>
#include <iss/iss.h>
#include <iss/vm_types.h>
#include <iss/factory.h>
#include "iss_factory.h"
#ifndef WIN32
#include <iss/plugin/loader.h>
#endif
@@ -128,7 +128,9 @@ public:
void reset(uint64_t addr){vm->reset(addr);}
inline void start(){vm->start();}
inline std::pair<uint64_t, bool> load_file(std::string const& name){ return cpu->load_file(name);};
inline std::pair<uint64_t, bool> load_file(std::string const& name){
iss::arch_if* cc = cpu->get_arch_if();
return cc->load_file(name);};
std::function<unsigned(void)> get_mode;
std::function<uint64_t(void)> get_state;
@@ -137,7 +139,7 @@ public:
std::function<void(short, bool)> local_irq;
void create_cpu(std::string const& type, std::string const& backend, unsigned gdb_port, uint32_t hart_id){
auto & f = iss::core_factory::instance();
auto & f = sysc::iss_factory::instance();
if(type.size()==0 || type == "?") {
std::cout<<"Available cores: "<<util::join(f.get_names(), ", ")<<std::endl;
sc_core::sc_stop();
@@ -148,7 +150,7 @@ public:
if(base_isa=="tgc5d" || base_isa=="tgc5e") {
std::tie(cpu, vm) = f.create(type + "|mu_p_clic_pmp|" + backend, gdb_port);
} else {
std::tie(cpu, vm) = f.create(type + "|m_p|" + backend, gdb_port);
std::tie(cpu, vm) = f.create(type + "|m_p|" + backend, gdb_port, owner);
}
}
if(!cpu ){
@@ -157,12 +159,13 @@ public:
if(!vm ){
SCCFATAL() << "Could not create vm for isa " << type << " and backend " <<backend;
}
reinterpret_cast<sc_core_adapter_if&>(*cpu).set_mhartid(hart_id);
get_mode = [this]() { return reinterpret_cast<sc_core_adapter_if&>(*cpu).get_mode(); };
get_state = [this]() { return reinterpret_cast<sc_core_adapter_if&>(*cpu).get_state(); };
get_interrupt_execution = [this]() { return reinterpret_cast<sc_core_adapter_if&>(*cpu).get_interrupt_execution(); };
set_interrupt_execution = [this](bool b) { return reinterpret_cast<sc_core_adapter_if&>(*cpu).set_interrupt_execution(b); };
local_irq = [this](short s, bool b) { return reinterpret_cast<sc_core_adapter_if&>(*cpu).local_irq(s, b); };
auto* sc_cpu_if = reinterpret_cast<sc_core_adapter_if*>(cpu.get());
sc_cpu_if->set_mhartid(hart_id);
get_mode = [sc_cpu_if]() { return sc_cpu_if->get_mode(); };
get_state = [sc_cpu_if]() { return sc_cpu_if->get_state(); };
get_interrupt_execution = [sc_cpu_if]() { return sc_cpu_if->get_interrupt_execution(); };
set_interrupt_execution = [sc_cpu_if](bool b) { return sc_cpu_if->set_interrupt_execution(b); };
local_irq = [sc_cpu_if](short s, bool b) { return sc_cpu_if->local_irq(s, b); };
auto *srv = debugger::server<debugger::gdb_session>::get();
if (srv) tgt_adapter = srv->get_target();
@@ -176,7 +179,7 @@ public:
core_complex * const owner;
vm_ptr vm{nullptr};
cpu_ptr cpu{nullptr};
sc_cpu_ptr cpu{nullptr};
iss::debugger::target_adapter_if *tgt_adapter{nullptr};
};

88
src/sysc/iss_factory.h Normal file
View File

@@ -0,0 +1,88 @@
/*******************************************************************************
* Copyright (C) 2021 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.
*
*******************************************************************************/
#ifndef _ISS_FACTORY_H_
#define _ISS_FACTORY_H_
#include <iss/iss.h>
#include "sc_core_adapter_if.h"
#include <memory>
#include <unordered_map>
#include <functional>
#include <string>
#include <algorithm>
#include <vector>
namespace sysc {
using sc_cpu_ptr = std::unique_ptr<sc_core_adapter_if>;
using vm_ptr= std::unique_ptr<iss::vm_if>;
class iss_factory {
public:
using base_t = std::tuple<sc_cpu_ptr, vm_ptr>;
using create_fn = std::function<base_t(unsigned, void*) >;
using registry_t = std::unordered_map<std::string, create_fn> ;
iss_factory() = default;
iss_factory(const iss_factory &) = delete;
iss_factory & operator=(const iss_factory &) = delete;
static iss_factory & instance() { static iss_factory bf; return bf; }
bool register_creator(const std::string & className, create_fn const& fn) {
registry[className] = fn;
return true;
}
base_t create(std::string const& className, unsigned gdb_port=0, void* init_data=nullptr) const {
registry_t::const_iterator regEntry = registry.find(className);
if (regEntry != registry.end())
return regEntry->second(gdb_port, init_data);
return {nullptr, nullptr};
}
std::vector<std::string> get_names() {
std::vector<std::string> keys{registry.size()};
std::transform(std::begin(registry), std::end(registry), std::begin(keys), [](std::pair<std::string, create_fn> const& p){
return p.first;
});
return keys;
}
private:
registry_t registry;
};
}
#endif /* _ISS_FACTORY_H_ */

View File

@@ -30,15 +30,17 @@
*
*******************************************************************************/
#include <iss/factory.h>
#include "iss_factory.h"
#include <iss/arch/tgc5c.h>
#include <iss/arch/riscv_hart_m_p.h>
#include <iss/arch/riscv_hart_mu_p.h>
#include "sc_core_adapter.h"
#include "core_complex.h"
#include <array>
namespace iss {
namespace interp {
using namespace sysc;
volatile std::array<bool, 2> tgc_init = {
core_factory::instance().register_creator("tgc5c|m_p|interp", [](unsigned gdb_port, void* data) -> std::tuple<cpu_ptr, vm_ptr>{
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
@@ -54,6 +56,7 @@ volatile std::array<bool, 2> tgc_init = {
}
#if defined(WITH_TCC)
namespace tcc {
using namespace sysc;
volatile std::array<bool, 2> tgc_init = {
core_factory::instance().register_creator("tgc5c|m_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple<cpu_ptr, vm_ptr>{
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);

View File

@@ -16,6 +16,7 @@
#include <iss/vm_types.h>
#include <iostream>
namespace sysc {
template<typename PLAT>
class sc_core_adapter : public PLAT, public sc_core_adapter_if {
public:
@@ -25,6 +26,8 @@ public:
sc_core_adapter(sysc::tgfs::core_complex *owner)
: owner(owner) { }
iss::arch_if* get_arch_if() override { return this;}
void set_mhartid(unsigned id) override { PLAT::set_mhartid(id); }
uint32_t get_mode() override { return this->reg.PRIV; }
@@ -144,6 +147,5 @@ private:
sysc::tgfs::core_complex *const owner;
sc_core::sc_event wfi_evt;
};
}
#endif /* _SYSC_SC_CORE_ADAPTER_H_ */

View File

@@ -16,7 +16,9 @@
#include <iss/vm_types.h>
#include <iostream>
namespace sysc {
struct sc_core_adapter_if {
virtual iss::arch_if* get_arch_if() = 0;
virtual void set_mhartid(unsigned) = 0;
virtual uint32_t get_mode() = 0;
virtual uint64_t get_state() = 0;
@@ -25,6 +27,5 @@ struct sc_core_adapter_if {
virtual void local_irq(short id, bool value) = 0;
virtual ~sc_core_adapter_if() = default;
};
}
#endif /* _SYSC_SC_CORE_ADAPTER_IF_H_ */