Or1ksimなしで「Simple SoC Design」を動かす

前に「Virtual PlatformでUARTを実装」で書いた、Exampleを「Or1ksim」なしで動かしました。
※記載してあるコードに関して一切の責任負いません。

動かすには、Or1ksimExtSC の代わりとなる TLMのInitiatorモデルを作成すれば良いので、簡易版を作ってみました。
ソフトの中身(レジスタ設定)はモデル内に直書きです。

○lt_initiator.h
#ifndef __LT_INITIATOR__
#define __LT_INITIATOR__

#include <stdlib.h> // Webの関係上全角になってます。
#include "tlm.h"
#include "UartSC.h"

using namespace std;
using namespace sc_core;

//# Clase
class lt_initiator
 :  public sc_module,
    public tlm::tlm_bw_transport_if<>
{
private:
 // Transe Command
 void read(unsigned int, unsigned int*);
 void write(unsigned int, unsigned int&);

public:
 typedef tlm::tlm_generic_payload      trans_type;
 typedef tlm::tlm_phase                phase_type;
 typedef tlm::tlm_initiator_socket<32> initiator_socket_type;

 lt_initiator( sc_module_name name );

 // Thread
 void initiator_thread(void);

 // TLM2.0 I/F
 tlm::tlm_sync_enum nb_transport_bw(trans_type&, phase_type&, sc_time&);
 void invalidate_direct_mem_ptr(sc_dt::uint64 a, sc_dt::uint64 b);

 // Socket
 initiator_socket_type initiator_socket;

};

#endif

○lt_initiator.cpp
#include "lt_initiator.h"

//#
SC_HAS_PROCESS(lt_initiator);
lt_initiator::lt_initiator(sc_module_name name)
: sc_module(name),
  initiator_socket("initiator_socket")
{
 SC_THREAD(initiator_thread);
 //dont_initialize();
 initiator_socket.bind( *this );

}
//# Thread
void lt_initiator::initiator_thread(void){

 unsigned int address;
 unsigned int data;

 const unsigned int BAND_RATE = 9600;
 const unsigned int CLOCK_RATE= 100000000;

 unsigned short int divisor;

 divisor = CLOCK_RATE/16/BAND_RATE; /* DL is for 16x baud rate */

 address = UART_LCR; data = UART_LCR_DLAB;         write( address, data);
 address = UART_BUF; data = divisor & 0xff;        write( address, data);
 address = UART_IER; data = (divisor >> 8) & 0xff; write( address, data);
 address = UART_LCR; data = ~UART_LCR_DLAB;        write( address, data);
 address = UART_LCR; data = 0x03;                  write( address, data);

 bool judge = false;
 /* Loop echoing characters */
 while( 1 ) {
   unsigned int  ch;

   do { /* Loop until a char is available */
     address = UART_LSR; read( address, &ch);
     if((ch & UART_LSR_DR) == 1) { judge = false; }
     else                        { judge = true;  }
   } while( judge );

   address = UART_BUF; read( address, &ch);

   do { /* Loop until the transmit register is free */
     address = UART_LSR; read( UART_LSR, &data);
     if((data & (UART_LSR_TEMT | UART_LSR_THRE )) == 0x60) { judge = false; }
     else                                                  { judge = true;  }
   } while( judge );

   address = UART_BUF; write( UART_BUF, ch);

 }

}

//# Read
void lt_initiator::read(unsigned int address, unsigned int *data){
 trans_type* trans         = new trans_type;
 sc_time delay             = SC_ZERO_TIME;
 unsigned char byte_enable = 0xff;

 trans->set_command(tlm::TLM_READ_COMMAND);
 trans->set_address(static_cast(address));
 trans->set_data_ptr(reinterpret_cast(data));
 trans->set_byte_enable_ptr(&byte_enable);
 trans->set_data_length(4);
 trans->set_streaming_width(4);

 initiator_socket->b_transport(*trans, delay);
 wait(delay);

 // Check return value of b_transport
 if( trans->is_response_error() ) {
   SC_REPORT_ERROR("TLM-2.0", trans->get_response_string().c_str());
 }

 delete trans;
}

//# Write
void lt_initiator::write(unsigned int address, unsigned int& data){
 trans_type* trans         = new trans_type;
 sc_time delay             = SC_ZERO_TIME;
 unsigned char byte_enable = 0xff;

 trans->set_command(tlm::TLM_WRITE_COMMAND);
 trans->set_address(static_cast(address));
 trans->set_data_ptr(reinterpret_cast(&data));
 trans->set_byte_enable_ptr(&byte_enable);
 trans->set_data_length(4);
 trans->set_streaming_width(4);

 initiator_socket->b_transport(*trans, delay);
 wait(delay);

 // Check return value of b_transport
 if( trans->is_response_error() ) {
   SC_REPORT_ERROR("TLM-2.0", trans->get_response_string().c_str());
 }

 delete trans;
}

//# TLM2.0 I/F

tlm::tlm_sync_enum lt_initiator::nb_transport_bw(trans_type& trans, phase_type& phase, sc_time& delay){
 trans.set_response_status(tlm::TLM_GENERIC_ERROR_RESPONSE);
 return tlm::TLM_COMPLETED;
}

void lt_initiator::invalidate_direct_mem_ptr(sc_dt::uint64 a, sc_dt::uint64 b){

}
TLM2.0のpayloadにて、byte_enableを設定しないとエラーになるので注意です。
本来であれば、Target側が考慮すべきところなんですが。。。
あとは、「simpleSocMainSC.cpp」をちょこちょこっと変更すれば動作確認できました。
関連記事

コメントの投稿

非公開コメント

プロフィール

Kocha

Author:Kocha
なんでもチャレンジ!(^o^)/
E-mail
github:Kocha
イベントカレンダー

カレンダー
10 | 2017/11 | 12
- - - 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 - -
カテゴリ
OVP (4)
最新記事
最新コメント
アーカイブ
リンク
Twitter
アクセス人数