diff --git a/riscv.sc/gen_input/aon.rdl b/riscv.sc/gen_input/aon.rdl new file mode 100644 index 0000000..234d313 --- /dev/null +++ b/riscv.sc/gen_input/aon.rdl @@ -0,0 +1,158 @@ +regfile aon_regs { + // Watchdog Timer Registers + reg { + name = "wdogcfg"; + desc = "Watchdog Timer Config Register"; + field { + name="data"; + } data[31:0]; + } wdogcfg @0x00; + reg { + name ="wdogcount"; + desc = "Watchdog Timer Count Registers"; + field { + name="data"; + } data[31:0]; + } wdogcount @0x08; + reg { + name ="wdogs"; + desc = ""; + field { + name="data"; + } data[31:0]; + } wdogs @0x10; + reg { + name ="wdogfeed"; + desc = ""; + field { + name="data"; + } data[31:0]; + } wdogfeed @0x18; + reg { + name ="wdogkey"; + desc = ""; + field { + name="data"; + } data[31:0]; + } wdogkey @0x1C; + reg { + name ="wdogcmp"; + desc = ""; + field { + name="data"; + } data[31:0]; + } wdogcmp @0x20; + // Real-Time Clock Registers + reg { + name ="rtccfg"; + desc = ""; + field { + name="data"; + } data[31:0]; + } rtccfg @0x40; + reg { + name ="rtclo"; + desc = ""; + field { + name="data"; + } data[31:0]; + } rtclo @0x48; + reg { + name ="rtchi"; + desc = ""; + field { + name="data"; + } data[31:0]; + } rtchi @0x4C; + reg { + name ="rtcs"; + desc = ""; + field { + name="data"; + } data[31:0]; + } rtcs @0x50; + reg { + name ="rtccmp"; + desc = ""; + field { + name="data"; + } data[31:0]; + } rtccmp @0x60; + // AON Clock Configuration Registers + reg { + name ="lfrosccfg"; + desc = ""; + field { + name="data"; + } data[31:0]; + } lfrosccfg @0x70; + // Backup Registers + reg { + name ="lfrosccfg"; + desc = ""; + field { + name="data"; + } data[31:0]; + } backup[32] @0x80; + // Power Management Unit + reg { + name ="pmuwakeupi"; + desc = ""; + field { + name="delay"; + } delay[3:0]; + field { + name="vddpaden"; + } vddpaden[5:5]; + field { + name="corerst"; + } corerst[7:7]; + field { + name="hfclkrst"; + } hfclkrst[8:8]; + } pmuwakeupi[8] @0x0100; + reg { + name ="pmusleepi"; + desc = ""; + field { + name="delay"; + } delay[3:0]; + field { + name="vddpaden"; + } vddpaden[5:5]; + field { + name="corerst"; + } corerst[7:7]; + field { + name="hfclkrst"; + } hfclkrst[8:8]; + } pmusleepi[8] @0x0120; + reg { + name ="pmuie"; + desc = ""; + field { + name="data"; + } data[31:0]; + } pmuie @0x0140; + reg { + name ="pmucause"; + desc = ""; + field { + name="data"; + } data[31:0]; + } pmucause @0x0144; + reg { + name ="pmusleep"; + desc = ""; + field { + name="data"; + } data[31:0]; + } pmusleep @0x0148; + reg { + name ="pmukey"; + desc = ""; + field { + name="data"; + } data[31:0]; + } pmukey @0x014C; +}; \ No newline at end of file diff --git a/riscv.sc/gen_input/clint.rdl b/riscv.sc/gen_input/clint.rdl new file mode 100644 index 0000000..4d61ba6 --- /dev/null +++ b/riscv.sc/gen_input/clint.rdl @@ -0,0 +1,27 @@ +regfile clint_regs { + reg { + name = "msip"; + desc = "Hart 0 software interrupt register"; + field { + name="msip"; + } msip[0:0]; + } msip @0; + reg { + name = "mtimecmp"; + desc = "Hart 0 time comparator register"; + regwidth=64; + field { + name="data"; + fieldwidth=64; + } data = 64'h7FFFFFFFFFFFFFFF; + } mtimecmp @0x4000; + reg { + name = "mtime"; + desc = "Timer register"; + regwidth=64; + field { + fieldwidth=64; + name="data"; + } data[63:0]; + } mtime @0xBFF8; +}; \ No newline at end of file diff --git a/riscv.sc/gen_input/fe310.rdl b/riscv.sc/gen_input/fe310.rdl index e355d2b..20428c0 100644 --- a/riscv.sc/gen_input/fe310.rdl +++ b/riscv.sc/gen_input/fe310.rdl @@ -2,10 +2,18 @@ `include "uart.rdl" `include "spi.rdl" `include "plic.rdl" +`include "aon.rdl" +`include "prci.rdl" +`include "clint.rdl" addrmap e300_plat_t { - plic_regs plic @0x0C000000; - gpio_regs gpio @0x10012000; - uart_regs uart @0x10013000; - spi_regs spi @0x10014000; + lsb0; + clint_regs clint @0x02000000; + plic_regs plic @0x0C000000; + aon_regs aon @0x10000000; + prci_regs prci @0x10008000; + gpio_regs gpio @0x10012000; + uart_regs uart0 @0x10013000; + uart_regs uart1 @0x10023000; + spi_regs spi @0x10014000; } e300_plat; diff --git a/riscv.sc/gen_input/gpio.rdl b/riscv.sc/gen_input/gpio.rdl index 6137c0f..483f4b6 100644 --- a/riscv.sc/gen_input/gpio.rdl +++ b/riscv.sc/gen_input/gpio.rdl @@ -1,5 +1,4 @@ regfile gpio_regs { - lsb0; reg { name="value"; desc="pin value"; diff --git a/riscv.sc/gen_input/plic.rdl b/riscv.sc/gen_input/plic.rdl index ee7b004..54bd6aa 100644 --- a/riscv.sc/gen_input/plic.rdl +++ b/riscv.sc/gen_input/plic.rdl @@ -2,36 +2,26 @@ regfile plic_regs { reg { name="priority"; desc="interrupt source priority"; - field { - name = "priority"; - } priority[2:0]; + field {} priority[2:0]; } priority[255] @0x004; reg { name="pending"; desc="pending irq"; - field { - name = "pending"; - } pending[31:0]; + field {} pending[31:0]; } pending @0x1000; reg { name="enabled"; desc="enabled interrupts"; - field { - name = "enabled"; - } enabled[31:0]; + field {} enabled[31:0]; } enabled @0x2000; reg { name="threshold"; desc="interrupt priority threshold"; - field { - name = "threshold"; - } \threshold[2:0]; + field {} \threshold[2:0]; } \threshold @0x200000; reg { name="claim/complete"; desc="interrupt handling completed"; - field { - name = "interrupt_claimed"; - } interrupt_claimed[31:0]; + field {} interrupt_claimed[31:0]; } claim_complete @0x200004; }; \ No newline at end of file diff --git a/riscv.sc/gen_input/prci.rdl b/riscv.sc/gen_input/prci.rdl new file mode 100644 index 0000000..ee00de8 --- /dev/null +++ b/riscv.sc/gen_input/prci.rdl @@ -0,0 +1,41 @@ +regfile prci_regs { + reg { + name ="hfrosccfg"; + desc = ""; + field {} hfroscdiv[5:0]; + field {} hfrosctrim[20:16]; + field {} hfroscen[30:30]; + field {} hfroscrdy[31:31]; + } hfrosccfg @0x00; + reg { + name ="hfxosccfg"; + desc = ""; + field {} hfxoscrdy[31:31]; + field {} hfxoscen[30:30]; + } hfxosccfg @0x04; + reg { + name ="pllcfg"; + desc = ""; + field {} pllr[2:0]; + field {} pllf[9:4]; + field {} pllq[11:10]; + field {} pllsel[16:16]; + field {} pllrefsel[17:17]; + field {} pllbypass[18:18]; + field {} plllock[31:31]; + } pllcfg @0x08; + reg { + name ="plloutdiv"; + desc = ""; + field { + name="data"; + } data[31:0]; + } plloutdiv @0x0c; + reg { + name ="coreclkcfg"; + desc = ""; + field { + name="data"; + } data[31:0]; + } coreclkcfg @0x10; +}; \ No newline at end of file diff --git a/riscv.sc/gen_input/spi.rdl b/riscv.sc/gen_input/spi.rdl index 8c142f4..44c8222 100644 --- a/riscv.sc/gen_input/spi.rdl +++ b/riscv.sc/gen_input/spi.rdl @@ -1,5 +1,4 @@ regfile spi_regs { - lsb0; reg { name="sckdiv"; desc="Serial clock divisor"; diff --git a/riscv.sc/gen_input/uart.rdl b/riscv.sc/gen_input/uart.rdl index a7aef85..d095437 100644 --- a/riscv.sc/gen_input/uart.rdl +++ b/riscv.sc/gen_input/uart.rdl @@ -1,80 +1,45 @@ regfile uart_regs { - lsb0; reg { name="txdata"; desc="Transmit data register"; - field { - name ="data"; - } data[7:0]; - field { - name ="full"; - } full[31:31]; + field {} data[7:0]; + field {} full[31:31]; } txdata @0x00; reg { name="rxdata"; desc="Receive data register"; - field { - name ="data"; - } data[7:0]; - field { - name ="empty"; - } empty[31:31]; + field {} data[7:0]; + field {} empty[31:31]; }rxdata @0x04; reg { name="txctrl"; desc="Transmit control register"; - field { - name ="txen"; - } txen[1]; - field { - name ="nstop"; - } nstop[1]; - field { - name ="reserved"; - } reserved[14]; - field { - name ="txcnt"; - } txcnt[3]; + field {} txen[1]; + field {} nstop[1]; + field {} txcnt[18:16]; }txctrl @0x08; reg { name="rxctrl"; desc="Receive control register"; - field { - name ="rxen"; - } rxen[1]; - field { - name ="reserved"; - } reserved[15]; - field { - name ="rxcnt"; - } rxcnt[3]; + field {} rxen[1]; + field {} rxcnt[18:16]; }rxctrl @0x0C; reg { name="ie"; desc="UART interrupt enable"; - field{ - name ="txwm"; - } txwm[1]; - field{ - name ="rxwm"; - } rxwm[1]; + field{} txwm[1]; + field{} rxwm[1]; }ie @0x10; reg { name="ip"; desc="UART Interrupt pending"; - field{ - name ="txwm"; - } txwm[1]; - field{ - name ="rxwm"; - } rxwm[1]; + field{} txwm[1]; + field{} rxwm[1]; } ip @0x14; reg { name="div"; desc="Baud rate divisor"; - field{ - name ="div"; - } div[16]; + field{} div[16]; } div @0x18; }; diff --git a/riscv.sc/incl/cli_options.h b/riscv.sc/incl/cli_options.h deleted file mode 100644 index 10090e3..0000000 --- a/riscv.sc/incl/cli_options.h +++ /dev/null @@ -1,173 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017, 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 API and implementation - ******************************************************************************/ - -#ifndef _CLI_OPTIONS_H_ -#define _CLI_OPTIONS_H_ -#include -#include -#include -#include - -namespace { -const size_t ERROR_IN_COMMAND_LINE = 1; -const size_t SUCCESS = 0; -const size_t ERROR_UNHANDLED_EXCEPTION = 2; - -inline void enable_log_level(int level) { - switch (level) { - case 0: - logging::Logger::reporting_level() = logging::FATAL; - /* no break */ - case 1: - logging::Logger::reporting_level() = logging::ERROR; - /* no break */ - case 2: - logging::Logger::reporting_level() = logging::WARNING; - /* no break */ - case 3: - logging::Logger::reporting_level() = logging::INFO; - /* no break */ - case 4: - logging::Logger::reporting_level() = logging::DEBUG; - /* no break */ - case 5: - logging::Logger::reporting_level() = logging::TRACE; - /* no break */ - } -} - -inline void configure_default_logger(boost::program_options::variables_map &vm) { - // el::Configurations defaultConf; - // defaultConf.setToDefault(); - // defaultConf.set(el::Level::Error, el::ConfigurationType::Format, - //"%datetime{%H:%m:%s.%g} %level %msg"); - // defaultConf.set(el::Level::Warning, el::ConfigurationType::Format, - //"%datetime{%H:%m:%s.%g} %level %msg"); - // defaultConf.set(el::Level::Info, el::ConfigurationType::Format, - //"%datetime{%H:%m:%s.%g} %level %msg"); - // defaultConf.set(el::Level::Debug, el::ConfigurationType::Format, - //"%datetime{%H:%m:%s.%g} %level %msg"); - // defaultConf.set(el::Level::Trace, el::ConfigurationType::Format, - //"%datetime{%H:%m:%s.%g} %level %msg"); - if (vm.count("verbose")) enable_log_level(vm["verbose"].as()); - if (vm.count("log-file")) logging::Output2FILE::stream() = fopen(vm["log-file"].as().c_str(), "w"); - // default logger uses default configurations - // el::Loggers::reconfigureLogger("default", defaultConf); -} - -inline void configure_debugger_logger() { - // configure the connection logger - // el::Logger* gdbServerLogger = el::Loggers::getLogger(connection); - // el::Configurations gdbServerConf; - // gdbServerConf.setToDefault(); - // gdbServerConf.set(el::Level::Error, el::ConfigurationType::Format, - // "%datetime{%H:%m:%s.%g} %level [%logger] %msg"); - // gdbServerConf.set(el::Level::Warning, el::ConfigurationType::Format, - // "%datetime{%H:%m:%s.%g} %level [%logger] %msg"); - // gdbServerConf.set(el::Level::Info, el::ConfigurationType::Format, - // "%datetime{%H:%m:%s.%g} %level [%logger] %msg"); - // gdbServerConf.set(el::Level::Debug, el::ConfigurationType::Format, - // "%datetime{%H:%m:%s.%g} %level [%logger] %msg"); - // gdbServerConf.set(el::Level::Trace, el::ConfigurationType::Format, - // "%datetime{%H:%m:%s.%g} %level [%logger] %msg"); - // enable_log_level(gdbServerConf, 5); - // gdbServerLogger->configure(gdbServerConf); -} - -inline void configure_disass_logger(boost::program_options::variables_map &vm) { - // el::Logger* disassLogger = el::Loggers::getLogger(disass); - // el::Configurations disassConf; - // if(vm.count(disass)){ - // auto file_name=vm[disass].as(); - // disassConf.setToDefault(); - // if (file_name.length() > 0) { - // disassConf.set(el::Level::Global, el::ConfigurationType::ToFile, - // std::string("true")); - // disassConf.set(el::Level::Global, - // el::ConfigurationType::ToStandardOutput, - // std::string("false")); - // disassConf.set(el::Level::Global, el::ConfigurationType::Format, - // std::string("%msg")); - // disassConf.set(el::Level::Global, - // el::ConfigurationType::Filename, - // file_name); - // std::ofstream str(file_name); // just to clear the file - // } else { - // disassConf.set(el::Level::Global, el::ConfigurationType::Format, - // "%datetime{%H:%m:%s.%g} [%logger] %msg"); - // } - // } else { - // enable_log_level(disassConf, 0); - // } - // disassLogger->configure(disassConf); -} - -} // namespace - -inline int parse_cli_options(boost::program_options::variables_map &vm, int argc, char *argv[]) { - namespace po = boost::program_options; - po::options_description desc("Options"); - desc.add_options()("help,h", "Print help message")("verbose,v", po::value()->implicit_value(0), - "Sets logging verbosity")("vmodule", po::value(), - "Defines the module(s) to be logged")( - "logging-flags", po::value(), "Sets logging flag(s).")("log-file", po::value(), - "Sets default log file.")( - "disass,d", po::value()->implicit_value(""), - "Enables disassembly")("elf,l", po::value>(), "ELF file(s) to load")( - "gdb-port,g", po::value(), "enable gdb server and specify port to use")( - "input,i", po::value(), "the elf file to load (instead of hex files)")( - "dump-ir", "dump the intermediate representation")("cycles,c", po::value()->default_value(-1), - "number of cycles to run")( - "systemc,s", "Run as SystemC simulation")("time", po::value(), "SystemC siimulation time in ms")( - "reset,r", po::value(), "reset address")( - "trace", po::value(), "enable tracing, or cmbintation of 1=signals and 2=TX text, 4=TX " - "compressed text, 6=TX in SQLite")("mem,m", po::value(), - "the memory input file")("rv64", "run RV64"); - try { - po::store(po::parse_command_line(argc, argv, desc), vm); // can throw - // --help option - if (vm.count("help")) { - std::cout << "DBT-RISE-RiscV" << std::endl << desc << std::endl; - return SUCCESS; - } - po::notify(vm); // throws on error, so do after help in case - } catch (po::error &e) { - // there are problems - std::cerr << "ERROR: " << e.what() << std::endl << std::endl; - std::cerr << desc << std::endl; - return ERROR_IN_COMMAND_LINE; - } - return SUCCESS; -} -#endif /* _CLI_OPTIONS_H_ */ diff --git a/riscv.sc/incl/sysc/SiFive/aon.h b/riscv.sc/incl/sysc/SiFive/aon.h new file mode 100644 index 0000000..fe02e92 --- /dev/null +++ b/riscv.sc/incl/sysc/SiFive/aon.h @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright 2017 eyck@minres.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + ******************************************************************************/ + +#ifndef _AON_H_ +#define _AON_H_ + +#include + +namespace sysc { + +class aon_regs; + +class aon : public sc_core::sc_module, public tlm_target<> { +public: + SC_HAS_PROCESS(aon); + sc_core::sc_in clk_i; + sc_core::sc_in rst_i; + aon(sc_core::sc_module_name nm); + virtual ~aon() override; // need to keep it in source file because of fwd declaration of aon_regs + +protected: + void clock_cb(); + void reset_cb(); + sc_core::sc_time clk; + std::unique_ptr regs; +}; + +} /* namespace sysc */ + +#endif /* _GPIO_H_ */ diff --git a/riscv.sc/incl/sysc/SiFive/clint.h b/riscv.sc/incl/sysc/SiFive/clint.h new file mode 100644 index 0000000..a0a035b --- /dev/null +++ b/riscv.sc/incl/sysc/SiFive/clint.h @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright 2017 eyck@minres.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + ******************************************************************************/ + +#ifndef _CLINT_H_ +#define _CLINT_H_ + +#include + +namespace iss { +namespace arch { +template struct riscv_hart_msu_vp; +} +} + +namespace sysc { + +class clint_regs; +namespace SiFive { +class core_complex; +} + +class clint : public sc_core::sc_module, public tlm_target<> { +public: + SC_HAS_PROCESS(clint); + sc_core::sc_in clk_i; + sc_core::sc_in rst_i; + sc_core::sc_out mtime_int_o; + sc_core::sc_out msip_int_o; + clint(sc_core::sc_module_name nm); + virtual ~clint() override; // need to keep it in source file because of fwd declaration of clint_regs + +protected: + void clock_cb(); + void reset_cb(); + void update_mtime(); + sc_core::sc_time clk, last_updt; + unsigned cnt_fraction; + std::unique_ptr regs; + sc_core::sc_event mtime_evt; +}; + +} /* namespace sysc */ + +#endif /* _CLINT_H_ */ diff --git a/riscv.sc/incl/sysc/SiFive/core_complex.h b/riscv.sc/incl/sysc/SiFive/core_complex.h index 52835b9..6382cd4 100644 --- a/riscv.sc/incl/sysc/SiFive/core_complex.h +++ b/riscv.sc/incl/sysc/SiFive/core_complex.h @@ -37,21 +37,89 @@ #ifndef _SYSC_SIFIVE_FE310_H_ #define _SYSC_SIFIVE_FE310_H_ -#include -#include +#include +#include +#include #include #include +#include +#include + +namespace iss { +class vm_if; +namespace arch { +template struct riscv_hart_msu_vp; +} +} namespace sysc { -namespace SiFive { -class core_complex : public iss::arch::riscv_hart_msu_vp, public sc_core::sc_module { +class tlm_dmi_ext : public tlm::tlm_dmi { public: - tlm::tlm_initiator_socket<32> initiator; + 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 SiFive { +class core_wrapper; + +class core_complex : public sc_core::sc_module, public sysc::traceable { +public: + SC_HAS_PROCESS(core_complex); + + sysc::initiator_mixin> initiator; + + sc_core::sc_in clk_i; sc_core::sc_in rst_i; + + sysc::ext_attribute elf_file; + + sysc::ext_attribute enable_disass; + + sysc::ext_attribute reset_address; + + sysc::ext_attribute gdb_server_port; + + sysc::ext_attribute dump_ir; + core_complex(sc_core::sc_module_name name); - virtual ~core_complex() = default; + + ~core_complex(); + + inline void sync() { + quantum_keeper.inc(curr_clk); + if (quantum_keeper.need_sync()) { + wait(quantum_keeper.get_local_time()); + quantum_keeper.reset(); + } + } + + bool read_mem(uint64_t addr, unsigned length, uint8_t *const data); + + 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) override; + +protected: + void before_end_of_elaboration(); + void start_of_simulation(); + void run(); + void clk_cb(); + util::range_lut read_lut, write_lut; + tlm_utils::tlm_quantumkeeper quantum_keeper; + std::vector write_buf; + std::unique_ptr cpu; + std::unique_ptr vm; + sc_core::sc_time curr_clk; }; } /* namespace SiFive */ diff --git a/riscv.sc/incl/sysc/SiFive/gen/aon_regs.h b/riscv.sc/incl/sysc/SiFive/gen/aon_regs.h new file mode 100644 index 0000000..0d472bf --- /dev/null +++ b/riscv.sc/incl/sysc/SiFive/gen/aon_regs.h @@ -0,0 +1,173 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017, 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. +// +// Created on: Wed Oct 04 10:06:35 CEST 2017 +// * aon_regs.h Author: +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _AON_REGS_H_ +#define _AON_REGS_H_ + +#include +#include +#include +#include + +namespace sysc { + +class aon_regs : public sc_core::sc_module, public sysc::resetable { +public: + // storage declarations + uint32_t r_wdogcfg; + + uint32_t r_wdogcount; + + uint32_t r_wdogs; + + uint32_t r_wdogfeed; + + uint32_t r_wdogkey; + + uint32_t r_wdogcmp; + + uint32_t r_rtccfg; + + uint32_t r_rtclo; + + uint32_t r_rtchi; + + uint32_t r_rtcs; + + uint32_t r_rtccmp; + + uint32_t r_lfrosccfg; + + std::array r_backup; + + BEGIN_BF_DECL(pmuwakeupi_t, uint32_t); + BF_FIELD(delay, 0, 4); + BF_FIELD(vddpaden, 5, 1); + BF_FIELD(corerst, 7, 1); + BF_FIELD(hfclkrst, 8, 1); + END_BF_DECL(); + std::array r_pmuwakeupi; + + BEGIN_BF_DECL(pmusleepi_t, uint32_t); + BF_FIELD(delay, 0, 4); + BF_FIELD(vddpaden, 5, 1); + BF_FIELD(corerst, 7, 1); + BF_FIELD(hfclkrst, 8, 1); + END_BF_DECL(); + std::array r_pmusleepi; + + uint32_t r_pmuie; + + uint32_t r_pmucause; + + uint32_t r_pmusleep; + + uint32_t r_pmukey; + + // register declarations + sysc::sc_register wdogcfg; + sysc::sc_register wdogcount; + sysc::sc_register wdogs; + sysc::sc_register wdogfeed; + sysc::sc_register wdogkey; + sysc::sc_register wdogcmp; + sysc::sc_register rtccfg; + sysc::sc_register rtclo; + sysc::sc_register rtchi; + sysc::sc_register rtcs; + sysc::sc_register rtccmp; + sysc::sc_register lfrosccfg; + sysc::sc_register_indexed backup; + sysc::sc_register_indexed pmuwakeupi; + sysc::sc_register_indexed pmusleepi; + sysc::sc_register pmuie; + sysc::sc_register pmucause; + sysc::sc_register pmusleep; + sysc::sc_register pmukey; + + aon_regs(sc_core::sc_module_name nm); + + template void registerResources(sysc::tlm_target &target); +}; +} +////////////////////////////////////////////////////////////////////////////// +// member functions +////////////////////////////////////////////////////////////////////////////// + +inline sysc::aon_regs::aon_regs(sc_core::sc_module_name nm) +: sc_core::sc_module(nm) +, NAMED(wdogcfg, r_wdogcfg, 0, *this) +, NAMED(wdogcount, r_wdogcount, 0, *this) +, NAMED(wdogs, r_wdogs, 0, *this) +, NAMED(wdogfeed, r_wdogfeed, 0, *this) +, NAMED(wdogkey, r_wdogkey, 0, *this) +, NAMED(wdogcmp, r_wdogcmp, 0, *this) +, NAMED(rtccfg, r_rtccfg, 0, *this) +, NAMED(rtclo, r_rtclo, 0, *this) +, NAMED(rtchi, r_rtchi, 0, *this) +, NAMED(rtcs, r_rtcs, 0, *this) +, NAMED(rtccmp, r_rtccmp, 0, *this) +, NAMED(lfrosccfg, r_lfrosccfg, 0, *this) +, NAMED(backup, r_backup, 0, *this) +, NAMED(pmuwakeupi, r_pmuwakeupi, 0, *this) +, NAMED(pmusleepi, r_pmusleepi, 0, *this) +, NAMED(pmuie, r_pmuie, 0, *this) +, NAMED(pmucause, r_pmucause, 0, *this) +, NAMED(pmusleep, r_pmusleep, 0, *this) +, NAMED(pmukey, r_pmukey, 0, *this) {} + +template inline void sysc::aon_regs::registerResources(sysc::tlm_target &target) { + target.addResource(wdogcfg, 0x0UL); + target.addResource(wdogcount, 0x8UL); + target.addResource(wdogs, 0x10UL); + target.addResource(wdogfeed, 0x18UL); + target.addResource(wdogkey, 0x1cUL); + target.addResource(wdogcmp, 0x20UL); + target.addResource(rtccfg, 0x40UL); + target.addResource(rtclo, 0x48UL); + target.addResource(rtchi, 0x4cUL); + target.addResource(rtcs, 0x50UL); + target.addResource(rtccmp, 0x60UL); + target.addResource(lfrosccfg, 0x70UL); + target.addResource(backup, 0x80UL); + target.addResource(pmuwakeupi, 0x100UL); + target.addResource(pmusleepi, 0x120UL); + target.addResource(pmuie, 0x140UL); + target.addResource(pmucause, 0x144UL); + target.addResource(pmusleep, 0x148UL); + target.addResource(pmukey, 0x14cUL); +} + +#endif // _AON_REGS_H_ diff --git a/riscv.sc/incl/sysc/SiFive/gen/clint_regs.h b/riscv.sc/incl/sysc/SiFive/gen/clint_regs.h new file mode 100644 index 0000000..306339e --- /dev/null +++ b/riscv.sc/incl/sysc/SiFive/gen/clint_regs.h @@ -0,0 +1,83 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017, 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. +// +// Created on: Wed Oct 04 10:06:35 CEST 2017 +// * clint_regs.h Author: +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _CLINT_REGS_H_ +#define _CLINT_REGS_H_ + +#include +#include +#include +#include + +namespace sysc { + +class clint_regs : public sc_core::sc_module, public sysc::resetable { +public: + // storage declarations + BEGIN_BF_DECL(msip_t, uint32_t); + BF_FIELD(msip, 0, 1); + END_BF_DECL() r_msip; + + uint64_t r_mtimecmp; + + uint64_t r_mtime; + + // register declarations + sysc::sc_register msip; + sysc::sc_register mtimecmp; + sysc::sc_register mtime; + + clint_regs(sc_core::sc_module_name nm); + + template void registerResources(sysc::tlm_target &target); +}; +} +////////////////////////////////////////////////////////////////////////////// +// member functions +////////////////////////////////////////////////////////////////////////////// + +inline sysc::clint_regs::clint_regs(sc_core::sc_module_name nm) +: sc_core::sc_module(nm) +, NAMED(msip, r_msip, 0, *this) +, NAMED(mtimecmp, r_mtimecmp, 0, *this) +, NAMED(mtime, r_mtime, 0, *this) {} + +template inline void sysc::clint_regs::registerResources(sysc::tlm_target &target) { + target.addResource(msip, 0x0UL); + target.addResource(mtimecmp, 0x4000UL); + target.addResource(mtime, 0xbff8UL); +} + +#endif // _CLINT_REGS_H_ diff --git a/riscv.sc/incl/sysc/SiFive/gen/e300_plat_t.h b/riscv.sc/incl/sysc/SiFive/gen/e300_plat_t.h index 402a1c3..8d8d5d2 100644 --- a/riscv.sc/incl/sysc/SiFive/gen/e300_plat_t.h +++ b/riscv.sc/incl/sysc/SiFive/gen/e300_plat_t.h @@ -2,11 +2,15 @@ #define _E300_PLAT_MAP_H_ // need double braces, see // https://stackoverflow.com/questions/6893700/how-to-construct-stdarray-object-with-initializer-list#6894191 -const std::array, 4> e300_plat_map = {{ - {&i_plic, 0xc000000, 0x1000}, - {&i_gpio, 0x10012000, 0x1000}, - {&i_uart, 0x10013000, 0x1000}, - {&i_spi, 0x10014000, 0x1000}, +const std::array, 8> e300_plat_map = {{ + {&i_clint, 0x2000000, 0xc000}, + {&i_plic, 0xc000000, 0x200008}, + {&i_aon, 0x10000000, 0x150}, + {&i_prci, 0x10008000, 0x14}, + {&i_gpio, 0x10012000, 0x44}, + {&i_uart0, 0x10013000, 0x1c}, + {&i_uart1, 0x10023000, 0x1c}, + {&i_spi, 0x10014000, 0x78}, }}; #endif /* _E300_PLAT_MAP_H_ */ diff --git a/riscv.sc/incl/sysc/SiFive/gen/gpio_regs.h b/riscv.sc/incl/sysc/SiFive/gen/gpio_regs.h index f91a056..1dbb745 100644 --- a/riscv.sc/incl/sysc/SiFive/gen/gpio_regs.h +++ b/riscv.sc/incl/sysc/SiFive/gen/gpio_regs.h @@ -28,7 +28,7 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // -// Created on: Wed Sep 20 11:47:24 CEST 2017 +// Created on: Wed Oct 04 10:06:35 CEST 2017 // * gpio_regs.h Author: // //////////////////////////////////////////////////////////////////////////////// @@ -44,7 +44,7 @@ namespace sysc { class gpio_regs : public sc_core::sc_module, public sysc::resetable { -protected: +public: // storage declarations uint32_t r_value; @@ -99,7 +99,6 @@ protected: sysc::sc_register iof_sel; sysc::sc_register out_xor; -public: gpio_regs(sc_core::sc_module_name nm); template void registerResources(sysc::tlm_target &target); diff --git a/riscv.sc/incl/sysc/SiFive/gen/plic_regs.h b/riscv.sc/incl/sysc/SiFive/gen/plic_regs.h index 875a855..014951f 100644 --- a/riscv.sc/incl/sysc/SiFive/gen/plic_regs.h +++ b/riscv.sc/incl/sysc/SiFive/gen/plic_regs.h @@ -28,7 +28,7 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // -// Created on: Wed Sep 20 22:30:45 CEST 2017 +// Created on: Wed Oct 04 10:06:35 CEST 2017 // * plic_regs.h Author: // //////////////////////////////////////////////////////////////////////////////// @@ -44,7 +44,7 @@ namespace sysc { class plic_regs : public sc_core::sc_module, public sysc::resetable { -protected: +public: // storage declarations BEGIN_BF_DECL(priority_t, uint32_t); BF_FIELD(priority, 0, 3); @@ -68,7 +68,6 @@ protected: sysc::sc_register threshold; sysc::sc_register claim_complete; -public: plic_regs(sc_core::sc_module_name nm); template void registerResources(sysc::tlm_target &target); @@ -90,8 +89,8 @@ template inline void sysc::plic_regs::registerResources(sysc target.addResource(priority, 0x4UL); target.addResource(pending, 0x1000UL); target.addResource(enabled, 0x2000UL); - target.addResource(threshold, 0xc200000UL); - target.addResource(claim_complete, 0xc200004UL); + target.addResource(threshold, 0x200000UL); + target.addResource(claim_complete, 0x200004UL); } #endif // _PLIC_REGS_H_ diff --git a/riscv.sc/incl/sysc/SiFive/gen/prci_regs.h b/riscv.sc/incl/sysc/SiFive/gen/prci_regs.h new file mode 100644 index 0000000..a197408 --- /dev/null +++ b/riscv.sc/incl/sysc/SiFive/gen/prci_regs.h @@ -0,0 +1,107 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017, 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. +// +// Created on: Wed Oct 04 10:06:35 CEST 2017 +// * prci_regs.h Author: +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _PRCI_REGS_H_ +#define _PRCI_REGS_H_ + +#include +#include +#include +#include + +namespace sysc { + +class prci_regs : public sc_core::sc_module, public sysc::resetable { +public: + // storage declarations + BEGIN_BF_DECL(hfrosccfg_t, uint32_t); + BF_FIELD(hfroscdiv, 0, 6); + BF_FIELD(hfrosctrim, 16, 5); + BF_FIELD(hfroscen, 30, 1); + BF_FIELD(hfroscrdy, 31, 1); + END_BF_DECL() r_hfrosccfg; + + BEGIN_BF_DECL(hfxosccfg_t, uint32_t); + BF_FIELD(hfxoscrdy, 31, 1); + BF_FIELD(hfxoscen, 30, 1); + END_BF_DECL() r_hfxosccfg; + + BEGIN_BF_DECL(pllcfg_t, uint32_t); + BF_FIELD(pllr, 0, 3); + BF_FIELD(pllf, 4, 6); + BF_FIELD(pllq, 10, 2); + BF_FIELD(pllsel, 16, 1); + BF_FIELD(pllrefsel, 17, 1); + BF_FIELD(pllbypass, 18, 1); + BF_FIELD(plllock, 31, 1); + END_BF_DECL() r_pllcfg; + + uint32_t r_plloutdiv; + + uint32_t r_coreclkcfg; + + // register declarations + sysc::sc_register hfrosccfg; + sysc::sc_register hfxosccfg; + sysc::sc_register pllcfg; + sysc::sc_register plloutdiv; + sysc::sc_register coreclkcfg; + + prci_regs(sc_core::sc_module_name nm); + + template void registerResources(sysc::tlm_target &target); +}; +} +////////////////////////////////////////////////////////////////////////////// +// member functions +////////////////////////////////////////////////////////////////////////////// + +inline sysc::prci_regs::prci_regs(sc_core::sc_module_name nm) +: sc_core::sc_module(nm) +, NAMED(hfrosccfg, r_hfrosccfg, 0, *this) +, NAMED(hfxosccfg, r_hfxosccfg, 0, *this) +, NAMED(pllcfg, r_pllcfg, 0, *this) +, NAMED(plloutdiv, r_plloutdiv, 0, *this) +, NAMED(coreclkcfg, r_coreclkcfg, 0, *this) {} + +template inline void sysc::prci_regs::registerResources(sysc::tlm_target &target) { + target.addResource(hfrosccfg, 0x0UL); + target.addResource(hfxosccfg, 0x4UL); + target.addResource(pllcfg, 0x8UL); + target.addResource(plloutdiv, 0xcUL); + target.addResource(coreclkcfg, 0x10UL); +} + +#endif // _PRCI_REGS_H_ diff --git a/riscv.sc/incl/sysc/SiFive/gen/spi_regs.h b/riscv.sc/incl/sysc/SiFive/gen/spi_regs.h index 03e5b13..05b3608 100644 --- a/riscv.sc/incl/sysc/SiFive/gen/spi_regs.h +++ b/riscv.sc/incl/sysc/SiFive/gen/spi_regs.h @@ -28,7 +28,7 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // -// Created on: Wed Sep 20 22:30:45 CEST 2017 +// Created on: Wed Oct 04 10:06:35 CEST 2017 // * spi_regs.h Author: // //////////////////////////////////////////////////////////////////////////////// @@ -44,7 +44,7 @@ namespace sysc { class spi_regs : public sc_core::sc_module, public sysc::resetable { -protected: +public: // storage declarations BEGIN_BF_DECL(sckdiv_t, uint32_t); BF_FIELD(div, 0, 12); @@ -141,7 +141,6 @@ protected: sysc::sc_register ie; sysc::sc_register ip; -public: spi_regs(sc_core::sc_module_name nm); template void registerResources(sysc::tlm_target &target); diff --git a/riscv.sc/incl/sysc/SiFive/gen/uart_regs.h b/riscv.sc/incl/sysc/SiFive/gen/uart_regs.h index 4f4b166..84f4fb5 100644 --- a/riscv.sc/incl/sysc/SiFive/gen/uart_regs.h +++ b/riscv.sc/incl/sysc/SiFive/gen/uart_regs.h @@ -28,7 +28,7 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // -// Created on: Wed Sep 20 22:30:45 CEST 2017 +// Created on: Wed Oct 04 10:06:35 CEST 2017 // * uart_regs.h Author: // //////////////////////////////////////////////////////////////////////////////// @@ -44,7 +44,7 @@ namespace sysc { class uart_regs : public sc_core::sc_module, public sysc::resetable { -protected: +public: // storage declarations BEGIN_BF_DECL(txdata_t, uint32_t); BF_FIELD(data, 0, 8); @@ -59,13 +59,11 @@ protected: BEGIN_BF_DECL(txctrl_t, uint32_t); BF_FIELD(txen, 0, 1); BF_FIELD(nstop, 1, 1); - BF_FIELD(reserved, 2, 14); BF_FIELD(txcnt, 16, 3); END_BF_DECL() r_txctrl; BEGIN_BF_DECL(rxctrl_t, uint32_t); BF_FIELD(rxen, 0, 1); - BF_FIELD(reserved, 1, 15); BF_FIELD(rxcnt, 16, 3); END_BF_DECL() r_rxctrl; @@ -92,7 +90,6 @@ protected: sysc::sc_register ip; sysc::sc_register div; -public: uart_regs(sc_core::sc_module_name nm); template void registerResources(sysc::tlm_target &target); diff --git a/riscv.sc/incl/sysc/SiFive/platform.h b/riscv.sc/incl/sysc/SiFive/platform.h index 31fa95f..dd3dc5d 100644 --- a/riscv.sc/incl/sysc/SiFive/platform.h +++ b/riscv.sc/incl/sysc/SiFive/platform.h @@ -23,14 +23,19 @@ #ifndef SIMPLESYSTEM_H_ #define SIMPLESYSTEM_H_ +#include "aon.h" +#include "clint.h" #include "gpio.h" #include "plic.h" +#include "prci.h" #include "spi.h" #include "uart.h" #include #include +#include #include +#include #include "core_complex.h" @@ -40,14 +45,20 @@ class platform : public sc_core::sc_module { public: SC_HAS_PROCESS(platform); - SiFive::core_complex i_master; + SiFive::core_complex i_core_complex; router<> i_router; - uart i_uart; + uart i_uart0, i_uart1; spi i_spi; gpio i_gpio; plic i_plic; + aon i_aon; + prci i_prci; + clint i_clint; + + memory<512_MB, 32> i_mem_qspi; + memory<128_kB, 32> i_mem_ram; sc_core::sc_signal s_clk; - sc_core::sc_signal s_rst; + sc_core::sc_signal s_rst, s_mtime_int, s_msie_int; platform(sc_core::sc_module_name nm); diff --git a/riscv.sc/incl/sysc/SiFive/prci.h b/riscv.sc/incl/sysc/SiFive/prci.h new file mode 100644 index 0000000..5c9f376 --- /dev/null +++ b/riscv.sc/incl/sysc/SiFive/prci.h @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright 2017 eyck@minres.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + ******************************************************************************/ + +#ifndef _PRCI_H_ +#define _PRCI_H_ + +#include + +namespace sysc { + +class prci_regs; + +class prci : public sc_core::sc_module, public tlm_target<> { +public: + SC_HAS_PROCESS(prci); + sc_core::sc_in clk_i; + sc_core::sc_in rst_i; + prci(sc_core::sc_module_name nm); + virtual ~prci() override; // need to keep it in source file because of fwd declaration of prci_regs + +protected: + void clock_cb(); + void reset_cb(); + void hfrosc_en_cb(); + sc_core::sc_time clk; + std::unique_ptr regs; + sc_core::sc_event hfrosc_en_evt; +}; + +} /* namespace sysc */ + +#endif /* _GPIO_H_ */ diff --git a/riscv.sc/incl/sysc/SiFive/uart.h b/riscv.sc/incl/sysc/SiFive/uart.h index d119605..4487484 100644 --- a/riscv.sc/incl/sysc/SiFive/uart.h +++ b/riscv.sc/incl/sysc/SiFive/uart.h @@ -34,8 +34,10 @@ public: protected: void clock_cb(); void reset_cb(); + void transmit_data(); sc_core::sc_time clk; std::unique_ptr regs; + std::vector queue; }; } /* namespace sysc */ diff --git a/riscv.sc/src/CMakeLists.txt b/riscv.sc/src/CMakeLists.txt index ee4461b..9a37b54 100644 --- a/riscv.sc/src/CMakeLists.txt +++ b/riscv.sc/src/CMakeLists.txt @@ -1,13 +1,9 @@ # library files FILE(GLOB RiscVSCHeaders *.h) +FILE(GLOB RiscvSCSources sysc/*.cpp) + set(LIB_HEADERS ${RiscVSCHeaders} ) -set(LIB_SOURCES - sysc/core_complex.cpp - sysc/gpio.cpp - sysc/plic.cpp - sysc/platform.cpp - sysc/spi.cpp - sysc/uart.cpp +set(LIB_SOURCES ${RiscvSCSources} ) set(APP_HEADERS ) diff --git a/riscv.sc/src/sc_main.cpp b/riscv.sc/src/sc_main.cpp index 8a35081..9e24318 100644 --- a/riscv.sc/src/sc_main.cpp +++ b/riscv.sc/src/sc_main.cpp @@ -21,9 +21,12 @@ */ #include +#include +#include #include #include #include +#include #include #include #include @@ -39,19 +42,34 @@ const size_t ERROR_UNHANDLED_EXCEPTION = 2; int sc_main(int argc, char *argv[]) { // sc_report_handler::set_handler(my_report_handler); - sysc::Logger::reporting_level() = log::DEBUG; + sysc::Logger<>::reporting_level() = log::ERROR; /////////////////////////////////////////////////////////////////////////// // CLI argument parsing /////////////////////////////////////////////////////////////////////////// po::options_description desc("Options"); - desc.add_options()("help,h", "Print help message")("debug,d", po::value(), - "set debug level")("trace,t", "trace SystemC signals"); + // clang-format off + desc.add_options() + ("help,h", "Print help message") + ("verbose,v", po::value()->implicit_value(0), "Sets logging verbosity") + ("log-file", po::value(), "Sets default log file.") + ("disass,d", po::value()->implicit_value(""), "Enables disassembly") +// ("elf,l", po::value>(), "ELF file(s) to load") + ("elf,l", po::value(), "ELF file to load") + ("gdb-port,g", po::value()->default_value(0), "enable gdb server and specify port to use") + ("dump-ir", "dump the intermediate representation") + ("cycles,c", po::value()->default_value(-1), "number of cycles to run") + ("quantum", po::value(), "SystemC quantum time in ns") + ("reset,r", po::value(), "reset address") + ("trace,t", po::value()->default_value(0), "enable tracing, or combintation of 1=signals and 2=TX text, 4=TX compressed text, 6=TX in SQLite") + ("rv64", "run RV64") + ("config-file,c", po::value()->default_value(""), "configuration file"); + // clang-format on po::variables_map vm; try { po::store(po::parse_command_line(argc, argv, desc), vm); // can throw // --help option if (vm.count("help")) { - std::cout << "JIT-ISS simulator for AVR" << std::endl << desc << std::endl; + std::cout << "DBT-RISE-RiscV simulator for RISC-V" << std::endl << desc << std::endl; return SUCCESS; } po::notify(vm); // throws on error, so do after help in case @@ -61,21 +79,65 @@ int sc_main(int argc, char *argv[]) { std::cerr << desc << std::endl; return ERROR_IN_COMMAND_LINE; } + if (vm.count("verbose")) { + auto l = logging::as_log_level(vm["verbose"].as()); + LOGGER(DEFAULT)::reporting_level() = l; + LOGGER(connection)::reporting_level() = l; + LOGGER(SystemC)::reporting_level() = l; + sysc::Logger<>::reporting_level() = l; + } + if (vm.count("log-file")) { + // configure the connection logger + auto f = fopen(vm["log-file"].as().c_str(), "w"); + LOG_OUTPUT(DEFAULT)::stream() = f; + LOG_OUTPUT(connection)::stream() = f; + LOG_OUTPUT(SystemC)::stream() = f; + } + /////////////////////////////////////////////////////////////////////////// + // set up infrastructure + /////////////////////////////////////////////////////////////////////////// + iss::init_jit(argc, argv); /////////////////////////////////////////////////////////////////////////// // set up tracing & transaction recording /////////////////////////////////////////////////////////////////////////// - sysc::tracer trace("simple_system", sysc::tracer::TEXT, vm.count("trace")); + sysc::tracer trace("simple_system", static_cast(vm["trace"].as() >> 1), + vm["trace"].as() != 0); + /////////////////////////////////////////////////////////////////////////// + // set up configuration + /////////////////////////////////////////////////////////////////////////// + sysc::configurer cfg(vm["config-file"].as()); /////////////////////////////////////////////////////////////////////////// // instantiate top level /////////////////////////////////////////////////////////////////////////// platform i_simple_system("i_simple_system"); // sr_report_handler::add_sc_object_to_filter(&i_simple_system.i_master, // sc_core::SC_WARNING, sc_core::SC_MEDIUM); - + // cfg.dump_hierarchy(); + if (vm.count("elf")) cfg.set_value("i_simple_system.i_core_complex.elf_file", vm["elf"].as()); + if (vm.count("reset")) { + auto str = vm["reset"].as(); + uint64_t start_address = str.find("0x") == 0 ? std::stoull(str.substr(2), 0, 16) : std::stoull(str, 0, 10); + cfg.set_value("i_simple_system.i_core_complex.reset_address", start_address); + } + if (vm.count("disass")) { + cfg.set_value("i_simple_system.i_core_complex.enable_disass", true); + LOGGER(disass)::reporting_level() = logging::INFO; + auto file_name = vm["disass"].as(); + if (file_name.length() > 0) { + LOG_OUTPUT(disass)::stream() = fopen(file_name.c_str(), "w"); + LOGGER(disass)::print_time() = false; + LOGGER(disass)::print_severity() = false; + } + } + cfg.set_value("i_simple_system.i_core_complex.gdb_server_port", vm["gdb-port"].as()); + cfg.set_value("i_simple_system.i_core_complex.dump_ir", vm.count("dump-ir") != 0); + if (vm.count("quantum")) { + tlm::tlm_global_quantum::instance().set(sc_core::sc_time(vm["quantum"].as(), sc_core::SC_NS)); + } /////////////////////////////////////////////////////////////////////////// // run simulation /////////////////////////////////////////////////////////////////////////// - sc_start(sc_core::sc_time(100, sc_core::SC_NS)); + sc_start(); if (!sc_end_of_simulation_invoked()) sc_stop(); return 0; } diff --git a/riscv.sc/src/sysc/aon.cpp b/riscv.sc/src/sysc/aon.cpp new file mode 100644 index 0000000..e177112 --- /dev/null +++ b/riscv.sc/src/sysc/aon.cpp @@ -0,0 +1,48 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 eyck@minres.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +//////////////////////////////////////////////////////////////////////////////// + +#include "sysc/SiFive/aon.h" +#include "sysc/SiFive/gen/aon_regs.h" +#include "sysc/utilities.h" + +namespace sysc { + +aon::aon(sc_core::sc_module_name nm) +: sc_core::sc_module(nm) +, tlm_target<>(clk) +, NAMED(clk_i) +, NAMED(rst_i) +, NAMEDD(aon_regs, regs) { + regs->registerResources(*this); + SC_METHOD(clock_cb); + sensitive << clk_i; + SC_METHOD(reset_cb); + sensitive << rst_i; + dont_initialize(); +} + +void aon::clock_cb() {} + +aon::~aon() {} + +void aon::reset_cb() { + if (rst_i.read()) + regs->reset_start(); + else + regs->reset_stop(); +} + +} /* namespace sysc */ diff --git a/riscv.sc/src/sysc/clint.cpp b/riscv.sc/src/sysc/clint.cpp new file mode 100644 index 0000000..f21de23 --- /dev/null +++ b/riscv.sc/src/sysc/clint.cpp @@ -0,0 +1,95 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 eyck@minres.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +//////////////////////////////////////////////////////////////////////////////// + +#include "sysc/SiFive/clint.h" +#include "sysc/SiFive/gen/clint_regs.h" +#include "sysc/utilities.h" + +namespace sysc { + +const int lfclk_mutiplier = 1 << 12; + +clint::clint(sc_core::sc_module_name nm) +: sc_core::sc_module(nm) +, tlm_target<>(clk) +, NAMED(clk_i) +, NAMED(rst_i) +, NAMED(mtime_int_o) +, NAMED(msip_int_o) +, NAMEDD(clint_regs, regs) +, cnt_fraction(0) { + regs->registerResources(*this); + SC_METHOD(clock_cb); + sensitive << clk_i; + SC_METHOD(reset_cb); + sensitive << rst_i; + dont_initialize(); + regs->mtimecmp.set_write_cb([this](sc_register ®, uint64_t data) -> bool { + if (!regs->in_reset()) { + reg.put(data); + this->update_mtime(); + } + return true; + }); + regs->mtime.set_read_cb([this](const sc_register ®, uint64_t &data) -> bool { + this->update_mtime(); + data = reg.get(); + return true; + }); + regs->mtime.set_write_cb([this](sc_register ®, uint64_t data) -> bool { return false; }); + regs->msip.set_write_cb([this](sc_register ®, uint32_t data) -> bool { + reg.put(data); + msip_int_o.write(regs->r_msip.msip); + return true; + }); + SC_METHOD(update_mtime); + sensitive << mtime_evt; + dont_initialize(); +} + +void clint::clock_cb() { + update_mtime(); + clk = clk_i.read(); + update_mtime(); +} + +clint::~clint() {} + +void clint::reset_cb() { + if (rst_i.read()) { + regs->reset_start(); + msip_int_o.write(false); + mtime_int_o.write(false); + cnt_fraction = 0; + } else + regs->reset_stop(); +} + +void clint::update_mtime() { + auto diff = (sc_time_stamp() - last_updt) / clk; + auto diffi = (int)diff; + regs->r_mtime += (diffi + cnt_fraction) / lfclk_mutiplier; + cnt_fraction = (cnt_fraction + diffi) % lfclk_mutiplier; + mtime_evt.cancel(); + if (regs->r_mtimecmp > regs->r_mtime && clk > SC_ZERO_TIME) { + sc_core::sc_time next_trigger = (clk * lfclk_mutiplier) * (regs->r_mtimecmp - regs->mtime) - cnt_fraction * clk; + mtime_evt.notify(next_trigger); + } else + mtime_int_o.write(true); + last_updt = sc_time_stamp(); +} + +} /* namespace sysc */ diff --git a/riscv.sc/src/sysc/core_complex.cpp b/riscv.sc/src/sysc/core_complex.cpp index 757e08b..8996316 100644 --- a/riscv.sc/src/sysc/core_complex.cpp +++ b/riscv.sc/src/sysc/core_complex.cpp @@ -34,16 +34,222 @@ // //////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include #include +#include namespace sysc { namespace SiFive { +class core_wrapper : public iss::arch::riscv_hart_msu_vp { +public: + using core_type = iss::arch::rv32imac; + using base_type = iss::arch::riscv_hart_msu_vp; + using phys_addr_t = typename iss::arch::traits::phys_addr_t; + core_wrapper(core_complex *owner) + : owner(owner) {} + + void notify_phase(iss::arch_if::exec_phase phase); + + iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data) { + if (addr.type & iss::DEBUG) + return owner->read_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err; + else + return owner->read_mem(addr.val, length, data) ? iss::Ok : iss::Err; + } + + iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data) { + if (addr.type & iss::DEBUG) + return owner->write_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err; + else + return owner->write_mem(addr.val, length, data) ? iss::Ok : iss::Err; + } + +private: + core_complex *const owner; +}; + +void core_wrapper::notify_phase(exec_phase phase) { + core_type::notify_phase(phase); + if (phase == ISTART) owner->sync(); +} + core_complex::core_complex(sc_core::sc_module_name name) : sc_core::sc_module(name) , NAMED(initiator) -, NAMED(rst_i) { - // TODO Auto-generated constructor stub +, NAMED(clk_i) +, NAMED(rst_i) +, NAMED(elf_file, this) +, NAMED(enable_disass, true, this) +, NAMED(reset_address, 0ULL, this) +, NAMED(gdb_server_port, 0, this) +, NAMED(dump_ir, false, this) +, read_lut(tlm_dmi_ext()) +, write_lut(tlm_dmi_ext()) { + + initiator.register_invalidate_direct_mem_ptr([=](uint64_t start, uint64_t end) -> void { + 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) { + read_lut.removeEntry(lut_entry); + } + lut_entry = write_lut.getEntry(start); + if (lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && end <= lut_entry.get_end_address() + 1) { + write_lut.removeEntry(lut_entry); + } + }); + + SC_THREAD(run); + SC_METHOD(clk_cb); + sensitive << clk_i; +} + +core_complex::~core_complex() = default; + +void core_complex::trace(sc_core::sc_trace_file *trf) {} + +void core_complex::before_end_of_elaboration() { + cpu = std::make_unique(this); + vm = iss::create(cpu.get(), gdb_server_port.value, dump_ir.value); + vm->setDisassEnabled(enable_disass.value); +} + +void core_complex::start_of_simulation() { + quantum_keeper.reset(); + if (elf_file.value.size() > 0) cpu->load_file(elf_file.value); +} + +void core_complex::clk_cb() { curr_clk = clk_i.read(); } + +void core_complex::run() { + wait(sc_core::SC_ZERO_TIME); + cpu->reset(reset_address.value); + try { + vm->start(-1); + } catch (iss::simulation_stopped &e) { + } + sc_core::sc_stop(); +} + +bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data) { + auto lut_entry = read_lut.getEntry(addr); + if (lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && + addr + length <= lut_entry.get_end_address() + 1) { + auto offset = addr - lut_entry.get_start_address(); + std::copy(lut_entry.get_dmi_ptr() + offset, lut_entry.get_dmi_ptr() + offset + length, data); + quantum_keeper.inc(lut_entry.get_read_latency()); + return true; + } else { + tlm::tlm_generic_payload gp; + gp.set_command(tlm::TLM_READ_COMMAND); + gp.set_address(addr); + gp.set_data_ptr(data); + gp.set_data_length(length); + gp.set_streaming_width(4); + auto delay{quantum_keeper.get_local_time()}; + initiator->b_transport(gp, delay); + LOG(TRACE) << "read_mem(0x" << std::hex << addr << ") : " << data; + if (gp.get_response_status() != tlm::TLM_OK_RESPONSE) { + return false; + } + if (gp.is_dmi_allowed()) { + gp.set_command(tlm::TLM_READ_COMMAND); + gp.set_address(addr); + tlm_dmi_ext dmi_data; + if (initiator->get_direct_mem_ptr(gp, dmi_data)) { + if (dmi_data.is_read_allowed()) + read_lut.addEntry(dmi_data, dmi_data.get_start_address(), + dmi_data.get_end_address() - dmi_data.get_start_address() + 1); + if (dmi_data.is_write_allowed()) + write_lut.addEntry(dmi_data, dmi_data.get_start_address(), + dmi_data.get_end_address() - dmi_data.get_start_address() + 1); + } + } + return true; + } +} + +bool core_complex::write_mem(uint64_t addr, unsigned length, const uint8_t *const data) { + auto lut_entry = write_lut.getEntry(addr); + if (lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && + addr + length <= lut_entry.get_end_address() + 1) { + auto offset = addr - lut_entry.get_start_address(); + std::copy(data, data + length, lut_entry.get_dmi_ptr() + offset); + quantum_keeper.inc(lut_entry.get_read_latency()); + return true; + } else { + write_buf.resize(length); + std::copy(data, data + length, write_buf.begin()); // need to copy as TLM does not guarantee data integrity + tlm::tlm_generic_payload gp; + gp.set_command(tlm::TLM_WRITE_COMMAND); + gp.set_address(addr); + gp.set_data_ptr(write_buf.data()); + gp.set_data_length(length); + gp.set_streaming_width(4); + auto delay{quantum_keeper.get_local_time()}; + initiator->b_transport(gp, delay); + quantum_keeper.set(delay); + LOG(TRACE) << "write_mem(0x" << std::hex << addr << ") : " << data; + if (gp.get_response_status() != tlm::TLM_OK_RESPONSE) { + return false; + } + if (gp.is_dmi_allowed()) { + gp.set_command(tlm::TLM_READ_COMMAND); + gp.set_address(addr); + tlm_dmi_ext dmi_data; + if (initiator->get_direct_mem_ptr(gp, dmi_data)) { + if (dmi_data.is_read_allowed()) + read_lut.addEntry(dmi_data, dmi_data.get_start_address(), + dmi_data.get_end_address() - dmi_data.get_start_address() + 1); + if (dmi_data.is_write_allowed()) + write_lut.addEntry(dmi_data, dmi_data.get_start_address(), + dmi_data.get_end_address() - dmi_data.get_start_address() + 1); + } + } + return true; + } +} + +bool core_complex::read_mem_dbg(uint64_t addr, unsigned length, uint8_t *const data) { + auto lut_entry = read_lut.getEntry(addr); + if (lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && + addr + length <= lut_entry.get_end_address() + 1) { + auto offset = addr - lut_entry.get_start_address(); + std::copy(lut_entry.get_dmi_ptr() + offset, lut_entry.get_dmi_ptr() + offset + length, data); + quantum_keeper.inc(lut_entry.get_read_latency()); + return true; + } else { + tlm::tlm_generic_payload gp; + gp.set_command(tlm::TLM_READ_COMMAND); + gp.set_address(addr); + gp.set_data_ptr(data); + gp.set_data_length(length); + gp.set_streaming_width(length); + return initiator->transport_dbg(gp) == length; + } +} + +bool core_complex::write_mem_dbg(uint64_t addr, unsigned length, const uint8_t *const data) { + auto lut_entry = write_lut.getEntry(addr); + if (lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && + addr + length <= lut_entry.get_end_address() + 1) { + auto offset = addr - lut_entry.get_start_address(); + std::copy(data, data + length, lut_entry.get_dmi_ptr() + offset); + quantum_keeper.inc(lut_entry.get_read_latency()); + return true; + } else { + write_buf.resize(length); + std::copy(data, data + length, write_buf.begin()); // need to copy as TLM does not guarantee data integrity + tlm::tlm_generic_payload gp; + gp.set_command(tlm::TLM_WRITE_COMMAND); + gp.set_address(addr); + gp.set_data_ptr(write_buf.data()); + gp.set_data_length(length); + gp.set_streaming_width(length); + return initiator->transport_dbg(gp) == length; + } } } /* namespace SiFive */ diff --git a/riscv.sc/src/sysc/gpio.cpp b/riscv.sc/src/sysc/gpio.cpp index eb625bb..4236b1a 100644 --- a/riscv.sc/src/sysc/gpio.cpp +++ b/riscv.sc/src/sysc/gpio.cpp @@ -31,6 +31,7 @@ gpio::gpio(sc_core::sc_module_name nm) sensitive << clk_i; SC_METHOD(reset_cb); sensitive << rst_i; + dont_initialize(); } void gpio::clock_cb() {} diff --git a/riscv.sc/src/sysc/platform.cpp b/riscv.sc/src/sysc/platform.cpp index e3a308c..5471f63 100644 --- a/riscv.sc/src/sysc/platform.cpp +++ b/riscv.sc/src/sysc/platform.cpp @@ -26,37 +26,60 @@ namespace sysc { platform::platform(sc_core::sc_module_name nm) : sc_core::sc_module(nm) -, NAMED(i_master) -, NAMED(i_router, 4, 1) -, NAMED(i_uart) +, NAMED(i_core_complex) +, NAMED(i_router, 10, 1) +, NAMED(i_uart0) +, NAMED(i_uart1) , NAMED(i_spi) , NAMED(i_gpio) , NAMED(i_plic) +, NAMED(i_aon) +, NAMED(i_prci) +, NAMED(i_clint) +, NAMED(i_mem_qspi) +, NAMED(i_mem_ram) , NAMED(s_clk) , NAMED(s_rst) { - i_master.initiator(i_router.target[0]); + i_core_complex.initiator(i_router.target[0]); size_t i = 0; for (const auto &e : e300_plat_map) { i_router.initiator.at(i)(e.target->socket); i_router.add_target_range(i, e.start, e.size); i++; } - i_uart.clk_i(s_clk); + i_router.initiator.at(i)(i_mem_qspi.target); + i_router.add_target_range(i, 0x20000000, 512_MB); + i_router.initiator.at(++i)(i_mem_ram.target); + i_router.add_target_range(i, 0x80000000, 128_kB); + + i_uart0.clk_i(s_clk); + i_uart1.clk_i(s_clk); i_spi.clk_i(s_clk); i_gpio.clk_i(s_clk); i_plic.clk_i(s_clk); - s_clk.write(10_ns); + i_aon.clk_i(s_clk); + i_prci.clk_i(s_clk); + i_clint.clk_i(s_clk); + i_core_complex.clk_i(s_clk); - i_uart.rst_i(s_rst); + i_uart0.rst_i(s_rst); + i_uart1.rst_i(s_rst); i_spi.rst_i(s_rst); i_gpio.rst_i(s_rst); i_plic.rst_i(s_rst); - i_master.rst_i(s_rst); + i_aon.rst_i(s_rst); + i_prci.rst_i(s_rst); + i_clint.rst_i(s_rst); + i_core_complex.rst_i(s_rst); + + i_clint.mtime_int_o(s_mtime_int); + i_clint.msip_int_o(s_msie_int); SC_THREAD(gen_reset); } void platform::gen_reset() { + s_clk = 10_ns; s_rst = true; wait(10_ns); s_rst = false; diff --git a/riscv.sc/src/sysc/plic.cpp b/riscv.sc/src/sysc/plic.cpp index fe1a006..4e0d33e 100644 --- a/riscv.sc/src/sysc/plic.cpp +++ b/riscv.sc/src/sysc/plic.cpp @@ -31,6 +31,7 @@ plic::plic(sc_core::sc_module_name nm) sensitive << clk_i; SC_METHOD(reset_cb); sensitive << rst_i; + dont_initialize(); } plic::~plic() {} diff --git a/riscv.sc/src/sysc/prci.cpp b/riscv.sc/src/sysc/prci.cpp new file mode 100644 index 0000000..2e77656 --- /dev/null +++ b/riscv.sc/src/sysc/prci.cpp @@ -0,0 +1,71 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2017 eyck@minres.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +//////////////////////////////////////////////////////////////////////////////// + +#include "sysc/SiFive/prci.h" +#include "sysc/SiFive/gen/prci_regs.h" +#include "sysc/utilities.h" + +namespace sysc { + +prci::prci(sc_core::sc_module_name nm) +: sc_core::sc_module(nm) +, tlm_target<>(clk) +, NAMED(clk_i) +, NAMED(rst_i) +, NAMEDD(prci_regs, regs) { + regs->registerResources(*this); + SC_METHOD(clock_cb); + sensitive << clk_i; + SC_METHOD(reset_cb); + sensitive << rst_i; + dont_initialize(); + SC_METHOD(hfrosc_en_cb); + sensitive << hfrosc_en_evt; + dont_initialize(); + + regs->hfrosccfg.set_write_cb([this](sysc::sc_register ®, uint32_t data) -> bool { + reg.put(data); + if (this->regs->r_hfrosccfg & (1 << 30)) { // check rosc_en + this->hfrosc_en_evt.notify(1, sc_core::SC_US); + } + return true; + }); + regs->pllcfg.set_write_cb([this](sysc::sc_register ®, uint32_t data) -> bool { + reg.put(data); + auto &pllcfg = this->regs->r_pllcfg; + if (pllcfg.pllbypass == 0 && pllcfg.pllq != 0) { // set pll_lock if pll is selected + pllcfg.plllock = 1; + } + return true; + }); +} + +void prci::clock_cb() {} + +prci::~prci() {} + +void prci::reset_cb() { + if (rst_i.read()) + regs->reset_start(); + else + regs->reset_stop(); +} + +void prci::hfrosc_en_cb() { + regs->r_hfrosccfg |= (1 << 31); // set rosc_rdy +} + +} /* namespace sysc */ diff --git a/riscv.sc/src/sysc/spi.cpp b/riscv.sc/src/sysc/spi.cpp index 1ddd1a6..bda7942 100644 --- a/riscv.sc/src/sysc/spi.cpp +++ b/riscv.sc/src/sysc/spi.cpp @@ -31,6 +31,7 @@ spi::spi(sc_core::sc_module_name nm) sensitive << clk_i; SC_METHOD(reset_cb); sensitive << rst_i; + dont_initialize(); } spi::~spi() {} diff --git a/riscv.sc/src/sysc/uart.cpp b/riscv.sc/src/sysc/uart.cpp index 7888c90..eef2758 100644 --- a/riscv.sc/src/sysc/uart.cpp +++ b/riscv.sc/src/sysc/uart.cpp @@ -16,6 +16,7 @@ #include "sysc/SiFive/uart.h" #include "sysc/SiFive/gen/uart_regs.h" +#include "sysc/report.h" #include "sysc/utilities.h" namespace sysc { @@ -31,6 +32,14 @@ uart::uart(sc_core::sc_module_name nm) sensitive << clk_i; SC_METHOD(reset_cb); sensitive << rst_i; + dont_initialize(); + regs->txdata.set_write_cb([this](sc_register ®, uint32_t data) -> bool { + if (!this->regs->in_reset()) { + reg.put(data); + this->transmit_data(); + } + return true; + }); } uart::~uart() {} @@ -44,4 +53,13 @@ void uart::reset_cb() { regs->reset_stop(); } +void uart::transmit_data() { + if (queue.size() >> 0 && (regs->r_txdata.data == '\n' || regs->r_txdata.data == 0)) { + LOG(INFO) << this->name() << " transmit: '" << std::string(queue.begin(), queue.end()) << "'"; + queue.clear(); + } else { + queue.push_back(regs->r_txdata.data); + } +} + } /* namespace sysc */ diff --git a/riscv/incl/cli_options.h b/riscv/incl/cli_options.h deleted file mode 100644 index cb32c73..0000000 --- a/riscv/incl/cli_options.h +++ /dev/null @@ -1,81 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017, 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 API and implementation - ******************************************************************************/ - -#ifndef _CLI_OPTIONS_H_ -#define _CLI_OPTIONS_H_ -#include -#include -#include -#include - -const size_t ERROR_IN_COMMAND_LINE = 1; -const size_t SUCCESS = 0; -const size_t ERROR_UNHANDLED_EXCEPTION = 2; - -inline int parse_cli_options(boost::program_options::variables_map &vm, int argc, char *argv[]) { - namespace po = boost::program_options; - po::options_description desc("Options"); - desc.add_options()("help,h", "Print help message")("verbose,v", po::value()->implicit_value(0), - "Sets logging verbosity")("vmodule", po::value(), - "Defines the module(s) to be logged")( - "logging-flags", po::value(), "Sets logging flag(s).")("log-file", po::value(), - "Sets default log file.")( - "disass,d", po::value()->implicit_value(""), - "Enables disassembly")("elf,l", po::value>(), "ELF file(s) to load")( - "gdb-port,g", po::value(), "enable gdb server and specify port to use")( - "input,i", po::value(), "the elf file to load (instead of hex files)")( - "dump-ir", "dump the intermediate representation")("cycles,c", po::value()->default_value(-1), - "number of cycles to run")( - "systemc,s", "Run as SystemC simulation")("time", po::value(), "SystemC siimulation time in ms")( - "reset,r", po::value(), "reset address")( - "trace", po::value(), "enable tracing, or cmbintation of 1=signals and 2=TX text, 4=TX " - "compressed text, 6=TX in SQLite")("mem,m", po::value(), - "the memory input file")("rv64", "run RV64"); - try { - po::store(po::parse_command_line(argc, argv, desc), vm); // can throw - // --help option - if (vm.count("help")) { - std::cout << "DBT-RISE-RiscV" << std::endl << desc << std::endl; - return SUCCESS; - } - po::notify(vm); // throws on error, so do after help in case - } catch (po::error &e) { - // there are problems - std::cerr << "ERROR: " << e.what() << std::endl << std::endl; - std::cerr << desc << std::endl; - return ERROR_IN_COMMAND_LINE; - } - return SUCCESS; -} -#endif /* _CLI_OPTIONS_H_ */ diff --git a/riscv/incl/iss/arch/riscv_hart_msu_vp.h b/riscv/incl/iss/arch/riscv_hart_msu_vp.h index 8c201d4..abdf585 100644 --- a/riscv/incl/iss/arch/riscv_hart_msu_vp.h +++ b/riscv/incl/iss/arch/riscv_hart_msu_vp.h @@ -431,7 +431,7 @@ template struct riscv_hart_msu_vp : public BASE { riscv_hart_msu_vp(); virtual ~riscv_hart_msu_vp() = default; - virtual void load_file(std::string name, int type = -1); + void load_file(std::string name, int type = -1) override; virtual phys_addr_t v2p(const iss::addr_t &addr); @@ -550,9 +550,12 @@ template void riscv_hart_msu_vp::load_file(std::string nam const auto fsize = pseg->get_file_size(); // 0x42c/0x0 const auto seg_data = pseg->get_data(); if (fsize > 0) { - this->write( - typed_addr_t(iss::DEBUG_WRITE, traits::MEM, pseg->get_virtual_address()), fsize, - reinterpret_cast(seg_data)); + auto res = this->write( + typed_addr_t(iss::DEBUG_WRITE, traits::MEM, pseg->get_physical_address()), + fsize, reinterpret_cast(seg_data)); + if (res != iss::Ok) + LOG(ERROR) << "problem writing " << fsize << "bytes to 0x" << std::hex + << pseg->get_physical_address(); } } for (const auto sec : reader.sections) { @@ -596,20 +599,9 @@ iss::status riscv_hart_msu_vp::read(const iss::addr_t &addr, unsigned leng } } phys_addr_t paddr = (addr.type & iss::ADDRESS_TYPE) == iss::PHYSICAL ? addr : v2p(addr); - if ((paddr.val + length) > mem.size()) return iss::Err; - switch (paddr.val) { - case 0x0200BFF8: { // CLINT base, mtime reg - uint64_t mtime = this->reg.icount >> 12 /*12*/; - std::copy((uint8_t *)&mtime, ((uint8_t *)&mtime) + length, data); - } break; - case 0x10008000: { - const mem_type::page_type &p = mem(paddr.val / mem.page_size); - uint64_t offs = paddr.val & mem.page_addr_mask; - std::copy(p.data() + offs, p.data() + offs + length, data); - if (this->reg.icount > 30000) data[3] |= 0x80; - } break; - default: { return read_mem(paddr, length, data); } - } + auto res = read_mem(paddr, length, data); + if (res != iss::Ok) this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault + return res; } catch (trap_access &ta) { this->reg.trap_state = (1 << 31) | ta.id; return iss::Err; @@ -677,6 +669,33 @@ iss::status riscv_hart_msu_vp::write(const iss::addr_t &addr, unsigned len try { switch (addr.space) { case traits::MEM: { + if ((addr.type & (iss::ACCESS_TYPE - iss::DEBUG)) == iss::FETCH && (addr.val & 0x1) == 1) { + fault_data = addr.val; + if ((addr.type & iss::DEBUG)) throw trap_access(0, addr.val); + this->reg.trap_state = (1 << 31); // issue trap 0 + return iss::Err; + } + try { + if ((addr.val & ~PGMASK) != ((addr.val + length - 1) & ~PGMASK)) { // we may cross a page boundary + vm_info vm = decode_vm_info::XLEN>(this->reg.machine_state, csr[satp]); + if (vm.levels != 0) { // VM is active + auto split_addr = (addr.val + length) & ~PGMASK; + auto len1 = split_addr - addr.val; + auto res = write(addr, len1, data); + if (res == iss::Ok) + res = write(iss::addr_t{addr.type, addr.space, split_addr}, length - len1, data + len1); + return res; + } + } + phys_addr_t paddr = (addr.type & iss::ADDRESS_TYPE) == iss::PHYSICAL ? addr : v2p(addr); + auto res = write_mem(paddr, length, data); + if (res != iss::Ok) this->reg.trap_state = (1 << 31) | (7 << 16); // issue trap 7 (load access fault + return res; + } catch (trap_access &ta) { + this->reg.trap_state = (1 << 31) | ta.id; + return iss::Err; + } + phys_addr_t paddr = (addr.type & iss::ADDRESS_TYPE) == iss::PHYSICAL ? addr : v2p(addr); if ((paddr.val + length) > mem.size()) return iss::Err; switch (paddr.val) { @@ -691,22 +710,22 @@ iss::status riscv_hart_msu_vp::write(const iss::addr_t &addr, unsigned len } return iss::Ok; case 0x10008000: { // HFROSC base, hfrosccfg reg - mem_type::page_type &p = mem(paddr.val / mem.page_size); - size_t offs = paddr.val & mem.page_addr_mask; + auto &p = mem(paddr.val / mem.page_size); + auto offs = paddr.val & mem.page_addr_mask; std::copy(data, data + length, p.data() + offs); - uint8_t &x = *(p.data() + offs + 3); + 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 - mem_type::page_type &p = mem(paddr.val / mem.page_size); - size_t offs = paddr.val & mem.page_addr_mask; + auto &p = mem(paddr.val / mem.page_size); + auto offs = paddr.val & mem.page_addr_mask; std::copy(data, data + length, p.data() + offs); - uint8_t &x = *(p.data() + offs + 3); + auto &x = *(p.data() + offs + 3); x |= 0x80; // set pll lock upon writing return iss::Ok; } break; - default: { return write_mem(paddr, length, data); } + default: {} } } break; case traits::CSR: { @@ -857,56 +876,102 @@ template iss::status riscv_hart_msu_vp::write_satp(unsigne } template -iss::status riscv_hart_msu_vp::read_mem(phys_addr_t addr, unsigned length, uint8_t *const data) { - const auto &p = mem(addr.val / mem.page_size); - auto offs = addr.val & mem.page_addr_mask; - std::copy(p.data() + offs, p.data() + offs + length, data); - return iss::Ok; +iss::status riscv_hart_msu_vp::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { + if ((paddr.val + length) > mem.size()) return iss::Err; + switch (paddr.val) { + case 0x0200BFF8: { // CLINT base, mtime reg + uint64_t mtime = this->reg.icount >> 12 /*12*/; + std::copy((uint8_t *)&mtime, ((uint8_t *)&mtime) + length, data); + } break; + case 0x10008000: { + const mem_type::page_type &p = mem(paddr.val / mem.page_size); + uint64_t offs = paddr.val & mem.page_addr_mask; + std::copy(p.data() + offs, p.data() + offs + length, data); + if (this->reg.icount > 30000) data[3] |= 0x80; + } break; + default: { + const auto &p = mem(paddr.val / mem.page_size); + auto offs = paddr.val & mem.page_addr_mask; + std::copy(p.data() + offs, p.data() + offs + length, data); + return iss::Ok; + } + } } template -iss::status riscv_hart_msu_vp::write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data) { - mem_type::page_type &p = mem(addr.val / mem.page_size); - std::copy(data, data + length, p.data() + (addr.val & mem.page_addr_mask)); - // tohost handling in case of riscv-test - if ((addr.type & iss::DEBUG) == 0) { - auto tohost_upper = - (traits::XLEN == 32 && addr.val == (tohost + 4)) || (traits::XLEN == 64 && addr.val == tohost); - auto tohost_lower = - (traits::XLEN == 32 && addr.val == tohost) || (traits::XLEN == 64 && addr.val == tohost); - if (tohost_lower || tohost_upper) { - uint64_t hostvar = *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)); - if (tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) { - switch (hostvar >> 48) { - case 0: - if (hostvar != 0x1) - LOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar - << "), stopping simulation"; - else - LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar - << "), stopping simulation"; - throw(iss::simulation_stopped(hostvar)); - case 0x0101: { - char c = static_cast(hostvar & 0xff); - if (c == '\n' || c == 0) { - LOG(INFO) << "tohost send '" << uart_buf.str() << "'"; - uart_buf.str(""); - } else - uart_buf << c; - to_host_wr_cnt = 0; - } break; - default: - break; - } - } else if (tohost_lower) - to_host_wr_cnt++; - } else if ((traits::XLEN == 32 && addr.val == fromhost + 4) || - (traits::XLEN == 64 && addr.val == fromhost)) { - uint64_t fhostvar = *reinterpret_cast(p.data() + (fromhost & mem.page_addr_mask)); - *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)) = fhostvar; +iss::status riscv_hart_msu_vp::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { + if ((paddr.val + length) > mem.size()) return iss::Err; + switch (paddr.val) { + 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 + // '"<::XLEN == 32 && paddr.val == (tohost + 4)) || + (traits::XLEN == 64 && paddr.val == tohost); + auto tohost_lower = + (traits::XLEN == 32 && paddr.val == tohost) || (traits::XLEN == 64 && paddr.val == tohost); + if (tohost_lower || tohost_upper) { + uint64_t hostvar = *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)); + if (tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) { + switch (hostvar >> 48) { + case 0: + if (hostvar != 0x1) + LOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar + << "), stopping simulation"; + else + LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar + << "), stopping simulation"; + throw(iss::simulation_stopped(hostvar)); + case 0x0101: { + char c = static_cast(hostvar & 0xff); + if (c == '\n' || c == 0) { + LOG(INFO) << "tohost send '" << uart_buf.str() << "'"; + uart_buf.str(""); + } else + uart_buf << c; + to_host_wr_cnt = 0; + } break; + default: + break; + } + } else if (tohost_lower) + to_host_wr_cnt++; + } else if ((traits::XLEN == 32 && paddr.val == fromhost + 4) || + (traits::XLEN == 64 && paddr.val == fromhost)) { + uint64_t fhostvar = *reinterpret_cast(p.data() + (fromhost & mem.page_addr_mask)); + *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)) = fhostvar; + } + } + return iss::Ok; + } } - return iss::Ok; } template void riscv_hart_msu_vp::check_interrupt() { diff --git a/riscv/incl/iss/arch/rv32imac.h b/riscv/incl/iss/arch/rv32imac.h index df99839..607e5ad 100644 --- a/riscv/incl/iss/arch/rv32imac.h +++ b/riscv/incl/iss/arch/rv32imac.h @@ -140,7 +140,7 @@ struct rv32imac : public arch_if { using addr_t = typename traits::addr_t; rv32imac(); - ~rv32imac(); + ~rv32imac() = default; void reset(uint64_t address = 0) override; @@ -154,7 +154,7 @@ struct rv32imac : public arch_if { /// deprecated void update_flags(operations op, uint64_t opr1, uint64_t opr2) override{}; - void notify_phase(exec_phase phase) { + void notify_phase(exec_phase phase) override { if (phase == ISTART) { ++reg.icount; reg.PC = reg.NEXT_PC; diff --git a/riscv/src/internal/vm_riscv.in.cpp b/riscv/src/internal/vm_riscv.in.cpp index ef5008a..a5d6057 100644 --- a/riscv/src/internal/vm_riscv.in.cpp +++ b/riscv/src/internal/vm_riscv.in.cpp @@ -342,21 +342,8 @@ template <> std::unique_ptr create(arch::CORE_DEF_NAME *core, unsigned short port, bool dump) { std::unique_ptr> ret = std::make_unique>(*core, dump); - debugger::server::run_server(ret.get(), port); + if (port != 0) debugger::server::run_server(ret.get(), port); return ret; } -template <> std::unique_ptr create(std::string inst_name, unsigned short port, bool dump) { - return create(new arch::riscv_hart_msu_vp(), port, - dump); /* FIXME: memory leak!!!!!!! */ -} - -template <> std::unique_ptr create(arch::CORE_DEF_NAME *core, bool dump) { - return std::make_unique>(*core, dump); /* FIXME: memory leak!!!!!!! */ -} - -template <> std::unique_ptr create(std::string inst_name, bool dump) { - return create(new arch::riscv_hart_msu_vp(), dump); -} - } // namespace iss diff --git a/riscv/src/internal/vm_rv32imac.cpp b/riscv/src/internal/vm_rv32imac.cpp index 949fc4f..088d903 100644 --- a/riscv/src/internal/vm_rv32imac.cpp +++ b/riscv/src/internal/vm_rv32imac.cpp @@ -4014,21 +4014,8 @@ template inline void vm_impl::gen_trap_check(llvm::BasicBl template <> std::unique_ptr create(arch::rv32imac *core, unsigned short port, bool dump) { std::unique_ptr> ret = std::make_unique>(*core, dump); - debugger::server::run_server(ret.get(), port); + if (port != 0) debugger::server::run_server(ret.get(), port); return ret; } -template <> std::unique_ptr create(std::string inst_name, unsigned short port, bool dump) { - return create(new arch::riscv_hart_msu_vp(), port, - dump); /* FIXME: memory leak!!!!!!! */ -} - -template <> std::unique_ptr create(arch::rv32imac *core, bool dump) { - return std::make_unique>(*core, dump); /* FIXME: memory leak!!!!!!! */ -} - -template <> std::unique_ptr create(std::string inst_name, bool dump) { - return create(new arch::riscv_hart_msu_vp(), dump); -} - } // namespace iss diff --git a/riscv/src/internal/vm_rv64ia.cpp b/riscv/src/internal/vm_rv64ia.cpp index 1262182..dc6bffa 100644 --- a/riscv/src/internal/vm_rv64ia.cpp +++ b/riscv/src/internal/vm_rv64ia.cpp @@ -3101,21 +3101,8 @@ template inline void vm_impl::gen_trap_check(llvm::BasicBl template <> std::unique_ptr create(arch::rv64ia *core, unsigned short port, bool dump) { std::unique_ptr> ret = std::make_unique>(*core, dump); - debugger::server::run_server(ret.get(), port); + if (port != 0) debugger::server::run_server(ret.get(), port); return ret; } -template <> std::unique_ptr create(std::string inst_name, unsigned short port, bool dump) { - return create(new arch::riscv_hart_msu_vp(), port, - dump); /* FIXME: memory leak!!!!!!! */ -} - -template <> std::unique_ptr create(arch::rv64ia *core, bool dump) { - return std::make_unique>(*core, dump); /* FIXME: memory leak!!!!!!! */ -} - -template <> std::unique_ptr create(std::string inst_name, bool dump) { - return create(new arch::riscv_hart_msu_vp(), dump); -} - } // namespace iss diff --git a/riscv/src/iss/rv32imac.cpp b/riscv/src/iss/rv32imac.cpp index 667450c..677b4f4 100644 --- a/riscv/src/iss/rv32imac.cpp +++ b/riscv/src/iss/rv32imac.cpp @@ -54,8 +54,6 @@ using namespace iss::arch; rv32imac::rv32imac() { reg.icount = 0; } -rv32imac::~rv32imac() {} - void rv32imac::reset(uint64_t address) { for (size_t i = 0; i < traits::NUM_REGS; ++i) set_reg(i, std::vector(sizeof(traits::reg_t), 0)); diff --git a/riscv/src/main.cpp b/riscv/src/main.cpp index 75a6a97..c21cc03 100644 --- a/riscv/src/main.cpp +++ b/riscv/src/main.cpp @@ -32,11 +32,12 @@ // eyck@minres.com - initial API and implementation //////////////////////////////////////////////////////////////////////////////// -#include #include #include #include +#include +#include #include #include #include @@ -45,69 +46,97 @@ namespace po = boost::program_options; int main(int argc, char *argv[]) { + /* + * Define and parse the program options + */ + po::variables_map clim; + po::options_description desc("Options"); + // clang-format off + desc.add_options() + ("help,h", "Print help message") + ("verbose,v", po::value()->implicit_value(0), "Sets logging verbosity") + ("log-file", po::value(), "Sets default log file.") + ("disass,d", po::value()->implicit_value(""), "Enables disassembly") + ("elf,l", po::value>(), "ELF file(s) to load") + ("gdb-port,g", po::value()->default_value(0), "enable gdb server and specify port to use") + ("input,i", po::value(), "the elf file to load (instead of hex files)") + ("dump-ir", "dump the intermediate representation") + ("cycles,c", po::value()->default_value(-1), "number of cycles to run") + ("systemc,s", "Run as SystemC simulation") + ("time", po::value(), "SystemC siimulation time in ms") + ("reset,r", po::value(), "reset address") + ("trace", po::value(), "enable tracing, or cmbintation of 1=signals and 2=TX text, 4=TX compressed text, 6=TX in SQLite") + ("mem,m", po::value(), "the memory input file") + ("rv64", "run RV64"); + // clang-format on try { - /* - * Define and parse the program options - */ - po::variables_map vm; - if (parse_cli_options(vm, argc, argv)) return ERROR_IN_COMMAND_LINE; - if (vm.count("verbose")) { - auto l = logging::as_log_level(vm["verbose"].as()); - LOGGER(DEFAULT)::reporting_level() = l; - LOGGER(connection)::reporting_level() = l; - } - if (vm.count("log-file")) { - // configure the connection logger - auto f = fopen(vm["log-file"].as().c_str(), "w"); - LOG_OUTPUT(DEFAULT)::stream() = f; - LOG_OUTPUT(connection)::stream() = f; + po::store(po::parse_command_line(argc, argv, desc), clim); // can throw + // --help option + if (clim.count("help")) { + std::cout << "DBT-RISE-RiscV simulator for RISC-V" << std::endl << desc << std::endl; + return 0; } + po::notify(clim); // throws on error, so do after help in case + } catch (po::error &e) { + // there are problems + std::cerr << "ERROR: " << e.what() << std::endl << std::endl; + std::cerr << desc << std::endl; + return 1; + } + if (clim.count("verbose")) { + auto l = logging::as_log_level(clim["verbose"].as()); + LOGGER(DEFAULT)::reporting_level() = l; + LOGGER(connection)::reporting_level() = l; + } + if (clim.count("log-file")) { + // configure the connection logger + auto f = fopen(clim["log-file"].as().c_str(), "w"); + LOG_OUTPUT(DEFAULT)::stream() = f; + LOG_OUTPUT(connection)::stream() = f; + } + try { // application code comes here // iss::init_jit(argc, argv); - bool dump = vm.count("dump-ir"); + bool dump = clim.count("dump-ir"); // instantiate the simulator - std::unique_ptr cpu{nullptr}; - if (vm.count("rv64") == 1) { - if (vm.count("gdb-port") == 1) - cpu = iss::create("rv64ia", vm["gdb-port"].as(), dump); - else - cpu = iss::create("rv64ia", dump); + std::unique_ptr vm{nullptr}; + if (clim.count("rv64") == 1) { + auto cpu = new iss::arch::riscv_hart_msu_vp(); + vm = iss::create(cpu, clim["gdb-port"].as(), dump); } else { - if (vm.count("gdb-port") == 1) - cpu = iss::create("rv32ima", vm["gdb-port"].as(), dump); - else - cpu = iss::create("rv32ima", dump); + auto cpu = new iss::arch::riscv_hart_msu_vp(); + vm = iss::create(cpu, clim["gdb-port"].as(), dump); } - if (vm.count("elf")) { - for (std::string input : vm["elf"].as>()) cpu->get_arch()->load_file(input); - } else if (vm.count("mem")) { - cpu->get_arch()->load_file(vm["mem"].as(), iss::arch::traits::MEM); + if (clim.count("elf")) { + for (std::string input : clim["elf"].as>()) vm->get_arch()->load_file(input); + } else if (clim.count("mem")) { + vm->get_arch()->load_file(clim["mem"].as(), iss::arch::traits::MEM); } - if (vm.count("disass")) { - cpu->setDisassEnabled(true); + if (clim.count("disass")) { + vm->setDisassEnabled(true); LOGGER(disass)::reporting_level() = logging::INFO; - auto file_name = vm["disass"].as(); + auto file_name = clim["disass"].as(); if (file_name.length() > 0) { LOG_OUTPUT(disass)::stream() = fopen(file_name.c_str(), "w"); LOGGER(disass)::print_time() = false; LOGGER(disass)::print_severity() = false; } } - if (vm.count("reset")) { - auto str = vm["reset"].as(); - auto start_address = str.find("0x") == 0 ? std::stoull(str, 0, 16) : std::stoull(str, 0, 10); - cpu->reset(start_address); + if (clim.count("reset")) { + auto str = clim["reset"].as(); + auto start_address = str.find("0x") == 0 ? std::stoull(str.substr(2), 0, 16) : std::stoull(str, 0, 10); + vm->reset(start_address); } else { - cpu->reset(); + vm->reset(); } int64_t cycles = -1; - cycles = vm["cycles"].as(); - return cpu->start(cycles); + cycles = clim["cycles"].as(); + return vm->start(cycles); } catch (std::exception &e) { LOG(ERROR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" << std::endl; - return ERROR_UNHANDLED_EXCEPTION; + return 2; } } diff --git a/sc-components b/sc-components index 3693b05..35379b7 160000 --- a/sc-components +++ b/sc-components @@ -1 +1 @@ -Subproject commit 3693b0553602337f702753e208329d0e2a4f99c3 +Subproject commit 35379b77b6297557de15e37c009501dbdfc747f7