AWS F1インスタンス HDK の勉強を続けている。 遅いながらにどうにか進めている。cl_dram_dma についてなんとなく分かってきた。 前回はアサーションを追加してAXIバスが動作していることを確認した。
次はAXIをどうにか動かすことはできないだろうか?目標としてはCLモジュール内に新しいAXIマスタを作成して内部からDRAMにアクセスできるパスを作りたい。
目標としては、以下の部分にAXIマスタを接続してDRAMにアクセスし、データをフェッチする。
- DMAでホストからデータをDDR4メモリに格納する。
- AXIマスタデータをフェッチする
- 演算し、結果を格納する。
として、例えば行列積のアクセラレータをF1インスタンス上で動作させてみたい。
まずはテストベクタを作成して、DDR4メモリに対して自由にデータを読み書きしてみよう。
test_dram_matrix テストベクタの作成
サンプルプロジェクトとしてtest_dram_dmaをコピーしてtest_dram_matrix を作成した。これは、
$readmemh
で整数行列(16×16)を2つ分、DRAMにロードする- CLに通知し、同じ場所からデータをフェッチする(という回路を作成する)
- フェッチしたデータを使って行列積を計算し、計算結果をDRAMに格納する
というシナリオだ。
とりあえず書きかけのコードだが、githubに開発中のものをアップロードしている。
readmemh
をしているのは以下で、16×16のデータをまずはローカルメモリに読み込む。
initial begin $readmemh ("datasets1.txt", datasets1); $readmemh ("datasets2.txt", datasets2); end
次に、データをDMAでDDR4に転送する。tb.que_buffer_to_cl
、tb.hm_put_byte
、tb.start_que_to_cl
を使って転送する。
行列1はchannel0、行列1はchannel1を使って転送する。
//Queue data to be transfered to CL DDR tb.que_buffer_to_cl(.chan(0), .src_addr(host_memory_buffer_address), .cl_addr(64'h0000_0004_0000_0000), .len(matrix_size) ); // move buffer to DDR 0 // Put test pattern in host memory for (int i = 0 ; i < matrix_size / 4 ; i++) begin tb.hm_put_byte(.addr(host_memory_buffer_address+0), .d(datasets1[i][ 7: 0])); tb.hm_put_byte(.addr(host_memory_buffer_address+1), .d(datasets1[i][15: 8])); tb.hm_put_byte(.addr(host_memory_buffer_address+2), .d(datasets1[i][23:16])); tb.hm_put_byte(.addr(host_memory_buffer_address+3), .d(datasets1[i][31:24])); host_memory_buffer_address+=4; end host_memory_buffer_address = 64'h0_0001_0000; tb.que_buffer_to_cl(.chan(1), .src_addr(host_memory_buffer_address), .cl_addr(64'h0000_0004_0001_0000), .len(matrix_size) ); // move buffer to DDR 1 for (int i = 0 ; i < matrix_size / 4 ; i++) begin tb.hm_put_byte(.addr(host_memory_buffer_address+0), .d(datasets2[i][ 7: 0])); tb.hm_put_byte(.addr(host_memory_buffer_address+1), .d(datasets2[i][15: 8])); tb.hm_put_byte(.addr(host_memory_buffer_address+2), .d(datasets2[i][23:16])); tb.hm_put_byte(.addr(host_memory_buffer_address+3), .d(datasets2[i][31:24])); host_memory_buffer_address+=4; end ... //Start transfers of data to CL DDR tb.start_que_to_cl(.chan(0)); tb.start_que_to_cl(.chan(1)); do begin status[0] = tb.is_dma_to_cl_done(.chan(0)); status[1] = tb.is_dma_to_cl_done(.chan(1)); #10ns; timeout_count++; end while ((status != 4'hf) && (timeout_count < 4000));
次に、CLに対してデータフェッチをトリガするのは以下だ。CLバス経由で0x500のアドレスに対して1を書き込む。これをCL側のデータフェッチのトリガ信号としよう。
tb.poke(.addr(32'h0500), .data(32'h1), .size(DataSize::UINT16), .intf(AxiPort::PORT_OCL)); // write register
CL側の記述
CL側のハードウェア構成はファブリックのS1はデフォルトでTie offされており、自由に使用できる、のように書いてあるが実際にはATGのバスが接続されている。 これは取り外して良いのだろうか?とりあえず使わないのであれば外してしまってもよい気がしている。
/////////////////////////////////////////////////////////////////////// ///////////////// Secondary AXI Master module ///////////////////////// /////////////////////////////////////////////////////////////////////// // cl_dram_dma_axi_mstr CL_DRAM_DMA_AXI_MSTR ( // .aclk(clk), // .aresetn(dma_pcis_slv_sync_rst_n), // .cl_axi_mstr_bus(cl_axi_mstr_bus), // .axi_mstr_cfg_bus(axi_mstr_cfg_bus) // );
その代わりに、空いたcl_axi_mstr_bus
に対してAXIマスタを接続した。とりあえず、DRAMのデータを書き込んだところに対してデータフェッチを行う記述だ。
- cl_dram_dma.sv
case (state) state_init: begin if (axi_mstr_cfg_bus.wr && axi_mstr_cfg_bus.addr[ 7: 0] == 8'h00 && !cl_axi_mstr_bus.arvalid) begin cl_axi_mstr_bus.arvalid <= 1'b1; cl_axi_mstr_bus.araddr <= 64'h0000_0004_0000_0000; cl_axi_mstr_bus.arid <= 16'b0; // Only 1 outstanding command cl_axi_mstr_bus.arlen <= 8'h00; // Always 1 burst cl_axi_mstr_bus.arsize <= 3'b111; // Always 128 bytes end if (cl_axi_mstr_bus.arvalid && cl_axi_mstr_bus.arready) begin cl_axi_mstr_bus.arvalid <= 1'b0; state <= state_row; end end state_row: begin cl_axi_mstr_bus.arvalid <= 1'b1; cl_axi_mstr_bus.araddr <= 64'h0000_0004_0001_0004; cl_axi_mstr_bus.arid <= 16'b0; // Only 1 outstanding command cl_axi_mstr_bus.arlen <= 8'h00; // Always 1 burst cl_axi_mstr_bus.arsize <= 3'b010; // Always 4 bytes state <= state_col; end state_col: begin if (cl_axi_mstr_bus.arready) begin if (col_counter <= 15) begin cl_axi_mstr_bus.arvalid <= 1'b1; cl_axi_mstr_bus.araddr <= cl_axi_mstr_bus.araddr + 64; // Proceed 64-byte state <= state_col; col_counter <= col_counter + 6'h1; end else begin cl_axi_mstr_bus.arvalid <= 1'b0; state <= state_init; end cl_axi_mstr_bus.arid <= 16'b0; // Only 1 outstanding command cl_axi_mstr_bus.arlen <= 8'h00; // Always 1 burst cl_axi_mstr_bus.arsize <= 3'b010; // Always 4 bytes end // if (cl_axi_mstr_bus.arready) end // case: state_col endcase // case (state)
cl_axi_mstr_bus
に対するデータロガーも接続して動作を観察しておく。
always @ (negedge clk) begin if (cl_axi_mstr_bus.awvalid & cl_axi_mstr_bus.awready) begin $display ("%t : [cl_axi_mstr_bus AW] LEN=%d SIZE=%d ADDR=%x", $time, cl_axi_mstr_bus.awlen, cl_axi_mstr_bus.awsize, cl_axi_mstr_bus.awaddr); end if (cl_axi_mstr_bus.arvalid & cl_axi_mstr_bus.arready) begin $display ("%t : [cl_axi_mstr_bus AR] LEN=%d SIZE=%d ADDR=%x", $time, cl_axi_mstr_bus.arlen, cl_axi_mstr_bus.arsize, cl_axi_mstr_bus.araddr); end if (cl_axi_mstr_bus.wvalid & cl_axi_mstr_bus.wready) begin $display ("%t : [cl_axi_mstr_bus W] STB=%x DATA=%x", $time, cl_axi_mstr_bus.wstrb, cl_axi_mstr_bus.wdata); end if (cl_axi_mstr_bus.rvalid & cl_axi_mstr_bus.rready) begin $display ("%t : [cl_axi_mstr_bus R] DATA=%x", $time, cl_axi_mstr_bus.rdata); end end // always @ (negedge clk)
これで動作を見てみた。 めっちゃ時間はかかるが、どうやらちゃんとDRAMにアクセスしてデータをフェッチできたみたいだ。
[ 33462000] : Initializing buffers [ 33462000] : starting H2C DMA channels 33474000 : [sh_cl_dma AW] LEN= 15 SIZE=6 ADDR=0000000400000000 33474000 : [sh_cl_dma W] STB=ffffffffffffffff DATA=efe3be658f3f3b25123b5fef95d0dbf2eeee6b4b49aa9135f25b09fb79da57bd9ea0db5f4ea6d904e1ef3abb5e3cf5d888d272fbb6f7bafe70ef716ea7feef1a 33482000 : [sh_cl_dma W] STB=ffffffffffffffff DATA=cdeb2996cebedacc06c3d8fe51fdf3420225cefba9cf9fddee6ffa0fa70bfa0febbc9e3dfb1ebaee5b0d21dee4a10ee92989facf78cd9b379abb719bcf2a0eea 33490000 : [sh_cl_dma AW] LEN= 15 SIZE=6 ADDR=0000000400010000 33494000 : [sh_cl_dma W] STB=ffffffffffffffff DATA=2404db84ad6199a6c37abe9c7cf482e9be6d67ccd40f64cdf2e9e4c8267a7f297bd88dbca72faa04fbbed32f24e1eac3ad3cbfcc9d2ed1a050df8a68b92d4b99 33498000 : [sh_cl_dma W] STB=ffffffffffffffff DATA=acb3f8a6a6de5ddc950d8cade9d6b9daafb96ebae1a1a4bcc8a2a24ffc9eb0f4bd38e6d75ce4703f7b0ce090d25c7e52be7d3ab7f3a5d0a93eaafe1c2db7c5cf 33506000 : [sh_cl_dma W] STB=ffffffffffffffff DATA=43bdcf1cba9bccd0d2b8d5e6cbb3dd51fed2553af9541b01230b7fb12bacb2b4c8fcea96b23ea5b1dd4086c9ffdecb8fbfcab8ba2e6b5d99591a5c93aad1e4be 33514000 : [sh_cl_dma W] STB=ffffffffffffffff DATA=908a71bc8e2dbc6dc818d823af24f74cb42dedb33e8cccfe42e84bde682cb56a76aa5c78a7e1b20cdb263f68a76f2ac8576cedf6dbde1ff9ccd61b8d2d2a29a3 33522000 : [sh_cl_dma W] STB=ffffffffffffffff DATA=3db619aceddb35fddeefcb6ea8b1a6ae36ff7cb5b55fb2230eba5eea09f559b119319c8fe28ff36feb437cc792fc6498b1dbad5ae492cce7bef8aea48ff4f4ba 33530000 : [sh_cl_dma W] STB=ffffffffffffffff DATA=59716bea2d1e4dbfc6fbb8abfaea0e16aabdc9cdfedac4eb9f3bef10a9ad4fd48b98eadd8d00eefbda36ddbddfd1cbafde8674437efc2b354fe87ac7c1083fc9 33538000 : [sh_cl_dma W] STB=ffffffffffffffff DATA=fa8c09af8ccb49e6fb7c8e54d30be8e2a23cfe69ccbd9ccb40debf5acddbd0bafcfaae244eeca080fc4deb95d44cd9723b7fe462f7feb21cebf54e9b3c6f6beb 33546000 : [sh_cl_dma W] STB=ffffffffffffffff DATA=a8df1175cc16bae62bec11411a14e41e532fb6f433f32d3be0cadc320942237d72afdcb1a1c33c0f6f2fa8c40000dd7bfafcf3b0aaec9cbbbaafe33c6f5e31bb 33554000 : [sh_cl_dma W] STB=ffffffffffffffff DATA=ddd631659ffe89ea783a31c9a4bf1cdcd89ee92f5cf3acd7fae2dc1eb2abdb5d3ffdec13b8380fadefbf7eea9a67bf1bdcdefd275ae5ba8c29aaa545eda4eb4f 33562000 : [sh_cl_dma W] STB=ffffffffffffffff DATA=26a3c6cd3fa9d0bdfbb2c08ad72de5c0ca0fd8d00bfa9bb4cef194abe7c28fc4e07029fedd9c22acfe3fa16b01cb140ec8d1e5a8caecbbdfeb9c0c0dd0faf13d 33570000 : [sh_cl_dma W] STB=ffffffffffffffff DATA=ceddd41b08ab61bded11af8bb27654fbaa4b105dc8f61b16eeaff71c19cb6b7be8ee39273ca94dcf650fdd76287ef63bdb6dd0fad249cf8c9a689401c3d5bbbe ... [ 33732000] : starting C2H DMA channels Writing 0xDEAD_BEEF to address 0x00000500 34762000 : [axi_mstr_cfg_bus W] ADDR=00000500 34766000 : [cl_axi_mstr_bus AR] LEN= 0 SIZE=7 ADDR=0000000400000000 34766000 : [axi_mstr_cfg_bus W] ADDR=00000500 34782000 : [cl_axi_mstr_bus AR] LEN= 0 SIZE=2 ADDR=0000000400010004 34798000 : [cl_axi_mstr_bus AR] LEN= 0 SIZE=2 ADDR=0000000400010044 34814000 : [cl_axi_mstr_bus AR] LEN= 0 SIZE=2 ADDR=0000000400010084 34830000 : [cl_axi_mstr_bus AR] LEN= 0 SIZE=2 ADDR=00000004000100c4 34846000 : [cl_axi_mstr_bus AR] LEN= 0 SIZE=2 ADDR=0000000400010104 34862000 : [cl_axi_mstr_bus AR] LEN= 0 SIZE=2 ADDR=0000000400010144 34878000 : [cl_axi_mstr_bus AR] LEN= 0 SIZE=2 ADDR=0000000400010184 34894000 : [cl_axi_mstr_bus AR] LEN= 0 SIZE=2 ADDR=00000004000101c4 34910000 : [cl_axi_mstr_bus AR] LEN= 0 SIZE=2 ADDR=0000000400010204 34926000 : [cl_axi_mstr_bus AR] LEN= 0 SIZE=2 ADDR=0000000400010244 34942000 : [cl_axi_mstr_bus AR] LEN= 0 SIZE=2 ADDR=0000000400010284 34958000 : [cl_axi_mstr_bus AR] LEN= 0 SIZE=2 ADDR=00000004000102c4 34974000 : [cl_axi_mstr_bus AR] LEN= 0 SIZE=2 ADDR=0000000400010304 34986000 : [cl_axi_mstr_bus R] DATA=efe3be658f3f3b25123b5fef95d0dbf2eeee6b4b49aa9135f25b09fb79da57bd9ea0db5f4ea6d904e1ef3abb5e3cf5d888d272fbb6f7bafe70ef716ea7feef1a 34990000 : [cl_axi_mstr_bus AR] LEN= 0 SIZE=2 ADDR=0000000400010344 34994000 : [cl_axi_mstr_bus R] DATA=a622eeadfbdeae582fc8a39e30bacd0ac9daba51caadfdff7dab21b8740b152c2493f4fabeaa3bef8eaeeb3bcd7941a978ffa3fec942a985b0ce9b1de998efbf 35006000 : [cl_axi_mstr_bus AR] LEN= 0 SIZE=2 ADDR=0000000400010384 35014000 : [cl_axi_mstr_bus R] DATA=28eacbe767f7f34ff42e9a5c4de1cec44fbe9bcecc064db7fcf1a0f3b234c6d1f26cb0fdf3524d8bcdb917fbb91b4efcea83dfa8a7e5c1ebb12ce8ccdaaf6c4f 35022000 : [cl_axi_mstr_bus AR] LEN= 0 SIZE=2 ADDR=00000004000103c4 35026000 : [cl_axi_mstr_bus R] DATA=68f25ebf12cc8f5daea31cd4bd2bc9c64cbb656cc918a8bf2afdb3e8b25cedc4c65584db1fecd041fc5a124f93babe1ecd89fcba9edd802918bd676a0ac560cc 35038000 : [cl_axi_mstr_bus AR] LEN= 0 SIZE=2 ADDR=0000000400010404 35046000 : [cl_axi_mstr_bus R] DATA=1cadddac5ca664b3740e3fd2f5caf9ae1e5fb3e99ca3d0c3b2b8a2ff100e75febb65b131e40daef7b95ab6c8f6a5d4e5fff319b6cb208f4aeaeeb108b3ff1fb4 35050000 : [cl_axi_mstr_bus R] DATA=1efd6a41ceaf3ff86fdfdbf6b5ab2b1d9258660912ebf13944cd0387bdf9eee5c67a911a7ed6887c48edde0ec87faebae3bd46dc31636a7d5b06e9af5be4787f 35058000 : [cl_axi_mstr_bus R] DATA=7cadeaa3470d2f7e3fb1dcbf0fb5ca57d492d6c238b8ffe2a2eefc8cc2dbabdfb66568e5fa704caafc31d0dc1e9ebbb327c5b21fcdf3193d5ab2b53243b1ebfc 35074000 : [cl_axi_mstr_bus R] DATA=b301cea0c9bbde7c2594f2f3b7ad0b61ac9b2bd19ca2c9c081d0ce61e6c8cc2cd2d624785a9ea4d49dd3dd5266cd1b1c3d3bc3265cd941fc361aafc26ac2edbd 35090000 : [cl_axi_mstr_bus R] DATA=0def5d1ebb3f453e61ff7ea314e1abaafb6ffcbcae48681feb742569fe267bf18b2abbb1bf1b42dbb059cdb0d8b9bd05a531e78dd7af7d31bc2e08af5ff1f365