本物のシリコンOS
HOSの続編として本物のシリコンOSを考え中である。
大雑把にコンセプトだけ書いておく。
あくまでイメージのデフォルメだが、ITRON-APIのようなものを
用いてモジュール間同期する、ハードウェア記述言語を考えている。
ブログにあまり壮大な例を載せてもアレなので超デフォルメした言語を書く。
下記のようなものを、次のようにVerilog変換するようなイメージだ。
=====元ソース======
CRE_FLG(FLG_ID, {TA_WSGL, 0, 1}); // 初期値0, BIT幅1
module hoge
{
input unsigned int [1:0] port_in;
output unsigned int port_out;
task {
while (1) {
while ( port_in[0] ) {
dly_tsk(1);
}
while ( port_in[1] ) {
dly_tsk(1);
}
set_flg(FLG_ID, 1);
}
}
task {
port_out = 0;
while (1) {
wai_flg(FLG_ID, 1, TWF_ANDW);
clr_flg(FLG_ID, 0);
port_out = 1;
dly_tsk(1);
port_out = 0;
}
}
}
=====変換後Verilog======
module hoge
(
input wire clk,
input wire reset,
input wire [1:0] port_in,
output reg port_out
);
// CRE_FLG
wire FLG_ID_set;
wire FLG_ID_clr;
wire FLG_ID_flg;
flg
#(
.WIDTH(1)
)
i_FLG_ID
(
.set (FLG_ID_set),
.clr (FLG_ID_clr),
.flg (FLG_ID_flg)
);
// task1
reg [0:0] task1_state;
always @(posedge clk) begin
if ( reset ) begin
task1_state <= 0;
end
else begin
case (task1_state) begin
0: begin
if ( port[0] ) begin
task1_state <= 1;
end
end
1: begin
if ( port[1] ) begin
task1_state <= 0;
end
endcase
end
end
assign FLG_ID_set = ((task1_state == 1) && port[1]);
// task2
reg [0:0] task2_state;
always @(posedge clk) begin
if ( reset ) begin
task2_state <= 0;
end
else begin
case (task2_state) begin
0: begin
if ( (FLG_ID_flg & 1) == 1 ) begin
task2_state <= 1;
end
end
1: begin
task1_state <= 0;
endcase
end
end
assign FLG_ID_clr = ((task2_state == 0) && ((FLG_ID_flg & 1) == 1 ));
endmodule
=====ここまで======
たとえば Verilog の always文は、計算機科学的にはタスク(スレッド)に他ならない。
スレッドには待ちという状態が発生するが、ステートマシンの状態数に他ならない。
ここまでの変形は、普通の高位合成ツールがやってのける。
が、スレッド間同期に、ITRON的APIを使うなんて試みは多分あまりないと思う。
静的APIで同期オブジェクトを生成して、タスク間を連携させていくなどRTL化しやすい。
もちろんH/Wモジュール同士でなく、S/WのAPIとも直結可能なはずだ。
他にもセマフォ、データキューなど非常に相性がよさそうだ。
H/Wでは、演算器などリソースを排他制御で使いまわすことも多い。
タスクに優先度を与えて、スケジューリング理論に則ったアサインが簡単自在に書ければ非常に面白そうだ。
一般の RTL 言語はモジュール階層を木構造でしか許していないが、IDなどでフラットな結線を許す言語を作ることは難しいことではないはずだ。
夢が膨らむ。もっとも現在FlexとBISONお勉強中だがいつになることやら。