Commit 2e05526f authored by Leon Hiemstra's avatar Leon Hiemstra

support ranges in /unb[] and pn[]. Removed 'cat'

parent 05171c29
......@@ -25,7 +25,7 @@ make
# Configure server:
edit /etc/uniboard2.conf
vi src/uniboard2.conf
Usage:
Startup server process:
......
......@@ -72,8 +72,6 @@ CMDstatus CMD::command(string line, TermOutput& termout, string& cmdname, Server
*/
if(cmd == INFO) {
req_ret = Info(argc,argv,termout,sd);
} else if(cmd == CAT) {
req_ret = Cat(argc,argv,termout,sd);
} else if(cmd == MREAD) {
req_ret = Mread(argc,argv,termout,sd);
} else if(cmd == MWRITE) {
......@@ -87,7 +85,7 @@ CMDstatus CMD::command(string line, TermOutput& termout, string& cmdname, Server
req_ret.status=CMD_STATUS_OK;
termout.strout << "Available commands:" << endl;
for(uint i=0;i<supported_cmds.size();i++) {
termout.strout << i << ". " << supported_cmds[i] << " [options]" << endl;
termout.strout << i << ". " << supported_cmds[i] << endl;
}
termout.strout << endl << "Server also supports '>' and '>>' and '|' operators like the Bash shell" << endl;
termout.strout << endl << "Syntax help: use option -h for each command" << endl;
......@@ -181,66 +179,57 @@ CMDstatus CMD::Info(int argc, char* argv[], TermOutput& termout, Serverdat *sd)
CMDstatus ret={CMD_STATUS_ERROR,0,0};
std::vector<int> nodes;
po::options_description desc("Uniboard system info");
desc.add_options()
po::options_description generic("Uniboard register info");
generic.add_options()
("help,h", "shows this help text")
("version", "shows version")
("all,a", "select all nodes")
("gn", po::value<std::string>(),
"Node global number. Example: [3,4:7] for PN 3 on UniBoard 0 and PN0:3 on UniBoard 1")
("pn", po::value<std::string>(),
"Node local number: [0:3] for PN 0, 1, 2 and 3")
("unb", po::value<std::string>(),
"UniBoard number: [0,2:4] for UniBoard 0, 2, 3 and 4")
("list,l", "display uniboard map")
;
po::options_description hidden("hidden options");
hidden.add_options()
("file,f", po::value<std::string>(), "filename")
;
po::options_description cmdline_options;
cmdline_options.add(generic).add(hidden);
po::options_description visible("Allowed options");
visible.add(generic);
try {
po::positional_options_description p;
p.add("file", -1);
po::variables_map vm;
po::store(po::parse_command_line(argc,argv,desc), vm);
po::store(po::command_line_parser(argc,argv).
options(cmdline_options).positional(p).run(), vm);
po::notify(vm);
if (vm.count("help")) {
termout.strout << "Usage: " << INFO << " [options]" << endl << "Options: " << desc;
termout.strout << "Usage: " << INFO << " [options] /unb..." << endl
<< "Options: " << generic << endl
<< "Example: ls /unb0/pn3" << endl;
return {CMD_STATUS_OK,0,0};
}
if (vm.count("version")) {
termout.strout << "Version: " << SDPUNB_VERSION << endl;
return {CMD_STATUS_OK,0,0};
}
if (vm.count("unb") && vm.count("pn")) {
string unb=vm["unb"].as<string>();
string pn="[]";
if (vm.count("pn")) pn=vm["pn"].as<string>();
istringstream vecstr(unb);
std::vector<int> unbs=parse_int_vector_range(vecstr);
vecstr.str(pn);
std::vector<int> pns=parse_int_vector_range(vecstr);
nodes = sd->unb->unb_pn__to__nodes(unbs,pns);
} else if (vm.count("gn")) {
string gn=vm["gn"].as<string>();
istringstream vecstr(gn);
nodes=parse_int_vector_range(vecstr);
} else if (vm.count("all")) {
nodes=sd->unb->get_nodes();
if (vm.count("file")) {
string filename=vm["file"].as<string>();
nodes = sd->unb->path_to_node(filename);
}
if(nodes.size()==0) throw runtime_error("missing argument(s), add options: --gn or --unb,--pn");
if(nodes.size()==0) throw runtime_error("missing file(s), add /unb.../pn...");
if(vm.count("list")) {
for(auto node : nodes) {
RegisterMap *regmap = sd->unb->get_RegisterMap(termout, node);
for(auto node : nodes) {
RegisterMap *regmap = sd->unb->get_RegisterMap(termout, node);
std::string prefix = sd->unb->string_node_id(node);
std::vector<std::string> regnames = regmap->getRegnames_full(prefix);
for(auto m : regnames) {
termout.strout << m << endl;
}
std::string prefix = sd->unb->string_node_id(node);
std::vector<std::string> regnames = regmap->getRegnames_full(prefix);
for(auto m : regnames) {
termout.strout << m << endl;
}
}
}
ret.status=CMD_STATUS_OK;
} catch(po::error& e) {
termout.strerr << e.what() << endl;
......@@ -253,60 +242,50 @@ CMDstatus CMD::Info(int argc, char* argv[], TermOutput& termout, Serverdat *sd)
CMDstatus CMD::Mread(int argc, char* argv[], TermOutput& termout, Serverdat *sd)
{
CMDstatus ret={CMD_STATUS_ERROR,0,0};
std::vector<int> nodes;
po::options_description desc("Memory mapped read");
desc.add_options()
po::options_description generic("Generic read");
generic.add_options()
("help,h", "shows this help text")
("all,a", "select all nodes")
("gn", po::value<std::string>(),
"Node global number. Example: [3,4:7] for PN 3 on UniBoard 0 and PN0:3 on UniBoard 1")
("pn", po::value<std::string>(),
"Node local number: [0:3] for PN 0, 1, 2 and 3")
("unb", po::value<std::string>(),
"UniBoard number: [0,2:4] for UniBoard 0, 2, 3 and 4")
("addr", po::value<std::string>(),"base address string e.g. system/info/info")
("offs", po::value<uint>(),"offset from base address (per dword)")
("nvalues", po::value<uint>(),"number of dwords to read")
("offs", po::value<uint>(),"offset from base address (per dword) (default=0)")
("nvalues", po::value<uint>(),"number of dwords to read (default=all)")
;
po::options_description hidden("hidden options");
hidden.add_options()
("file,f", po::value<std::string>(), "filename")
;
po::options_description cmdline_options;
cmdline_options.add(generic).add(hidden);
po::options_description visible("Allowed options");
visible.add(generic);
try {
po::positional_options_description p;
p.add("file", -1);
po::variables_map vm;
po::store(po::parse_command_line(argc,argv,desc), vm);
po::store(po::command_line_parser(argc,argv).
options(cmdline_options).positional(p).run(), vm);
po::notify(vm);
if (vm.count("help")) {
termout.strout << "usage: " << MREAD << " [options]" << endl << "Options: " << desc;
termout.strout << "usage: " << MREAD << " [options] file(s)" << endl
<< "Options: " << generic << endl
<< "Example 1: read --nvalues=1 /unb0/pn3/mm/ppsh/ppsh/status" << endl
<< "Example 2: read /unb[0:10,15]/pn[0:3]/mm/ppsh/ppsh/status" << endl
<< "Example 3: read /unb0/pn[3]/dev/name" << endl;
return {CMD_STATUS_OK,0,0};
}
if (vm.count("unb") && vm.count("pn")) {
string unb=vm["unb"].as<string>();
string pn="[]";
if (vm.count("pn")) pn=vm["pn"].as<string>();
istringstream vecstr(unb);
std::vector<int> unbs=parse_int_vector_range(vecstr);
vecstr.str(pn);
std::vector<int> pns=parse_int_vector_range(vecstr);
nodes = sd->unb->unb_pn__to__nodes(unbs,pns);
} else if (vm.count("gn")) {
string gn=vm["gn"].as<string>();
istringstream vecstr(gn);
nodes=parse_int_vector_range(vecstr);
} else if (vm.count("all")) {
nodes=sd->unb->get_nodes();
}
if(nodes.size()==0) throw runtime_error("missing argument(s), add options: --gn or --unb,--pn");
string addr_str="";
uint offs=0;
uint nvalues=0;
if(vm.count("addr")) { addr_str=vm["addr"].as<string>(); }
if(vm.count("offs")) { offs=vm["offs"].as<uint>(); }
if(vm.count("nvalues")) { nvalues=vm["nvalues"].as<uint>(); }
} else if (vm.count("file")) {
string addr_str="";
uint offs=0;
int nvalues=-1;
if(vm.count("file")) { addr_str=vm["file"].as<string>(); }
if(vm.count("offs")) { offs=vm["offs"].as<uint>(); }
if(vm.count("nvalues")) { nvalues=vm["nvalues"].as<int>(); }
if(sd->unb->read(termout,addr_str,offs,nvalues)) ret.status=CMD_STATUS_OK;
} else throw runtime_error("missing argument(s)");
if(sd->unb->mread(termout,nodes,addr_str,offs,nvalues)) ret.status=CMD_STATUS_OK;
} catch(po::error& e) {
termout.strerr << e.what() << endl;
} catch(std::exception& e) {
......@@ -318,88 +297,13 @@ CMDstatus CMD::Mread(int argc, char* argv[], TermOutput& termout, Serverdat *sd)
CMDstatus CMD::Mwrite(int argc, char* argv[], TermOutput& termout, Serverdat *sd)
{
CMDstatus ret={CMD_STATUS_ERROR,0,0};
std::vector<int> nodes;
po::options_description desc("Memory mapped write");
desc.add_options()
po::options_description generic("Memory mapped write");
generic.add_options()
("help,h", "shows this help text")
("all,a", "select all nodes")
("gn", po::value<std::string>(),
"Node global number. Example: [3,4:7] for PN 3 on UniBoard 0 and PN0:3 on UniBoard 1")
("pn", po::value<std::string>(),
"Front Node local number: [0:3] for PN 0, 1, 2 and 3")
("unb", po::value<std::string>(),
"UniBoard number: [0,2:4] for UniBoard 0, 2, 3 and 4")
("addr", po::value<std::string>(),"base address string e.g. system/info/info")
("offs", po::value<uint>(),"offset from base address (per dword)")
("data", po::value<std::string>(),"data to write there: e.g. [1,2,3,4]")
;
try {
po::variables_map vm;
po::store(po::parse_command_line(argc,argv,desc), vm);
po::notify(vm);
if (vm.count("help")) {
termout.strout << "usage: " << MWRITE << " [options]" << endl << "Options: " << desc;
return {CMD_STATUS_OK,0,0};
}
if (vm.count("unb") && vm.count("pn")) {
string unb=vm["unb"].as<string>();
string pn="[]";
if (vm.count("pn")) pn=vm["pn"].as<string>();
istringstream vecstr(unb);
std::vector<int> unbs=parse_int_vector_range(vecstr);
vecstr.str(pn);
std::vector<int> pns=parse_int_vector_range(vecstr);
nodes = sd->unb->unb_pn__to__nodes(unbs,pns);
} else if (vm.count("gn")) {
string gn=vm["gn"].as<string>();
istringstream vecstr(gn);
nodes=parse_int_vector_range(vecstr);
} else if (vm.count("all")) {
nodes=sd->unb->get_nodes();
}
if(nodes.size()==0) throw runtime_error("missing argument(s), add options: --gn or --unb,--pb");
string addr_str="";
uint offs=0;
std::vector<int64_t> data64;
std::vector<int> data;
if(vm.count("addr")) { addr_str=vm["addr"].as<string>(); }
if(vm.count("offs")) { offs=vm["offs"].as<uint>(); }
if(vm.count("data")) {
string datastr=vm["data"].as<string>();
istringstream vecstr(datastr);
data64=parse_int64_vector_range(vecstr);
data.resize(data64.size());
for(uint i=0;i<data64.size();i++) {
if((data64[i] & 0xffffffff00000000) != 0) {
cout << "cmd() mwrite() warning 64bit value detected, truncating!!!" << endl;
termout.strerr << "cmd() mwrite() warning 64bit value detected, truncating!!!" << endl;
}
data[i]=(int)data64[i];
}
}
if(sd->unb->mwrite(termout,nodes,addr_str,offs,data)) ret.status=CMD_STATUS_OK;
} catch(po::error& e) {
termout.strerr << e.what() << endl;
} catch(std::exception& e) {
termout.strerr << e.what() << endl;
}
return ret;
}
CMDstatus CMD::Cat(int argc, char* argv[], TermOutput& termout, Serverdat *sd)
{
CMDstatus ret={CMD_STATUS_ERROR,0,0};
po::options_description generic("concatenate files and print on the standard output");
generic.add_options()
("help,h", "shows this help text")
;
po::options_description hidden("hidden options");
hidden.add_options()
("file,f", po::value<std::string>(), "filename")
......@@ -419,14 +323,34 @@ CMDstatus CMD::Cat(int argc, char* argv[], TermOutput& termout, Serverdat *sd)
po::store(po::command_line_parser(argc,argv).
options(cmdline_options).positional(p).run(), vm);
po::notify(vm);
if (vm.count("help")) {
termout.strout << "usage: " << CAT << " [options]" << endl << "Options: " << generic;
termout.strout << "usage: " << MWRITE << " [options] file(s)" << endl
<< "Options: " << generic << endl
<< "Example: mwrite --offs=1 --data=[1,2,3,4] /unb0/pn3/mm/sens/sens/temp_high" << endl;
return {CMD_STATUS_OK,0,0};
} else if (vm.count("file")) {
string filename=vm["file"].as<string>();
if(sd->unb->read(termout,filename)) ret.status=CMD_STATUS_OK;
string addr_str="";
uint offs=0;
std::vector<int64_t> data64;
std::vector<int> data;
if(vm.count("file")) { addr_str=vm["file"].as<string>(); }
if(vm.count("offs")) { offs=vm["offs"].as<uint>(); }
if(vm.count("data")) {
string datastr=vm["data"].as<string>();
istringstream vecstr(datastr);
data64=parse_int64_vector_range(vecstr);
data.resize(data64.size());
for(uint i=0;i<data64.size();i++) {
if((data64[i] & 0xffffffff00000000) != 0) {
cout << "cmd() mwrite() warning 64bit value detected, truncating!!!" << endl;
termout.strerr << "cmd() mwrite() warning 64bit value detected, truncating!!!" << endl;
}
data[i]=(int)data64[i];
}
}
if(sd->unb->mwrite(termout,addr_str,offs,data)) ret.status=CMD_STATUS_OK;
} else throw runtime_error("missing argument(s)");
} catch(po::error& e) {
termout.strerr << e.what() << endl;
} catch(std::exception& e) {
......@@ -435,6 +359,7 @@ CMDstatus CMD::Cat(int argc, char* argv[], TermOutput& termout, Serverdat *sd)
return ret;
}
/***********************
* End user commands *
***********************/
......
......@@ -33,8 +33,7 @@ private:
const std::string HELP="help";
const std::string QUIT="quit";
const std::string INFO="ls";
const std::string CAT="cat";
const std::string MREAD="mread";
const std::string MREAD="read";
const std::string MWRITE="mwrite";
......@@ -44,7 +43,6 @@ private:
// (3)
CMDstatus Info(int argc, char* argv[], TermOutput& termout, Serverdat *sd);
CMDstatus Cat(int argc, char* argv[], TermOutput& termout, Serverdat *sd);
CMDstatus Mread(int argc, char* argv[], TermOutput& termout, Serverdat *sd);
CMDstatus Mwrite(int argc, char* argv[], TermOutput& termout, Serverdat *sd);
......@@ -54,7 +52,6 @@ private:
supported_cmds.push_back(HELP);
supported_cmds.push_back(QUIT);
supported_cmds.push_back(INFO);
supported_cmds.push_back(CAT);
supported_cmds.push_back(MREAD);
supported_cmds.push_back(MWRITE);
}
......
......@@ -23,6 +23,7 @@
#include <arpa/inet.h> //inet_aton
#include "common.h"
#include "tools/parse.h"
extern int debug;
......@@ -86,27 +87,38 @@ RegisterMap * Common::get_RegisterMap(TermOutput& termout, int node)
return n->get_RegisterMap(termout.strout);
}
bool Common::mread(TermOutput& termout, std::vector<int> nodes, const string addr,
const uint offs, const uint len)
bool Common::read(TermOutput& termout, const string addr, const uint offs, const int len)
{
bool retval=false;
uint retcnt=0;
std::vector<int> nodes = path_to_node(addr);
std::string relative_addr = addr_to_relative_addr(addr);
std::string type = addr_to_type(addr);
std::string peripheral = addr_to_peripheral(addr);
for(uint idx=0;idx<nodes.size();idx++) {
auto node = select_node(nodes[idx]);
print_node_id(termout.strout,node);
if(idx>0) termout.strout << ",";
termout.strout << "[" << node->GetGlobalNr() << "],";
//termout.strout << "[" << node->GetGlobalNr() << "],";
termout.strout << "[";
std::vector<int> datavec;
if(node->mread(termout.strout,addr,offs,datavec,len)) {
retcnt++;
for(uint i=0;i<datavec.size();i++) {
if(i>0) termout.strout << ",";
termout.strout << datavec[i];
if(type == "mm") {
RegisterMap *regmap = node->get_RegisterMap(termout.strout);
uint32_t nvalues = (len<0 ? (regmap->getSpan(relative_addr) / 4) : len);
std::vector<int> datavec;
if(node->mread(termout.strout,relative_addr,offs,datavec,nvalues)) {
retcnt++;
}
} else if(type == "dev") {
if(node->get_system_info(termout.strout,peripheral)) {
retcnt++;
} else {
termout.strerr << "no such peripheral: " << peripheral;
}
} else {
termout.strerr << "no such type: " << type;
}
termout.strout << "]";
}
......@@ -114,44 +126,12 @@ bool Common::mread(TermOutput& termout, std::vector<int> nodes, const string add
return retval;
}
bool Common::read(TermOutput& termout, const string addr)
{
bool retval=false;
uint retcnt=0;
auto node = select_node(path_to_node(addr));
std::string relative_addr = addr_to_relative_addr(addr);
std::string type = addr_to_type(addr);
std::string peripheral = addr_to_peripheral(addr);
termout.strout << addr << "=[";
if(type == "mm") {
RegisterMap *regmap = node->get_RegisterMap(termout.strout);
uint32_t nvalues = regmap->getSpan(relative_addr) / 4;
std::vector<int> datavec;
if(node->mread(termout.strout,relative_addr,0,datavec,nvalues)) {
retcnt++;
}
} else if(type == "dev") {
if(node->get_system_info(termout.strout,peripheral)) {
retcnt++;
} else {
termout.strerr << "no such peripheral: " << peripheral;
}
} else {
termout.strerr << "no such type: " << type;
}
termout.strout << "]";
retval = retcnt;
return retval;
}
bool Common::mwrite(TermOutput& termout, std::vector<int> nodes, const string addr,
bool Common::mwrite(TermOutput& termout, const string addr,
const uint offs, const std::vector<int>& data)
{
bool retval=false;
uint retcnt=0;
std::vector<int> nodes;
for(uint idx=0;idx<nodes.size();idx++) {
auto node = select_node(nodes[idx]);
......@@ -189,11 +169,11 @@ std::vector<int> Common::unb_pn__to__nodes(std::vector<int> unbs, std::vector<in
nodes.push_back(pn+(4*unb));
}
}
cout << "unb_pn__to__nodes:";
for(auto n : nodes) {
cout << n << " ";
}
cout << endl;
// cout << "unb_pn__to__nodes:";
// for(auto n : nodes) {
// cout << n << " ";
// }
// cout << endl;
return nodes;
}
......@@ -215,42 +195,62 @@ uint Common::ipaddr_to_id(const string ipaddr)
return (unb*8+node);
}
int Common::unb_name_to_number(const std::string unb_name)
std::vector<int> Common::unb_name_to_number(const std::string unb_name)
{
int number = -1;
std::vector<int> unbs;
cout << "Common::unb_name_to_number: unb_name=" << unb_name << endl;
if(unb_name.length() >= 4) {
char *s = new char[unb_name.length() + 1];
s[unb_name.length()] = '\0';
for(uint i=0;i<unb_name.length();i++) {
s[i] = unb_name.c_str()[i];
}
if(s[0] == 'u' && s[1] == 'n' && s[2] == 'b') {
char *s_ptr = &s[3];
number = atoi(s_ptr);
if(unb_name[0] == 'u' && unb_name[1] == 'n' && unb_name[2] == 'b') {
std::string unb_range = unb_name.substr(3);
cout << "unb_range=" << unb_range << endl;
try {
unbs.push_back(std::stoi(unb_range,nullptr));
} catch (const std::invalid_argument& ia) {
cerr << "Common::unb_name_to_number: Invalid argument: " << ia.what() << " - but trying vector..." << endl;
istringstream vecstr(unb_range);
unbs=parse_int_vector_range(vecstr);
}
}
delete[] s;
}
return number;
// cout << "Common::unb_name_to_number: found unb:" << endl;
// for(auto u : unbs) {
// cout << u << " ";;
// }
// cout << endl;
return unbs;
}
int Common::pn_name_to_number(const std::string pn_name)
std::vector<int> Common::pn_name_to_number(const std::string pn_name)
{
int number = -1;
std::vector<int> pns;
if(pn_name.length() >= 3) {
if(pn_name.c_str()[0] == 'p' && pn_name.c_str()[1] == 'n' && isdigit(pn_name.c_str()[2])) {
number = pn_name.c_str()[2] - '0';
if(pn_name[0] == 'p' && pn_name[1] == 'n') {
std::string pn_range = pn_name.substr(2);
cout << "pn_range=" << pn_range << endl;
try {
pns.push_back(std::stoi(pn_range,nullptr));
} catch (const std::invalid_argument& ia) {
cerr << "Common::pn_name_to_number: Invalid argument: " << ia.what() << " - but trying vector..." << endl;
istringstream vecstr(pn_range);
pns=parse_int_vector_range(vecstr);
}
}
}
return number;
// cout << "Common::pn_name_to_number: found pns:" << endl;
// for(auto p : pns) {
// cout << p << " ";;
// }
// cout << endl;
return pns;
}
int Common::path_to_node(std::string path_str)
std::vector<int> Common::path_to_node(std::string path_str)
{
int node = -1;
std::vector<int> nodes;
std::stringstream ss(path_str);
std::string token;
std::vector<std::string> tokens;
......@@ -260,14 +260,24 @@ int Common::path_to_node(std::string path_str)
if(tokens.size() >= 3) {
if(tokens[0] == "") {
// ok, is absolute path starting with '/'
int unb = unb_name_to_number(tokens[1]);
int pn = pn_name_to_number(tokens[2]);
if(unb>=0 && pn>=0) {
node = pn+(4*unb);
std::vector<int> unb = unb_name_to_number(tokens[1]);
std::vector<int> pn = pn_name_to_number(tokens[2]);