VHDL-2008のforce/releaseとexternal name

# はじめに
VHDL-2008で導入されたforce/releaseとexternalについて解説します。
force/releaseについては、2021/Q3までは一般人が無償で使えるシミュレータ(Vivado シミュレータ/ModelSim Intel Starter)では次のような理由で使う機会はあまりありませんでした。

1. Vivadoではバージョン2021.2現在force/releaseは未サポート
1. ModelSim Intel Starterは10,000ステートメント制限のため、現実的にはモジュール単体でのシミュレーションに限られる

ところが、2021/11月に5,000インスタンスまで実行できるIntelがQuesta Intel Starterを出してくれたおかげでVHDLでも大きなデザインをシミュレーションできるようになり、force/releaseがより実用的になりました。
Questa Intel Starterのインスタンス数については、[Questa Intel Starterの制限を確認する](https://qiita.com/windy/items/a403a435509ebbec7e67)を参照下さい。

external nameはVivadoでも以前から使用可能です。

# どんな機能？
どちらもシミュレーションで使用する機能です。
シミュレーションなんかしないという悪い子には縁の無い機能です。
## force/release
Verilogにあるforce/releaseと同じです。
階層内にあるsignal/portの値を強制的に任意に上書きする機能です。
## external name
別のentity階層にあるオブジェクトを参照する機能です。
Verilogで`uut.data_rcv.valid`のように`.`で階層を区切って参照する機能と同じです。
# 使い方
## force/release
順序処理領域(process/procedure内)で予約語`force`を付けてsignal/portに代入する事で、任意の値を一時的に上書きします。
上書き後に対象の信号に対して予約後`release`を代入すると、上書きを解除します。

```VHDL
  signal CLK   : std_logic;
  signal valid : std_logic;  --CLKの↑エッジで変化する信号

  --テストベンチのスティミュラス
  process begin
    --CLK↓エッジでvalid=1になるのを待つ
    wait until falling_edge(CLK) and valid = '1';
    data <= force '0';       --'0'を上書きする
    wait until falling_edge(CLK);  --次のCLKの↓エッジを待つ
    data <= release;         --上書きを解放
  end process
```

注意すべき点は`release`実行のタイミングで **その時点での本来の値に戻る** という事です。
例えば上記のコードで、validがCLKの2サイクルアサートされる場合の波形は以下のようになります。

```
CLK  :_|^|_|^|_|^|_|^|_|^|_|^|
本来の
valid:_____|^^^^^^^|__________
force:-------|___|------------
forceされた
valid:_____|^|___|^|__________
```

現実的にはこの例のように同じ階層の信号に対してforceする事は無いと思います。
forceは下位の階層の信号に対して実行する事で本来の価値を発揮します。
階層内の信号は次のexternal nameで参照する事が可能です。
## external name
以下のようなシミュレーション階層があるとします

```
+<testbench>---------------+
| +<uut>----------------+  |
| | +<rcv (data_rcv)>-+ |  |
| | |                 | |  |
| | +-----------------+ |  |
| +---------------------+  |
+--------------------------+
```
```VHDL
--rcvのentity
entity data_rcv
  port (
    valid : out std_logic
  );
end;
architecture rtl of data_rcv is
  signal   valid_tmp : std_logic;
begin
  proc_rcv: process
    variable cnt : integer;
  begin
    ...
  end process;
end rtl;
```
最上位のtestbenchから、下位階層rcvのオブジェクトを以下のように参照できます。
``<<``と`>>`で囲まれた部分がexternal nameです。

```VHDL
  wait until falling_edge(CLK) and  <<signal uut.rcv.valid_tmp : std_logic>>  = '1';
  <<signal uut.rcv.valid_tmp : std_logic>>  <= force '0';
  wait until falling_edge(CLK);
  <<signal uut.rcv.valid_tmp : std_logic>>  <= release;
```
見て分かる通り、非常に長くて煩わしいです。VHDLの型に厳格な性格が滲み出ていますね。
ですので、普通はaliasで別名を付けて参照します。

```VHDL
  alias rcv_valid_tmp is <<signal uut.rcv.valid_tmp : std_logic>>;  --rcv_valid_tmpとする

  wait until falling_edge(CLK) and  rcv_valid_tmp = '1';  --rcv_valid_tmpで参照可能
  rcv_valid_tmp <= force '0';
```
external nameで参照可能なオブジェクトは同時処理領域のconstant, signal, variableです。
同時処理領域とは要するにarchitecture直下の事で、process内部で宣言されたconstant, variableは参照できません。

```VHDL
  alias cnt is <<variable uut.rcv.proc_rcv.cnt : integer>>;  --エラー process内は参照不可
```
portはsignalと同じ扱いなので、signalとして参照可能です。

```VHDL
  alias rcv_valid is <<signal uut.rcv.valid : std_logic>>;
```
# まとめ
VHDL-2008でのシミュレーションで使用可能な以下の2つの機能を説明しました。

1. force/releaseでVerilogのforce/releaseと同様の機能を実現できます
1. external nameでVerilogと同様に階層内のオブジェクトを参照できます