FC2カウンター FPGAの部屋 2020年01月21日
FC2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

Vivado HLS 2019.2 で krnl_dma_read を作成する1(ソースコードの表示)

Vitis のカーネル間ストーミング接続をテストするために DMA Read カーネル ー ラプラシアン・フィルタ・カーネル ー DMA Write カーネルをストーミング接続してみよう。
今回は、DMA Read カーネルを作成しよう。

ストーミング接続用のhls::stream の定義は、hls::stream<ap_axiu<32,0,0,0> > にする必要がある。こうするとサイドチャネルの信号は last と keep , strb だけになる。この内の last を使用して、フレームの最後をマークしよう。
ストーミング接続用 DMA Read カーネルの krnl_dma_read.cpp を示す。
なお、C シミュレーションできないので、とりあえず extern "C" { } は外してある。

// krnl_dma_read.cpp
// 2020/01/21 by marsee

#include <stdint.h>
#include <ap_int.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>

//extern "C" {
void dma_read(volatile int32_t *inm, hls::stream<ap_axiu<32,0,0,0> >& outs, int32_t x_size, int32_t y_size){
#pragma HLS INTERFACE s_axilite port=return bundle=control
#pragma HLS INTERFACE s_axilite port=y_size bundle=control
#pragma HLS INTERFACE s_axilite port=x_size bundle=control
#pragma HLS INTERFACE axis register both port=outs
#pragma HLS INTERFACE m_axi depth=3072 port=inm offset=slave bundle=gmem

    ap_axiu<32,0,0,0> pix;

    LOOP_DRY: for(int y=0; y<y_size; y++){
#pragma HLS LOOP_TRIPCOUNT min=48 max=600
        LOOP_DRX: for(int x=0; x<x_size; x++){
#pragma HLS LOOP_TRIPCOUNT min=64 max=800
#pragma HLS PIPELINE II=1
            pix.data = inm[x_size*y+x];

            if(x==(x_size-1) && y==(y_size-1))
                pix.last = 1;
            else
                pix.last = 0;
            outs << pix;
        }
    }
}
//}


テストベンチの krnl_dma_read_tb.cpp を示す。

// krnl_dma_read_tb.cpp
// 2020/01/21 by marsee

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <ap_int.h>
#include <hls_stream.h>
#include <iostream>
#include <fstream>
#include <ap_axi_sdata.h>
#include "bmp_header.h"

void dma_read(volatile int32_t *inm, hls::stream<ap_axiu<32,0,0,0> >& outs, int32_t x_size, int32_t y_size);

int main(){
    BITMAPFILEHEADER bmpfhr; // BMPファイルのファイルヘッダ(for Read)
    BITMAPINFOHEADER bmpihr; // BMPファイルのINFOヘッダ(for Read)
    FILE *fbmpr, *fbmpw;
    int32_t *rd_bmp, *dmar;
    int32_t blue, green, red;
    hls::stream<ap_axiu<32,0,0,0> > outs;
    ap_axiu<32,0,0,0> vals;

    if ((fbmpr = fopen("test.bmp", "rb")) == NULL){ // test.bmp をオープン
        fprintf(stderr, "Can't open test.bmp by binary read mode\n");
        exit(1);
    }
    // bmpヘッダの読み出し
    fread(&bmpfhr.bfType, sizeof(uint16_t), 1, fbmpr);
    fread(&bmpfhr.bfSize, sizeof(uint32_t), 1, fbmpr);
    fread(&bmpfhr.bfReserved1, sizeof(uint16_t), 1, fbmpr);
    fread(&bmpfhr.bfReserved2, sizeof(uint16_t), 1, fbmpr);
    fread(&bmpfhr.bfOffBits, sizeof(uint32_t), 1, fbmpr);
    fread(&bmpihr, sizeof(BITMAPINFOHEADER), 1, fbmpr);

    // ピクセルを入れるメモリをアロケートする
    if ((rd_bmp =(int32_t *)malloc(sizeof(int32_t) * (bmpihr.biWidth * bmpihr.biHeight))) == NULL){
        fprintf(stderr, "Can't allocate rd_bmp memory\n");
        exit(1);
    }
    if ((dmar =(int32_t *)malloc(sizeof(int32_t) * (bmpihr.biWidth * bmpihr.biHeight))) == NULL){
        fprintf(stderr, "Can't allocate hw_lapd memory\n");
        exit(1);
    }

    // rd_bmp にBMPのピクセルを代入。その際に、行を逆転する必要がある
    for(int y=0; y<bmpihr.biHeight; y++){
        for(int x=0; x<bmpihr.biWidth; x++){
            blue = fgetc(fbmpr);
            green = fgetc(fbmpr);
            red = fgetc(fbmpr);
            rd_bmp[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] = (int32_t)((blue & 0xff) | ((green & 0xff)<<8) | ((red & 0xff)<<16));
        }
    }
    fclose(fbmpr);

    dma_read(rd_bmp, outs, bmpihr.biWidth, bmpihr.biHeight);

    // DMAされた値のチェック
    for(int y=0; y<bmpihr.biHeight; y++){
        for(int x=0; x<bmpihr.biWidth; x++){
            outs >> vals;
            dmar[(y*bmpihr.biWidth)+x] = (int32_t)vals.data;
            if ((int32_t)vals.data != rd_bmp[(y*bmpihr.biWidth)+x]){
                printf("ERROR HW and SW results mismatch x = %ld, y = %ld, DMAR = %d, ORG = %d\n", x, y, (int)vals.data, (int)rd_bmp[(y*bmpihr.biWidth)+x]);
                return(1);
            }
        }
    }
    std::cout << "Success DMA READ results match" << std::endl;
    std::cout << std::endl;


    // DMA_Read の結果を dma_read.bmp へ出力する
    if ((fbmpw=fopen("dma_read.bmp", "wb")) == NULL){
        fprintf(stderr, "Can't open temp_lap.bmp by binary write mode\n");
        exit(1);
    }
    // BMPファイルヘッダの書き込み
    fwrite(&bmpfhr.bfType, sizeof(uint16_t), 1, fbmpw);
    fwrite(&bmpfhr.bfSize, sizeof(uint32_t), 1, fbmpw);
    fwrite(&bmpfhr.bfReserved1, sizeof(uint16_t), 1, fbmpw);
    fwrite(&bmpfhr.bfReserved2, sizeof(uint16_t), 1, fbmpw);
    fwrite(&bmpfhr.bfOffBits, sizeof(uint32_t), 1, fbmpw);
    fwrite(&bmpihr, sizeof(BITMAPINFOHEADER), 1, fbmpw);

    // RGB データの書き込み、逆順にする
    for (int y=0; y<bmpihr.biHeight; y++){
        for (int x=0; x<bmpihr.biWidth; x++){
            blue = dmar[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] & 0xff;
            green = (dmar[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] >> 8) & 0xff;
            red = (dmar[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x]>>16) & 0xff;

            fputc(blue, fbmpw);
            fputc(green, fbmpw);
            fputc(red, fbmpw);
        }
    }
    fclose(fbmpw);
    free(rd_bmp);
    free(dmar);

    return(0);
}


bmp_header.h を示す。

// bmp_header.h
// BMP ファイルフォーマットから引用させて頂きました
// http://www.kk.iij4u.or.jp/~kondo/bmp/
//
// 2017/05/04 : takseiさんのご指摘によりintX_tを使った宣言に変更。takseiさんありがとうございました
//              変数の型のサイズの違いによってLinuxの64ビット版では動作しなかったためです
//              http://marsee101.blog19.fc2.com/blog-entry-3354.html#comment2808
//

#include <stdio.h>
#include <stdint.h>

// BITMAPFILEHEADER 14bytes
typedef struct tagBITMAPFILEHEADER {
    uint16_t bfType;
    uint32_t bfSize;
    uint16_t bfReserved1;
    uint16_t bfReserved2;
    uint32_t bfOffBits;
} BITMAPFILEHEADER;

// BITMAPINFOHEADER 40bytes
typedef struct tagBITMAPINFOHEADER{
    uint32_t biSize;
    int32_t biWidth;
    int32_t biHeight;
    uint16_t biPlanes;
    uint16_t biBitCount;
    uint32_t biCompression;
    uint32_t biSizeImage;
    int32_t biXPixPerMeter;
    int32_t biYPixPerMeter;
    uint32_t biClrUsed;
    uint32_t biClrImporant;
} BITMAPINFOHEADER;

typedef struct BMP24bitsFORMAT {
    uint8_t blue;
    uint8_t green;
    uint8_t red;
} BMP24FORMAT;

  1. 2020年01月21日 05:39 |
  2. Vitis
  3. | トラックバック:0
  4. | コメント:0