Vengineerの妄想(準備期間)

人生は短いけど、長いです。人生を楽しみましょう!

DMI : Direct Memory Interface

Verification Engineerの戯言

TLM 2.0 draft #2では、DMI(Direct Memory Interface)というものがあります。
このDMIは、2つのtransport interface(blockingとnon-blocking)とは違って、
直接ターゲット側にアクセスするものです。これは、シミュレーション速度を改善するために役立ちます。
たとえば、DMA用データをTargetに設定したり、Targetへのレジスタアクセス(内部RAMへのアクセス)などに使います。

DMIでは、次のような2つのインターフェースを用意しています。
    template <typename DMI_MODE = tlm_dmi_mode>
    class tlm_fw_direct_mem_if : public virtual sc_core::sc_interface
    {
        public:
            virtual bool get_direct_mem_ptr( const sc_dt::uint64& address,
                                             DMI_MODE& dmi_mode,
                                             tlm_dmi& dmi_data) = 0;
    };

    class tlm_bw_direct_mem_if : public virtual sc_core::sc_interface
    {
        public:
        virtual void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, 
                                               sc_dt::uint64 end_range) = 0;
    };
tlm_fw_direct_mem_ifインターフェースは、Forward path(Initiator->Targetのパス)で、
メソッドとしては、get_direct_mem_ptrを持ちます。
一方、tlm_bw_direct_mem_ifインターフェースは、Backward path(Target->Initiatorのパス)で、
メソッドとしては、invalidate_direct_mem_ptrを持ちます。

Initiatorは、get_direct_mem_ptrメソッドを使って、Target側へ直接アクセスできるメモリを獲得します。
獲得できると、get_direct_mem_ptrメソッドはtrueを返します。
一方、獲得できないあるいはサポートしていないときは、falseを返します。

第1引数のaddressは、アクセスアドレスを示します。
第2引数のdma_modeは、アクセスのタイプを示すもので次のように定義されています。
    class tlm_dmi_mode
    {
        public:
            enum Type { READ = 0x1, WRITE = 0x2, READ_WRITE == READ|WRITE };
            Type type;
    };
つまり、READのみ、WRITEのみ、READ/WRITEを指定できます。
第3引数のdmi_dataは、Initiatorがリファレンスを渡し、Targetが各値を設定するもので、次のように定義されています。
    class tlm_dmi
    {
        public:
        tlm_dmi() { init(); }
        void init();
        unsigned char* dmi_ptr;
        sc_dt::uint64 dmi_start_address;
        sc_dt::uint64 dmi_end_address;
        sc_core::sc_time read_latency;
        sc_core::sc_time write_latency;
        tlm_endianness endianness;
    };
Initiatorはget_direct_mem_prtメソッドにtlm_dmiクラスのインスタンス(dmi_data)のリファレンスを渡します。
つまり、Initiatorがdmi_dataを初期化しておきます。
Targetはアクセスできる場合、アクセス範囲をdmi_start_address/dmi_end_addressに設定し、
リードレイテンシーをread_latencyに、ライトレイテンシーをwrite_latencyに、
エンディアンをendiannessに設定します。そして、アクセスできるメモリのポインタをdmi_ptrに設定します。
Targetはアクセスできない場合、つまり戻り値がfalseの場合は、dmi_start_addressを0、dmi_end_addressを最大値(一般的には、unsigned intの最大値)に設定する必要があるので注意してください。

TargetからInitiatorへのメソッドであるinvalidate_direct_mem_prtは、何らかの理由でアドレス内のデータを無効化したいときに呼び出されます。