From a899d30556aadbeb6df6e61f168f4d1ba4fef54d Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 13 Jul 2018 20:04:07 +0200 Subject: [PATCH] Implemented basic HiFive1-like platform with PLL,tracing etc. --- dbt-core | 2 +- riscv.sc/incl/sysc/General/system.h | 7 +- riscv.sc/incl/sysc/SiFive/aon.h | 6 +- riscv.sc/incl/sysc/SiFive/core_complex.h | 1 + riscv.sc/incl/sysc/SiFive/gen/prci_regs.h | 2 +- riscv.sc/incl/sysc/SiFive/gpio.h | 5 ++ riscv.sc/incl/sysc/SiFive/platform.h | 2 + riscv.sc/incl/sysc/SiFive/prci.h | 11 ++- riscv.sc/src/CMakeLists.txt | 10 +-- riscv.sc/src/sc_main.cpp | 24 ++++-- riscv.sc/src/sysc/aon.cpp | 22 ++++-- riscv.sc/src/sysc/core_complex.cpp | 34 +++++++-- riscv.sc/src/sysc/gpio.cpp | 54 ++++++++++++-- riscv.sc/src/sysc/platform.cpp | 18 ++--- riscv.sc/src/sysc/prci.cpp | 74 ++++++++++++++++--- riscv.sc/src/sysc/system.cpp | 22 ++++-- riscv.sc/src/sysc/uart.cpp | 60 ++++++--------- riscv/gen_input/templates/incl-CORENAME.h.gtl | 1 + .../gen_input/templates/src-CORENAME.cpp.gtl | 12 +-- riscv/incl/iss/arch/rv32gc.h | 2 + riscv/incl/iss/arch/rv32imac.h | 5 ++ riscv/incl/iss/arch/rv64ia.h | 2 + riscv/src/iss/rv32gc.cpp | 1 + riscv/src/iss/rv64ia.cpp | 1 + sc-components | 2 +- 25 files changed, 268 insertions(+), 112 deletions(-) diff --git a/dbt-core b/dbt-core index 34abe11..31263d4 160000 --- a/dbt-core +++ b/dbt-core @@ -1 +1 @@ -Subproject commit 34abe11e782335ae02dd74a3e47ae8bb366abc25 +Subproject commit 31263d4aaa6a7f01914c2decead091dc968f30d3 diff --git a/riscv.sc/incl/sysc/General/system.h b/riscv.sc/incl/sysc/General/system.h index 9645762..07b72d9 100644 --- a/riscv.sc/incl/sysc/General/system.h +++ b/riscv.sc/incl/sysc/General/system.h @@ -16,14 +16,17 @@ namespace sysc { class system: sc_core::sc_module { public: + SC_HAS_PROCESS(system); + system(sc_core::sc_module_name nm); virtual ~system(); - sc_core::sc_vector> s_gpio; - private: + sc_core::sc_vector> s_gpio; + sc_core::sc_signal s_rst_n; sysc::platform i_platform; sysc::terminal i_terminal; + void gen_por(); }; } diff --git a/riscv.sc/incl/sysc/SiFive/aon.h b/riscv.sc/incl/sysc/SiFive/aon.h index 4173def..c695158 100644 --- a/riscv.sc/incl/sysc/SiFive/aon.h +++ b/riscv.sc/incl/sysc/SiFive/aon.h @@ -47,13 +47,17 @@ class aon : public sc_core::sc_module, public scc::tlm_target<> { public: SC_HAS_PROCESS(aon); sc_core::sc_in clk_i; - sc_core::sc_in rst_i; + sc_core::sc_in erst_n_i; + sc_core::sc_out lfclkc_o; + sc_core::sc_out rst_o; 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 start_of_simulation() override; void clock_cb(); void reset_cb(); + void reset_internal_cb(); sc_core::sc_time clk; std::unique_ptr regs; }; diff --git a/riscv.sc/incl/sysc/SiFive/core_complex.h b/riscv.sc/incl/sysc/SiFive/core_complex.h index 669c4d4..ad427da 100644 --- a/riscv.sc/incl/sysc/SiFive/core_complex.h +++ b/riscv.sc/incl/sysc/SiFive/core_complex.h @@ -134,6 +134,7 @@ protected: void start_of_simulation(); void run(); void clk_cb(); + void rst_cb(); void sw_irq_cb(); void timer_irq_cb(); void global_irq_cb(); diff --git a/riscv.sc/incl/sysc/SiFive/gen/prci_regs.h b/riscv.sc/incl/sysc/SiFive/gen/prci_regs.h index e616c74..2a50824 100644 --- a/riscv.sc/incl/sysc/SiFive/gen/prci_regs.h +++ b/riscv.sc/incl/sysc/SiFive/gen/prci_regs.h @@ -95,7 +95,7 @@ public: 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(hfxosccfg, r_hfxosccfg, 0x40000000, *this) , NAMED(pllcfg, r_pllcfg, 0, *this) , NAMED(plloutdiv, r_plloutdiv, 0, *this) , NAMED(coreclkcfg, r_coreclkcfg, 0, *this) diff --git a/riscv.sc/incl/sysc/SiFive/gpio.h b/riscv.sc/incl/sysc/SiFive/gpio.h index a4cc267..fa2612d 100644 --- a/riscv.sc/incl/sysc/SiFive/gpio.h +++ b/riscv.sc/incl/sysc/SiFive/gpio.h @@ -77,8 +77,13 @@ protected: void forward_pin_input(unsigned int tag, tlm::tlm_signal_gp& gp); void iof_input(unsigned int tag, unsigned iof_idx, tlm::tlm_signal_gp<>& gp, sc_core::sc_time& delay); sc_core::sc_time clk; + std::array last_iof0, last_iof1; std::unique_ptr regs; std::shared_ptr handler; + +private: + tlm::tlm_phase write_output(tlm::tlm_signal_gp& gp, size_t i, sc_dt::sc_logic val); + void enable_outputs(uint32_t new_data); }; } /* namespace sysc */ diff --git a/riscv.sc/incl/sysc/SiFive/platform.h b/riscv.sc/incl/sysc/SiFive/platform.h index cd493c4..2464a06 100644 --- a/riscv.sc/incl/sysc/SiFive/platform.h +++ b/riscv.sc/incl/sysc/SiFive/platform.h @@ -63,6 +63,8 @@ public: sc_core::sc_vector> pins_o; sc_core::sc_vector> pins_i; + sc_core::sc_in erst_n; + platform(sc_core::sc_module_name nm); private: diff --git a/riscv.sc/incl/sysc/SiFive/prci.h b/riscv.sc/incl/sysc/SiFive/prci.h index da854c3..fc62683 100644 --- a/riscv.sc/incl/sysc/SiFive/prci.h +++ b/riscv.sc/incl/sysc/SiFive/prci.h @@ -46,18 +46,21 @@ class prci_regs; class prci : public sc_core::sc_module, public scc::tlm_target<> { public: SC_HAS_PROCESS(prci); - sc_core::sc_in clk_i; + sc_core::sc_port,1,SC_ZERO_OR_MORE_BOUND> hfxosc_i; sc_core::sc_in rst_i; + sc_core::sc_out hfclk_o; 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 hfxosc_cb(); void reset_cb(); void hfrosc_en_cb(); - sc_core::sc_time clk; + void hfxosc_en_cb(); + void update_hfclk(); + sc_core::sc_time hfxosc_clk, hfrosc_clk, pll_clk, hfclk; std::unique_ptr regs; - sc_core::sc_event hfrosc_en_evt; + sc_core::sc_event hfrosc_en_evt, hfxosc_en_evt; }; } /* namespace sysc */ diff --git a/riscv.sc/src/CMakeLists.txt b/riscv.sc/src/CMakeLists.txt index 89decc0..6bdfb44 100644 --- a/riscv.sc/src/CMakeLists.txt +++ b/riscv.sc/src/CMakeLists.txt @@ -3,17 +3,17 @@ FILE(GLOB RiscVSCHeaders *.h */*.h) FILE(GLOB RiscvSCSources sysc/*.cpp) set(LIB_HEADERS ${RiscVSCHeaders} ) -set(LIB_SOURCES ${RiscvSCSources} -) +set(LIB_SOURCES ${RiscvSCSources} ) set(APP_HEADERS ) - -set(APP_SOURCES sc_main.cpp -) +set(APP_SOURCES sc_main.cpp) # Define two variables in order not to repeat ourselves. set(LIBRARY_NAME risc-v.sc) +## the following setting needs to be consistent with the library +#add_definitions(-DSC_DEFAULT_WRITER_POLICY=SC_MANY_WRITERS) + # Define the library add_library(${LIBRARY_NAME} ${LIB_SOURCES}) diff --git a/riscv.sc/src/sc_main.cpp b/riscv.sc/src/sc_main.cpp index 3b2a4ce..701f3c2 100644 --- a/riscv.sc/src/sc_main.cpp +++ b/riscv.sc/src/sc_main.cpp @@ -54,6 +54,16 @@ const size_t SUCCESS = 0; const size_t ERROR_UNHANDLED_EXCEPTION = 2; } // namespace +#include "sysc/kernel/sc_externs.h" +int +main( int argc, char* argv[]){ +#ifdef _POSIX_SOURCE + putenv(const_cast("SC_SIGNAL_WRITE_CHECK=DISABLE")); + putenv(const_cast("SC_VCD_SCOPES=ENABLE")); +#endif + return sc_core::sc_elab_and_sim( argc, argv ); +} + int sc_main(int argc, char *argv[]) { // sc_report_handler::set_handler(my_report_handler); scc::Logger<>::reporting_level() = logging::ERROR; @@ -159,11 +169,15 @@ int sc_main(int argc, char *argv[]) { /////////////////////////////////////////////////////////////////////////// // run simulation /////////////////////////////////////////////////////////////////////////// - if(vm.count("max_time")){ - sc_core::sc_time max_time = scc::parse_from_string(vm["max_time"].as()); - sc_core::sc_start(max_time); - } else - sc_core::sc_start(); + try { + if(vm.count("max_time")){ + sc_core::sc_time max_time = scc::parse_from_string(vm["max_time"].as()); + sc_core::sc_start(max_time); + } else + sc_core::sc_start(); + } catch(sc_core::sc_report& rep){ + CLOG(FATAL, SystemC)<<"IWEF"[rep.get_severity()]<<"("<(clk) , NAMED(clk_i) -, NAMED(rst_i) +, NAMED(erst_n_i) +, NAMED(lfclkc_o) +, NAMED(rst_o) , NAMEDD(aon_regs, regs) { regs->registerResources(*this); SC_METHOD(clock_cb); sensitive << clk_i; SC_METHOD(reset_cb); - sensitive << rst_i; - dont_initialize(); + sensitive << erst_n_i; +} + +void aon::start_of_simulation() { + rst_o=true; } void aon::clock_cb() { @@ -62,10 +67,17 @@ void aon::clock_cb() { aon::~aon() {} void aon::reset_cb() { - if (rst_i.read()) + if (!erst_n_i.read()){ regs->reset_start(); - else + rst_o=true; + } else { regs->reset_stop(); + rst_o=false; + } + lfclkc_o.write(sc_core::sc_time(1/32768., sc_core::SC_SEC)); +} + +void aon::reset_internal_cb() { } } /* namespace sysc */ diff --git a/riscv.sc/src/sysc/core_complex.cpp b/riscv.sc/src/sysc/core_complex.cpp index 5d673b4..36929a6 100644 --- a/riscv.sc/src/sysc/core_complex.cpp +++ b/riscv.sc/src/sysc/core_complex.cpp @@ -101,6 +101,12 @@ public: uint32_t get_mode(){ return this->reg.machine_state; } + inline + void set_interrupt_execution(bool v){ this->interrupt_sim=v;} + + inline + bool get_interrupt_execution(){ return this->interrupt_sim;} + base_type::hart_state& get_state() { return this->state; } void notify_phase(exec_phase p) override { @@ -241,6 +247,8 @@ core_complex::core_complex(sc_core::sc_module_name name) SC_THREAD(run); SC_METHOD(clk_cb); sensitive << clk_i; + SC_METHOD(rst_cb); + sensitive << rst_i; SC_METHOD(sw_irq_cb); sensitive<set_interrupt_execution(true); +} + +void core_complex::rst_cb() { + if(rst_i.read()) + cpu->set_interrupt_execution(true); } void core_complex::sw_irq_cb(){ @@ -314,13 +328,19 @@ void core_complex::global_irq_cb(){ } void core_complex::run() { - wait(sc_core::SC_ZERO_TIME); - cpu->reset(reset_address.get_value()); - try { - vm->start(-1); - } catch (simulation_stopped &e) { - } - sc_core::sc_stop(); + wait(SC_ZERO_TIME); // separate from elaboration phase + do{ + if(rst_i.read()){ + cpu->reset(reset_address.get_value()); + wait(rst_i.negedge_event()); + } + while(clk_i.read()==SC_ZERO_TIME){ + wait(clk_i.value_changed_event()); + } + cpu->set_interrupt_execution(false); + vm->start(); + } while(cpu->get_interrupt_execution()); + sc_stop(); } bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data, bool is_fetch) { diff --git a/riscv.sc/src/sysc/gpio.cpp b/riscv.sc/src/sysc/gpio.cpp index ecd7d94..1a3c498 100644 --- a/riscv.sc/src/sysc/gpio.cpp +++ b/riscv.sc/src/sysc/gpio.cpp @@ -73,6 +73,7 @@ gpio::gpio(sc_core::sc_module_name nm) } auto iof0_i_cb =[this](unsigned int tag, tlm::tlm_signal_gp& gp, tlm::tlm_phase& phase, sc_core::sc_time& delay)->tlm::tlm_sync_enum{ + last_iof0[tag]=gp.get_value(); this->iof_input(tag, 0, gp, delay); return tlm::TLM_COMPLETED; }; @@ -83,6 +84,7 @@ gpio::gpio(sc_core::sc_module_name nm) } auto iof1_i_cb =[this](unsigned int tag, tlm::tlm_signal_gp& gp, tlm::tlm_phase& phase, sc_core::sc_time& delay)->tlm::tlm_sync_enum{ + last_iof1[tag]=gp.get_value(); this->iof_input(tag, 1, gp, delay); return tlm::TLM_COMPLETED; }; @@ -99,6 +101,13 @@ gpio::gpio(sc_core::sc_module_name nm) } return true; }); + regs->iof_en.set_write_cb([this](scc::sc_register ®, uint32_t data) -> bool { + if (!this->regs->in_reset()) { + enable_outputs(data); + reg.put(data); + } + return true; + }); } @@ -123,21 +132,51 @@ void gpio::clock_cb() { this->clk = clk_i.read(); } +tlm::tlm_phase gpio::write_output(tlm::tlm_signal_gp& gp, size_t i, sc_dt::sc_logic val) { + sc_core::sc_time delay{SC_ZERO_TIME}; + tlm::tlm_phase phase{ tlm::BEGIN_REQ }; + gp.set_command(tlm::TLM_WRITE_COMMAND); + gp.set_response_status(tlm::TLM_OK_RESPONSE); + gp.set_value(val); + pins_o.at(i)->nb_transport_fw(gp, phase, delay); + return phase; +} + void gpio::update_pins() { sc_core::sc_inout_rv<32>::data_type out_val; tlm::tlm_signal_gp gp; for(size_t i=0, mask = 1; i<32; ++i, mask<<=1){ if((regs->iof_en&mask == 0) || (iof0_i[i].size()==0 && iof1_i[i].size()==0)){ - sc_core::sc_time delay{SC_ZERO_TIME}; - tlm::tlm_phase phase{tlm::BEGIN_REQ}; - gp.set_command(tlm::TLM_WRITE_COMMAND); - gp.set_response_status(tlm::TLM_OK_RESPONSE); - gp.set_value(regs->r_output_en&mask?regs->r_port&mask?sc_dt::Log_1:sc_dt::Log_0:sc_dt::Log_Z); - pins_o.at(i)->nb_transport_fw(gp, phase, delay); + auto val = regs->r_output_en&mask? + regs->r_port&mask? + sc_dt::Log_1: + sc_dt::Log_0: + sc_dt::Log_Z; + tlm::tlm_phase phase = write_output(gp, i, val); } } } +void gpio::enable_outputs(uint32_t new_data) { + auto changed_bits = regs->r_iof_en^new_data; + tlm::tlm_signal_gp gp; + for(size_t i=0, mask=1; i<32; ++i, mask<<=1){ + if(changed_bits&mask){ + if(new_data&mask){ + if((regs->r_iof_sel&mask)==0 && iof0_i[i].size()>0){ + tlm::tlm_phase phase = write_output(gp, i, last_iof0[i]?sc_dt::Log_1:sc_dt::Log_0); + } else if((regs->r_iof_sel&mask)==1 && iof1_i[i].size()>0) + tlm::tlm_phase phase = write_output(gp, i, last_iof1[i]?sc_dt::Log_1:sc_dt::Log_0); + } else { + auto val = regs->r_output_en&mask? + regs->r_port&mask?sc_dt::Log_1:sc_dt::Log_0: + sc_dt::Log_Z; + tlm::tlm_phase phase = write_output(gp, i, val); + } + } + } +} + void gpio::pin_input(unsigned int tag, tlm::tlm_signal_gp& gp, sc_core::sc_time& delay) { if(delay>SC_ZERO_TIME){ wait(delay); @@ -187,7 +226,8 @@ void gpio::iof_input(unsigned int tag, unsigned iof_idx, tlm::tlm_signal_gp<>& g tlm::tlm_phase phase{tlm::BEGIN_REQ}; tlm::tlm_signal_gp new_gp; new_gp.set_command(tlm::TLM_WRITE_COMMAND); - new_gp.set_value(gp.get_value()?sc_dt::Log_1:sc_dt::Log_0); + auto val = gp.get_value(); + new_gp.set_value(val?sc_dt::Log_1:sc_dt::Log_0); new_gp.copy_extensions_from(gp); socket->nb_transport_fw(new_gp, phase, delay); // we don't care about phase and sync enum } diff --git a/riscv.sc/src/sysc/platform.cpp b/riscv.sc/src/sysc/platform.cpp index 5d5241f..93c6d66 100644 --- a/riscv.sc/src/sysc/platform.cpp +++ b/riscv.sc/src/sysc/platform.cpp @@ -42,6 +42,7 @@ platform::platform(sc_core::sc_module_name nm) : sc_core::sc_module(nm) , NAMED(pins_o, 32) , NAMED(pins_i, 32) +, NAMED(erst_n) , NAMED(i_core_complex) , NAMED(i_router, 12, 1) , NAMED(i_uart0) @@ -85,7 +86,8 @@ platform::platform(sc_core::sc_module_name nm) i_gpio0.clk_i(s_tlclk); i_plic.clk_i(s_tlclk); i_aon.clk_i(s_tlclk); - i_prci.clk_i(s_tlclk); + i_aon.lfclkc_o(s_lfclk); + i_prci.hfclk_o(s_tlclk); // clock driver i_clint.tlclk_i(s_tlclk); i_clint.lfclk_i(s_lfclk); i_core_complex.clk_i(s_tlclk); @@ -97,11 +99,13 @@ platform::platform(sc_core::sc_module_name nm) i_qspi2.rst_i(s_rst); i_gpio0.rst_i(s_rst); i_plic.rst_i(s_rst); - i_aon.rst_i(s_rst); + i_aon.rst_o(s_rst); i_prci.rst_i(s_rst); i_clint.rst_i(s_rst); i_core_complex.rst_i(s_rst); + i_aon.erst_n_i(erst_n); + i_clint.mtime_int_o(s_mtime_int); i_clint.msip_int_o(s_msie_int); @@ -124,17 +128,7 @@ platform::platform(sc_core::sc_module_name nm) i_uart1.rx_i(s_dummy_sck_o[0]); i_uart1.irq_o(s_dummy[0]); - SC_THREAD(gen_reset); - for(auto& sock:s_dummy_sck_i) sock.error_if_no_callback=false; } -void platform::gen_reset() { - s_tlclk = 10_ns; - s_lfclk = 30517_ns; - s_rst = true; - wait(10_ns); - s_rst = false; -} - } /* namespace sysc */ diff --git a/riscv.sc/src/sysc/prci.cpp b/riscv.sc/src/sysc/prci.cpp index 363def0..28cf62b 100644 --- a/riscv.sc/src/sysc/prci.cpp +++ b/riscv.sc/src/sysc/prci.cpp @@ -43,24 +43,35 @@ namespace sysc { prci::prci(sc_core::sc_module_name nm) : sc_core::sc_module(nm) -, tlm_target<>(clk) -, NAMED(clk_i) +, tlm_target<>(hfclk) , NAMED(rst_i) +, NAMED(hfclk_o) , 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(hfxosc_cb); + sensitive << hfxosc_i; SC_METHOD(hfrosc_en_cb); sensitive << hfrosc_en_evt; dont_initialize(); + regs->hfxosccfg.set_write_cb([this](scc::sc_register ®, uint32_t data) -> bool { + reg.put(data); + if (this->regs->r_hfxosccfg.hfxoscen==1) { // check rosc_en + this->hfxosc_en_evt.notify(1, sc_core::SC_US); + } else { + this->hfxosc_en_evt.notify(SC_ZERO_TIME); + } + return true; + }); regs->hfrosccfg.set_write_cb([this](scc::sc_register ®, uint32_t data) -> bool { reg.put(data); - if (this->regs->r_hfrosccfg & (1 << 30)) { // check rosc_en + if (this->regs->r_hfrosccfg.hfroscen==1) { // check rosc_en this->hfrosc_en_evt.notify(1, sc_core::SC_US); + } else { + this->hfrosc_en_evt.notify(SC_ZERO_TIME); } return true; }); @@ -70,13 +81,15 @@ prci::prci(sc_core::sc_module_name nm) if (pllcfg.pllbypass == 0 && pllcfg.pllq != 0) { // set pll_lock if pll is selected pllcfg.plllock = 1; } + update_hfclk(); return true; }); -} - -void prci::clock_cb() { - this->clk = clk_i.read(); - + regs->plloutdiv.set_write_cb([this](scc::sc_register ®, uint32_t data) -> bool { + reg.put(data); + update_hfclk(); + return true; + }); + hfxosc_clk=62.5_ns; } prci::~prci() {} @@ -84,12 +97,49 @@ prci::~prci() {} void prci::reset_cb() { if (rst_i.read()) regs->reset_start(); - else + else { regs->reset_stop(); + this->hfxosc_en_evt.notify(1, sc_core::SC_US); + } +} + +void prci::hfxosc_cb() { + this->regs->r_hfxosccfg.hfxoscrdy=0; + this->hfxosc_en_evt.notify(1, sc_core::SC_US); + +} + +void prci::hfxosc_en_cb() { + update_hfclk(); + if(regs->r_hfxosccfg.hfxoscen==1)// set rosc_rdy + regs->r_hfxosccfg.hfxoscrdy =1; + else + regs->r_hfxosccfg.hfxoscrdy =0; } void prci::hfrosc_en_cb() { - regs->r_hfrosccfg |= (1 << 31); // set rosc_rdy + update_hfclk(); + auto& hfrosccfg=regs->r_hfrosccfg; + if(regs->r_hfrosccfg.hfroscen==1) {// set rosc_rdy + regs->r_hfrosccfg.hfroscrdy =1; + } else { + regs->r_hfrosccfg.hfroscrdy =0; + } +} + +void prci::update_hfclk() { + auto& hfrosccfg=regs->r_hfrosccfg; + auto& pllcfg=regs->r_pllcfg; + auto& plldiv=regs->r_plloutdiv; + hfrosc_clk = sc_core::sc_time(((hfrosccfg.hfroscdiv+1)*1.0)/(1125000.0*(hfrosccfg.hfrosctrim+1)), sc_core::SC_SEC); + auto pll_ref = pllcfg.pllrefsel==1?hfxosc_clk:hfrosc_clk; + auto r = pllcfg.pllr+1; + auto f = 2*(pllcfg.pllf+1); + auto q = 1< gp; - gp.set_command(tlm::TLM_WRITE_COMMAND); - gp.set_value(true); - tx_o->nb_transport_fw(gp, phase, delay); + sc_core::sc_time delay(SC_ZERO_TIME); + sc_core::sc_time bit_duration(SC_ZERO_TIME); + + gp.set_extension(&ext); + ext.tx.data_bits=8; + ext.tx.parity=false; + + auto set_bit = [&](bool val){ + gp.set_command(tlm::TLM_WRITE_COMMAND); + gp.set_value(val); + tlm::tlm_phase phase(tlm::BEGIN_REQ); + tx_o->nb_transport_fw(gp, phase, delay); + if(delayr_txdata.full=tx_fifo.num_free()==0; regs->r_ip.txwm=regs->r_txctrl.txcnt<=(7-tx_fifo.num_free())?1:0; - auto bit_duration = (regs->r_div.div+1)*clk; - sysc::tlm_signal_uart_extension ext; + bit_duration = (regs->r_div.div+1)*clk; ext.start_time = sc_core::sc_time_stamp(); - ext.tx.data_bits=8; - ext.tx.parity=false; ext.tx.stop_bits=1+regs->r_txctrl.nstop; ext.tx.baud_rate=static_cast(1/bit_duration.to_seconds()); ext.tx.data=txdata; - delay=SC_ZERO_TIME; - auto start = sc_time_stamp(); - gp.set_command(tlm::TLM_WRITE_COMMAND); - gp.set_value(false); - gp.set_extension(&ext); - phase=tlm::BEGIN_REQ; - tx_o->nb_transport_fw(gp, phase, delay); - auto duration = bit_duration*(1+8+1+ext.tx.stop_bits);//start+data+parity+stop - auto diff=start+duration-sc_time_stamp(); - if(diff>SC_ZERO_TIME) wait(diff); - delay=SC_ZERO_TIME; - gp.set_command(tlm::TLM_WRITE_COMMAND); - gp.set_value(true); - phase=tlm::BEGIN_REQ; - tx_o->nb_transport_fw(gp, phase, delay); - -// if(txdata != '\r') queue.push_back(txdata); -// if (queue.size() >> 0 && (txdata == '\n' || txdata == 0)) { -// std::string msg(queue.begin(), queue.end()-1); -// LOG(INFO) << this->name() << " transmit: '" << msg << "'"; -// sc_core::sc_time now = sc_core::sc_time_stamp(); -// if(handler) -// sc_comm_singleton::inst().execute([this, msg, now](){ -// std::stringstream os; -// os << "{\"time\":\"" << now << "\",\"message\":\""<handler->send(os.str()); -// }); -// queue.clear(); -// } + set_bit(false); // start bit + for(int i = 8; i>0; --i) + set_bit(txdata&(1<<(i-1))); // 8 data bits, MSB first + set_bit(true); // stop bit 1 + if(regs->r_txctrl.nstop) set_bit(true); // stop bit 2 } } } diff --git a/riscv/gen_input/templates/incl-CORENAME.h.gtl b/riscv/gen_input/templates/incl-CORENAME.h.gtl index e32a36e..7c6aad2 100644 --- a/riscv/gen_input/templates/incl-CORENAME.h.gtl +++ b/riscv/gen_input/templates/incl-CORENAME.h.gtl @@ -162,6 +162,7 @@ protected: std::array addr_mode; + bool interrupt_sim=false; <% def fcsr = allRegs.find {it.name=='FCSR'} if(fcsr != null) {%> diff --git a/riscv/gen_input/templates/src-CORENAME.cpp.gtl b/riscv/gen_input/templates/src-CORENAME.cpp.gtl index 5c2f1bd..cafe82c 100644 --- a/riscv/gen_input/templates/src-CORENAME.cpp.gtl +++ b/riscv/gen_input/templates/src-CORENAME.cpp.gtl @@ -1,21 +1,21 @@ //////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2017, MINRES Technologies GmbH +// Copyright (C) 2017,2018 MINRES Technologies GmbH // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: -// +// // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. -// +// // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. -// +// // 3. Neither the name of the copyright holder nor the names of its contributors // may be used to endorse or promote products derived from this software // without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE diff --git a/riscv/incl/iss/arch/rv32gc.h b/riscv/incl/iss/arch/rv32gc.h index 6d533ca..c153887 100644 --- a/riscv/incl/iss/arch/rv32gc.h +++ b/riscv/incl/iss/arch/rv32gc.h @@ -179,6 +179,8 @@ struct rv32gc: public arch_if { uint64_t get_icount() { return reg.icount;} + bool should_stop(){return false;} + inline phys_addr_t v2p(const iss::addr_t& addr){ if(addr.space != traits::MEM || addr.type == iss::address_type::PHYSICAL || diff --git a/riscv/incl/iss/arch/rv32imac.h b/riscv/incl/iss/arch/rv32imac.h index 4a080dd..a018635 100644 --- a/riscv/incl/iss/arch/rv32imac.h +++ b/riscv/incl/iss/arch/rv32imac.h @@ -144,8 +144,12 @@ struct rv32imac: public arch_if { /// deprecated void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {}; + inline uint64_t get_icount() { return reg.icount;} + inline + bool should_stop() { return interrupt_sim;} + inline phys_addr_t v2p(const iss::addr_t& addr){ if(addr.space != traits::MEM || addr.type == iss::address_type::PHYSICAL || @@ -204,6 +208,7 @@ protected: std::array addr_mode; + bool interrupt_sim=false; uint32_t get_fcsr(){return 0;} void set_fcsr(uint32_t val){} diff --git a/riscv/incl/iss/arch/rv64ia.h b/riscv/incl/iss/arch/rv64ia.h index 464fee7..871d4aa 100644 --- a/riscv/incl/iss/arch/rv64ia.h +++ b/riscv/incl/iss/arch/rv64ia.h @@ -146,6 +146,8 @@ struct rv64ia: public arch_if { uint64_t get_icount() { return reg.icount;} + bool should_stop(){return false;} + inline phys_addr_t v2p(const iss::addr_t& addr){ if(addr.space != traits::MEM || addr.type == iss::address_type::PHYSICAL || diff --git a/riscv/src/iss/rv32gc.cpp b/riscv/src/iss/rv32gc.cpp index 95472fe..0e9bb96 100644 --- a/riscv/src/iss/rv32gc.cpp +++ b/riscv/src/iss/rv32gc.cpp @@ -62,6 +62,7 @@ void rv32gc::reset(uint64_t address) { reg.NEXT_PC=reg.PC; reg.trap_state=0; reg.machine_state=0x0; + reg.icount=0; } uint8_t* rv32gc::get_regs_base_ptr(){ diff --git a/riscv/src/iss/rv64ia.cpp b/riscv/src/iss/rv64ia.cpp index b6534e4..f5f542e 100644 --- a/riscv/src/iss/rv64ia.cpp +++ b/riscv/src/iss/rv64ia.cpp @@ -63,6 +63,7 @@ void rv64ia::reset(uint64_t address) { reg.NEXT_PC = reg.PC; reg.trap_state = 0; reg.machine_state = 0x3; + reg.icount=0; } uint8_t *rv64ia::get_regs_base_ptr() { return reinterpret_cast(®); } diff --git a/sc-components b/sc-components index 019a041..57853f5 160000 --- a/sc-components +++ b/sc-components @@ -1 +1 @@ -Subproject commit 019a04132a8beb7fcab24d504e3347ca0771ea5f +Subproject commit 57853f5df2ee573c35ef598a8a259696ae6059c0