HYS-C サンプルプログラム(1)導入

ここでは仕様の説明前に、どういった感覚で使うものなのか、まずサンプルプログラム2例を挙げてみます。なお、論理式の記述法に関してはここでは割愛します。論理式は加法標準形の論理式記述を基本として拡張されています。
このサンプルプログラムでは、3ビットのシフトレジスタの動き(出力は入力に戻してループさせる)を表示させるだけのものです。HybridStatesを使用してプログラミングを行う場合、以下の論理記述ファイルSHIFTREG.LGC及びプログラム本体SHIFTREG.Cを作成する必要があります。

-----------SHIFTREG.LGC------------------------
 
01 ;logical definition file
02
03 sbrdef reg_a
04 sbrdef reg_b
05 sbrdef reg_c
06 
07 prgdef regdump
08
09 EQUATIONS
10  regdump=const.;
11  reg_a=reg_c;
12  reg_b=reg_a;
13  reg_c=reg_b;
14 ENDE
03行から05行において、レジスタの定義をしています。ここではシングルビットの レジスタとして、reg_a,reg_b,reg_cの3つを定義しています。
また、11行から13行 では論理式によってシフトレジスタを記述しています。ここまでの記述に関しては、 論理回路設計時に使う記述とコンパチのものです。

HybridStatesでは、さらに、07行 と10行の記述に特徴があります。07行で、イベントによって呼ばれるプログラムとし てregdump()が定義されており、10行において、そのイベントはconst.として、無条件 に呼ばれる、という論理表記を行っています。(論理式の左側にプログラム名を書くこ とによって、等号で示される論理式評価内容が真の場合にプログラムが呼び出されます)
-----------SHIFTREG.C---------------------------
01 /* Shift registor                            */
02 /* Rev.01                                    */
03 /* Date:2000-08-26                           */
04 
05 #include 
06 #include 
07 #include 
08 #include "hysc.h"
09 #include "trans.h"
10 
11
12 main()
13 {
14	int logic_data[4096],data_len=0;
15	char file_name[20];
16
17	/* massage */
18	printf("The Shift Register by HYS-C 1.00 2000/08/26\n");
19
20	/* Read Logic Definition File */
21	strcpy(file_name,"shiftreg.out");
22	read_logic_file(logic_data,&data_len,file_name);
23
24	/*PLD RESET*/
25	sbrw(reg_a,1);
26	sbrw(reg_b,0);
27	sbrw(reg_c,0);
28
29	/* Exec Hybrid States */
30	for(;;) ehyscm(logic_data,data_len);
31 }
32
33
34 regdump()
35 {
36	static int count=0;
37   	printf("Clk_No.%2d ",count);
38	printf("reg_a=%d ",sbrr(reg_a));
39	printf("reg_b=%d ",sbrr(reg_b));
40	printf("reg_c=%d ",sbrr(reg_c));
41	printf("\n");
42
43	count++;
44	/* End condition */
45	if(count==20) 	exit(0);
46 }

上記Cソースの22行目まではおまじないと思ってください(といってもそれほど多く ありませんが)インクルードされているヘッダーや、またこのほかに必要なCソース はあらかじめ標準で用意しているか、プリプロセッサによって自動生成されますから、 ユーザが作る必要があるのは、上述の論理設計ファイルと、このソースの25行目以降 となります。

25行から27行では、論理設計ファイルで設計したシフトレジスタの初期化(リセット) を行っています。reg_aのみ1をセットしましたので、正常に動けばその'1'がreg_a →reg_b→reg_c→reg_aとシフトしてゆくはずです。

30行ではHybridStatesの論理シミュレーション関数が呼び出されています。1回呼ぶ ごとに”1クロック分”シミュレーションが行われます。ここではfor(;;)を用いて 無限ループを形成しています。

regdump()はmain()からは一切呼ばれません。regdump()の呼ばれるタイミングは、 論理シミュレーション関数ehyscm()が全て管理しています。論理式記述で regdump=const. としましたので、ここでは毎回(毎クロック)呼ばれることになります。 regdump()では、HybridStatesが標準で用意しているレジスタアクセス関数、 sbrr()を用いてレジスタ値を呼び出して表示します。 また、regdump()は20回呼ばれるとプロセスを終了させます。

以下はこのプログラムの実行結果です。
The Shift Register by HYS-C 1.00 2000/08/26
Clk_No. 0 reg_a=1 reg_b=0 reg_c=0 
Clk_No. 1 reg_a=0 reg_b=1 reg_c=0 
Clk_No. 2 reg_a=0 reg_b=0 reg_c=1 
Clk_No. 3 reg_a=1 reg_b=0 reg_c=0 
Clk_No. 4 reg_a=0 reg_b=1 reg_c=0 
Clk_No. 5 reg_a=0 reg_b=0 reg_c=1 
Clk_No. 6 reg_a=1 reg_b=0 reg_c=0 
Clk_No. 7 reg_a=0 reg_b=1 reg_c=0 
Clk_No. 8 reg_a=0 reg_b=0 reg_c=1 
Clk_No. 9 reg_a=1 reg_b=0 reg_c=0 
Clk_No.10 reg_a=0 reg_b=1 reg_c=0 
Clk_No.11 reg_a=0 reg_b=0 reg_c=1 
Clk_No.12 reg_a=1 reg_b=0 reg_c=0 
Clk_No.13 reg_a=0 reg_b=1 reg_c=0 
Clk_No.14 reg_a=0 reg_b=0 reg_c=1 
Clk_No.15 reg_a=1 reg_b=0 reg_c=0 
Clk_No.16 reg_a=0 reg_b=1 reg_c=0 
Clk_No.17 reg_a=0 reg_b=0 reg_c=1 
Clk_No.18 reg_a=1 reg_b=0 reg_c=0 
Clk_No.19 reg_a=0 reg_b=1 reg_c=0 
使用例その1ではまだHybridStatesのあまり利点が明確になりません。その2では簡単な状態遷移図プログラミングをHybridStatesを用いて作成してみます。

下記がそのサンプルシステムの状態遷移図です。


このシステムでは、状態が4つあります。基本となるのが、idle状態で、そこへイベントev1が入ると(ハード的にはイベントと表現するより、入力ev1と言った方がしっくりきますが)waitへと状態遷移します。waitではまたイベント待ち状態となり、イベントev2が入ればexe1 へ、ev3が入ればexe2へ進みます。この図で"・prog1"等、"・"を付けたのはそのタイミングで起動されるべきプログラムを示しています。例えば、idle状態でイベントev1が入ったタイミングではプログラムprog3が起動されます。また、wait状態では常にプログラムprog4が実行されます。欄外に記載した"input"はconst、つまり状態とかかわらず定常的に実行されます。


-----------A.LGC-------------------------------

01 ;logical definition file
02 
03 byrdef state{idle,wait,exe1,exe2}
04 sbrdef ev1
05 sbrdef ev2
06 sbrdef ev3
07
08 prgdef prg1
09 prgdef prg2
10 prgdef prg3
11 prgdef prg4
12 prgdef input
13 
14
15 EQUATIONS
16 state(wait)=(state=idle)*ev1;
17 state(exe1)=(state=wait)*ev2;
18 state(exe2)=(state=wait)*ev3;
19 state(idle)=(state=exe1)+(state=exe2);
20
21 prg3=(state=idle)*ev1;
22 prg4=(state=wait);
23 prg1=(state=exe1);
24 prg2=(state=exe2);
25 input=const.;
26 ENDE
上記がこのシステム構造を示す論理設計ファイルです。03行目では状態保存用の レジスタとして、8ビット長のレジスタ"state"を定義し、また状態名を列挙定義してい ます。

論理式の16行から19行では、stateレジスタの更新タイミングを記述しています。 例えば、16行目ではidle状態でイベントev1が入力された場合、wait状態へ遷移させる ことを記述しています。22行目では、プログラムprg3の実行論理として、idle状態の 時にイベントev1が入力された場合を指定しています。

 HybridStatesでは普通の論理表記(+,*,/:inv.)の他にこのようにバイト、ワード 単位での比較(=、<,>)記述も可能にして、ステートマシーンの記述をしやすくしてい ます。

なお、EQUATIONS-ENDE内の論理式評価は同時処理です。上から順に評価されるのでは なく同期的同時処理のため、それより上の論理式により更新されたレジスタ値によって それより下の論理式に影響を与えることはありません。


01 /* Test progrmam type A                      */
02 /* Rev.01                                    */
03 /* Date:2000-08-27                           */
04
05 #include 
06 #include 
07 #include 
08 #include "hysc.h"
09 #include "trans.h"
10 
11 static clk_count=0;
12
13
14 main()
15 {
16	int logic_data[4096],data_len=0;
17	char file_name[20];
18	int i;
19	/* massage */
20	printf("HYS-C Test program 2000/08/27\n");
21
22	/* Read Logic Definition File */
23	strcpy(file_name,"a.out");
24	read_logic_file(logic_data,&data_len,file_name);
25	/*PLD RESET*/
26	byrw(state,idle);
27	sbrw(ev1,0);
28	sbrw(ev2,0);
29	sbrw(ev3,0);
30
31	/* Exec Hybrid States (max 20clock)*/
32	for(i=0;i<20;i++){
33		/* debug */
34		printf("-----State debug-----\n");
35		printf("clock_count=%d\n",clk_count);
36		printf("State=%d\n",byrr(state));
37		printf("Ev1=%d\n",sbrr(ev1));
38		printf("Ev2=%d\n",sbrr(ev2));
39		printf("Ev3=%d\n",sbrr(ev3));
40        	printf("---------------------\n");
41
42		ehyscm(logic_data,data_len);
43	}
44 }
45
46
47 input()
48 {
49	printf("input prgram executed:");
50	switch(clk_count){
51		case 0:	sbrw(ev1,1);
52			printf("event1 occured\n");
53			break;
54		case 3:	sbrw(ev2,1);
55			printf("event2 occured\n");
56			break;
57		case 5: sbrw(ev1,1);
58			printf("event1 occured\n");
59			break;
60		case 6: sbrw(ev3,1);
61			printf("event3 occured\n");
62			break;
63		case 10: exit(0);	/*exit*/
64		default: printf("No event occured\n");
65	}
66	clk_count++;
67 }
68 prg1()
69 {
70	sbrw(ev2,0);
71	printf("prg1 executed\n");
72 }
73 prg2()
74 {
75	sbrw(ev3,0);
76	printf("prg2 excuted\n");
77 }
78 prg3()
79 {
80	sbrw(ev1,0);	/*reset ev1 */
81	printf("prg3 excuted\n");
82 }
83 prg4()
84 {
85	printf("prg4 excuted\n");
86 }
上記がプログラム本体です。例によって24行目まではおまじないです。
26〜29行で初期状態を決定し、32行目以降で論理式評価を行っています。

ここではデバッグ用に毎回の状態遷移をトレース出力するようなprintf文 を追加しています。これにより、プログラム本体の動作は差し置いて、制御 構造だけ限ってデバッグすることが可能です。(また、26〜29行の初期値を 変えるだけで簡単にプログラム評価の条件を変えることが可能なことにも 特徴的です。評価が楽なプログラミングというのも利点の1つになると 思います)

47行からのinput()関数では、イベントを発生させています。クロックが 0,3,5,6,個目でイベントが発生するように仕組んでありますが、これは、 制御用プログラムでは割り込み処理によるものでもかまいません。 クロック10発目で、プロセスを終了します。

68行から86行は論理式によって実行制御されているプログラム群です。 (ここではイベントフラグのリセットを行っている他はデバッグ文しか 記述していません。)

上記プログラムの実行結果は、以下のようになります。


HYS-C Test program 2000/08/27
-----State debug-----
clock_count=0
State=0
Ev1=0
Ev2=0
Ev3=0
---------------------
input prgram executed:event1 occured
-----State debug-----
clock_count=1
State=0
Ev1=1
Ev2=0
Ev3=0
---------------------
prg3 excuted
input prgram executed:No event occured
-----State debug-----
clock_count=2
State=1
Ev1=0
Ev2=0
Ev3=0
---------------------
prg4 excuted
input prgram executed:No event occured
-----State debug-----
clock_count=3
State=1
Ev1=0
Ev2=0
Ev3=0
---------------------
prg4 excuted
input prgram executed:event2 occured
-----State debug-----
clock_count=4
State=1
Ev1=0
Ev2=1
Ev3=0
---------------------
prg4 excuted
input prgram executed:No event occured
-----State debug-----
clock_count=5
State=2
Ev1=0
Ev2=1
Ev3=0
---------------------
prg1 executed
input prgram executed:event1 occured
-----State debug-----
clock_count=6
State=0
Ev1=1
Ev2=0
Ev3=0
---------------------
prg3 excuted
input prgram executed:event3 occured
-----State debug-----
clock_count=7
State=1
Ev1=0
Ev2=0
Ev3=1
---------------------
prg4 excuted
input prgram executed:No event occured
-----State debug-----
clock_count=8
State=3
Ev1=0
Ev2=0
Ev3=1
---------------------
prg2 excuted
input prgram executed:No event occured
-----State debug-----
clock_count=9
State=0
Ev1=0
Ev2=0
Ev3=0
---------------------
input prgram executed:No event occured
-----State debug-----
clock_count=10
State=0
Ev1=0
Ev2=0
Ev3=0
---------------------
input prgram executed:


長い間読んで頂いてありがとうございました。(ここまで読まれた方いるんだろうかちょっと心配ですが)補足とまとめです。
(補足)
論理シュミレーションというと巨大なものを連想しがちですが、HYS-Cのシミュレーション部のソースは7KBです。Z80アセンブラ版は実行形式ファイルで最小僅か1.5KB、速度面では、制御用目的に使用した場合でも人的入力に対する制御(これは、毎秒数十回の超人的連打キー入力を考慮する場合にも適合します)であれば、ほとんどCPUリソースを使用しない程度ですみます。
また、上記使用例2では、2箇所(idel,wait状態)で入力イベント待ち状態となり ますが、プログラムはイベント待ちのポーリングで停止してしまっている訳ではありません。const指定しているinput()を始め、これとは全く別系統の状態遷移図を持つ処理を追加した場合なども、もちろん並列に動作します。

この先ご案内する、5.HYS-C サンプルプログラム(2)JTAG解析について、論理設計ファイル だけ先に記載します。今まで、サンプル用に状態遷移図などを作りましたが、こういったすでに遷移構造がわかっている対象であれば、論理設計の必要がない場合もあります。
JTAG解析
戻る