Skip to content

Commit

Permalink
Work dump
Browse files Browse the repository at this point in the history
  • Loading branch information
jchabloz committed Jul 19, 2024
1 parent 300a16f commit e3a50f0
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 79 deletions.
72 changes: 26 additions & 46 deletions include/vsl_integ.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
MIT License
Copyright (c) 2022-2024 Jérémie Chabloz
Copyright (c) 2024 Jérémie Chabloz
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand All @@ -25,10 +25,10 @@ SOFTWARE.
#ifndef VSL_INTEG_H
#define VSL_INTEG_H

#include <memory>
#include "cJSON.h"
#include "verilated.h"

#include <memory>

namespace vsl{

Expand All @@ -43,18 +43,21 @@ typedef enum {
} vsl_state_t;


template <class T> class VslInteg {
class VslInteg {

public:
VslInteg(T* const model, const int port=5100, const int timeout=120);
//VslInteg(VerilatedModel* const model, const int port=5100, const int timeout=120);
VslInteg(const int port=5100, const int timeout=120);
~VslInteg();

void run();

private:

//VerilatedModel* p_model; //Pointer to VerilatedModel derived class

vsl_state_t _state {VSL_STATE_INIT}; //Verisocks state
T* p_model; //Pointer to VerilatedModel derived class
cJSON* p_cmd; //Pointer to current/latest command
cJSON* p_cmd {nullptr}; //Pointer to current/latest command

int num_port {5100}; // Port number
int num_timeout_sec {120}; //Timeout, in seconds
Expand All @@ -66,57 +69,34 @@ template <class T> class VslInteg {
void main_connect();
void main_wait();
void main_process();
void main_run();
};


/*Use a collection of type map associate key and command handler function
* pointers together*/
void main_sim();

/*
What do we need to have here and in the accompanying .cc file?
* One class that:
* encapsulates the top-level state machine for the Verisocks Verilator
integration
* members
* Verilator context (pointer)
* simulation/verisocks state
* server socket current timeout setting
* descriptor for server socket
* descriptor for the currently connected client socket
* pointer to current/latest received command (CJSON*)
* methods:
* Constructor
* Destructor
* main Verisocks loop (state machine)
* Command handler function table
* Command handler sub-functions table(s)
* One class or struct that represents signals that can be used in
Verisocks commands. Maybe this class already exists and is defined in
verilated.h.
* Find a way to register callbacks - either based on simulation time or based
on signal values
* One enumeration that defines a type to support the different possible states
of the top-level state machine
*/
};



/**
* @brief Type for a command handler function pointer
*/
typedef int (*vsl_cmd_handler_t)(void);
typedef void (*vsl_cmd_handler_t)(void);

/**
* @brief Struct type for commands
* Associates a command name with a command handler function pointer
*/
typedef struct vsl_cmd {
vsl_cmd_handler_t cmd_handler; // Pointer to handler function
const char *cmd_name; // Command name
const char *cmd_key; // Command key if not cmd_name, NULL otherwise
} vsl_cmd_t;



/**
* @brief Helper macro to declare a command handler function
* @param cmd Command short name
*/
#define VSL_CMD_HANDLER(cmd) static int VSL_ ## cmd ## _cmd_handler()
#define VSL_CMD_HANDLER(cmd) static void VSL_ ## cmd ## _cmd_handler()

/**
* @brief Helper marco to define a command structure with a command name and
Expand Down
167 changes: 134 additions & 33 deletions src/vsl_integ.cpp
Original file line number Diff line number Diff line change
@@ -1,43 +1,77 @@
/*
MIT License
Copyright (c) 2024 Jérémie Chabloz
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#include <cstdlib>
#include <cstdio>
#include <type_traits>
//#include <unistd.h>
//#include <netdb.h>
//#include <sys/time.h>

#include "vsl_integ.h"
#include "verilated.h"

//#include "verilated.h"
//#include "verilated_vpi.h"
#include "vs_server.h"
#include "vs_logging.h"

#include "vs_msg.h"
//#include "cJSON.h"

// #include <cstdlib>
// #include <cstdio>
//#include <type_traits>
#include <unistd.h>
#include <netdb.h>
//#include <sys/time.h>

namespace vsl{

template <class T> VslInteg<T>::VslInteg(T* const _p_model__, const int port, const int timeout) {
static_assert(std::is_base_of<VerilatedModel, T>::value,
"Expected a Verilated model for type");
/* Constructor */
VslInteg::VslInteg(const int port, const int timeout) {
num_port = port;
num_timeout_sec = timeout;
}
/*
template<class T> VslInteg::VslInteg(T* const _p_model__, const int port,
const int timeout) {
// static_assert(std::is_base_of<VerilatedModel, T>::value,
// "Expected a Verilated model for type");
p_model = _p_model__;
num_port = port;
num_timeout_sec = timeout;
}
*/


template <class T> VslInteg<T>::~VslInteg() {
if (0 <= fd_server_socket) close(fd_server_socket);
if (NULL != p_cmd) cJSON_Delete(p_cmd);
/* Destructor */
VslInteg::~VslInteg() {
if (0 < fd_server_socket) close(fd_server_socket);
if (nullptr != p_cmd) cJSON_Delete(p_cmd);
}


template <class T> void VslInteg<T>::run() {
void VslInteg::run() {
printf("******************************************\n");
printf("* __ __ _ _ *\n");
printf("* \\ \\ / /__ _ _(_)___ ___ __| |__ ___ *\n");
printf("* \\ V / -_) '_| (_-</ _ \\/ _| / /(_-< *\n");
printf("* \\_/\\___|_| |_/__/\\___/\\__|_\\_\\/__/ *\n");
printf("* *\n");
printf("* For Verilator *\n");
printf("* (c) 2022-2024 Jérémie Chabloz *\n");
printf("* For Verilator integration *\n");
printf("******************************************\n");

while(true) {
Expand All @@ -58,7 +92,7 @@ template <class T> void VslInteg<T>::run() {
}
break;
case VSL_STATE_SIM_RUNNING:
main_run();
main_sim();
break;
case VSL_STATE_EXIT:
if (0 <= fd_server_socket) {
Expand All @@ -69,7 +103,8 @@ template <class T> void VslInteg<T>::run() {
return;
case VSL_STATE_ERROR:
default:
vs_log_error("Exiting Verisocks main loop (error state)");
vs_log_mod_error("vsl",
"Exiting Verisocks main loop (error state)");
if (0 <= fd_server_socket) {
close(fd_server_socket);
fd_server_socket = -1;
Expand All @@ -82,19 +117,19 @@ template <class T> void VslInteg<T>::run() {
}


template <class T> void VslInteg<T>::main_init() {
void VslInteg::main_init() {

/* Check state consistency */
if (_state != VSL_STATE_INIT) {
vs_log_error("Wrong state in init function %d", _state);
vs_log_mod_error("vsl", "Wrong state in init function %d", _state);
_state = VSL_STATE_ERROR;
return;
}

/* Create server socket */
fd_server_socket = vs_server_make_socket(num_port);
if (0 > fd_server_socket) {
vs_log_error("Issue making socket at port %d", num_port);
vs_log_mod_error("vsl", "Issue making socket at port %d", num_port);
_state = VSL_STATE_ERROR;
return;
}
Expand All @@ -103,42 +138,108 @@ template <class T> void VslInteg<T>::main_init() {
struct sockaddr_in sin;
socklen_t len = sizeof(sin);
if (0 > getsockname(fd_server_socket, (struct sockaddr *) &sin, &len)) {
vs_log_error("Issue getting socket address info");
vs_log_mod_error("vsl", "Issue getting socket address info");
_state = VSL_STATE_ERROR;
return;
}
uint32_t s_addr = ntohl(sin.sin_addr.s_addr);

/* Logs server address and port number */
vs_log_info("Server address: %d.%d.%d.%d",
vs_log_mod_info("vsl", "Server address: %d.%d.%d.%d",
(s_addr & 0xff000000) >> 24u,
(s_addr & 0x00ff0000) >> 16u,
(s_addr & 0x0000ff00) >> 8u,
(s_addr & 0x000000ff)
);
vs_log_info("Port: %d", ntohs(sin.sin_port));
vs_log_mod_info("vsl", "Port: %d", ntohs(sin.sin_port));

/* Update state */
_state = VSL_STATE_CONNECT;
return;
}


template <class T> void VslInteg<T>::main_connect() {
void VslInteg::main_connect() {
char hostname_buffer[128];
struct timeval timeout;
timeout.tv_sec = num_timeout_sec;
timeout.tv_usec = 0;

vs_log_mod_debug(
"vsl",
"Waiting for a client to connect (%ds timeout) ...",
(int) timeout.tv_sec);
fd_client_socket = vs_server_accept(
fd_server_socket, hostname_buffer, sizeof(hostname_buffer), &timeout);
if (0 > fd_client_socket) {
vs_log_mod_error("vsl", "Failed to connect");
_state = VSL_STATE_ERROR;
return;
}
vs_log_mod_info("vsl", "Connected to %s", hostname_buffer);
_state = VSL_STATE_WAITING;
return;
}

template <class T> void VslInteg<T>::main_wait() {
}

template <class T> void VslInteg<T>::main_process() {
void VslInteg::main_wait() {
char read_buffer[4096];
int msg_len;
msg_len = vs_msg_read(fd_client_socket,
read_buffer,
sizeof(read_buffer));
if (0 > msg_len) {
close(fd_client_socket);
vs_log_mod_debug(
"vsl",
"Lost connection. Waiting for a client to (re-)connect ..."
);
_state = VSL_STATE_CONNECT;
return;
}
if (msg_len >= (int) sizeof(read_buffer)) {
read_buffer[sizeof(read_buffer) - 1] = '\0';
vs_log_mod_warning(
"vsl",
"Received message longer than RX buffer, discarding it"
);
vs_msg_return(fd_client_socket, "error",
"Message too long - Discarding");
return;
}
else {
read_buffer[msg_len] = '\0';
}
vs_log_mod_debug("vsl", "Message: %s", &read_buffer[2]);
p_cmd = vs_msg_read_json(read_buffer);
if (nullptr != p_cmd) {
_state = VSL_STATE_PROCESSING;
return;
}
vs_log_mod_warning(
"vsl",
"Received message content cannot be interpreted as a valid JSON \
content. Discarding it."
);
vs_msg_return(fd_client_socket, "error",
"Invalid message content - Discarding");
return;
}

template <class T> void VslInteg<T>::main_run() {

void VslInteg::main_process() {
vs_log_mod_info("vsl", "Processing command");
//TODO
vs_msg_return(fd_client_socket, "info", "Command processing not yet implemented");
_state = VSL_STATE_WAITING;
}


void VslInteg::main_sim() {
vs_log_mod_info("vsl", "Simulation ongoing");
//TODO
}

} //namespace vsl

int main() { } //Temporary for compilation
//EOF

0 comments on commit e3a50f0

Please sign in to comment.