Step 3 打開Analysis窗口,選擇state C1的write operation,右擊選擇Goto Source
?
狀態(tài)C1下的寫操作是由于代碼在Product loop前就已經(jīng)設(shè)置res為0。因?yàn)閞es是在頂層函數(shù),在RTL里這是在寫入一個(gè)端口:這個(gè)操作必須發(fā)生在loop Product執(zhí)行之前。因?yàn)樗皇且粋€(gè)內(nèi)部操作,而是會(huì)對(duì)I / O行為產(chǎn)生影響,這種操作不能移動(dòng)或優(yōu)化。這可以阻止Product loop被flatten進(jìn)入row_col loop。
更重要的是,對(duì)于Product loop來說,為什么只有II為2是可能flatten的。
這個(gè)問題被稱作carried dependency,這個(gè)dependency發(fā)生在一個(gè)loop的迭代操作和相同loop的不同迭代操作。例如,一個(gè)操作分別發(fā)生在K = 1時(shí),當(dāng)K = 2時(shí)(其中k是循環(huán)指數(shù))。
第一個(gè)操作是在line 60數(shù)組res上的存儲(chǔ)(內(nèi)存讀操作)。
第二個(gè)操作是在line 60數(shù)組res上的下載(內(nèi)存寫操作)。
從圖中可以看到line 60是從數(shù)組res的讀取(由于+=操作符)和寫入數(shù)組res。數(shù)組默認(rèn)映射到RAM block,下面Performance View的細(xì)節(jié)解釋了為什么會(huì)發(fā)生這種沖突。
?
成功的schedule中,Product loop的下一次迭代如上所示。在這個(gè)schedule中,initiation interval(II)= 2,即loop操作每兩個(gè)周期重啟。任何block RAM之間的訪問沒有沖突。(沒有突出顯示的單元迭代重疊。)
不成功的schedule顯示了為什么loop不能在II = 1時(shí)pipeline。此時(shí),下一次迭代將需要1個(gè)時(shí)鐘周期后開始。當(dāng)?shù)诙蔚鷩L試一個(gè)地址去讀入時(shí),第一次迭代中寫入block RAM的操作仍然發(fā)生。這些地址是不同的,并且都不能在同一時(shí)間被應(yīng)用到block RAM。
因此,你不能將Product loop的initiation interval 設(shè)置為1。下一步是pipeline Col loop。這將自動(dòng)展開Product loop,并創(chuàng)建更多的operators,因此需要更多的硬件資源,但它確保在Product loop的不同迭代之間沒有dependency。
?
?
在綜合過程中,在控制臺(tái)窗格中報(bào)告的信息顯示loop Product被展開,loop flattening是在loop Row上執(zhí)行,默認(rèn)initiation intervalv為1的目標(biāo)不能在loop Row_Col上實(shí)現(xiàn),這是由于數(shù)組a上memory資源的限制。
?
綜合報(bào)告顯示,如上所述,對(duì)loop Row_Col的interval只有2:目標(biāo)是每個(gè)周期處理一個(gè)sample。你可以再一次使用Analysis窗口來證明為什么不實(shí)現(xiàn)initiation target。
Step 3 打開Analysis perspective,在Performance View里,展開Row_Col loop
?
在數(shù)組a中有三個(gè)讀操作。兩個(gè)讀操作開始于C1狀態(tài),第三個(gè)讀操作開始與C2狀態(tài)。數(shù)組被實(shí)現(xiàn)為block RAMs和數(shù)組,這是參數(shù)的函數(shù)是實(shí)現(xiàn)塊內(nèi)存端口。在這兩種情況下,一個(gè)block RAM最大只能有兩個(gè)端口(對(duì)于雙端口block RAM來說)。訪問數(shù)組a通過一個(gè)單一block RAM接口,沒有足夠的端口能夠在一個(gè)時(shí)鐘周期中讀取所有三個(gè)值。
另一種查看該資源限制的方法是使用到Resource窗口。
Step 4打開Resource tab,擴(kuò)展Memory Ports
狀態(tài)C1下面兩個(gè)讀操作與那些狀態(tài)C2下的讀操作重疊,因此,只有一個(gè)單一的周期是可見的:很顯然該資源被用于在多個(gè)狀態(tài)。即使當(dāng)端口a的問題得到解決,相同的問題會(huì)發(fā)生在端口b:它也有三個(gè)讀操作。
?
高級(jí)綜合允許數(shù)組被partitioned, mapped together和 re-shaped。這些都允許在不改變源代碼的情況下,對(duì)數(shù)組進(jìn)行修改。
solution4: Reshape the Arrays
Step 1 創(chuàng)建solution4,在Directive里給數(shù)組a和數(shù)組b插入ARRAY_RESHAPE,選擇dimension分別為2和1
?
Step 2 Run C Synthesis
綜合報(bào)告顯示頂層loop Row_Col現(xiàn)在是每個(gè)時(shí)鐘周期處理數(shù)據(jù)的一個(gè)sample。
? 頂層模塊需要12個(gè)時(shí)鐘周期才能完成。
? 經(jīng)過3次循環(huán),Row_Col loop輸出sample(迭代延遲)。
? 然后每個(gè)周期讀取1個(gè)sample(Initiation Interval)。
? 9次iterations/samples(Trip count)完成所有samples。
? 3 + 9 = 12個(gè)時(shí)鐘周期
函數(shù)可以完成并返回開始處理下一組數(shù)據(jù)。現(xiàn)在,把block RAM接口設(shè)置為FIFO接口,數(shù)據(jù)流形式。
solution5: Apply FIFO Interfaces
Step 1 創(chuàng)建solution5,在Directive里給數(shù)組a,b,res插入INTERFACE,在mode里選擇ap_fifo
?
Step 2 Run C Synthesis,Console窗口報(bào)錯(cuò)
評(píng)論