从Verilog设计到AI芯片架构:微观与宏观的设计理念框架共通

一、Verilog的设计思维

想要使用一种代码语言做开发,只知道编程语言的语法是没有意义的,工具只是表面,背后的设计思维才是关键。初学者经过一定的学习,可能可以很快地对Verilog设计的基本方式有一些了解,比如通过状态机来控制模块整体的工作过程等,然而,这通常只是一种粗略的感知,以至于在面对真正复杂的代码时可能还是感觉不太能理解过来,这时候就是实战层面的事情了——看不懂是因为不理解某些内容的意图,或者不了解芯片设计中常见的单元与方法。实际上,想要提高对Verilog的理解能力,我们得在设计思维上做一点提炼吗,以便更清楚地知道在设计电路时该从哪开始思考、如何用明确的方法实现需求。

想要有条理地设计或理解代码,我认为关键是分清数字设计的2大基本方面:数据通路控制通路。数据通路搭载的是电路中说到底想要传递的那些“有实质意义”的信号,比如卷积模块的最终目的是做卷积计算,这个计算说到底是由模块对输入特征、权重/偏置参数、输出特征的流动做出具体的引导来实现的。数据通路代表着数字设计中具象的思维,其搭载的数据流是设计者具体地想象好的,所有需要参与运算的数据按照设想好的方式流转,比如脉动阵列里的权重稳定(WS)和输出稳定(OS)数据流,就是通过特定的数据调度方式来实现不同类型的复用吗。具体地说,数据通路中数据信号的走向和轨迹会反映到比如流水线的结构、哪些东西并行、哪些东西串行、计算电路的规模(乘法器具体几个等)、多路数据之间的相互配合等。而控制通路搭载的是为了实现电路中不同组件的协同工作所必须存在的那些起控制作用的信号,比如状态机、握手信号(ready/valid)、各种使能信号、标识某个过程起止的start/end信号、标识某个核心或特殊的情况发生的flag信号等等。控制通路偏向于抽象思维,它们常常很难用单一的具象时序图或者其他直白的形式所概括,比如在握手过程当中,你不知道现实中模块外部的ready或valid会在什么时候有效,严格来说你只能将握手这件事总结成一套确切的条件并直接转化为逻辑电路(只不过我们可以通过各种假设的时序图来辅助理解)。控制流伴随着数据流一起在电路中传递,从而保证不同组件之间能够正确地完成信息的交互并各自实现自己的功能。

在实际设计中,数据通路和控制通路是相互交织的。数据通路虽然具象,但是往往比较宏观,而微观的细节与控制通路紧密联系。比如你可能可以把一个模块的运转过程划分为多个阶段,设定好每路数据的流转方式,但是一方面,具体每个阶段会花多少时钟周期来完成是不一定的,这可能要看比如外部输入过来的源数据是每隔多久才会valid一波,或者不同阶段之间有没有处理难度、数据量等方面的差异,另一方面,各路数据的流转方式复杂了以后,模块内部的控制往往也更复杂(比如可能会引入仲裁等过程),从而导致了时序上的不确定性。因此,具象的数据通路主管整体性的模块结构和数据走向,抽象的控制通路则主管底层的交互细节。有趣的是,数据通路的具象需求会让一些控制信号也变得具象,比如尽管你无法预测某个计数器在真实工作时的计数过程是否是均匀变动的、如是不均匀则具体是怎样的不均匀,但你可以明确地写出当计数值等于某个确切值的时候,就触发状态机的某个转换,或者生成一个start/end/flag,这很常见。另外,由于在握手中每个模块一定会作为数据的发送者、接收者当中的至少一方,所以许多时候我们的模块所要输出给其他模块的ready或valid其实也是由我们自己具象地设定的。因此,总体来看数据通路也不是完全具象的,控制通路也不是完全抽象的,只是它们包含的思维方式让我们懂得去分析每个信号的具体情况,弄清楚哪些东西要主动确定、哪些则要被动接受,从而理清所有的东西。明白了这些之后,可以通过这个视频来了解一下中央控制和逐级反压方式的流水线写法分别是怎样的——《芯片流水线设计思路分享》,一般而言,用于教学的流水线CPU demo往往基于前者,但后者实际上也是一种重要且规范的做法,而且在控制流上更加直观。

二、AI芯片中的数据流与控制流

事实上,控制流和数据流的区分不仅是微观设计层面的思维,也是我们需要在整体的架构设计层面建立的认识。一般来说,我们把芯片工作模式中像指令调度这样的部分称为控制流,而把一些具有特定的数据计算与流动方式的部分称为数据流。这种区分非常好理解——指令控制着模块或者说某一电路部分的工作起止,反映到微观代码设计的层面可能就与模块里的状态机息息相关,而宏观意义与微观意义上的数据流也明显具有相通的含义。有了这样的概念后,我们就能更清晰地反观和梳理一下AI芯片的设计理念——在AI芯片当中,定制化设计(即领域定制架构思想)被特别强调,因为通过对算法特性的具体分析和利用才能更好地提高硬件的性能和效率,但如果从控制流和数据流这一对概念的角度理解这个问题,现在如果再来反观领域定制架构思想,就会意识到定制化程度的提高在某种意义上就是在放大数据流的重要性,因为当我们根据AI算法在计算过程、访存模式、数据稀疏性等方面的特点而设计一些定制化的硬件时,其实就是在创造特定的数据流,从而达到提高计算并行度、减少冗余访存、跳过冗余计算、简化复杂操作等各种各样的目的。这种对数据流优化的格外强调,我觉得是AI芯片区别于传统处理器芯片的关键。

在芯片设计中,控制流与数据流的相互平衡和各司其职是非常重要的。尽管AI芯片需要我们特别关注数据流的设计,但是数据流在芯片架构与工作模式中具体占有多大的比重,则是一个需要我们自己折中的问题。在计算机架构理论中,人们一般把通用处理器架构(一般认为即是冯·诺依曼架构)称为control flow架构,并定义了所谓的data flow架构来表示与control flow架构相反、以数据驱动计算的架构[1][2]。其中,第2篇博客对data flow架构的解读比较好地解释了我们在这里想要强调的对控制流与数据流之平衡的反思,即最原始的、狭义的data flow架构中是没有任何控制调度部分的,而是在硬件开始工作前先由AI编译器(或人为地)规划好计算通路对应的硬件结构,让AI计算图被直接映射成硬件上的数据流。这种完全基于数据流的架构或多或少会因为对特定硬件结构的过高需求而在通用性上受到限制,一旦算法对象有所变化,就必须重新生成对应的硬件,这件事即使对于能重新烧录的FPGA来说在现实情景中也很有困难,并且我们未必能保证对于任意规模的算法都能拿出足够充足的硬件资源来把计算图的所有部分映射成分立的硬件。因此,为了实现一种更均衡的方案,AI加速器最终还是需要控制流与数据流的良好结合。一方面,我们可以把控制流负责的部分定义在以算子模块为最小单位的层面上,而在算子模块自身内部可以设计定制化的数据流(比如脉动阵列),这样既能够直接地兼容那些涉及同样算子但在结构和计算过程上有区别的同类算法,又保留了数据流创新的空间,从而真正提升加速器的各方面效果。另一方面,我们可以像上面的第2篇博客所说的那样把原始的data flow架构作为一种思想,实际采用以片上互连网络(NoC)连接硬件单元的形式,保留通过顶层的控制模块做控制调度的部分,并把控制调度最终转化为比如NoC中硬件单元间连接规则的配置,从而实现定制化但又可调整的计算通路,遇到硬件资源不足以支撑算法对象全流水计算的情况也可以按分轮次计算的模式做调度,这样便能具有更好的通用性。需要注意的是,这2种做法之间其实也没有太泾渭分明的界限,例如在Overlay架构中,虽然算子模块一般是各自作为通过总线与存储模块相连的主机,但如果我们在算子模块之间添加一些直接的互连并定义配套的指令控制规则,而非让算子模块的工作完全隔离,也就可以实现类似于上述第二种做法的思路了。总而言之,AI芯片中的控制流与数据流需要找到一个平衡点,这里讨论的设计范式也只是作为参考,至于具体的创新与实现,就看实际研究中的探索了。

posted @ 2025-07-03 12:13  梦中一盏灯  阅读(29)  评论(0)    收藏  举报