TLMモデルからSystemCモデルへの7つの課題

Merry Christmas!!!

SystemCでは幅広い範囲の抽象度で記述することができます。
それではそれぞれのモデルを再度は以下のような感じになります。

モデリング例

  • Cycleモデル
#include <stdlib.h>
#include <vector>
using namespace std;

#include <systemc.h>

SC_MODULE( hoge ) {

  sc_in  <bool >        clk;
  sc_in  <bool >        xrst;
  sc_in  <bool >        ce;
  sc_in  <bool >        we;
  sc_in  <sc_uint<10> > address;
  sc_in  <sc_uint<32> > wdata;
  sc_out <sc_uint<32> > rdata;

  vector<unsigned int>  mem;
  unsigned int          mem_size;

  void process();
  void write(unsigned int, unsigned int);
  unsigned int read(unsigned int);

  SC_CTOR( hoge )
    :  clk("clk"), xrst("xrst"), ce("ce"), we("we")
     , address("address"), wdata("wdata"), rdata("rdata")
  {
    SC_THREAD(process);
      sensitive << clk.pos();
      async_reset_signal_is(xrst, false);
    // Size Of Memory 32bit x 256word
    mem_size = 0x100;
    mem.resize(mem_size);
    for(unsigned int i=0; i<mem_size; i++){ mem[i] = 0; }
  }
};

inline void hoge::process(){
  rdata.write(0);
  wait();

  while (true) {
    if ((ce.read() == 1)) {
      unsigned int _adrs = address.read() >> 2;
      if (we.read() == 1) {
        unsigned int _data = wdata.read();
        write(_adrs, _data);
      } else {
        rdata = read(_adrs);
      }
    } else {
      wait();
    }
  }
}

inline void hoge::write(unsigned int _adrs, unsigned int _data){
  mem[_adrs] = _data;
  wait();
}

inline unsigned int hoge::read(unsigned int _adrs){
  wait();
  wait();
  return mem[_adrs];
}

f:id:kocha2012:20121225003532p:plain

  • TLMモデル
#include <stdlib.h>
#include <vector>
using namespace std;

#include <systemc.h>
#include <tlm.h>
#include "tlm_utils/simple_target_socket.h"
using namespace tlm;

SC_MODULE( hoge ) {

  tlm_utils::simple_target_socket<hoge, 32> target_socket;

  vector<unsigned int> mem;
  unsigned int         mem_size;

  void my_b_transport(tlm_generic_payload&, sc_time&);
  void write(unsigned int, unsigned int);
  unsigned int read(unsigned int);

  SC_CTOR( hoge )
    : target_socket("target_socket")
  {

    target_socket.register_b_transport(this, &hoge::my_b_transport);

    // Size Of Memory 32bit x 256word
    mem_size = 0x100;
    mem.resize(mem_size);
    for(unsigned int i=0; i<mem_size; i++){ mem[i] = 0; }
  }
};

inline void hoge::my_b_transport(tlm_generic_payload& trans, sc_time& delay){

  sc_dt::uint64  adr  = trans.get_address() >> 2;
  unsigned char* ptr  = trans.get_data_ptr();
  unsigned int   len  = trans.get_data_length();
  unsigned int   _tmp;

  if (trans.is_read()) {
    delay += sc_time(30, SC_NS);
    _tmp = read(adr);
    memcpy(ptr, &_tmp, len);
  } else if (trans.is_write()) {
    delay += sc_time(10, SC_NS);
    memcpy( &_tmp, ptr, len);
    write(adr, _tmp);
  } else {
    delay += SC_ZERO_TIME;
  }
  trans.set_dmi_allowed(false);
  trans.set_response_status( tlm::TLM_OK_RESPONSE );
}

inline void hoge::write(unsigned int _adrs, unsigned int _data){
  mem[_adrs] = _data;
}

inline unsigned int hoge::read(unsigned int _adrs){
  return mem[_adrs];
}

差分はなにか?

例えば、 #define で記述するような場合はこんな感じです。

#include <stdlib.h>
#include <vector>
using namespace std;

#include <systemc.h>
//###################################################################//
//# 1.Include
//###################################################################//
#ifdef TLM
  #include "tlm_utils/simple_target_socket.h"
  using namespace tlm;
#endif
//###################################################################//

SC_MODULE( hoge ) {

//###################################################################//
//# 2.Interface
//###################################################################//
#ifdef TLM
  tlm_utils::simple_target_socket<hoge, 32> target_socket;
#else
  sc_in  <bool >        clk;
  sc_in  <bool >        xrst;
  sc_in  <bool >        ce;
  sc_in  <bool >        we;
  sc_in  <sc_uint<10> > address;
  sc_in  <sc_uint<32> > wdata;
  sc_out <sc_uint<32> > rdata;
#endif
//###################################################################//

  vector<unsigned int> mem;
  unsigned int         mem_size;

//###################################################################//
//# 3.process関数
//###################################################################//
#ifdef TLM
  void my_b_transport(tlm_generic_payload&, sc_time&);
#else
  void process();
#endif
  void write(unsigned int, unsigned int);
  unsigned int read(unsigned int);
//###################################################################//

  SC_CTOR( hoge )
//###################################################################//
//# 4.初期化リスト
//###################################################################//
#ifdef TLM
    : target_socket("target_socket")
#else
    :  clk("clk"), xrst("xrst"), ce("ce"), we("we")
     , address("address"), wdata("wdata"), rdata("rdata")
#endif
//###################################################################//
  {

//###################################################################//
//# 5.process起動条件
//###################################################################//
#ifdef TLM
    target_socket.register_b_transport(this, &hoge::my_b_transport);
#else
    SC_THREAD(process);
      sensitive << clk.pos();
      async_reset_signal_is(xrst, false);
#endif
//###################################################################//
    // Size Of Memory 32bit x 256word
    mem_size = 0x100;
    mem.resize(mem_size);
    for(unsigned int i=0; i<mem_size; i++){ mem[i] = 0; }
  }
};

//###################################################################//
//# 6.process(処理)
//###################################################################//
#ifdef TLM
inline void hoge::my_b_transport(tlm_generic_payload& trans, sc_time& delay){

  sc_dt::uint64  adr  = trans.get_address() >> 2;
  unsigned char* ptr  = trans.get_data_ptr();
  unsigned int   len  = trans.get_data_length();
  unsigned int   _tmp;

  if (trans.is_read()) {
    delay += sc_time(30, SC_NS);
    _tmp = read(adr);
    memcpy(ptr, &_tmp, len);
  } else if (trans.is_write()) {
    delay += sc_time(10, SC_NS);
    memcpy( &_tmp, ptr, len);
    write(adr, _tmp);
  } else {
    delay += SC_ZERO_TIME;
  }
  trans.set_dmi_allowed(false);
  trans.set_response_status( tlm::TLM_OK_RESPONSE );
}
#else
inline void hoge::process(){
  rdata.write(0);
  wait();

  while (true) {
    if ((ce.read() == 1)) {
      unsigned int _adrs = address.read() >> 2;
      if (we.read() == 1) {
        unsigned int _data = wdata.read();
        write(_adrs, _data);
      } else {
        rdata = read(_adrs);
      }
    } else {
      wait();
    }
  }
}
#endif
//###################################################################//

inline void hoge::write(unsigned int _adrs, unsigned int _data){
  mem[_adrs] = _data;
//###################################################################//
//# 7.Timing
//###################################################################//
#ifndef TLM
  wait();
#endif
//###################################################################//
}

inline unsigned int hoge::read(unsigned int _adrs){
//###################################################################//
//# 7.Timing
//###################################################################//
#ifndef TLM
  wait();
  wait();
#endif
//###################################################################//
  return mem[_adrs];
}

まとめ

理想的な設計フローとして、TLMモデルから SystemCモデルにする場合に課題点についてでした。 ただ、これらの課題は簡単に解決するものもあるし、更に追求していくともっと壁があると思います(笑)

  • 課題点
    1. Include
    2. Interface
    3. process関数
    4. 初期化リスト
    5. process起動条件
    6. process(処理)
    7. Timing