# 2018q3 Homework1 contributed by <`yanjiunhaha`> >這是固定格式,請注意 >[name=課程助教][color=red] >>了解。[共筆示範](https://hackmd.io/s/Hyv1gVRux)所使用的格式好像不太一樣,所以讓我猶豫了。[name=YanJiun][time=Wed, Sep 19, 2018 12:33 AM] > Homework2 之後才會嚴格要求格式 [name="jserv"] --- ## [2018q3 第 1 週測驗題](https://hackmd.io/s/S1a9-YO_Q#) ### Problem 1 ::: success 嘗試不用 XOR 運算子做出等效的 XOR 運算。 ::: * 解答 : ```C int my_xor(int x, int y) return (x | y) & (~ x | ~ y); ``` * 心得: 當我一看到這個題目,我馬上想到我在高中學到的數位邏輯。 $A \oplus B = \overline{A}B + A\overline{B}$ \begin{array}{|c|c|c|} \hline A \ B & 0 & 1 \\ \hline 0 & 0 & 1\\ \hline 1 & 1 & 0\\ \hline \end{array} 但我看到 code 發現到它前面指定 `(x | y)`,我就思考了一下才想起它還有另一種表示法: $A \oplus B = (A+B)(\overline{A}+\overline{B})$ * 延伸思考: $\overline{A}B + A\overline{B}$ 與 $(A+B)(\overline{A}+\overline{B})$ 功能雖然一樣,但是用到的運算單元次數不一樣。 前者只用一次 Or,但有兩次 And。 `(~ x & y) | (x & ~ y)` 後者只用一次 And,但有兩次 Or。 `(x | y) & (~ x | ~ y)` * And 和 Or 運算哪個比較快? ==我的猜想:~~And 比較快~~== ==一樣== >仔細思考後,這些運算在一個系統中應該都已經整合成一個 ALU 了。 >即使這些運算真的有些微的延遲差異,其實應該都在系統整合時,就已經被**管線化**( Pipeline )。 >因此我們在考慮這類的效率問題,應該是要以==指令==層級來考慮。 >應該考慮程式碼所對應的==組合語言==,並且計算每個==指令==執行所需幾個 ==指令週期 ( Cycle )==。 >這裡 And 與 Or 的==指令週期==應該是一樣的。[name=YanJiun][time=Fri, Sep 21, 2018 10:16 AM][color=#0000ff] :::warning 避免只用圖表去判斷特定 logic gate 是否「快」(這不是精準詞彙),請複習數位邏輯電路,用 pre-determined latency 來分析。 :notes: jserv ::: 這是一張 4 bits 加法器,可以做一般的加/減法 ($S$ 可以控制),由四個半加器 (FA) 構成。 ![4bits adder](https://d2vlcm61l7u1fs.cloudfront.net/media%2F6ca%2F6ca063f0-7cb9-4698-b188-4e5bcc3f039d%2Fphpk2uxlt.png) ###### [image resource](https://www.chegg.com/homework-help/questions-and-answers/want-make-4-bit-ripple-carry-adder-subtractor-using-verilog-hdl-made-4-bit-ripple-carry-ad-q13057505) 根據上圖,如果我們想要讓這個加法器也可以做出邏輯運算的效果,我們只須改動一小部份。 * And 運算: 將每一級的 $C_i$ 不要接上下一級的 FA ,且直接將 $C_i$ 輸出及是 $A_i\&B_i$($S$ 為 $0$)。 * Or 運算: 將每一級的 $C_i$ 不要接上下一級的 FA ,且將 $C_i$ 與 $S_i$ 做 Or 運算後輸出及是 $A_i|B_i$ ($S$ 為 $0$)。 Or 運算會多出一個 Gate 的延遲時間,因此做出此猜想。 但這也只是我目前所學,實際上電腦的 CPU 設計可能不是如此簡單。 --- ### Problem 2 :::success Parity (check) bit 可翻譯為「奇偶校驗位元」或「同位檢查位元」。 ::: * 解答 ```C int max = 16; while (max >= 8) { num = num ^ (num >> max); max /= 2; } ``` 由於後面這行`return table[num & 0xff];`,這裡的 table's size 只有 $256$。 需要將 num 降到 $256$ 以下。 但我關注的重點不是 `max` 應該`/=`多少,而是這裡使用的 `^`。 (Xor 的真值表可以往上找) 根據 Xor 的特性我們可以發現,`1` 將會兩兩消除,因此不會影響奇偶校正結果。 :::info example 1101_0011 $\Rightarrow$ 1101 ^ 0011 $\Rightarrow$ 1110 0011_1011 $\Rightarrow$ 0011 ^ 1011 $\Rightarrow$ 1000 ::: * 心得 我一眼先看到這段程式碼 ```cpp /* Generate look-up table while pre-processing */ #define P2(n) n, n ^ 1, n ^ 1, n #define P4(n) P2(n), P2(n ^ 1), P2(n ^ 1), P2(n) #define P6(n) P4(n), P4(n ^ 1), P4(n ^ 1), P4(n) #define LOOK_UP P6(0), P6(1), P6(1), P6(0) ``` 冷靜分析一下馬上就懂了。 1. `n ^ 1` 其實等效於 `!n` 2. `LOOK_UP ` 列出前幾項 ``` 0110_1001_1001_0110 1001_0110_0110_1001 1001_0110_0110_1001 0110_1001_1001_0110 ``` 0~10~ = 000~2~ $\Rightarrow$ 0 1~10~ = 001~2~ $\Rightarrow$ 1 2~10~ = 010~2~ $\Rightarrow$ 1 3~10~ = 011~2~ $\Rightarrow$ 0 不知道你看出規律了沒,我多列了幾行。 3. `unsigned int table[256] = { LOOK_UP };` 事實上這個 `table` 是一個 $16\times16$ 的**對稱矩陣**。 當下我馬上想要縮減這個矩陣,以減少佔用記憶體空間。 很快的,我便覺得這個`table`可以直接使用**演算法**替代。 * 缺點是這樣的程式將無法確定在==常數時間==完成。 * 優點是可以省下`256*sizeof(int)`的記憶體空間。 * 延伸思考 那可以用哪些**演算法**取代呢? 1. 計算資料裡`1`的個數 ```C int count = 0; while(n) { n = n & (n-1); ++count; } return count & 0x1; ``` 這個算法的複雜度是`n`有幾個`1`就跑幾次。 2. 使用上面程式碼的概念 ```C while (max) { n = n ^ (n >> max); max >>= 1; } return n & 0x1; ``` 這個演算法的時間複雜度則取決於輸入資料寬度,$log_2(sizeof(n))$。 3. [week3 隨堂測驗-3](https://hackmd.io/s/BkyQskjK7#) ```c #include <stdint.h> int parity(uint32_t x) x ^= x >> 1; x ^= x >> 2; x = (x & 0x11111111U) * 0x11111111U; return (x >> 28) & 1; } ```