diff --git a/inc/Trace.h b/inc/Trace.h index 8624904..fb69f92 100644 --- a/inc/Trace.h +++ b/inc/Trace.h @@ -29,14 +29,35 @@ using namespace std; */ class Trace: sc_module { public: - // TLM-2 socket, defaults to 32-bits wide, base protocol + + /** + * @brief Bus socket + */ tlm_utils::simple_target_socket socket; - // Constructor + /** + * @brief Constructor + * @param name Module name + */ Trace(sc_module_name name); - + + /** + * @brief Destructor + */ + ~Trace(); + +private: + // TLM-2 blocking transport method virtual void b_transport( tlm::tlm_generic_payload& trans, sc_time& delay ); + + void xtermLaunch(char *slaveName); + void xtermKill( const char *mess ); + void xtermSetup(void); + + int ptSlave; + int ptMaster; + int xtermPid; }; #endif diff --git a/src/Trace.cpp b/src/Trace.cpp index 0da0866..14bdb96 100644 --- a/src/Trace.cpp +++ b/src/Trace.cpp @@ -1,12 +1,102 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Code taken from +// https://github.com/embecosm/esp1-systemc-tlm/blob/master/sysc-models/simple-soc/TermSC.h + #include "Trace.h" +void Trace::xtermLaunch( char *slaveName ) { + char *arg; + char *fin = &(slaveName[strlen( slaveName ) - 2]); + + if( NULL == strchr(fin, '/' )) { + arg = new char[2 + 1 + 1 + 20 + 1]; + sprintf( arg, "-S%c%c%d", fin[0], fin[1], ptMaster ); + } else { + char *slaveBase = ::basename( slaveName ); + arg = new char[2 + strlen( slaveBase ) + 1 + 20 + 1]; + sprintf( arg, "-S%s/%d", slaveBase, ptMaster ); + } + + char *argv[3]; + argv[0] = (char *)( "xterm" ); + argv[1] = arg; + argv[2] = NULL; + + execvp( "xterm", argv ); +} + +void Trace::xtermKill( const char *mess ) { + + + if( -1 != ptSlave ) { // Close down the slave + + close( ptSlave ); // Close the FD + ptSlave = -1; + } + + if( -1 != ptMaster ) { // Close down the master + close( ptMaster ); + ptMaster = -1; + } + + if( xtermPid > 0 ) { // Kill the terminal + kill( xtermPid, SIGKILL ); + waitpid( xtermPid, NULL, 0 ); + } + + if( NULL != mess ) { // If we really want a message + perror( mess ); + } + + +} + +void Trace::xtermSetup(void) { + ptMaster = open("/dev/ptmx", O_RDWR); + grantpt( ptMaster ); + + unlockpt( ptMaster ); + + char *ptSlaveName = ptsname( ptMaster ); + ptSlave = open( ptSlaveName, O_RDWR ); // In and out are the same + + struct termios termInfo; + tcgetattr( ptSlave, &termInfo ); + + termInfo.c_lflag &= ~ECHO; + termInfo.c_lflag &= ~ICANON; + tcsetattr( ptSlave, TCSADRAIN, &termInfo ); + + xtermPid = fork(); + + if (xtermPid == 0) { + xtermLaunch( ptSlaveName ); + } +} + SC_HAS_PROCESS(Trace); Trace::Trace(sc_module_name name): sc_module(name) - ,socket("socket") { +,socket("socket") { + socket.register_b_transport(this, &Trace::b_transport); - } - + + xtermSetup(); +} +Trace::~Trace() { + xtermKill( NULL ); +} void Trace::b_transport( tlm::tlm_generic_payload& trans, sc_time& delay ) { //tlm::tlm_command cmd = trans.get_command(); //sc_dt::uint64 adr = trans.get_address() / 4; @@ -14,8 +104,8 @@ void Trace::b_transport( tlm::tlm_generic_payload& trans, sc_time& delay ) { //unsigned int len = trans.get_data_length(); //unsigned char* byt = trans.get_byte_enable_ptr(); //unsigned int wid = trans.get_streaming_width(); - - cout << (char) *ptr << flush; - + + write(ptSlave, ptr, 1); + trans.set_response_status( tlm::TLM_OK_RESPONSE ); }