原貼如下,寫的很好,轉(zhuǎn)載備查!
http://bbs.eetop.cn/thread-636337-1-1.html
紅色字體為我自己加的理解之類的
??論壇里面討論Low Power RTL前端設(shè)計的帖子好像不多,許多大牛的書上來就談工藝,半導體結(jié)構(gòu),讓我高山仰止,但也只能心向往之(實在有些看不懂)。
??工藝的提升帶來的收益可能遠比RTL深度優(yōu)化高,如TSMC 40LP vs TSMC 28HPC+,后者基本上比前者面積小一半,速度快一倍,dynamic power小40~50%,代價是leakage高3~4倍。在老工藝上如何絞盡腦汁優(yōu)化設(shè)計,可能也很難達到這種效果。
??但作為前端RTL designer,一旦工藝選定,我們只能在自己的一畝三分地里面做到最好,本帖就此拋磚引玉,結(jié)合自己的工作經(jīng)驗討論下Low Power RTL design,挖個坑,希望壇子里的大牛一起幫忙填坑。
??剛?cè)胄凶鰀esign時,考慮的是Area和Speed,近些年來,Power變成了越來越重要的指標,有時候更是犧牲Area和Speed來換取Power的收益,畢竟有些領(lǐng)域,電池容量是很難增大的。
??有人做過大體統(tǒng)計,降低功耗的方法和收益大體如下,對于前端RTL設(shè)計,最好用的還是clock gating,收益最顯著,代價最小,其它方法也能有可觀的收益,具體還得依靠具體應用場景分析。

??Power主要消耗在:1) combinational logic; 2) sequential logic; 3) memory; 4) clock network
??下面我將就以下幾個方面展開討論:
??1. Improve clock gating efficiency
???a. Block level clock gating
???b. RTL clock gating
??2. Reduce data toggle rate
???a. FIFO vs PIPE
???b. FSM coding style
???c. Unnecessary reset
??3. Refine memory selection
???a. Area power balance
???b. I/F bitwidth selection
???c. Depth selection
??4. Reduce memory accessing
???a. Address caching
??5. Reduce logic size
???a. Logic sharing
???b. Logic balancing
???c. Divider optimization
???d. Reduce pipe line length
???e. Hardmacro vs Register
???f. Reduce bitwidth
???g. Async reset vs non-async-reset
??6. Misunderstanding
1. Improve clock gating efficiency
1.1 block level clock gating
??如果某個模塊或者功能可以打開或關(guān)閉,且logic相對獨立,則可以在這部分logic的時鐘上手工插入一個ICG,用模塊使能控制ICG的開關(guān),這樣能最大限度的提升gating效率。
??1) ICG最好選取驅(qū)動能力大的,以便于驅(qū)動足夠多的DFF;
??2) ICG建議加一個wrapper,這樣當需要替換其它工藝時,只需要將wrapper里的instance換掉;
??3) 綜合時對此類ICG設(shè)置don't touch
Q: 綜合時對此類ICG設(shè)置don't touch,請問原因是什么?是因為綜合工具可能把它優(yōu)化沒了嗎?
A: 同型號的ICG有多種驅(qū)動能力,一般手工插入的ICG會挑驅(qū)動能力比較大的,也不希望綜合工具去改這個東西。
1.2 RTL clock gating
??Low power RTL綜合的精髓就是把本該綜合在D端的enable信號,綜合到clock端,這樣只有enable有效才能釋放一個clock使得D端數(shù)據(jù)傳遞到Q端。當D超過一定bit數(shù),通常認為>=4bit能節(jié)省power,為了達到這種效果,寄存器的賦值一定是條件賦值,示范代碼和電路如下:

??Metor有power_pro能夠幫助分析RTL,提取有效的enable,并完成代碼的優(yōu)化,但就我看下來,它優(yōu)化過的代碼可讀性非常差,條件有時候也有冗余,導致過多的使能ICG,而且后續(xù)如果需要ECO,還需要購買它的formal工具,不然很難再改它的code.
??Low power RTL理想代碼結(jié)構(gòu)
always @(posedge clk or negedge rstn) begin
if(!rstn) begin
Q <= 'h0;
end
else if(condition_1) begin
Q <= D_1;
// other condition 2, 3, 4 ...
end
else begin
Q <= Q; // better to remove this assignment, then data will be kept
end
end
Q: 請問line 9不拿掉不會keep嗎?有點不理解,之前一直都是推薦將條件寫完整
A: 留著沒問題,但我喜歡代碼精簡,不賦值對于寄存器來說就是保持 (Q <= Q)
??錯誤代碼的示例,如果不管在什么情況下,總有D值需要打到Q, 使得即使綜合出來ICG,該ICG也不能關(guān)斷。錯誤遠不止下面幾種,if/else if/else, case/default等等
??1) 沒有賦值條件
always @(posedge clk) begin // "if-else" hierarchy 0, default is "else" block
Q <= D; // Error: no condition for data assignment
end
??2) else賦值
always @(posedge clk or negedge rstn) begin // hier 0
if(!rstn) begin // hier 1 "if" block
Q <= 'h0;
end else begin // hier 1 "else" block
Q <= D;
end
end
??3) 多級條件中的else
always @(posedge clk or negedge rstn) begin // hier 0
if(!rstn) begin // hier 1 "if" block
Q <= 'h0;
end else if(condition1) begin // hier 1 "else if" block
if(condition1_1) begin // hier 2 "if" block
Q <= D1_1;
end else begin // hier 2 "else" block
Q <= D1_2; // not report error, as it is in "else if" block
end
end else begin // hier 1 "else" block
if(condition2_1) begin // hier 2 "if" block
Q <= D2_1;
end else begin // hier 2 "else" block, in hier 1 "else" block
Q <= D2_2; // Error: no condition for data assignment
end
end
end
??4) 下面這個例子不會報錯
always @(posedge clk or negedge rstn) begin // hier 0
if(!rstn) begin // hier 1 "if" block
Q <= 'h0;
end else if(condition1) begin // hier 1 "else if" block
Q <= Q; // "Q <= Q" ensure ICG insertion
end else begin // hier 1 "else" block
Q <= D; // Not report ERROR as "Q <= Q" in "else if"
end
end
2. Reduce data toggle rate
2.1 FIFO vs PIPE
??當數(shù)據(jù)需要穿過N拍delay后再使用時,我們通常有兩種方法來實現(xiàn),一是將數(shù)據(jù)打N級pipe,一級一級往后傳;二是將數(shù)據(jù)存入FIFO,到后級需要使用時直接讀出來。兩種方式的vld信號都需要單獨傳遞。
??對比PIPE方式,F(xiàn)IFO的方式有額外地址計算比較的開銷,但每個數(shù)據(jù)只需要讀寫各一次,不像PIPE,數(shù)據(jù)需要在整個PIPE中shift一輪,F(xiàn)IFO方式每個寄存器的toggle rate將大幅下降。假設(shè)數(shù)據(jù)的toggle rate為Tr,N級pipe的toggle為N*Tr, FIFO為Tr

??如果由于FIFO輸出數(shù)據(jù)+后續(xù)計算timing不滿足,可以考慮縮短一級FIFO,最后一級仍由PIPE輸出。

??根據(jù)我在TSMC 40nm和28nm下PTPX仿真結(jié)果分析,結(jié)論如下:
??FIFO replace PIPE for power reduction:
??when ADDR >= 2 bits, DATA should be >= 4 bits; DATA越寬,級數(shù)越深,F(xiàn)IFO power收益越高,但有額外的面積開銷。
??上面腳本提供命令power_check.pl -2d -d 來把代碼中所有的2D array找出來,有些同學喜歡把PIPE賦值寫成下面的樣子
代碼的第2行和第3行,原文是N,我認為應該是i
for(i = 1; i < N; i ++) begin
if(VLD[i-1])
Array[i] <= Array[i-1]; // 這個代碼雖然是有條件賦值,但如果符合上面的條件,可以考慮換成FIFO
end
Q: 樓主能具體講一下關(guān)于2D reg array的問題嗎?
A: 為什么2D reg array要拿出來單獨講。如果寫代碼的人不注意,Inst的2D reg array可能是幾百或者幾千bits。我曾遇到一個項目,組里一個同事為了對齊某路復雜計算邏輯結(jié)果,把另一路的一組2D reg array多打了一拍,這一拍就打掉3千多bits DFF; Power review前用此腳本抓出所有2D array,發(fā)現(xiàn)了這個問題,讓他想辦法縮短計算邏輯一拍來對齊,power大幅降低。
遇到2D reg array,需要根據(jù)應用來確定是否還可以優(yōu)化:如果是做pipeline,能否考慮使用FIFO結(jié)構(gòu);如果沒有multiple RD/WR的需求,是否可以用hardmacro替換。
總之,寫下去的2D array最好要經(jīng)過review,這個腳本能方便的把這個結(jié)果抓出來。
2.2 FSM coding style
??狀態(tài)機常用編碼有3中:
??1) one-hot: 如3'b001 -> 3'b010 -> 3'b100,狀態(tài)個數(shù)和比特位寬相同,每次狀態(tài)變化,最多只有兩個bit變化。
??2)二進制編碼,如3'b000 -> 3'b001 -> 3'b010 -> ..., N bit能支持種狀態(tài)。
??3)格雷碼,3'b000 -> 3'b001 -> 3'b011 -> 3'b010 -> ..., 如果按照順序變化,每次只有一個bit跳變。
??總體來說,one-hot使用bit數(shù)較多,power最差,如果狀態(tài)跳變有一定順序,采用格雷碼能降低toggle rate.
??40LP下4bit FSM,16個狀態(tài),從4'h0跳轉(zhuǎn)到4'hf的狀態(tài)機,功耗面積對比結(jié)果如下。
??即使狀態(tài)機不能完全按照格雷碼編碼,把頻繁跳轉(zhuǎn)的狀態(tài)用格雷碼編碼,也能獲得舉手之勞的power收益。盡量少用one-hot編碼。
| FSM | Power | Area |
|---|---|---|
|
|
||
| One-hot | 1.023e-05 | 166.69 |
| Binary | 9.984e-06 | 108.48 |
2.3 Unnecessary reset
??對于控制寄存器,清理掉殘余狀態(tài)很多情況下是必要的,但對于data寄存器,數(shù)據(jù)殘余可以不用復位。
??如果只在read_en的條件下把有效的數(shù)據(jù)寫入rdata,完全沒有必要在!read_en的時候復位寄存器,這么做只會白白增加toggle rate.
if(read_en) rdata <= read_data;
else if(!read_en) rdata <= 'h0; // Don't reset rdata to all 0
??如果寫了這種語句,即使用power優(yōu)化工具,或者上面那個腳本,都是沒有辦法來優(yōu)化的;總的來說,寄存器使能控制越精確(打開ICG幾率越?。?,越有利于power優(yōu)化。
3. Refine memory selection
??SRAM的選擇有很多講究,我們需要看throughput, size, width來決定到底是選1p, 2p, spra和1prf,通常情況下,在滿足速度要求的情況下,挑選面積小的。在這里我提一種新的挑選方法,即在速度達到要求的前提下,挑選power, area性價比最高的。
??當我們選的面積最小的為基準時,看面積增加的百分比和power減少的百分比的差值,假設(shè)area和power對性價比評估各占50%的權(quán)重,如面積增加10%,但power下降20%,則認為性價比變好了,如果只換來5%的power下降,則認為性價比變差了。
??當然我們可以調(diào)整area/power的權(quán)重來改變挑選規(guī)則,極端情況下,把area權(quán)重設(shè)置為100%就是通常情況下挑面積最小的那種方法。
??那么,我們只需要用memory生成工具,將滿足尺寸的sram按照不同的rf/sram segment_option, mux, width, bits用腳本全部生成一遍,用上述規(guī)則挑選最優(yōu),有些面積相差不大的sram,power差20%~30%.
??另外,同樣位寬,深度減半的也可以考慮(這個從我做的實驗看,收益不如double位寬的)
??總之,挑sram不光考慮面積,可以嘗試不同的選擇,更多的考慮性價比。
??sram面積可以直接從生成文件里讀出,但power需要手工計算:假設(shè)standby power不考慮,只考慮read/write power, 我們可以從生成文件中得到每次讀寫所需要的power, pwr, prd,然后根據(jù)sram使用的特性,比如在一定時間內(nèi)(周期內(nèi)),是多少寫多少讀,乘上單次讀寫對應的power,就可以大體估計sram的power.
??另外強烈建議在生成的sram外面加個wrapper,并手動插入一個ICG,只有在RD或者WR的時候才打開ICG,通常情況下,sram的clock是被gating掉的。
4 Memory Address Caching
??當sram使用場景需要對同一個地址多次查表時,可以考慮將上一輪讀地址存下來,和新地址比較,如果在上次讀之后沒有對該地址的寫操作,且新地址等于鎖存的地址,則可以省略該輪讀訪問。
5. Reduce logic size
??Area大通常意味著power大,站在save power的角度,減少面積,減少邏輯單元,和降低功耗的方向是一致的。
5.1 Logic share
??有些邏輯的throughput要求不高,一份邏輯分時進行N次計算,等效于N份邏輯在一定時間內(nèi)計算一次。復用之后計算總量一樣,但靜態(tài)功耗會降低。當然需要考慮1份邏輯N次計算帶來的副作用,計算latency加長是否可以接受。
5.2 Multiplier
??乘法器,在這特指變量乘變量,如果是變量乘以常數(shù),綜合工具都是綜合成加法器,不在考慮范圍內(nèi)。
??同等bit數(shù),乘法器比加法器大許多,對于每個乘法器,我們都:
??1) 需要仔細review它的使用是否必須;
??2) 使用的時候位寬是不是可以降低,乘法器位寬嚴重影響綜合面積和timing,在計算的時候,即使是signed的數(shù),也不要輕易添加N bit最高位(符號位),建議使用verilog-2001語法,用signed(B[dw-1:0]),千萬別寫成{{(dw){A[dw-1]}}, A[dw-1:0]}{{(dw){B[dw-1]}}, B[dw-1:0]},雖然輸出位寬為2dw.
??3) 乘法器是不是前后組合邏輯很多,造成綜合工具為了meet timing而產(chǎn)生一個超級并行(巨大)的組合邏輯(這個在logic balance也會提到);
??4) “乘加”邏輯是不是可以轉(zhuǎn)變成“加乘”邏輯,這里“乘加”指的是Amul和Bmul乘完寄存后再加,還是(A+B)mul后再寄存,如果在同一拍內(nèi),即使寫成Amul+Bmul,綜合工具也會優(yōu)化成(A+B)*mul,但建議在代碼上體現(xiàn)先加后乘。
??下面是4bit和15bit“乘加”、“加乘”面積比較,“乘加”面積幾乎大一倍。
| Add_before_Mul or Mul_before_Add | Area (um2) | Multiplier number |
|---|---|---|
| ADD_MUL = bit4 * (bit15 + bit15) | 543 | 1 |
| MUL_ADD = bit4 * bit15 + bit4 * bit15 | 919 | 2 |
Q: 現(xiàn)在乘法器好像很少有人自己寫了,都用的是EDA公司的DesignWare,不知道樓主那邊是不是也是這樣子
A: 是的,基本就寫個,等著EDA工具去優(yōu)化,但寫在什么位置,先*還是先+,是不是可以合并計算,乘法的位寬等還是要自己考慮。
5.3 Divider optimization (N/M)
??乘法器通常1拍內(nèi)完成,但除法器少有1拍完成的。乘法我們可以直接在代碼里面寫“*”號,綜合工具通常能給我們滿意的結(jié)果,但除法器,極少數(shù)情況下我們直接寫“/”,大部分情況我們需要單獨inst除法module.
??1) 標準除法器(N和M都是變量):
??基本的設(shè)計思路是移位減,如果每個cycle計算被除數(shù)1bit, N/M,我們需要N拍;如果每個cycle 2bit,則需要(N+1)/2拍,這樣的除法器面積都不大,但計算latency長。同時EDA公司也提供design-ware除法器,速度更快,面積也更大。當然還有一種查LUT表的除法器,但我沒用過,不好評價。
??2) 特殊除法器:
??2.1) 除數(shù)是2的冪次,如2/4/8,很多人會想到直接移位,對于被除數(shù)是正數(shù)來說移位絕對正確;但如果被除數(shù)是負數(shù),除法結(jié)果收斂到0,移位結(jié)果收斂到-1.
??如-5/64 = 0, -5 = 5b'1_1011,右移后,變成5'b1_1111,= -1. 兩者結(jié)果不同。
??判斷高位都全為1,如A[m:0] >> n,需要確認A[m:n]的情況。
??|A[n-1:0] != 1'b0 ? A[m:n] + 1'b1 : A[m:n];
??2.2) 除數(shù)是常數(shù),最好為(2的冪次+/-1),如5,7等,可以考慮泰勒展開,用2的冪次和來近似。
??如下,用最近的2的冪去近似的除,將余數(shù)和商迭代直到其和小于除數(shù)。Div/( - K)
??step 1 Div/ = M0 + R0 if KM0 + R0 >=
, to step 2; else M = M0, R = R0 + KM0
?? step 2 (K*M0 + R0)/2 ...
?? 如下:
?? 100/7 = 14 + 2 step 1 100/8 = 12 + 4 if(12 + 4) >= 7, to step 2
?? step 2 (12 + 4)/8 = 2 + 0 if(2+0) < 7. result = 12 + 2 余 2
??2.3) 除數(shù)是常數(shù),是不是可以用近似的乘法代替,比如先計算X = 1024/M,再用X*N/1024來還原成N/M.當然這個除法會有精度損失需要考慮。
??網(wǎng)上還有相關(guān)文檔針對特殊除法器的優(yōu)化,這個需要具體應用具體分析。
??正因為除法器在面積和latency上的差異非常大,特別是長latency的除法器,很容易成為計算邏輯中的瓶頸,別的邏輯都在等著它的結(jié)果才能開始后面的計算。因此在選擇不同除法器時,需要考慮整個data-path的開銷,減少1個cycle的除法計算,是不是能縮短整個path 1拍,可以節(jié)約多少寄存器。
??當data-path不關(guān)心除法latency的時候,直接選1bit移位減的除法器,area和power最優(yōu),如果能結(jié)合邏輯復用效果更佳。
5.4 Reduce pipeline length
??在寫RTL前,我們應該知道最基本的計算單元(*, +, >=等)的延時和面積,這個數(shù)據(jù)可以通過對基本計算單元在sdc中約束緊和松的綜合得到。在tight的情況下,我們能看到綜合工具把邏輯并行展開,面積非常大,也行還不能meet timing;在loose的情況下,邏輯串行都能滿足timing要求。兩者面積相差3~6倍都不稀奇。
??Reduce pipeline,要求對基本的組合邏輯delay有基本的認識,合理的排列pipeline,同時注意關(guān)注data-path converge點,看看data-path長短的瓶頸在哪條分支上,壓縮關(guān)鍵分支是否能帶來整個path的縮短,以及這樣帶來的好處。
??當然預估data-path的延時和面積的影響,這個要求非常高,我自己也難做的很好,一般為了timing容易meet,大家可能都會在設(shè)計時留足余量,導致path比理想狀態(tài)下長不少。但我有一個想法,也許可以幫大家找到最合理的pipeline length,我準備整個腳本來幫忙實現(xiàn)這個功能。(僅針對算法模塊,控制少,計算多)
??1) 先直接照搬C code,不考慮timing,把中間計算邏輯RTL寫出來,最后輸出用寄存器,建議寫成參數(shù)化的方式,方便后續(xù)re-timing;
??2) 進行tight/loose兩輪綜合,這樣我們得到組合邏輯的最大面積(最小delay)和最小面積(最大delay);
??3) 通過最大delay/clock_period,得到最小的pipeline length;通過最小delay/clock_period,得到最大的pipeline length.
??4) 用re-timing的方式,從最小pipeline length開始,調(diào)整pipeline重新綜合,不停找面積的拐點,我期待看到的結(jié)果是,中間有個面積最小的拐點,或者直到pipeline length最大,面積單調(diào)遞減;
??5) 面積最小的pipeline length就是理想的結(jié)果。

如上圖所示,縱軸Z是面積,X軸是頻率,Y軸是pipeline length,在不同的頻率下(不同的截面),不同的pipeline面積曲線是圖上離散的點,我們求的就是面積最小解。
??我們可以用這個結(jié)果來指導實踐RTL design,達不到最好可以采用次好,但總比沒有準備直接上手要好。如果腳本準備妥當,只是花幾輪綜合的時間,我覺得可行性還是有的,反正都是機器跑,不然這種設(shè)計全憑經(jīng)驗,沒有benchmark來check quality.
??我還想是不是還可以用HLS的綜合結(jié)果來當benchmark,用算法C code去綜合,看看catapuls給出來的建議是多少級,再和上述re-timing循環(huán)綜合的最優(yōu)結(jié)果比,差多少,如果兩者接近,證明HLS的建議可信。
5.5 Reduce bit width
??最簡單的比如4個10 bits數(shù)相加,也許就有人得出需要13bit的結(jié)論。
c code: F = A + B + C + D;
wire [10:0] F_pre1 = A[9:0] + B[9:0];
wire [11:0] F_pre2 = F_pre1 + C[9:0];
wire [12:0] F = F_pre2 + D[9:0]; // sum of four 10 bits only needs 12 bits result
5.6 Hardmacro vs Register
??TSMC 40nm工藝下,簡單對比單個寄存器和SRAM的大小
?? SDFCNQD1BWP (min size)
?? SDFCNQD2BWP
?? For , each bit is
?? For , each bit is
?? For , each bit is
??通過查手冊,知道單次讀寫的power,以便在大量數(shù)據(jù)需要寄存時,分析到底是用hardmacro還是DFF.
5.7 Logic balancing
??綜合工具在時序緊的時候,更多的用并行邏輯來減少計算delay,在時序松的時候用串行邏輯來減少面積,如果我們在寫code的時候能把一些不在關(guān)鍵路徑上的邏輯拆開,這樣能優(yōu)化面積,同時減少power.
??如下圖,非關(guān)鍵路徑第一拍邏輯多,第二拍邏輯少。

??Balance后的結(jié)構(gòu)如下:

??一個具體實例如下:兩個時序很緊的加法器balance后,area和power的變換。area和power都有下降。
| Style | Power | Area |
|---|---|---|
| No-balance | 6.491e-06 | 729.06 |
| Balance | 5.618e-06 | 373.08 |
??當然,如果為了balance邏輯,需要寄存大量的中間結(jié)果也是不合適的;上面power沒降這么多是因為增加寄存器hold中間結(jié)果,這個最好能有工具提供優(yōu)化提示。
Comments from huoyumutou:
- 狀態(tài)機編碼的優(yōu)化感覺不是很必要,會增加調(diào)試的難度(雖然verdi中可以看到content)
- memory的選擇還要考慮后端F&P的難度,形狀不能特別奇怪,否則沒法塞
- RAM和寄存器的對比,如果只對比面積的話,40nm下1000bits是分界線,如果1000bits以下,寄存器面積小于RAM;如果1000bits以上,寄存器面積大于RAM。除此之外,要考慮到寄存器的吞吐率比RAM高很多,這個主要考慮是不是需要這么高的頻率。
Response from lz:- 狀態(tài)機優(yōu)化屬于舉手之勞,做也沒多少油水;
- memory那項可以加一個長寬比的限制,剔除掉一些奇怪的形狀;
- 有時候面積不是唯一的考量,我的想法是求加權(quán)平均值最優(yōu)。