# C07: simulator
###### tags: `sysprog2017`
:::info
主講人: [jserv](http://wiki.csie.ncku.edu.tw/User/jserv) / 課程討論區: [2017 年系統軟體課程](https://www.facebook.com/groups/system.software2017/)
:mega: 返回「[進階電腦系統理論與實作](http://wiki.csie.ncku.edu.tw/sysprog/schedule)」課程進度表
:::
## 預期目標
* 搭配 [現代處理器設計](http://hackfoldr.org/cpu),實際練習系統軟體開發
* 思考函式呼叫和掌握遞迴程式開發技巧
* 擴充給定的指令集 (ISA) 模擬器
## [full-stack-hello](https://github.com/sysprog21/full-stack-hello)
* [full-stack-hello](https://github.com/sysprog21/full-stack-hello) 是成功大學發展的小型指令集模擬器,附帶組譯器和編譯器等系統工具
* 編譯和測試
```shell
$ git clone https://github.com/sysprog21/full-stack-hello.git
$ cd full-stack-hello
$ make
$ make check
```
預期得到以下輸出:
```
42
tests/halt.s pass
Hello World
tests/hello.s pass
42
50
150
tests/test.s pass
$ make test
python tests/run_tests.py
..
---------------------------------------------------------
Ran 4 tests in 0.002s
OK
```
* 組譯器使用
```
$ ./as_exec -h
Usage: as_exec [-w] [-x] [-o <out_file>] <in_file>
-w Assemble <in_file> and write to an ELF file, see -o below
-o if -w is specifed, <out_file> is used to store the object code
-x Load <in_file> and execute it
<in_file> the file name to be used by commands above
```
* 用給定的 `tests/hello.s` 檔案做示範
1. 組譯和執行
```shell
$ ./as_exec tests/hello.s
```
2. 組譯並輸出 ELF 格式目的檔 `tests/hello.o`
```shell
$ ./as_exec -w tests/hello.s
```
3. 組譯並輸出 ELF 到給定的路徑
```shell
$ ./as_exec -o tests/temp.o -w tests/hello.s
```
4. 載入之前組譯得到的 ELF 檔案並執行
```shell
$ ./as_exec -x tests/hello.o
```
* 輸出的 ELF 檔案可用 [objdump](https://sourceware.org/binutils/docs/binutils/objdump.html) 工具分析和觀察:
```shell
$ objdump -x tests/hello.o
```
* 注意 `vm.c` 用到 GCC [computed goto](https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html) 的機制
```Clike
#define OP(name) OP_##name
#define BEGIN_OPCODES \
const static void *labels[] = {OP_LABELS}; \
goto *labels[OPCODE.opcode]
#define DISPATCH \
do { \
++env->r.pc; \
goto *labels[OPCODE.opcode]; \
} while (0)
#define GOTO(n) \
do { \
env->r.from = env->r.pc; \
env->r.to = n; \
env->r.pc = n; \
goto *labels[OPCODE.opcode]; \
} while (0)
#define END_OPCODES
```
## [clang-format](https://clang.llvm.org/docs/ClangFormat.html)
* LLVM 專案旗下的 [clang-format](https://clang.llvm.org/docs/ClangFormat.html)
* 安裝方式:
```shell
$ sudo apt-get install clang-format
```
* 延伸閱讀: [使用Clang-format來幫助你美化你的程式碼](https://forum.angular.tw/t/topic/235)
## 作業要求
* 閱讀 [現代處理器設計](http://hackfoldr.org/cpu) 教材和觀看裡頭所有錄影,記錄你的心得和疑惑
* 研究給定的 [full-stack-hello](https://github.com/sysprog21/full-stack-hello),學習其中 ISA 和模擬器實作,並在 GitHub 上 fork [full-stack-hello](https://github.com/sysprog21/full-stack-hello)
* 對照研讀 [你所不知道的 C 語言:編譯器和最佳化原理篇](https://hackmd.io/s/Hy72937Me) 教材和觀看直播錄影,以得知編譯器運作原理
* 閱讀 [你所不知道的C語言:遞迴呼叫篇](https://hackmd.io/s/rJ8BOjGGl) 和觀看對應講座錄影,用 [full-stack-hello](https://github.com/sysprog21/full-stack-hello) 的指令實作 Fibonacci 數列
* 需要包含 recursive 和 non-recursive 實作,分別置於檔案 `tests/fib-recursive.s` 和 `tests/fib-iterative.s`
* 修改 `vm.c` (和對應的原始程式碼),允許執行時期由使用者 (和 `Makefile`) 帶入參數,如 `--input`,這數值應該透過暫存器作為上述 Fibonacci 數列程式的 `Fib(N)`
* 研究現有 [full-stack-hello](https://github.com/sysprog21/full-stack-hello) 的自動測試程式,整合上述兩種 Fibonacci 程式實作,並且比較效能 (需要包含 vm 內部的 cycle count)
* 除了 recursive 和 iterative 版本,應該一併考慮以下 Fibonacci 數列的實作方式,並善用 GNU plot 製圖和解讀
* Tail recursion
* Q-Matrix
* Fast doubling
* 過程中可修改 [full-stack-hello](https://github.com/sysprog21/full-stack-hello) 模擬器的程式碼,加入追蹤 / 除錯用途的指令 (instruction),也應該探討模擬器的運作機制並說明自己修改的方式
* 注意 Fib(46) 之後的數值會超過 2^32^ 可表達的範圍,需要設計有效的數值表示機制來處理 (如用兩個 32-bit 暫存器保存 2^64^ 數值)
* 觀察 [Add label support](https://github.com/jserv/full-stack-hello/pull/30) 的實作方式,試著在[full-stack-hello](https://github.com/sysprog21/full-stack-hello) 給定的組譯器中新增 label 的支援
* 相關的背景知識錄影共有 ==18 小時== (當然不可能看了就懂,請預留思考和提問討論的時間),務必及早開始
* 將你的觀察、上述要求的解說,以及各式效能改善過程,善用 gnuplot 製圖,紀錄於「[作業區](https://hackmd.io/s/BJR9BTlRW)」
## 截止日期
* Nov 9, 2017 (含) 之前
* 越早在 GitHub 上有動態、越早接受 code review,評分越高