FC2ブログ

SystemC coding note by using stratus

- .h file
-- SC_MODULE(モジュール名){ IO プロセス コンストラクタ }; が基本構成です。

-- #include <systemc.h> は不必要で、代わりに#include <stratus_hls.h> を使います。

-- IO
入力は sc_in< データタイプ >、出力は sc_out< データタイプ >、プロセス間信号は sc_signal< データタイプ > になります。
クロックには bool型、もしくは型無しで sc_in_clk を使用します。
リセットには bool型を使用します。
固定小数点の型は種類によりそれぞれ動作が異なるため、 sc_* もしくは cynw_* のどちらかにしますが、Stratusを使用する場合はcynw_*を使います。その場合、#include <cynw_fixed.h> を使います。
入出力信号は規定のデータタイプ以外にユーザー定義のクラスを作る事で複数の信号をまとめる事も可能です。
整数と固定小数とのデータの代入は、同じbit幅でも固定少数側に.range()が必要です。
sc_int = cynw_fixed.range()
cynw_fixed.range() = sc_int

-- プロセス
SC_MODULE内ではそれぞれのプロセス単位で並列処理が可能です。
プロセスはコンストラクタ内でSC_CTHREADもしくはSC_METHODのどちらかの動作を割り当てます。
SC_CTHREADはクロック同期の順序回路、SC_METHODは組み合わせ回路になります。
SC_CTHREADはどのクロックに同期するか、また使用する非同期リセット(async_reset_signal_is)や同期リセット(reset_signal_is)を割り当てます。
SC_METHODは使用する信号をセンリビティリストとして sensitive で指定する必要があります。
組み合わせ回路はSC_CTHREAD内で通常の関数やクラスで構造化する事も可能なので、あえてSC_METHODを使う必要は無いです。ただし、接続階層に組み合わせ回路の論理を入れる場合は、SC_METHODを使う必要があります。

-- コンストラクタ
SC_CTOR(モジュール名){ 各プロセス割り当て }が基本構成です。
クロック周波数は基本的に project.tcl で定義しますが、クロックが複数ある場合は最初のクロック以外はコンストラクタ内で HLS_SET_CLOCK_PERIOD を使用して周波数定義を行います。単位は使用するライブラリに依存します。ただし、基本的に1 SC_MODULEに対して1クロックにします。多クロックにするメリットはありません。

-- 通常接続記述
接続記述を行う場合はIOの後にサブモジュールとしてSC_MODULEをポインタとして宣言します。※定義による記述方法もあります。その場合newや->は使用しません。
コンストラクタ内でサブモジュールを new によってコンストラクトを行い、さらに下記のように信号接続を行います。
サブモジュールポインタ -> サブモジュールIO(モジュールIO)

-- SRAM
SRAMを使う場合はIOの後にメンバ変数として配列を定義します。
定義した配列に対してコンストラクタ内で HLS_MAP_TO_MEMORY を使い、配列と実際に使用するSRAMモジュールとの紐付けを行います。

- .cpp file
各プロセスを、void モジュール名::プロセス名(){ } というように、C++のメンバ関数と同じ書き方で記述します。

SC_CTHREADの場合、レイテンシの種類としては、fix_latency/relax_latency/pipeline の3種類がありますが、そもそもモジュールをSC_MODULEにすると決めた時点でそのメリットを生かすには pipeline 以外の選択肢は無いです。
{HLS_DEFINE_PROTOCOL(“reset”); リセット記述} while(true){HLS_PIPELINE_LOOP(HARD_STALL, 1); {HLS_DEFINE_PROTOCOL(“in”); 入力記述} パイプライン処理記述 {HLS_DEFINE_PROTOCOL(“out”); 出力記述 wait();} } が基本構成です。

複数サイクルで値を保持したい場合はwhileの外で変数定義を行います。

HLS_DEFINE_PROTOCOL(“reset”)はプロセス内に1個だけにし、その中で出力信号に.write()を行い初期化します。

HLS_DEFINE_PROTOCOL(“in”)はプロセスのwhile内に1個だけにし、その中で入力信号の.read()を行い内部信号に値を毎サイクル代入します。
イネーブル入力時にだけ動作させたい場合は、HLS_DEFINE_PROTOCOL(“in”)の最初で、do wait(); while(!イネーブル信号名.read()); のストール記述を行います。
静的に使用する信号はHLS_ASSUME_STABLE(信号名); HLS_SET_INPUT_DELAY(信号名, 0.0) にしておくとHLS_DEFINE_PROTOCOL(“in”)外でも直接参照可能です。

HLS_DEFINE_PROTOCOL(“out”)はプロセスのwhile内に1個だけにし、その中で出力信号の.write()を毎サイクル行います。

クロックサイクル記述は HLS_DEFINE_PROTOCOL(“out”) 内の最後に記述する1個だけです。その間のパイプラインレイテンシ挿入は高位合成ツールに任せます。

パイプライン処理記述の for は基本的に展開(UNROLL)され、各ループは並列処理されます。もしもUNROLLしない場合は、for 内に HLS_UNROLL_LOOP(OFF); を記述します。

同じ演算がある場合は事前に演算しておき、その後複数個所で使用するようにします。

int型で定義されているとツールが適切なbit幅を推定できない場合があり、それにより必要以上の個数のリソースが生成されてしまう事があります。そのため、変数のbit幅は可能な限り明示的に記述するようにします。よくある例としては、indexを演算で使用するという記述が挙げられます。対策としてはindexを使用する場合にはループ内でbit幅指定の変数に代入してから演算で使用します。
for(int i=0; i<6; i++) {
out = (temp+i)*5…….
}

HLS_DPOPT_REGIONを指定し複合演算リソースを生成する事でAreaが小さくなる場合があります。dpopt_auto=exprで効果のありそうなおおよそのプロセスは判定可能です。
2018-11-26 : Work-Product-Design : コメント : 0 : トラックバック : 0
Pagetop

Data type note for sc_fixed in SystemC

sc_fixed <wl, iwl> var_name;

wl: total number of bits
iwl: number of integer bits

Use .range() to assign to/from sc_int.

ref:
https://upload.wikimedia.org/wikiversity/en/a/ad/SystemC.06.A.DataTypes.20120605.pdf
2018-10-30 : Work-Product-Design : コメント : 0 : トラックバック : 0
Pagetop

端子情報(端子表)からVerilogのRTLテンプレートを作成


#!/usr/bin/perl

use strict;
use warnings;
use Getopt::Std;
use File::Basename;

my $outdir = "./";
my $signal_max = 20;

my $modname;
my @signal;
my @msb;
my @lsb;
my @inout;
my $linenum;

my %opt = ();
getopts("hg", \%opt);
if ($opt{h}) { &help(); }
if ($opt{g}) {
foreach (@ARGV) {
my $infilename = $_;
&parse_txt($infilename);

my $outfilename;
my @extlist;
my $dir;
my $ext;
@extlist = qw /.txt/;
($modname, $dir, $ext) = fileparse($infilename, @extlist);
$outfilename = $outdir . $modname . ".v";
open (OUTFILE, ">$outfilename") || die "$outfilename: $!";
&gen_module();
&gen_interface();
&gen_connect();
close (OUTFILE);
}
}

sub help()
{
print << "ENDLINE";
Usage: ${0} [Optin]
Option:
-h :help
-g modulename.txt ... :making template
txt fomat is:
hoge \t input
hoge[MSB:LSB] \t input
hoge \t output
hoge[MSB:LSB] \t output
ENDLINE
}

sub parse_txt {
my $ifn = $_[0];

@signal = ();
@msb = ();
@lsb = ();
@inout = ();
$linenum = 0;

open (INFILE, "<$ifn") || die "$ifn: $!";
while (<INFILE>) {
chomp;

s/ //g;

my @line = split(/\t/, $_);

push(@inout, $line[1]);
@line = split(/[\[:\]]/, $line[0]);
push(@signal, $line[0]);
if (defined($line[1])) { push(@msb, $line[1]); }
else { push(@msb, ""); }
if (defined($line[2])) { push(@lsb, $line[2]); }
else { push(@lsb, ""); }

$linenum++;
}
close (INFILE);
}

sub gen_module {
my $i;

print OUTFILE "module $modname\n";
print OUTFILE "(\n";

for ($i = 0; $i < $linenum; $i++) {
print OUTFILE " " x 4 . $signal[$i];
if ($i != ($linenum - 1)) { print OUTFILE " " x ($signal_max - length($signal[$i])) . ","; }
print OUTFILE "\n";
}

print OUTFILE ");\n\n";
}

sub gen_interface {
my $i;
my $max = 0;
my $str;
my $size;

for ($i = 0; $i < $linenum; $i++) {
$str = " " x 4;
if ($inout[$i] eq "in") { $inout[$i] = "input"; }
if ($inout[$i] eq "out") { $inout[$i] = "output"; }
$str = $str . $inout[$i];
if ($inout[$i] eq "input") { $str = $str . " " x 3; }
elsif ($inout[$i] eq "output") { $str = $str . " " x 2; }
if ($msb[$i] ne "" && $lsb[$i] ne "") { $str = $str . "[" . $msb[$i] . ":" . $lsb[$i] . "]" }
$str = $str . " ";
$size = length($str);
if ($max < $size) { $max = $size; }
}

for ($i = 0; $i < $linenum; $i++) {
$str = " " x 4;
$str = $str . $inout[$i];
if ($inout[$i] eq "input") { $str = $str . " " x 3; }
elsif ($inout[$i] eq "output") { $str = $str . " " x 2; }
if ($msb[$i] ne "" && $lsb[$i] ne "") { $str = $str . "[" . $msb[$i] . ":" . $lsb[$i] . "]" }
$size = length($str);
$str = $str . " " x ($max - $size) . $signal[$i] . " " x ($signal_max - length($signal[$i])) . ";";
print OUTFILE $str;
if ($inout[$i] eq "input") { print OUTFILE " // I :\n"; }
elsif ($inout[$i] eq "output") { print OUTFILE " // O :\n"; }
}

print OUTFILE "endmodule\n\n";
}

sub gen_connect {
my $i;
my $max = 0;
my $str;
my $size;

print OUTFILE $modname . " " . $modname . "\n";
print OUTFILE "(\n";

for ($i = 0; $i < $linenum; $i++) {
$str = " " x 4;
$str = $str . "." . $signal[$i];
$str = $str . " ";
$size = length($str);
if ($max < $size) { $max = $size; }
}

for ($i = 0; $i < $linenum; $i++) {
$str = " " x 4;
$str = $str . "." . $signal[$i];
$size = length($str);
$str = $str . " " x ($max - $size);
$str = $str . "(" . $signal[$i] . " " x ($signal_max - length($signal[$i]));
print OUTFILE $str;
if ($i != ($linenum - 1)) { print OUTFILE "),"; }
else { print OUTFILE ") "; }
if ($inout[$i] eq "input") { print OUTFILE " // I :\n"; }
elsif ($inout[$i] eq "output") { print OUTFILE " // O :\n"; }
}

print OUTFILE ");\n\n";
}

2018-10-30 : Work-Linux-Perl : コメント : 0 : トラックバック : 0
Pagetop

svn command for making release note

svn info -r$new_revision -R $tgt_path
svn log -r$old_revision:$new_revision --incremental $tgt_path
svn diff -r$old_revision:$new_revision $tgt_path
2018-10-26 : Work-Linux-Command/Editor : コメント : 0 : トラックバック : 0
Pagetop
ホーム  次のページ »

プロフィール

zive

Author:zive
大阪在住、男

ブログ検索

月別アーカイブ

FC2カウンター