iT邦幫忙

0

[gem5] 嘗試插入事件 --- 開始以 DES 的風格模擬時間的推進

  • 分享至 

  • xImage
  •  

系列文章 : [gem5] 從零開始的 gem5 學習筆記

這裡我們可以開始嘗試 gem5 的核心之一 : 模擬時間。
當 gem5 想要模擬時間的時候,就是把某個事件安排 ( schedule ) 到某個時間點,當時間到了之後,就執行相對應的程式碼。

這篇文章絕大部份來自 learning gem5 / Event-driven programming.

如何運行範例

可以依照下面的指令,去將 gem5 編譯,並運行起範例。

git clone -b example-object https://github.com/TommyWu-fdgkhdkgh/gem5.git
cd gem5
scons build/RISCV/gem5.debug -j$(nproc)

# 開始進行模擬
./build/RISCV/gem5.debug --debug-flags=TimeExampleObject ./configs/learning_gem5/tommy/time_example.py --latency 10ns --times-left 6 

最後該會看到下面的 log。

      0: example: Hello World! From a SimObject!
Beginning simulation!
    100: example: Processing the event! 5 left
  10100: example: Processing the event! 4 left
  20100: example: Processing the event! 3 left
  30100: example: Processing the event! 2 left
  40100: example: Processing the event! 1 left
  50100: example: Processing the event! 0 left
  50100: example: Last event !

以這個 log 來說,最左邊的 40100 代表的就是這個事件發生的時間點。
40100 的單位是 Tick,也就是在第 40100 個 Tick 的時候,觸發了這個 log 。

40100: example: Processing the event! 1 left


Tick 代表多長的時間 ?

Tick 是 gem5 自己定義的時間單位,那一個 Tick 代表了多長的時間呢 ?
一個 Tick 到底代表了多少秒呢 ?



一個 Tick 的長度其實是可變的!
就如同開啟 gem5 時會顯示的 log 一樣

Global frequency set at 1000000000000 ticks per second

Tick 預設的長度是 1/1000000000000 秒,也就是 1 Picosecond ( 皮秒 )。



希望改變 Tick 長度的話,可以在 python configuration script 裡面加上

m5.ticks.setGlobalFrequency("1ns")

這樣就可以將 1 個 Tick 的長度從 1/1000000000000 ( 1 Picosecond ) 秒,改成 1/1000000000 ( 1 nanosecond )



建立一個簡單的 event callback

在 gem5 裡面,每一個 event 都會有一個 callback function,當 event 被觸發的時候,就會呼叫這一個 callback function。

在我們的範例裡面 ( TimeExampleObject ),我們需要宣告 ( declare ) 一個新的 function ( processEvent ),每當 Event 被 trigger 的時候,就需要被執行。

EventFunctionWrapper 則是 event 本身,他會記錄 callback function ( processEvent ) 的資訊,以便知道自己被觸發的時候,要呼叫誰。

{ gem5/src/learning_gem5/tommy/time_example_object.hh }

class TimeExampleObject : public SimObject
{
  private:
    void processEvent();
    EventFunctionWrapper event;
    const Tick latency;
    int timesLeft; 

  public:
    TimeExampleObject(const TimeExampleObjectParams &p);
    void startup() override;
};


以下是 source file 的部分。

{ gem5/src/learning_gem5/tommy/time_example_object.cc }

TimeExampleObject::TimeExampleObject(const TimeExampleObjectParams &params)
    : SimObject(params),
      event([this] { processEvent(); }, name()),
      latency(params.latency),
      timesLeft(params.times_lelft)
{ DPRINTF(TimeExampleObject, "Hello World! From a SimObject!\n"); }


在這裡,我們會初始化這個 event。
第一個參數是該 event 被觸發的時候,要呼叫什麼 function。
第二個參數是帶有這個 event 的 SimObject 的名稱。

      event([this] { processEvent(); }, name()),

startupschedule 第一個 Event

startup function 是一個特別的 function,他是繼承自 class SimObject
startup function 會在即將要開始進行模擬的時候呼叫。

{ gem5/src/python/m5/simulate.py }

def simulate(*args, **kwargs):
    global need_startup
    global _instantiated

    if not _instantiated:
        fatal("m5.instantiate() must be called before m5.simulate().")

    if need_startup:
        root = Root.getInstance()
        for obj in root.descendants():
            obj.startup()
        need_startup = False

在這裡,我們嘗試在 startup 去 schedule 第一個 Event

schedule 的第一個參數是我們想要 schedule 的 event。
第二個參數是設定這個 event 要在多久後被 trigger,單位是 Tick。
因為我沒有做任何其他的設定,所以每一個 Tick 是 1 picosecond,於是這個 event 會在 100 picosecond 後被觸發。

void
TimeExampleObject::startup()
{ schedule(event, 100); }

Event 裡面去 schedule 其他 Event

當 Event 被觸發後,會去執行 processEvent 這個我們一開始就設定好的 callback function。

這邊可以發現,在 event 的 callback function 裡面,可以再去 schedule 其他的 event。在這裡,我們每個 Event 會間隔 latency,總共 schedule timesLeft 個 events

void
TimeExampleObject::processEvent()
{
    timesLeft--;
    DPRINTF(TimeExampleObject, "Processing the event! %d left\n", timesLeft);

    if (timesLeft <= 0) {
        DPRINTF(TimeExampleObject, "Last event !\n");
    } else {
        schedule(event, curTick() + latency);
    }
}

模擬時間的原理 — event queue 與 DES

相關的檔案

  • gem5/src/sim/eventq.hh
  • gem5/src/sim/eventq.cc
  • gem5/src/sim/simulate.cc

其實模擬時間的原理很簡單,在 gem5 內的實作是一個 events 串在一起的 linked list,並且會以時間做排序,時間越小的會排在越前面。另外也會用 priority 做排序,但這邊先介紹簡化版的。

所以這個 linked-list 的 head 節點永遠都會有最小的時間。
在模擬的時候,會做以下的操作

  • 從 linked-list 的 head 拿挑出時間最小的 event 出來
  • 把這個 event 從 linked-list 裡面拔出來,linked-list 的 head 指向下一個時間最小的 event
  • 執行 event 的 callback function
  • 把 event 給 release,也就是執行 event 的解構子, 並釋放資源
  • 回到第一步,直到模擬器停止運行

這種把對於連續時間的模擬,變成像這樣離散的一個個事件,就叫做 discrete event simulation ( DES )。

參考連結


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言