新聞中心

        EEPW首頁 > 網絡與存儲 > 設計應用 > Vivado HLS推動協議處理系統蓬勃發展(下)

        Vivado HLS推動協議處理系統蓬勃發展(下)

        作者:KimonKarras JamesHrica 時間:2015-04-29 來源:電子產品世界 收藏

          5 流分割和合并

        本文引用地址:http://www.104case.com/article/273295.htm

          在協議處理中,根據協議棧特定字段轉發數據包給不同模塊,然后在發送前將不同的流重新組合,是一項關鍵功能。 HLS允許使用高級架構來推動這一轉發過程,具體如例4中所示的流合并。

          例4:簡單的流合并情況

          1 void merge(stream inData[NUM_MERGE_
          STREAMS], stream&outData) {
          2 #pragma HLS INLINE off
          3 #pragma HLS pipeline II=1 enable_flush
          4
          5 static enum mState{M_IDLE = 0, M_STREAM}
          mergeState;
          6 static ap_uint
          rrCtr = 0;
          7 static ap_uint
          streamSource = 0;
          8 axiWord inputWord = {0, 0, 0, 0};
          9
          10 switch(mergeState) {
          11 case M_IDLE:
          12 bool streamEmpty[NUM_MERGE_STREAMS];
          13 #pragma HLS ARRAY_PARTITION variable=stream-
          Empty complete
          14 for (uint8_t i=0;i
          15 streamEmpty[i] = inData[i].empty();
          16 for (uint8_t i=0;i
          17 uint8_t tempCtr = streamSource + 1 + i;
          18 if (tempCtr >= NUM_MERGE_STREAMS)
          19 tempCtr -= NUM_MERGE_STREAMS;
          20 if(!streamEmpty[tempCtr]) {
          21 streamSource = tempCtr;
          22 inputWord = inData[streamSource].
          read();
          23 outData.write(inputWord);
          24 if (inputWord.last == 0)
          25 mergeState = M_STREAM;
          26 break;
          27 }
          28 }
          29 break;
          30 case M_STREAM:
          31 if (!inData[streamSource].empty()) {
          32 inData[streamSource].read(inputWord);
          33 outData.write(inputWord);
          34 if (inputWord.last == 1)
          35 mergeState = M_IDLE;
          36 }
          37 break;
          38 }
          39 }

          本例體現的是模塊合并功能的使用,其中一個流陣列作為輸入(inData),一個單流作為輸出(outData)。這個模塊的功能是以無區別的方式從輸入流讀取數據,然后將讀取的數據輸出給輸出流。該模塊采用雙級FSM實現,其結構與前文介紹的結構一致。

          FSM的第一個狀態用于確保選擇輸入流的無區別性(fairness)。實現的方法是使用循環算法檢查隊列。該算法在完成上一隊列的訪問之后,即從下一隊列起查找新的數據。第17到19行的代碼采用的即是此循環算法。常量NUM_MERGE_STREAMS用于設定待合并的流的數量。接下來的第20行負責測試當前的流,其內容用tempCntr變量標示。如果當前流非空,則將其設置為活躍流(第21行)。然后從該流中讀取數據(第22行)。如果讀取的數據字不是最后一個數據字(由第24行負責檢查),則狀態機進入M_STREAM狀態,然后輸出來自該流的剩余數據字。在處理完成最后一個數據字后,FSM返回M_IDLE狀態,然后重復上述過程。

          這個模塊引入了一個新的編譯指令,稱為“array_partition”。該編譯指令能讓 HLS了解為了提高吞吐量,是否需要把一個陣列拆分為多個子陣列。如果未加設定, HLS會使用雙端口B來訪問陣列。如果要在一個時鐘周期中訪問陣列兩次以上,如果不適當地提高初始化間隔(II)的值,該工具將無法調度這些訪問。在本例中,略去array_partition編譯指令,將NUN_MERGE_STREAMS值設為8,就可以讓II=4。但因為想能夠在每個時鐘周期內訪問steamEmpty陣列的所有元素,讓目標II=1,我們需要對這個陣列進行充分分區。在本例中,該陣列實現為一組基于觸發器的寄存器。

          拆分輸入流的過程耳熟能詳,把來自一個流的數據字正確地路由到一個流陣列即可。

          6 抽取字段和重新對齊字段

          在包處理中,抽取字段和重新對齊字段是最基本的操作之一。由于數據包一般是經過多個時鐘周期內通過總線到達模塊的,常見的情況是需要的字段要么在它們抵達的數據字中未能對齊,要么分散在多個數據字中(往往兩種情況都有)。因此要處理這些字段,必須將它們從數據流中抽取出來,存入緩存然后重新對齊以便處理。

          例5:源MAC地址抽取示例

          1 if (!inData.empty()) {
          2 inData.read(currWord);
          3 switch(wordCount) {
          4 case 0:
          5 MAC_DST = currWord.data.range(47, 0);
          6 MAC_SRC.range(15, 0) = currWord.data.
          range(63, 48);
          7 break;
          8 case 1:
          9 MAC_SRC.range(47 ,16) = currWord.
          data.range(31, 0);
          10 break;
          11 case 2:
          12 ……

          例5是一個非常簡單的字段抽取和再對齊示例。這個示例從以太網報頭中抽取源MAC地址。數據通過稱為“inData”的64位流抵達。在每個時鐘周期讀入數據(第2行)。隨后根據讀取的數據字執行合適的語句。因此在第5行中源MAC地址的頭16位被抽取出來,并移位到MAC_SRC變量的起始部分。在下一時鐘周期中,MAC地址的其余32位抵達總線,然后存入MAC_SRC變量的32位更高位中。

        c++相關文章:c++教程




        關鍵詞: Vivado FIFO 存儲器 RAM C/C++

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 忻城县| 灵川县| 余庆县| 泾阳县| 柘城县| 邢台县| 北票市| 岑巩县| 吉木乃县| 眉山市| 咸阳市| 泾源县| 疏附县| 本溪| 霍州市| 桃园市| 枣强县| 开远市| 深水埗区| 永善县| 澄迈县| 丽水市| 高雄市| 海口市| 吉林省| 阿拉尔市| 米易县| 壶关县| 桑日县| 阿城市| 淅川县| 灯塔市| 封开县| 深泽县| 兰西县| 广丰县| 莱西市| 博白县| 大新县| 丽江市| 黔江区|