# 2017q3 Homework3 (simulator) contributed by < `changyuanhua` > ## 閱讀筆記 ### 現代處理器設計 - [ ] 閱讀 [現代處理器設計](http://hackfoldr.org/cpu) 教材和觀看裡頭所有錄影,記錄你的心得和疑惑 #### 原理和關鍵特徵 #### Cache 原理和實際影響 #### 虛擬機器設計與實作 ### 你所不知道的 C 語言:編譯器和最佳化原理篇 - [ ] 對照研讀 [你所不知道的 C 語言:編譯器和最佳化原理篇](https://hackmd.io/s/Hy72937Me) 教材和觀看直播錄影,以得知編譯器運作原理 ### 你所不知道的C語言:遞迴呼叫篇 - [ ] 閱讀 [你所不知道的C語言:遞迴呼叫篇](https://hackmd.io/s/rJ8BOjGGl) 和觀看對應講座錄影 - [ ] 用 [full-stack-hello](https://github.com/sysprog21/full-stack-hello) 的指令實作 Fibonacci 數列 - [x] 需要包含 recursive 和 non-recursive 實作,分別置於檔案 `tests/fib-recursive.s` 和 `tests/fib-iterative.s` - [x] 修改 `vm.c` (和對應的原始程式碼),允許執行時期由使用者 (和 `Makefile`) 帶入參數,如 `--input`,這數值應該透過暫存器作為上述 Fibonacci 數列程式的 `Fib(N)` - [ ] 研究現有 [full-stack-hello](https://github.com/sysprog21/full-stack-hello) 的自動測試程式,整合上述兩種 Fibonacci 程式實作,並且比較效能 (需要包含 vm 內部的 cycle count) - [ ] 考慮以下 Fibonacci 數列的實作方式,並善用 GNU plot 製圖和解讀 - [x] Tail recursion - [ ] Q-Matrix - [ ] Fast doubling ## 開發環境 ``` Architecture: x86_64 CPU 作業模式: 32-bit, 64-bit Byte Order: Little Endian CPU(s): 4 On-line CPU(s) list: 0-3 每核心執行緒數:1 每通訊端核心數:4 Socket(s): 1 NUMA 節點: 1 供應商識別號: GenuineIntel CPU 家族: 6 型號: 94 Model name: Intel(R) Core(TM) i5-6300HQ CPU @ 2.30GHz 製程: 3 CPU MHz: 799.890 CPU max MHz: 3200.0000 CPU min MHz: 800.0000 BogoMIPS: 4608.00 虛擬: VT-x L1d 快取: 32K L1i 快取: 32K L2 快取: 256K L3 快取: 6144K NUMA node0 CPU(s): 0-3 ``` ## 解析程式架構 以 `driver.c` 為主要程式,其他程式作為輔助,提供相關的函式,下面分別簡單概述每個程式的主要功能: * opcode:自訂指令集,以及相關實作,實作主要用於虛擬機器 * as:組譯器,用於組譯自訂指令集,產生對應的 object file * elf:提供產生 object file 相關的函式 * vm:虛擬機器,內涵虛擬機器的架構, 運作 ## 接受輸入參數 在 `vm.h` 和 `vm.c` 加入一個可以設定 temps 的值的函式 `vm_set_temp_value(vm_env *env, int pos, int val)` : 接收輸入參數,並將輸入參數存入 vm 中的 #0 位置 ```clike= inline void vm_set_temp_value(vm_env *env, int pos, int val) { vm_value v = {.type = INT}; v.value.vint = val; env->temps[pos] = v; } ``` 接著在 `driver.c` 中 `argv` 的部份加入 --input 的判斷,並以 `input` 紀錄輸入的值 ```clike= int input = 0; ... else if (!strcmp(argv[i], "--input")) { if (!argv[i + 1]) FATAL(-1, "Missing argument\n"); input = atoi(argv[++i]); } ... ``` 接著在 `driver.c` 中初始化 vm 的下一行都強制設定 **#0** ```clike= vm_env *env = vm_new(); vm_set_temp_value(env, 0, input); ``` 最後在 `Makefile` 內新增 Fibonacci 相關的操作 ```cmake= TEMP ?= 10 FIB_ITERATIVE ?= ./tests/fib-iterative.s FIB_RECURSIVE ?= ./tests/fib-recursive.s fib: $(EXEC) @./$(EXEC) --input $(TEMP) $(FIB_ITERATIVE) @./$(EXEC) --input $(TEMP) $(FIB_RECURSIVE) ``` reference: [st9007a 共筆](https://hackmd.io/s/Hkf6pkPAb) ## 實作 Fibonacci 數列 ### iteration c code: ```clike= int iterative(int x) { int first = 0 , second = 1 , result = 0; if (x == 0) return n; if (x == 1) return n; int i = x - 1; while(i > 0) { i--; result = first + second; first = second; second = result; } return result; } ``` 組合語言: ```clike= ; #0: x ; if (x == 0) return x jz #0 #15 ; if (x == 1) return x sub #0 $1 #4 jz #4 #15 or $0 #4 #0 ; #1: first = 0 ; #2: second = 1 ; #3: result = 0 or $0 $0 #1 or $0 $1 #2 or $0 $0 #3 ; iteration jz #0 #13 sub #0 $1 #0 add #1 #2 #3 or $0 #2 #1 or $0 #3 #2 call #7 print #3 halt print #0 halt ``` ### recursive c code: ```clike= int recursive(int x) { if (x == 0) return 0; if (x == 1) return 1; return recursive(x - 1) + recursive(x - 2); } ``` 組合語言: ```clike= ; #0: x ; #1: result = 0 or $0 $0 #1 call #4 print #1 halt ; if (x == 0) return 0; or $0 #0 #2 jz #2 #12 jnz #2 #8 ret ; if (x == 1) return 1; sub #0 $1 #2 jz #2 #11 jnz #2 #13 add #1 $1 #1 ret ; fib_ecursive(n-1) sub #0 $1 #0 call #4 ; fib_recursive(n-2) sub #0 $1 #0 call #4 add #0 $2 #0 ret ``` ### tail recursive c code: ```clike= int tail_recursive(int x, int a = 0, int b = 1) { if (x == 0) return a; if (x == 1) return b; return tail_recursive(x-1, b, a+b); } ``` 組合語言: ```clike= ; #0: x ; #1: a = 0 ; #2: b = 1 ; #3: result = 0 or $0 $0 #1 or $0 $1 #2 or $0 $0 #3 call #6 print #3 halt ; if (x == 0) return a or #0 $0 #4 jz #4 #9 jnz #4 #11 or $0 #1 #3 ret ; if (x == 1) return b sub #0 $1 #4 jz #4 #14 jnz #4 #16 or $0 #2 #3 ret ; tail_recursive(x-1, b, a+b) sub #0 $1 #0 or $0 #1 #4 or $0 #2 #1 add #2 #4 #2 call #6 ret ``` ### Q-Matrix The Fibonacci Q-matrix 的定義為下方式子: $Q=\left [ \begin{array}{cc} F_2 & F_1 \\ F_1 & F_0 \end{array} \right ]=\left[ \begin{array}{cc} 1 & 1 \\ 1 & 0 \end{array} \right ]$ ,其中 $F_n$ 是斐波納契數。 $Q$ 的n次方: $Q^n=\left [ \begin{array}{cc} F_{n+1} & F_n \\ F_n & F_{n-1} \end{array} \right ]$ 而得知 $Det(A^n)= Det(A)^n$ ,因此得到下列性質: $Det(Q^n)= Det(-1)^n$ 又因此結合上述式子,可以得到: $Q^{n}Q^{1}=Q^{n+1}$, $Det(Q^n)= F_{n-1}F_{n+1}-F_n^2 = (-1)^n$ 然後就能得知下列式子: $Q^{n+1}=\left[ \begin{array}{cc} F_{n+1} & F_n \\ F_n & F_{n-1} \end{array} \right ]$$\left[ \begin{array}{cc} F_{2} & F_{1} \\ F_{1} & F_{0} \end{array} \right ]=\left[ \begin{array}{cc} F_{n+2} & F_{n+1} \\ F_{n+1} & F_{n} \end{array} \right ]$ 也就是說,每次做矩陣乘法,$F_n$ 會被 $F_{n+1}$ 取代 組合語言 ```clike= ; #0: n ; #1: F0 = 0 ; #2: F1 = 1 ; #3; F2 = 1 ; #4; result = 0 or $0 $0 #1 or $0 $1 #2 or $0 $1 #3 or $0 $0 #4 ; if (n == 0) return 0 jz #0 #25 ; if (n == 1) return 1 sub #0 $1 #5 jz #5 #25 or $0 #5 #0 sub #0 $1 #0 jz #0 #23 ; F2 = 1*F2 + 1*F1 mul $1 #3 #4 mul $1 #2 #5 add #4 #5 #4 ; F1 = 1*F2 + 0*F1 mul $1 #3 #5 mul $0 #2 #6 add #5 #6 #5 ; F0 = 1*F1 + 0*F0 mul $1 #2 #6 mul $0 #1 #7 add #6 #7 #6 or $0 #4 #3 or $0 #5 #2 or $0 #6 #1 call #8 print #4 halt print #0 halt ``` ### Fast doubling