4、架构级低功耗设计:并行与流水线、多核与异构计算、数据流优化、存储层次设计
各位好,我是老张。今天咱们聊聊架构级的低功耗设计。说实话,很多工程师一上来就盯着门级电路、电压频率调节,其实真正的功耗大头,在架构层面就已经决定了。你想想看,一个糟糕的架构,后面再怎么优化,也是事倍功半。
我个人习惯,在做基带芯片架构时,先问自己三个问题:数据怎么流?计算怎么分?存储怎么放?这三个问题想清楚了,功耗基本就控住了。
4.1 并行与流水线:时间换面积,还是面积换时间?
并行和流水线,是低功耗设计的两把刷子。但很多人用错了地方。
并行,说白了就是多个人干同一件事。比如一个FFT运算,你用一个蝶形单元做64次,功耗是1份;你用8个蝶形单元并行做,时间缩短到1/8,但功耗变成了8份。等等,那总功耗不是一样吗?
嗯,这里要注意:并行真正的收益在于电压缩放。因为并行后时间充裕了,你可以把电压降下来。电压降一点,功耗是平方级的下降。我在项目中遇到过,一个LTE的PDSCH处理模块,用4路并行后,电压从1.1V降到0.9V,总功耗反而降了40%。
核心原则:并行不是为了快,而是为了降压。降压才是低功耗的真谛。
流水线呢?它是把一个大任务切成小段,每段用专门的硬件做。比如5G NR的LDPC译码器,我习惯把它分成:初始化、变量节点更新、校验节点更新、判决输出。每一级之间插寄存器。
流水线的功耗优势在于:减少了毛刺传播。组合逻辑越长,毛刺越多,无效翻转就越多。切短了,毛刺被寄存器挡住,动态功耗就下来了。
// 伪代码:流水线级间寄存器示例
always @(posedge clk) begin
// 流水线第1级
stage1_data <= input_data;
stage1_valid <= input_valid;
// 流水线第2级
stage2_data <= process_stage1(stage1_data);
stage2_valid <= stage1_valid;
// 流水线第3级
stage3_data <= process_stage2(stage2_data);
stage3_valid <= stage2_valid;
end
避坑指南:我曾经在一个项目中,流水线级数设计得太深(16级),结果每一级的寄存器都开着,空闲时功耗反而比非流水线版本还高。后来加了时钟门控,每级空闲时自动关掉,才把功耗降下来。
4.2 多核与异构计算:别让CPU干GPU的活
5G NR基带处理,任务类型五花八门。有控制信道这种小数据量、高实时性的;有数据信道这种大数据量、高吞吐的;还有测量、同步这种周期性任务。
用一个大核通吃?功耗肯定炸。我建议的做法是:异构多核。
| 任务类型 | 推荐核 | 功耗特点 |
|---|---|---|
| 控制信道(PDCCH) | 小核(Cortex-M4级别) | 低频率、低漏电 |
| 数据信道(PDSCH) | 大核+DSP加速器 | 高频率、可关断 |
| FFT/IFFT | 专用硬件加速器 | 固定流水线、无指令开销 |
| 信道估计 | SIMD向量处理器 | 数据并行、访存密集 |
你看,每个任务用最合适的计算单元,功耗自然就下来了。我记得有一次,一个团队用Cortex-A55硬跑LDPC译码,功耗直接飙到2W。后来换成专用译码器,功耗降到200mW。这就是异构的价值。
注意:多核之间的一致性开销不可忽视。我曾经见过一个设计,8个核之间为了维护缓存一致性,光总线翻转就占了总功耗的30%。后来改成消息传递模型,每个核只管自己的数据,功耗才正常。
4.3 数据流优化:让数据少跑路
数据流优化,说白了就是减少数据搬运。你想想看,从DDR搬一次数据到L2 Cache,功耗是搬一次到寄存器的100倍以上。
我常用的几个技巧:
- 数据重用:同一个数据,尽量在本地多用几次。比如信道估计的导频符号,算一次存下来,后面解调、译码都能用。
- 流水线数据直通:上一级的输出直接送给下一级,不经过内存。我在5G NR的PUSCH接收链路中,把FFT输出直接送到信道估计器,省掉了两次DDR读写。
- 批处理:小数据攒成大包再处理。比如控制信道的盲检,一次处理一个时隙的所有候选,比逐个处理省了50%的访存功耗。
// 数据流优化示例:流水线直通
// 不好的做法:每级都写回DDR
fft_output = fft(input);
write_to_ddr(fft_output); // 功耗高
ch_est_data = read_from_ddr(fft_output); // 功耗高
// 好的做法:流水线直通
fft_output = fft(input);
ch_est_data = channel_estimate(fft_output); // 直接传递,不经过DDR
个人经验:在做数据流优化时,我习惯先画一张数据流图,标出每个数据的来源和去向。然后问自己:这个数据能不能在本地多待一会儿?能不能不走DDR?往往改完数据流,功耗能降20-30%。
4.4 存储层次设计:把热数据放在近处
存储层次,是低功耗设计的最后一道防线。5G NR基带处理,数据量大、实时性高,存储设计不好,功耗全浪费在访存上。
我建议的存储层次:
- 寄存器文件:放最热的数据,比如当前处理的符号、中间结果。容量小(几十KB),但速度最快、功耗最低。
- L1 Scratchpad:放次热的数据,比如一个子帧的导频、控制信息。容量几百KB,用SRAM实现。
- L2 Cache/Shared Memory:放一个时隙的数据,比如PDSCH的软比特。容量几MB。
- DDR:放整个帧的数据,或者历史数据。容量大,但功耗最高。
这里有个关键点:数据要分层存放。热数据放近处,冷数据放远处。我见过一个设计,把整个子帧的IQ数据都放在L1里,结果L1容量不够,频繁换入换出,功耗反而更高。
经验之谈:存储层次设计,本质是容量与功耗的权衡。我一般先用profiling工具跑一遍典型场景,看看哪些数据访问最频繁,然后把这些数据放到最近的存储里。其他数据,能放多远放多远。
另外,存储的位宽也要注意。5G NR的调制阶数高(256QAM),一个符号就是8比特。如果存储位宽是32比特,一次读4个符号,但实际只用1个,剩下的3个就浪费了。我建议用可变位宽的存储,或者用打包存储,把多个小数据拼成一个大数据,减少无效读取。
避坑指南:我曾经在一个项目中,为了省面积,把L1 Scratchpad的位宽从128比特砍到32比特。结果每次读数据都要读4次,功耗反而涨了3倍。后来老老实实改回128比特,功耗才正常。存储位宽,不能只看面积,还要看访问次数。
4.5 本章小结
架构级低功耗设计,说白了就是四个字:少做、少搬、少存。
- 少做:用并行和流水线,让每个计算单元做最少的活。
- 少搬:优化数据流,让数据少跑路。
- 少存:合理设计存储层次,让热数据待在近处。
嗯,这些说起来简单,做起来需要大量的实践和调试。我建议各位在开始设计前,先花一周时间做架构评估,把数据流、计算量、存储需求都摸清楚。磨刀不误砍柴工,架构定好了,后面的低功耗设计就水到渠成了。
公众号:蓝海资料掘金营,微信deep3321