20 |
Pongと強化学習 (89) |
BSVにより、DumpFSMを改造します。従来のDumpDSMの仕様は、
- SW等の外部指示により、GameFSMにウエイト要求を出す
- GameFSMはSyncWait時にウエイト信号(停止中信号)を出力する
- DumpFSMは停止中信号を確認し、SELをTrueとする
- VRAMの内容をUARTで出力する
- 完了したらSELとウエイト要求をFalseにする
という動作でした。今回改造するポイントは外部指示ではなく、強化学習ソフトウエアの指示により画面ダンプを実施する点です。そのために従来送信部のみであったUARTを受信部も作成します。
- SW等の外部指示により、GameモードがFalseになる
- シリアルデータがSTXを指示したらGameFSMにwait要求を出す
- GameFSMはSyncWait時にウエイト信号(停止中信号)を出力する
- DumpFSMは停止中信号を確認し、SELをTrueとする
- SELがTrueの間は60Hz信号を遮断する。これによりGameFSMが進むことは無い
- VRAMの内容をUARTで出力する
- 完了したらSELとウエイト要求をFalseにする。
- GameモードがTrueになったら60Hz信号を再開する。
図962.1に構造図を示します。DumpFSMモジュールには送信と受信のUARTを配置し、それをテストするテストベンチ内にも同じUARTを対向して配置します。

DumpFSM.bsv
import StmtFSM::*;
import Uart::*;
import Connectable::*;
typedef Bit#(16) Addr;
typedef Bit#(4) Data;
typedef Bit#(8) Byte;
`define STX 8'h02
interface DumpFSM_ifc;
(* prefix="" *)
method Action datam(Data newdata); // input
(* prefix="" *)
method Action cwaitm(Bool newcwait); // input
method Bool sreqm(); // output
method Addr addrm(); // output
method Bool selm(); // output
method Bit#(1) sout(); // serial output
(* prefix="" *)
method Action sin(Bit#(1) nidata); // serial input
(* prefix="" *)
method Action c60Hz(Bool newtic); // input
method Bool ticfunction(); // output
(* prefix="" *)
method Action mode(Bool newgame); // input
endinterface
(* synthesize, always_ready="sreqm, addrm, selm, sout, ticfunction",
always_enabled="datam, cwaitm, sin, c60Hz, mode" *)
module mkDumpFSM(DumpFSM_ifc);
Reg#(Addr) addr <- mkReg(0);
Reg#(Data) data <- mkRegU;
Reg#(Byte) byteData <- mkRegU;
Reg#(UInt#(9)) x <- mkRegU;
Reg#(UInt#(9)) y <- mkRegU;
Reg#(UInt#(4)) i <- mkRegU;
Reg#(Bool) cwait <- mkReg(False);
Reg#(Bool) sreq <- mkReg(False);
Reg#(Bool) sel <- mkReg(False);
Reg#(Bool) tic <- mkReg(False);
Reg#(Bool) game <- mkReg(True);
Uart_ifc uart <- mkUart();
function Stmt nibbleOut(Data nibble);
return (seq
byteData <= extend(nibble) + ((nibble >= 10) ? (-10 + 8'h61) : 8'h30);
uart.write(byteData);
$write("%c", byteData);
endseq);
endfunction: nibbleOut
Stmt test = seq
while (True) seq
await(!game); // Gameでない場合、トリガが来たら吸出し
await(uart.read() == `STX);
sreq <= True; // 描画マスタ停止要求を出す
await(cwait); // 描画マスタ停止したら、
sel <= True; // ダンプ開始
for (i <= 1; i <= 4; i <= i + 1) seq
uart.write(8'h38); // start of header '8888' -> remove
$display("8");
endseq
addr <= 0;
for (y <= 0; y <= 2/* 255 */; y <= y + 1) seq
for (x <= 0; x <= 255; x <= x + 1) seq
// $display("%3d, %3d", x, y);
// $display(" %04x ", addr);
action
addr <= addr + 1;
endaction
nibbleOut(data);
endseq // for x
uart.write(8'h0a); // LF
endseq // for y
await (uart.done()); // 送信終了待ち
action
sreq <= False; // 要求OFF
sel <= False; // 選択OFF
endaction
endseq // while
endseq; // Stmt
mkAutoFSM(test);
method Bool sreqm(); // output
return sreq;
endmethod
method Addr addrm(); // output
return addr;
endmethod
method Action datam(Data newdata); // input
data <= newdata;
endmethod
method Action cwaitm(Bool newcwait); // input
cwait <= newcwait;
endmethod
method Bool selm(); // output
return sel;
endmethod
method Bit#(1) sout(); // serial output
return uart.sout();
endmethod
method Action sin(Bit#(1) nidata); // serial input
action
uart.sin(nidata);
endaction
endmethod
method Action c60Hz(Bool newtic); // input
if (game && !sel) action
tic <= newtic;
endaction
endmethod
method Bool ticfunction; // output
return tic;
endmethod
method Action mode(Bool newgame); // input
game <= newgame;
endmethod
endmodule