/******************************************************************************* * Copyright (C) 2017, 2018 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. * *******************************************************************************/ // clang-format off #include #include #include #include #include #include #include "iss_factory.h" #ifndef WIN32 #include #endif #include "sc_core_adapter_if.h" #include #include #include #include #include #include #include #include #include // clang-format on #define STR(X) #X #define CREATE_CORE(CN) \ if(type == STR(CN)) { \ std::tie(cpu, vm) = create_core(backend, gdb_port, hart_id); \ } else #ifdef HAS_SCV #include #else #include 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; using namespace iss; using namespace logging; using namespace sc_core; namespace { iss::debugger::encoder_decoder encdec; std::array lvl = {{'U', 'S', 'H', 'M'}}; } // namespace int cmd_sysc(int argc, char* argv[], debugger::out_func of, debugger::data_func df, debugger::target_adapter_if* tgt_adapter) { if(argc > 1) { if(strcasecmp(argv[1], "print_time") == 0) { std::string t = sc_time_stamp().to_string(); of(t.c_str()); std::array buf; encdec.enc_string(t.c_str(), buf.data(), 63); df(buf.data()); return Ok; } else if(strcasecmp(argv[1], "break") == 0) { sc_time t; if(argc == 4) { t = scc::parse_from_string(argv[2], argv[3]); } else if(argc == 3) { t = scc::parse_from_string(argv[2]); } else return Err; // no check needed as it is only called if debug server is active tgt_adapter->add_break_condition([t]() -> unsigned { SCCTRACE() << "Checking condition at " << sc_time_stamp(); return sc_time_stamp() >= t ? std::numeric_limits::max() : 0; }); return Ok; } return Err; } return Err; } using cpu_ptr = std::unique_ptr; using vm_ptr = std::unique_ptr; class core_wrapper { public: core_wrapper(core_complex* owner) : owner(owner) {} void reset(uint64_t addr) { vm->reset(addr); } inline void start(bool dump = false) { vm->start(std::numeric_limits::max(), dump); } inline std::pair load_file(std::string const& name) { iss::arch_if* cc = cpu->get_arch_if(); return cc->load_file(name); }; std::function get_mode; std::function get_state; std::function get_interrupt_execution; std::function set_interrupt_execution; std::function local_irq; void create_cpu(std::string const& type, std::string const& backend, unsigned gdb_port, uint32_t hart_id) { 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(); } else if(type.find('|') != std::string::npos) { std::tie(cpu, vm) = f.create(type + "|" + backend); } else { auto base_isa = type.substr(0, 5); if(base_isa == "tgc5d" || base_isa == "tgc5e") { std::tie(cpu, vm) = f.create(type + "|mu_p_clic_pmp|" + backend, gdb_port, owner); } else { std::tie(cpu, vm) = f.create(type + "|m_p|" + backend, gdb_port, owner); } } if(!cpu) { SCCFATAL() << "Could not create cpu for isa " << type << " and backend " << backend; } if(!vm) { SCCFATAL() << "Could not create vm for isa " << type << " and backend " << backend; } auto* sc_cpu_if = reinterpret_cast(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::get(); if(srv) tgt_adapter = srv->get_target(); if(tgt_adapter) tgt_adapter->add_custom_command({"sysc", [this](int argc, char* argv[], debugger::out_func of, debugger::data_func df) -> int { return cmd_sysc(argc, argv, of, df, tgt_adapter); }, "SystemC sub-commands: break