Skip to content

Commit

Permalink
add crc note
Browse files Browse the repository at this point in the history
  • Loading branch information
RockyQLuo committed Nov 4, 2024
1 parent 6ccb3b1 commit 6613164
Show file tree
Hide file tree
Showing 9 changed files with 227 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
layout: post
title: AMBA CHI
title: AMBA CHI随笔记
date: 2024-10-20 21:55 +0800
categories: [spec文档阅读, protocol]
tags: []
Expand All @@ -11,9 +11,20 @@ img_path: /assets/img/chi/

## overall
[CHI的几个重要概念](https://mp.weixin.qq.com/s/JK9f90-1E6xQhOE8GWQ9vg)
[【CHI】transaction事务汇总](https://blog.csdn.net/m0_52840978/article/details/133967221?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522ACFA855F-A42C-44F5-A12D-C6401F400E9B%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=ACFA855F-A42C-44F5-A12D-C6401F400E9B&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-5-133967221-null-null.nonecase&utm_term=CHI&spm=1018.2226.3001.4450)




> 无论是独占状态还是共享状态,缓存里面的数据都是clean,<font color="#d99694">在独占状态下</font>对应的Cache Line只加载到了当前CPU核所拥有的Cache里。其他的CPU核,并没有加载对应的数据到自己的Cache里。这个 时候,如果要向独占的Cache Block写入数据,我们可以自由地写入数据,而不需要告知其他CPU核。如果收到了一个来自于总线的读取对应缓存的请求,它就会变成共享状态。
>
> 在共享状态下,需要先向所有的其他CPU核心广播一个请求,把其他CPU核心里面的Cache,都变成无效的状态,然后再更新当前Cache里面的数据。这个广播操作,一般叫作RFO(Request For Ownership),也就是获取当前对应Cache Block数据的所有权。
{: .prompt-info}

[CHI协议的发展](https://mp.weixin.qq.com/s/ZpZNBhW7_VECyr5JwDCSfA)
[前置知识--Transaction Serialization和总线嗅探(Bus Snooping)](https://www.cnblogs.com/gujiangtaoFuture/articles/14336014.html)


Core 未命中读路径最典型的 Flow:

![Core 未命中]({{ page.img_path }}Core 未命中.gif){: width="972" height="589" }
Expand All @@ -24,15 +35,11 @@ Core 未命中读路径最典型的 Flow:

---

- 新术语 Requester(请求者)在旧文档中与 master(主设备)同义
- 新术语 Subordinate(从属设备)在旧文档中与 slave(从设备)同义
- **Write back**:数据首先写入缓存,而不是直接写入主存。当缓存行被替换时,才将数据写回主存。这种策略减少了主存的写操作次数,提高了性能。
- **Write allocate**:如果目标地址不在缓存中,会先把该地址的数据块加载到缓存,然后再进行写操作。这与“write no-allocate”策略相反,后者在写操作时不加载数据块到缓存。


[CHI协议的发展](https://mp.weixin.qq.com/s/ZpZNBhW7_VECyr5JwDCSfA)

## **chap1**

## **chap1 basic**
Coherence overview:如果两个组件对同一存储器位置的写入可被所有组件以相同的顺序观察到,则存储器区域是一致的。

分布式虚拟内存DVM 接口主要用于 Broadcast TLB Invalidate
Expand Down Expand Up @@ -92,27 +99,28 @@ cache line 被定义为大小为 64 字节的以 64 字节对齐的存储器区
![DCT]({{ page.img_path }}DCT.png){: width="972" height="589" }
![DWT]({{ page.img_path }}DWT.png){: width="972" height="589" }

---
## **chap2 Transactions**

待看













---

## **chap4 一致性协议**
> 个人认为这里用到的时候查阅就可以了
{: .prompt-tip}

下面是request types--各种transactions

[这个视频讲了一下type的分类](https://www.bilibili.com/video/BV1cN411T7Pp/?spm_id_from=333.337.search-card.all.click&vd_source=aaf91522adc6826d87c67900ed8b01d9)

[transaction事务汇总](https://blog.csdn.net/m0_52840978/article/details/133967221)

[CHI的事务流程,这个很清晰](https://blog.csdn.net/m0_52840978/article/details/132131717)

<font color="#d99694">下面总结的有点烂 建议看上面文章链接</font>

### 4.2.1 **Read transactions**
有以下特性:

Expand All @@ -125,19 +133,23 @@ read类型的操作分为两类,non-allocating read 和allocating read

![read_class]({{ page.img_path }}read_class.png){: width="972" height="589" }

[transaction事务汇总](https://blog.csdn.net/m0_52840978/article/details/133967221)

<details> <summary><font size="4" color="orange">TMP TRASH</font></summary> <pre><code class="language-scala">

#### 4.2.1.1 **non-allocating read**

![read_noalloc]({{ page.img_path }}read_noalloc.png){: width="972" height="589" }

<details> <summary><font size="4" color="orange">non-allocating read</font></summary> <pre><code class="language-scala">

| read supporting transactions | description |
|---------|------------------------------|
| **ReadNoSnp** | <ul><li>RN请求去Non—snoopable address region获取数据</li><li>不需要snoop其它RN或者HN访问任意空间</li></ul> |
| **ReadNoSnpSep** | <ul><li>与ReadNoSnp类似,只是告知Completer只需要返回data response</li></ul> |
| **ReadOnce** | <ul><li>该命令访问的是snoopable空间,用以获取一份数据,但是该数据不会在当前的RN中缓存</li><li> <font color="#d99694">也就是说,只是用一下该地址的数据;无需allocate到本地私有cache.</font></li></ul> |
| **ReadOnceCleaninvalid** | <ul><li>访问的是snoopable的地址空间;获取该地址的数据</li><li>建议其他拥有该地址copy的RN,其状态变成invalid,但不是强制的</li><li> 如果dirty的cacheline被invalid了,需要将数据写入主存</li><li> 当application想要该地址的数据仍然是有效的,但是近期又不使用的时候,可以使用该命令,而不是readonce/readoncemakeinvalid</li><li> 此命令可以提高cache效率,因为其主动将近期不使用的cache line从cache中invalid掉; </li><li> 此命令不能代替CMO (Cache Maintenance Operation)操作,因为它不保证所有的cachline都变成了invalid; </li><li> 由于这个命令会导致cache line的invalid,因此,当系统中有其他人在使用exclusive访问时,需要小心。 </li></ul> |
|**ReadOnceMakelnvalid**|<ul><li>访问的是 snoopable 的地址空间;获取该地址的数据;</li><li>建议其他拥有该地址副本的 RN,其状态变成 invalid,但是不是强制的;</li><li>如果 dirty 的 cache line 被 invalid 了,则直接丢弃数据;</li><li>当 application 知道后续这个地址的数据不再使用,即不再需要该最新数据之后,可以发送该命令;</li><li>此种命令在上述场景下,减少了 writeback 数据到 DDR 的带宽和时间;</li><li> 此命令不能代替 CMO(Cache Maintenance Operation)操作,因为它不保证所有的 cache line 都变成了 invalid;</li><li>由于这个命令会导致 cache line 的 invalid,因此,当系统中有其他人在使用 exclusive 访问时,需要小心;</li><li>此命令必须保证,在返回响应之前,先将该 cache line invalid 掉,并且在这个时刻点之后的所有写,都不受此次 invalid 的影响。</li></ul>
</code> </pre> </details>



#### 4.2.1.2 **allocating read**
Expand All @@ -156,12 +168,55 @@ read类型的操作分为两类,non-allocating read 和allocating read
| MakeReadUnique |<ul> <li>访问 snoopable 的空间,想要获取该 cacheline 的 unique 状态;</li> <li>典型使用场景是当前 RN 有该 cacheline 的 shared copy,想要获得写该 cacheline 的权限;</li> <li>此命令分为 exclusive/非 exclusive 两种。</li> </ul> |
</code> </pre> </details>

### 4.2.2 Dataless transactions
有以下特性
</code> </pre> </details>

---

发送多少snoop:stach和fwd只能发往1个RN-F



## 附录 术语
[术语查询](https://blog.csdn.net/qq_40147893/article/details/136596743)
[术语查询](https://blog.csdn.net/qq_40147893/article/details/136596743)



- PoC:管理一致性,所有可以访问内存的agent都保证看到内存的相同位置的副本。在HN中需要
- PoS:管理多个memory请求的顺序,在HN中需要
- PoP:管理内存通断电情况下的一些操作
- Snoopee:接受snop的node,即RN-F
- 新术语 Requester(请求者)在旧文档中与 master(主设备)同义
- 新术语 Subordinate(从属设备)在旧文档中与 slave(从设备)同义
- cache HIT
- **Read through**,即直接从内存中读取数据;
- **Read allocate**,先把数据读取到Cache中,再从Cache中读数据。
- **Write-through**(直写模式)在更新数据时,同时写入Cache和内存。简言之,把数据同时写到Cache和内存中。
- **Write back**:数据首先写入缓存,而不是直接写入主存。当缓存行被替换时,才将数据写回主存。这种策略减少了主存的写操作次数,提高了性能。
- **cache-misses** :目标地址不在缓存中
- **Write allocate**:会先把该地址的数据块加载到缓存,然后再进行写操作,然后再通过flush方式写入到内存中;写缺失操作与读缺失操作类似。
- **write no-allocate**:并不将写入位置读入缓存,直接把要写的数据写入到内存中。这种方式下,只有读操作会被缓存。

>Write Allocate与Write Back经常一起使用,No Write Allocate与Write Through经常一起使用。
{: .prompt-tip}

- snoop filter:在总线中为设备维护标志位,来标识某些core中是否存在这个cacheline,不存在就不用发起snoop请求了
- TxnID:除了PrefetchTgt,这个ID指向唯一的Request,在收到完全响应或者Retry之后,可重用ID
- ReturnNID:SN返回数据响应, Persist响应或TagMatch响应的节点ID
- ReturnTxnID:SN返回数据响应, Persist响应或TagMatch响应的TxnlD
- Deep:置位后,写操作到达PoP和最终目的,才能提供Persist响应




- MESI协议,是一种叫作 写失效(Write Invalidate)的协议
- M:代表已修改(Modified),“脏”的Cache Block。
- E:代表独占(Exclusive)
- S:代表共享(Shared)
- I:代表已失效(Invalidated)
- MOESI协议引入了一个O(Owned)状态,并在MESI协议的基础上,进行了重新定义了S状态
对应CHI:M=UD、O=SD、E=UC、S=SC

1. O位为1表示在当前Cache 行中包含的数据是当前处理器系统最新的数据拷贝,而且在其他CPU中一定具有该Cache行的副本,其他CPU的Cache行状态为S。如果主存储器的数据在多个CPU的Cache中都具有副本时,有且仅有一个CPU的Cache行状态为O,其他CPU的Cache行状态只能为S,状态为O的Cache行中的数据与存储器中的数据并不一致。
2. S位。在MOESI协议中,S状态的定义发生了细微的变化。当一个Cache行状态为S时,<font color="#d99694">其包含的数据并不一定与存储器一致</font>。如果在其他CPU的Cache中不存在状态为O的副本时,该Cache行中的数据与存储器一致;如果在其他CPU的Cache中存在状态为O的副本时,Cache行中的数据与存储器不一致。
3. 处于E(UC)态,收到snoop请求,不需要返回数据给HN或者forward数据给RN。
4. 处于M(UD)态,收到snoop请求,需要返回数据给HN或者forward数据给RN。
149 changes: 149 additions & 0 deletions _posts/算法/2024-11-4-CRC.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
---
layout: post
title: CRC
date: 2024-11-4 11:29 +0800
categories: [项目学习, 算法]
tags: []
math: true
img_path: /assets/img/learn/
---

1. [CRC 冗余校验原理_异或计算法](https://www.bilibili.com/video/BV1Yp421R7D4/?spm_id_from=333.337.search-card.all.click&vd_source=aaf91522adc6826d87c67900ed8b01d9)
2. [refrence-CRC校验-手算与直观演示](https://www.bilibili.com/video/BV1V4411Z7VA/?spm_id_from=333.337.search-card.all.click&vd_source=aaf91522adc6826d87c67900ed8b01d9)

这俩计算好像不太一样,好像方案1更简单

---

```scala
package d2d.common

import chisel3._
import chisel3.util._
/**
* CRC Generation
* **this is because result is inverted,so 0=15 1=14 ...**
* Polynomial x16 + x12 + x5 + x0 (Visual represenation below) 1_0001_0000_0010_0001
*
* +------------------------+---------------------------------+
* | | |
* | v v
* -->x--+->15 14 13 12 11--->x--->10 9 8 7 6 5 4--->x---->3 2 1 0
* ^ |
* | |
* +-------------------------------------------------------------------------------+
*/

/**
* CRC Generation
* **below show u wher to place xor gate**
* Polynomial x16 + x12 + x5 + x0 (Visual represenation below) * 1_0001_0000_0010_0001 *
*
* +-------------------+---------------------------------+
* | | |
* | v v
* in(MSB)-->x--+->0 1 2 3 4--->x--->5 6 7 8 9 10 11--->x---->12 13 14 15
* ^ |
* | |
* +-----------------------------------------------------------------------------+
* x means xor gate
*/

class crcGen(val width: Int, val dummyImport: Boolean = false) extends Module{
val io = IO(new Bundle{
val in = Input (UInt(width.W))
val out= Output(UInt(16.W))
})

val numBytes = scala.math.ceil(width / 8.0).toInt

val totalBits = numBytes * 8
val paddedData = Wire(UInt(totalBits.W))
val extraZeros = Wire(UInt((totalBits-width).W))
extraZeros := 0.U
paddedData := Cat(extraZeros, io.in)


// This is going to be out XOR variables for each entry, 16 total
// What we plan to do is add in the XORing for each bit as a "shift" operation
var crcMap = scala.collection.mutable.Map[Int, scala.collection.mutable.ListBuffer[Int]]()
for (i <- 0 until 16){
crcMap(i) = scala.collection.mutable.ListBuffer[Int]()
// -1 will represent the initial SEED for this CRC, in this case the seed is 0xFFFF
// so when a -1 is seen in the map it's viewed as a 1'b1
crcMap(i) += -1
}

for(chunk16 <- 0 until numBytes){ //could probably just be a totalBits?
for (chunkbit <- 0 until 8){
val newCrcIn : scala.collection.mutable.ListBuffer[Int] = crcMap(0).clone += ((chunk16*8)+chunkbit) // crcMap(0) is going to xor with in((chunk16*8)+chunkbit)

// means i of 16 in the result is comnputed by xoring all components in crcMap(i)
for (i <- 0 until 16){
i match {
case 3 => crcMap(i) = newCrcIn ++ crcMap(i+1)
case 10 => crcMap(i) = newCrcIn ++ crcMap(i+1)
case 15 => crcMap(i) = newCrcIn
case _ => crcMap(i) = crcMap(i+1)
}

// Remove all of the XOR variables that have more than one instance, since something XOR'ed with itself is 0
crcMap(i) = crcMap(i).groupBy(x=>x).filter(_._2.lengthCompare(1) == 0).keySet.to(scala.collection.mutable.ListBuffer)
}
}
}

val crcCalc = Wire(Vec(16, Bool()))
// This is where we will create the XORing for each crc output bit
val xorList = Seq.tabulate(16){i => Wire(Vec(crcMap(i).size, Bool()))}

for(i <- 0 until 16){
var bindex = 0
crcMap(i).foreach{ j =>
if(j != -1) {
xorList(i)(bindex) := paddedData(j).asBool //io.in(j).asBool
} else {
xorList(i)(bindex) := true.B
}
bindex += 1
}
crcCalc(i) := xorList(i).reduce(_^_)
}
io.out := crcCalc.asUInt
}


object crcGen{
def apply[T <: Data](in: T): UInt = {
val crcgen = Module(new crcGen(in.getWidth))
crcgen.io.in := in
crcgen.io.out
}
}

```
{: file='*/crcGen.scala'}


---
这个是方案2
step1:根据多项式来获得CRC除数:

<font color="#d99694">$x^{6}+x^{4}+x^2+x+x^0$的CRC除数为:101_0111</font>

step2:将你要校验的数据串末尾添加`6`个0(最大项系数)

数据串1101011011_000000

step3:循环处理

![crc_calcu]({{ page.img_path }}crc_calcu.png){: width="972" height="589" }
![crc_step]({{ page.img_path }}crc_step.png){: width="972" height="589" }
![3]({{ page.img_path }}3.png){: width="972" height="589" }
![4]({{ page.img_path }}4.png){: width="972" height="589" }
![5]({{ page.img_path }}5.png){: width="972" height="589" }
![6]({{ page.img_path }}6.png){: width="972" height="589" }

最后得到的就是CRC校验和(长度为CRC除数-1)

![all]({{ page.img_path }}all.png){: width="972" height="589" }
Binary file added assets/img/learn/3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/learn/4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/learn/5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/learn/6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/learn/all.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/learn/crc_calcu.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/learn/crc_step.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 6613164

Please sign in to comment.