From 100822810f2ad98e153996503557388d029ae968 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 23 Jul 2018 22:15:38 +0200 Subject: [PATCH] Added entire system incl. terminal and MCP3008 ADC connected via SPI --- riscv.sc/incl/sysc/General/mcp3008.h | 47 ++++++++ riscv.sc/incl/sysc/General/system.h | 4 + riscv.sc/incl/sysc/General/terminal.h | 4 +- riscv.sc/incl/sysc/SiFive/gpio.h | 2 +- riscv.sc/incl/sysc/SiFive/spi.h | 20 +++- riscv.sc/incl/sysc/SiFive/uart.h | 8 +- riscv.sc/incl/sysc/tlm_extensions.h | 17 +++ riscv.sc/src/sc_main.cpp | 21 ++-- riscv.sc/src/sysc/core_complex.cpp | 6 +- riscv.sc/src/sysc/gpio.cpp | 16 ++- riscv.sc/src/sysc/mcp3008.cpp | 85 +++++++++++++++ riscv.sc/src/sysc/platform.cpp | 13 ++- riscv.sc/src/sysc/plic.cpp | 2 +- riscv.sc/src/sysc/spi.cpp | 148 ++++++++++++++++++++++++++ riscv.sc/src/sysc/system.cpp | 21 +++- riscv.sc/src/sysc/terminal.cpp | 13 ++- riscv.sc/src/sysc/uart.cpp | 33 +++--- simple-system.json | 13 ++- 18 files changed, 423 insertions(+), 50 deletions(-) create mode 100644 riscv.sc/incl/sysc/General/mcp3008.h create mode 100644 riscv.sc/src/sysc/mcp3008.cpp diff --git a/riscv.sc/incl/sysc/General/mcp3008.h b/riscv.sc/incl/sysc/General/mcp3008.h new file mode 100644 index 0000000..2a1ba37 --- /dev/null +++ b/riscv.sc/incl/sysc/General/mcp3008.h @@ -0,0 +1,47 @@ +/* + * mcp3008.h + * + * Created on: 17.07.2018 + * Author: eyck + */ + +#ifndef RISCV_SC_INCL_SYSC_GENERAL_MCP3008_H_ +#define RISCV_SC_INCL_SYSC_GENERAL_MCP3008_H_ + +#include "scc/signal_target_mixin.h" +#include "scc/signal_initiator_mixin.h" +#include "sysc/tlm_extensions.h" +#include +#include "cci_configuration" +#include +#include + +namespace sysc { + +class mcp3008: public sc_core::sc_module { +public: + SC_HAS_PROCESS(mcp3008); + scc::tlm_signal_logic_in sck_i; + scc::tlm_signal_logic_out miso_o; + scc::tlm_signal_logic_in mosi_i; + scc::tlm_signal_logic_in cs_i; + + sc_core::sc_in vref_i; + sc_core::sc_vector> ch_i; + + mcp3008(sc_core::sc_module_name nm); + virtual ~mcp3008(); + +private: + tlm::tlm_sync_enum receive(tlm::tlm_signal_gp &, tlm::tlm_phase &, sc_core::sc_time &); + void do_conversion(); + unsigned idx, rx_bits; + std::array rx_bytes, tx_bytes; + sc_dt::sc_logic mosi_v, miso_v, cs_v; + sysc::tlm_signal_spi_extension* ext, tx_ext; + sc_core::sc_time last_tx_start; +}; + +} /* namespace sysc */ + +#endif /* RISCV_SC_INCL_SYSC_GENERAL_MCP3008_H_ */ diff --git a/riscv.sc/incl/sysc/General/system.h b/riscv.sc/incl/sysc/General/system.h index 07b72d9..d066b0e 100644 --- a/riscv.sc/incl/sysc/General/system.h +++ b/riscv.sc/incl/sysc/General/system.h @@ -10,6 +10,7 @@ #include "sysc/SiFive/platform.h" #include "sysc/General/terminal.h" +#include "sysc/General/mcp3008.h" #include namespace sysc { @@ -24,8 +25,11 @@ public: private: sc_core::sc_vector> s_gpio; sc_core::sc_signal s_rst_n; + sc_core::sc_signal s_vref; + sc_core::sc_vector> s_ana; sysc::platform i_platform; sysc::terminal i_terminal; + sysc::mcp3008 i_adc; void gen_por(); }; diff --git a/riscv.sc/incl/sysc/General/terminal.h b/riscv.sc/incl/sysc/General/terminal.h index d614051..06eb197 100644 --- a/riscv.sc/incl/sysc/General/terminal.h +++ b/riscv.sc/incl/sysc/General/terminal.h @@ -32,8 +32,10 @@ public: cci::cci_param write_to_ws; protected: - std::vector queue; + void before_end_of_elaboration(); void receive(tlm::tlm_signal_gp& gp, sc_core::sc_time& delay); + + std::vector queue; std::shared_ptr handler; sc_core::sc_time last_tx_start=sc_core::SC_ZERO_TIME; }; diff --git a/riscv.sc/incl/sysc/SiFive/gpio.h b/riscv.sc/incl/sysc/SiFive/gpio.h index fa2612d..f0c3284 100644 --- a/riscv.sc/incl/sysc/SiFive/gpio.h +++ b/riscv.sc/incl/sysc/SiFive/gpio.h @@ -83,7 +83,7 @@ protected: 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); + void enable_outputs(uint32_t new_iof_en, uint32_t new_iof_sel); }; } /* namespace sysc */ diff --git a/riscv.sc/incl/sysc/SiFive/spi.h b/riscv.sc/incl/sysc/SiFive/spi.h index 5d0ec2a..c10e258 100644 --- a/riscv.sc/incl/sysc/SiFive/spi.h +++ b/riscv.sc/incl/sysc/SiFive/spi.h @@ -38,6 +38,11 @@ #define _SPI_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 { @@ -47,15 +52,28 @@ class spi : public sc_core::sc_module, public scc::tlm_target<> { public: SC_HAS_PROCESS(spi); sc_core::sc_in clk_i; - sc_core::sc_in rst_i; + sc_core::sc_in rst_i; + scc::tlm_signal_bool_opt_out sck_o; + scc::tlm_signal_bool_opt_out mosi_o; + scc::tlm_signal_bool_opt_in miso_i; + sc_core::sc_vector scs_o; + + sc_core::sc_out irq_o; + + cci::cci_param bit_true_transfer; + spi(sc_core::sc_module_name nm); virtual ~spi() override; 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(); sc_core::sc_time clk; std::unique_ptr regs; + sc_core::sc_fifo rx_fifo, tx_fifo; }; } /* namespace sysc */ diff --git a/riscv.sc/incl/sysc/SiFive/uart.h b/riscv.sc/incl/sysc/SiFive/uart.h index 43fe99e..26defe0 100644 --- a/riscv.sc/incl/sysc/SiFive/uart.h +++ b/riscv.sc/incl/sysc/SiFive/uart.h @@ -58,7 +58,7 @@ public: sc_core::sc_out irq_o; - cci::cci_param write_to_ws; + cci::cci_param bit_true_transfer; uart(sc_core::sc_module_name nm); virtual ~uart() override; @@ -69,13 +69,9 @@ protected: 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; + sc_core::sc_time clk{SC_ZERO_TIME},rx_last_start{SC_ZERO_TIME}; 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; }; } /* namespace sysc */ diff --git a/riscv.sc/incl/sysc/tlm_extensions.h b/riscv.sc/incl/sysc/tlm_extensions.h index b2f5663..cc88599 100644 --- a/riscv.sc/incl/sysc/tlm_extensions.h +++ b/riscv.sc/incl/sysc/tlm_extensions.h @@ -24,6 +24,23 @@ struct tlm_signal_uart_extension : public tlm::tlm_unmanaged_extension { + + struct spi_tx { + unsigned data_bits:5; + bool msb_first:1; + bool s2m_data_valid:1; + unsigned m2s_data, s2m_data; + } tx; + sc_core::sc_time start_time; + + void copy_from(tlm_extension_base const & other) override { + auto& o = static_cast(other); + this->tx=o.tx; + this->start_time=o.start_time; + } +}; + } diff --git a/riscv.sc/src/sc_main.cpp b/riscv.sc/src/sc_main.cpp index 701f3c2..62c5dfb 100644 --- a/riscv.sc/src/sc_main.cpp +++ b/riscv.sc/src/sc_main.cpp @@ -122,11 +122,6 @@ int sc_main(int argc, char *argv[]) { /////////////////////////////////////////////////////////////////////////// iss::init_jit(argc, argv); /////////////////////////////////////////////////////////////////////////// - // set up tracing & transaction recording - /////////////////////////////////////////////////////////////////////////// - auto trace_val = vm["trace"].as(); - scc::tracer trace("simple_system", static_cast(trace_val >> 1), trace_val != 0); - /////////////////////////////////////////////////////////////////////////// // set up configuration /////////////////////////////////////////////////////////////////////////// scc::configurer cfg(vm["config-file"].as()); @@ -134,16 +129,24 @@ int sc_main(int argc, char *argv[]) { // instantiate top level /////////////////////////////////////////////////////////////////////////// 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); + /////////////////////////////////////////////////////////////////////////// + // set up tracing & transaction recording + /////////////////////////////////////////////////////////////////////////// + auto trace_val = vm["trace"].as(); + scc::tracer trace("simple_system", static_cast(trace_val >> 1), trace_val != 0); + /////////////////////////////////////////////////////////////////////////// + // dump configuration if requested + /////////////////////////////////////////////////////////////////////////// if(vm["dump-config"].as().size()>0){ std::ofstream of{vm["dump-config"].as()}; if(of.is_open()) cfg.dump_configuration(of); } cfg.configure(); - // overwrite with command line settings - if (vm["gdb-port"].as()) + /////////////////////////////////////////////////////////////////////////// + // overwrite config with command line settings + /////////////////////////////////////////////////////////////////////////// + if (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_system.i_platform.i_core_complex.dump_ir", vm.count("dump-ir") != 0); diff --git a/riscv.sc/src/sysc/core_complex.cpp b/riscv.sc/src/sysc/core_complex.cpp index 36929a6..4364a8f 100644 --- a/riscv.sc/src/sysc/core_complex.cpp +++ b/riscv.sc/src/sysc/core_complex.cpp @@ -218,7 +218,7 @@ core_complex::core_complex(sc_core::sc_module_name name) , NAMED(timer_irq_i) , NAMED(local_irq_i, 16) , NAMED(elf_file, "") -, NAMED(enable_disass, true) +, NAMED(enable_disass, false) , NAMED(reset_address, 0ULL) , NAMED(gdb_server_port, 0) , NAMED(dump_ir, false) @@ -264,7 +264,11 @@ void core_complex::trace(sc_core::sc_trace_file *trf) {} void core_complex::before_end_of_elaboration() { cpu = make_unique(this); vm = create(cpu.get(), gdb_server_port.get_value(), dump_ir.get_value()); +#ifdef WITH_SCV + vm->setDisassEnabled(enable_disass.get_value() || m_db!=nullptr); +#else vm->setDisassEnabled(enable_disass.get_value()); +#endif auto* srv = debugger::server::get(); if(srv) tgt_adapter = srv->get_target(); if(tgt_adapter) diff --git a/riscv.sc/src/sysc/gpio.cpp b/riscv.sc/src/sysc/gpio.cpp index 1a3c498..6fe8007 100644 --- a/riscv.sc/src/sysc/gpio.cpp +++ b/riscv.sc/src/sysc/gpio.cpp @@ -103,7 +103,14 @@ gpio::gpio(sc_core::sc_module_name nm) }); regs->iof_en.set_write_cb([this](scc::sc_register ®, uint32_t data) -> bool { if (!this->regs->in_reset()) { - enable_outputs(data); + enable_outputs(data, regs->r_iof_sel); + reg.put(data); + } + return true; + }); + regs->iof_sel.set_write_cb([this](scc::sc_register ®, uint32_t data) -> bool { + if (!this->regs->in_reset()) { + enable_outputs(regs->r_iof_en, data); reg.put(data); } return true; @@ -157,12 +164,12 @@ void gpio::update_pins() { } } -void gpio::enable_outputs(uint32_t new_data) { - auto changed_bits = regs->r_iof_en^new_data; +void gpio::enable_outputs(uint32_t new_iof_en, uint32_t new_iof_sel) { + auto changed_bits = (regs->r_iof_en^new_iof_en) | (regs->r_iof_sel^new_iof_sel); 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(new_iof_en&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) @@ -230,6 +237,7 @@ void gpio::iof_input(unsigned int tag, unsigned iof_idx, tlm::tlm_signal_gp<>& g 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 + gp.update_extensions_from(new_gp); } } } diff --git a/riscv.sc/src/sysc/mcp3008.cpp b/riscv.sc/src/sysc/mcp3008.cpp new file mode 100644 index 0000000..8846202 --- /dev/null +++ b/riscv.sc/src/sysc/mcp3008.cpp @@ -0,0 +1,85 @@ +/* + * mcp3008.cpp + * + * Created on: 17.07.2018 + * Author: eyck + */ + +#include "sysc/General/mcp3008.h" +#include +#include + +namespace sysc { + +mcp3008::mcp3008(sc_core::sc_module_name nm) +: sc_core::sc_module(nm) +, NAMED(sck_i) +, NAMED(miso_o) +, NAMED(mosi_i) +, NAMED(cs_i) +, NAMED(vref_i) +, NAMED(ch_i, 8) +, last_tx_start(sc_core::SC_ZERO_TIME) +{ + sck_i.register_nb_transport([this](tlm::tlm_signal_gp& gp, tlm::tlm_phase& phase, sc_core::sc_time& delay) + -> tlm::tlm_sync_enum{ + return tlm::TLM_COMPLETED; + }); + + mosi_i.register_nb_transport([this](tlm::tlm_signal_gp& gp, tlm::tlm_phase& phase, sc_core::sc_time& delay) + -> tlm::tlm_sync_enum{ + if(cs_v==sc_dt::Log_0) + return receive(gp, phase, delay); + }); + + cs_i.register_nb_transport([this](tlm::tlm_signal_gp& gp, tlm::tlm_phase& phase, sc_core::sc_time& delay) + -> tlm::tlm_sync_enum{ + if(cs_v!=sc_dt::Log_0 && gp.get_value()==sc_dt::Log_0){ + idx=0; // falling edge + rx_bits=0; + } + cs_v=gp.get_value(); + return tlm::TLM_COMPLETED; + }); +} + +mcp3008::~mcp3008() { +} + +tlm::tlm_sync_enum mcp3008::receive(tlm::tlm_signal_gp& gp, tlm::tlm_phase& phase, sc_core::sc_time& delay) { + gp.get_extension(ext); + if(ext){ + if( ext->start_time!=last_tx_start){ + assert(ext->tx.data_bits==8); + rx_bytes[idx]=bit_sub<0,8>(ext->tx.m2s_data); + if(idx==1) + do_conversion(); + ext->tx.s2m_data=tx_bytes[idx]; + ext->tx.s2m_data_valid=true; + idx++; + last_tx_start=ext->start_time; + } + } + return tlm::TLM_COMPLETED; +} + +void mcp3008::do_conversion() { + if(rx_bytes[0]==0x1){ + auto mode = bit_sub<7,1>(rx_bytes[1]); + auto channel = bit_sub<4,3>(rx_bytes[1]); + auto vref=vref_i.read(); + if(mode){ // single ended + auto inp = ch_i[channel].read(); + auto norm = inp/vref*1024.0; + auto res = static_cast(norm); + CLOG(DEBUG, SystemC)<<"Converting "<(res); + tx_bytes[2]=bit_sub<0,8>(res); + } else { + tx_bytes[1]=0; + tx_bytes[2]=0; + } + } +} + +} /* namespace sysc */ diff --git a/riscv.sc/src/sysc/platform.cpp b/riscv.sc/src/sysc/platform.cpp index 93c6d66..df6ede4 100644 --- a/riscv.sc/src/sysc/platform.cpp +++ b/riscv.sc/src/sysc/platform.cpp @@ -124,9 +124,20 @@ platform::platform(sc_core::sc_module_name nm) i_uart0.rx_i(i_gpio0.iof0_o[16]); i_uart0.irq_o(s_global_int[3]); + i_gpio0.iof0_i[2](i_qspi1.scs_o[0]); + i_gpio0.iof0_i[3](i_qspi1.mosi_o); + i_qspi1.miso_i(i_gpio0.iof0_o[4]); + i_gpio0.iof0_i[5](i_qspi1.sck_o); + i_gpio0.iof0_i[9](i_qspi1.scs_o[2]); + i_gpio0.iof0_i[10](i_qspi1.scs_o[3]); + + i_qspi0.irq_o(s_global_int[5]); + i_qspi1.irq_o(s_global_int[6]); + i_qspi2.irq_o(s_global_int[7]); + 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]); + i_uart1.irq_o(s_global_int[4]); for(auto& sock:s_dummy_sck_i) sock.error_if_no_callback=false; } diff --git a/riscv.sc/src/sysc/plic.cpp b/riscv.sc/src/sysc/plic.cpp index 1cfb0e7..ca131f3 100644 --- a/riscv.sc/src/sysc/plic.cpp +++ b/riscv.sc/src/sysc/plic.cpp @@ -167,7 +167,7 @@ void plic::handle_pending_int() { void plic::reset_pending_int(uint32_t irq) { // todo: evaluate enable register (see spec) // todo: make sure that pending is set, otherwise don't reset irq ... read spec. - LOG(INFO) << "reset pending interrupt: " << irq; + LOG(TRACE) << "reset pending interrupt: " << irq; // reset related pending bit auto reg_idx = irq>>5; auto bit_ofs = irq & 0x1F; diff --git a/riscv.sc/src/sysc/spi.cpp b/riscv.sc/src/sysc/spi.cpp index cb4b79d..f35e375 100644 --- a/riscv.sc/src/sysc/spi.cpp +++ b/riscv.sc/src/sysc/spi.cpp @@ -36,8 +36,10 @@ #include "sysc/SiFive/spi.h" +#include "sysc/tlm_extensions.h" #include "scc/utilities.h" #include "sysc/SiFive/gen/spi_regs.h" +#include namespace sysc { @@ -46,6 +48,12 @@ spi::spi(sc_core::sc_module_name nm) , tlm_target<>(clk) , NAMED(clk_i) , NAMED(rst_i) +, NAMED(sck_o) +, NAMED(mosi_o) +, NAMED(miso_i) +, NAMED(scs_o, 4) +, NAMED(irq_o) +, NAMED(bit_true_transfer, false) , NAMEDD(spi_regs, regs) { regs->registerResources(*this); SC_METHOD(clock_cb); @@ -53,6 +61,80 @@ spi::spi(sc_core::sc_module_name nm) SC_METHOD(reset_cb); sensitive << rst_i; dont_initialize(); + SC_THREAD(transmit_data); + miso_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); + tx_fifo.nb_write(static_cast(regs->r_txdata.data)); + regs->r_txdata.full=tx_fifo.num_free()==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.empty=0; + regs->r_rxdata.data=val; + if(regs->r_rxmark.rxmark<=rx_fifo.num_available()){ + regs->r_ip.rxwm=1; + update_irq(); + } + } else + regs->r_rxdata.empty=1; + data = reg.get()®.rdmask; + } + return true; + }); + regs->csmode.set_write_cb([this](const scc::sc_register ®, uint32_t& data) -> bool { + if(regs->r_csmode.mode==2 && regs->r_csmode.mode != bit_sub<0, 2>(data) && regs->r_csid<4){ + tlm::tlm_phase phase(tlm::BEGIN_REQ); + sc_core::sc_time delay(SC_ZERO_TIME); + tlm::tlm_signal_gp<> gp; + gp.set_command(tlm::TLM_WRITE_COMMAND); + gp.set_value(true); + scs_o[regs->r_csid]->nb_transport_fw(gp, phase, delay); + } + reg.put(data); + return true; + }); + regs->csid.set_write_cb([this](const scc::sc_register ®, uint32_t& data) -> bool { + if(regs->r_csmode.mode==2 && regs->csid != data && regs->r_csid<4){ + tlm::tlm_phase phase(tlm::BEGIN_REQ); + sc_core::sc_time delay(SC_ZERO_TIME); + tlm::tlm_signal_gp<> gp; + gp.set_command(tlm::TLM_WRITE_COMMAND); + gp.set_value(true); + scs_o[regs->r_csid]->nb_transport_fw(gp, phase, delay); + } + reg.put(data); + return true; + }); + regs->csdef.set_write_cb([this](const scc::sc_register ®, uint32_t& data) -> bool { + auto diff = regs->csdef ^ data; + if(regs->r_csmode.mode==2 && diff!=0 && (regs->r_csid<4) && (diff & (1<r_csid))!=0){ + tlm::tlm_phase phase(tlm::BEGIN_REQ); + sc_core::sc_time delay(SC_ZERO_TIME); + tlm::tlm_signal_gp<> gp; + gp.set_command(tlm::TLM_WRITE_COMMAND); + gp.set_value(true); + scs_o[regs->r_csid]->nb_transport_fw(gp, phase, delay); + } + reg.put(data); + 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(); + }); } spi::~spi() {} @@ -68,4 +150,70 @@ void spi::reset_cb() { regs->reset_stop(); } +void spi::transmit_data() { + uint8_t txdata; + sysc::tlm_signal_spi_extension ext; + tlm::tlm_phase phase(tlm::BEGIN_REQ); + tlm::tlm_signal_gp<> gp; + 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; + + auto set_bit = [&](bool val, scc::tlm_signal_bool_opt_out& socket){ + if(socket.get_interface()==nullptr) return; + gp.set_command(tlm::TLM_WRITE_COMMAND); + gp.set_value(val); + tlm::tlm_phase phase(tlm::BEGIN_REQ); + socket->nb_transport_fw(gp, phase, delay); + }; + + wait(delay); //intentionally 0ns; + while(true){ + wait(tx_fifo.data_written_event()); + if(regs->r_csmode.mode != 3 && regs->r_csid<4) // not in OFF mode + set_bit(false, scs_o[regs->r_csid]); + set_bit(regs->r_sckmode.pol, sck_o); + while(tx_fifo.nb_read(txdata)){ + regs->r_txdata.full=tx_fifo.num_free()==0; + regs->r_ip.txwm=regs->r_txmark.txmark<=(7-tx_fifo.num_free())?1:0; + bit_duration = 2*(regs->r_sckdiv.div+1)*clk; + ext.start_time = sc_core::sc_time_stamp(); + ext.tx.m2s_data=txdata; + ext.tx.s2m_data_valid=false; + set_bit(txdata&0x80, mosi_o); // 8 data bits, MSB first + set_bit(1-regs->r_sckmode.pol, sck_o); + wait(bit_duration/2); + set_bit(regs->r_sckmode.pol, sck_o); + wait(bit_duration/2); + if(bit_true_transfer.get_value()){ + for(size_t i = 0, mask=0x40; i<7; ++i, mask>=1){ + set_bit(txdata&mask, mosi_o); // 8 data bits, MSB first + set_bit(1-regs->r_sckmode.pol, sck_o); + wait(bit_duration/2); + set_bit(regs->r_sckmode.pol, sck_o); + wait(bit_duration/2); + + } + } else + wait(7*bit_duration); + rx_fifo.nb_write(ext.tx.s2m_data&0xff); + if(regs->r_rxmark.rxmark<=rx_fifo.num_available()){ + regs->r_ip.rxwm=1; + update_irq(); + } + } + if(regs->r_csmode.mode == 0 && regs->r_csid<4) // in AUTO mode + set_bit(false, scs_o[regs->r_csid]); + } +} + +void spi::receive_data(tlm::tlm_signal_gp<>& gp, sc_core::sc_time& delay) { +} + +void spi::update_irq() { +} + } /* namespace sysc */ + diff --git a/riscv.sc/src/sysc/system.cpp b/riscv.sc/src/sysc/system.cpp index 8c41971..34842fb 100644 --- a/riscv.sc/src/sysc/system.cpp +++ b/riscv.sc/src/sysc/system.cpp @@ -13,8 +13,11 @@ system::system(sc_core::sc_module_name nm) : sc_module(nm) , NAMED(s_gpio, 32) , NAMED(s_rst_n) +, NAMED(s_vref) +, NAMED(s_ana, 8) , NAMED(i_platform) , NAMED(i_terminal) +, NAMED(i_adc) { // connect platform i_platform.erst_n(s_rst_n); @@ -24,8 +27,18 @@ system::system(sc_core::sc_module_name nm) i_platform.pins_i[i](s_gpio[i].out); } // connect other units - s_gpio[17].out(i_terminal.rx_i); + // terminal i_terminal.tx_o(s_gpio[16].in); + s_gpio[17].out(i_terminal.rx_i); + // adc digital io + s_gpio[2].out(i_adc.cs_i); + s_gpio[3].out(i_adc.mosi_i); + i_adc.miso_o(s_gpio[4].in); + s_gpio[5].out(i_adc.sck_i); + // adc analog inputs + i_adc.ch_i(s_ana); + i_adc.vref_i(s_vref); + SC_THREAD(gen_por); } @@ -37,4 +50,10 @@ void sysc::system::gen_por() { s_rst_n = false; wait(10_ns); s_rst_n = true; + s_vref=1.024; + double val=0.1; + for(auto& sig:s_ana){ + sig=val; + val+=0.12; + } } diff --git a/riscv.sc/src/sysc/terminal.cpp b/riscv.sc/src/sysc/terminal.cpp index f4b7115..54c8c82 100644 --- a/riscv.sc/src/sysc/terminal.cpp +++ b/riscv.sc/src/sysc/terminal.cpp @@ -12,7 +12,9 @@ using namespace sysc; -terminal::terminal() :terminal(sc_core::sc_gen_unique_name("terminal")){ +terminal::terminal() +: terminal(sc_core::sc_gen_unique_name("terminal")) +{ } terminal::terminal(const sc_core::sc_module_name& nm) @@ -33,6 +35,15 @@ terminal::terminal(const sc_core::sc_module_name& nm) terminal::~terminal() { } +void terminal::before_end_of_elaboration() { + if(write_to_ws.get_value()) { + LOG(TRACE)<<"Adding WS handler for "<<(std::string{"/ws/"}+name()); + handler=std::make_shared(); + sc_comm_singleton::inst().registerWebSocketHandler((std::string{"/ws/"}+name()).c_str(), handler); + } +} + + void terminal::receive(tlm::tlm_signal_gp& gp, sc_core::sc_time& delay) { sysc::tlm_signal_uart_extension* ext; gp.get_extension(ext); diff --git a/riscv.sc/src/sysc/uart.cpp b/riscv.sc/src/sysc/uart.cpp index a3a6942..554369d 100644 --- a/riscv.sc/src/sysc/uart.cpp +++ b/riscv.sc/src/sysc/uart.cpp @@ -36,7 +36,6 @@ #include "sysc/SiFive/uart.h" -#include "sysc/sc_comm_singleton.h" #include "sysc/tlm_extensions.h" #include "scc/report.h" #include "scc/utilities.h" @@ -46,12 +45,7 @@ using namespace std; namespace sysc { -namespace { -using namespace seasocks; - - -} uart::uart(sc_core::sc_module_name nm) : sc_core::sc_module(nm) , tlm_target<>(clk) @@ -60,8 +54,10 @@ uart::uart(sc_core::sc_module_name nm) , NAMED(tx_o) , NAMED(rx_i) , NAMED(irq_o) -, NAMED(write_to_ws, false) +, NAMED(bit_true_transfer, false) , NAMEDD(uart_regs, regs) +, NAMED(rx_fifo, 8) +, NAMED(tx_fifo, 8) { regs->registerResources(*this); SC_METHOD(clock_cb); @@ -113,14 +109,6 @@ 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()); - handler=std::make_shared(); - sc_comm_singleton::inst().registerWebSocketHandler((std::string{"/ws/"}+name()).c_str(), handler); - } -} - void uart::clock_cb() { this->clk = clk_i.read(); } @@ -164,10 +152,13 @@ void uart::transmit_data() { ext.tx.baud_rate=static_cast(1/bit_duration.to_seconds()); ext.tx.data=txdata; 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 + if(bit_true_transfer.get_value()){ + for(int i = 8; i>0; --i) + set_bit(txdata&(1<<(i-1))); // 8 data bits, MSB first + if(regs->r_txctrl.nstop) set_bit(true); // stop bit 1 + } else + wait(8*bit_duration); + set_bit(true); // stop bit 1/2 } } } @@ -175,7 +166,7 @@ void uart::transmit_data() { 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){ + if(ext && ext->start_time != rx_last_start){ 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); @@ -183,7 +174,7 @@ void uart::receive_data(tlm::tlm_signal_gp<>& gp, sc_core::sc_time& delay) { regs->r_ip.rxwm=1; update_irq(); } - rx_ext=ext; // omit repeated handling of signale changes + rx_last_start=ext->start_time; // omit repeated handling of signal changes } gp.set_response_status(tlm::TLM_OK_RESPONSE); } diff --git a/simple-system.json b/simple-system.json index 129ef12..ec47338 100644 --- a/simple-system.json +++ b/simple-system.json @@ -2,10 +2,19 @@ "i_simple_system":{ "i_platform": { "i_uart0":{ - "write_to_ws": false + "bit_true_transfer": false }, "i_uart1":{ - "write_to_ws": false + "bit_true_transfer": false + }, + "i_qspi0":{ + "bit_true_transfer": false + }, + "i_qspi1":{ + "bit_true_transfer": false + }, + "i_qspi2":{ + "bit_true_transfer": false }, "i_gpio0.write_to_ws": false }