Browse Source

Changed SystemC model to model a platform in a system. Added dedicated

Eyck Jentzsch 10 months ago
parent
commit
fede5b2af1

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

@@ -0,0 +1,30 @@
1
+/*
2
+ * system.h
3
+ *
4
+ *  Created on: 11.07.2018
5
+ *      Author: eyck
6
+ */
7
+
8
+#ifndef __SYSC_GENERAL_SYSTEM_H_
9
+#define __SYSC_GENERAL_SYSTEM_H_
10
+
11
+#include "sysc/SiFive/platform.h"
12
+#include "sysc/General/terminal.h"
13
+#include <systemc>
14
+
15
+namespace sysc {
16
+
17
+class system: sc_core::sc_module {
18
+public:
19
+    system(sc_core::sc_module_name nm);
20
+    virtual ~system();
21
+
22
+    sc_core::sc_vector<tlm::tlm_signal<sc_dt::sc_logic>> s_gpio;
23
+
24
+private:
25
+    sysc::platform i_platform;
26
+    sysc::terminal i_terminal;
27
+};
28
+
29
+}
30
+#endif /* __SYSC_GENERAL_SYSTEM_H_ */

+ 42
- 0
riscv.sc/incl/sysc/General/terminal.h View File

@@ -0,0 +1,42 @@
1
+/*
2
+ * terminal.h
3
+ *
4
+ *  Created on: 07.07.2018
5
+ *      Author: eyck
6
+ */
7
+
8
+#ifndef RISCV_SC_INCL_SYSC_GENERAL_TERMINAL_H_
9
+#define RISCV_SC_INCL_SYSC_GENERAL_TERMINAL_H_
10
+
11
+#include "scc/signal_target_mixin.h"
12
+#include "scc/signal_initiator_mixin.h"
13
+#include "tlm/tlm_signal.h"
14
+#include "cci_configuration"
15
+#include <sysc/kernel/sc_module.h>
16
+#include <memory>
17
+
18
+namespace sysc {
19
+class WsHandler;
20
+
21
+class terminal: public sc_core::sc_module {
22
+public:
23
+    scc::tlm_signal_logic_out tx_o;
24
+    scc::tlm_signal_logic_in  rx_i;
25
+
26
+    terminal();
27
+
28
+    terminal(const sc_core::sc_module_name& nm);
29
+
30
+    virtual ~terminal();
31
+
32
+    cci::cci_param<bool> write_to_ws;
33
+
34
+protected:
35
+    std::vector<uint8_t> queue;
36
+    void receive(tlm::tlm_signal_gp<sc_dt::sc_logic>& gp, sc_core::sc_time& delay);
37
+    std::shared_ptr<sysc::WsHandler> handler;
38
+    sc_core::sc_time last_tx_start=sc_core::SC_ZERO_TIME;
39
+};
40
+}
41
+
42
+#endif /* RISCV_SC_INCL_SYSC_GENERAL_TERMINAL_H_ */

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

@@ -55,7 +55,8 @@ class core_complex;
55 55
 class clint : public sc_core::sc_module, public scc::tlm_target<> {
56 56
 public:
57 57
     SC_HAS_PROCESS(clint);
58
-    sc_core::sc_in<sc_core::sc_time> clk_i;
58
+    sc_core::sc_in<sc_core::sc_time> tlclk_i;
59
+    sc_core::sc_in<sc_core::sc_time> lfclk_i;
59 60
     sc_core::sc_in<bool> rst_i;
60 61
     sc_core::sc_out<bool> mtime_int_o;
61 62
     sc_core::sc_out<bool> msip_int_o;

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

@@ -109,7 +109,8 @@ public:
109 109
     ~core_complex();
110 110
 
111 111
     inline void sync(uint64_t cycle) {
112
-        quantum_keeper.inc(curr_clk*(cycle-last_sync_cycle));
112
+        auto time = curr_clk*(cycle-last_sync_cycle);
113
+        quantum_keeper.inc(time);
113 114
         if (quantum_keeper.need_sync()) {
114 115
             wait(quantum_keeper.get_local_time());
115 116
             quantum_keeper.reset();

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

@@ -38,8 +38,10 @@
38 38
 #define _GPIO_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>
41 44
 #include "cci_configuration"
42
-#include <sysc/communication/sc_signal_rv_ports.h>
43 45
 
44 46
 namespace sysc {
45 47
 
@@ -51,7 +53,15 @@ public:
51 53
     SC_HAS_PROCESS(gpio);
52 54
     sc_core::sc_in<sc_core::sc_time> clk_i;
53 55
     sc_core::sc_in<bool> rst_i;
54
-    sc_core::sc_inout_rv<32> pins_io;
56
+    // sc_core::sc_inout_rv<32> pins_io;
57
+
58
+    sc_core::sc_vector<scc::tlm_signal_logic_out> pins_o;
59
+    sc_core::sc_vector<scc::tlm_signal_logic_in>  pins_i;
60
+
61
+    sc_core::sc_vector<scc::tlm_signal_bool_opt_out> iof0_o;
62
+    sc_core::sc_vector<scc::tlm_signal_bool_opt_out> iof1_o;
63
+    sc_core::sc_vector<scc::tlm_signal_bool_opt_in>  iof0_i;
64
+    sc_core::sc_vector<scc::tlm_signal_bool_opt_in>  iof1_i;
55 65
 
56 66
     gpio(sc_core::sc_module_name nm);
57 67
     virtual ~gpio() override; // need to keep it in source file because of fwd declaration of gpio_regs
@@ -62,14 +72,13 @@ protected:
62 72
     void clock_cb();
63 73
     void reset_cb();
64 74
     void update_pins();
65
-    void pins_cb();
66 75
     void before_end_of_elaboration();
76
+    void pin_input(unsigned int tag, tlm::tlm_signal_gp<sc_logic>& gp, sc_core::sc_time& delay);
77
+    void forward_pin_input(unsigned int tag, tlm::tlm_signal_gp<sc_logic>& gp);
78
+    void iof_input(unsigned int tag, unsigned iof_idx, tlm::tlm_signal_gp<>& gp, sc_core::sc_time& delay);
67 79
     sc_core::sc_time clk;
68 80
     std::unique_ptr<gpio_regs> regs;
69 81
     std::shared_ptr<sysc::WsHandler> handler;
70
-
71
-private:
72
-	void update_value_reg();
73 82
 };
74 83
 
75 84
 } /* namespace sysc */

+ 20
- 11
riscv.sc/incl/sysc/SiFive/platform.h View File

@@ -34,8 +34,8 @@
34 34
 //
35 35
 ////////////////////////////////////////////////////////////////////////////////
36 36
 
37
-#ifndef SIMPLESYSTEM_H_
38
-#define SIMPLESYSTEM_H_
37
+#ifndef _PLATFORM_H_
38
+#define _PLATFORM_H_
39 39
 
40 40
 #include "aon.h"
41 41
 #include "clint.h"
@@ -44,14 +44,15 @@
44 44
 #include "prci.h"
45 45
 #include "spi.h"
46 46
 #include "uart.h"
47
-
48
-#include <array>
49
-#include <sysc/kernel/sc_module.h>
47
+#include "core_complex.h"
50 48
 
51 49
 #include "scc/memory.h"
52 50
 #include "scc/router.h"
53 51
 #include "scc/utilities.h"
54
-#include "core_complex.h"
52
+#include "tlm/tlm_signal_sockets.h"
53
+#include <sysc/kernel/sc_module.h>
54
+#include <array>
55
+
55 56
 
56 57
 namespace sysc {
57 58
 
@@ -59,6 +60,12 @@ class platform : public sc_core::sc_module {
59 60
 public:
60 61
     SC_HAS_PROCESS(platform);
61 62
 
63
+    sc_core::sc_vector<tlm::tlm_signal_initiator_socket<sc_dt::sc_logic>> pins_o;
64
+    sc_core::sc_vector<tlm::tlm_signal_target_socket<sc_dt::sc_logic>>    pins_i;
65
+
66
+    platform(sc_core::sc_module_name nm);
67
+
68
+private:
62 69
     SiFive::core_complex i_core_complex;
63 70
     scc::router<> i_router;
64 71
     uart i_uart0, i_uart1;
@@ -71,13 +78,15 @@ public:
71 78
 
72 79
     scc::memory<512_MB, 32> i_mem_qspi;
73 80
     scc::memory<128_kB, 32> i_mem_ram;
74
-    sc_core::sc_signal<sc_core::sc_time> s_clk;
81
+    sc_core::sc_signal<sc_core::sc_time> s_tlclk;
82
+    sc_core::sc_signal<sc_core::sc_time> s_lfclk;
75 83
     sc_core::sc_signal<bool> s_rst, s_mtime_int, s_msie_int;
76
-    sc_core::sc_vector<sc_core::sc_signal<bool>> s_global_int, s_local_int;
84
+    sc_core::sc_vector<sc_core::sc_signal<bool, SC_MANY_WRITERS>> s_global_int, s_local_int;
77 85
     sc_core::sc_signal<bool> s_core_int;
78
-    sc_core::sc_signal_rv<32> s_gpio_pins;
86
+    sc_core::sc_vector<sc_core::sc_signal<bool>> s_dummy;
87
+    sc_core::sc_vector<scc::tlm_signal_bool_opt_in>  s_dummy_sck_i;
88
+    sc_core::sc_vector<scc::tlm_signal_bool_opt_out> s_dummy_sck_o;
79 89
 
80
-    platform(sc_core::sc_module_name nm);
81 90
 
82 91
 protected:
83 92
     void gen_reset();
@@ -87,4 +96,4 @@ protected:
87 96
 
88 97
 } /* namespace sysc */
89 98
 
90
-#endif /* SIMPLESYSTEM_H_ */
99
+#endif /* _PLATFORM_H_ */

+ 16
- 3
riscv.sc/incl/sysc/SiFive/uart.h View File

@@ -37,11 +37,14 @@
37 37
 #ifndef _UART_H_
38 38
 #define _UART_H_
39 39
 
40
-#include "cci_configuration"
41 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"
42 45
 
43 46
 namespace sysc {
44
-
47
+class tlm_signal_uart_extension;
45 48
 class uart_regs;
46 49
 class WsHandler;
47 50
 
@@ -50,18 +53,28 @@ public:
50 53
     SC_HAS_PROCESS(uart);
51 54
     sc_core::sc_in<sc_core::sc_time> clk_i;
52 55
     sc_core::sc_in<bool> rst_i;
56
+    scc::tlm_signal_bool_out tx_o;
57
+    scc::tlm_signal_bool_in  rx_i;
58
+
59
+    sc_core::sc_out<bool> irq_o;
60
+
61
+    cci::cci_param<bool> write_to_ws;
62
+
53 63
     uart(sc_core::sc_module_name nm);
54 64
     virtual ~uart() override;
55 65
 
56
-    cci::cci_param<bool> write_to_ws;
57 66
 protected:
58 67
     void clock_cb();
59 68
     void reset_cb();
60 69
     void transmit_data();
70
+    void receive_data(tlm::tlm_signal_gp<>& gp, sc_core::sc_time& delay);
71
+    void update_irq();
61 72
     void before_end_of_elaboration();
62 73
     sc_core::sc_time clk;
63 74
     std::unique_ptr<uart_regs> regs;
75
+    sc_core::sc_fifo<uint8_t> rx_fifo, tx_fifo;
64 76
     std::vector<uint8_t> queue;
77
+    sysc::tlm_signal_uart_extension *rx_ext, *tx_ext;
65 78
     std::shared_ptr<sysc::WsHandler> handler;
66 79
 };
67 80
 

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

@@ -0,0 +1,31 @@
1
+/*
2
+ * tlm_extensions.h
3
+ *
4
+ *  Created on: 12.07.2018
5
+ *      Author: eyck
6
+ */
7
+
8
+#ifndef RISCV_SC_INCL_SYSC_TLM_EXTENSIONS_H_
9
+#define RISCV_SC_INCL_SYSC_TLM_EXTENSIONS_H_
10
+
11
+#include "tlm/tlm_extensions.h"
12
+
13
+namespace sysc {
14
+struct tlm_signal_uart_extension : public tlm::tlm_unmanaged_extension<tlm_signal_uart_extension> {
15
+
16
+    struct uart_tx {
17
+        unsigned data_bits:4;
18
+        unsigned stop_bits:2;
19
+        bool parity:1;
20
+        unsigned baud_rate:24;
21
+        unsigned data;
22
+    } tx;
23
+    sc_core::sc_time start_time;
24
+
25
+};
26
+
27
+}
28
+
29
+
30
+
31
+#endif /* RISCV_SC_INCL_SYSC_TLM_EXTENSIONS_H_ */

+ 1
- 1
riscv.sc/src/CMakeLists.txt View File

@@ -1,5 +1,5 @@
1 1
 # library files
2
-FILE(GLOB RiscVSCHeaders *.h)
2
+FILE(GLOB RiscVSCHeaders *.h */*.h)
3 3
 FILE(GLOB RiscvSCSources sysc/*.cpp)
4 4
 
5 5
 set(LIB_HEADERS ${RiscVSCHeaders} )

+ 7
- 7
riscv.sc/src/sc_main.cpp View File

@@ -37,7 +37,7 @@
37 37
 #include <boost/program_options.hpp>
38 38
 #include <iss/log_categories.h>
39 39
 #include <sstream>
40
-#include <sysc/SiFive/platform.h>
40
+#include <sysc/General/system.h>
41 41
 #include "scc/configurer.h"
42 42
 #include "scc/report.h"
43 43
 #include "scc/scv_tr_db.h"
@@ -123,7 +123,7 @@ int sc_main(int argc, char *argv[]) {
123 123
     ///////////////////////////////////////////////////////////////////////////
124 124
     // instantiate top level
125 125
     ///////////////////////////////////////////////////////////////////////////
126
-    platform i_simple_system("i_simple_system");
126
+    sysc::system i_system("i_system");
127 127
     // sr_report_handler::add_sc_object_to_filter(&i_simple_system.i_master,
128 128
     // sc_core::SC_WARNING, sc_core::SC_MEDIUM);
129 129
     if(vm["dump-config"].as<std::string>().size()>0){
@@ -134,20 +134,20 @@ int sc_main(int argc, char *argv[]) {
134 134
 	cfg.configure();
135 135
     // overwrite with command line settings
136 136
     if (vm["gdb-port"].as<unsigned short>())
137
-    	cfg.set_value("i_simple_system.i_core_complex.gdb_server_port", vm["gdb-port"].as<unsigned short>());
137
+    	cfg.set_value("i_system.i_platform.i_core_complex.gdb_server_port", vm["gdb-port"].as<unsigned short>());
138 138
     if (vm.count("dump-ir"))
139
-    	cfg.set_value("i_simple_system.i_core_complex.dump_ir", vm.count("dump-ir") != 0);
139
+    	cfg.set_value("i_system.i_platform.i_core_complex.dump_ir", vm.count("dump-ir") != 0);
140 140
     if (vm.count("elf"))
141
-    	cfg.set_value("i_simple_system.i_core_complex.elf_file", vm["elf"].as<std::string>());
141
+    	cfg.set_value("i_system.i_platform.i_core_complex.elf_file", vm["elf"].as<std::string>());
142 142
     if (vm.count("quantum"))
143 143
         tlm::tlm_global_quantum::instance().set(sc_core::sc_time(vm["quantum"].as<unsigned>(), sc_core::SC_NS));
144 144
     if (vm.count("reset")) {
145 145
         auto str = vm["reset"].as<std::string>();
146 146
         uint64_t start_address = str.find("0x") == 0 ? std::stoull(str.substr(2), 0, 16) : std::stoull(str, 0, 10);
147
-        cfg.set_value("i_simple_system.i_core_complex.reset_address", start_address);
147
+        cfg.set_value("i_system.i_platform.i_core_complex.reset_address", start_address);
148 148
     }
149 149
     if (vm.count("disass")) {
150
-        cfg.set_value("i_simple_system.i_core_complex.enable_disass", true);
150
+        cfg.set_value("i_system.i_platform.i_core_complex.enable_disass", true);
151 151
         LOGGER(disass)::reporting_level() = logging::INFO;
152 152
         auto file_name = vm["disass"].as<std::string>();
153 153
         if (file_name.length() > 0) {

+ 21
- 17
riscv.sc/src/sysc/clint.cpp View File

@@ -47,7 +47,8 @@ const int lfclk_mutiplier = 1 << 12;
47 47
 clint::clint(sc_core::sc_module_name nm)
48 48
 : sc_core::sc_module(nm)
49 49
 , tlm_target<>(clk)
50
-, NAMED(clk_i)
50
+, NAMED(tlclk_i)
51
+, NAMED(lfclk_i)
51 52
 , NAMED(rst_i)
52 53
 , NAMED(mtime_int_o)
53 54
 , NAMED(msip_int_o)
@@ -55,7 +56,7 @@ clint::clint(sc_core::sc_module_name nm)
55 56
 , cnt_fraction(0) {
56 57
     regs->registerResources(*this);
57 58
     SC_METHOD(clock_cb);
58
-    sensitive << clk_i;
59
+    sensitive << tlclk_i<<lfclk_i;
59 60
     SC_METHOD(reset_cb);
60 61
     sensitive << rst_i;
61 62
     dont_initialize();
@@ -84,7 +85,7 @@ clint::clint(sc_core::sc_module_name nm)
84 85
 
85 86
 void clint::clock_cb() {
86 87
     update_mtime();
87
-    this->clk = clk_i.read();
88
+    clk = lfclk_i.read();
88 89
     update_mtime();
89 90
 }
90 91
 
@@ -101,20 +102,23 @@ void clint::reset_cb() {
101 102
 }
102 103
 
103 104
 void clint::update_mtime() {
104
-    auto diff = (sc_core::sc_time_stamp() - last_updt) / clk;
105
-    auto diffi = (int)diff;
106
-    regs->r_mtime += (diffi + cnt_fraction) / lfclk_mutiplier;
107
-    cnt_fraction = (cnt_fraction + diffi) % lfclk_mutiplier;
108
-    mtime_evt.cancel();
109
-    if (regs->r_mtimecmp > 0)
110
-    	if(regs->r_mtimecmp > regs->r_mtime && clk > sc_core::SC_ZERO_TIME) {
111
-    		sc_core::sc_time next_trigger = (clk * lfclk_mutiplier) * (regs->r_mtimecmp - regs->mtime) - cnt_fraction * clk;
112
-    		LOG(DEBUG)<<"Timer fires at "<< sc_time_stamp()+next_trigger;
113
-    		mtime_evt.notify(next_trigger);
114
-    		mtime_int_o.write(false);
115
-    	} else
116
-    		mtime_int_o.write(true);
117
-    last_updt = sc_core::sc_time_stamp();
105
+    if(clk>SC_ZERO_TIME){
106
+        uint64_t elapsed_clks = (sc_time_stamp()-last_updt)/clk; // get the number of clock periods since last invocation
107
+        last_updt += elapsed_clks*clk; // increment the last_updt timestamp by the number of clocks
108
+        if(elapsed_clks){ // update mtime reg if we have more than 0 elapsed clk periods
109
+            regs->r_mtime+=elapsed_clks;
110
+            mtime_evt.cancel();
111
+            if (regs->r_mtimecmp > 0)
112
+                if(regs->r_mtimecmp > regs->r_mtime && clk > sc_core::SC_ZERO_TIME) {
113
+                    sc_core::sc_time next_trigger = (clk * lfclk_mutiplier) * (regs->r_mtimecmp - regs->mtime) - cnt_fraction * clk;
114
+                    LOG(DEBUG)<<"Timer fires at "<< sc_time_stamp()+next_trigger;
115
+                    mtime_evt.notify(next_trigger);
116
+                    mtime_int_o.write(false);
117
+                } else
118
+                    mtime_int_o.write(true);
119
+        }
120
+    } else
121
+        last_updt = sc_time_stamp();
118 122
 }
119 123
 
120 124
 } /* namespace sysc */

+ 102
- 43
riscv.sc/src/sysc/gpio.cpp View File

@@ -35,7 +35,6 @@
35 35
 ////////////////////////////////////////////////////////////////////////////////
36 36
 
37 37
 #include "sysc/SiFive/gpio.h"
38
-
39 38
 #include "sysc/sc_comm_singleton.h"
40 39
 #include "scc/report.h"
41 40
 #include "scc/utilities.h"
@@ -48,7 +47,12 @@ gpio::gpio(sc_core::sc_module_name nm)
48 47
 , tlm_target<>(clk)
49 48
 , NAMED(clk_i)
50 49
 , NAMED(rst_i)
51
-, NAMED(pins_io)
50
+, NAMED(pins_o, 32)
51
+, NAMED(pins_i, 32)
52
+, NAMED(iof0_o, 32)
53
+, NAMED(iof1_o, 32)
54
+, NAMED(iof0_i, 32)
55
+, NAMED(iof1_i, 32)
52 56
 , NAMEDD(gpio_regs, regs)
53 57
 , NAMED(write_to_ws, false){
54 58
     regs->registerResources(*this);
@@ -57,9 +61,36 @@ gpio::gpio(sc_core::sc_module_name nm)
57 61
     SC_METHOD(reset_cb);
58 62
     sensitive << rst_i;
59 63
     dont_initialize();
60
-    SC_METHOD(pins_cb);
61
-    sensitive << pins_io;
62
-
64
+    auto pins_i_cb =[this](unsigned int tag, tlm::tlm_signal_gp<sc_logic>& gp,
65
+            tlm::tlm_phase& phase, sc_core::sc_time& delay)->tlm::tlm_sync_enum{
66
+        this->pin_input(tag, gp, delay);
67
+        return tlm::TLM_COMPLETED;
68
+    };
69
+    auto i=0U;
70
+    for(auto& s:pins_i){
71
+        s.register_nb_transport(pins_i_cb, i);
72
+        ++i;
73
+    }
74
+    auto iof0_i_cb =[this](unsigned int tag, tlm::tlm_signal_gp<bool>& gp,
75
+            tlm::tlm_phase& phase, sc_core::sc_time& delay)->tlm::tlm_sync_enum{
76
+        this->iof_input(tag, 0, gp, delay);
77
+        return tlm::TLM_COMPLETED;
78
+    };
79
+    i=0;
80
+    for(auto& s:iof0_i){
81
+        s.register_nb_transport(iof0_i_cb, i);
82
+        ++i;
83
+    }
84
+    auto iof1_i_cb =[this](unsigned int tag, tlm::tlm_signal_gp<bool>& gp,
85
+            tlm::tlm_phase& phase, sc_core::sc_time& delay)->tlm::tlm_sync_enum{
86
+        this->iof_input(tag, 1, gp, delay);
87
+        return tlm::TLM_COMPLETED;
88
+    };
89
+    i=0;
90
+    for(auto& s:iof1_i){
91
+        s.register_nb_transport(iof1_i_cb, i);
92
+        ++i;
93
+    }
63 94
     regs->port.set_write_cb([this](scc::sc_register<uint32_t> &reg, uint32_t data) -> bool {
64 95
         if (!this->regs->in_reset()) {
65 96
             reg.put(data);
@@ -69,14 +100,6 @@ gpio::gpio(sc_core::sc_module_name nm)
69 100
         return true;
70 101
     });
71 102
 
72
-    regs->value.set_read_cb([this](const scc::sc_register<uint32_t> &reg, uint32_t& data) -> bool {
73
-        if (!this->regs->in_reset()) {
74
-        	// read pins_io and update r_value
75
-        	update_value_reg();
76
-            data=reg.get();
77
-        }
78
-        return true;
79
-    });
80 103
 }
81 104
 
82 105
 gpio::~gpio() {}
@@ -100,40 +123,76 @@ void gpio::clock_cb() {
100 123
 	this->clk = clk_i.read();
101 124
 }
102 125
 
103
-void gpio::pins_cb(){
104
-	auto inval=pins_io.read();
105
-	std::string msg(inval.to_string());
106
-    sc_core::sc_time now = sc_core::sc_time_stamp();
107
-    if(handler) sc_comm_singleton::inst().execute([this, msg, now](){
108
-		std::stringstream os;
109
-		os << "{\"time\":\"" << now << "\",\"data\":\""<<msg<<"\"}";
110
-		this->handler->send(os.str());
111
-	});
126
+void gpio::update_pins() {
127
+	sc_core::sc_inout_rv<32>::data_type out_val;
128
+	tlm::tlm_signal_gp<sc_dt::sc_logic> gp;
129
+	for(size_t i=0, mask = 1; i<32; ++i, mask<<=1){
130
+	    if((regs->iof_en&mask == 0) || (iof0_i[i].size()==0 && iof1_i[i].size()==0)){
131
+	        sc_core::sc_time delay{SC_ZERO_TIME};
132
+            tlm::tlm_phase phase{tlm::BEGIN_REQ};
133
+            gp.set_command(tlm::TLM_WRITE_COMMAND);
134
+            gp.set_response_status(tlm::TLM_OK_RESPONSE);
135
+            gp.set_value(regs->r_output_en&mask?regs->r_port&mask?sc_dt::Log_1:sc_dt::Log_0:sc_dt::Log_Z);
136
+            pins_o.at(i)->nb_transport_fw(gp, phase, delay);
137
+	    }
138
+	}
139
+}
140
+
141
+void gpio::pin_input(unsigned int tag, tlm::tlm_signal_gp<sc_logic>& gp, sc_core::sc_time& delay) {
142
+    if(delay>SC_ZERO_TIME){
143
+         wait(delay);
144
+         delay=SC_ZERO_TIME;
145
+     }
146
+     switch(gp.get_value().value()){
147
+     case sc_dt::Log_1:
148
+         regs->r_value|=1<<tag;
149
+         forward_pin_input(tag, gp);
150
+         break;
151
+     case sc_dt::Log_0:
152
+         regs->r_value&=~(1<<tag);
153
+         forward_pin_input(tag, gp);
154
+         break;
155
+     }
112 156
 }
113 157
 
114
-void gpio::update_value_reg() {
115
-	// read pins_io and update r_value reg
116
-	auto inval = pins_io.read();
117
-	uint32_t res = 0;
118
-	for (size_t i = 0, msk = 1; i < 32; ++i, msk = msk << 1) {
119
-		bool bit_set = false;
120
-		if ((regs->r_input_en & msk) != 0) {
121
-			if (inval.get_bit(1) == sc_dt::Log_1)
122
-				bit_set = true;
123
-			else if (inval.get_bit(1) == sc_dt::Log_Z
124
-					&& (regs->r_pue & msk) != 0)
125
-				bit_set = true;
126
-		}
127
-		if (bit_set) res |= msk;
128
-	}
129
-	regs->r_value = res;
158
+void gpio::forward_pin_input(unsigned int tag, tlm::tlm_signal_gp<sc_logic>& gp) {
159
+    const auto mask = 1U<<tag;
160
+    if(regs->iof_en&mask){
161
+        auto& socket = regs->iof_sel&mask?iof1_o[tag]:iof0_o[tag];
162
+        tlm::tlm_signal_gp<> new_gp;
163
+        for(size_t i=0; i<socket.size(); ++i){
164
+            sc_core::sc_time delay{SC_ZERO_TIME};
165
+            tlm::tlm_phase phase{tlm::BEGIN_REQ};
166
+            new_gp.set_command(tlm::TLM_WRITE_COMMAND);
167
+            new_gp.set_response_status(tlm::TLM_OK_RESPONSE);
168
+            new_gp.set_value(gp.get_value().value()==sc_dt::Log_1);
169
+            new_gp.update_extensions_from(gp);
170
+            socket->nb_transport_fw(new_gp, phase, delay); // we don't care about phase and sync enum
171
+        }
172
+    }
130 173
 }
131 174
 
132
-void gpio::update_pins() {
133
-	sc_core::sc_inout_rv<32>::data_type out_val;
134
-	for(size_t i=0, msk = 1; i<32; ++i, msk=msk<<1)
135
-		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);
136
-	pins_io.write(out_val);
175
+void gpio::iof_input(unsigned int tag, unsigned iof_idx, tlm::tlm_signal_gp<>& gp, sc_core::sc_time& delay) {
176
+    if(delay>SC_ZERO_TIME){
177
+         wait(delay);
178
+         delay=SC_ZERO_TIME;
179
+    }
180
+    const auto mask = 1U<<tag;
181
+    if(regs->r_iof_en&mask){
182
+        const auto idx = regs->r_iof_sel&mask?1:0;
183
+        if(iof_idx == idx){
184
+            auto& socket = pins_o[tag];
185
+            for(size_t i=0; i<socket.size(); ++i){
186
+                sc_core::sc_time delay{SC_ZERO_TIME};
187
+                tlm::tlm_phase phase{tlm::BEGIN_REQ};
188
+                tlm::tlm_signal_gp<sc_logic> new_gp;
189
+                new_gp.set_command(tlm::TLM_WRITE_COMMAND);
190
+                new_gp.set_value(gp.get_value()?sc_dt::Log_1:sc_dt::Log_0);
191
+                new_gp.copy_extensions_from(gp);
192
+                socket->nb_transport_fw(new_gp, phase, delay); // we don't care about phase and sync enum
193
+            }
194
+        }
195
+    }
137 196
 }
138 197
 
139 198
 } /* namespace sysc */

+ 33
- 15
riscv.sc/src/sysc/platform.cpp View File

@@ -40,6 +40,8 @@ namespace sysc {
40 40
 
41 41
 platform::platform(sc_core::sc_module_name nm)
42 42
 : sc_core::sc_module(nm)
43
+, NAMED(pins_o, 32)
44
+, NAMED(pins_i, 32)
43 45
 , NAMED(i_core_complex)
44 46
 , NAMED(i_router, 12, 1)
45 47
 , NAMED(i_uart0)
@@ -54,12 +56,15 @@ platform::platform(sc_core::sc_module_name nm)
54 56
 , NAMED(i_clint)
55 57
 , NAMED(i_mem_qspi)
56 58
 , NAMED(i_mem_ram)
57
-, NAMED(s_clk)
59
+, NAMED(s_tlclk)
58 60
 , NAMED(s_rst)
59 61
 , NAMED(s_global_int, 256)
60 62
 , NAMED(s_local_int, 16)
61 63
 , NAMED(s_core_int)
62
-, NAMED(s_gpio_pins) {
64
+, NAMED(s_dummy, 16)
65
+, NAMED(s_dummy_sck_i, 16)
66
+, NAMED(s_dummy_sck_o, 16)
67
+{
63 68
     i_core_complex.initiator(i_router.target[0]);
64 69
     size_t i = 0;
65 70
     for (const auto &e : e300_plat_map) {
@@ -72,17 +77,18 @@ platform::platform(sc_core::sc_module_name nm)
72 77
     i_router.initiator.at(++i)(i_mem_ram.target);
73 78
     i_router.add_target_range(i, 0x80000000, 128_kB);
74 79
 
75
-    i_uart0.clk_i(s_clk);
76
-    i_uart1.clk_i(s_clk);
77
-    i_qspi0.clk_i(s_clk);
78
-    i_qspi1.clk_i(s_clk);
79
-    i_qspi2.clk_i(s_clk);
80
-    i_gpio0.clk_i(s_clk);
81
-    i_plic.clk_i(s_clk);
82
-    i_aon.clk_i(s_clk);
83
-    i_prci.clk_i(s_clk);
84
-    i_clint.clk_i(s_clk);
85
-    i_core_complex.clk_i(s_clk);
80
+    i_uart0.clk_i(s_tlclk);
81
+    i_uart1.clk_i(s_tlclk);
82
+    i_qspi0.clk_i(s_tlclk);
83
+    i_qspi1.clk_i(s_tlclk);
84
+    i_qspi2.clk_i(s_tlclk);
85
+    i_gpio0.clk_i(s_tlclk);
86
+    i_plic.clk_i(s_tlclk);
87
+    i_aon.clk_i(s_tlclk);
88
+    i_prci.clk_i(s_tlclk);
89
+    i_clint.tlclk_i(s_tlclk);
90
+    i_clint.lfclk_i(s_lfclk);
91
+    i_core_complex.clk_i(s_tlclk);
86 92
 
87 93
     i_uart0.rst_i(s_rst);
88 94
     i_uart1.rst_i(s_rst);
@@ -107,13 +113,25 @@ platform::platform(sc_core::sc_module_name nm)
107 113
     i_core_complex.global_irq_i(s_core_int);
108 114
     i_core_complex.local_irq_i(s_local_int);
109 115
 
110
-    i_gpio0.pins_io(s_gpio_pins);
116
+    pins_i(i_gpio0.pins_i);
117
+    i_gpio0.pins_o(pins_o);
118
+
119
+    i_gpio0.iof0_i[17](i_uart0.tx_o);
120
+    i_uart0.rx_i(i_gpio0.iof0_o[16]);
121
+    i_uart0.irq_o(s_global_int[3]);
122
+
123
+    s_dummy_sck_i[0](i_uart1.tx_o);
124
+    i_uart1.rx_i(s_dummy_sck_o[0]);
125
+    i_uart1.irq_o(s_dummy[0]);
111 126
 
112 127
     SC_THREAD(gen_reset);
128
+
129
+    for(auto& sock:s_dummy_sck_i) sock.error_if_no_callback=false;
113 130
 }
114 131
 
115 132
 void platform::gen_reset() {
116
-    s_clk = 10_ns;
133
+    s_tlclk = 10_ns;
134
+    s_lfclk = 30517_ns;
117 135
     s_rst = true;
118 136
     wait(10_ns);
119 137
     s_rst = false;

+ 30
- 0
riscv.sc/src/sysc/system.cpp View File

@@ -0,0 +1,30 @@
1
+/*
2
+ * system.cpp
3
+ *
4
+ *  Created on: 11.07.2018
5
+ *      Author: eyck
6
+ */
7
+
8
+#include "sysc/General/system.h"
9
+
10
+using namespace sysc;
11
+
12
+system::system(sc_core::sc_module_name nm)
13
+: sc_module(nm)
14
+, NAMED(s_gpio, 32)
15
+, NAMED(i_platform)
16
+, NAMED(i_terminal)
17
+{
18
+  for(auto i=0U; i<s_gpio.size(); ++i){
19
+      s_gpio[i].in(i_platform.pins_o[i]);
20
+      i_platform.pins_i[i](s_gpio[i].out);
21
+  }
22
+//  i_platform.pins_i(i_platform.pins_o);
23
+
24
+  s_gpio[17].out(i_terminal.rx_i);
25
+  i_terminal.tx_o(s_gpio[16].in);
26
+}
27
+
28
+system::~system() {
29
+}
30
+

+ 57
- 0
riscv.sc/src/sysc/terminal.cpp View File

@@ -0,0 +1,57 @@
1
+/*
2
+ * terminal.cpp
3
+ *
4
+ *  Created on: 07.07.2018
5
+ *      Author: eyck
6
+ */
7
+
8
+#include "sysc/General/terminal.h"
9
+#include "sysc/sc_comm_singleton.h"
10
+#include "sysc/tlm_extensions.h"
11
+#include "scc/report.h"
12
+
13
+using namespace sysc;
14
+
15
+terminal::terminal() :terminal(sc_core::sc_gen_unique_name("terminal")){
16
+}
17
+
18
+terminal::terminal(const sc_core::sc_module_name& nm)
19
+: sc_core::sc_module(nm)
20
+, NAMED(tx_o)
21
+, NAMED(rx_i)
22
+, NAMED(write_to_ws, false)
23
+{
24
+    rx_i.register_nb_transport([this](
25
+            tlm::tlm_signal_gp<sc_dt::sc_logic>& gp,
26
+            tlm::tlm_phase& phase,
27
+            sc_core::sc_time& delay)->tlm::tlm_sync_enum{
28
+        this->receive(gp, delay);
29
+        return tlm::TLM_COMPLETED;
30
+    });
31
+}
32
+
33
+terminal::~terminal() {
34
+}
35
+
36
+void terminal::receive(tlm::tlm_signal_gp<sc_dt::sc_logic>& gp, sc_core::sc_time& delay) {
37
+    sysc::tlm_signal_uart_extension* ext;
38
+    gp.get_extension(ext);
39
+    if(ext && ext->start_time!=last_tx_start){
40
+        uint8_t txdata = static_cast<uint8_t>(ext->tx.data);
41
+        last_tx_start = ext->start_time;
42
+        if(txdata != '\r') queue.push_back(txdata);
43
+        if (queue.size() >> 0 && (txdata == '\n' || txdata == 0)) {
44
+            std::string msg(queue.begin(), queue.end()-1);
45
+            sc_core::sc_time now = sc_core::sc_time_stamp();
46
+            if(handler)
47
+                sysc::sc_comm_singleton::inst().execute([this, msg, now](){
48
+                    std::stringstream os;
49
+                    os << "{\"time\":\"" << now << "\",\"message\":\""<<msg<<"\"}";
50
+                    this->handler->send(os.str());
51
+                });
52
+            else
53
+                LOG(INFO) << this->name() << " receive: '" << msg << "'";
54
+            queue.clear();
55
+        }
56
+    }
57
+}

+ 107
- 14
riscv.sc/src/sysc/uart.cpp View File

@@ -37,6 +37,7 @@
37 37
 #include "sysc/SiFive/uart.h"
38 38
 
39 39
 #include "sysc/sc_comm_singleton.h"
40
+#include "sysc/tlm_extensions.h"
40 41
 #include "scc/report.h"
41 42
 #include "scc/utilities.h"
42 43
 #include "sysc/SiFive/gen/uart_regs.h"
@@ -56,25 +57,62 @@ uart::uart(sc_core::sc_module_name nm)
56 57
 , tlm_target<>(clk)
57 58
 , NAMED(clk_i)
58 59
 , NAMED(rst_i)
60
+, NAMED(tx_o)
61
+, NAMED(rx_i)
62
+, NAMED(irq_o)
63
+, NAMED(write_to_ws, false)
59 64
 , NAMEDD(uart_regs, regs)
60
-, NAMED(write_to_ws, false) {
65
+{
61 66
     regs->registerResources(*this);
62 67
     SC_METHOD(clock_cb);
63 68
     sensitive << clk_i;
64 69
     SC_METHOD(reset_cb);
65 70
     sensitive << rst_i;
66 71
     dont_initialize();
72
+    SC_THREAD(transmit_data);
73
+    rx_i.register_nb_transport([this](tlm::tlm_signal_gp<bool>& gp,
74
+            tlm::tlm_phase& phase, sc_core::sc_time& delay)->tlm::tlm_sync_enum{
75
+       this->receive_data(gp, delay);
76
+       return tlm::TLM_COMPLETED;
77
+    });
67 78
     regs->txdata.set_write_cb([this](scc::sc_register<uint32_t> &reg, uint32_t data) -> bool {
68 79
         if (!this->regs->in_reset()) {
69 80
             reg.put(data);
70
-            this->transmit_data();
81
+            tx_fifo.nb_write(static_cast<uint8_t>(regs->r_txdata.data));
82
+            regs->r_txdata.full=tx_fifo.num_free()==0;
83
+            regs->r_ip.txwm=regs->r_txctrl.txcnt<=(7-tx_fifo.num_free())?1:0;
84
+            update_irq();
85
+        }
86
+        return true;
87
+    });
88
+    regs->rxdata.set_read_cb([this](const scc::sc_register<uint32_t> &reg, uint32_t& data) -> bool {
89
+        if (!this->regs->in_reset()) {
90
+            uint8_t val;
91
+            if(rx_fifo.nb_read(val)){
92
+                regs->r_rxdata.data=val;
93
+                if(regs->r_rxctrl.rxcnt<=rx_fifo.num_available()){
94
+                    regs->r_ip.rxwm=1;
95
+                    update_irq();
96
+                }
97
+            }
98
+            data = reg.get()&reg.rdmask;
71 99
         }
72 100
         return true;
73 101
     });
102
+    regs->ie.set_write_cb([this](scc::sc_register<uint32_t> &reg, uint32_t data) -> bool {
103
+        update_irq();
104
+    });
105
+    regs->ip.set_write_cb([this](scc::sc_register<uint32_t> &reg, uint32_t data) -> bool {
106
+        update_irq();
107
+    });
74 108
 }
75 109
 
76 110
 uart::~uart() {}
77 111
 
112
+void uart::update_irq() {
113
+    irq_o=(regs->r_ip.rxwm==1 && regs->r_ie.rxwm==1) || (regs->r_ip.txwm==1 && regs->r_ie.txwm==1);
114
+}
115
+
78 116
 void uart::before_end_of_elaboration() {
79 117
 	if(write_to_ws.get_value()) {
80 118
 	    LOG(TRACE)<<"Adding WS handler for "<<(std::string{"/ws/"}+name());
@@ -95,19 +133,74 @@ void uart::reset_cb() {
95 133
 }
96 134
 
97 135
 void uart::transmit_data() {
98
-    if(regs->r_txdata.data != '\r') queue.push_back(regs->r_txdata.data);
99
-    if (queue.size() >> 0 && (regs->r_txdata.data == '\n' || regs->r_txdata.data == 0)) {
100
-    	std::string msg(queue.begin(), queue.end()-1);
101
-        LOG(INFO) << this->name() << " transmit: '" << msg << "'";
102
-        sc_core::sc_time now = sc_core::sc_time_stamp();
103
-		if(handler)
104
-			sc_comm_singleton::inst().execute([this, msg, now](){
105
-				std::stringstream os;
106
-				os << "{\"time\":\"" << now << "\",\"message\":\""<<msg<<"\"}";
107
-				this->handler->send(os.str());
108
-			});
109
-        queue.clear();
136
+    uint8_t txdata;
137
+    sc_core::sc_time delay(SC_ZERO_TIME);
138
+    tlm::tlm_phase phase(tlm::BEGIN_REQ);
139
+    tlm::tlm_signal_gp<> gp;
140
+    gp.set_command(tlm::TLM_WRITE_COMMAND);
141
+    gp.set_value(true);
142
+    tx_o->nb_transport_fw(gp, phase, delay);
143
+    while(true){
144
+        wait(tx_fifo.data_written_event());
145
+        while(tx_fifo.nb_read(txdata)){
146
+            regs->r_txdata.full=tx_fifo.num_free()==0;
147
+            regs->r_ip.txwm=regs->r_txctrl.txcnt<=(7-tx_fifo.num_free())?1:0;
148
+            auto bit_duration = (regs->r_div.div+1)*clk;
149
+            sysc::tlm_signal_uart_extension ext;
150
+            ext.start_time = sc_core::sc_time_stamp();
151
+            ext.tx.data_bits=8;
152
+            ext.tx.parity=false;
153
+            ext.tx.stop_bits=1+regs->r_txctrl.nstop;
154
+            ext.tx.baud_rate=static_cast<unsigned>(1/bit_duration.to_seconds());
155
+            ext.tx.data=txdata;
156
+            delay=SC_ZERO_TIME;
157
+            auto start = sc_time_stamp();
158
+            gp.set_command(tlm::TLM_WRITE_COMMAND);
159
+            gp.set_value(false);
160
+            gp.set_extension(&ext);
161
+            phase=tlm::BEGIN_REQ;
162
+            tx_o->nb_transport_fw(gp, phase, delay);
163
+            auto duration = bit_duration*(1+8+1+ext.tx.stop_bits);//start+data+parity+stop
164
+            auto diff=start+duration-sc_time_stamp();
165
+            if(diff>SC_ZERO_TIME) wait(diff);
166
+            delay=SC_ZERO_TIME;
167
+            gp.set_command(tlm::TLM_WRITE_COMMAND);
168
+            gp.set_value(true);
169
+            phase=tlm::BEGIN_REQ;
170
+            tx_o->nb_transport_fw(gp, phase, delay);
171
+
172
+//            if(txdata != '\r') queue.push_back(txdata);
173
+//            if (queue.size() >> 0 && (txdata == '\n' || txdata == 0)) {
174
+//                std::string msg(queue.begin(), queue.end()-1);
175
+//                LOG(INFO) << this->name() << " transmit: '" << msg << "'";
176
+//                sc_core::sc_time now = sc_core::sc_time_stamp();
177
+//                if(handler)
178
+//                    sc_comm_singleton::inst().execute([this, msg, now](){
179
+//                        std::stringstream os;
180
+//                        os << "{\"time\":\"" << now << "\",\"message\":\""<<msg<<"\"}";
181
+//                        this->handler->send(os.str());
182
+//                    });
183
+//                queue.clear();
184
+//            }
185
+        }
186
+    }
187
+}
188
+
189
+void uart::receive_data(tlm::tlm_signal_gp<>& gp, sc_core::sc_time& delay) {
190
+    sysc::tlm_signal_uart_extension* ext{nullptr};
191
+    gp.get_extension(ext);
192
+    if(ext && ext != rx_ext){
193
+        auto data = static_cast<uint8_t>(ext->tx.data);
194
+        if(ext->tx.parity || ext->tx.data_bits!=8) data = rand(); // random value if wrong config
195
+        rx_fifo.write(data);
196
+        if(regs->r_rxctrl.rxcnt<=rx_fifo.num_available()){
197
+            regs->r_ip.rxwm=1;
198
+            update_irq();
199
+        }
200
+        rx_ext=ext; // omit repeated handling of signale changes
110 201
     }
202
+    gp.set_response_status(tlm::TLM_OK_RESPONSE);
111 203
 }
112 204
 
113 205
 } /* namespace sysc */
206
+

+ 1
- 1
riscv/incl/iss/arch/riscv_hart_msu_vp.h View File

@@ -697,7 +697,7 @@ iss::status riscv_hart_msu_vp<BASE>::read(const iss::addr_t &addr, unsigned leng
697 697
         } break;
698 698
         case traits<BASE>::RES: {
699 699
             auto it = atomic_reservation.find(addr.val);
700
-            if (it != atomic_reservation.end() && (*it).second != 0) {
700
+            if (it != atomic_reservation.end() && it->second != 0) {
701 701
                 memset(data, 0xff, length);
702 702
                 atomic_reservation.erase(addr.val);
703 703
             } else

+ 1
- 1
sc-components

@@ -1 +1 @@
1
-Subproject commit b50df83ebfbf06299613a973552856954ed383c1
1
+Subproject commit 019a04132a8beb7fcab24d504e3347ca0771ea5f

+ 9
- 7
simple-system.json View File

@@ -1,11 +1,13 @@
1 1
 {
2 2
 	"i_simple_system":{
3
-		"i_uart0":{
4
-			"write_to_ws": true
5
-		},
6
-		"i_uart1":{
7
-			"write_to_ws": false
8
-		},
9
-		"i_gpio0.write_to_ws": true
3
+		"i_platform": {
4
+			"i_uart0":{
5
+				"write_to_ws": false
6
+			},
7
+			"i_uart1":{
8
+				"write_to_ws": false
9
+			},
10
+			"i_gpio0.write_to_ws": false
11
+		}
10 12
 	}
11 13
 }