diff --git a/riscv.sc/incl/sysc/General/system.h b/riscv.sc/incl/sysc/General/system.h new file mode 100644 index 0000000..9645762 --- /dev/null +++ b/riscv.sc/incl/sysc/General/system.h @@ -0,0 +1,30 @@ +/* + * system.h + * + * Created on: 11.07.2018 + * Author: eyck + */ + +#ifndef __SYSC_GENERAL_SYSTEM_H_ +#define __SYSC_GENERAL_SYSTEM_H_ + +#include "sysc/SiFive/platform.h" +#include "sysc/General/terminal.h" +#include + +namespace sysc { + +class system: sc_core::sc_module { +public: + system(sc_core::sc_module_name nm); + virtual ~system(); + + sc_core::sc_vector> s_gpio; + +private: + sysc::platform i_platform; + sysc::terminal i_terminal; +}; + +} +#endif /* __SYSC_GENERAL_SYSTEM_H_ */ diff --git a/riscv.sc/incl/sysc/General/terminal.h b/riscv.sc/incl/sysc/General/terminal.h new file mode 100644 index 0000000..d614051 --- /dev/null +++ b/riscv.sc/incl/sysc/General/terminal.h @@ -0,0 +1,42 @@ +/* + * terminal.h + * + * Created on: 07.07.2018 + * Author: eyck + */ + +#ifndef RISCV_SC_INCL_SYSC_GENERAL_TERMINAL_H_ +#define RISCV_SC_INCL_SYSC_GENERAL_TERMINAL_H_ + +#include "scc/signal_target_mixin.h" +#include "scc/signal_initiator_mixin.h" +#include "tlm/tlm_signal.h" +#include "cci_configuration" +#include +#include + +namespace sysc { +class WsHandler; + +class terminal: public sc_core::sc_module { +public: + scc::tlm_signal_logic_out tx_o; + scc::tlm_signal_logic_in rx_i; + + terminal(); + + terminal(const sc_core::sc_module_name& nm); + + virtual ~terminal(); + + cci::cci_param write_to_ws; + +protected: + std::vector queue; + void receive(tlm::tlm_signal_gp& gp, sc_core::sc_time& delay); + std::shared_ptr handler; + sc_core::sc_time last_tx_start=sc_core::SC_ZERO_TIME; +}; +} + +#endif /* RISCV_SC_INCL_SYSC_GENERAL_TERMINAL_H_ */ diff --git a/riscv.sc/incl/sysc/SiFive/clint.h b/riscv.sc/incl/sysc/SiFive/clint.h index c4001d5..8ebbfb8 100644 --- a/riscv.sc/incl/sysc/SiFive/clint.h +++ b/riscv.sc/incl/sysc/SiFive/clint.h @@ -55,7 +55,8 @@ class core_complex; class clint : public sc_core::sc_module, public scc::tlm_target<> { public: SC_HAS_PROCESS(clint); - sc_core::sc_in clk_i; + sc_core::sc_in tlclk_i; + sc_core::sc_in lfclk_i; sc_core::sc_in rst_i; sc_core::sc_out mtime_int_o; sc_core::sc_out msip_int_o; diff --git a/riscv.sc/incl/sysc/SiFive/core_complex.h b/riscv.sc/incl/sysc/SiFive/core_complex.h index b60a920..669c4d4 100644 --- a/riscv.sc/incl/sysc/SiFive/core_complex.h +++ b/riscv.sc/incl/sysc/SiFive/core_complex.h @@ -109,7 +109,8 @@ public: ~core_complex(); inline void sync(uint64_t cycle) { - quantum_keeper.inc(curr_clk*(cycle-last_sync_cycle)); + auto time = curr_clk*(cycle-last_sync_cycle); + quantum_keeper.inc(time); if (quantum_keeper.need_sync()) { wait(quantum_keeper.get_local_time()); quantum_keeper.reset(); diff --git a/riscv.sc/incl/sysc/SiFive/gpio.h b/riscv.sc/incl/sysc/SiFive/gpio.h index 5dd1de3..a4cc267 100644 --- a/riscv.sc/incl/sysc/SiFive/gpio.h +++ b/riscv.sc/incl/sysc/SiFive/gpio.h @@ -38,8 +38,10 @@ #define _GPIO_H_ #include "scc/tlm_target.h" +#include "scc/signal_target_mixin.h" +#include "scc/signal_initiator_mixin.h" +#include #include "cci_configuration" -#include namespace sysc { @@ -51,7 +53,15 @@ public: SC_HAS_PROCESS(gpio); sc_core::sc_in clk_i; sc_core::sc_in rst_i; - sc_core::sc_inout_rv<32> pins_io; + // sc_core::sc_inout_rv<32> pins_io; + + sc_core::sc_vector pins_o; + sc_core::sc_vector pins_i; + + sc_core::sc_vector iof0_o; + sc_core::sc_vector iof1_o; + sc_core::sc_vector iof0_i; + sc_core::sc_vector iof1_i; gpio(sc_core::sc_module_name nm); virtual ~gpio() override; // need to keep it in source file because of fwd declaration of gpio_regs @@ -62,14 +72,13 @@ protected: void clock_cb(); void reset_cb(); void update_pins(); - void pins_cb(); void before_end_of_elaboration(); + void pin_input(unsigned int tag, tlm::tlm_signal_gp& gp, sc_core::sc_time& delay); + 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::unique_ptr regs; std::shared_ptr handler; - -private: - void update_value_reg(); }; } /* namespace sysc */ diff --git a/riscv.sc/incl/sysc/SiFive/platform.h b/riscv.sc/incl/sysc/SiFive/platform.h index 9055c43..cd493c4 100644 --- a/riscv.sc/incl/sysc/SiFive/platform.h +++ b/riscv.sc/incl/sysc/SiFive/platform.h @@ -34,8 +34,8 @@ // //////////////////////////////////////////////////////////////////////////////// -#ifndef SIMPLESYSTEM_H_ -#define SIMPLESYSTEM_H_ +#ifndef _PLATFORM_H_ +#define _PLATFORM_H_ #include "aon.h" #include "clint.h" @@ -44,14 +44,15 @@ #include "prci.h" #include "spi.h" #include "uart.h" - -#include -#include +#include "core_complex.h" #include "scc/memory.h" #include "scc/router.h" #include "scc/utilities.h" -#include "core_complex.h" +#include "tlm/tlm_signal_sockets.h" +#include +#include + namespace sysc { @@ -59,6 +60,12 @@ class platform : public sc_core::sc_module { public: SC_HAS_PROCESS(platform); + sc_core::sc_vector> pins_o; + sc_core::sc_vector> pins_i; + + platform(sc_core::sc_module_name nm); + +private: SiFive::core_complex i_core_complex; scc::router<> i_router; uart i_uart0, i_uart1; @@ -71,13 +78,15 @@ public: scc::memory<512_MB, 32> i_mem_qspi; scc::memory<128_kB, 32> i_mem_ram; - sc_core::sc_signal s_clk; + sc_core::sc_signal s_tlclk; + sc_core::sc_signal s_lfclk; sc_core::sc_signal s_rst, s_mtime_int, s_msie_int; - sc_core::sc_vector> s_global_int, s_local_int; + sc_core::sc_vector> s_global_int, s_local_int; sc_core::sc_signal s_core_int; - sc_core::sc_signal_rv<32> s_gpio_pins; + sc_core::sc_vector> s_dummy; + sc_core::sc_vector s_dummy_sck_i; + sc_core::sc_vector s_dummy_sck_o; - platform(sc_core::sc_module_name nm); protected: void gen_reset(); @@ -87,4 +96,4 @@ protected: } /* namespace sysc */ -#endif /* SIMPLESYSTEM_H_ */ +#endif /* _PLATFORM_H_ */ diff --git a/riscv.sc/incl/sysc/SiFive/uart.h b/riscv.sc/incl/sysc/SiFive/uart.h index 68e6e3e..43fe99e 100644 --- a/riscv.sc/incl/sysc/SiFive/uart.h +++ b/riscv.sc/incl/sysc/SiFive/uart.h @@ -37,11 +37,14 @@ #ifndef _UART_H_ #define _UART_H_ -#include "cci_configuration" #include "scc/tlm_target.h" +#include "scc/signal_target_mixin.h" +#include "scc/signal_initiator_mixin.h" +#include +#include "cci_configuration" namespace sysc { - +class tlm_signal_uart_extension; class uart_regs; class WsHandler; @@ -50,18 +53,28 @@ public: SC_HAS_PROCESS(uart); sc_core::sc_in clk_i; sc_core::sc_in rst_i; + scc::tlm_signal_bool_out tx_o; + scc::tlm_signal_bool_in rx_i; + + sc_core::sc_out irq_o; + + cci::cci_param write_to_ws; + uart(sc_core::sc_module_name nm); virtual ~uart() override; - cci::cci_param write_to_ws; protected: void clock_cb(); void reset_cb(); void transmit_data(); + void receive_data(tlm::tlm_signal_gp<>& gp, sc_core::sc_time& delay); + void update_irq(); void before_end_of_elaboration(); sc_core::sc_time clk; std::unique_ptr regs; + sc_core::sc_fifo rx_fifo, tx_fifo; std::vector queue; + sysc::tlm_signal_uart_extension *rx_ext, *tx_ext; std::shared_ptr handler; }; diff --git a/riscv.sc/incl/sysc/tlm_extensions.h b/riscv.sc/incl/sysc/tlm_extensions.h new file mode 100644 index 0000000..b2f5663 --- /dev/null +++ b/riscv.sc/incl/sysc/tlm_extensions.h @@ -0,0 +1,31 @@ +/* + * tlm_extensions.h + * + * Created on: 12.07.2018 + * Author: eyck + */ + +#ifndef RISCV_SC_INCL_SYSC_TLM_EXTENSIONS_H_ +#define RISCV_SC_INCL_SYSC_TLM_EXTENSIONS_H_ + +#include "tlm/tlm_extensions.h" + +namespace sysc { +struct tlm_signal_uart_extension : public tlm::tlm_unmanaged_extension { + + struct uart_tx { + unsigned data_bits:4; + unsigned stop_bits:2; + bool parity:1; + unsigned baud_rate:24; + unsigned data; + } tx; + sc_core::sc_time start_time; + +}; + +} + + + +#endif /* RISCV_SC_INCL_SYSC_TLM_EXTENSIONS_H_ */ diff --git a/riscv.sc/src/CMakeLists.txt b/riscv.sc/src/CMakeLists.txt index 4e11fc5..89decc0 100644 --- a/riscv.sc/src/CMakeLists.txt +++ b/riscv.sc/src/CMakeLists.txt @@ -1,5 +1,5 @@ # library files -FILE(GLOB RiscVSCHeaders *.h) +FILE(GLOB RiscVSCHeaders *.h */*.h) FILE(GLOB RiscvSCSources sysc/*.cpp) set(LIB_HEADERS ${RiscVSCHeaders} ) diff --git a/riscv.sc/src/sc_main.cpp b/riscv.sc/src/sc_main.cpp index 6ea94cb..3b2a4ce 100644 --- a/riscv.sc/src/sc_main.cpp +++ b/riscv.sc/src/sc_main.cpp @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include "scc/configurer.h" #include "scc/report.h" #include "scc/scv_tr_db.h" @@ -123,7 +123,7 @@ int sc_main(int argc, char *argv[]) { /////////////////////////////////////////////////////////////////////////// // instantiate top level /////////////////////////////////////////////////////////////////////////// - platform i_simple_system("i_simple_system"); + sysc::system i_system("i_system"); // sr_report_handler::add_sc_object_to_filter(&i_simple_system.i_master, // sc_core::SC_WARNING, sc_core::SC_MEDIUM); if(vm["dump-config"].as().size()>0){ @@ -134,20 +134,20 @@ int sc_main(int argc, char *argv[]) { cfg.configure(); // overwrite with command line settings if (vm["gdb-port"].as()) - cfg.set_value("i_simple_system.i_core_complex.gdb_server_port", vm["gdb-port"].as()); + cfg.set_value("i_system.i_platform.i_core_complex.gdb_server_port", vm["gdb-port"].as()); if (vm.count("dump-ir")) - cfg.set_value("i_simple_system.i_core_complex.dump_ir", vm.count("dump-ir") != 0); + cfg.set_value("i_system.i_platform.i_core_complex.dump_ir", vm.count("dump-ir") != 0); if (vm.count("elf")) - cfg.set_value("i_simple_system.i_core_complex.elf_file", vm["elf"].as()); + cfg.set_value("i_system.i_platform.i_core_complex.elf_file", vm["elf"].as()); if (vm.count("quantum")) tlm::tlm_global_quantum::instance().set(sc_core::sc_time(vm["quantum"].as(), sc_core::SC_NS)); 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); + cfg.set_value("i_system.i_platform.i_core_complex.reset_address", start_address); } if (vm.count("disass")) { - cfg.set_value("i_simple_system.i_core_complex.enable_disass", true); + cfg.set_value("i_system.i_platform.i_core_complex.enable_disass", true); LOGGER(disass)::reporting_level() = logging::INFO; auto file_name = vm["disass"].as(); if (file_name.length() > 0) { diff --git a/riscv.sc/src/sysc/clint.cpp b/riscv.sc/src/sysc/clint.cpp index fffcf20..90ec09b 100644 --- a/riscv.sc/src/sysc/clint.cpp +++ b/riscv.sc/src/sysc/clint.cpp @@ -47,7 +47,8 @@ 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(tlclk_i) +, NAMED(lfclk_i) , NAMED(rst_i) , NAMED(mtime_int_o) , NAMED(msip_int_o) @@ -55,7 +56,7 @@ clint::clint(sc_core::sc_module_name nm) , cnt_fraction(0) { regs->registerResources(*this); SC_METHOD(clock_cb); - sensitive << clk_i; + sensitive << tlclk_i<clk = clk_i.read(); + clk = lfclk_i.read(); update_mtime(); } @@ -101,20 +102,23 @@ void clint::reset_cb() { } void clint::update_mtime() { - auto diff = (sc_core::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 > 0) - if(regs->r_mtimecmp > regs->r_mtime && clk > sc_core::SC_ZERO_TIME) { - sc_core::sc_time next_trigger = (clk * lfclk_mutiplier) * (regs->r_mtimecmp - regs->mtime) - cnt_fraction * clk; - LOG(DEBUG)<<"Timer fires at "<< sc_time_stamp()+next_trigger; - mtime_evt.notify(next_trigger); - mtime_int_o.write(false); - } else - mtime_int_o.write(true); - last_updt = sc_core::sc_time_stamp(); + if(clk>SC_ZERO_TIME){ + uint64_t elapsed_clks = (sc_time_stamp()-last_updt)/clk; // get the number of clock periods since last invocation + last_updt += elapsed_clks*clk; // increment the last_updt timestamp by the number of clocks + if(elapsed_clks){ // update mtime reg if we have more than 0 elapsed clk periods + regs->r_mtime+=elapsed_clks; + mtime_evt.cancel(); + if (regs->r_mtimecmp > 0) + if(regs->r_mtimecmp > regs->r_mtime && clk > sc_core::SC_ZERO_TIME) { + sc_core::sc_time next_trigger = (clk * lfclk_mutiplier) * (regs->r_mtimecmp - regs->mtime) - cnt_fraction * clk; + LOG(DEBUG)<<"Timer fires at "<< sc_time_stamp()+next_trigger; + mtime_evt.notify(next_trigger); + mtime_int_o.write(false); + } else + mtime_int_o.write(true); + } + } else + last_updt = sc_time_stamp(); } } /* namespace sysc */ diff --git a/riscv.sc/src/sysc/gpio.cpp b/riscv.sc/src/sysc/gpio.cpp index 28eaffa..ecd7d94 100644 --- a/riscv.sc/src/sysc/gpio.cpp +++ b/riscv.sc/src/sysc/gpio.cpp @@ -35,7 +35,6 @@ //////////////////////////////////////////////////////////////////////////////// #include "sysc/SiFive/gpio.h" - #include "sysc/sc_comm_singleton.h" #include "scc/report.h" #include "scc/utilities.h" @@ -48,7 +47,12 @@ gpio::gpio(sc_core::sc_module_name nm) , tlm_target<>(clk) , NAMED(clk_i) , NAMED(rst_i) -, NAMED(pins_io) +, NAMED(pins_o, 32) +, NAMED(pins_i, 32) +, NAMED(iof0_o, 32) +, NAMED(iof1_o, 32) +, NAMED(iof0_i, 32) +, NAMED(iof1_i, 32) , NAMEDD(gpio_regs, regs) , NAMED(write_to_ws, false){ regs->registerResources(*this); @@ -57,9 +61,36 @@ gpio::gpio(sc_core::sc_module_name nm) SC_METHOD(reset_cb); sensitive << rst_i; dont_initialize(); - SC_METHOD(pins_cb); - sensitive << pins_io; - + auto pins_i_cb =[this](unsigned int tag, tlm::tlm_signal_gp& gp, + tlm::tlm_phase& phase, sc_core::sc_time& delay)->tlm::tlm_sync_enum{ + this->pin_input(tag, gp, delay); + return tlm::TLM_COMPLETED; + }; + auto i=0U; + for(auto& s:pins_i){ + s.register_nb_transport(pins_i_cb, i); + ++i; + } + 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{ + this->iof_input(tag, 0, gp, delay); + return tlm::TLM_COMPLETED; + }; + i=0; + for(auto& s:iof0_i){ + s.register_nb_transport(iof0_i_cb, i); + ++i; + } + 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{ + this->iof_input(tag, 1, gp, delay); + return tlm::TLM_COMPLETED; + }; + i=0; + for(auto& s:iof1_i){ + s.register_nb_transport(iof1_i_cb, i); + ++i; + } regs->port.set_write_cb([this](scc::sc_register ®, uint32_t data) -> bool { if (!this->regs->in_reset()) { reg.put(data); @@ -69,14 +100,6 @@ gpio::gpio(sc_core::sc_module_name nm) return true; }); - regs->value.set_read_cb([this](const scc::sc_register ®, uint32_t& data) -> bool { - if (!this->regs->in_reset()) { - // read pins_io and update r_value - update_value_reg(); - data=reg.get(); - } - return true; - }); } gpio::~gpio() {} @@ -100,40 +123,76 @@ void gpio::clock_cb() { this->clk = clk_i.read(); } -void gpio::pins_cb(){ - auto inval=pins_io.read(); - std::string msg(inval.to_string()); - 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 << "\",\"data\":\""<handler->send(os.str()); - }); -} - -void gpio::update_value_reg() { - // read pins_io and update r_value reg - auto inval = pins_io.read(); - uint32_t res = 0; - for (size_t i = 0, msk = 1; i < 32; ++i, msk = msk << 1) { - bool bit_set = false; - if ((regs->r_input_en & msk) != 0) { - if (inval.get_bit(1) == sc_dt::Log_1) - bit_set = true; - else if (inval.get_bit(1) == sc_dt::Log_Z - && (regs->r_pue & msk) != 0) - bit_set = true; - } - if (bit_set) res |= msk; - } - regs->r_value = res; -} - void gpio::update_pins() { sc_core::sc_inout_rv<32>::data_type out_val; - for(size_t i=0, msk = 1; i<32; ++i, msk=msk<<1) - out_val.set_bit(i, regs->r_output_en&msk?regs->r_port&msk?sc_dt::Log_1:sc_dt::Log_0:sc_dt::Log_Z); - pins_io.write(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); + } + } +} + +void gpio::pin_input(unsigned int tag, tlm::tlm_signal_gp& gp, sc_core::sc_time& delay) { + if(delay>SC_ZERO_TIME){ + wait(delay); + delay=SC_ZERO_TIME; + } + switch(gp.get_value().value()){ + case sc_dt::Log_1: + regs->r_value|=1<r_value&=~(1<& gp) { + const auto mask = 1U<iof_en&mask){ + auto& socket = regs->iof_sel&mask?iof1_o[tag]:iof0_o[tag]; + tlm::tlm_signal_gp<> new_gp; + for(size_t i=0; inb_transport_fw(new_gp, phase, delay); // we don't care about phase and sync enum + } + } +} + +void gpio::iof_input(unsigned int tag, unsigned iof_idx, tlm::tlm_signal_gp<>& gp, sc_core::sc_time& delay) { + if(delay>SC_ZERO_TIME){ + wait(delay); + delay=SC_ZERO_TIME; + } + const auto mask = 1U<r_iof_en&mask){ + const auto idx = regs->r_iof_sel&mask?1:0; + if(iof_idx == idx){ + auto& socket = pins_o[tag]; + for(size_t i=0; i 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); + new_gp.copy_extensions_from(gp); + socket->nb_transport_fw(new_gp, phase, delay); // we don't care about phase and sync enum + } + } + } } } /* namespace sysc */ diff --git a/riscv.sc/src/sysc/platform.cpp b/riscv.sc/src/sysc/platform.cpp index 40d1e9d..5d5241f 100644 --- a/riscv.sc/src/sysc/platform.cpp +++ b/riscv.sc/src/sysc/platform.cpp @@ -40,6 +40,8 @@ namespace sysc { platform::platform(sc_core::sc_module_name nm) : sc_core::sc_module(nm) +, NAMED(pins_o, 32) +, NAMED(pins_i, 32) , NAMED(i_core_complex) , NAMED(i_router, 12, 1) , NAMED(i_uart0) @@ -54,12 +56,15 @@ platform::platform(sc_core::sc_module_name nm) , NAMED(i_clint) , NAMED(i_mem_qspi) , NAMED(i_mem_ram) -, NAMED(s_clk) +, NAMED(s_tlclk) , NAMED(s_rst) , NAMED(s_global_int, 256) , NAMED(s_local_int, 16) , NAMED(s_core_int) -, NAMED(s_gpio_pins) { +, NAMED(s_dummy, 16) +, NAMED(s_dummy_sck_i, 16) +, NAMED(s_dummy_sck_o, 16) +{ i_core_complex.initiator(i_router.target[0]); size_t i = 0; for (const auto &e : e300_plat_map) { @@ -72,17 +77,18 @@ platform::platform(sc_core::sc_module_name nm) 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_qspi0.clk_i(s_clk); - i_qspi1.clk_i(s_clk); - i_qspi2.clk_i(s_clk); - i_gpio0.clk_i(s_clk); - i_plic.clk_i(s_clk); - 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_uart0.clk_i(s_tlclk); + i_uart1.clk_i(s_tlclk); + i_qspi0.clk_i(s_tlclk); + i_qspi1.clk_i(s_tlclk); + i_qspi2.clk_i(s_tlclk); + 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_clint.tlclk_i(s_tlclk); + i_clint.lfclk_i(s_lfclk); + i_core_complex.clk_i(s_tlclk); i_uart0.rst_i(s_rst); i_uart1.rst_i(s_rst); @@ -107,13 +113,25 @@ platform::platform(sc_core::sc_module_name nm) i_core_complex.global_irq_i(s_core_int); i_core_complex.local_irq_i(s_local_int); - i_gpio0.pins_io(s_gpio_pins); + pins_i(i_gpio0.pins_i); + i_gpio0.pins_o(pins_o); + + i_gpio0.iof0_i[17](i_uart0.tx_o); + i_uart0.rx_i(i_gpio0.iof0_o[16]); + i_uart0.irq_o(s_global_int[3]); + + s_dummy_sck_i[0](i_uart1.tx_o); + 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_clk = 10_ns; + s_tlclk = 10_ns; + s_lfclk = 30517_ns; s_rst = true; wait(10_ns); s_rst = false; diff --git a/riscv.sc/src/sysc/system.cpp b/riscv.sc/src/sysc/system.cpp new file mode 100644 index 0000000..e8212dc --- /dev/null +++ b/riscv.sc/src/sysc/system.cpp @@ -0,0 +1,30 @@ +/* + * system.cpp + * + * Created on: 11.07.2018 + * Author: eyck + */ + +#include "sysc/General/system.h" + +using namespace sysc; + +system::system(sc_core::sc_module_name nm) +: sc_module(nm) +, NAMED(s_gpio, 32) +, NAMED(i_platform) +, NAMED(i_terminal) +{ + for(auto i=0U; i& gp, + tlm::tlm_phase& phase, + sc_core::sc_time& delay)->tlm::tlm_sync_enum{ + this->receive(gp, delay); + return tlm::TLM_COMPLETED; + }); +} + +terminal::~terminal() { +} + +void terminal::receive(tlm::tlm_signal_gp& gp, sc_core::sc_time& delay) { + sysc::tlm_signal_uart_extension* ext; + gp.get_extension(ext); + if(ext && ext->start_time!=last_tx_start){ + uint8_t txdata = static_cast(ext->tx.data); + last_tx_start = ext->start_time; + if(txdata != '\r') queue.push_back(txdata); + if (queue.size() >> 0 && (txdata == '\n' || txdata == 0)) { + std::string msg(queue.begin(), queue.end()-1); + sc_core::sc_time now = sc_core::sc_time_stamp(); + if(handler) + sysc::sc_comm_singleton::inst().execute([this, msg, now](){ + std::stringstream os; + os << "{\"time\":\"" << now << "\",\"message\":\""<handler->send(os.str()); + }); + else + LOG(INFO) << this->name() << " receive: '" << msg << "'"; + queue.clear(); + } + } +} diff --git a/riscv.sc/src/sysc/uart.cpp b/riscv.sc/src/sysc/uart.cpp index f90bd7c..2565f27 100644 --- a/riscv.sc/src/sysc/uart.cpp +++ b/riscv.sc/src/sysc/uart.cpp @@ -37,6 +37,7 @@ #include "sysc/SiFive/uart.h" #include "sysc/sc_comm_singleton.h" +#include "sysc/tlm_extensions.h" #include "scc/report.h" #include "scc/utilities.h" #include "sysc/SiFive/gen/uart_regs.h" @@ -56,25 +57,62 @@ uart::uart(sc_core::sc_module_name nm) , tlm_target<>(clk) , NAMED(clk_i) , NAMED(rst_i) +, NAMED(tx_o) +, NAMED(rx_i) +, NAMED(irq_o) +, NAMED(write_to_ws, false) , NAMEDD(uart_regs, regs) -, NAMED(write_to_ws, false) { +{ regs->registerResources(*this); SC_METHOD(clock_cb); sensitive << clk_i; SC_METHOD(reset_cb); sensitive << rst_i; dont_initialize(); + SC_THREAD(transmit_data); + rx_i.register_nb_transport([this](tlm::tlm_signal_gp& gp, + tlm::tlm_phase& phase, sc_core::sc_time& delay)->tlm::tlm_sync_enum{ + this->receive_data(gp, delay); + return tlm::TLM_COMPLETED; + }); regs->txdata.set_write_cb([this](scc::sc_register ®, uint32_t data) -> bool { if (!this->regs->in_reset()) { reg.put(data); - this->transmit_data(); + tx_fifo.nb_write(static_cast(regs->r_txdata.data)); + regs->r_txdata.full=tx_fifo.num_free()==0; + regs->r_ip.txwm=regs->r_txctrl.txcnt<=(7-tx_fifo.num_free())?1:0; + update_irq(); } return true; }); + regs->rxdata.set_read_cb([this](const scc::sc_register ®, uint32_t& data) -> bool { + if (!this->regs->in_reset()) { + uint8_t val; + if(rx_fifo.nb_read(val)){ + regs->r_rxdata.data=val; + if(regs->r_rxctrl.rxcnt<=rx_fifo.num_available()){ + regs->r_ip.rxwm=1; + update_irq(); + } + } + data = reg.get()®.rdmask; + } + return true; + }); + regs->ie.set_write_cb([this](scc::sc_register ®, uint32_t data) -> bool { + update_irq(); + }); + regs->ip.set_write_cb([this](scc::sc_register ®, uint32_t data) -> bool { + update_irq(); + }); } uart::~uart() {} +void uart::update_irq() { + irq_o=(regs->r_ip.rxwm==1 && regs->r_ie.rxwm==1) || (regs->r_ip.txwm==1 && regs->r_ie.txwm==1); +} + void uart::before_end_of_elaboration() { if(write_to_ws.get_value()) { LOG(TRACE)<<"Adding WS handler for "<<(std::string{"/ws/"}+name()); @@ -95,19 +133,74 @@ void uart::reset_cb() { } void uart::transmit_data() { - if(regs->r_txdata.data != '\r') queue.push_back(regs->r_txdata.data); - if (queue.size() >> 0 && (regs->r_txdata.data == '\n' || regs->r_txdata.data == 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(); + uint8_t txdata; + sc_core::sc_time delay(SC_ZERO_TIME); + tlm::tlm_phase phase(tlm::BEGIN_REQ); + tlm::tlm_signal_gp<> gp; + gp.set_command(tlm::TLM_WRITE_COMMAND); + gp.set_value(true); + tx_o->nb_transport_fw(gp, phase, delay); + while(true){ + wait(tx_fifo.data_written_event()); + while(tx_fifo.nb_read(txdata)){ + regs->r_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; + 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(); +// } + } } } +void uart::receive_data(tlm::tlm_signal_gp<>& gp, sc_core::sc_time& delay) { + sysc::tlm_signal_uart_extension* ext{nullptr}; + gp.get_extension(ext); + if(ext && ext != rx_ext){ + auto data = static_cast(ext->tx.data); + if(ext->tx.parity || ext->tx.data_bits!=8) data = rand(); // random value if wrong config + rx_fifo.write(data); + if(regs->r_rxctrl.rxcnt<=rx_fifo.num_available()){ + regs->r_ip.rxwm=1; + update_irq(); + } + rx_ext=ext; // omit repeated handling of signale changes + } + gp.set_response_status(tlm::TLM_OK_RESPONSE); +} + } /* namespace sysc */ + diff --git a/riscv/incl/iss/arch/riscv_hart_msu_vp.h b/riscv/incl/iss/arch/riscv_hart_msu_vp.h index 4bcdd52..8b6c509 100644 --- a/riscv/incl/iss/arch/riscv_hart_msu_vp.h +++ b/riscv/incl/iss/arch/riscv_hart_msu_vp.h @@ -697,7 +697,7 @@ iss::status riscv_hart_msu_vp::read(const iss::addr_t &addr, unsigned leng } break; case traits::RES: { auto it = atomic_reservation.find(addr.val); - if (it != atomic_reservation.end() && (*it).second != 0) { + if (it != atomic_reservation.end() && it->second != 0) { memset(data, 0xff, length); atomic_reservation.erase(addr.val); } else diff --git a/sc-components b/sc-components index b50df83..019a041 160000 --- a/sc-components +++ b/sc-components @@ -1 +1 @@ -Subproject commit b50df83ebfbf06299613a973552856954ed383c1 +Subproject commit 019a04132a8beb7fcab24d504e3347ca0771ea5f diff --git a/simple-system.json b/simple-system.json index 250a235..129ef12 100644 --- a/simple-system.json +++ b/simple-system.json @@ -1,11 +1,13 @@ { "i_simple_system":{ - "i_uart0":{ - "write_to_ws": true - }, - "i_uart1":{ - "write_to_ws": false - }, - "i_gpio0.write_to_ws": true + "i_platform": { + "i_uart0":{ + "write_to_ws": false + }, + "i_uart1":{ + "write_to_ws": false + }, + "i_gpio0.write_to_ws": false + } } }