aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerry Zhao <jerryz123@berkeley.edu>2022-12-11 10:56:56 -0800
committerJerry Zhao <jerryz123@berkeley.edu>2022-12-13 12:21:11 -0800
commit68a3039598dc418b0fd25e971746bee31e28b3ea (patch)
tree71b301b7463dccf5dae0f037684f8700bd155eb8
parent572d5e44097d9e37c1233a8df4b6bba0c387363c (diff)
downloadspike-68a3039598dc418b0fd25e971746bee31e28b3ea.zip
spike-68a3039598dc418b0fd25e971746bee31e28b3ea.tar.gz
spike-68a3039598dc418b0fd25e971746bee31e28b3ea.tar.bz2
Move boost asio socket interface to socketif_t
This reduces dependencies on config.h in sim.h
-rw-r--r--riscv/interactive.cc73
-rw-r--r--riscv/riscv.mk.in4
-rw-r--r--riscv/sim.cc25
-rw-r--r--riscv/sim.h21
-rw-r--r--riscv/socketif.cc74
-rw-r--r--riscv/socketif.h32
-rw-r--r--spike_main/spike.cc27
7 files changed, 144 insertions, 112 deletions
diff --git a/riscv/interactive.cc b/riscv/interactive.cc
index 251a1ca..02ba227 100644
--- a/riscv/interactive.cc
+++ b/riscv/interactive.cc
@@ -1,10 +1,12 @@
// See LICENSE for license details.
+#include "config.h"
#include "sim.h"
#include "decode.h"
#include "disasm.h"
#include "mmu.h"
#include "vector_unit.h"
+#include "socketif.h"
#include <sys/mman.h>
#include <termios.h>
#include <map>
@@ -247,58 +249,6 @@ static std::string readline(int fd)
return s.substr(initial_s_len);
}
-#ifdef HAVE_BOOST_ASIO
-// read input command string
-std::string sim_t::rin(boost::asio::streambuf *bout_ptr) {
- std::string s;
- if (acceptor_ptr) { // if we are listening, get commands from socket
- try {
- socket_ptr.reset(new boost::asio::ip::tcp::socket(*io_service_ptr));
- acceptor_ptr->accept(*socket_ptr); // wait for someone to open connection
- boost::asio::streambuf buf;
- boost::asio::read_until(*socket_ptr, buf, "\n"); // wait for command
- s = boost::asio::buffer_cast<const char*>(buf.data());
- boost::erase_all(s, "\r"); // get rid off any cr and lf
- boost::erase_all(s, "\n");
- // The socket client is a web server and it appends the IP of the computer
- // that sent the command from its web browser.
-
- // For now, erase the IP if it is there.
- boost::regex re(" ((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}"
- "(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])$");
- s = boost::regex_replace(s, re, (std::string)"");
-
- // TODO: check the IP against the IP used to upload RISC-V source files
- } catch (std::exception& e) {
- std::cerr << e.what() << std::endl;
- }
- // output goes to socket
- sout_.rdbuf(bout_ptr);
- } else { // if we are not listening on a socket, get commands from terminal
- s = readline(2); // 2 is stderr, but when doing reads it reverts to stdin
- // output goes to stderr
- sout_.rdbuf(std::cerr.rdbuf());
- }
- return s;
-}
-
-// write sout_ to socket (via bout)
-void sim_t::wout(boost::asio::streambuf *bout_ptr) {
- if (!cmd_file && acceptor_ptr) { // only if we are not getting command inputs from a file
- // and if a socket has been created
- try {
- boost::system::error_code ignored_error;
- boost::asio::write(*socket_ptr, *bout_ptr, boost::asio::transfer_all(), ignored_error);
- socket_ptr->close(); // close the socket after each command input/ouput
- // This is need to in order to make the socket interface
- // acessible by HTTP GET via a socket client in a web server.
- } catch (std::exception& e) {
- std::cerr << e.what() << std::endl;
- }
- }
-}
-#endif
-
void sim_t::interactive()
{
typedef void (sim_t::*interactive_func)(const std::string&, const std::vector<std::string>&);
@@ -330,9 +280,6 @@ void sim_t::interactive()
while (!done())
{
-#ifdef HAVE_BOOST_ASIO
- boost::asio::streambuf bout; // socket output
-#endif
std::string s;
char cmd_str[MAX_CMD_STR+1]; // only used for following fscanf
// first get commands from file, if cmd_file has been set
@@ -345,10 +292,14 @@ void sim_t::interactive()
// when there are no commands left from file or if there was no file from the beginning
cmd_file = NULL; // mark file pointer as being not valid, so any method can test this easily
#ifdef HAVE_BOOST_ASIO
- s = rin(&bout); // get command string from socket or terminal
-#else
- s = readline(2); // 2 is stderr, but when doing reads it reverts to stdin
+ if (socketif) {
+ s = socketif->rin(sout_); // get command string from socket or terminal
+ }
+ else
#endif
+ {
+ s = readline(2); // 2 is stderr, but when doing reads it reverts to stdin
+ }
}
std::stringstream ss(s);
@@ -360,7 +311,8 @@ void sim_t::interactive()
set_procs_debug(true);
step(1);
#ifdef HAVE_BOOST_ASIO
- wout(&bout); // socket output, if required
+ if (socketif)
+ socketif->wout(); // socket output, if required
#endif
continue;
}
@@ -380,7 +332,8 @@ void sim_t::interactive()
out << "Bad or missing arguments for command " << cmd << std::endl;
}
#ifdef HAVE_BOOST_ASIO
- wout(&bout); // socket output, if required
+ if (socketif)
+ socketif->wout(); // socket output, if required
#endif
}
ctrlc_pressed = false;
diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in
index 1eee43a..efe2bd0 100644
--- a/riscv/riscv.mk.in
+++ b/riscv/riscv.mk.in
@@ -42,7 +42,8 @@ riscv_hdrs = \
jtag_dtm.h \
csrs.h \
triggers.h \
- vector_unit.h
+ vector_unit.h \
+ socketif.h \
riscv_install_hdrs = \
abstract_device.h \
@@ -96,6 +97,7 @@ riscv_srcs = \
csrs.cc \
triggers.cc \
vector_unit.cc \
+ socketif.cc \
$(riscv_gen_srcs) \
riscv_test_srcs =
diff --git a/riscv/sim.cc b/riscv/sim.cc
index bb1d76b..8a65797 100644
--- a/riscv/sim.cc
+++ b/riscv/sim.cc
@@ -1,5 +1,6 @@
// See LICENSE for license details.
+#include "config.h"
#include "sim.h"
#include "mmu.h"
#include "dts.h"
@@ -7,6 +8,7 @@
#include "byteorder.h"
#include "platform.h"
#include "libfdt.h"
+#include "socketif.h"
#include <fstream>
#include <map>
#include <iostream>
@@ -35,9 +37,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted,
const debug_module_config_t &dm_config,
const char *log_path,
bool dtb_enabled, const char *dtb_file,
-#ifdef HAVE_BOOST_ASIO
- boost::asio::io_service *io_service_ptr, boost::asio::ip::tcp::acceptor *acceptor_ptr, // option -s
-#endif
+ bool socket_enabled,
FILE *cmd_file) // needed for command line option --cmd
: htif_t(args),
isa(cfg->isa(), cfg->priv()),
@@ -49,10 +49,6 @@ sim_t::sim_t(const cfg_t *cfg, bool halted,
dtb_enabled(dtb_enabled),
log_file(log_path),
cmd_file(cmd_file),
-#ifdef HAVE_BOOST_ASIO
- io_service_ptr(io_service_ptr), // socket interface
- acceptor_ptr(acceptor_ptr),
-#endif
sout_(nullptr),
current_step(0),
current_proc(0),
@@ -74,6 +70,21 @@ sim_t::sim_t(const cfg_t *cfg, bool halted,
debug_module.add_device(&bus);
+ socketif = NULL;
+#ifdef HAVE_BOOST_ASIO
+ if (socket_enabled) {
+ socketif = new socketif_t();
+ }
+#else
+ if (socket_enabled) {
+ fputs("Socket support requires compilation with boost asio; "
+ "please rebuild the riscv-isa-sim project using "
+ "\"configure --with-boost-asio\".\n",
+ stderr);
+ abort();
+ }
+#endif
+
#ifndef RISCV_ENABLE_DUAL_ENDIAN
if (cfg->endianness != memif_endianness_little) {
fputs("Big-endian support has not been prroperly enabled; "
diff --git a/riscv/sim.h b/riscv/sim.h
index 8ca06fe..b3b5d40 100644
--- a/riscv/sim.h
+++ b/riscv/sim.h
@@ -4,13 +4,6 @@
#define _RISCV_SIM_H
#include "config.h"
-
-#ifdef HAVE_BOOST_ASIO
-#include <boost/algorithm/string.hpp>
-#include <boost/regex.hpp>
-#include <boost/asio.hpp>
-#endif
-
#include "cfg.h"
#include "debug_module.h"
#include "devices.h"
@@ -27,6 +20,7 @@
class mmu_t;
class remote_bitbang_t;
+class socketif_t;
// this class encapsulates the processors and memory in a RISC-V machine.
class sim_t : public htif_t, public simif_t
@@ -38,9 +32,7 @@ public:
const std::vector<std::string>& args,
const debug_module_config_t &dm_config, const char *log_path,
bool dtb_enabled, const char *dtb_file,
-#ifdef HAVE_BOOST_ASIO
- boost::asio::io_service *io_service_ptr_ctor, boost::asio::ip::tcp::acceptor *acceptor_ptr_ctor, // option -s
-#endif
+ bool socket_enabled,
FILE *cmd_file); // needed for command line option --cmd
~sim_t();
@@ -89,14 +81,7 @@ private:
FILE *cmd_file; // pointer to debug command input file
-#ifdef HAVE_BOOST_ASIO
- // the following are needed for command socket interface
- boost::asio::io_service *io_service_ptr;
- boost::asio::ip::tcp::acceptor *acceptor_ptr;
- std::unique_ptr<boost::asio::ip::tcp::socket> socket_ptr;
- std::string rin(boost::asio::streambuf *bout_ptr); // read input command string
- void wout(boost::asio::streambuf *bout_ptr); // write output to socket
-#endif
+ socketif_t *socketif;
std::ostream sout_; // used for socket and terminal interface
processor_t* get_core(const std::string& i);
diff --git a/riscv/socketif.cc b/riscv/socketif.cc
new file mode 100644
index 0000000..0884752
--- /dev/null
+++ b/riscv/socketif.cc
@@ -0,0 +1,74 @@
+// See LICENSE for license details.
+
+#include "socketif.h"
+
+#ifdef HAVE_BOOST_ASIO
+
+#include <iostream>
+
+socketif_t::socketif_t()
+{
+ try { // create socket server
+ using boost::asio::ip::tcp;
+ io_service_ptr = new boost::asio::io_service;
+ acceptor_ptr = new tcp::acceptor(*io_service_ptr, tcp::endpoint(tcp::v4(), 0));
+ // acceptor is created passing argument port=0, so O.S. will choose a free port
+ std::string name = boost::asio::ip::host_name();
+ std::cout << "Listening for debug commands on " << name.substr(0,name.find('.'))
+ << " port " << acceptor_ptr->local_endpoint().port() << " ." << std::endl;
+ // at the end, add space and some other character for convenience of javascript .split(" ")
+ } catch (std::exception& e) {
+ std::cerr << e.what() << std::endl;
+ exit(-1);
+ }
+}
+
+socketif_t::~socketif_t()
+{
+ delete io_service_ptr;
+ delete acceptor_ptr;
+}
+
+// read input command string
+std::string socketif_t::rin(std::ostream &sout_)
+{
+ std::string s;
+ try {
+ socket_ptr.reset(new boost::asio::ip::tcp::socket(*io_service_ptr));
+ acceptor_ptr->accept(*socket_ptr); // wait for someone to open connection
+ boost::asio::streambuf buf;
+ boost::asio::read_until(*socket_ptr, buf, "\n"); // wait for command
+ s = boost::asio::buffer_cast<const char*>(buf.data());
+ boost::erase_all(s, "\r"); // get rid off any cr and lf
+ boost::erase_all(s, "\n");
+ // The socket client is a web server and it appends the IP of the computer
+ // that sent the command from its web browser.
+
+ // For now, erase the IP if it is there.
+ boost::regex re(" ((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}"
+ "(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])$");
+ s = boost::regex_replace(s, re, (std::string)"");
+
+ // TODO: check the IP against the IP used to upload RISC-V source files
+ } catch (std::exception& e) {
+ std::cerr << e.what() << std::endl;
+ }
+ // output goes to socket
+ sout_.rdbuf(&bout);
+ return s;
+}
+
+// write sout_ to socket (via bout)
+void socketif_t::wout() {
+ try {
+ boost::system::error_code ignored_error;
+ boost::asio::write(*socket_ptr, bout, boost::asio::transfer_all(), ignored_error);
+ socket_ptr->close(); // close the socket after each command input/ouput
+ // This is need to in order to make the socket interface
+ // acessible by HTTP GET via a socket client in a web server.
+ } catch (std::exception& e) {
+ std::cerr << e.what() << std::endl;
+ }
+}
+
+#endif
diff --git a/riscv/socketif.h b/riscv/socketif.h
new file mode 100644
index 0000000..7ce9142
--- /dev/null
+++ b/riscv/socketif.h
@@ -0,0 +1,32 @@
+// See LICENSE for license details.
+
+#ifndef _RISCV_SOCKETIF_H
+#define _RISCV_SOCKETIF_H
+
+#include "config.h"
+
+#ifdef HAVE_BOOST_ASIO
+
+#include <boost/algorithm/string.hpp>
+#include <boost/regex.hpp>
+#include <boost/asio.hpp>
+
+class socketif_t
+{
+public:
+ socketif_t();
+ ~socketif_t();
+
+ std::string rin(std::ostream &sout_); // read input command string
+ void wout(); // write output to socket
+
+private:
+ // the following are needed for command socket interface
+ boost::asio::io_service *io_service_ptr;
+ boost::asio::ip::tcp::acceptor *acceptor_ptr;
+ std::unique_ptr<boost::asio::ip::tcp::socket> socket_ptr;
+ boost::asio::streambuf bout;
+};
+
+#endif
+#endif
diff --git a/spike_main/spike.cc b/spike_main/spike.cc
index 5815761..f0d6920 100644
--- a/spike_main/spike.cc
+++ b/spike_main/spike.cc
@@ -497,29 +497,6 @@ int main(int argc, char** argv)
}
}
-#ifdef HAVE_BOOST_ASIO
- boost::asio::io_service *io_service_ptr = NULL; // needed for socket command interface option -s
- boost::asio::ip::tcp::acceptor *acceptor_ptr = NULL;
- if (socket) { // if command line option -s is set
- try
- { // create socket server
- using boost::asio::ip::tcp;
- io_service_ptr = new boost::asio::io_service;
- acceptor_ptr = new tcp::acceptor(*io_service_ptr, tcp::endpoint(tcp::v4(), 0));
- // aceptor is created passing argument port=0, so O.S. will choose a free port
- std::string name = boost::asio::ip::host_name();
- std::cout << "Listening for debug commands on " << name.substr(0,name.find('.'))
- << " port " << acceptor_ptr->local_endpoint().port() << " ." << std::endl;
- // at the end, add space and some other character for convenience of javascript .split(" ")
- }
- catch (std::exception& e)
- {
- std::cerr << e.what() << std::endl;
- exit(-1);
- }
- }
-#endif
-
if (cfg.explicit_hartids) {
if (nprocs.overridden() && (nprocs() != cfg.nprocs())) {
std::cerr << "Number of specified hartids ("
@@ -542,9 +519,7 @@ int main(int argc, char** argv)
sim_t s(&cfg, halted,
mems, plugin_devices, htif_args, dm_config, log_path, dtb_enabled, dtb_file,
-#ifdef HAVE_BOOST_ASIO
- io_service_ptr, acceptor_ptr,
-#endif
+ socket,
cmd_file);
std::unique_ptr<remote_bitbang_t> remote_bitbang((remote_bitbang_t *) NULL);
std::unique_ptr<jtag_dtm_t> jtag_dtm(