2024年8月27日 星期二

2024 week 35 新玩意

01. the Linux way to solve problems

這兩天在查一個上禮拜聽同事學習分享時所討論到的問題,為了查這個問題,我需要將 RTL module 分開成個別檔案,才不會用 vim search 時過了頭看到錯的地方XD

之前雖然知道可以在 module 第一行用 V + /endmodule 複製整個 module code,但需要用 :tabe 貼上並儲存下來,故我之前用 vim 時都省略儲存下來的步驟,反正要看的 module 數量也不多,每次重作即可。

不要小看每天這樣重複選取複製的時間,累積下來也很可觀,如果可以,我還是習慣在下班時關掉工作站的所有工作階段,故還是要有個機制快速來產生我要 trace 的檔案。

即使是這樣的需求,用 C 語言寫也是很簡單的,最主要 line array 要宣告夠大,畢竟我已經在 RTL 看到不只超過一行長度的 wire 宣告。

但是既然現在都在 Linux 工作站做事,我們就要用 the linux way 來解決問題!也就是善用組合的力量。

查了一下,用 sed 可以跨行尋找 pattern,指令如下:

sed -n '/module XXX /,/endmodule/p'  RTL.v

注意 XXX module name 後面要空一格或是加上 port declaration 的左括號,這要看 RTL coding style,不然假設你有模組 XXX、XXX_1,則全部都會被複製下來。


感覺這個需求還蠻常用的,將整個 script 改寫成變數驅動並放進我的工作站工具箱中。注意,c shell 沒辦法宣告 array,故這裡還是建議使用 bash。

$@ 命令列參數
modules=("aa" "bb" "cc")  bash array
${#modules[@]} 取得陣列個數
unset modules[0] 移除陣列第一個元素


2024/08/29 更新

前天話才說完,今天就遇到不同 coding style 的 module declaration。

這個有點棘手,但不是因為現在這個 case 棘手,而是隨著這個衍生而來的 case 棘手。

綜合我目前看過的 coding style 至少有 3 種:

module pattern (xxx, xxx)
module pattern(xxx,xxx)
module pattern
(

如果下 module pattern\s*\(* 並不能解決 pattern 及 pattern_x 在 sed 一起出現的問題,但我現在想不到更好的方式只用一個 regex 就可以解決的。

2024年8月25日 星期日

Verilog 里程碑

Verilog 真的是很神奇的一門語言!

有時候覺得懂了,有時候卻又覺得什麼都不懂!至少無法像我會的其他程式語言一樣,可以隨心所欲的拿它來解決任何問題。

HDLBits 是一個很好的網站,可以拿它來學習 Verilog,但它有一些缺點,我們無法看到它的 Testbench,所以有時 debug 會有點困難,不過想想 leedcode 也是如此,似乎也很正常?

另外,它其實是會跑 Synthesis,故它其實是用合成出來的 netlist 來跑 Testbench。換句話說,如果寫出來的 Verilog 有問題,則有可能會跑不過 post-synthesis simulation。


這題我覺得是一個學習 Verilog 的里程碑,至少對我來說是如此。

照它題意,它希望你用前幾題學到的技巧,來解決這題,也就是將前幾題的電路用在此處。

但我一直無法順利用小電路來解決此一道題,我甚至想寫 3 個 module 來解此問題,其中最後兩個訊號,我感覺是一樣的意思,故想用同一個 module 來解題,換句話說,我的 top_module,就只是 initial 4 個實體罷了。

雖然可以用 iverilog 跑成功,但是在 HDLBit 就是會錯在 130 ns 的時間點,在知道 HDLBits 是用 netlist 跑合成後,我甚至用 DC 試跑合成,果然我的 netlist 用 ncverilog 也會跑出問題,問題是出在 DC 會報 time loop warning,故它在 3 個 cell 處會忽略 timing arc,我在 dump waveform 會一直無限膨脹檔案大小,卡在 100 ns 處,感覺是我組合邏輯哪邊有問題?


如果我放棄使用小電路方式來解題,改在 top_module 用 FSM 寫出所有的 code,就可以順利通過 HDLBits 的 Testbench。

我想讓 shift_ena、counting、done 都委由 submodule 來設定,但這會有 timing 問題,有時候為了滿足 timing 我甚至會在 submodule 改用組合邏輯提早一個 T 將訊號送出,好滿足下一個 submodule 的 timing。

先不說這樣設計對不對,但我還是想用這樣的方式來解決這一道題目,說它是我學習 Verilog 的里程碑還真不為過。

想當年我初學程式以及使用 Keil C 撰寫 8051 也都是卡在某個地方,後來意外打通之後,世界突然就變輕盈了,真希望趕快打通這裡。

2024/08/25 更新

忘記在哪個 github 看到,有人確實是用兩個電路來解決此題,recognizer and shifter,但是他是在 top_module 統一控制 output 訊號。

目前只知道,HDLBits 會故意在不同階段亂送某階段需要觀察的訊號,但我還是想不通我的 130 ns 錯在哪裡?

2024/08/26 更新

我的第一個 submodule pattern 是用來捕捉 1101 訊號用,故其餘的 submodules 都是靠他往下走,所以我需要讓 pattern 不要被 data 訊號影響,這是我錯誤的第一個點,也就是說整個電路未完成前(未收到 ack 前),我的 pattern 應該要讓他一直處在 reset 狀態才對。

其餘的錯誤就是其他 submodules 忘記在 END state 回到 IDLE 階段。


雖然目前暫時解決了,但為了配合時序圖,提早改變 output 訊號感覺還是很怪?

我覺得要不就是我不能這樣劃分 submodule,不然就是我的 verilog 寫法還是哪邊觀念不對。

2024/08/27 更新

今天看 1500 spec 時,文件也有提到需讓待測 core 視情況處在穩定狀態(reset),看起來這是用 Verilog 描述電路時的一個重要關鍵,就像我們純軟在 task 做完時,會 reset 變數一樣!

補上 gtkwave 訊號 configuration,之後有空再來繼續改進此電路XD

橘色劃線的訊號就是為了配合時序控制下一個電路而提早 1T 改變的回饋觸發訊號。


2024/08/29 更新

看 1500 spec 突然想到,米利型 FSM 的輸出不只要看 state 也會看輸入,我的 stop_module 頗有這樣的味道在?done_counting or ack 就是我要配合的輸入。

另外在看同事 wrapper demo code 時,發現該同事會用很多 assign 語法,甚至還看到他不直接 posedge clk 而是改用 assign 語法將 wire 搭配一些條件判斷將 clk 指派給該 wire,之後反而直接用 posedge wire_name?

原來我沒看過的 Verilog code 還真多,雖然還沒深入探討,但應該是為了 timing 或是為了縮短減少測試時間?應該吧?

2024/08/30 更新

昨天忘記補充,摩爾型 3 段式 FSM 的 output logic,我有看到用組合的也有看到用循序的。

我覺得比較合理的應該是用組合邏輯,但我有看到一個比較合理的說法,為了避免組合邏輯 path 過長影響 timing,所以會多敲一級改用循序邏輯。

不過在我這邊的 case 就不適用,因為我的 timing 已經太慢,用循序會再多慢上 1T。

2024年8月22日 星期四

一些 SSD 數據

前家裡用筆電 SSD,用了約兩年又一個月


現役家裡用筆電 SSD,用了約一年又一個月


目前公司用桌機 SSD,差兩個月滿五年

2024年8月18日 星期日

每天都有新發現的 Linux

今天無意間看到一個 Youtube 推薦的駭客影片,雖然內容類似在解譯大陸牌子的網路攝影機 HTTPS 封包的內容,但在觀看的過程中,無意間發現作者使用了一個 "find ." 指令來列出現在目錄下的所有檔案,雖然我們可以用 ls -l 來印出檔案,但還需要再用 awk 取出檔名欄位,也無法列出子目錄的檔案,應該吧?

最近在整理別人的 code list 並加到 Synthesis TCL script 中,之前還傻傻的一個目錄一個目錄進去 ls,原來還有更快的方法,只要組合一堆指令,然後在根目錄打出這一串組合指令即可。

find . | sed -Ee 's/\.\/(.*)/\1/g' | awk -v var="$PWD" '{print var "/" $1}'

因為 "find ." 列出所有的檔案前面會包含 ".",雖然不影響結果,但看了就是不順眼XD

接著使用 sed 把 "." 去掉,最後再用之前這篇文章的做法,加上 $PWD 字串。


不得不承認 Linux 跟 vim 一樣,每天都能發現新玩意!

雖然我覺得一定還有其他做法,但等到下次發現新大陸時再說吧XD

2024/08/19 更新

原來用 "ls -1" 可以只列出檔案名稱並且 line by line 顯示。

所以我建了兩條 alias,一個配合 "ls -1",一個用 find 跨目錄搜尋。

因為用 alias 要跳脫,故把 fabs_name 簡化一下,不要把 "find ." 結果的 "/" 濾掉,將 "\/" 改放進括弧內 (\/.*) 也就是我們要取的 \1,這樣後面的 awk print 就可以簡化,不然很難懂XD


2024年8月17日 星期六

終於要畢業了

2021 年買了暗黑 2 重製版 PC 版遊戲後,由於手上滿 7 歲的筆電沒有獨顯,故無法執行遊戲!後來又把打算換機的預算挪去做好事,一直等到 2022 年端午節前夕才狠下心來購買 Switch 主機以及暗黑 2 重製版 Switch 版遊戲,也算回味一下當年畢業後玩過的少數幾款遊戲之一,記得當年玩過死靈法師後就因工作繁忙沒有下文了,也不太有印象當初手上為何有那款遊戲?

從 2022 年端午節開始,陸續玩了死靈法師、雙熱丁、旋風蠻、槌丁、電法、弓馬、標馬、召德、冰法、馬賽克刺客、又一隻雙熱丁以及最後的天拳丁,很多角色都是在半夜睡不著覺的夜晚練起來的,就如同今天凌晨 4 點起來關心洛杉磯的街頭一樣XD

雖然也不是每天都在玩,但陸續也投資了不少時間在上頭,這條路總有走到盡頭的時候。

可惜人生總有遺憾,尤其是暴雪不合理的升級經驗懲罰制度,實在是逼人花時間去玩遊戲!

雖然不玩了,還是記錄一下未完成的代辦事項。

01. 槌丁扮盾丁 atking

這隻由雙熱丁起家,9X 級後邊打紅門邊轉槌丁以及邊農裝備養家,配合單機複製大法複製打到過的特大板,最高傷害可以來到 15K 左右,幾個月前又悟出戰召權杖配裝後,雖然傷害只剩 12K,但什麼場景皆可通刷,只差打紅門時要不斷的喝紫水,整體來說也算是盡顯王者風範。


上圖是升 97 前抓的圖,盔甲也還只是法鎧,中間有過渡穿灰暮罩衣,最後則是穿龍皮甲的謎團,這樣好處是防禦可以多快 200,壞處是要額外點力量。

目前只差升到 98 就可以補齊專注靈氣的最後 1 點技能點,如果要開聖護打紅門則需要升到 99 級,當然也可以不點救贖改用權杖自帶的救贖技能,缺點是切執法者就不能使用救贖。

在悟出我要用標馬打牛關比較容易出征戰權杖後,武器就差打到 +3 祝槌以及 +3 專注的權杖,目前手上拿的是 +2 祝槌的戰召,另外也未成功洗出聖騎士 20 高施加 20 全抗的權冠。


02. 跟小老婆同名的冰法 Clare

雖然前一陣子順利打到夜翼面紗,但還差升到 96 補齊冰封球的最後一點技能點。


03. 手感最好的弓馬 Bow

技能點在 94 已差不多點齊,就差戰旅鞋未曾打到,目前掃射應該是 8K 左右。


賭百抗鞋的相關注意事項

clvl = character level 角色等級
mlvl = monster level 怪物等級
ilvl = item level 物品等級
    a. 等於怪物身上掉的 ilvl = mlvl
    b. npc 出售物品 ilvl = clvl + 5,但普通難度有上限
    c. 賭博時 ilvl = clvl - 5 ~ clvl + 4
    d. 洽西注入 ilvl = clvl + 4
    e. 隨著方塊公式改變
    f. 翻箱掉落 ilvl = area level

qlvl = quality level 品質等級
    不同物品有不同等級

magic_lvl = magic level 魔法等級
    只有少數物品有,比如權冠

alvl = affix level 魔法字首尾等級
    百抗鞋就是要看這個,來決定要用什麼等級角色賭什麼物品。

先決定你要的詞彙 alvl,再看你要賭的鞋 qlvl,便知道 ilvl 用多少等級角色,小數點是無條件捨去。



可以直接看此 Youtuber 的影片或是 ptt Diablo 精華區 z-2-3-9-3。

如果賭皮靴,魔法字首尾只要 30% 高跑,10% 打擊恢復以及百抗:

alvl = 37
qlvl = 3

利用 11 行公式可以得知,ilvl  = 38,因為賭博物品最少為 clvl -5,故得知 clvl = 43,也就是用 43 級人物去賭皮靴即可,由於我們有壓制 alvl,可以避免出現我們不要的詞彙。

但據我賭了八千萬左右的經驗得知,一切還是看臉,我最多得到相加 80 出頭的抗性而已。

我玩了2 年,也只打到過兩雙百抗鞋,且不是單抗都超過 30,高跑也只有 10% 或 20 % 而已。

無意間試出的 Switch 單機複製大法

先開啟任一角色至少打滿 5 ~ 10 分鐘,儲存後改用另外一角色登入,接著迅速複製東西或錢並按下儲存離開,然後迅速按 Home 回到 Switch 桌面並按 X 完全關閉暗黑 2 遊戲。

之後用複製東西的角色檢查,被複製物品以及複製物品都在就是成功了!

95 升 96 單機八人難度經驗值

超市全打約 100 多萬(邪惡區域則有 31X 多萬)。

97 升 98 單機八人難度經驗值

超市全打約 23 萬(邪惡區域則有 100 多萬),只打巴爾五將軍及巴爾約 28 萬。

2024/11/09 更新

最近搞定了 PAD Placement 後,練了一隻火法來慶祝,記錄一下單機 8pp 注意事項!

以下都是有遺產的情況下,除了火棒、火山頭、火法專用高施藍項鍊外,其餘該有的我都有了,包含精神劍盾、橡樹、戰召、大小毀符、技能板 N 片等,大部分的數值都是近頂。

40 幾等可以過普通,不用半小時就可以練到 50 等。

60 幾等可以過惡夢,不用半小時就可以練到 75 等。76 等打巴爾從第四層一路清過去,一次約可升 4 格,77 等時可升 3 格,78 等時可升 2 格。

78 等進地獄,約 83 等可到巴爾,85 等時過關,88 等時打巴爾從第四層一路清過去,一次約可升 2 格。

以上惡夢及地獄懶得慢慢過的關卡都是用飛的,比如第三關,第五關等。

另外在單機複製東西時,假設人物已達上限 28 個記錄檔,最後創建的人物會被清掉以及最後一個開啟的記錄檔其人物技能快速鍵會被清空需要重設。

2024/11/20 更新

最後確定即使只建立 27 個角色,當使用複製大法時,第 27 個人物記錄檔技能快速鍵會被清空需要重設。

另外 90 等時,世界之石邪惡區域,從第二層一路打過去,視怪物數量不定,經驗值可以上升 0.5 ~ 1.5 格,91 等時大概只剩半格多。

結論就是,想練新角色時,大概升到 92 等就好,再來就太累了。

常用角色畢業需要等級

電法 94 等
冰法 96 等
火法 98 等(包含火蛇) 

2024 week 33 新玩意

01. Synthesis area improvement

這兩個禮拜除了研究 Verilog race condition 現象外,其餘時間都在包 SRAM wrapper!

部門資深同事著實太忙,想說自己來研究一下好了,Width 還算簡單,但 Depth 就需要稍微想一下,第一版出來後,對照時序圖寫了 testbench,也確認功能有合乎預期。

這星期再一次 review 同事那包 RTL code 才發現,有一個名為 dual port 的 FIFO SRAM,其真實行為居然是 1R1W,故只好再包另外一種 SRAM wrapper。

這個 wrapper 比較特別,有設計 bypass,但居然是 sequential logic?我唯一想到的就是不要太早反應 SRAM 吐回去的 data?不然正常來說,不管是調整 Width 或是 Depth,我們應該都用 combinationl logic 即可。

除了寫 testbench 外,也順便用 DC 跑 Synthesis,post-synthesis simulation 也是正常。

在等待工作站 code ready 的空檔,順便研究一下 RTL code 與面積的關係。

我需要的 SRAM wrapper 跟真實的 SRAM 資訊如下:

DP 4096X96 ( SP512X32 )
DP 1024X96 ( SP512X32 )
2P 1024X64 ( 2P512X32 )

1 和 2 其實是相關的,故我一開始是用 2 的 module 再包一層,但這樣面積會比較大,拆成 8 顆 512X96 後,面積就改進了。

一些取餘數跟 Address 位址一開始沒想到的 code,在改正後,面積居然沒變,看起來 DC 有一定的功力,知道如何優化。

但隨著 code 不斷再精簡(通常來說,RTL code 越多,其實合出來的 cell 也就越多),最後兩種 wrapper 面積分別可以減少 300 和 200 左右。

我用的 Cell Library INV 的某 cell 面積大概是 1.29,其他一些小 cell 約略是 0.29 左右,基底的 SRAM 以 1P 來看則約莫是 5000 多一點。

過程中還發生了小插曲,因為被 KB5041578 事件搞了,最後一版的 RTL code 還未跑 simulation,故等到下午 IT 處理後補跑才發現資料都是錯的,由於這裡沒有用 Git,工作站空間也很吃緊,故我也沒建 local git,因改動的東西確實太多(第一版 code 真的很差,雖然可讀性比較好,但應該是我還用 SW 思維寫 code 的緣故,之後應該會慢慢習慣),只好一層一層 wrapper 檢查回來,但也很快地找到原因。

我發現組合邏輯善用 bit operation 後,大部分可以有效減少面積,但撰寫時就要特別注意資料寬度是否一致。

由於同事那包 RTL code,其 SRAM port 和 active signal 都跟我用的 Cell Library 不同,考量這只是中繼 wrapper(最終還是要用 Memory Compiler 重新產生,只是什麼軟體都要 License,目前部門還沒有相關 License 可用),故把 difference 直接改在最底層的 module code 中。

原本的 code:

localparam WIDTH = 32;

input WEB;

if (WEB)
    BWEB = 32'h00000000;
else
    BWEB = 32'hFFFFFFFF;

改進後:

BWEB = (~(32'h00000000 | WEB)

正確的 code:

BWEB = (~(32'h00000000 | {WIDTH{WEB}};

只是 or 操作的長度不對,結果就天差地遠XD

02. testbench simulation

雖然知道了 Verilog race conditon,也看了Clifford E. Cummings 大神的幾篇論文,但對於 testbench 設值的時間點還是不知道有沒有一般公認的標準可供遵循?大神的論文雖然有些建議,但我還是覺得看 Spec 寫 testbench 還是最適當?

寫 testbench 時,我們很容易讓 clk 和 data 在同一個 timing 中更改,這其實要看 active event region 被 simulaor 取出執行的順序,故結果不一定跟你想的一樣?

這也是為什麼 VCS 有一個 deraceclockdata 的 flag 可設,雖然應該要使用者自行避免才對。

我自己感覺 iverilog 行為是這樣?

testbench 中設定的值,不管是 clk or data,sensitivity list 的 signal,就是你在另外 module 中會用 if 判斷的,iverilog 會先設值,接著是 clk,最後才是 data,就是 RHS 的 signal。

順帶一提,要 trace iverilog 的 code 應該要從 vvp 和 tgt-verilog 的資料夾開始,當初稍微一喵的感覺是這樣?

不過在前項 SRAM wrapper 的研究中,TSMC SRAM 確實是在 postedge 前,address 和 data 就要 ready,我最早版本的 SRAM testbench 也是這樣設值,差別在 TSMC Spec 看起來最好不管是讀或寫,最好都保持 2 個 T 後,第 3 個 T 才繼續下一動操作,雖然我用他們的 verilog code 跑 testbench 用原始版本 1 個操作使用 1 個 T 也是正常?

我目前的結論是還是看時序圖寫 testbench 最準。

希望等到越來越有經驗後,能夠回過頭來給個最後結論。

由於 Verilog 及相關知識都是自行上網學習,也不知道自己看的方向是否正確?

2024年8月16日 星期五

Windows 10 2019 LTSC 不要安裝 KB5041578

前天 8/14 (三) 上午安裝了 3 個 Windows 更新,沒想到重開機後登入就開始發生異常!一開始只看到滑鼠游標,等很久後才看到桌面,任何操作都要等上 20 ~ 40 分鐘不等。

詳細狀況如下:


好不容易在 8/14 (三) 快 6 點時,順利按下舊程式與功能裡的移除更新的對話框,剛好我選的就是 KB5041578,移除後一切正常。

沒想到今天 8/16 (五) 快中午時,又被 ivanti 軟體自動安裝相關更新(我到現在才知道這套軟體有這功能,原本以為只是資產管理軟體之類的),不知情的我在看到 ivanti 軟體重開機提示訊息後又再一次的中獎了!

有了前一次的經驗,一樣慢慢地嘗試去移除該更新,結果卡在執行進度 15% 中,還好後來 IT 來了之後,重開機時發現其實有順利移除,但 IT 多移除了某個更新,我的電腦應該只要移除 KB5041578 即可。

從事件檢視器可以看出,我昨天一整天都正常。


後來聽我新部門強者同事說,他都不管 ivanti 軟體的更新通知,完全不去動它,我才知道還有這招可以使用XD

正常來說,Windows 更新應該要等過一陣子才推送,不過這算重大安全性更新,可能有其他資安政策考量吧?

8/15 (四) 查詢時只看到一篇 reddit 文章討論,看起來也不是什麼重大問題?


剛 google 後,終於有人發表中獎文章了。


這次中獎最大的收穫是知道安全模式不再是開機按下 F8,而是在開機選單中同時按下 Shift 後重開機。

坦白說這是很蠢的設計,如果連開機都有問題,除了安裝光碟外哪有機會進安全模式?

這也是我一直不喜歡微軟的原因。

2024/08/16 晚上更新

我想這篇文章的解決方式應該是正解,我前天確實在能看到工作管理員的情況下,會看到 Cryptographic Services" 一直在讀寫。


2024/08/17 更新

看起來這個網站會討論更新是否有問題,前天就是沒有再繼續追蹤,導致昨天再一次中獎!

查了一下之前自己買的 SSD 是 2019/10 購買,被這個不斷讀寫 bug 也不知會不會搞出內傷?於是勇敢的掏出魔法小卡再買一顆 SSD 為將來的重灌作準備XD

也不知道這個工作會再待多久?花點小錢增加工作效率還是很值得的。

2024/08/19 更新

快下班前檢查了一下,SSD 健康程度 89%,累計寫入 12TB,總使用時數 50XX 小時,查了一下我 5 年前購買的 Crucial MX500 500GB TBW 為 180TB。

對比我家裡購買一年的筆電 SSD,我的累計寫入居然有 4TB,不知是不是被微軟該死的 BitLocker 或是 vcpkg 安裝各個軟體套件的頻繁讀寫有關?


馬上 Disable BitLocker 功能,靠,為了解密又被累積寫入了 400GB,溫度也上升了 6 度左右。順帶一提,我的 C 槽使用量為 334 GB。


另外我強者同事說的沒錯,ivanti 的提醒視窗可以不用理它,應該不會幫你重開機,但是需把視窗移至角落,但大概一個小時內又會被置中提醒重開機。

不得不說,ivanti 真的很爛繼之前不斷發 arp 封包打掛我的 UEFI 測試外,事件檢視器系統裡有一個 "CISMBIOS Warning event ID  54" 事件居然也是 ivanti 引起的,每天都有快 10 個 Warning,當我們有需要檢查事件檢視器時,真的會影響我們查找事件的工作效率。


2024/08/29 更新

為了等待一個未完的工作,一直不敢抱電腦去重灌,而這個星期居然有其他不是我作業系統版本的同事被 IT 電話通知要更新系統。

早上終於輪到我被 email 通知了,跟 IT 約好明天更新,由於會有一些時間不能使用電腦,乾脆請特休好了,順便可以去處理一些私人事情。

不過 IT 說可以原機升級,除非特殊狀況才要整個重灌,於是趁著快中午前安裝 5 年前購買的 Renee Becca 將舊 SSD 資料複製到新 SSD。

這次不同上次,可能是電腦還在使用的關係,進度不快,還好吃飯時可能因為休眠,故進度有加快,回來時就已經複製完畢。

忘記上次將新 SSD 接回電腦後開機是否需要掃描修復?我才不到 180 的實際使用空間居然花了一個小時半才搞定?幸好掃描完開機還是無痛的轉移完畢。

2024年8月11日 星期日

Verilog race condition example

在 IEEE Std 1364-2005 Section 11 提到 Event simulation 和 stratified event queue 等概念,雖然只有 4 頁,但卻很難用自己的話來闡述它。

簡單來說,event 在執行時,會將其加到 event queue 並分為 5 大區塊,只有放到 active event region 的 event 才會被移出,其它 region 則是會隨時機移到 active event queue。

由於 simulation 是用軟體模擬,不像硬體電路可以並行,故在執行上會有先後之分,因此這章節會定義哪些 execution event 其執行順序是確定的,哪些又不是。

因此我們要注意撰寫 Verilog code 以避免 race condtion 發生。

下面是一個簡單的例子可以看出隨著調整不同區塊的位置,其模擬結果也會不同。

flag = 1

0: initial1 d = 0
0: initial2 d = 0
0: always1 d = 0
0: always2 d = 0

flag = 0

0: initial1 d = x
0: initial2 d = x
0: always1 d = 1
0: always2 d = 1

`timescale 1ns/1ns
`define flag 0

module test();
    reg d;
    
    initial begin
        if (`flag)
            d = 0;
    end
    
    initial begin
        $display("%t: initial1 d = %d", $time, d);
    end
    
    always @(*) begin
        $display("%t: always1 d = %d", $time, d);
    end
    
    always @(*) begin
        $display("%t: always2 d = %d", $time, d);
    end
    
    initial begin
        $display("%t: initial2 d = %d", $time, d);
    end
    
    initial begin
        if (!`flag)
            d = 1;
    end
endmodule