---
# System prepended metadata

title: Computer Org
tags: [note, courses]

---

# Computer Org
###### tags: `courses`, `note`

## Cache
### 濃縮
> 參考：https://hackmd.io/@drwQtdGASN2n-vt_4poKnw/H1U6NgK3Z?type=view

```graphviz
digraph {
  rankdir=LR;
  cpu [label="CPU"]
  m [label="main memory"]
  
  cpu -> m [label="addr"]
  m -> cpu [label="data"]
  rank=same; cpu; m;
}
```
```graphviz
digraph {
  rankdir=LR;
  cpu [label="CPU"]
  c [label="cache"]
  m [label="main memory"]
  
  cpu -> c [label="addr"]
  c -> cpu [label="data"]
  c -> m [label="addr"]
  m -> c [label="data"]
  rank=same; cpu; m;
}
```
對 CPU 與 main memory 來說，他們的做的事完全沒有改變。
我們會將 main memory 分為很多個 **block**，一次 cache 一個 **block**
```graphviz
digraph {
  node [shape="pain text"];
  rankdir=LR;
  cache [label=<
    <table>
      <tr>
        <td colspan="3" border="0">Cache</td>
      </tr>
      <tr>
        <td>valid</td>
        <td>Tag</td>
        <td>Block data</td>
      </tr>
      <tr><td PORT="line0">1</td><td>01010011</td><td>1010101001</td></tr>
      <tr><td PORT="line1">0</td><td>01010011</td><td>1010101001</td></tr>
      <tr><td>0</td><td>01010110</td><td>1010101001</td></tr>
      <tr><td>:</td><td>:</td><td>:</td></tr>
    </table>
  >];
  
  l0 [label="line: 0" shape=""]
  l0 -> cache:line0
  l1 [label="line: 1" shape=""]
  l1 -> cache:line1
}
```
**Cache line**: 一個 line 包含 valid bit, tag, 與 block data
**Block data**: 從 main memory copy 下來的 data
**Tag**: 在後續用作查詢用的 key

### Cache mapping
在 CPU 要求某個 address 時，我們需要用某種算法查訊這個 address 的 data 在不在當前 cache 起來的 data 中。

#### **Fully-associated**
 main memory 的 address 可以看成，第 x 個 block 中的第 y byte。
 接著把 x 當成 tag，在查詢的時候便咳以直接 for 每一個 line 比較 tag
 
 ```python=
 CPU_get_byte(addr):
   for line in cache:
     if line.tag == addr.tag and line.vaild == True:
       return line.block_data[addr.block_offset]
   return Fetch_data_from_memory(addr)
 ```

##### example:
```graphviz
digraph {
  rankdir=LR;
  label="Assume:\n32-bit addressing arch,\nblock_size=32B"
  m [shape="record" label="main memory|block 0|block 1|<b2>block 2|...|..."]
  addr [shape="pain text" label=<
    <table border="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="10">
      <tr><td colspan="2">address: 32-bit</td></tr>
      <tr>
        <td>000000000000000000000000020</td>
        <td PORT="tail">00011</td>
      </tr>
      <tr>
        <td>tag: 27 bit</td>
        <td>block_offset: 5 bit</td>
      </tr>
    </table>
  >]
  
  addr:tail->m:b2
  cache [shape="pain text" label=<
    <table>
      <tr>
        <td colspan="3" border="0">Cache</td>
      </tr>
      <tr>
        <td>valid</td>
        <td>Tag</td>
        <td>Block data</td>
      </tr>
      <tr>
        <td PORT="b2">1</td>
        <td>000000000000000000000000020    </td>
        <td>block 2</td>
      </tr>
      <tr>
        <td>:</td><td>:</td><td>:</td>
      </tr>
    </table>
  >];
  
  addr:tail->cache:b2
}
```
缺點：查詢慢 

#### **Directed mapped**
將 main memory 中的 block map 到特定 line。

```python=
CPU_get_byte(addr):
  target_line = addr.index
  if target_line.tag == addr.tag:
    return target_line.block_data[addr.offset]
  else:
    return Fetch_from_memory(addr)
```

##### example:
假設總共有 512 個 line。則：
block 0, 512, 1024.. 會 map 到 line 0
block 1, 513, 1025... 會 map 到 line 1
```graphviz
digraph {
  rankdir=LR;
  label="Assume:\
          32-bit addressing arch,\
          block_size = 32B\
          Number of line/block = 512\n"
          
  m [shape="record" label="main memory|block 0|...|<b514>block 514|...|..."]
  addr [shape="pain text" label=<
    <table border="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="10">
      <tr><td colspan="3">address: 32-bit</td></tr>
      <tr>
        <td>0000000000000000000001</td>
        <td>00010</td>
        <td PORT="tail">00011</td>
      </tr>
      <tr>
        <td>tag: 22 bit</td>
        <td>index: 5 bit</td>
        <td>block_offset: 5 bit</td>
      </tr>
    </table>
  >]
  
  cache [shape="pain text" label=<
    <table>
      <tr>
        <td colspan="3" border="0">Cache</td>
      </tr>
      <tr>
        <td>valid</td>
        <td>Tag</td>
        <td>Block data</td>
      </tr>
      <tr>
        <td>1</td><td>some tag</td><td PORT="b0_tail">some block data</td>
      </tr>
      <tr>
        <td>1</td><td>some tag</td><td PORT="b1_tail">some block data</td>
      </tr>
      <tr>
        <td PORT="b2">1</td>
        <td>0000000000000000000001   </td>
        <td PORT="b2_tail">block 514</td>
      </tr>
      <tr>
        <td>:</td><td>:</td><td>:</td>
      </tr>
    </table>
  >];
  
  addr:tail->m:b514
  addr:tail->cache:b2
  
  cache:b0_tail -> index0 [dir="back"]
  cache:b1_tail -> index1 [dir="back"]
  cache:b2_tail -> index2 [dir="back"]
}
```


缺點：有幾個 block 將會共用一個 line，導致他們不能同時存在於 cache 中：

#### **X byte N-way Set Associative**
> 合併上面兩者的好處

將 main memory 中的 block map 到特定 set。
**set**：包含 N 個 line。
因此在查詢時，只需要對一個 set 迭代一次找 tag 即可。
> 有點類似 hash

```python=
CPU_get_byte(addr):
  let target_set = addr.index
  for EACH line in target_set:
    if line.tag == addr.tag and line.vaild == True:
      return line.block_data[addr.block_offset]
    else:
      return Fetch_from_memory(addr)
```


## Page Table

```c=
union Content{
  struct Page_table*;
  Addr phy_addr;
}
struct Page_table {
  Content table[n];
}

Page_table first_table[n];

Addr get_PA_by_VA(Addr VA) {
    struct Page_table* second = first_table.table[VA[0:7]]
    struct Page_table* third = second->table[VA[7:14]]
    struct Page_table* f = third->table[VA[14:21]]
    Addr phy_page_number = f->table[VA[21:32]]
    Addr offset = VA[32:43]
    return concat(phy_page_number, offset)
}
```