在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

數(shù)據(jù)流式編程在硬件設(shè)計中的應(yīng)用

冬至子 ? 來源:Datenlord ? 作者:Datenlord ? 2023-10-31 11:04 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

01、數(shù)據(jù)流式編程的思想

數(shù)據(jù)流式編程思想簡介

數(shù)據(jù)流式編程(Dataflow Programming)是一種存在已久的程序設(shè)計范式,可以追溯到19世紀60年代,由MIT的Jack Dennis教授開創(chuàng)。

圖1 信號處理領(lǐng)域的數(shù)據(jù)流框圖

數(shù)據(jù)流的前身是信號流,如上圖1所示,在信號與系統(tǒng)相關(guān)的領(lǐng)域中,使用信號流框圖來表示模擬信號在一個系統(tǒng)中的處理過程。隨著計算機技術(shù)的發(fā)展,越來越多的模擬系統(tǒng)被數(shù)字系統(tǒng)所取代,連續(xù)的信號也變?yōu)榱穗x散的數(shù)據(jù)。

軟件開發(fā)中的數(shù)據(jù)流式編程思想

在介紹硬件中的數(shù)據(jù)流式編程思想之前,先來看一下軟件中的數(shù)據(jù)流式編程,并了解數(shù)據(jù)流式編程中的幾個基本元素的概念。

動圖封面

圖2 一段LabView編寫的流式數(shù)據(jù)處理軟件程序

在軟件開發(fā)領(lǐng)域,數(shù)據(jù)流式程序的開發(fā)已經(jīng)得到了廣泛的應(yīng)用。其中頗具代表性的是NI公司的LabView軟件以及Mathworks公司的Simulink。如上圖2所示,該圖為LabView可視化開發(fā)環(huán)境中,采用圖形化編程的方式編寫的一個簡易數(shù)據(jù)處理程序。觀察圖2,可以得到數(shù)據(jù)流式程序具有的一些要素:

  • Node:數(shù)據(jù)處理節(jié)點,代表著實際的數(shù)據(jù)處理步驟(如上圖中骰子節(jié)點、節(jié)拍器節(jié)點、4輸入加法器節(jié)點、除法節(jié)點等)
    • Port:分為In和Out兩種類型,一個Node可以具有多個In和Out端口(如除法器就是2輸入1輸出)
  • Source:數(shù)據(jù)源,待處理輸入通過數(shù)據(jù)源進入到程序中(例如上述的骰子節(jié)點,會生成隨機數(shù)輸出,即為一個可以輸出動態(tài)數(shù)據(jù)的Source,而圖中藍色的500、綠色的布爾節(jié)點則可以視為產(chǎn)生靜態(tài)常量的Source)。
  • Sink:數(shù)據(jù)出口,經(jīng)過處理的數(shù)據(jù)經(jīng)過出口輸出(例如上述節(jié)拍器節(jié)點、右下角的紅色停止條件節(jié)點,它們都只有輸入沒有輸出,即接收最終數(shù)據(jù)結(jié)果)。
  • Edge:連接Port與Port的邊,代表數(shù)據(jù)流通的管道

同樣,通過觀察圖2,還可以發(fā)現(xiàn)流式程序的執(zhí)行一些特點:

  • 當一個Node的In端口滿足觸發(fā)條件(例如任意輸入端口有數(shù)據(jù),或所有端口都有數(shù)據(jù)),并且其Out端口不阻塞時(下游Node可以可以接收數(shù)據(jù)),該Node開始執(zhí)行自己的處理邏輯,并將輸出數(shù)據(jù)投遞到對應(yīng)的輸出端口。
  • 反壓的思想貫穿了整個程序的執(zhí)行流程,當下游節(jié)點無法處理新數(shù)據(jù)時,上游節(jié)點的處理過程將被阻塞。
  • 并發(fā)性:每個Node獨立處理自己的邏輯,Node之間是并發(fā)的
  • 層次性:可以將多個Node組成的子系統(tǒng)看做一個黑箱,子系統(tǒng)的Sink和Source作為該黑箱的Port,這樣就可以把子系統(tǒng)看做上層系統(tǒng)的一個Node,從而形成層級結(jié)構(gòu)。

圖3 帶有循環(huán)、條件分支結(jié)構(gòu)的數(shù)據(jù)流式程序

近些年以來,為了實現(xiàn)敏捷化開發(fā)而逐步流行的圖形化拖拽編程、低代碼編程等敏捷開發(fā)方式中,通常都可以看到數(shù)據(jù)流式編程的影子。與DSP領(lǐng)域中的簡單數(shù)據(jù)流思想不同,在軟件開發(fā)領(lǐng)域的數(shù)據(jù)流程序中,通常可以看到條件分支結(jié)構(gòu)和循環(huán)執(zhí)行結(jié)構(gòu)。因此,數(shù)據(jù)流的編程模式是圖靈完備的,不僅可以用于表示簡單的數(shù)據(jù)計算流程,還可以表達復(fù)雜的控制流。

如上圖3所示即為一款兒童編程軟件的示意圖,讀者可以嘗試在上面的圖中找出Source、Sink、Node、Port、Edge這些概念。

軟件數(shù)據(jù)流 vs 硬件數(shù)據(jù)流

軟件實現(xiàn):

數(shù)據(jù)流系統(tǒng)都需要一套調(diào)度框架,所有節(jié)點之間的并行執(zhí)行都是軟件虛擬出來的,節(jié)點是否可以激活的判斷需要框架進行額外的計算,因此性能開銷不能忽略。

硬件實現(xiàn):

硬件天然具有并發(fā)的特性。端口、連線、層級結(jié)構(gòu)、反壓、并發(fā)執(zhí)行這些概念與硬件設(shè)計有著完美的對應(yīng)關(guān)系。事實上,Verilog、VHDL等語言本身也可以被算作是和LabView、Simulink一樣的數(shù)據(jù)流式程序的開發(fā)語言[1]。

數(shù)據(jù)流思想與狀態(tài)機思想的對比

在很多場景下,如果使用狀態(tài)機的思想對硬件行為進行建模,則需要考慮很多狀態(tài)之間的轉(zhuǎn)換關(guān)系,容易造成狀態(tài)爆炸。而是用數(shù)據(jù)流的編程思想,只需要考慮數(shù)據(jù)在兩個節(jié)點之間的傳輸關(guān)系以及各個節(jié)點自己要做的事情,每個節(jié)點各司其職,可以有效降低程序的復(fù)雜度。

下面以AXI4協(xié)議的寫通道握手為例,寫地址通道和寫數(shù)據(jù)通道之間沒有明確的先后依賴順序。

圖4 AXI握手協(xié)議的順序關(guān)系

圖5 一個最簡單的狀態(tài)機握手模型,忽略了其他狀態(tài)

如果以狀態(tài)機的思路來實現(xiàn),是上述圖5這樣的,它是一種順序化執(zhí)行的思維模式,依次進行各個通道上的握手,難以描述并行發(fā)生的事件。如果強行使用狀態(tài)機來描述并發(fā)場景下各種可能的先后順序,則容易導(dǎo)致狀態(tài)爆炸,維護成本高,不夠敏捷。

圖6 基于數(shù)據(jù)流思想的握手模型

如果以數(shù)據(jù)流的思想來實現(xiàn),則如上述圖6所示,4個環(huán)節(jié)之間各自獨立運行,各司其職,兩個輸入通道以及一個輸出通道是獨立模塊,各自可以并行的完成自己的握手,模塊與模塊之間通過Skid Buf(FIFO)進行解耦。可以靈活應(yīng)對各種握手信號到達的先后順序,可以寫出易于維護且吞吐量高的代碼。

02、Bluespec語言及其流式編程框架PAClib

Bluespec SystemVerilog(BSV)和PAClib簡介

Bluespec SystemVerilog是一種高級的函數(shù)式硬件描述語言,由MIT的Arvind教授開發(fā),最初以商業(yè)授權(quán)形式發(fā)布,并于2020年正式開源。

該語言將硬件行為抽象成多個可以并發(fā)運行的Rule,Rule由觸發(fā)邏輯來控制其運行時機,Rule之間、Module之間可以通過FIFO進行通信建模,編譯器會自動生成Module之間的握手和反壓信號(即Rule的觸發(fā)邏輯),從而降低了描述復(fù)雜并行系統(tǒng)的難度,使得它非常適合使用數(shù)據(jù)流的思想進行開發(fā)。

PAClib是Pipelined Architecture Composers library的縮寫,是BSV提供的一個官方庫,可以方便的開發(fā)出基于數(shù)據(jù)流思想設(shè)計的硬件邏輯。

與DSP領(lǐng)域的流式處理相比,PAClib提供了諸如If-Else-Then、While Loop、For Loop、Fork、Join等操作,因此PAClib所提供的數(shù)據(jù)流式編程框架是圖靈完備的,不僅可以用于對復(fù)雜數(shù)據(jù)流邏輯的描述,也可以用于對復(fù)雜控制流的描述。

PAClib中的基礎(chǔ)開發(fā)組件

PACLib中的基礎(chǔ)組件可以看做是流式編程中的各個節(jié)點,為了使用流式編程,需要首先了解各個節(jié)點的功能,然后才能將這些節(jié)點連接起來,從而形成完整的程序。下面首先介紹這些節(jié)點的通用形式,即PAClib中定義的PipeOut接口以及Pipe類型,其定義如下:

interface PipeOut #(type a); 
    method a first ();
    method Action deq ();
    method Bool notEmpty (); 
endinterface


typedef (function Module #(PipeOut #(b)) mkPipeComponent (PipeOut #(a) ifc)) 
    Pipe#(type a, type b);

上述PipeOut接口的形式類似于一個FIFO,即為一條數(shù)據(jù)通道的出口端。Pipe類型本質(zhì)是一個函數(shù),用來把一個PipeOut類型的輸入轉(zhuǎn)換為另一個PipeOut類型的輸出模塊,因此Pipe類型表示了一個連接并轉(zhuǎn)換的概念。

圖7 Pipe類型的圖形化示意

上述圖7可以幫助大家更形象的理解Pipe類型和PipeOut接口,其中整個節(jié)點可以看做是一個Pipe,數(shù)據(jù)從左側(cè)流入,從右側(cè)流出,并在流經(jīng)節(jié)點的過程中被處理(處理的過程在下文介紹)。其中右側(cè)突出的部分是用于和下一個節(jié)點(也就是下一段Pipe)連接的接口,即PipeOut。Pipe和PipeOut類型提供了數(shù)據(jù)流程序中各個節(jié)點的統(tǒng)一接口規(guī)范,所有基于PAClib開發(fā)的處理邏輯都要用這兩個概念進行包裝,從而使得各個節(jié)點之間具有一定的互換性,為架構(gòu)提供了很強的靈活性。

將函數(shù)包裝為Pipe

Pipe類型只是定義了數(shù)據(jù)流經(jīng)過一個節(jié)點前后的數(shù)據(jù)類型,因此還需要具體的邏輯來實現(xiàn)從類型A到類型B的轉(zhuǎn)換。由于函數(shù)的本質(zhì)就是做映射,因此使用函數(shù)來表達對數(shù)據(jù)的加工過程再合適不過了。mkFn_to_Pipe_buffered是一個工具函數(shù),提供了將一個函數(shù)封裝為一個Pipe的能力,其定義如下:

function Pipe #(ta, tb) mkFn_to_Pipe_buffered (Bool paramPre, 
                                               tb fn (ta x), 
                                               Bool paramPost);

圖8 mkFn_to_Pipe_buffered工具函數(shù)所生成的Pipe節(jié)點示意圖

這里的用法也體現(xiàn)出了BSV函數(shù)式編程語言的特性,函數(shù)是語言中的一等公民。事實上,PAClib中對數(shù)據(jù)流模式中各個節(jié)點之間的“連線”也是通過高階函數(shù)的嵌套來實現(xiàn)的。

兩個Bool類型的參數(shù)可以選擇是否在函數(shù)的前后加入FIFO隊列進行緩沖。如果前后兩個FIFO都不開啟,則該節(jié)點表現(xiàn)出組合邏輯的性質(zhì)。開啟FIFO后,則表現(xiàn)出了流水線的性質(zhì)。通過FIFO實現(xiàn)前后級節(jié)點之間的反壓邏輯,自動適應(yīng)不同的數(shù)據(jù)流速。

Map操作

map是函數(shù)式編程中必不可少的一個功能,PAClib中也提供了不同形式的map功能:

  • mkMap用于將Vector中的每一個元素并行地進行處理。
  • mkMap_indexed則在mkMap的基礎(chǔ)之上,額外提供了元素對應(yīng)的索引信息,從而使得用于map的函數(shù)可以獲得關(guān)于被處理數(shù)據(jù)的位置信息。這兩個函數(shù)的定義如下:
function Pipe #(Vector #(n, a),
                Vector #(n, b)) 
         mkMap (Pipe #(a, b) mkP);


function Pipe #(Vector #(n, a),
                Vector #(n, b))
         mkMap_indexed (Pipe #(Tuple2 #(a, UInt #(logn)), b) mkP);

圖9 mkMap節(jié)點的圖形化示意

如上圖9所示,展示了mkMap節(jié)點的示意圖,可以看到圖中用深淺兩種顏色表示了嵌套的Pipe類型,圖中不同Pipe類型的嵌套表示了Node之間的層級關(guān)系,本質(zhì)上是通過高階函數(shù)實現(xiàn)了簡單邏輯的組合。

由于BSV靜態(tài)展開的原因,如果Vector長度較大,則會產(chǎn)生出很多個mkP的實例(mkP實例的數(shù)量與輸入向量的長度相同),占用大量面積。為了減少面積占同,用時間換空間,則可以使用接下來要介紹的節(jié)點。

分批Map操作

PAClib中提供了mkMap_with_funnel_indexed函數(shù)來創(chuàng)建支持分批Map操作的處理節(jié)點,從而可以在面積和吞吐率之間進行取舍,其定定義如下:

function Pipe #(Vector #(nm, a),
                Vector #(nm, b))
         mkMap_with_funnel_indexed (UInt #(m) dummy_m,
                                    Pipe #(Tuple2 #(a, UInt #(lognm)), b) mkP,
                                    Bool param_buf_unfunnel)
         provisos (...);

圖10 mkMap_with_funnel_indexed工具函數(shù)所創(chuàng)建的處理流程

mkMap_with_funnel_indexed函數(shù)實際上是一個工具函數(shù),該工具函數(shù)幫助用戶創(chuàng)建了3個Pipe的組合,其中mkMap節(jié)點已經(jīng)介紹過了,另外兩個節(jié)點分別是mkFunnel_IndexedmkUnfunnel,其定義如下:

function Pipe #(Vector #(nm, a),
                Vector #(m, Tuple2 #(a, UInt #(lognm))))
         mkFunnel_Indexed
         provisos (...);

function Pipe #(Vector #(m, a),
                Vector #(nm, a)) 
         mkUnfunnel (Bool state_if_k_is_1)
         provisos (...);

上述兩個節(jié)點的作用,第一個是將一個較長的向量輸入以指定的長度進行切分,從而產(chǎn)生多個批次的輸出。而第二個是接收多個批次較短的輸入,然后產(chǎn)生一個較長的輸出,即把之前切分的批次重新拼接回來。mkMap_with_funnel_indexed函數(shù)通過上述3個節(jié)點的組合,其實現(xiàn)的最終功能為:

  • 指定一個參數(shù)m,輸入的Vector會被自動切分為多段,每段的長度為m,然后以m長度的切片為單位進行map操作。
  • 在實際設(shè)計中,只需要調(diào)整參數(shù)m的值就可以很方便的在面積和吞吐率之間進行平衡。串并轉(zhuǎn)換功能由框架自動完成,開發(fā)者只需要把精力放在核心的mkP 節(jié)點即可。

節(jié)點的串聯(lián)

上述的mkMap_with_funnel_indexed函數(shù)將3個特定的節(jié)點進行了串聯(lián),從而實現(xiàn)了更加復(fù)雜的邏輯。將簡單節(jié)點進行串聯(lián)是流式編程中必不可少的操作,為了將任意節(jié)點進行串聯(lián),可以使用mkComposemkLinearPipe這兩個函數(shù)實現(xiàn),其定義如下:

function Pipe #(a, c) mkCompose (Pipe #(a, b) mkP, 
                                 Pipe #(b, c) mkQ);

圖11 mkCompose節(jié)點示意圖

function Pipe #(a, a)
         mkLinearPipe_S (Integer n,
                         function Pipe #(a,a) mkStage (UInt #(logn) j));

圖12 mkLinearPipe節(jié)點示意圖

可以看到,mkCompose的作用是將兩個不同的Pipe進行串接,多個mkCompose嵌套使用則可以實現(xiàn)多級的串接。而mkLinearPipe_S是將同一個函數(shù)進行多次調(diào)用,但每次調(diào)用時會傳入不同的參數(shù),從而使得這個函數(shù)可以在不同的調(diào)用位置上表現(xiàn)出不同的行為。

Fork和Join操作

上述介紹的節(jié)點都是對數(shù)據(jù)進行線性操作的節(jié)點,如果只有這樣的節(jié)點是無法實現(xiàn)圖靈完備的數(shù)據(jù)流式程序的,接下來介紹的幾個非線性操作節(jié)點可以使得程序變得圖靈完備。下面從mkForkmkJoin兩個函數(shù)開始介紹:

module mkFork #(function Tuple2 #(b, c) fork_fn (a va),
                PipeOut #(a) poa)
       (Tuple2 #(PipeOut #(b), PipeOut #(c)));
       

module mkJoin #(function c join_fn (a va, b vb),
                PipeOut #(a)       poa,
                PipeOut #(b)       pob )
       (PipeOut #(c));

圖13 mkFork與mkJoin節(jié)點的示意圖

mkForkmkJoin可以創(chuàng)建簡單的并行結(jié)構(gòu),通過用戶自己提供的函數(shù)fork_fn和join_fn,由用戶決定如何將一個輸入數(shù)據(jù)流拆分成2個輸出數(shù)據(jù)流,以及如何把兩個輸入數(shù)據(jù)流合并為一個輸出數(shù)據(jù)流。

對于Join操作而言,要求兩個輸入端口上均存在數(shù)據(jù)時,該Node才可以執(zhí)行操作,如果兩條路徑上處理數(shù)據(jù)所需的時鐘周期數(shù)不一致,則Join節(jié)點會進行等待,直到兩個輸入都有數(shù)據(jù)為止。此外,PAClib中還提供了多種Fork節(jié)點的變種實現(xiàn),可以自行了解。

條件分支操作

使用mkIfThenElse可以創(chuàng)建條件分支,其定義及示意圖如下:

module [Module] mkIfThenElse #(Integer                        latency,
                               Pipe #(a,b)                    pipeT,
                               Pipe #(a,b)                    pipeF,
                               PipeOut #(Tuple2 #(a, Bool))   poa)
                (PipeOut #(b));

圖14 mkIfThenElse節(jié)點示意圖

mkIfThenElse可以實現(xiàn)分支邏輯。輸入數(shù)據(jù)是一個Tuple2#(a, Bool)類型,該節(jié)點會根據(jù)Bool類型的取值將數(shù)據(jù)包路由到pipeT或者pipeF子節(jié)點。其內(nèi)部具有一個FIFO結(jié)構(gòu)用于存儲Token,從而實現(xiàn)在pipeT和pipeF兩個節(jié)點所需處理周期不一致時起到保序的作用。

此外,PAClib中還提供了mkIfThenElse_unordered變種實現(xiàn),當對輸入和輸出之間的數(shù)據(jù)沒有嚴格的順序要求時,可以使用這個變種來簡化設(shè)計。For循環(huán) 使用mkForLoop可以創(chuàng)建條件分支,其定義及示意圖如下:

module [Module] mkForLoop #(Integer                            n_iters,
                            Pipe #(Tuple2 #(a, UInt #(wj)),
                                   Tuple2 #(a, UInt #(wj)))    mkLoopBody,
                            Pipe #(a,b)                        mkFinal,
                            PipeOut #(a)                       po_in)
                (PipeOut #(b))
                provisos (Bits #(a, sa));

圖15 mkForLoop節(jié)點示意圖

mkForLoop需要通過n_iters參數(shù)傳入循環(huán)次數(shù)。在實現(xiàn)邏輯上,Loop Control Logic內(nèi)部有一個共享隊列,外部進入的新數(shù)據(jù)和經(jīng)過循環(huán)體執(zhí)行過一次處理的數(shù)據(jù),都會被放到這個隊列中。

每個新進入的數(shù)據(jù)都會被打上一個Tag,Tag的值為循環(huán)次數(shù),這個Tag伴隨著數(shù)據(jù)在循環(huán)中流動,每流動一次,Tag減一,Loop Control Logic在從共享隊列中取出數(shù)據(jù)時,會根據(jù)Tag的計數(shù)值決定將其送入mkLoopBody節(jié)點還是mkFinal節(jié)點。內(nèi)部有兩條Rule,分別獨立負責(zé)把新數(shù)據(jù)和正在循環(huán)的數(shù)據(jù)放入FIFO中,為循環(huán)提供了內(nèi)在動力(圖中Pump標注路徑)。

注意,由于mkLoopBody也可能是一個需要多拍才能完成的節(jié)點,因此可以有多個數(shù)據(jù)包同時在流水線中進行循環(huán)。

While循環(huán)

在理解了For循環(huán)的實現(xiàn)原理之后,理解While循環(huán)的實現(xiàn)就沒有太大困難了。其定義和示意圖如下:

module [Module] mkWhileLoop #(Pipe #(a,Tuple2 #(b, Bool))  mkPreTest,
                              Pipe #(b,a)                  mkPostTest,
                              Pipe #(b,c)                  mkFinal,
                              PipeOut #(a) po_in)
                (PipeOut #(c))
        provisos (Bits #(a, sa));

圖16 mkWhileLoop節(jié)點示意圖

while循環(huán)的實現(xiàn)需要用戶提供3個處理節(jié)點:

  • mkPreTest子節(jié)點用于執(zhí)行循環(huán)終止條件的判斷
  • mkPostTest子節(jié)點是循環(huán)體要做的處理邏輯
  • mkFinal子節(jié)點是循環(huán)體退出前對數(shù)據(jù)再進行一次修改的機會 其實現(xiàn)邏輯與For循環(huán)類似,都是通過內(nèi)部共享一個隊列來實現(xiàn)的,同時通過兩條Rule來為循環(huán)提供動力。

03、IFFT應(yīng)用實例

需求背景

圖17 一個IFFT數(shù)據(jù)處理流程

以上述圖17中的IFFT變換為例,該流程中有很多平鋪重復(fù)的結(jié)構(gòu),對于不同的應(yīng)用場景,需要在面積、吞吐量之間進行平衡,例如:

  • 組合邏輯實現(xiàn)?還是流水線實現(xiàn)?
  • 幾個不同的stage之間是否可以fold以減少面積?
  • 每個stage內(nèi)部的f_radix4實例是否可以減少?

代碼實現(xiàn)

使用PAClib提供的數(shù)據(jù)流式開發(fā)框架,只需要調(diào)整少量參數(shù)就可以快速調(diào)整系統(tǒng)的計算結(jié)構(gòu)。下面先給出整體代碼,再對其中的各個部分進行解析,可以看到,整體框架的代碼量小于40行(僅包含用于調(diào)度數(shù)據(jù)流的框架代碼,不包含具體的運算邏輯以及注釋):

module [Module] mkIFFT (Server#(IFFTData, IFFTData));
    Bool param_linear_not_looped = False;
    Integer jmax = 2;
    FIFO#(IFFTData) tf < - mkFIFO;

    function Tuple2#(IFFTData, UInt#(6)) stage_d(Tuple2#(IFFTData, UInt#(6)) a);
        return a;
    endfunction

    let mkStage_D = mkFn_to_Pipe (stage_d);

    let s < - mkPipe_to_Server
                ( param_linear_not_looped
                    ? mkLinearPipe_S (3, mkStage_S)
                    : mkForLoop (jmax, mkStage_D, mkFn_to_Pipe (id)));
    return s;
endmodule

function Pipe #(IFFTData, IFFTData) mkStage_S (UInt#(2) stagenum);
    UInt#(1) param_dummy_m = ?;
    Bool param_buf_permuter_output = True;
    Bool param_buf_unfunnel = True;

    function f_radix4(UInt#(2) stagenum, 
                                    Tuple2#(Vector#(4, ComplexSample), UInt#(4)) element);
        return tpl_1(element);
    endfunction

    // ---- Group 64-vector into 16-vector of 4-vectors
    let grouper = mkFn_to_Pipe (group);
    // ---- Map f_radix4 over the 16-vec
    let mapper = mkMap_fn_with_funnel_indexed ( param_dummy_m,
                                                f_radix4 (stagenum),
                                                param_buf_unfunnel);
    // ---- Ungroup 16-vector of 4-vectors into a 64-vector
    let ungrouper = mkFn_to_Pipe (ungroup);
    // ---- Permute it
    let permuter = mkFn_to_Pipe_Buffered (False, f_permute,
                                            param_buf_permuter_output);
    return mkCompose (grouper,
                        mkCompose (mapper,
                                    mkCompose (ungrouper, permuter)));
endfunction

下面來依次解析代碼,首先下面看這一段:

let s < - mkPipe_to_Server
                ( param_linear_not_looped
                    ? mkLinearPipe_S (3, mkStage_S)
                    : mkForLoop (jmax, mkStage_D, mkFn_to_Pipe (id)));

圖18 平鋪結(jié)構(gòu)的IFFT計算架構(gòu)

圖19 折疊結(jié)構(gòu)的IFFT計算架構(gòu)

如上圖18和19所示,只需要修改代碼中的param_linear_not_looped變量,即可以在兩種截然不同的計算架構(gòu)之間進行切換。通過選擇mkLinerPipe_S或者mkForLoop來選擇stage之間是流水線平鋪的方式來實現(xiàn),還是通過Fold的方式來實現(xiàn)。

let mapper = mkMap_fn_with_funnel_indexed ( param_dummy_m,
                                                f_radix4 (stagenum),
                                                param_buf_unfunnel);

圖20 通過參數(shù)調(diào)整計算的并發(fā)度

如上述代碼片段和圖20所示,通過mkMap_fn_with_funnel_indexed函數(shù)的第一個參數(shù)來決定實例化多少個f_radix4計算單元,從而改變計算的并行度。

let permuter = mkFn_to_Pipe_Buffered (False, f_permute,
                                            param_buf_permuter_output);

圖21 在不同位置插入流水線寄存器

如上述代碼片段和圖21所示,通過mkFn_to_Pipe_Buffered函數(shù)的兩個輸入?yún)?shù)來控制是否加入FIFO,從而實現(xiàn)在流水線或組合邏輯之間的切換,使得程序可以在時序上做出簡單的調(diào)整。

return mkCompose (grouper,
                        mkCompose (mapper,
                                    mkCompose (ungrouper, permuter)));

圖22 節(jié)點的串聯(lián)

如上述代碼片段和圖22所示,通過mkCompose可以實現(xiàn)多個Node之間的順序連接。

最終效果

圖23 使用PAClib實現(xiàn)的各種IFFT計算架構(gòu)

在最終效果部分,直接引用Bluespec原始介紹PPT[2]中的一個頁面來進行說明,使用不超過100行代碼,僅需要調(diào)整4個參數(shù),即可實現(xiàn)在24種不同的計算架構(gòu)之間進行切換,這24中計算架構(gòu)在面積和功耗上的差異可以達到10倍以上,用戶可以根據(jù)自己的使用場景靈活的選擇實現(xiàn)方案。

04、寫在最后

從上述示例可以看到數(shù)據(jù)流式的編程思想可以為硬件設(shè)計引入極大的靈活性和可維護性。同時,由于分支節(jié)點、條件節(jié)點、循環(huán)節(jié)點的存在,這種數(shù)據(jù)流式的編程模式是圖靈完備的,因此數(shù)據(jù)流的開發(fā)思想可以用于簡化復(fù)雜的控制通路設(shè)計。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • DSP技術(shù)
    +關(guān)注

    關(guān)注

    2

    文章

    58

    瀏覽量

    28465
  • LabVIEW
    +關(guān)注

    關(guān)注

    1998

    文章

    3670

    瀏覽量

    334948
  • 接收機
    +關(guān)注

    關(guān)注

    8

    文章

    1222

    瀏覽量

    54440
  • VHDL語言
    +關(guān)注

    關(guān)注

    1

    文章

    113

    瀏覽量

    18629
  • 狀態(tài)機
    +關(guān)注

    關(guān)注

    2

    文章

    493

    瀏覽量

    28189
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    labview數(shù)據(jù)流用法注意事項

    數(shù)據(jù)并將該數(shù)據(jù)傳送給數(shù)據(jù)流路徑的下一個節(jié)點。數(shù)據(jù)流經(jīng)節(jié)點的動作決定了程序框圖上VI和函數(shù)的執(zhí)行順序。 使用LabVIEW進行
    發(fā)表于 02-14 11:10

    LabVIEW數(shù)據(jù)流編程基礎(chǔ)

    傳到“減”法函數(shù)后才能執(zhí)行。 節(jié)點只有在所有輸入接線端數(shù)據(jù)準備好后才能執(zhí)行,只有節(jié)點完成執(zhí)行后才能向輸出接線端提供數(shù)據(jù)。  圖1.數(shù)據(jù)流編程
    發(fā)表于 11-20 10:47

    怎么將數(shù)據(jù)流式傳輸?shù)紼4438C

    使用RS232標準。系統(tǒng)需要連續(xù)工作,即系統(tǒng)的作用類似于RF中繼器。我的問題是: - E4438C是否能夠從PC接收流式波形數(shù)據(jù) - 內(nèi)置的任意波形發(fā)生器可以創(chuàng)建流式波形數(shù)據(jù)并輸入FM
    發(fā)表于 04-16 13:10

    怎么通過USB將SPI數(shù)據(jù)流式傳輸?shù)絇C

    千字節(jié)/秒的數(shù)據(jù)結(jié)構(gòu)。現(xiàn)在,我嘗試使用USB套件大容量模式下與UBFS建立數(shù)據(jù)傳輸。用CySalk我可以讀出端點,但是每次我想讀取數(shù)據(jù)時,我都要按下“傳輸
    發(fā)表于 06-19 15:17

    通過Virtex5 FPGA上的SATA連接將數(shù)據(jù)流式傳輸?shù)紿DD或SSD的可行性

    全部:我目前正在探索通過Virtex 5 FPGA上的SATA連接將數(shù)據(jù)流式傳輸?shù)紿DD或SSD的可行性。我很難找到如何做到這一點的示例,或者它是否可行。到目前為止,我已經(jīng)找到
    發(fā)表于 06-02 06:28

    LabVIEW用NI-DAQmx高速數(shù)據(jù)流

    現(xiàn)在直接集成到NI-DAQmx驅(qū)動程序,能夠以最簡單、最快速的方式將數(shù)據(jù)流式傳輸?shù)酱疟P,速率可高達1.2GB/s。NI-DAQmx 9.0或更高版本安裝了一個新的VI,即DAQmxConfigure
    發(fā)表于 06-10 21:08

    數(shù)據(jù)流采集處理的軟硬件接口設(shè)計

    數(shù)據(jù)流采集處理的軟硬件接口設(shè)計:主要介紹了TMS320VC5402(VC5402)與兩片TC1_320AD50C(AD50C)之間通信的軟硬件接口設(shè)計,這種工作方式實現(xiàn)了兩個
    發(fā)表于 10-26 11:04 ?18次下載

    數(shù)據(jù)流編程以及LabVIEW多核編程

    因為NI LabVIEW是數(shù)據(jù)流編程語言,開發(fā)者們可以編寫并行的應(yīng)用程序,這些應(yīng)用程序可以直接映射到并行的硬件(如多核心處理器和FPGA等)上以獲得最優(yōu)異的性能。這篇白皮書討論了什么是數(shù)據(jù)流
    發(fā)表于 11-18 02:39 ?1984次閱讀
    <b class='flag-5'>數(shù)據(jù)流</b><b class='flag-5'>編程</b>以及LabVIEW多核<b class='flag-5'>編程</b>

    基于大數(shù)據(jù)流式計算

    流式計算是大數(shù)據(jù)的一種重要計算模式,大數(shù)據(jù)流式計算已成為研究熱點。任務(wù)管理是大數(shù)據(jù)流式計算的核心功能之一,負責(zé)對流式計算的任務(wù)進行資源調(diào)度及
    發(fā)表于 11-22 17:34 ?1次下載
    基于大<b class='flag-5'>數(shù)據(jù)</b>的<b class='flag-5'>流式</b>計算

    數(shù)據(jù)流編程模型優(yōu)化

    提出了新的挑戰(zhàn)。針對數(shù)據(jù)流程序分布式架構(gòu)下所面臨的問題,設(shè)計并實現(xiàn)了數(shù)據(jù)流編程模型和分布式計算框架的結(jié)合在COStream的基礎(chǔ)上提出了面向Storm的編譯優(yōu)化框架。框架包括兩個模塊
    發(fā)表于 11-23 15:48 ?3次下載
    <b class='flag-5'>數(shù)據(jù)流</b><b class='flag-5'>編程</b>模型優(yōu)化

    基于實時車牌識別數(shù)據(jù)流的套牌車流式并行檢測方法

    模型,能夠?qū)崟r地甄別出交通數(shù)據(jù)流的套牌嫌疑車。Storm環(huán)境下,利用某市真實交通數(shù)據(jù)集模擬成實時交通流數(shù)據(jù)進行實驗和評估,實驗結(jié)果表明計
    發(fā)表于 12-07 15:02 ?0次下載
    基于實時車牌識別<b class='flag-5'>數(shù)據(jù)流</b>的套牌車<b class='flag-5'>流式</b>并行檢測方法

    數(shù)據(jù)流是什么

    數(shù)據(jù)流最初是通信領(lǐng)域使用的概念,代表傳輸中所使用的信息的數(shù)字編碼信號序列。然而,我們所提到的數(shù)據(jù)流概念與此不同。這個概念最初1998年由Henzinger文獻87
    的頭像 發(fā)表于 02-27 15:25 ?7433次閱讀

    Labview數(shù)據(jù)流編程的簡單介紹

    Labview數(shù)據(jù)流編程基本概念視頻教學(xué)
    的頭像 發(fā)表于 08-05 06:05 ?4398次閱讀

    使用Edison、Pi等將傳感器數(shù)據(jù)流式傳輸?shù)絆ctoblu

    電子發(fā)燒友網(wǎng)站提供《使用Edison、Pi等將傳感器數(shù)據(jù)流式傳輸?shù)絆ctoblu.zip》資料免費下載
    發(fā)表于 06-13 14:47 ?0次下載
    使用Edison、Pi等將傳感器<b class='flag-5'>數(shù)據(jù)流式</b>傳輸?shù)絆ctoblu

    流式圖計算TuGraph-Analytics技術(shù)背后的故事和技術(shù)特性

    流式計算針對流式動態(tài)變化的數(shù)據(jù)流,一般動態(tài)的數(shù)據(jù)流有實時的日志流,或者數(shù)據(jù)庫的變化日志,主要是為了場景
    的頭像 發(fā)表于 06-28 11:34 ?1380次閱讀
    <b class='flag-5'>流式</b>圖計算TuGraph-Analytics技術(shù)背后的故事和技術(shù)特性
    主站蜘蛛池模板: 仙踪林欧美另类视频 | 在线二区| 欧美日剧在线免费 | 国产视频一区二区在线观看 | 亚洲伊人久久大香线蕉影院 | 午夜国产精品免费观看 | 三级不卡 | 亚洲香蕉久久一区二区三区四区 | 青楼社区51在线视频视频 | 精品日韩一区二区三区 | 天天色天天舔 | 在线看欧美成人中文字幕视频 | 欧美一级日韩在线观看 | 欧美二区三区 | 男人天堂黄色 | 狠狠色婷婷丁香综合久久韩国 | 亚洲综合在线最大成人 | 日本免费精品视频 | 4438x成人免费 | 正在播放羽月希与黑人bd在线 | 亚洲国产第一区二区香蕉 | 久久国产热 | 免费一级毛片在级播放 | 五月天婷婷激情 | 欧美在线视频一区二区三区 | 国产三级在线免费 | 青草青草视频2免费观看 | 你懂得网址在线观看 | 婷婷六 | 成人性生活免费视频 | 福利在线看 | 亚洲第一伊人 | aaaaa级毛片免费视频 | 精品欧美小视频在线观看 | 亚洲六月丁香六月婷婷花 | 天天插天天插天天插 | 国产精品三级在线 | 亚洲一二三四区 | 欧美午夜寂寞影院安卓列表 | 在线麻豆国产传媒60在线观看 | 天天做天天爱天天大综合 |