对于处理器而言,虽然我们非常关注其主频和性能,但有一个不可忽视的事实是,处理器在绝大多数的时间是处于待机休眠状态。譬如我们日常使用的手机,绝大多数的时间是处于一种休眠状态。而即便是在运行的过程中,绝大多数的时间也是处于性能要求不高的场景。
以知名的ARM big-LITTLE架构为例,便是使用能效比更高的小核运行于性能要求不高的场景,只有在最关键的时刻才启用耗电较高的大核。
处理器的低功耗技术可以从多个层面加以探讨,从高层的软件、系统,到底层的硬件工艺均可涉及。
一、软件层面低功耗运行于处理器之上的是软件程序,是软件赋予了处理器灵魂。软件层面的灵活性很高,软件层面发掘低功耗的效果比硬件低功耗本身的效果更加显著。通俗地讲,底层硬件辛辛苦苦地优化设计省点电,远远不如软件多休眠省的电多。
为了使处理器消耗尽可能少的功耗,一套好的软件程序应该尽可能合理地调用处理器的硬件资源,譬如:
- 仅在最关键的场景调用耗能高的硬件,在一般的场景尽可能使用耗能低的硬件;
在处理器空闲的时刻,尽可能的进入低功耗休眠模式,以节省功耗。
系统层面的低功耗技术可以涉及板级硬件系统和芯片内的SoC系统,其原理基本一致。以SoC系统为例,常见的低功耗技术如下:
SoC系统中往往划分不同的电源域,能够支持将SoC中的大部分硬件关闭电源;
SoC系统中往往划分不同的时钟域,能够支持小部分电路以低速低功耗的方式运行;
通过不同的电源域与时钟域的组合,划分出不同的低功耗模式,SoC配备PMU(Power Management Unit)控制进入或者退出不同的低功耗模式;
软件可以通过使用PMU的功能,在不同的场景下进入和退出不同的低功耗模式。
处理器层面的常见的低功耗技术如下:
处理器指令集中定义一种休眠指令,运行该指令后处理器核便进入休眠状态。
譬如RISC-V定义了WFI指令,全称为Wait For Interrupt,是RISC-V架构定义的专门用于休眠的指令。当处理器执行到WFI指令之后,将会停止执行当前的指令流,进入一种空闲状态,这种空闲状态可以被称之为“休眠”状态,直到处理器接受到中断(中断局部开关必须被打开,由mie寄存器控制),处理器便被唤醒。处理器被唤醒后,如果中断被全局打开(mstatus寄存器的MIE域控制),则进入到中断异常服务程序开始执行;如果中断被全局关闭,则继续顺序执行之前停止的指令流。
休眠状态可分为浅度休眠和深度休眠。
浅度休眠状态往往将处理器核的整个时钟关闭,但仍然保留电源供电,因此可以节省动态功耗,但是静态漏电功耗仍然有消耗;
深度休眠状态往往不仅将处理器核的时钟,甚至将电源也关闭,因此可以同时省掉动态和静态功耗。
处理器核深度休眠断电之后,其内部上下文状态可以有两种策略进行保存和恢复。
策略一是在处理器核内部使用带Retention能力的寄存器或者SRAM保存处理器状态,Retention Cell或者SRAM可以使用极低的漏电消耗保存处理器的状态;
策略二是使用软件的Save-and-Restore机制,即在断电前将处理器的上下文状态保存在SoC层面的电源常开域(Power Always-on Domain)中,待到唤醒恢复供电后使用软件从外部Always-on Domain读取回来加以恢复。
策略一的优点是休眠和唤醒的速度极快,但是ASIC设计的复杂度高,策略二的优点是实现非常简单,但是休眠和唤醒的速度相对较慢。
在处理器的架构上,可以采用异构的方式节省功耗。
四、单元层面低功耗一种知名度很高的示例便是ARM big-LITTLE架构,其使用能效比更高的小核来运行于性能要求不高的场景,只有在最关键的时刻才启用耗电较高的大核,从而节省动态功耗。
模块和单元层面的低功耗技术已经进入了IC设计微架构的范畴,其常见的技术与SoC系统层面基本一致,只不过是规模更小的版本:
- 一个功能完整的单元,往往需要单独配备独立的Clock Gate,当该模块或者单元空闲的时候,可以使用Clock Gate将其时钟关闭以节省动态功耗;
某些比较独立和规模较大的模块,甚至可以划分独立的电源域支持关闭电源,以进一步节省静态功耗。
寄存器层面的低功耗技术已经进入了IC设计编码风格的范畴,可以从以下几个方面减少寄存器层面的功耗:
时钟门控
目前主流的逻辑综合工具均有从代码风格中直接推断出ICG(Integrated Clock Gating)的能力。因此只要遵循一定的编码风格,便能够将一组寄存器的时钟自动推断出ICG,以节省动态功耗。
在逻辑综合完成之后,工具可以生成整个电路的Clock Gating Rate,开发者可以通过此Clock Gating Rate数据的高低来判断其设计的电路是否被自动推断出了足够的ICG。好的电路一般有超过90%的Gating Rate,否则一方面可能是电路中数据通路较少(主要以小位宽寄存器为基础的控制电路为主),或者编码风格有问题。
减少数据通路翻转
为了减少不必要的动态功耗,应该尽量减少寄存器的翻转。
示例一:以处理器的流水线为例,每级流水线通常需要配置一位控制位(Valid位)表示该级流水线是否有有效指令,当指令加载至此级流水线时将Valid位设为高,离开此级流水线时将Valid位清零。但是对于此级流水线的数据通路载体部分(Payload部分),只有在指令加载至此级流水线时向Payload部分的寄存器加载指令信息(通常有数十位),而指令离开此级流水线时Payload部分的寄存器无需清零。通过此方法能够极大减少数据通路部分的寄存器翻转率。
示例二:对于基于寄存器的FIFO的设计,虽然理论上可以使用比较简单的数据表项逐次移位的方式实现FIFO的先入先出功能,但是却应该使用维护读写指针的方式(数据表项寄存器则不用移位)实现其先入先出的功能。因为数据表项逐逐次移位的方式会造成寄存器的大量翻转,相比而言使用读写指针的方式实现则保持了表项寄存器中的值静止不动,从而大幅减少动态功耗,因此应该优先采用此方法。
数据通路不复位
六、锁存器层面低功耗
与上一点同理,对于数据通路部分的寄存器,甚至可以使用不带复位信号的寄存器。不带复位信号的寄存器面积更小,时序更优,功耗更低。譬如对于某些Buffer、FIFO、Regfile的寄存器部分,经常使用不带复位的寄存器。
但是,使用不带复位的寄存器时必须小心谨慎,保证其没有作为任何其他控制信号,从而造成不定态的传播。在前仿真阶段必须有完善的不定态捕捉机制发现这些问题,否则可能造成芯片的严重Bug。
锁存器相比寄存器面积更小,功耗更低。在某些特定的场合使用可以降低芯片功耗。但是锁存器会给数字ASIC流程带来极大困扰,因此应该谨慎使用。
七、SRAM层面低功耗SRAM在芯片设计中经常使用到,可以从以下几个方面减少SRAM的功耗:
选择合适的SRAM
常规SRAM通常分为“单口SRAM(Single Port SRAM)”,“一读一写SRAM(Two-Port Regfile)”,“双口SRAM(Dual-Port SRAM)”。其他类型的SRAM需要特殊定制。
从功耗与面积的角度来讲,Single Port SRAM最小,Two-Port Regfile其次,Dual-Port SRAM最大。应该优先选择功耗与面积小者,应该尽量避免使用高功耗的SRAM类型。
SRAM的数据宽度也会影响其面积。譬如以同等大小的SRAM为例,假设总容量为16KB,如果SRAM的数据宽度为32位则深度为4096,如果SRAM的数据宽度为64位则深度为2048。不同的宽度深度比可能会产生面积迥异的SRAM,因此也需要综合权衡。
尽量减少SRAM读写
SRAM的读写动态功耗相当可观,因此应该尽量减少读写SRAM。
譬如,以处理器取指令为例,由于处理器多数按顺序取指,因此应该尽量一次从SRAM中多读回一些指令为好,而不是反复多次的读取SRAM(一次读一点点指令),从而节省SRAM的动态功耗。
空闲时关闭SRAM
八、组合逻辑层面低功耗
与单元门控时钟相同的原理,SRAM的时钟应该在空闲时予以关闭 ,以节省动态功耗。
SRAM的漏电功耗相当可观,因此,在省电模式下,可以将SRAM的电源关闭以节省其漏电。
组合逻辑是芯片中的基本逻辑,可以从以下几个方面减少组合逻辑的功耗:
减少面积
通过使用尽量少的组合逻辑面积从而减少静态功耗,此为数字逻辑设计的基本认知,无需赘述。因此从设计思路和代码风格上应该尽量将大的数据通路(或者运算单元)进行复用从而减少面积。另外应该避免使用除法乘法等等大面积的运算单元,尽量将其转化成为加减法运算。
减少翻转率
九、工艺层面低功耗
可以通过逻辑门控的方式,在数据通路上加入一级“与”门,使没有用到的组合逻辑在空闲的时候不翻转,从而达到减少动态功耗的效果。
但是由于额外加入一级与门,在时序非常紧张的场合也许无法接受,需要谨慎使用。
工艺层面的低功耗一般涉及到使用特殊的工艺单元库,本文在此不做过多探讨。
综上所述,低功耗机制对于处理器而言至关重要,IC设计师可从软件层面、系统层面、处理器层面、单元层面、寄存器层面、锁存器层面、SRAM层面、组合逻辑层面、工艺层面采取不同的低功耗机制降低处理器功耗。
看看你的设计中采用了哪些低功耗机制?