ひでみのアイデア帳

くだらないことなんだけど、忘れないために・・・

SystemVerilogのお勉強(2−2)

ZynqのPSからのPL制御を考えてみた。

普段、テストベンチレベルではPSからPLへのアクセスは/dev/mem開いて直接制御しちゃいます。

なので、面倒に感じるのかもしれませんが次のよう間にラッパーをかましてしまえば、上位テストアプリは共通化で、SystemVerilogでも安易にアクセスできそうです。

これは一例ってことで・・・

関数名 概要
hw_open デバイスのオープン
hw_read データの読込み
hw_write データの書込み
hw_close デバイスのクローズ

hw_open関数

fd = hw_open(FILE, address);

PLデバイスをオープンします。 関数内部では次のように処理します。

#if 実機環境
fd = open("/dev/mem", O_RDWR | O_SYNC );
if( fd == -1 ){
  return -1;
}
base = mmap(NULL, MAP_LENG, PROT_READ | PROT_WRITE, MAP_SHARED, fd, address & 0xFFFF0000);
if( addr == MAP_FAILED ){
  return -1;
}
base_table[fd] = base;
return fd;
#else SystemVerilog環境
base_table[fd] = address;
return fd;
#end

関数内部でbaseを持つってことは、グルーバル配列でテーブルを保持させます。

hw_read

size = hw_read(fd, address, data, size);

データの読込みではfdに該当するベースアドレスからデータの読込みを行います。

#if 実機環境
base = base_table(fd);
offset = base - address;
for(i=0;i<size;i++){
  data[i] = base[i];
}
#else SystemVerilog環境
base = table_base(fd);
for(i=0;i<size;i++){
  data[i] = sv_read(base+i);
}
#end

hw_write

size = hw_write(fd, address, data, size);

データの書込みではfdに該当するベースアドレスにデータを書き込みます。

#if 実機環境
base = base_table(fd);
offset = base - address;
for(i=0;i<size;i++){
  base[i] = data[i];
}
#else SystemVerilog環境
base = table_base(fd);
for(i=0;i<size;i++){
  sv_write(base+i, data[i]);
}
#end

hw_close

result = hw_close(fd);

クローズはmmapを開放して、closeします。

#if 実機環境
base = base_table[fd];
munmap(base, MAP_LENG);
close(fd);
#else SystemVerilog環境
table_base[fd]を破棄する
#end

まとめ

こうしておいて、おけば、上位層は同じままで作れるよね。

SystemVerilogのtaskの動かし方はSystemVerilog側で細工しておくと・・・

でも、まだ試していないので動作するかは不明・・・