iT邦幫忙

2021 iThome 鐵人賽

DAY 2
1
Software Development

猴子都寫得出來的 RISC-V CPU Emulator系列 第 4

SystemC: 月球轉運站

創世神創造了世界,還覺得不夠,又做了一顆月球。
過了兩天覺得地球不夠圓,決定把存在月球的 pi拿回來。
於是再打個響指!

這時候就輪到猴子來操心了。
有了第一個基本模組,就會有第二個,那他們之間要怎麼互相交換資料呢?

b_transport

對應到 blocked transport,只要在 initiator socket 呼叫這個函式就可以進行傳輸。
但是在能運作之前,要先把基礎建設建好。

moon_access_socket->b_transport(trans, delay);

initiator_socket

轉運站的第一站,傳輸發起端。
負責發起 read/write 指令。
既然能要月球的 pi,就能把地球的派送回去。

tlm_utils::simple_initiator_socket<HELLO> moon_access_socket;

target_socket

轉運站的終點站,傳輸響應端。
不管是 read/write ,到了之後都會有專人服務!

tlm_utils::simple_target_socket<MOON> moon_access_socket;

register

安排響應站的專職服務人員。
只要把對應的函式接上去就可以囉!

moon_access_socket.register_b_transport(this, &MOON::b_transport);

bind

有了傳輸發起端和傳輸響應端之後,
還要記得告訴公車司機要到哪邊些收指令和開往哪邊。

hello.moon_access_socket.bind(moon.moon_access_socket);

實際程式碼

這次把 dataMemory 從 hello 搬到 moon囉!

//main.cpp
#include <vector>

#include "systemc.h"
#include "tlm.h"
#include "tlm_utils/simple_initiator_socket.h"
#include "tlm_utils/simple_target_socket.h"

class HELLO : public sc_module{
public:
        HELLO(sc_module_name name) : sc_module(name){
                SC_HAS_PROCESS(HELLO);
                SC_THREAD(hello_thread);
        }

        tlm_utils::simple_initiator_socket<HELLO> moon_access_socket;
private:
        sc_core::sc_time  delay = sc_core::sc_time(1, sc_core::SC_NS);
        uint32_t pc = 0;


        void hello_thread(void)
        {
                for(int i = 0; i < 30; i++)
                {
                        step();
                        wait(delay);
                }
        }

        void step()
        {
                char data;
                sc_dt::uint64 addr = pc;
                int size = 1;
                tlm::tlm_generic_payload trans;
                trans.set_command(tlm::TLM_READ_COMMAND);
                trans.set_data_ptr(reinterpret_cast<unsigned char*>(&data));
                trans.set_data_length(size);
                trans.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
                trans.set_address(addr);
                sc_core::sc_time delay = sc_core::SC_ZERO_TIME;

                moon_access_socket->b_transport(trans, delay);
                std::cout << "time " << sc_core::sc_time_stamp() << ":" << "hello received!!" << data << std::endl;

                pc++;
        }
};

class MOON : public sc_module{
public:
        MOON(sc_module_name name) : sc_module(name){
                moon_access_socket.register_b_transport(this, &MOON::b_transport);
        }

        tlm_utils::simple_target_socket<MOON> moon_access_socket;

private:
        std::vector<char> dataMemory{'M', 'o', 'o', 'n', '!',
                                        ',', ' ', '3', '.', '1',
                                        '4', '1', '5', '9', '2',
                                        '6', '5', '3', '5', '8',
                                        '9', '7', '9', '3', '2',
                                        '3', '8', '4', '6', '2'};

        void b_transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &delay){
                delay = sc_core::SC_ZERO_TIME;
                tlm::tlm_command cmd = trans.get_command();
                sc_dt::uint64 adr = trans.get_address();
                unsigned char *ptr = trans.get_data_ptr();
                unsigned int len = trans.get_data_length();

                if(adr < dataMemory.size())
                {
                        *(char*)ptr = dataMemory[adr];
                        std::cout << "time " << sc_core::sc_time_stamp() << ":" << "moon response!!" << dataMemory[adr] << std::endl;
                        trans.set_response_status(tlm::TLM_OK_RESPONSE);
                }
                else
                {
                        trans.set_response_status(tlm::TLM_BURST_ERROR_RESPONSE);
                        std::cout << "error an address " << adr << "!!" << std::endl;
                }
        }
};

int sc_main(int argc,char** argv){

        HELLO hello("hello");
        MOON moon("moon");
        hello.moon_access_socket.bind(moon.moon_access_socket);
        sc_core::sc_start();
        return 0;
}

執行結果

這次將sc_start()改成sc_start(sc_core::sc_time(11, sc_core::SC_NS))
跑了 11ns 當作示範。

$ make run
./hello

        SystemC 2.3.3-Accellera --- Sep 17 2021 22:09:07
        Copyright (c) 1996-2018 by all Contributors,
        ALL RIGHTS RESERVED
time 0 s:moon response!!M
time 0 s:hello received!!M
time 1 ns:moon response!!o
time 1 ns:hello received!!o
time 2 ns:moon response!!o
time 2 ns:hello received!!o
time 3 ns:moon response!!n
time 3 ns:hello received!!n
time 4 ns:moon response!!!
time 4 ns:hello received!!!
time 5 ns:moon response!!,
time 5 ns:hello received!!,
time 6 ns:moon response!! 
time 6 ns:hello received!! 
time 7 ns:moon response!!3
time 7 ns:hello received!!3
time 8 ns:moon response!!.
time 8 ns:hello received!!.
time 9 ns:moon response!!1
time 9 ns:hello received!!1
time 10 ns:moon response!!4
time 10 ns:hello received!!4

上一篇
SystemC: 開始囉,再等等!
下一篇
RISC-V: 介紹
系列文
猴子都寫得出來的 RISC-V CPU Emulator31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言