/******************************************************************************* * Copyright (C) 2017-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 _SYSC_CORE_COMPLEX_H_ #define _SYSC_CORE_COMPLEX_H_ #include #include #include #include #include #ifdef CWR_SYSTEMC #include #define SOCKET_WIDTH 32 #else #include #define SOCKET_WIDTH scc::LT #endif #include #include #include #include namespace iss { class vm_plugin; } namespace sysc { class tlm_dmi_ext : public tlm::tlm_dmi { public: bool operator==(const tlm_dmi_ext &o) const { return this->get_granted_access() == o.get_granted_access() && this->get_start_address() == o.get_start_address() && this->get_end_address() == o.get_end_address(); } bool operator!=(const tlm_dmi_ext &o) const { return !operator==(o); } }; namespace tgfs { class core_wrapper; struct core_trace; class core_complex : public sc_core::sc_module, public scc::traceable { public: tlm::scc::initiator_mixin> ibus{"ibus"}; tlm::scc::initiator_mixin> dbus{"dbus"}; sc_core::sc_in rst_i{"rst_i"}; sc_core::sc_in ext_irq_i{"ext_irq_i"}; sc_core::sc_in timer_irq_i{"timer_irq_i"}; sc_core::sc_in sw_irq_i{"sw_irq_i"}; sc_core::sc_vector> local_irq_i{"local_irq_i", 16}; #ifndef CWR_SYSTEMC sc_core::sc_in clk_i{"clk_i"}; sc_core::sc_port, 1, sc_core::SC_ZERO_OR_MORE_BOUND> mtime_o{"mtime_o"}; cci::cci_param elf_file{"elf_file", ""}; cci::cci_param enable_disass{"enable_disass", false}; cci::cci_param reset_address{"reset_address", 0ULL}; cci::cci_param core_type{"core_type", "tgc_c"}; cci::cci_param backend{"backend", "interp"}; cci::cci_param gdb_server_port{"gdb_server_port", 0}; cci::cci_param dump_ir{"dump_ir", false}; cci::cci_param mhartid{"mhartid", 0}; cci::cci_param plugins{"plugins", ""}; core_complex(sc_core::sc_module_name const& name); #else sc_core::sc_in clk_i{"clk_i"}; sc_core::sc_in mtime_i{"mtime_i"}; scml_property elf_file{"elf_file", ""}; scml_property enable_disass{"enable_disass", false}; scml_property reset_address{"reset_address", 0ULL}; scml_property core_type{"core_type", "tgc_c"}; scml_property backend{"backend", "interp"}; scml_property gdb_server_port{"gdb_server_port", 0}; scml_property dump_ir{"dump_ir", false}; scml_property mhartid{"mhartid", 0}; scml_property plugins{"plugins", ""}; 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} , plugins{"plugins", ""} , fetch_lut(tlm_dmi_ext()) , read_lut(tlm_dmi_ext()) , write_lut(tlm_dmi_ext()) { init(); } #endif ~core_complex(); inline void sync(uint64_t cycle) { auto core_inc = curr_clk * (cycle - last_sync_cycle); auto incr = std::max(core_inc, std::max(ibus_inc, dbus_inc)); quantum_keeper.inc(incr); if (quantum_keeper.need_sync()) { wait(quantum_keeper.get_local_time()); quantum_keeper.reset(); } last_sync_cycle = cycle; ibus_inc = sc_core::SC_ZERO_TIME; dbus_inc = sc_core::SC_ZERO_TIME; } bool read_mem(uint64_t addr, unsigned length, uint8_t *const data, bool is_fetch); bool write_mem(uint64_t addr, unsigned length, const uint8_t *const data); bool read_mem_dbg(uint64_t addr, unsigned length, uint8_t *const data); bool write_mem_dbg(uint64_t addr, unsigned length, const uint8_t *const data); void trace(sc_core::sc_trace_file *trf) const override; bool disass_output(uint64_t pc, const std::string instr); void set_clock_period(sc_core::sc_time period); protected: void before_end_of_elaboration() override; void start_of_simulation() override; void forward(); void run(); void rst_cb(); void sw_irq_cb(); void timer_irq_cb(); void ext_irq_cb(); void local_irq_cb(); uint64_t last_sync_cycle = 0; util::range_lut fetch_lut, read_lut, write_lut; tlm_utils::tlm_quantumkeeper quantum_keeper; std::vector write_buf; core_wrapper* cpu{nullptr}; sc_core::sc_signal curr_clk; sc_core::sc_time ibus_inc, dbus_inc; core_trace* trc{nullptr}; std::unique_ptr t2t; private: void init(); std::vector plugin_list; }; } /* namespace tgfs */ } /* namespace sysc */ #endif /* _SYSC_CORE_COMPLEX_H_ */