首页
游戏
影视
直播
广播
听书
音乐
图片
更多
看书
微视
主播
统计
友链
留言
关于
论坛
邮件
推荐
我的硬盘
我的搜索
我的记录
我的文件
我的图书
我的笔记
我的书签
我的微博
Search
1
在IC617中进行xa+vcs数模混仿
81 阅读
2
科普:Memory Compiler生成的Register file和SRAM有何区别?
73 阅读
3
virtuoso和empyrean alps模拟仿真和混仿教程
73 阅读
4
后仿中$setup,$hold与$setuphold
44 阅读
5
文档内容搜索哪家强? 15款文件搜索软件横向评测
35 阅读
默认分类
芯片市场
数字电路
芯片后端
模拟电路
芯片验证
原型与样片验证
算法与架构
DFX与量产封装
PC&Server OS设置
移动OS设置
软件方案
新浪备份
有道备份
登录
Search
标签搜索
python
Docker
vscode
linux
systemverilog
vcs
STM32
PyQT
EDA
FPGA
gvim
cadence
Alist
xilinx
UVM
uos
macos
package
MCU
risc-v
bennyhe
累计撰写
378
篇文章
累计收到
31
条评论
首页
栏目
默认分类
芯片市场
数字电路
芯片后端
模拟电路
芯片验证
原型与样片验证
算法与架构
DFX与量产封装
PC&Server OS设置
移动OS设置
软件方案
新浪备份
有道备份
页面
游戏
影视
直播
广播
听书
音乐
图片
看书
微视
主播
统计
友链
留言
关于
论坛
邮件
推荐
我的硬盘
我的搜索
我的记录
我的文件
我的图书
我的笔记
我的书签
我的微博
搜索到
40
篇与
的结果
2026-01-12
计算机体系架构——一文读懂Cache(一)
0 绪论最近需要开个新坑,讲讲计算机体系架构方面的东西。这方面应用最为广泛的是一个叫cache的东西。这方面内容图比较多,不想自己画了,所以图都来自《Computer Architecture : A Quantitative Approach》。这是一本体系架构方面的神书,推荐大家看一下。本文主要内容如下,基本涉及了cache的概念,工作原理,以及保持一致性的入门内容。1 为什么需要Cache1.1 为什么需要Cache我们首先从一张图来开始讲为什么需要cache.上图是CPU性能和Memory存储器访问性能的发展。我们可以看到,随着工艺和设计的演进,CPU计算性能其实发生了翻天覆地的变化,但是DRAM存储性能的发展没有那么快。所以造成了一个问题,存储限制了计算的发展。容量与速度不可兼得。如何解决这个问题呢?可以从计算访问数据的规律入手。我们随便贴段代码可以看到,由于大量循环的存在,我们访问的数据其实在内存中的位置是相近的。换句专业点的话说,我们访问的数据有局部性。我们只需要将这些数据放入一个小而快的存储中,这样就可以快速访问相关数据了。总结起来,Cache是为了给CPU提供高速存储访问,利用数据局部性而设计的小存储单元。1.2 实际系统中的Cache我们展示一下实际系统中的cache。如上图所示。整个系统的存储架构包括了CPU的寄存器,L1/L2/L3 CACHE,DRAM和硬盘。数据访问时先找寄存器,寄存器里没有找L1 Cache, L1 Cache里没有找L2 Cache依次类推,最后找到硬盘中。同时,我们可以看到,速度与存储容量的折衷关系。容量越小,访问速度越快!其中,一个概念需要搞清楚。CPU和Cache是word传输的,而Cache到主存是以块传输的。一块大约64Byte.现有SOC中的Cache一般组成如下。1.3 Cache的分类Cache按照不同标准分类可以分为若干类。按照数据类型划分:I-Cache与D-Cache。其中I-Cache负责放置指令,D-Cache负责方式数据。两者最大的不同是D-Cache里的数据可以写回,I-Cache是只读的。按照大小划分:分为small cache和large cache。没路组(后文组相连介绍)<4KB叫small cache, 多用于L1 Cache, 大于4KB叫large cache。多用于L2及其他cache.按照位置划分:Inner Cache和Outer Cache。一般独属于CPU微架构的叫Inner cache, 例如上图的L1 L2 CACHE。不属于CPU微架构的叫outer cache.按照数据关系划分:Inclusive/exclusive Cache: 下级Cache包含上级的数据叫inclusive cache。不包含叫exclusive cache。举个例子,L3 Cache里有L2 Cache的数据,则L2 Cache叫exclusive cache。2 Cache的工作原理要讲清楚Cache的工作原理,需要回答4个问题:数据如何放置数据如何查询数据如何被替换如果发生了写操作,cache如何处理2.1 数据如何放置这个问题也好解决。我们举个简单的栗子来说明问题。假设我们主存中有32个块,而我们的cache一共有8个cache行( 一个cache行放一行数据)。假设我们要把主存中的块12放到cache里。那么应该放到cache里什么位置呢?三种方法:全相连(Fully associative)。可以放在cache的任何位置。直接映射(Direct mapped)。只允许放在cache的某一行。比如12 mod 8组相连(set associative)。可以放在cache的某几行。例如2路组相连,一共有4组,所以可以放在0,1位置中的一个。可以看到,全相连和直接映射是Cache组相连的两种极端情况。不同的放置方式主要影响有两点:组相连组数越大,比较电路就越大,但Cache利用率更高,cache miss发生的概率小。组相连数目变小,cache经常发生替换,但是比较电路比较小。这也好理解,内存中的块在cache中可放置的位置多,自然找起来就麻烦。2.2 如何在Cache中找数据其实找数据就是一个比对过程。如下图所示。我们地址都以Byte为单位的。但主存于cache之间的数据交换单位都是块(block,现代cache一般一个block大约64Byte)。所以地址对最后几位是block offset。由于我们采用了组相连,则还有几个比特代表的是存储到了哪个组。组内放着若干数据。我们需要比较Tag, 如果组内有Tag出现,则说明我们访问的数据在缓存中,可以开心的使用了。比如举个2路组相连的例子。如下图所示。T表示Tag。直接比较Tag,就能得知是不是命中了。如果命中了,则根据index(组号)将对应的块取出来即可。如上图所示。用index选出位于组相连的哪个组。然后并行的比较Tag, 判断最后是不是在cache中。上图是2路组相连,也就是说两组并行比较。那如果不在缓存中呢?这就涉及到另一个问题。不在缓存中如何替换cache?2.3 如何替换Cache中的数据cache中的数据如何被替换的?这个就比较简单直接。随机替换。如果发生cache miss里随机替换掉一块。Least recently used. LRU。最近使用的块最后替换。First in, first out (FIFO), 先进先出。实际上第一个不怎么使用,LRU和FIFO根据实际情况选择即可。cache在什么时候数据会被替换内?也有几种策略。不在本cache替换。如果cache miss了,直接转发访问地址到主存,取到的数据不会写到cache.在读MISS时替换。如果读的时候cache里没有该数据,则从主存读取该数据后写入cache。在写MISS时替换。如果写的时候cache里没有该数据,则将本数据调入cache再写。2.4 如果发生了写操作怎么办Cache毕竟是个临时缓存。如果发生了写操作,会造成cache和主存中的数据不一致。如何保证写数据操作正确呢?也有三种策略。通写:直接把数据写回cache的同时写回主存。极其影响写速度。回写:先把数据写回cache, 然后当cache的数据被替换时再写回主存。通写队列:通写与回写的结合。先写回一个队列,然后慢慢往主存储写。如果多次写同一个数据,直接写这个队列。避免频繁写主存。3 Cache一致性Cache一致性是Cache中遇到的比较坑的一个问题。什么原因需要cache处理一致性呢?主要是多核系统中,假如core 0读了主存储的数据,写了数据。core 1也读了主从的数据。这个时候core 1并不知道数据已经被改动了,也就是说,core 1 cache中的数据过时了,会产生错误。Cache一致性的保证就是让多核访问不出错。Cache一致性主要有两种策略。策略一:基于监听的一致性策略这种策略是所有cache均监听各cache的写操作,如果一个cache中的数据被写了,有两种处理办法。写更新协议:某个cache发生写了,就索性把所有cache都给更新了。写失效协议:某个cache发生写了,就把其他cache中的该数据块置为无效。策略1由于监听起来成本比较大,所以只应用于极简单的系统中。策略二:基于目录的一致性策略这种策略是在主存处维护一张表。记录各数据块都被写到了哪些cache, 从而更新相应的状态。一般来讲这种策略采用的比较多。又分为下面几个常用的策略。SI: 对于一个数据块来讲,有share和invalid两种状态。如果是share状态,直接通知其他cache, 将对应的块置为无效。MSI:对于一个数据块来讲,有share和invalid,modified三种状态。其中modified状态表表示该数据只属于这个cache, 被修改过了。当这个数据被逐出cache时更新主存。这么做的好处是避免了大量的主从写入。同时,如果是invalid时写该数据,就要保证其他所有cache里该数据的标志位不为M,负责要先写回主存储。MESI:对于一个数据来讲,有4个状态。modified, invalid, shared, exclusive。其中exclusive状态用于标识该数据与其他cache不依赖。要写的时候直接将该cache状态改成M即可。我们着重讲讲MESI。图中黑线:CPU的访问。红线:总线的访问,其他cache的访问。当前状态时I状态时,如果发生处理器读操作prrd如果其他cache里有这份数据,如果其他cache里是M态,先 把M态写回主存再读。否则直接读。最终状态变为S。其他cache里没这个数据,直接变到E状态。当前状态为S态如果发生了处理器读操作,仍然在S态。如果发生了处理器写操作,则跳转到M状态。如果其他cache发生了写操作,跳到I态。当前状态E态发生了处理器读操作还是E。发生了处理器写操作变成M。如果其他cache发生了读操作,变到S状态。当前状态M态发生了读操作依旧是M态。发生了写操作依旧是M态。如果其他cache发生了读操作,则将数据写回主存储,变换到S态。4 总结cache在计算机体系架构中有非常重要的地位。本文讲了cache中最主要的内容。具体细节可以再根据某个点深入研究。https://zhuanlan.zhihu.com/p/386919471
2026年01月12日
3 阅读
0 评论
0 点赞
2026-01-12
GitHub上Star量最高的5个机器学习项目
本文介绍了 GitHub 上 star 量最高的 5 个机器学习项目,涉及人脸识别、文本处理、机器学习框架等。选自towardsdatascience,作者:Rishi Sidhu,机器之心编译参与:Nurhachu Null、Geek AI。机器学习领域正在飞速发展。GitHub 是一张举世瞩目的白板,高质量的代码通常被发布在这张充满智慧的无限大白板上。显然,我们不可能追踪机器学习世界中的所有东西,但是 GitHub 上每个项目都具备自己的 star 量。即,如果你标星了一个仓库,这意味着你对这个项目表达了赞赏,同时也跟踪了你觉得有意思的仓库。星数排名可作为了解最受关注项目的重要指标。本文就介绍了机器学习领域星数排名最高的 5 个项目。Face Recognition:26073★GitHub 地址:https://github.com/ageitgey/face_recognition?source=post_page---------------------------这是世界上最简洁的人脸识别工具。它提供对 Python 和命令行的应用程序接口(API),其用途是识别以及操作图像中的人脸。它使用 Dlib 最先进的人脸识别算法构建,该深度学习模型在 LFW(Labeled Faces in the Wild)数据集上达到了 99.38% 的准确率。它还提供了 face_recognition 命令行工具,它可以让你在包含图像的文件夹中使用命令行来进行人脸识别!这个库还可以处理实时人脸识别。动图封面fastText:18931 ★GitHub 地址:https://github.com/facebookresearch/fastText?source=post_page---------------------------fastText 是由 Facebook 团队开发的免费开源库,用于高效词表征学习。它是轻量级的,允许用户学习文本表征和句子分类器。它可以在标准通用硬件上运行,模型甚至可以被压缩到适应移动设备的大小。文本分类是很多应用的核心问题,例如垃圾邮件检测、情感分析或智能回复。文本分类的目标是给文档(例如电子邮件、博客、短信、产品评论等)分配多个类别。词类示例(图源:Alterra.ai)对自然语言处理(NLP)爱好者而言,这是一款非常有用的工具。图源:https://fasttext.cc/?source=post_pag (https://fasttext.cc/?source=post_pag%EF%BC%89)Awesome TensorFlow:14501★GitHub 地址:https://github.com/jtoy/awesome-tensorflow这是一个帮你理解和使用 TensorFlow 的资源集合。该 repo 涵盖一系列资源列表,如很棒的 TensorFlow 实验、库和项目。TensorFlow 是 Google 开发的端到端开源机器学习平台。它有全面的生态系统,包括工具、库和社区资源,允许研究者创建最先进的机器学习算法。使用 TensorFlow,开发者可以很容易地构建并部署由机器学习驱动的应用。图源:https://www.tensorflow.org/tutorials/keras/basic_classification?source=post_pageApache predictionio 11866 ★GitHub 地址:https://github.com/apache/predictionioApache PredictionIO 是供开发者、数据科学家和终端用户使用的开源机器学习框架。用户可使用该框架构建真实的机器学习应用,并进行部署和测试。它甚至支持事件收集、评估,以及查询预测结果。它基于可扩展的开源服务,如 Hadoop、HBase 等。就机器学习而言,该工具减轻了开发人员的思维负担。图源:http://predictionio.apache.org/appintegration/?source=post_pageStyle2Paints:9860 ★GitHub 地址:https://github.com/lllyasviel/style2paints该 repo 与前面 4 个有点不一样,因为缺乏资金,它已经被关闭了!它确实是一个有趣的设想,使用 AI 给图像上色。创建者称 Style2paints V4 是当前最好的 AI 线稿上色工具。他们称这个项目与之前的端到端图像转换方法不同,因为它是第一个用真实的人类作业流程为线稿上色的系统。很多艺术家熟悉这个流程。素描-->彩色填充/扁平化-->渐变/细节添加-->阴影处理Style2Paints就是根据这个流程设计的。只用两次点击,该流程就可以使下图中最左的图变成中间的图。图源:https://style2paints.github.io/?source=post_page仅仅点击 4 次,你就能够得到下面这张图:图源:https://github.com/lllyasviel/style2paints?source=post_page原文链接:https://towardsdatascience.com/
2026年01月12日
3 阅读
0 评论
0 点赞
2026-01-12
CPU 的工作原理是什么?
想了解CPU的工作原理莫过于从头开始用最基础的元素打造一个简单CPU。接下来我会从最简单的晶体管开始一步步讲解CPU是如何构造出来的,明白了这个过程理解 CPU 的工作原理不在话下,在此之后我会从最基础的二进制机器指令一步步讲解高级语言的基本原理,通读本文后你将彻底明白CPU与高级语言的工作原理。以下内容出自我的两篇文章《你管这破玩意叫CPU?》《你管这破玩意叫编程语言?》。次回家开灯时你有没有想过,用你按的简单开关实际上能打造出复杂的 CPU 来,只不过需要的数量会比较多,也就几十亿个吧。伟大的发明过去200年人类最重要的发明是什么?蒸汽机?电灯?火箭?这些可能都不是,最重要的也许是这个小东西:这个小东西就叫晶体管,你可能会问,晶体管有什么用呢?实际上晶体管的功能简单到不能再简单,给一端通上电,那么电流可以从另外两端通过,否则不能通过,其本质就是一个开关。就是这个小东西的发明让三个人获得了诺贝尔物理学奖,可见其举足轻重的地位。无论程序员编写的程序多么复杂,软件承载的功能最终都是通过这个小东西简单的开闭完成的,除了神奇二字,我想不出其它词来。AND、OR、NOT现在有了晶体管,也就是开关,在此基础之上就可以搭积木了,你随手搭建出来这样三种组合:两个开关只有同时打开电流才会通过,灯才会亮两个开关中只要有一个打开电流就能通过,灯就会亮当开关关闭时电流通过灯会亮,打开开关灯反而电流不能通过灯会灭天赋异禀的你搭建的上述组合分别就是:与门,AND Gate、或门,OR gate、非门,NOT gate,用符号表示就是这样:道生一、一生二、二生三、三生万物最神奇的是,你随手搭建的三种电路竟然有一种很amazing的特性,那就是:任何一个逻辑函数最终都可以通过AND、OR以及NOT表达出来,这就是所谓的逻辑完备性,就是这么神奇。也就是说给定足够的AND、OR以及NOT门,就可以实现任何一个逻辑函数,除此之外我们不需要任何其它类型的逻辑门电路,这时我们认为{AND、OR、NOT}就是逻辑完备的。这一结论的得出吹响了计算机革命的号角,这个结论告诉我们计算机最终可以通过简单的{AND、OR、NOT}门构造出来,就好比基因。计算能力是怎么来的现在能生成万物的基础元素与或非门出现了,接下来我们着手设计CPU 最重要的能力:计算,以加法为例。由于CPU只认知 0 和 1,也就是二进制,那么二进制的加法有哪些组合呢:0 + 0,结果为0,进位为00 + 1,结果为1,进位为01 + 0,结果为1,进位为01 + 1,结果为0,进位为1,二进制嘛!注意进位一列,只有当两路输入的值都是 1 时,进位才是 1 ,看一下你设计的三种组合电路,这就是与门啊,有没有!再看下结果一列,当两路输入的值不同时结果为1,输入结果相同时结果为0,这就是异或啊,有没有!我们说过与或非门是逻辑完备可以生万物,异或逻辑当然不在话下,用一个与门和一个异或门就可以实现二进制加法:上述电路就是一个简单的加法器,就问你神奇不神奇,加法可以用与或非门实现,其它的也一样能实现,逻辑完备嘛。除了加法,我们也可以根据需要将不同的算数运算设计出来,负责计算的电路有一个统称,这就是所谓的arithmetic/logic unit,ALU,CPU 中专门负责运算的模块,本质上和上面的简单电路没什么区别,就是更加复杂而已。现在,通过与或非门的组合我们获得了计算能力,计算能力就是这么来的。但,只有计算能力是不够的,电路需要能记得住信息。神奇的记忆能力到目前为止,你设计的组合电路比如加法器天生是没有办法存储信息的,它们只是简单的根据输入得出输出,但输入输出总的有个地方能够保存起来,这就是需要电路能保存信息。电路怎么能保存信息呢?你不知道该怎么设计,这个问题解决不了你寝食难安,吃饭时在思考、走路时在思考,蹲坑时在思考,直到有一天你在梦中遇一位英国物理学家,他给了你这样一个简单但极其神奇的电路:这是两个NAND门的组合,不要紧张,NAND也是有你设计的与或非门组合而成的,所谓NAND门就是与非门,先与然后取非,比如给定输入1和0,那么与运算后为0,非运算后为1,这就是与非门,这些不重要。比较独特的是该电路的组合方式,一个NAND门的输出是两一个NAND门的输入,该电路的组合方式会自带一种很有趣的特性,只要给S和R段输入1,那么这个电路只会有两种状态:要么a端为1,此时B=0、A=1、b=0;要么a端为0,此时B=1、A=0、b=1;不会再有其他可能了,我们把a端的值作为电路的输出。此后,你把S端置为0的话(R保持为1),那么电路的输出也就是a端永远为1,这时就可以说我们把1存到电路中了;而如果你把R段置为0的话(S保持为1),那么此时电路的输出也就是a端永远为0,此时我们可以说把0存到电路中了。就问你神奇不神奇,电路竟然具备存储信息的能力了。现在为保存信息你需要同时设置S端和R端,但你的输入是有一个(存储一个bit位嘛),为此你对电路进行了简单的改造:这样,当D为0时,整个电路保存的就是0,否则就是1。寄存器与内存的诞生现在你的电路能存储一个比特位了,想存储多个比特位还不简单,复制粘贴就可以了:我们管这个组合电路就叫寄存器,你没有看错,我们常说的寄存器就是这个东西。你不满足,还要继续搭建更加复杂的电路以存储更多信息,同时提供寻址功能,就这样内存也诞生了。寄存器及内存都离不开上一节那个简单电路,只要通电,这个电路中就保存信息,但是断电后很显然保存的信息就丢掉了,现在你应该明白为什么内存在断电后就不能保存数据了吧。硬件的基本功让我们来思考一个问题,CPU怎么能知道自己要去对两个数进行加法计算,以及哪两个数进行加法计算呢?很显然,你得告诉CPU,该怎么告诉呢?还记得上一节中给厨师的菜谱吗?没错,CPU也需要一张菜谱告诉自己该接下来该干啥,在这里菜谱就是机器指令,指令通过我们上述实现的组合电路来执行。接下来我们面临另一个问题,那就是这样的指令应该会很多吧,废话,还是以加法指令为例,你可以让CPU计算1+1,也可以计算1+2等等,实际上单单加法指令就可以有无数种组合,显然CPU不可能去实现所有的指令。实际上CPU只需要提供加法操作,你提供操作数就可以了,CPU 说:“我可以打人”,你告诉CPU该打谁、CPU 说:“我可以唱歌”,你告诉CPU唱什么,CPU 说我可以做饭,你告诉CPU该做什么饭,CPU 说:“我可以炒股”,你告诉CPU快滚一边去吧韭菜。因此我们可以看到CPU只提供机制或者说功能(打人、唱歌、炒菜,加法、减法、跳转),我们提供策略(打谁、歌名、菜名,操作数,跳转地址)。CPU 表达机制就通过指令集来实现的。指令集指令集告诉我们 CPU 可以执行什么指令,每种指令需要提供什么样的操作数。不同类型的CPU会有不同的指令集。指令集中的指令其实都非常简单,画风大体上是这样的:从内存中读一个数,地址是abc对两个数加和检查一个数是不是大于6把这数存储到内存,地址是abc等等看上去很像碎碎念有没有,这就是机器指令,我们用高级语言编写的程序,比如对一个数组进行排序,最终都会等价转换为上面的碎碎念指令,然后 CPU 一条一条的去执行,很神奇有没有。接下来我们看一条可能的机器指令:这条指令占据16比特,其中前四个比特告诉CPU这是加法指令,这意味着该CPU的指令集中可以包含2^4也就是16个机器指令,这四个比特位告诉CPU该做什么,剩下的bit告诉CPU该怎么做,也就是把寄存器R6和寄存器R2中的值相加然后写到寄存器R6中。可以看到,机器指令是非常繁琐的,现代程序员都使用高级语言来编写程序,关于高级程序语言以及机器指令的话题请参见《你管这破玩意叫编程语言?》。大功告成现在我们有了可以完成各种计算的ALU、可以存储信息的寄存器以及控制它们协同工作的时钟信号,这些统称 Central Processing Unit,简称就是 CPU。接下来我们看一下CPU 与高级语言。程序员按照 CPU 的旨意直接用0和1编写指令,你没有看错,这破玩意就是代码了,就是这么原生态,然后放到打孔纸带上输入给CPU,CPU 开始工作,这时的程序可真的是看得见摸得着,就是有点浪费纸。这时程序员必须站在 CPU 的角度来写代码,画风是这样的:1101101010011010100100110010100111001000110111101011101101010010终于有一天程序员受够了说鸟语,好歹也是灵长类,叽叽喳喳说鸟语太没面子,你被委以重任:让程序员说人话。你没有苦其心志劳其筋骨,而是仔细研究了一下 CPU,发现 CPU 执行的指令集来来回回就那么几个指令,比如加法指令、跳转指令等等,因此你把机器指令和对应的具体操作做了一个简单的映射,把机器指令映射到人类能看懂的单词,这样上面的01串就变成了:sub $8, %rsp mov $.LC0, %edi call puts mov $0, %eax这样,程序员不必生硬的记住1011.....,而是记住人类可以认识的ADD SUB MUL DIV等这样的单词即可。汇编语言就这样诞生了,编程语言中首次出现了人类可以认识的东西细节 VS 抽象尽管汇编语言已经有人类可以认识的单词,但汇编语言和机器语言一样都属于低级语言。所谓低级语言是说你需要关心所有细节。关心什么细节呢?我们说过,CPU 是非常原始的东西,只知道把数据从一个地方搬到另一个地方,简单的操作一下再从一个地方搬到另一地方。因此,如果你想用低级语言来编程的话,你需要使用多个“把数据从一个地方搬到另一个地方,简单的操作一下再从一个地方搬到另一地方”这样的简单指令来实现诸如排序这样复杂的问题。有的同学可能对此感触不深,这就好比,本来你想表达“去给我端杯水过来”:如果你用汇编这种低级语言就得这样实现:我想你已经 Get 到了。弥补差异CPU 实在太简单了,简单到不能了理解任何稍微抽象一点诸如“给我端杯水”这样的东西,但人类天生习惯抽象化的表达,人类和机器的差距有办法来弥补吗?换句话说就是有没有一种办法可以自动把人类抽象的表达转为 CPU 可以理解的具体实现,这显然可以极大增强程序员的生产力,现在,这个问题需要你来解决。电光火石之间灵光乍现,你发现了满满的套路,或者说模式。大部分情况下 CPU 执行的指令平铺直叙的,就像这样:这些都是告诉 CPU 完成某个特定动作,你给这些平铺直叙的指令起了个名字,姑且就叫陈述句吧,statement。除此之外,你还发现了这样的套路,那就是需要根据某种特定状态决定走哪段指令,这个套路在人看来就是“如果。。。就。。。否则。。就。。。”:if * blablabla else * blablabla在某些情况下还需要不断重复一些指令,这个套路看起来就是原地打转:while * blablabla最后就是这里有很多看起来差不多的指令,就像这里:这些指令是重复的,只是个别细节有所差异,把这些差异提取出来,剩下的指令打包到一起,用一个代号来指定这些指令就好了,这要有个名字,就叫函数吧:func abc: blablabla现在你发现了所有套路:// 条件转移 if * blablablaelse * blablabla// 循环 while * blablabla// 函数 func abc: blablabla这些相比汇编语言已经有了质的飞跃,因为这已经和人类的语言非常接近了。接下来你发现自己面临两个问题:这里的blablabla该是什么呢?该怎样把上面的人类可以认识的字符串转换为 CPU 可以认识的机器指令递归:代码的本质不就是嵌套嘛,一层套一层嘛,递归天生就是来表达这玩意的 (提示:这里的表达并不完备,真实的编程语言不会这么简单,这里仅仅用作示例):if : if bool statement else statements for: while bool statements statement: if | for | statement让计算机理解递归现在还差一个问题,怎样才能把这语言最终转化为 CPU 可以认识的机器指令呢?人类可以按照语法写出代码,这些代码其实就是一串字符,怎么让计算机也能认识用递归语法表达的一串字符呢?这是一项事关人类命运的事情,你不禁感到责任重大,但这最后一步又看似困难重重,你不禁仰天长叹,计算机可太难了。此时你的初中老师过来拍了拍你的肩膀,递给了你一本初中植物学课本,你恼羞成怒,给我这破玩意干什么,我现在想的问题这么高深,岂是一本破初中教科书能解决的了的,抓过来一把扔在了地上。此时又一阵妖风挂过,书被翻到了介绍树的一章,你望着这一页不禁发起呆来:我们可以把根据递归语法写出来的的代码用树来表示啊!优秀的翻译官计算机处理编程语言时可以按照递归定义把代码用树的形式组织起来,由于这棵树是按照语法生成的,姑且就叫语法树吧。现在代码被表示成了树的形式,你仔细观察后发现,其实叶子节点的表达是非常简单的,可以很简单的翻译成对应的机器指令,只要叶子节点翻译成了机器指令,你就可以把此结果应用到叶子节点的父节点,父节点又可以把翻译结果引用到父节点的父节点,一层层向上传递,最终整颗树都可以翻译成具体的机器指令。完成这个工作的程序也要有个名字,根据“弄不懂原则”(该原则的解释见下文 :)总结本文我们从最基本的晶体管一路讲解到CPU的工作原理,再从最低级的二进制机器指令到高级语言,相信如果你能读到这里定能有所收获。最后,有同学问有没有书单,我也仔细回想自己认真读过的计算机数据,在这里也给出自认为很经典的几本,书单这东西贵精不贵多,我在这里精心挑选了10本 ,不要贪心,如果你真能把这里推荐的 10 本书读通,可以说你已经能超越 90% 的程序员了。
2026年01月12日
3 阅读
0 评论
0 点赞
2026-01-08
CPU 系统级验证 —— 指令集验证 ——OpenHW core-v 验证环境及文件分析
本文记录的相关源工程和文件为:core-v RISCV 核功能验证工程:https://github.com/openhwgroup/core-v-verifcore-v 验证策略:https://core-v-docs-verif-strat.readthedocs.io/en/latest/#core-v 系列核 cva6 工程:https://github.com/openhwgroup/cva6core-v 系列核 cv32e40p 工程:https://github.com/openhwgroup/cv32e40pLowRISCV Ibex 核工程:https://github.com/lowRISC/ibexcore-v RISCV 核相关说明文档:https://github.com/openhwgroup/core-v-docsRISCV ISA 指令流(instruction stream)生成器:https://github.com/openhwgroup/force-riscvcore-v 系列指令流(instruction stream)生成器:https://github.com/openhwgroup/core-v-isgsail 语言介绍:https://www.cl.cam.ac.uk/~pes20/sail/REMS 的 sail RISCV 开源项目:https://github.com/rems-project/sail-riscvopenHW 全称为 open-source hardware,是一个支持开源软件和硬件的非盈利组织。该组织开源的内容包括开源 CPU 核、相关 IP、工具和软件等。指令集验证指令集验证的需求能够使用操作数产生合法的基本整数运算指令在指令执行完成后能够检查通用寄存器的状态指令执行完成后能检查副效应,例如溢出等。指令集验证内容指令集的验证需要验证工程师思考该指令需要测试的特征是什么,为了确保指令的正确执行需要检查的内容是什么,为了确保该特征被测试需要进行哪些激励和配置等。验证的充不充分取决于验证人员对 CPU 微架构的理解和风险应对能力。(1)RISCV 基本指令定向测试设计出来的 CPU 首先需要兼容 RISCV 基本指令,即需要满足 RISCV 基本整数指令及相关标准指令集。主要测试的内容有:溢出检测及相关标志位下溢检测及相关标志位无指令执行的副效应,比如异常的通用处理寄存器变化,异常的条件代码使用 x0-x31 作为 rs1/rs2使用 x0-x31 作为 rdx0 寄存器的值始终为 0set/clear 所有立即数的比特位set/clear 源寄存器 rs1/rs2 的比特位根据 7/8 两条 set/clear 目的寄存器 rd 的比特位(2)自定义扩展指令定向测试对于自定义扩展指令集的验证,该验证需要修改相关的工具链并通过相关测试验证工具链的修改成功,再进行(1)中的测试。(3)随机约束测试对进行大量的随机指令测试指令集验证激励的种类指令集测试激励分为自检(self-checking)和预存(pre-existing)两种。自检测试激励运行时按照源文件中指令顺序依次,并同时将指令执行结果和参考值作检查,若出错则程序跳转到 fail,打断正常执行顺序,立即执行完成。类似的测试集有 riscv-tests、riscv-compilance-tests 等预存测试激励运行时不会打断执行顺序,执行的结果会和指令集模拟器(ISS)的结果作对比,最终统计对比的结果。类似的测试集有 riscv-dv 等指令集验证 pass/fail 的标志测试的 pass/fail 与上述激励的种类有关self checking:自检性质的测试激励在每条指令执行时就会同时将结果和参考值作对比,若失败则跳转到 failsignature check:特征检查,相对自检来说更加复杂深入。测试的结果将被用来计算该指令的某个特征,这将会和预先确定好的较标准特征作对比。采用该检查的为 riscv-complience-tests。check against ISS:与指令集模拟器对比检查。该情况下,testcase 并不知道测试的参考值,仅仅给 DUT 提供激励,testbench 会对比 DUT 和 ISS 的输出结果确定测试的 pass/fail。该检查较被经常使用,因为它是的 testcase 更加简单。采用该检查的如 riscv-dvcheck against RM:与参考模型对比检查,该检查方式与第三点类似,但相对 ISS 更加通用。通常用作 ISS 检测的补充。assertion check:通过断言判断是否执行出错。相关 CPU 核的验证工程cv32e40pCV32E40P (原先 PULP 开发的 RI5CY) 是一个 32bit 的 4 级流水线核,支持整数运算指令、乘法除法指令、单浮点运算指令、压缩指令以及 DSP 扩展指令(包括硬件循环、SIMD 扩展、位操作和增量指令)该核的验证环境有两套,一套是专门的 core testbench;一套是 UVM 环境搭建的 testbench,该环境下 testcase 的产生是可以基于 UVM 环境的(这种方式类似于 Ibex 核验证环境)。两套环境均由 systemverilog 编写。均包含了指令集验证、中断验证、CSR 寄存器验证、异常验证、debug 验证等。1 core testbench该工程是 PULP 遗留下的产物,OpenHW 做了一定修改并持续维护。验证环境中已集成了指令集模拟器。该工程的测试集激励包含指令兼容性测试(偏定向测试,如 riscv-tests 和 riscv-compilance-tests)和随机约束(google riscv-dv),和其他的一些 fireware 测试用例。测试环境结构如下:该 testbench 简单,运行较快,通过 verilator 运行,但是有额外的开销且不能获取覆盖率。2 UVM 验证环境(uvmt_cv32)cv32 核的 UVM 验证环境已搭建完成,在 DSIM(Metrics)运行也很稳定。验证环境中已集成了指令集模拟器。uvm 验证环境的 testcase 均是由 uvm 相关类生成,同时该环境还集成了 riscv-dv,但具体的激励生成还需要再分析。具体验证环境结构UVM 内部组件关系debug、interrupt、control/status 均通过 UVM_agent 组件产生,且通过 uvm_sequence 组件输入激励。UVM 运行流程采用 UVM 搭环境的优势a) 便于验证环境的结构建模b) UVM 环境类支持完全的 UVM 运行流程和 log 服务c) 使用 UVM sequence-item 类可以产生随即约束激励d) 使用内建于验证环境中的参考模型预测执行的结果。(imperas 有现成的开源 ISS)e) scoreboard 可以比较参考模型和 RTL 的结果。f) 功能覆盖率和代码覆盖率确保验证的完全性。且 UVM 测试环境可复用性较高,也可以用在 CVA6 核上。CVA6CVA6(ariane) 是一个 6 级流水线、单发射、顺序执行的 RV32GC 或 RV64GC 核,支持 M/U/S 三种模式,支持 linux 操作系统。该核现存的验证环境尚未成熟,但同样可以构建 UVM 的验证环境。该工程的指令集测试激励包括 riscv 官方测试套件(即 riscv-tests)。IbexIbex 不是 openHW 的 core-v 系列,而是 lowRISC 持续维护的较为成熟的一款核,验证环境也较为成熟,其结构和运行非常类似于 CV32E 和 CVA6 的激励随机约束。该验证环境激励的产生同样是基于 GOOGLE 的随机指令生成器验证环境特征运行有效性testcase 在验证环境中会持续运行完成,除非激励运行出错方便调试能够增加功能覆盖率能够对比检查 RTL 运行的结果指令集描述语言 ——sailsail 是 REMS 构建的一种描述指令集的语言,可以认为是一种机器可读的形式化 ISA 模型。REMS 是英国的一家学术组织,该组织已构建出 RV32IMAC 和 RV64IMAC 指令集的 sail model,链接见上。riscv 基金会有意用其来描述 RISCV 指令集。初步来看,sail 可以用来形式化 testbench 断言的参考模型,这些 assertion 可以根据 sail spec 来验证基于 RISCV ISA 的某微架构。目前该领域 OneSpin GapFree 已经在 sail model 和 RTL 代码间做了可比性的 check,该公司仍在探索如何充分使用 sail model该语言将持续关注。
2026年01月08日
2 阅读
0 评论
0 点赞
2026-01-07
推荐一款好用的IC设计中生成register model的工具
无意中发现一个开源的工具,使用systemRDL文件作为输入,可以生成寄存器相关的RTL module,UVM中使用的regmodel,C和verilog的头文件(包含寄存器某个字段的偏移以及mask bits),以及html的文档。资源如下:https://github.com/zhajio1988/Open_RegModel生成的html文档示例如下:https://systemrdl.github.io/RALBot-html————————————————版权声明:本文为CSDN博主「XtremeDV」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/zhajio/article/details/102620859开源uvm reg model (UVM 寄存器模型)生成工具open-register-design-toolOrdt is a tool for automation of IC register definition and documentation. It currently supports 2 input formats:SystemRDL - a stardard register description format released by Accellera.orgJSpec - a register description format used within Juniper NetworksThe tool can generate several outputs from SystemRDL or JSpec, including:SystemVerilog/Verilog RTL code description of registersUVM model of the registersC++ models of the registersXML and text file register descriptionsSystemRDL and JSpec (conversion)Easiest way to get started with ordt is to download a runnable jar from the release area.Ordt documentation can be found here.注:nvdla中使用SystemRDL格式描述寄存器模型,并使用jar xxx ordt.jar ......生成uvm reg model————————————————版权声明:本文为CSDN博主「XtremeDV」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/zhajio/article/details/82870523
2026年01月07日
2 阅读
0 评论
0 点赞
1
2
...
8