Browse Source

Added entire system incl. terminal and MCP3008 ADC connected via SPI

Eyck Jentzsch 1 year ago
parent
commit
100822810f

+ 47
- 0
riscv.sc/incl/sysc/General/mcp3008.h View File

@@ -0,0 +1,47 @@
1
+/*
2
+ * mcp3008.h
3
+ *
4
+ *  Created on: 17.07.2018
5
+ *      Author: eyck
6
+ */
7
+
8
+#ifndef RISCV_SC_INCL_SYSC_GENERAL_MCP3008_H_
9
+#define RISCV_SC_INCL_SYSC_GENERAL_MCP3008_H_
10
+
11
+#include "scc/signal_target_mixin.h"
12
+#include "scc/signal_initiator_mixin.h"
13
+#include "sysc/tlm_extensions.h"
14
+#include <tlm/tlm_signal.h>
15
+#include "cci_configuration"
16
+#include <sysc/utils/sc_vector.h>
17
+#include <sysc/kernel/sc_module.h>
18
+
19
+namespace sysc {
20
+
21
+class mcp3008: public sc_core::sc_module {
22
+public:
23
+    SC_HAS_PROCESS(mcp3008);
24
+    scc::tlm_signal_logic_in  sck_i;
25
+    scc::tlm_signal_logic_out miso_o;
26
+    scc::tlm_signal_logic_in  mosi_i;
27
+    scc::tlm_signal_logic_in  cs_i;
28
+
29
+    sc_core::sc_in<double> vref_i;
30
+    sc_core::sc_vector<sc_core::sc_in<double>> ch_i;
31
+
32
+    mcp3008(sc_core::sc_module_name nm);
33
+    virtual ~mcp3008();
34
+
35
+private:
36
+    tlm::tlm_sync_enum receive(tlm::tlm_signal_gp<sc_dt::sc_logic> &, tlm::tlm_phase &, sc_core::sc_time &);
37
+    void do_conversion();
38
+    unsigned idx, rx_bits;
39
+    std::array<uint8_t, 3> rx_bytes, tx_bytes;
40
+    sc_dt::sc_logic mosi_v, miso_v, cs_v;
41
+    sysc::tlm_signal_spi_extension* ext, tx_ext;
42
+    sc_core::sc_time last_tx_start;
43
+};
44
+
45
+} /* namespace sysc */
46
+
47
+#endif /* RISCV_SC_INCL_SYSC_GENERAL_MCP3008_H_ */

+ 4
- 0
riscv.sc/incl/sysc/General/system.h View File

@@ -10,6 +10,7 @@
10 10
 
11 11
 #include "sysc/SiFive/platform.h"
12 12
 #include "sysc/General/terminal.h"
13
+#include "sysc/General/mcp3008.h"
13 14
 #include <systemc>
14 15
 
15 16
 namespace sysc {
@@ -24,8 +25,11 @@ public:
24 25
 private:
25 26
     sc_core::sc_vector<tlm::tlm_signal<sc_dt::sc_logic>> s_gpio;
26 27
     sc_core::sc_signal<bool> s_rst_n;
28
+    sc_core::sc_signal<double> s_vref;
29
+    sc_core::sc_vector<sc_core::sc_signal<double>> s_ana;
27 30
     sysc::platform i_platform;
28 31
     sysc::terminal i_terminal;
32
+    sysc::mcp3008 i_adc;
29 33
     void gen_por();
30 34
 };
31 35
 

+ 3
- 1
riscv.sc/incl/sysc/General/terminal.h View File

@@ -32,8 +32,10 @@ public:
32 32
     cci::cci_param<bool> write_to_ws;
33 33
 
34 34
 protected:
35
-    std::vector<uint8_t> queue;
35
+    void before_end_of_elaboration();
36 36
     void receive(tlm::tlm_signal_gp<sc_dt::sc_logic>& gp, sc_core::sc_time& delay);
37
+
38
+    std::vector<uint8_t> queue;
37 39
     std::shared_ptr<sysc::WsHandler> handler;
38 40
     sc_core::sc_time last_tx_start=sc_core::SC_ZERO_TIME;
39 41
 };

+ 1
- 1
riscv.sc/incl/sysc/SiFive/gpio.h View File

@@ -83,7 +83,7 @@ protected:
83 83
 
84 84
 private:
85 85
     tlm::tlm_phase write_output(tlm::tlm_signal_gp<sc_dt::sc_logic>& gp, size_t i, sc_dt::sc_logic val);
86
-    void enable_outputs(uint32_t new_data);
86
+    void enable_outputs(uint32_t new_iof_en, uint32_t new_iof_sel);
87 87
 };
88 88
 
89 89
 } /* namespace sysc */

+ 19
- 1
riscv.sc/incl/sysc/SiFive/spi.h View File

@@ -38,6 +38,11 @@
38 38
 #define _SPI_H_
39 39
 
40 40
 #include "scc/tlm_target.h"
41
+#include "scc/signal_target_mixin.h"
42
+#include "scc/signal_initiator_mixin.h"
43
+#include <tlm/tlm_signal.h>
44
+#include "cci_configuration"
45
+#include <sysc/utils/sc_vector.h>
41 46
 
42 47
 namespace sysc {
43 48
 
@@ -47,15 +52,28 @@ class spi : public sc_core::sc_module, public scc::tlm_target<> {
47 52
 public:
48 53
     SC_HAS_PROCESS(spi);
49 54
     sc_core::sc_in<sc_core::sc_time> clk_i;
50
-    sc_core::sc_in<bool> rst_i;
55
+    sc_core::sc_in<bool>             rst_i;
56
+    scc::tlm_signal_bool_opt_out         sck_o;
57
+    scc::tlm_signal_bool_opt_out         mosi_o;
58
+    scc::tlm_signal_bool_opt_in          miso_i;
59
+    sc_core::sc_vector<scc::tlm_signal_bool_opt_out> scs_o;
60
+
61
+    sc_core::sc_out<bool> irq_o;
62
+
63
+    cci::cci_param<bool> bit_true_transfer;
64
+
51 65
     spi(sc_core::sc_module_name nm);
52 66
     virtual ~spi() override;
53 67
 
54 68
 protected:
55 69
     void clock_cb();
56 70
     void reset_cb();
71
+    void transmit_data();
72
+    void receive_data(tlm::tlm_signal_gp<>& gp, sc_core::sc_time& delay);
73
+    void update_irq();
57 74
     sc_core::sc_time clk;
58 75
     std::unique_ptr<spi_regs> regs;
76
+    sc_core::sc_fifo<uint8_t> rx_fifo, tx_fifo;
59 77
 };
60 78
 
61 79
 } /* namespace sysc */

+ 2
- 6
riscv.sc/incl/sysc/SiFive/uart.h View File

@@ -58,7 +58,7 @@ public:
58 58
 
59 59
     sc_core::sc_out<bool> irq_o;
60 60
 
61
-    cci::cci_param<bool> write_to_ws;
61
+    cci::cci_param<bool> bit_true_transfer;
62 62
 
63 63
     uart(sc_core::sc_module_name nm);
64 64
     virtual ~uart() override;
@@ -69,13 +69,9 @@ protected:
69 69
     void transmit_data();
70 70
     void receive_data(tlm::tlm_signal_gp<>& gp, sc_core::sc_time& delay);
71 71
     void update_irq();
72
-    void before_end_of_elaboration();
73
-    sc_core::sc_time clk;
72
+    sc_core::sc_time clk{SC_ZERO_TIME},rx_last_start{SC_ZERO_TIME};
74 73
     std::unique_ptr<uart_regs> regs;
75 74
     sc_core::sc_fifo<uint8_t> rx_fifo, tx_fifo;
76
-    std::vector<uint8_t> queue;
77
-    sysc::tlm_signal_uart_extension *rx_ext, *tx_ext;
78
-    std::shared_ptr<sysc::WsHandler> handler;
79 75
 };
80 76
 
81 77
 } /* namespace sysc */

+ 17
- 0
riscv.sc/incl/sysc/tlm_extensions.h View File

@@ -24,6 +24,23 @@ struct tlm_signal_uart_extension : public tlm::tlm_unmanaged_extension<tlm_signa
24 24
 
25 25
 };
26 26
 
27
+struct tlm_signal_spi_extension : public tlm::tlm_unmanaged_extension<tlm_signal_spi_extension> {
28
+
29
+    struct spi_tx {
30
+        unsigned data_bits:5;
31
+        bool msb_first:1;
32
+        bool s2m_data_valid:1;
33
+        unsigned m2s_data, s2m_data;
34
+    } tx;
35
+    sc_core::sc_time start_time;
36
+
37
+    void copy_from(tlm_extension_base const & other) override {
38
+        auto& o = static_cast<const type&>(other);
39
+        this->tx=o.tx;
40
+        this->start_time=o.start_time;
41
+    }
42
+};
43
+
27 44
 }
28 45
 
29 46
 

+ 12
- 9
riscv.sc/src/sc_main.cpp View File

@@ -122,11 +122,6 @@ int sc_main(int argc, char *argv[]) {
122 122
     ///////////////////////////////////////////////////////////////////////////
123 123
     iss::init_jit(argc, argv);
124 124
     ///////////////////////////////////////////////////////////////////////////
125
-    // set up tracing & transaction recording
126
-    ///////////////////////////////////////////////////////////////////////////
127
-    auto trace_val = vm["trace"].as<unsigned>();
128
-    scc::tracer trace("simple_system", static_cast<scc::tracer::file_type>(trace_val >> 1), trace_val != 0);
129
-    ///////////////////////////////////////////////////////////////////////////
130 125
     // set up configuration
131 126
     ///////////////////////////////////////////////////////////////////////////
132 127
     scc::configurer cfg(vm["config-file"].as<std::string>());
@@ -134,16 +129,24 @@ int sc_main(int argc, char *argv[]) {
134 129
     // instantiate top level
135 130
     ///////////////////////////////////////////////////////////////////////////
136 131
     sysc::system i_system("i_system");
137
-    // sr_report_handler::add_sc_object_to_filter(&i_simple_system.i_master,
138
-    // sc_core::SC_WARNING, sc_core::SC_MEDIUM);
132
+    ///////////////////////////////////////////////////////////////////////////
133
+    // set up tracing & transaction recording
134
+    ///////////////////////////////////////////////////////////////////////////
135
+    auto trace_val = vm["trace"].as<unsigned>();
136
+    scc::tracer trace("simple_system", static_cast<scc::tracer::file_type>(trace_val >> 1), trace_val != 0);
137
+    ///////////////////////////////////////////////////////////////////////////
138
+    // dump configuration if requested
139
+    ///////////////////////////////////////////////////////////////////////////
139 140
     if(vm["dump-config"].as<std::string>().size()>0){
140 141
     	std::ofstream of{vm["dump-config"].as<std::string>()};
141 142
     	if(of.is_open())
142 143
     	    cfg.dump_configuration(of);
143 144
     }
144 145
 	cfg.configure();
145
-    // overwrite with command line settings
146
-    if (vm["gdb-port"].as<unsigned short>())
146
+    ///////////////////////////////////////////////////////////////////////////
147
+    // overwrite config with command line settings
148
+    ///////////////////////////////////////////////////////////////////////////
149
+   if (vm["gdb-port"].as<unsigned short>())
147 150
     	cfg.set_value("i_system.i_platform.i_core_complex.gdb_server_port", vm["gdb-port"].as<unsigned short>());
148 151
     if (vm.count("dump-ir"))
149 152
     	cfg.set_value("i_system.i_platform.i_core_complex.dump_ir", vm.count("dump-ir") != 0);

+ 5
- 1
riscv.sc/src/sysc/core_complex.cpp View File

@@ -218,7 +218,7 @@ core_complex::core_complex(sc_core::sc_module_name name)
218 218
 , NAMED(timer_irq_i)
219 219
 , NAMED(local_irq_i, 16)
220 220
 , NAMED(elf_file, "")
221
-, NAMED(enable_disass, true)
221
+, NAMED(enable_disass, false)
222 222
 , NAMED(reset_address, 0ULL)
223 223
 , NAMED(gdb_server_port, 0)
224 224
 , NAMED(dump_ir, false)
@@ -264,7 +264,11 @@ void core_complex::trace(sc_core::sc_trace_file *trf) {}
264 264
 void core_complex::before_end_of_elaboration() {
265 265
     cpu = make_unique<core_wrapper>(this);
266 266
     vm = create<arch::rv32imac>(cpu.get(), gdb_server_port.get_value(), dump_ir.get_value());
267
+#ifdef WITH_SCV
268
+    vm->setDisassEnabled(enable_disass.get_value() || m_db!=nullptr);
269
+#else
267 270
     vm->setDisassEnabled(enable_disass.get_value());
271
+#endif
268 272
     auto* srv = debugger::server<debugger::gdb_session>::get();
269 273
     if(srv) tgt_adapter = srv->get_target();
270 274
     if(tgt_adapter)

+ 12
- 4
riscv.sc/src/sysc/gpio.cpp View File

@@ -103,7 +103,14 @@ gpio::gpio(sc_core::sc_module_name nm)
103 103
     });
104 104
     regs->iof_en.set_write_cb([this](scc::sc_register<uint32_t> &reg, uint32_t data) -> bool {
105 105
         if (!this->regs->in_reset()) {
106
-            enable_outputs(data);
106
+            enable_outputs(data, regs->r_iof_sel);
107
+            reg.put(data);
108
+        }
109
+        return true;
110
+    });
111
+    regs->iof_sel.set_write_cb([this](scc::sc_register<uint32_t> &reg, uint32_t data) -> bool {
112
+        if (!this->regs->in_reset()) {
113
+            enable_outputs(regs->r_iof_en, data);
107 114
             reg.put(data);
108 115
         }
109 116
         return true;
@@ -157,12 +164,12 @@ void gpio::update_pins() {
157 164
 	}
158 165
 }
159 166
 
160
-void gpio::enable_outputs(uint32_t new_data) {
161
-    auto changed_bits = regs->r_iof_en^new_data;
167
+void gpio::enable_outputs(uint32_t new_iof_en, uint32_t new_iof_sel) {
168
+    auto changed_bits = (regs->r_iof_en^new_iof_en) | (regs->r_iof_sel^new_iof_sel);
162 169
     tlm::tlm_signal_gp<sc_dt::sc_logic> gp;
163 170
     for(size_t i=0, mask=1; i<32; ++i, mask<<=1){
164 171
         if(changed_bits&mask){
165
-            if(new_data&mask){
172
+            if(new_iof_en&mask){
166 173
                 if((regs->r_iof_sel&mask)==0 && iof0_i[i].size()>0){
167 174
                     tlm::tlm_phase phase = write_output(gp, i, last_iof0[i]?sc_dt::Log_1:sc_dt::Log_0);
168 175
                 } 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
230 237
                 new_gp.set_value(val?sc_dt::Log_1:sc_dt::Log_0);
231 238
                 new_gp.copy_extensions_from(gp);
232 239
                 socket->nb_transport_fw(new_gp, phase, delay); // we don't care about phase and sync enum
240
+                gp.update_extensions_from(new_gp);
233 241
             }
234 242
         }
235 243
     }

+ 85
- 0
riscv.sc/src/sysc/mcp3008.cpp View File

@@ -0,0 +1,85 @@
1
+/*
2
+ * mcp3008.cpp
3
+ *
4
+ *  Created on: 17.07.2018
5
+ *      Author: eyck
6
+ */
7
+
8
+#include "sysc/General/mcp3008.h"
9
+#include <scc/report.h>
10
+#include <util/ities.h>
11
+
12
+namespace sysc {
13
+
14
+mcp3008::mcp3008(sc_core::sc_module_name nm)
15
+: sc_core::sc_module(nm)
16
+, NAMED(sck_i)
17
+, NAMED(miso_o)
18
+, NAMED(mosi_i)
19
+, NAMED(cs_i)
20
+, NAMED(vref_i)
21
+, NAMED(ch_i, 8)
22
+, last_tx_start(sc_core::SC_ZERO_TIME)
23
+{
24
+    sck_i.register_nb_transport([this](tlm::tlm_signal_gp<sc_dt::sc_logic>& gp, tlm::tlm_phase& phase, sc_core::sc_time& delay)
25
+            -> tlm::tlm_sync_enum{
26
+        return tlm::TLM_COMPLETED;
27
+    });
28
+
29
+    mosi_i.register_nb_transport([this](tlm::tlm_signal_gp<sc_dt::sc_logic>& gp, tlm::tlm_phase& phase, sc_core::sc_time& delay)
30
+            -> tlm::tlm_sync_enum{
31
+        if(cs_v==sc_dt::Log_0)
32
+            return receive(gp, phase, delay);
33
+    });
34
+
35
+    cs_i.register_nb_transport([this](tlm::tlm_signal_gp<sc_dt::sc_logic>& gp, tlm::tlm_phase& phase, sc_core::sc_time& delay)
36
+            -> tlm::tlm_sync_enum{
37
+        if(cs_v!=sc_dt::Log_0 && gp.get_value()==sc_dt::Log_0){
38
+            idx=0; // falling edge
39
+            rx_bits=0;
40
+        }
41
+        cs_v=gp.get_value();
42
+        return tlm::TLM_COMPLETED;
43
+    });
44
+}
45
+
46
+mcp3008::~mcp3008() {
47
+}
48
+
49
+tlm::tlm_sync_enum mcp3008::receive(tlm::tlm_signal_gp<sc_dt::sc_logic>& gp, tlm::tlm_phase& phase, sc_core::sc_time& delay) {
50
+    gp.get_extension(ext);
51
+    if(ext){
52
+        if( ext->start_time!=last_tx_start){
53
+            assert(ext->tx.data_bits==8);
54
+            rx_bytes[idx]=bit_sub<0,8>(ext->tx.m2s_data);
55
+            if(idx==1)
56
+                do_conversion();
57
+            ext->tx.s2m_data=tx_bytes[idx];
58
+            ext->tx.s2m_data_valid=true;
59
+            idx++;
60
+            last_tx_start=ext->start_time;
61
+        }
62
+    }
63
+    return tlm::TLM_COMPLETED;
64
+}
65
+
66
+void mcp3008::do_conversion() {
67
+    if(rx_bytes[0]==0x1){
68
+        auto mode = bit_sub<7,1>(rx_bytes[1]);
69
+        auto channel = bit_sub<4,3>(rx_bytes[1]);
70
+        auto vref=vref_i.read();
71
+        if(mode){ // single ended
72
+            auto inp = ch_i[channel].read();
73
+            auto norm = inp/vref*1024.0;
74
+            auto res = static_cast<int>(norm);
75
+            CLOG(DEBUG, SystemC)<<"Converting "<<inp<<" to "<<norm<<" as int "<<res;
76
+            tx_bytes[1]=bit_sub<8,2>(res);
77
+            tx_bytes[2]=bit_sub<0,8>(res);
78
+        } else {
79
+            tx_bytes[1]=0;
80
+            tx_bytes[2]=0;
81
+        }
82
+    }
83
+}
84
+
85
+} /* namespace sysc */

+ 12
- 1
riscv.sc/src/sysc/platform.cpp View File

@@ -124,9 +124,20 @@ platform::platform(sc_core::sc_module_name nm)
124 124
     i_uart0.rx_i(i_gpio0.iof0_o[16]);
125 125
     i_uart0.irq_o(s_global_int[3]);
126 126
 
127
+    i_gpio0.iof0_i[2](i_qspi1.scs_o[0]);
128
+    i_gpio0.iof0_i[3](i_qspi1.mosi_o);
129
+    i_qspi1.miso_i(i_gpio0.iof0_o[4]);
130
+    i_gpio0.iof0_i[5](i_qspi1.sck_o);
131
+    i_gpio0.iof0_i[9](i_qspi1.scs_o[2]);
132
+    i_gpio0.iof0_i[10](i_qspi1.scs_o[3]);
133
+
134
+    i_qspi0.irq_o(s_global_int[5]);
135
+    i_qspi1.irq_o(s_global_int[6]);
136
+    i_qspi2.irq_o(s_global_int[7]);
137
+
127 138
     s_dummy_sck_i[0](i_uart1.tx_o);
128 139
     i_uart1.rx_i(s_dummy_sck_o[0]);
129
-    i_uart1.irq_o(s_dummy[0]);
140
+    i_uart1.irq_o(s_global_int[4]);
130 141
 
131 142
     for(auto& sock:s_dummy_sck_i) sock.error_if_no_callback=false;
132 143
 }

+ 1
- 1
riscv.sc/src/sysc/plic.cpp View File

@@ -167,7 +167,7 @@ void plic::handle_pending_int() {
167 167
 void plic::reset_pending_int(uint32_t irq) {
168 168
     // todo: evaluate enable register (see spec)
169 169
     // todo: make sure that pending is set, otherwise don't reset irq ... read spec.
170
-    LOG(INFO) << "reset pending interrupt: " << irq;
170
+    LOG(TRACE) << "reset pending interrupt: " << irq;
171 171
     // reset related pending bit
172 172
 	auto reg_idx = irq>>5;
173 173
 	auto bit_ofs = irq & 0x1F;

+ 148
- 0
riscv.sc/src/sysc/spi.cpp View File

@@ -36,8 +36,10 @@
36 36
 
37 37
 #include "sysc/SiFive/spi.h"
38 38
 
39
+#include "sysc/tlm_extensions.h"
39 40
 #include "scc/utilities.h"
40 41
 #include "sysc/SiFive/gen/spi_regs.h"
42
+#include <util/ities.h>
41 43
 
42 44
 namespace sysc {
43 45
 
@@ -46,6 +48,12 @@ spi::spi(sc_core::sc_module_name nm)
46 48
 , tlm_target<>(clk)
47 49
 , NAMED(clk_i)
48 50
 , NAMED(rst_i)
51
+, NAMED(sck_o)
52
+, NAMED(mosi_o)
53
+, NAMED(miso_i)
54
+, NAMED(scs_o, 4)
55
+, NAMED(irq_o)
56
+, NAMED(bit_true_transfer, false)
49 57
 , NAMEDD(spi_regs, regs) {
50 58
     regs->registerResources(*this);
51 59
     SC_METHOD(clock_cb);
@@ -53,6 +61,80 @@ spi::spi(sc_core::sc_module_name nm)
53 61
     SC_METHOD(reset_cb);
54 62
     sensitive << rst_i;
55 63
     dont_initialize();
64
+    SC_THREAD(transmit_data);
65
+    miso_i.register_nb_transport([this](tlm::tlm_signal_gp<bool>& gp,
66
+            tlm::tlm_phase& phase, sc_core::sc_time& delay)->tlm::tlm_sync_enum{
67
+       this->receive_data(gp, delay);
68
+       return tlm::TLM_COMPLETED;
69
+    });
70
+    regs->txdata.set_write_cb([this](scc::sc_register<uint32_t> &reg, uint32_t data) -> bool {
71
+        if (!this->regs->in_reset()) {
72
+            reg.put(data);
73
+            tx_fifo.nb_write(static_cast<uint8_t>(regs->r_txdata.data));
74
+            regs->r_txdata.full=tx_fifo.num_free()==0;
75
+            update_irq();
76
+        }
77
+        return true;
78
+    });
79
+    regs->rxdata.set_read_cb([this](const scc::sc_register<uint32_t> &reg, uint32_t& data) -> bool {
80
+        if (!this->regs->in_reset()) {
81
+            uint8_t val;
82
+            if(rx_fifo.nb_read(val)){
83
+                regs->r_rxdata.empty=0;
84
+                regs->r_rxdata.data=val;
85
+                if(regs->r_rxmark.rxmark<=rx_fifo.num_available()){
86
+                    regs->r_ip.rxwm=1;
87
+                    update_irq();
88
+                }
89
+            } else
90
+                regs->r_rxdata.empty=1;
91
+            data = reg.get()&reg.rdmask;
92
+        }
93
+        return true;
94
+    });
95
+    regs->csmode.set_write_cb([this](const scc::sc_register<uint32_t> &reg, uint32_t& data) -> bool {
96
+        if(regs->r_csmode.mode==2 && regs->r_csmode.mode != bit_sub<0, 2>(data) && regs->r_csid<4){
97
+            tlm::tlm_phase phase(tlm::BEGIN_REQ);
98
+            sc_core::sc_time delay(SC_ZERO_TIME);
99
+            tlm::tlm_signal_gp<> gp;
100
+            gp.set_command(tlm::TLM_WRITE_COMMAND);
101
+            gp.set_value(true);
102
+            scs_o[regs->r_csid]->nb_transport_fw(gp, phase, delay);
103
+        }
104
+        reg.put(data);
105
+        return true;
106
+    });
107
+    regs->csid.set_write_cb([this](const scc::sc_register<uint32_t> &reg, uint32_t& data) -> bool {
108
+        if(regs->r_csmode.mode==2 && regs->csid != data && regs->r_csid<4){
109
+            tlm::tlm_phase phase(tlm::BEGIN_REQ);
110
+            sc_core::sc_time delay(SC_ZERO_TIME);
111
+            tlm::tlm_signal_gp<> gp;
112
+            gp.set_command(tlm::TLM_WRITE_COMMAND);
113
+            gp.set_value(true);
114
+            scs_o[regs->r_csid]->nb_transport_fw(gp, phase, delay);
115
+        }
116
+        reg.put(data);
117
+        return true;
118
+    });
119
+    regs->csdef.set_write_cb([this](const scc::sc_register<uint32_t> &reg, uint32_t& data) -> bool {
120
+        auto diff = regs->csdef ^ data;
121
+        if(regs->r_csmode.mode==2 && diff!=0 && (regs->r_csid<4) && (diff & (1<<regs->r_csid))!=0){
122
+            tlm::tlm_phase phase(tlm::BEGIN_REQ);
123
+            sc_core::sc_time delay(SC_ZERO_TIME);
124
+            tlm::tlm_signal_gp<> gp;
125
+            gp.set_command(tlm::TLM_WRITE_COMMAND);
126
+            gp.set_value(true);
127
+            scs_o[regs->r_csid]->nb_transport_fw(gp, phase, delay);
128
+        }
129
+        reg.put(data);
130
+        return true;
131
+    });
132
+    regs->ie.set_write_cb([this](scc::sc_register<uint32_t> &reg, uint32_t data) -> bool {
133
+        update_irq();
134
+    });
135
+    regs->ip.set_write_cb([this](scc::sc_register<uint32_t> &reg, uint32_t data) -> bool {
136
+        update_irq();
137
+    });
56 138
 }
57 139
 
58 140
 spi::~spi() {}
@@ -68,4 +150,70 @@ void spi::reset_cb() {
68 150
         regs->reset_stop();
69 151
 }
70 152
 
153
+void spi::transmit_data() {
154
+    uint8_t txdata;
155
+    sysc::tlm_signal_spi_extension ext;
156
+    tlm::tlm_phase phase(tlm::BEGIN_REQ);
157
+    tlm::tlm_signal_gp<> gp;
158
+    sc_core::sc_time delay(SC_ZERO_TIME);
159
+    sc_core::sc_time bit_duration(SC_ZERO_TIME);
160
+
161
+    gp.set_extension(&ext);
162
+    ext.tx.data_bits=8;
163
+
164
+    auto set_bit = [&](bool val, scc::tlm_signal_bool_opt_out& socket){
165
+        if(socket.get_interface()==nullptr) return;
166
+        gp.set_command(tlm::TLM_WRITE_COMMAND);
167
+        gp.set_value(val);
168
+        tlm::tlm_phase phase(tlm::BEGIN_REQ);
169
+        socket->nb_transport_fw(gp, phase, delay);
170
+    };
171
+
172
+    wait(delay); //intentionally 0ns;
173
+    while(true){
174
+        wait(tx_fifo.data_written_event());
175
+        if(regs->r_csmode.mode != 3 && regs->r_csid<4) // not in OFF mode
176
+            set_bit(false, scs_o[regs->r_csid]);
177
+        set_bit(regs->r_sckmode.pol, sck_o);
178
+        while(tx_fifo.nb_read(txdata)){
179
+            regs->r_txdata.full=tx_fifo.num_free()==0;
180
+            regs->r_ip.txwm=regs->r_txmark.txmark<=(7-tx_fifo.num_free())?1:0;
181
+            bit_duration = 2*(regs->r_sckdiv.div+1)*clk;
182
+            ext.start_time = sc_core::sc_time_stamp();
183
+            ext.tx.m2s_data=txdata;
184
+            ext.tx.s2m_data_valid=false;
185
+            set_bit(txdata&0x80, mosi_o); // 8 data bits, MSB first
186
+            set_bit(1-regs->r_sckmode.pol, sck_o);
187
+            wait(bit_duration/2);
188
+            set_bit(regs->r_sckmode.pol, sck_o);
189
+            wait(bit_duration/2);
190
+            if(bit_true_transfer.get_value()){
191
+                for(size_t i = 0, mask=0x40; i<7; ++i, mask>=1){
192
+                    set_bit(txdata&mask, mosi_o); // 8 data bits, MSB first
193
+                    set_bit(1-regs->r_sckmode.pol, sck_o);
194
+                    wait(bit_duration/2);
195
+                    set_bit(regs->r_sckmode.pol, sck_o);
196
+                    wait(bit_duration/2);
197
+
198
+                }
199
+            } else
200
+                wait(7*bit_duration);
201
+            rx_fifo.nb_write(ext.tx.s2m_data&0xff);
202
+            if(regs->r_rxmark.rxmark<=rx_fifo.num_available()){
203
+                regs->r_ip.rxwm=1;
204
+                update_irq();
205
+            }
206
+        }
207
+        if(regs->r_csmode.mode == 0 && regs->r_csid<4) // in AUTO mode
208
+            set_bit(false, scs_o[regs->r_csid]);
209
+    }
210
+}
211
+
212
+void spi::receive_data(tlm::tlm_signal_gp<>& gp, sc_core::sc_time& delay) {
213
+}
214
+
215
+void spi::update_irq() {
216
+}
217
+
71 218
 } /* namespace sysc */
219
+

+ 20
- 1
riscv.sc/src/sysc/system.cpp View File

@@ -13,8 +13,11 @@ system::system(sc_core::sc_module_name nm)
13 13
 : sc_module(nm)
14 14
 , NAMED(s_gpio, 32)
15 15
 , NAMED(s_rst_n)
16
+, NAMED(s_vref)
17
+, NAMED(s_ana, 8)
16 18
 , NAMED(i_platform)
17 19
 , NAMED(i_terminal)
20
+, NAMED(i_adc)
18 21
 {
19 22
     // connect platform
20 23
     i_platform.erst_n(s_rst_n);
@@ -24,8 +27,18 @@ system::system(sc_core::sc_module_name nm)
24 27
       i_platform.pins_i[i](s_gpio[i].out);
25 28
     }
26 29
     // connect other units
27
-    s_gpio[17].out(i_terminal.rx_i);
30
+    // terminal
28 31
     i_terminal.tx_o(s_gpio[16].in);
32
+    s_gpio[17].out(i_terminal.rx_i);
33
+    // adc digital io
34
+    s_gpio[2].out(i_adc.cs_i);
35
+    s_gpio[3].out(i_adc.mosi_i);
36
+    i_adc.miso_o(s_gpio[4].in);
37
+    s_gpio[5].out(i_adc.sck_i);
38
+    // adc analog inputs
39
+    i_adc.ch_i(s_ana);
40
+    i_adc.vref_i(s_vref);
41
+
29 42
     SC_THREAD(gen_por);
30 43
 }
31 44
 
@@ -37,4 +50,10 @@ void sysc::system::gen_por() {
37 50
     s_rst_n = false;
38 51
     wait(10_ns);
39 52
     s_rst_n = true;
53
+    s_vref=1.024;
54
+    double val=0.1;
55
+    for(auto& sig:s_ana){
56
+        sig=val;
57
+        val+=0.12;
58
+    }
40 59
 }

+ 12
- 1
riscv.sc/src/sysc/terminal.cpp View File

@@ -12,7 +12,9 @@
12 12
 
13 13
 using namespace sysc;
14 14
 
15
-terminal::terminal() :terminal(sc_core::sc_gen_unique_name("terminal")){
15
+terminal::terminal()
16
+: terminal(sc_core::sc_gen_unique_name("terminal"))
17
+{
16 18
 }
17 19
 
18 20
 terminal::terminal(const sc_core::sc_module_name& nm)
@@ -33,6 +35,15 @@ terminal::terminal(const sc_core::sc_module_name& nm)
33 35
 terminal::~terminal() {
34 36
 }
35 37
 
38
+void terminal::before_end_of_elaboration() {
39
+    if(write_to_ws.get_value()) {
40
+        LOG(TRACE)<<"Adding WS handler for "<<(std::string{"/ws/"}+name());
41
+        handler=std::make_shared<WsHandler>();
42
+        sc_comm_singleton::inst().registerWebSocketHandler((std::string{"/ws/"}+name()).c_str(), handler);
43
+    }
44
+}
45
+
46
+
36 47
 void terminal::receive(tlm::tlm_signal_gp<sc_dt::sc_logic>& gp, sc_core::sc_time& delay) {
37 48
     sysc::tlm_signal_uart_extension* ext;
38 49
     gp.get_extension(ext);

+ 12
- 21
riscv.sc/src/sysc/uart.cpp View File

@@ -36,7 +36,6 @@
36 36
 
37 37
 #include "sysc/SiFive/uart.h"
38 38
 
39
-#include "sysc/sc_comm_singleton.h"
40 39
 #include "sysc/tlm_extensions.h"
41 40
 #include "scc/report.h"
42 41
 #include "scc/utilities.h"
@@ -46,12 +45,7 @@ using namespace std;
46 45
 
47 46
 
48 47
 namespace sysc {
49
-namespace {
50 48
 
51
-using namespace seasocks;
52
-
53
-
54
-}
55 49
 uart::uart(sc_core::sc_module_name nm)
56 50
 : sc_core::sc_module(nm)
57 51
 , tlm_target<>(clk)
@@ -60,8 +54,10 @@ uart::uart(sc_core::sc_module_name nm)
60 54
 , NAMED(tx_o)
61 55
 , NAMED(rx_i)
62 56
 , NAMED(irq_o)
63
-, NAMED(write_to_ws, false)
57
+, NAMED(bit_true_transfer, false)
64 58
 , NAMEDD(uart_regs, regs)
59
+, NAMED(rx_fifo, 8)
60
+, NAMED(tx_fifo, 8)
65 61
 {
66 62
     regs->registerResources(*this);
67 63
     SC_METHOD(clock_cb);
@@ -113,14 +109,6 @@ void uart::update_irq() {
113 109
     irq_o=(regs->r_ip.rxwm==1 && regs->r_ie.rxwm==1) || (regs->r_ip.txwm==1 && regs->r_ie.txwm==1);
114 110
 }
115 111
 
116
-void uart::before_end_of_elaboration() {
117
-	if(write_to_ws.get_value()) {
118
-	    LOG(TRACE)<<"Adding WS handler for "<<(std::string{"/ws/"}+name());
119
-	    handler=std::make_shared<WsHandler>();
120
-	    sc_comm_singleton::inst().registerWebSocketHandler((std::string{"/ws/"}+name()).c_str(), handler);
121
-	}
122
-}
123
-
124 112
 void uart::clock_cb() {
125 113
 	this->clk = clk_i.read();
126 114
 }
@@ -164,10 +152,13 @@ void uart::transmit_data() {
164 152
             ext.tx.baud_rate=static_cast<unsigned>(1/bit_duration.to_seconds());
165 153
             ext.tx.data=txdata;
166 154
             set_bit(false); // start bit
167
-            for(int i = 8; i>0; --i)
168
-                set_bit(txdata&(1<<(i-1))); // 8 data bits, MSB first
169
-            set_bit(true); // stop bit 1
170
-            if(regs->r_txctrl.nstop) set_bit(true); // stop bit 2
155
+            if(bit_true_transfer.get_value()){
156
+                for(int i = 8; i>0; --i)
157
+                    set_bit(txdata&(1<<(i-1))); // 8 data bits, MSB first
158
+                if(regs->r_txctrl.nstop) set_bit(true); // stop bit 1
159
+            } else
160
+                wait(8*bit_duration);
161
+            set_bit(true); // stop bit 1/2
171 162
         }
172 163
     }
173 164
 }
@@ -175,7 +166,7 @@ void uart::transmit_data() {
175 166
 void uart::receive_data(tlm::tlm_signal_gp<>& gp, sc_core::sc_time& delay) {
176 167
     sysc::tlm_signal_uart_extension* ext{nullptr};
177 168
     gp.get_extension(ext);
178
-    if(ext && ext != rx_ext){
169
+    if(ext && ext->start_time != rx_last_start){
179 170
         auto data = static_cast<uint8_t>(ext->tx.data);
180 171
         if(ext->tx.parity || ext->tx.data_bits!=8) data = rand(); // random value if wrong config
181 172
         rx_fifo.write(data);
@@ -183,7 +174,7 @@ void uart::receive_data(tlm::tlm_signal_gp<>& gp, sc_core::sc_time& delay) {
183 174
             regs->r_ip.rxwm=1;
184 175
             update_irq();
185 176
         }
186
-        rx_ext=ext; // omit repeated handling of signale changes
177
+        rx_last_start=ext->start_time; // omit repeated handling of signal changes
187 178
     }
188 179
     gp.set_response_status(tlm::TLM_OK_RESPONSE);
189 180
 }

+ 11
- 2
simple-system.json View File

@@ -2,10 +2,19 @@
2 2
 	"i_simple_system":{
3 3
 		"i_platform": {
4 4
 			"i_uart0":{
5
-				"write_to_ws": false
5
+				"bit_true_transfer": false
6 6
 			},
7 7
 			"i_uart1":{
8
-				"write_to_ws": false
8
+				"bit_true_transfer": false
9
+			},
10
+			"i_qspi0":{
11
+				"bit_true_transfer": false
12
+			},
13
+			"i_qspi1":{
14
+				"bit_true_transfer": false
15
+			},
16
+			"i_qspi2":{
17
+				"bit_true_transfer": false
9 18
 			},
10 19
 			"i_gpio0.write_to_ws": false
11 20
 		}