工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Industrial programming >> VHDL

VHDLで保護型とアクセスポインタを用いた動的リンクリスト実装

リンクリストは、要素の追加・削除に応じて拡張・縮小する動的データ構造です。VHDLのオブジェクト指向機能(アクセス型、レコード、保護型)を用いると、この構造をクリーンかつ効率的に実装できます。

DataStructuresパッケージの作成

リンクロジックを専用VHDLパッケージDataStructuresにカプセル化します。この将来を見据えた名前により、後でツリーやハッシュマップなど他の構造へ容易に拡張可能です。

package DataStructures is
  -- 公開宣言
end package DataStructures;

package body DataStructures is
  -- 非公開宣言と実装
end package body DataStructures;

VHDLパッケージは宣言部(公開インターフェース)と本体(非公開実装)で構成されます。宣言部はユーザーから見え、本体は内部に隠蔽されます。

保護型の定義

保護型はVHDLにおける軽量クラスのようなもので、サブプログラム、型宣言、変数を含められます。LinkedListという保護型を定義し、Push、Pop、IsEmptyの3操作を公開します。

package DataStructures is
  type LinkedList is protected
    procedure Push(constant Data : in integer);
    impure function Pop return integer;
    impure function IsEmpty return boolean;
  end protected;
end package DataStructures;

package body DataStructures is
  type LinkedList is protected body
  end protected body;
end package body DataStructures;

アイテムレコードの導入

保護型本体内で、ノードを表すrecordを宣言します。レコードはデータペイロードと次のノードへのポインタを含みます。

type LinkedList is protected body
  type Item is record
    Data : integer;
    NextItem : Ptr;
  end record;
end protected body;

保護型では宣言部で新しい型を宣言できないため、Itemレコードは本体内で定義します。

アクセス型でポインタを扱う

Itemインスタンスを動的に参照するため、アクセス型Ptrを使用します。この2段階宣言で循環依存を回避します。

type Item;
type Ptr is access Item;
type Item is record
  Data : integer;
  NextItem : Ptr;
end record;

最初のノードを追跡するルートポインタ。リストが空のときRootはnullです。

variable Root : Ptr;

リンクリスト操作の実装

Pushプロシージャ

新しい要素を追加:新しいItemを確保、データを設定、末尾にリンク。

procedure Push(Data : in integer) is
  variable NewItem : Ptr;
  variable Node : Ptr;
begin
  NewItem := new Item;
  NewItem.Data := Data;
  if Root = null then
    Root := NewItem;
  else
    Node := Root;
    while Node.NextItem /= null loop
      Node := Node.NextItem;
    end loop;
    Node.NextItem := NewItem;
  end if;
end;

Pop関数

最初の要素を削除。メモリ管理に注意が必要です。VHDLにはガベージコレクションがない(2017以前)ため、削除ノードを明示的に解放します。

impure function Pop return integer is
  variable Node : Ptr;
  variable RetVal : integer;
begin
  Node := Root;
  Root := Root.NextItem;
  RetVal := Node.Data;
  deallocate(Node);
  return RetVal;
end;

IsEmpty関数

impure function IsEmpty return boolean is
begin
  return Root = null;
end;

リンクリストのテスト

アクセス型は合成不可ですが、検証には最適です。テストベンチで動作をデモします。

パッケージのインポート

library work;
use work.DataStructures.LinkedList;

共有変数の使用

シグナルは保護型にできないため、複数プロセスからリストを操作するために共有変数を使用します。

architecture sim of LinkedListTb is
  shared variable List : LinkedList;
begin
  -- テストプロセス
end architecture;

完全なテストベンチ

library work;
use work.DataStructures.LinkedList;
entity LinkedListTb is
end entity;
architecture sim of LinkedListTb is
  shared variable List : LinkedList;
begin
  process is
  begin
    for i in 1 to 5 loop
      report "Pushing " & integer'image(i);
      List.Push(i);
    end loop;
    while not List.IsEmpty loop
      report "Popping " & integer'image(List.Pop);
    end loop;
    wait;
  end process;
end architecture;

DataStructuresパッケージ全体

package DataStructures is
  type LinkedList is protected
    procedure Push(constant Data : in integer);
    impure function Pop return integer;
    impure function IsEmpty return boolean;
  end protected;
end package DataStructures;

package body DataStructures is
  type LinkedList is protected body
    type Item;
    type Ptr is access Item;
    type Item is record
      Data : integer;
      NextItem : Ptr;
    end record;
    variable Root : Ptr;
    procedure Push(Data : in integer) is
      variable NewItem : Ptr;
      variable Node : Ptr;
    begin
      NewItem := new Item;
      NewItem.Data := Data;
      if Root = null then
        Root := NewItem;
      else
        Node := Root;
        while Node.NextItem /= null loop
          Node := Node.NextItem;
        end loop;
        Node.NextItem := NewItem;
      end if;
    end;
    impure function Pop return integer is
      variable Node : Ptr;
      variable RetVal : integer;
    begin
      Node := Root;
      Root := Root.NextItem;
      RetVal := Node.Data;
      deallocate(Node);
      return RetVal;
    end;
    impure function IsEmpty return boolean is
    begin
      return Root = null;
    end;
  end protected body;
end package body DataStructures;

テスト実行

ModelSimで実行するとコンソールに以下が表示されます:

# ** Note: Pushing 1
# ** Note: Pushing 2
# ** Note: Pushing 3
# ** Note: Pushing 4
# ** Note: Pushing 5
# ** Note: Popping 1
# ** Note: Popping 2
# ** Note: Pushing 3
# ** Note: Popping 4
# ** Note: Popping 5

出力は、リストが値をFIFO順で正しく格納・取得することを確認しています。

VHDL

  1. VHDLで文字列リストを作成する: ベスト・プラクティスと実装例
  2. Tcl駆動テストベンチでVHDLコード・ロック・モジュールを検証する
  3. VHDLテストベンチ・シミュレーションを優雅に終了させる方法
  4. VHDLでPWMコントローラを実装: 設計、シミュレーション、FPGAデモ
  5. VHDLで乱数生成: 一様分布からOSVVMまで
  6. ブロックRAMにおける堅牢なVHDLリングバッファFIFOの設計
  7. VHDLで自己検証テストベンチを構築する実践ガイド
  8. プロセス内プロシージャでVHDLステートマシンをクリーンに設計
  9. VHDLにおける不純関数の活用:FSMの可読性と保守性向上
  10. VHDL関数マスター:効率的な設計のための実践ガイド
  11. VHDLで有限ステートマシンを設計:信号機の実践例