risc-v-tlm/src/Trace.cpp

118 lines
2.3 KiB
C++

/*!
\file Trace.cpp
\brief Basic TLM-2 Trace module
\author Màrius Montón
\date September 2018
*/
// SPDX-License-Identifier: GPL-3.0-or-later
#include <stdio.h>
#include <fstream>
#include <iostream>
#include <termios.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
// Code partially 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);
if (ptMaster != -1) {
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_core::sc_module_name name) :
sc_module(name), 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_core::sc_time &delay) {
unsigned char *ptr = trans.get_data_ptr();
write(ptSlave, ptr, 1);
trans.set_response_status(tlm::TLM_OK_RESPONSE);
}