Posts Issued in July, 2025

posted by sakurai on July 31, 2025 #1002

まず、ChatGPTに、BSVの2線ハンドシェイクアルゴリズムを尋ねてみます。

bluespecのモジュールでは自動的に2線方式のハンドシェークが行われるが、そのアルゴリズムを解説してください。


BSVにおける2線ハンドシェークのアルゴリズム

Bluespec SystemVerilog(BSV)では、モジュール間やルール間の通信において、Ready/Enable方式(2線ハンドシェーク)が自動的に挿入されます。

本記事では、BSVのハンドシェークの動作アルゴリズムをまとめます。

用語定義

  • caller:メソッドを呼び出す側。通常はルールや上位モジュール。
  • callee:メソッドを提供する側(FIFO, Reg, モジュール等)。

信号の方向:

  • readyは callee から caller への出力(callee が「受け入れ可能」かを知らせる)
  • enableは caller から callee への入力(caller が「今起動する」意思を伝える)

1. ハンドシェークの基本モデル

各メソッド呼び出し(またはルール起動)には、以下の2本の信号が対応します。

信号名 BSV上の名称 役割
Ready can_fire() callee が実行可能であることを示す純組合せフラグ
Enable will_fire caller が実際に起動する1サイクルパルス
  • FIFOなら!full、Regなら常にTrueなど、内部状態から算出される組合せ信号がready
  • enablecan_fireとスケジューラの許可を元に生成され、callee の*_enポートに入力されます。

2. 合成フロー(ルール単位)

2.1 各メソッドのcan_fire取得

rule foo when (guard);
   let v  <- A.method1;   // メソッド呼び出し①
       w  <- B.method2;   // メソッド呼び出し②
endrule

実際は BSC が.can_fireを各メソッドに自動付与して評価します。

2.2 can_fire_rule(= 全 Ready の AND)

複数メソッドがある場合、各 callee の Ready を AND し、ガード条件と組み合わせて以下のように合成されます:

wire can_fire_rule = guard && A_ready && B_ready;

2.3 スケジューラ仲裁 (scheduler_grant)

競合する他ルールとの排他処理・優先度制御が組み合わさり、fire生成条件となるgrant_ruleが作られます:

wire grant_rule = can_fire_rule & scheduler_logic(...);

2.4 will_fire(= 発火パルス)

wire will_fire = grant_rule;  // 1サイクルだけ true になる

これが Enableパルスとして callee に伝わります。

2.5 Callee への配線(扇形ファンアウト)

assign A_en = will_fire;
assign B_en = will_fire;

caller はfireをすべての callee に配線します。

2.6 レジスタ書き込みの en 端子にも使用

同じwill_fireパルスが、そのルール内で行われるレジスタ更新の*_en信号にも使われます。

【構造図イメージ】

Ready ─────┐
       ├──> AND (+guard) ──> fire──┬──> EN_A
Ready ─────┘               └──> EN_B

3. 複数ルール/メソッドの競合処理

  • 同一リソースを書き換えるルール同士は、静的スケジューラにより優先順位が付けられ、同時発火しないように制御されます。
  • 同一ルール内のメソッド呼び出しは、すべて同時にfireする。
  • 非競合のルールは並列にwill_fireが生成され、同時実行可能です。

例:レジスタの write-data MUX / enable OR

assign reg_din =
   (rule2_will_fire) ? data2 :
   (rule1_will_fire) ? data1 :
                       reg_q;

assign reg_en = rule1_will_fire | rule2_will_fire | ... ;

4. まとめ:2線ハンドシェークの要点

  • Ready(can_fire):callee が「今可能か」を知らせる組合せ出力
  • Enable(will_fire):caller が実行する1サイクルパルス(fire
  • 論理合成:Ready と guard を AND、スケジューラで仲裁 → fireを生成
  • 配線:fireはすべての callee のenableに扇形配線される
  • AND 回路は自動挿入される:ユーザーが手で書く必要はないが、論理上は存在する
  • ユーザーの記述負荷は低い:can_fire 以外の信号論理はすべて BSC が生成する

備考

このアルゴリズムは、BSC コンパイラが提供する強力なスケジューラと構造的合成の基盤であり、明示的な回路記述が不要で高い信頼性と安全性を確保します。


左矢前のブログ 次のブログ右矢

posted by sakurai on July 30, 2025 #1001

外部投稿記事において、2つのFSM(Finite State Machine)の調停を図るコマンドバッファOneStageを設計しました。このコマンドバッファもFSMであり、GameFSMからくるサウンドコマンドを一時保持し、SoundFSMがそれを引き取り当該サウンドを鳴らすというものです。実際には中間バッファは省略し、制御のみでコマンドバッファ制御を実行しています。

図%%.1
図1001.1 GameFSMとSoundFSMの調停

実はBSVはこのような調停の仕組みを自動で持っていて、bscはそれを自動生成することができます。ChatGPTの助けを借りて、これを実装します。

また、中間バッファとしてFIFOが必要かどうかも助言を受けます。以前の記事中にあるとおり、FIFOは付ければ良いというものではなく、付ければ付けるほど取りこぼしは減るもののレイテンシーが大きくなります。

さらに、取りこぼしを防ぐため、SoundFSMがbusyとなることを避ける目的から、基本的には全てのコマンドをプリエンプティブにしています。これは割り込み可能という意味で、サウンド演奏中にコマンドが入ると演奏を中断し、新たに演奏を開始するものです。


左矢前のブログ 次のブログ右矢

posted by sakurai on July 29, 2025 #1000

安全要求、特にTSRについて業界の一部に誤解があるようなので解説します。

誤解:「安全要求(SR)は安全目標違反(VSG)を避ける目的のため、安全機構(SM)のみを仕様化する」
正解:「安全要求(SR)は安全目標違反(VSG)を避ける目的のため、意図機能(IF)及び安全機構(SM)の両方を仕様化する」

SMのみが誤りである理由を3点示します。

  1. そもそも論から言えば、ECU全体への要求であるFSR及びそのECUへの配置であるFSCと、それを分解してエレメントにTSRを配置したTSCは上位と下位で一貫していなければなりません。TSRがSMのみであればIFへの要求が抜けるため、上位と下位で一貫しなくなります。
    ※ただし安全要求が初めからSMのみを記述するものである場合、そうは言えなくなる可能性もあります。

  2. 反対にIFにSRが割り当てていないと次のような問題がおこります。定量評価において、例えばSGがASIL-Cだった場合、ECU全体としてASIL-Cで設計する必要があります。ところが安全分析において、SMのみがASIL-Cで設計されていても、肝心のIFの故障率が大きい場合には全体としてASIL-Cを満足できません
    安全分析のみIFも含めてASIL-Cで抑えると言う方法(脱法)を取る場合、要求されていない安全に関わる仕様をIFのエレメントに要請することになり、それがどこから来たものか、明文化されていないことになります。これはISO 26262の精神である要求の明文化を損なうものと言えます。

  3. 当たり前過ぎて規格から文言を探すのは却って難しいのですが、Part 5の6.4.2 e)において、TSRは意図機能を実装するハードウェアエレメントにも適用されるべきことが記されています。TSRはSMだけでなくIFにも割り当てられる必要があると明示されており、システムの信頼性を確保するためにIFの安全対策が必要であることが補強されます。

以上3点から結論として、IFにもTSRを割り当てなければならないと考えます。


左矢前のブログ 次のブログ右矢

posted by sakurai on July 28, 2025 #999

ChatGPTを駆使しドラフトの作成が完了したので、AJEに提出しました。

従来はnative checkとしてAJEが修正した点はほぼ全てそのとおりに反映していましたが、今回は修正の全か所について原文と修正文をChatGPTにより評価してもらいました。その結果、元の英文をChatGPTが作成したせいもあるかもしれませんが、原文の方がおおむね良いという評価になりました。

ChatGPTのほうがISO 26262や信頼性用語に詳しく、例えば原文のtop eventをAJEはhighest eventに修正してきましたが、これはFTA用語ではtop eventであり、修正する必要はありません。

7月末までに論文ドラフト及びプレゼン資料ドラフトを作成し、投稿を完了しました。

表999.1 RAMS 2026へのマイルストーン
期限 マイルストーン 状態
2025/4/30 AJEにアブストラクトを修正依頼
2025/4/30 アブストラクト(氏名、所属無し版)投稿締め切り(システム入力)
2025/6/2
2025/5/27
アブストラクト採択結果 採択
2025/7/31
2025/7/26
初稿論文、プレゼン投稿締め切り(氏名、所属無し版)
2025/9/1 査読コメント
2025/9/30 最終論文、プレゼン投稿締め切り(氏名、所属有り版)
IEEEコピーライトフォーム提出
2025/10/10 RAMSへの登録及びホテルの予約


左矢前のブログ 次のブログ右矢

Pongと強化学習 (114)

posted by sakurai on July 16, 2025 #998

このプロトコルを用いてpythonのCustomAtariEnvと統合します。


CustomAtariEnv クラスを Device クラスを用いてシリアル通信の詳細を抽象化し、インタフェースをシンプルにするために再設計します。この方法により、CustomAtariEnv クラスはゲーム環境のロジックに集中し、シリアル通信の詳細は Device クラスが担当します。

Device クラスの設計

Device クラスはシリアル通信を担当し、コマンドの送受信を簡単に行えるように設計します。

    import serial
    
    class Device:
        def __init__(self, port):
            self.serial = serial.Serial(port, baudrate=115200, timeout=1)
        
        def send(self, command, payload=None):
            message = bytearray([SOH])
            message.append(ord(command))
            if payload is not None:
                message.extend(payload)
            message.append(EOT)
            self.serial.write(message)
        
        def receive(self):
            response = bytearray()
            while True:
                byte = self.serial.read(1)
                if byte:
                    response.append(byte[0])
                    if byte[0] == EOT:
                        break
            return response
        
        def close(self):
            self.serial.close()

CustomAtariEnv クラスの再設計

CustomAtariEnv クラスは Device クラスを使用して通信を行います。これにより、CustomAtariEnv はシリアル通信の詳細から切り離されます。

    import gym
    from gym import spaces
    
    class CustomAtariEnv(gym.Env):
        def __init__(self, device):
            super(CustomAtariEnv, self).__init__()
            self.device = device
            self.action_space = spaces.Discrete(4)  # 仮に4つのアクション
            self.observation_space = spaces.Box(low=0, high=255, shape=(256, 160, 3), dtype=np.uint8)  # 仮の解像度
    
        def reset(self):
            self.device.send(CMD_RESET)
            return self.device.receive()
    
        def step(self, action):
            action_command = self.get_action_command(action)
            self.device.send(CMD_ACTION, [action_command])
            return self.device.receive()
    
        def get_action_command(self, action):
            # Map the action to the actual command
            if action == 0:
                return ACTION_MOVE_LEFT
            elif action == 1:
                return ACTION_MOVE_RIGHT
            elif action == 2:
                return ACTION_FIRE
            else:
                raise ValueError("Invalid action")
        
        def close(self):
            self.device.close()

使用例

    device = Device('/dev/ttyUSB0')
    env = CustomAtariEnv(device)
    
    initial_state = env.reset()
    action = 1  # 仮に右移動
    new_state = env.step(action)
    
    env.close()

この再設計により、CustomAtariEnv クラスはシリアル通信の詳細から独立し、デバイスとの通信は Device クラスを通じて抽象化されます。これにより、ゲームロジックと通信ロジックが分離され、コードの可読性と保守性が向上します。


左矢前のブログ 次のブログ右矢

Pongと強化学習 (113)

posted by sakurai on July 15, 2025 #997

FPGAとdqn_atari.pyとのインタフェースプロトコルをChatGPTと相談した結果、以下のプロトコルにまとまりました。ChatGPTは最初はjsonフォーマットを提案してきましたが、FPGAでデコードする都合上シンプルなフォーマットとしました。


通信プロトコル

PythonからFPGAへのコマンド

  • SOH = 0x01
  • EOT = 0x04
  • ACK = 0x06
  • NAK = 0x15
  • CMD_RESET = 'R' = 0x52
  • CMD_ACTION = 'A' = 0x41
  1. リセットコマンド:

    • 目的: ゲームを初期状態にリセットし、新しいエピソードを開始する。
    • フォーマット: [SOH, CMD_RESET, データ長(0), EOT]
    • データ長はこのコマンドにおいてペイロードがないため0。
      図%%.1
      図997.1 リセットコマンド
  2. ステップコマンド:

    • 目的: 特定のアクションを実行し、その結果としての新しいゲーム状態を取得する。
    • フォーマット: [SOH, CMD_ACTION, データ長(1), アクションコード, EOT]
    • データ長アクションコード1バイト。
      図%%.2
      図997.2 ステップコマンド

FPGAからPythonへの応答

  1. リセット応答:

    • 目的: リセットが完了したことを確認し、新しいゲームフレームを提供する。
    • フォーマット: [SOH, ACK/NAK, データ長, フレームデータ, EOT]
    • コマンドフォーマットが正常ならACK、異常ならNAKを返す。
    • データ長フレームデータのバイト数。
      図%%.3
      図997.3 リセット応答
  2. ステップ応答:

    • 目的: アクションの結果としての新しいゲーム状態、報酬、およびゲームの継続状態を提供する。
    • フォーマット: [SOH, ACK/NAK, データ長, フレームデータ, 報酬, ゲーム終了フラグ, EOT]
    • コマンドフォーマットが正常ならACK、異常ならNAKを返す。
    • データ長は(フレームデータのバイト数 + 報酬1バイト + ゲーム終了フラグ1バイト)のバイト数。
      図%%.4
      図997.4 ステップ応答

このプロトコルでは、ペイロードの長さを明確にすることで、EOTがペイロード内に現れる問題を解消しています。また、データの一貫性と通信の信頼性を高めるためにペイロードの長さを先頭に加えています。


左矢前のブログ 次のブログ右矢

Pongと強化学習 (112)

posted by sakurai on July 14, 2025 #996

ゲームの見栄えが良いので、Space Invadersで強化学習を実装しようと思っていましたが、考えを変えてPongで実装することにしました。その理由はpythonにより記述されたatari-dqnの学習の効果があまり現れなかったためです。

Pongのほうが学習の結果がずっと良かったのですがその学習効果を図996.1に示します。

図%%.1
図996.1 エピソード8と5000の学習効果の比較

画面中左のオレンジパドルが単純コンピュータ制御で、右側のグリーンパドルが強化学習により学習したエージェントです。左画面がエピソード8の段階で0対20で一点も取れないのに対し、右画面のエピソード5000の段階では20対14と単純AIに勝ち越しています。約1日程度でこのくらいの学習効果があります。

なお単純コンピュータ制御は、単純にパドルのY座標をボールと一致させているだけです。ただし完全に一致すると絶対に負けることがなく強化学習ができなくなるため、一度に一ドットしか移動できない制約をいれているようです。従ってかなり強いですが、急激な変化には弱い性質があります。

DQN学習中はロス等のパラメータをサーバーに送信しており、以下のような学習効果に関するチャートを取得することが可能です。

図%%.2
図996.2 各種パラメータのチャート

左矢前のブログ 次のブログ右矢

6月の検索結果

posted by sakurai on July 10, 2025 #995

弊社コンテンツの6月の検索結果です。

表995.1 上昇率上位のページ(前月との比較)
タイトル クリック数
SPFM, LFM, PMHFの計算法の例 +28
レイテントフォールトのご質問 +16
故障率 +12

表995.2 パフォーマンス上位のページ
タイトル クリック数
機能安全用語集 122
ISO 26262での独立の考え方 61
ASILデコンポジション 60

表995.3 上昇率上位のクエリ
クエリ クリック数
従属故障 +6
MPFDI +4
IEC TR 62380 +3

表995.4 パフォーマンス上位のクエリ
クエリ クリック数
FTTI 23
PMHF 20
レイテントフォールトとは 18


左矢前のブログ 次のブログ右矢

Pongと強化学習 (111)

posted by sakurai on July 8, 2025 #994

コードの先頭の部分の説明です。


プログラムの冒頭にあるインポートリストは、Deep Q-Network (DQN) の実装において使用されるさまざまなライブラリやモジュールを取り込むためのものです。それぞれのインポートがプログラム内でどのような役割を担っているか、詳しく解説します。

基本ライブラリのインポート

  1. argparse: コマンドライン引数を処理するためのモジュール。このモジュールを使ってプログラム実行時に外部から設定値を受け取ることができます。
  2. os: オペレーティングシステムとのインタラクションを行うためのモジュール。ファイルパスの操作や、環境変数へのアクセスなどに使用します。
  3. random: 乱数を生成するためのモジュール。DQNでの探索処理やランダムサンプリングに使用されます。
  4. time: 時間に関連する関数を提供するモジュール。プログラムのパフォーマンス測定や待機処理などに使われることがあります。
  5. strtobool(from distutils.util): 文字列形式の真偽値をPythonのブール型に変換する関数。設定ファイルやコマンドライン引数からの入力を扱う際に便利です。

機械学習・強化学習ライブラリのインポート

  1. gymnasium as gym: OpenAI Gym(現在はGymnasiumとして知られています)の環境を扱うためのライブラリ。強化学習アルゴリズムのトレーニングに必要な標準的なインターフェイスを提供します。
  2. numpy as np: 数値計算を効率的に行うためのライブラリ。配列操作や数学的計算に広く用いられます。
  3. torch: PyTorchライブラリで、ディープラーニングモデルの構築とトレーニングに使用されます。
    • torch.nn: ニューラルネットワークの構築に使用されるクラスや関数を含むモジュール。
    • torch.nn.functional as F: 損失関数や活性化関数など、ニューラルネットワークで頻繁に使用される関数を提供します。
    • torch.optim as optim: 最適化アルゴリズムを提供するモジュール。SGDやAdamなど、ニューラルネットワークの訓練に必要です。
  4. stable_baselines3.common.atari_wrappers: Atariゲーム環境のためのラッパー関数群。ゲームの観測や報酬の前処理を行います(例:ClipRewardEnv, EpisodicLifeEnvなど)。
  5. stable_baselines3.common.buffers: 経験再生バッファ(ReplayBuffer)など、強化学習においてデータを効率的に保存・利用するためのデータ構造を提供します。
  6. torch.utils.tensorboard: TensorBoardで訓練プロセスを可視化するためのユーティリティ。訓練中の損失や精度などのメトリクスをログに記録します。

このインポートリストは、DQNプログラムが多様な機能とモジュールを必要としていることを示しており、強化学習タスクを効果的に実行するための準備が整っています。


左矢前のブログ 次のブログ右矢