OpenCores
URL https://opencores.org/ocsvn/w11/w11/trunk

Subversion Repositories w11

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /w11/tags/w11a_V0.61/tools/src/librlinktpp
    from Rev 25 to Rev 26
    Reverse comparison

Rev 25 → Rev 26

/RtclRlinkConnect.cpp
0,0 → 1,815
// $Id: RtclRlinkConnect.cpp 576 2014-08-02 12:24:28Z mueller $
//
// Copyright 2011-2014 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2014-08-02 576 1.1.7 bugfix: redo estatdef logic; avoid LastExpect()
// 2013-02-23 492 1.1.6 use RlogFile.Name(); use Context().ErrorCount()
// 2013-02-22 491 1.1.5 use new RlogFile/RlogMsg interfaces
// 2013-02-02 480 1.1.4 allow empty exec commands
// 2013-01-27 478 1.1.3 use RtclRlinkPort::DoRawio on M_rawio
// 2013-01-06 473 1.1.2 add M_rawio: rawio -write|-read
// 2011-11-28 434 1.1.1 ConfigBase(): use uint32_t for lp64 compatibility
// 2011-04-23 380 1.1 use boost/bind instead of RmethDsc
// 2011-04-17 376 1.0.1 M_wtlam: now correct log levels
// 2011-03-27 374 1.0 Initial version
// 2011-02-11 360 0.1 First draft
// ---------------------------------------------------------------------------
 
/*!
\file
\version $Id: RtclRlinkConnect.cpp 576 2014-08-02 12:24:28Z mueller $
\brief Implemenation of class RtclRlinkConnect.
*/
 
#include <ctype.h>
 
#include <iostream>
 
#include "boost/bind.hpp"
 
#include "librtcltools/Rtcl.hpp"
#include "librtcltools/RtclOPtr.hpp"
#include "librtcltools/RtclNameSet.hpp"
#include "librtcltools/RtclStats.hpp"
#include "librtools/RosPrintf.hpp"
#include "librtools/RlogMsg.hpp"
#include "librlink/RlinkCommandList.hpp"
#include "RtclRlinkPort.hpp"
 
#include "RtclRlinkConnect.hpp"
 
using namespace std;
 
/*!
\class Retro::RtclRlinkConnect
\brief FIXME_docs
*/
 
// all method definitions in namespace Retro
namespace Retro {
 
//------------------------------------------+-----------------------------------
//! Default constructor
 
RtclRlinkConnect::RtclRlinkConnect(Tcl_Interp* interp, const char* name)
: RtclProxyOwned<RlinkConnect>("RlinkConnect", interp, name,
new RlinkConnect())
{
AddMeth("open", boost::bind(&RtclRlinkConnect::M_open, this, _1));
AddMeth("close", boost::bind(&RtclRlinkConnect::M_close, this, _1));
AddMeth("exec", boost::bind(&RtclRlinkConnect::M_exec, this, _1));
AddMeth("amap", boost::bind(&RtclRlinkConnect::M_amap, this, _1));
AddMeth("errcnt", boost::bind(&RtclRlinkConnect::M_errcnt, this, _1));
AddMeth("wtlam", boost::bind(&RtclRlinkConnect::M_wtlam, this, _1));
AddMeth("oob", boost::bind(&RtclRlinkConnect::M_oob, this, _1));
AddMeth("rawio", boost::bind(&RtclRlinkConnect::M_rawio, this, _1));
AddMeth("stats", boost::bind(&RtclRlinkConnect::M_stats, this, _1));
AddMeth("log", boost::bind(&RtclRlinkConnect::M_log, this, _1));
AddMeth("print", boost::bind(&RtclRlinkConnect::M_print, this, _1));
AddMeth("dump", boost::bind(&RtclRlinkConnect::M_dump, this, _1));
AddMeth("config", boost::bind(&RtclRlinkConnect::M_config, this, _1));
AddMeth("$default", boost::bind(&RtclRlinkConnect::M_default, this, _1));
 
for (size_t i=0; i<8; i++) {
fCmdnameObj[i] = Tcl_NewStringObj(RlinkCommand::CommandName(i), -1);
}
}
 
//------------------------------------------+-----------------------------------
//! Destructor
 
RtclRlinkConnect::~RtclRlinkConnect()
{}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkConnect::M_open(RtclArgs& args)
{
string path;
 
if (!args.GetArg("?path", path)) return kERR;
if (!args.AllDone()) return kERR;
 
RerrMsg emsg;
if (args.NOptMiss() == 0) { // open path
if (!Obj().Open(path, emsg)) return args.Quit(emsg);
} else { // open
string name = Obj().IsOpen() ? Obj().Port()->Url().Url() : string();
args.SetResult(name);
}
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkConnect::M_close(RtclArgs& args)
{
if (!args.AllDone()) return kERR;
if (!Obj().IsOpen()) return args.Quit("-E: port not open");
Obj().Close();
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkConnect::M_exec(RtclArgs& args)
{
static RtclNameSet optset("-rreg|-rblk|-wreg|-wblk|-stat|-attn|-init|"
"-edata|-estat|-estatdef|"
"-volatile|-print|-dump|-rlist");
 
Tcl_Interp* interp = args.Interp();
 
RlinkCommandList clist;
string opt;
uint16_t addr;
 
vector<string> vardata;
vector<string> varstat;
string varprint;
string vardump;
string varlist;
 
uint8_t estatdef_val = 0x00;
uint8_t estatdef_msk = 0xff;
 
while (args.NextOpt(opt, optset)) {
size_t lsize = clist.Size();
if (opt == "-rreg") { // -rreg addr ?varData ?varStat ---
if (!GetAddr(args, Obj(), addr)) return kERR;
if (!GetVarName(args, "??varData", lsize, vardata)) return kERR;
if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
clist.AddRreg(addr);
 
} else if (opt == "-rblk") { // -rblk addr size ?varData ?varStat
int32_t bsize;
if (!GetAddr(args, Obj(), addr)) return kERR;
if (!args.GetArg("bsize", bsize, 1, 256)) return kERR;
if (!GetVarName(args, "??varData", lsize, vardata)) return kERR;
if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
clist.AddRblk(addr, (size_t) bsize);
 
} else if (opt == "-wreg") { // -wreg addr data ?varStat -------
uint16_t data;
if (!GetAddr(args, Obj(), addr)) return kERR;
if (!args.GetArg("data", data)) return kERR;
if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
clist.AddWreg(addr, data);
 
} else if (opt == "-wblk") { // -wblk addr block ?varStat ------
vector<uint16_t> block;
if (!GetAddr(args, Obj(), addr)) return kERR;
if (!args.GetArg("data", block, 1, 256)) return kERR;
if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
clist.AddWblk(addr, block);
 
} else if (opt == "-stat") { // -stat varData ?varStat ---------
if (!GetVarName(args, "??varData", lsize, vardata)) return kERR;
if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
clist.AddStat();
 
} else if (opt == "-attn") { // -attn varData ?varStat ---------
if (!GetVarName(args, "??varData", lsize, vardata)) return kERR;
if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
clist.AddAttn();
 
} else if (opt == "-init") { // -init addr data ?varStat -------
uint16_t data;
if (!GetAddr(args, Obj(), addr)) return kERR;
if (!args.GetArg("data", data)) return kERR;
if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
clist.AddInit(addr, data);
 
} else if (opt == "-edata") { // -edata data ?mask --------------
if (!ClistNonEmpty(args, clist)) return kERR;
if (clist[lsize-1].Expect()==0) {
clist[lsize-1].SetExpect(new RlinkCommandExpect(estatdef_val,
estatdef_msk));
}
if (clist[lsize-1].Command() == RlinkCommand::kCmdRblk) {
vector<uint16_t> data;
vector<uint16_t> mask;
size_t bsize = clist[lsize-1].BlockSize();
if (!args.GetArg("data", data, 0, bsize)) return kERR;
if (!args.GetArg("??mask", mask, 0, bsize)) return kERR;
clist[lsize-1].Expect()->SetBlock(data, mask);
} else {
uint16_t data=0;
uint16_t mask=0;
if (!args.GetArg("data", data)) return kERR;
if (!args.GetArg("??mask", mask)) return kERR;
clist[lsize-1].Expect()->SetData(data, mask);
}
 
} else if (opt == "-estat") { // -estat ?stat ?mask -------------
if (!ClistNonEmpty(args, clist)) return kERR;
uint8_t stat=0;
uint8_t mask=0;
if (!args.GetArg("??stat", stat)) return kERR;
if (!args.GetArg("??mask", mask)) return kERR;
if (args.NOptMiss() == 2) mask = 0xff;
if (clist[lsize-1].Expect()==0) {
clist[lsize-1].SetExpect(new RlinkCommandExpect());
}
clist[lsize-1].Expect()->SetStatus(stat, mask);
 
} else if (opt == "-estatdef") { // -estatdef ?stat ?mask -----------
uint8_t stat=0;
uint8_t mask=0;
if (!args.GetArg("??stat", stat)) return kERR;
if (!args.GetArg("??mask", mask)) return kERR;
if (args.NOptMiss() == 2) mask = 0xff;
estatdef_val = stat;
estatdef_msk = mask;
 
} else if (opt == "-volatile") { // -volatile ----------------------
if (!ClistNonEmpty(args, clist)) return kERR;
clist.LastVolatile();
 
} else if (opt == "-print") { // -print ?varRes -----------------
varprint = "-";
if (!args.GetArg("??varRes", varprint)) return kERR;
} else if (opt == "-dump") { // -dump ?varRes ------------------
vardump = "-";
if (!args.GetArg("??varRes", vardump)) return kERR;
} else if (opt == "-rlist") { // -rlist ?varRes -----------------
varlist = "-";
if (!args.GetArg("??varRes", varlist)) return kERR;
}
 
if (estatdef_msk != 0xff && // estatdef defined
lsize != clist.Size()) { // and cmd added to clist
for (size_t i=lsize; i<clist.Size(); i++) { // loop over new cmds
if (clist[i].Expect()==0) { // if no stat
clist[i].SetExpect(new RlinkCommandExpect(estatdef_val,
estatdef_msk));
}
}
}
 
}
 
int nact = 0;
if (varprint == "-") nact += 1;
if (vardump == "-") nact += 1;
if (varlist == "-") nact += 1;
if (nact > 1)
return args.Quit(
"-E: more that one of -print,-dump,-list without target variable found");
 
if (!args.AllDone()) return kERR;
if (clist.Size() == 0) return kOK;
 
RerrMsg emsg;
if (!Obj().Exec(clist, emsg)) return args.Quit(emsg);
 
for (size_t icmd=0; icmd<clist.Size(); icmd++) {
RlinkCommand& cmd = clist[icmd];
if (icmd<vardata.size() && !vardata[icmd].empty()) {
RtclOPtr pres;
vector<uint16_t> retstat;
RtclOPtr pele;
switch (cmd.Command()) {
case RlinkCommand::kCmdRreg:
case RlinkCommand::kCmdAttn:
pres = Tcl_NewIntObj((int)cmd.Data());
break;
 
case RlinkCommand::kCmdRblk:
pres = Rtcl::NewListIntObj(cmd.Block());
break;
 
case RlinkCommand::kCmdStat:
retstat.resize(2);
retstat[0] = cmd.StatRequest();
retstat[1] = cmd.Data();
pres = Rtcl::NewListIntObj(retstat);
break;
}
if(!Rtcl::SetVar(interp, vardata[icmd], pres)) return kERR;
}
 
if (icmd<varstat.size() && !varstat[icmd].empty()) {
RtclOPtr pres(Tcl_NewIntObj((int)cmd.Status()));
if (!Rtcl::SetVar(interp, varstat[icmd], pres)) return kERR;
}
}
 
if (!varprint.empty()) {
ostringstream sos;
const RlinkConnect::LogOpts& logopts = Obj().GetLogOpts();
clist.Print(sos, Obj().Context(), &Obj().AddrMap(), logopts.baseaddr,
logopts.basedata, logopts.basestat);
RtclOPtr pobj(Rtcl::NewLinesObj(sos));
if (!Rtcl::SetVarOrResult(args.Interp(), varprint, pobj)) return kERR;
}
 
if (!vardump.empty()) {
ostringstream sos;
clist.Dump(sos, 0);
RtclOPtr pobj(Rtcl::NewLinesObj(sos));
if (!Rtcl::SetVarOrResult(args.Interp(), vardump, pobj)) return kERR;
}
 
if (!varlist.empty()) {
RtclOPtr prlist(Tcl_NewListObj(0, NULL));
for (size_t icmd=0; icmd<clist.Size(); icmd++) {
RlinkCommand& cmd(clist[icmd]);
RtclOPtr pres(Tcl_NewListObj(0, NULL));
Tcl_ListObjAppendElement(NULL, pres, fCmdnameObj[cmd.Command()]);
Tcl_ListObjAppendElement(NULL, pres, Tcl_NewIntObj((int)cmd.Request()));
Tcl_ListObjAppendElement(NULL, pres, Tcl_NewIntObj((int)cmd.Flags()));
Tcl_ListObjAppendElement(NULL, pres, Tcl_NewIntObj((int)cmd.Status()));
 
switch (cmd.Command()) {
case RlinkCommand::kCmdRreg:
case RlinkCommand::kCmdAttn:
Tcl_ListObjAppendElement(NULL, pres, Tcl_NewIntObj((int)cmd.Data()));
break;
case RlinkCommand::kCmdRblk:
Tcl_ListObjAppendElement(NULL, pres,
Rtcl::NewListIntObj(cmd.Block()));
break;
 
case RlinkCommand::kCmdStat:
Tcl_ListObjAppendElement(NULL, pres,
Tcl_NewIntObj((int)cmd.StatRequest()));
Tcl_ListObjAppendElement(NULL, pres, Tcl_NewIntObj((int)cmd.Data()));
break;
}
Tcl_ListObjAppendElement(NULL, prlist, pres);
}
if (!Rtcl::SetVarOrResult(args.Interp(), varlist, prlist)) return kERR;
}
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkConnect::M_amap(RtclArgs& args)
{
static RtclNameSet optset("-name|-testname|-testaddr|-insert|-erase|"
"-clear|-print");
 
const RlinkAddrMap& addrmap = Obj().AddrMap();
 
string opt;
string name;
uint16_t addr=0;
 
if (args.NextOpt(opt, optset)) {
if (opt == "-name") { // amap -name addr
if (!args.GetArg("addr", addr, 0x00ff)) return kERR;
if (!args.AllDone()) return kERR;
string tstname;
if(addrmap.Find(addr, tstname)) {
args.SetResult(tstname);
} else {
return args.Quit(string("-E: address '") + args.PeekArgString(-1) +
"' not mapped");
}
 
} else if (opt == "-testname") { // amap -testname name
if (!args.GetArg("name", name)) return kERR;
if (!args.AllDone()) return kERR;
uint16_t tstaddr;
args.SetResult(int(addrmap.Find(name, tstaddr)));
 
} else if (opt == "-testaddr") { // amap -testaddr addr
if (!args.GetArg("addr", addr, 0x00ff)) return kERR;
if (!args.AllDone()) return kERR;
string tstname;
args.SetResult(int(addrmap.Find(addr, tstname)));
 
} else if (opt == "-insert") { // amap -insert name addr
uint16_t tstaddr;
string tstname;
int tstint;
if (!args.GetArg("name", name)) return kERR;
// enforce that the name is not a valid representation of an int
if (Tcl_GetIntFromObj(NULL, args[args.NDone()-1], &tstint) == kOK)
return args.Quit(string("-E: name should not look like an int but '")+
name + "' does");
if (!args.GetArg("addr", addr, 0x00ff)) return kERR;
if (!args.AllDone()) return kERR;
if (addrmap.Find(name, tstaddr))
return args.Quit(string("-E: mapping already defined for '")+name+"'");
if (addrmap.Find(addr, tstname))
return args.Quit(string("-E: mapping already defined for address '") +
args.PeekArgString(-1) + "'");
Obj().AddrMapInsert(name, addr);
 
} else if (opt == "-erase") { // amap -erase name
if (!args.GetArg("name", name)) return kERR;
if (!args.AllDone()) return kERR;
if (!Obj().AddrMapErase(name))
return args.Quit(string("-E: no mapping defined for '") + name + "'");
 
} else if (opt == "-clear") { // amap -clear
if (!args.AllDone()) return kERR;
Obj().AddrMapClear();
 
} else if (opt == "-print") { // amap -print
if (!args.AllDone()) return kERR;
ostringstream sos;
addrmap.Print(sos);
args.AppendResultLines(sos);
}
} else {
if (!args.OptValid()) return kERR;
if (!args.GetArg("?name", name)) return kERR;
if (args.NOptMiss()==0) { // amap name
uint16_t tstaddr;
if(addrmap.Find(name, tstaddr)) {
args.SetResult(int(tstaddr));
} else {
return args.Quit(string("-E: no mapping defined for '") + name + "'");
}
 
} else { // amap
RtclOPtr plist(Tcl_NewListObj(0, NULL));
const RlinkAddrMap::amap_t amap = addrmap.Amap();
for (RlinkAddrMap::amap_cit_t it=amap.begin(); it!=amap.end(); it++) {
Tcl_Obj* tpair[2];
tpair[0] = Tcl_NewIntObj(it->first);
tpair[1] = Tcl_NewStringObj((it->second).c_str(),(it->second).length());
Tcl_ListObjAppendElement(NULL, plist, Tcl_NewListObj(2, tpair));
}
args.SetResult(plist);
}
}
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkConnect::M_errcnt(RtclArgs& args)
{
static RtclNameSet optset("-clear");
string opt;
bool fclear = false;
while (args.NextOpt(opt, optset)) {
if (opt == "-clear") fclear = true;
}
if (!args.AllDone()) return kERR;
 
args.SetResult(int(Obj().Context().ErrorCount()));
if (fclear) Obj().Context().ClearErrorCount();
 
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkConnect::M_wtlam(RtclArgs& args)
{
double tout;
if (!args.GetArg("tout", tout, 0.001)) return kERR;
if (!args.AllDone()) return kERR;
 
RerrMsg emsg;
double twait = Obj().WaitAttn(tout, emsg);
 
if (twait == -2.) {
return args.Quit(emsg);
} else if (twait == -1.) {
if (Obj().GetLogOpts().printlevel >= 1) {
RlogMsg lmsg(Obj().LogFile());
lmsg << "-- wtlam to=" << RosPrintf(tout, "f", 0,3)
<< " FAIL timeout" << endl;
Obj().Context().IncErrorCount();
args.SetResult(tout);
return kOK;
}
}
 
if (Obj().GetLogOpts().printlevel >= 3) {
RlogMsg lmsg(Obj().LogFile());
lmsg << "-- wtlam to=" << RosPrintf(tout, "f", 0,3)
<< " T=" << RosPrintf(twait, "f", 0,3)
<< " OK" << endl;
}
args.SetResult(twait);
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkConnect::M_oob(RtclArgs& args)
{
static RtclNameSet optset("-rlmon|-rbmon|-sbcntl|-sbdata");
 
string opt;
uint16_t addr;
uint16_t data;
RerrMsg emsg;
 
if (args.NextOpt(opt, optset)) {
if (opt == "-rlmon") { // oob -rlmon (0|1)
if (!args.GetArg("val", data, 1)) return kERR;
if (!args.AllDone()) return kERR;
addr = 15; // rlmon on bit 15
if (!Obj().SndOob(0x00, (addr<<8)+data, emsg)) return args.Quit(emsg);
 
} else if (opt == "-rbmon") { // oob -rbmon (0|1)
if (!args.GetArg("val", data, 1)) return kERR;
if (!args.AllDone()) return kERR;
addr = 14; // rbmon on bit 14
if (!Obj().SndOob(0x00, (addr<<8)+data, emsg)) return args.Quit(emsg);
 
} else if (opt == "-sbcntl") { // oob -sbcntl bit (0|1)
if (!args.GetArg("bit", addr, 15)) return kERR;
if (!args.GetArg("val", data, 1)) return kERR;
if (!args.AllDone()) return kERR;
if (!Obj().SndOob(0x00, (addr<<8)+data, emsg)) return args.Quit(emsg);
 
} else if (opt == "-sbdata") { // oob -sbdata addr val
if (!args.GetArg("bit", addr, 0x0ff)) return kERR;
if (!args.GetArg("val", data)) return kERR;
if (!args.AllDone()) return kERR;
if (!Obj().SndOob(addr, data, emsg)) return args.Quit(emsg);
}
} else {
return args.Quit(
"-E: missing option, one of -rlmon,-rbmon,-sbcntl,-sbdata");
}
 
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkConnect::M_rawio(RtclArgs& args)
{
size_t errcnt = 0;
int rc = RtclRlinkPort::DoRawio(args, Obj().Port(), errcnt);
Obj().Context().IncErrorCount(errcnt);
return rc;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkConnect::M_stats(RtclArgs& args)
{
RtclStats::Context cntx;
if (!RtclStats::GetArgs(args, cntx)) return kERR;
if (!RtclStats::Collect(args, cntx, Obj().Stats())) return kERR;
if (Obj().Port()) {
if (!RtclStats::Collect(args, cntx, Obj().Port()->Stats())) return kERR;
}
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkConnect::M_log(RtclArgs& args)
{
string msg;
if (!args.GetArg("msg", msg)) return kERR;
if (!args.AllDone()) return kERR;
if (Obj().GetLogOpts().printlevel != 0 ||
Obj().GetLogOpts().dumplevel != 0 ||
Obj().GetLogOpts().tracelevel != 0) {
Obj().LogFile().Write(string("# ") + msg);
}
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkConnect::M_print(RtclArgs& args)
{
if (!args.AllDone()) return kERR;
 
ostringstream sos;
Obj().Print(sos);
args.SetResult(sos);
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkConnect::M_dump(RtclArgs& args)
{
if (!args.AllDone()) return kERR;
 
ostringstream sos;
Obj().Dump(sos, 0);
args.SetResult(sos);
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkConnect::M_config(RtclArgs& args)
{
static RtclNameSet optset("-baseaddr|-basedata|-basestat|"
"-logfile|-logprintlevel|-logdumplevel|"
"-logtracelevel");
RlinkConnect::LogOpts logopts = Obj().GetLogOpts();
 
if (args.NDone() == (size_t)args.Objc()) {
ostringstream sos;
sos << "-baseaddr " << RosPrintf(logopts.baseaddr, "d")
<< " -basedata " << RosPrintf(logopts.basedata, "d")
<< " -basestat " << RosPrintf(logopts.basestat, "d")
<< " -logfile {" << Obj().LogFile().Name() << "}"
<< " -logprintlevel " << RosPrintf(logopts.printlevel, "d")
<< " -logdumplevel " << RosPrintf(logopts.dumplevel, "d")
<< " -logtracelevel " << RosPrintf(logopts.tracelevel, "d");
args.AppendResult(sos);
return kOK;
}
 
string opt;
while (args.NextOpt(opt, optset)) {
if (opt == "-baseaddr") { // -baseaddr ?base -----------------
if (!ConfigBase(args, logopts.baseaddr)) return kERR;
if (args.NOptMiss() == 0) Obj().SetLogOpts(logopts);
 
} else if (opt == "-basedata") { // -basedata ?base -----------------
if (!ConfigBase(args, logopts.basedata)) return kERR;
if (args.NOptMiss() == 0) Obj().SetLogOpts(logopts);
 
} else if (opt == "-basestat") { // -basestat ?base -----------------
if (!ConfigBase(args, logopts.basestat)) return kERR;
if (args.NOptMiss() == 0) Obj().SetLogOpts(logopts);
 
} else if (opt == "-logfile") { // -logfile ?name ------------------
string name;
if (!args.Config("??name", name)) return false;
if (args.NOptMiss() == 0) { // new filename ?
if (name == "-" || name == "<cout>") {
Obj().LogUseStream(&cout, "<cout>");
} else {
if (!Obj().LogOpen(name)) {
Obj().LogUseStream(&cout, "<cout>");
return args.Quit(string("-E: open failed for '") + name +
"', using stdout");
}
}
}
 
} else if (opt == "-logprintlevel") { // -logprintlevel ?loglevel --------
if (!args.Config("??loglevel", logopts.printlevel, 3)) return false;
if (args.NOptMiss() == 0) Obj().SetLogOpts(logopts);
 
} else if (opt == "-logdumplevel") { // -logdumplevel ?loglevel ---------
if (!args.Config("??loglevel", logopts.dumplevel, 3)) return false;
if (args.NOptMiss() == 0) Obj().SetLogOpts(logopts);
 
} else if (opt == "-logtracelevel") { // -logtracelevel ?loglevel --------
if (!args.Config("??loglevel", logopts.tracelevel, 3)) return false;
if (args.NOptMiss() == 0) Obj().SetLogOpts(logopts);
}
}
 
if (!args.AllDone()) return kERR;
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkConnect::M_default(RtclArgs& args)
{
if (!args.AllDone()) return kERR;
ostringstream sos;
const RlinkConnect::LogOpts& logopts = Obj().GetLogOpts();
 
sos << "print base: " << "addr " << RosPrintf(logopts.baseaddr, "d", 2)
<< " data " << RosPrintf(logopts.basedata, "d", 2)
<< " stat " << RosPrintf(logopts.basestat, "d", 2) << endl;
sos << "logfile: " << Obj().LogFile().Name()
<< " printlevel " << logopts.printlevel
<< " dumplevel " << logopts.dumplevel;
 
args.AppendResultLines(sos);
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
bool RtclRlinkConnect::GetAddr(RtclArgs& args, RlinkConnect& conn,
uint16_t& addr)
{
Tcl_Obj* pobj=0;
if (!args.GetArg("addr", pobj)) return kERR;
 
int tstint;
// if a number is given..
if (Tcl_GetIntFromObj(NULL, pobj, &tstint) == kOK) {
if (tstint >= 0 && tstint <= 0x00ff) {
addr = (uint16_t)tstint;
} else {
args.AppendResult("-E: value '", Tcl_GetString(pobj),
"' for 'addr' out of range 0...0x00ff", NULL);
return false;
}
// if a name is given
} else {
string name(Tcl_GetString(pobj));
uint16_t tstaddr;
if (Obj().AddrMap().Find(name, tstaddr)) {
addr = tstaddr;
} else {
args.AppendResult("-E: no address mapping known for '",
Tcl_GetString(pobj), "'", NULL);
return false;
}
}
 
return true;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
bool RtclRlinkConnect::GetVarName(RtclArgs& args, const char* argname,
size_t nind,
std::vector<std::string>& varname)
{
while (varname.size() < nind+1) varname.push_back(string());
string name;
if (!args.GetArg(argname, name)) return false;
if (name.length()) { // if variable defined
char c = name[0];
if (isdigit(c) || c=='+' || c=='-' ) { // check for mistaken number
args.AppendResult("-E: invalid variable name '", name.c_str(),
"': looks like a number", NULL);
return false;
}
}
varname[nind] = name;
return true;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
bool RtclRlinkConnect::ConfigBase(RtclArgs& args, uint32_t& base)
{
uint32_t tmp = base;
if (!args.Config("??base", tmp, 16, 2)) return false;
if (tmp != base && tmp != 2 && tmp !=8 && tmp != 16) {
args.AppendResult("-E: base must be 2, 8, or 16, found '",
args.PeekArgString(-1), "'", NULL);
return false;
}
base = tmp;
return true;
}
 
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
bool RtclRlinkConnect::ClistNonEmpty(RtclArgs& args,
const RlinkCommandList& clist)
{
if (clist.Size() == 0) {
args.AppendResult("-E: -edata, -estat, or -volatile "
"not allowed on empty command list", NULL);
return false;
}
return true;
}
 
} // end namespace Retro
/RtclAttnShuttle.cpp
0,0 → 1,161
// $Id: RtclAttnShuttle.cpp 521 2013-05-20 22:16:45Z mueller $
//
// Copyright 2013- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2013-05-20 521 1.0.1 Setup proper Tcl channel options
// 2013-03-01 493 1.0 Initial version
// 2013-01-12 475 0.5 First draft
// ---------------------------------------------------------------------------
 
/*!
\file
\version $Id: RtclAttnShuttle.cpp 521 2013-05-20 22:16:45Z mueller $
\brief Implemenation of class RtclAttnShuttle.
*/
 
#include <errno.h>
 
#include "boost/bind.hpp"
 
#include "librtools/Rexception.hpp"
 
#include "RtclAttnShuttle.hpp"
 
using namespace std;
 
/*!
\class Retro::RtclAttnShuttle
\brief FIXME_docs
*/
 
// all method definitions in namespace Retro
namespace Retro {
 
//------------------------------------------+-----------------------------------
//! constructor
 
RtclAttnShuttle::RtclAttnShuttle(uint16_t mask, Tcl_Obj* pobj)
: fpServ(0),
fpInterp(0),
fFdPipeRead(-1),
fFdPipeWrite(-1),
fShuttleChn(0),
fMask(mask),
fpScript(pobj)
{
int pipefd[2];
int irc = ::pipe(pipefd);
if (irc < 0)
throw Rexception("RtclAttnShuttle::<ctor>", "pipe() failed: ", errno);
fFdPipeRead = pipefd[0];
fFdPipeWrite = pipefd[1];
}
 
//------------------------------------------+-----------------------------------
//! Destructor
 
RtclAttnShuttle::~RtclAttnShuttle()
{
Remove();
::close(fFdPipeWrite);
::close(fFdPipeRead);
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void RtclAttnShuttle::Add(RlinkServer* pserv, Tcl_Interp* interp)
{
// connect to RlinkServer
pserv->AddAttnHandler(boost::bind(&RtclAttnShuttle::AttnHandler, this, _1),
fMask, (void*)this);
fpServ = pserv;
 
// connect to Tcl
fShuttleChn = Tcl_MakeFileChannel((ClientData)fFdPipeRead, TCL_READABLE);
 
Tcl_SetChannelOption(NULL, fShuttleChn, "-buffersize", "64");
Tcl_SetChannelOption(NULL, fShuttleChn, "-encoding", "binary");
Tcl_SetChannelOption(NULL, fShuttleChn, "-translation", "binary");
 
Tcl_CreateChannelHandler(fShuttleChn, TCL_READABLE,
(Tcl_FileProc*) ThunkTclChannelHandler,
(ClientData) this);
 
fpInterp = interp;
return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void RtclAttnShuttle::Remove()
{
// disconnect from RlinkServer
if (fpServ) {
fpServ->RemoveAttnHandler(fMask, (void*)this);
fpServ = 0;
}
// disconnect from Tcl
if (fpInterp) {
Tcl_DeleteChannelHandler(fShuttleChn,
(Tcl_FileProc*) ThunkTclChannelHandler,
(ClientData) this);
Tcl_Close(fpInterp, fShuttleChn);
fpInterp = 0;
}
return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclAttnShuttle::AttnHandler(const RlinkServer::AttnArgs& args)
{
uint16_t apat = args.fAttnPatt & args.fAttnMask;
int irc = ::write(fFdPipeWrite, (void*) &apat, sizeof(apat));
if (irc < 0)
throw Rexception("RtclAttnShuttle::AttnHandler()",
"write() failed: ", errno);
return 0;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void RtclAttnShuttle::TclChannelHandler(int mask)
{
uint16_t apat;
Tcl_ReadRaw(fShuttleChn, (char*) &apat, sizeof(apat));
// FIXME_code: handle return code
 
Tcl_SetVar2Ex(fpInterp, "Rlink_attnbits", NULL, Tcl_NewIntObj((int)apat), 0);
// FIXME_code: handle return code
 
Tcl_EvalObjEx(fpInterp, fpScript, TCL_EVAL_GLOBAL);
// FIXME_code: handle return code
return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void RtclAttnShuttle::ThunkTclChannelHandler(ClientData cdata, int mask)
{
((RtclAttnShuttle*) cdata)->TclChannelHandler(mask);
return;
}
 
} // end namespace Retro
/RtclRlinkPort.cpp
0,0 → 1,330
// $Id: RtclRlinkPort.cpp 521 2013-05-20 22:16:45Z mueller $
//
// Copyright 2013- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2013-02-23 492 1.0.2 use RlogFile.Name();
// 2013-02-22 491 1.0.1 use new RlogFile/RlogMsg interfaces
// 2013-01-27 478 1.0 Initial version
// ---------------------------------------------------------------------------
 
/*!
\file
\version $Id: RtclRlinkPort.cpp 521 2013-05-20 22:16:45Z mueller $
\brief Implemenation of class RtclRlinkPort.
*/
 
#include <ctype.h>
 
#include <iostream>
 
#include "boost/bind.hpp"
 
#include "librtcltools/Rtcl.hpp"
#include "librtcltools/RtclOPtr.hpp"
#include "librtcltools/RtclNameSet.hpp"
#include "librtcltools/RtclStats.hpp"
#include "librtools/RosPrintf.hpp"
#include "librtools/RlogFile.hpp"
#include "librlink/RlinkPortFactory.hpp"
 
#include "RtclRlinkPort.hpp"
 
using namespace std;
 
/*!
\class Retro::RtclRlinkPort
\brief FIXME_docs
*/
 
// all method definitions in namespace Retro
namespace Retro {
 
//------------------------------------------+-----------------------------------
//! Default constructor
 
RtclRlinkPort::RtclRlinkPort(Tcl_Interp* interp, const char* name)
: RtclProxyBase("RlinkPort"),
fpObj(0),
fspLog(new RlogFile(&cout, "<cout>")),
fTraceLevel(0),
fErrCnt(0)
{
CreateObjectCmd(interp, name);
AddMeth("open", boost::bind(&RtclRlinkPort::M_open, this, _1));
AddMeth("close", boost::bind(&RtclRlinkPort::M_close, this, _1));
AddMeth("errcnt", boost::bind(&RtclRlinkPort::M_errcnt, this, _1));
AddMeth("rawio", boost::bind(&RtclRlinkPort::M_rawio, this, _1));
AddMeth("stats", boost::bind(&RtclRlinkPort::M_stats, this, _1));
AddMeth("log", boost::bind(&RtclRlinkPort::M_log, this, _1));
AddMeth("dump", boost::bind(&RtclRlinkPort::M_dump, this, _1));
AddMeth("config", boost::bind(&RtclRlinkPort::M_config, this, _1));
AddMeth("$default", boost::bind(&RtclRlinkPort::M_default, this, _1));
}
 
//------------------------------------------+-----------------------------------
//! Destructor
 
RtclRlinkPort::~RtclRlinkPort()
{
delete fpObj;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkPort::M_open(RtclArgs& args)
{
string path;
 
if (!args.GetArg("?path", path)) return kERR;
if (!args.AllDone()) return kERR;
 
RerrMsg emsg;
if (args.NOptMiss() == 0) { // open path
delete fpObj;
fpObj = RlinkPortFactory::Open(path, emsg);
if (!fpObj) return args.Quit(emsg);
fpObj->SetLogFile(fspLog);
fpObj->SetTraceLevel(fTraceLevel);
} else { // open
string name = (fpObj && fpObj->IsOpen()) ? fpObj->Url().Url() : string();
args.SetResult(name);
}
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkPort::M_close(RtclArgs& args)
{
if (!args.AllDone()) return kERR;
if (!TestOpen(args)) return kERR;
delete fpObj;
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkPort::M_errcnt(RtclArgs& args)
{
static RtclNameSet optset("-clear");
string opt;
bool fclear = false;
while (args.NextOpt(opt, optset)) {
if (opt == "-clear") fclear = true;
}
if (!args.AllDone()) return kERR;
 
args.SetResult(int(fErrCnt));
if (fclear) fErrCnt = 0;
 
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkPort::M_rawio(RtclArgs& args)
{
return DoRawio(args, fpObj, fErrCnt);
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkPort::M_stats(RtclArgs& args)
{
RtclStats::Context cntx;
 
if (!TestOpen(args)) return kERR;
if (!RtclStats::GetArgs(args, cntx)) return kERR;
if (!RtclStats::Collect(args, cntx, fpObj->Stats())) return kERR;
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkPort::M_log(RtclArgs& args)
{
string msg;
if (!args.GetArg("msg", msg)) return kERR;
if (!args.AllDone()) return kERR;
if (fTraceLevel != 0) fspLog->Write(string("# ") + msg);
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkPort::M_dump(RtclArgs& args)
{
if (!args.AllDone()) return kERR;
if (!TestOpen(args)) return kERR;
 
ostringstream sos;
fpObj->Dump(sos, 0);
args.SetResult(sos);
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkPort::M_config(RtclArgs& args)
{
static RtclNameSet optset("-logfile|-logtracelevel");
 
if (args.NDone() == (size_t)args.Objc()) {
ostringstream sos;
sos << " -logfile {" << fspLog->Name() << "}"
<< " -logtracelevel " << RosPrintf(fTraceLevel, "d");
args.AppendResult(sos);
return kOK;
}
 
string opt;
while (args.NextOpt(opt, optset)) {
if (opt == "-logfile") { // -logfile ?name ------------------
string name;
if (!args.Config("??name", name)) return false;
if (args.NOptMiss() == 0) { // new filename ?
if (name == "-" || name == "<cout>") {
fspLog->UseStream(&cout, "<cout>");
} else {
if (!fspLog->Open(name)) {
fspLog->UseStream(&cout, "<cout>");
return args.Quit(string("-E: open failed for '") + name +
"', using stdout");
}
}
}
} else if (opt == "-logtracelevel") { // -logtracelevel ?loglevel --------
if (!args.Config("??loglevel", fTraceLevel, 3)) return false;
if (fpObj) fpObj->SetTraceLevel(fTraceLevel);
}
}
 
if (!args.AllDone()) return kERR;
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkPort::M_default(RtclArgs& args)
{
if (!args.AllDone()) return kERR;
ostringstream sos;
 
sos << "logfile: " << fspLog->Name()
<< " tracelevel " << fTraceLevel;
 
args.AppendResultLines(sos);
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
bool RtclRlinkPort::TestOpen(RtclArgs& args)
{
if (fpObj) return true;
args.AppendResult("-E: port not open", NULL);
return false;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkPort::DoRawio(RtclArgs& args, RlinkPort* pport, size_t& errcnt)
{
static RtclNameSet optset("-rblk|-wblk|-edata|-timeout");
 
if (!pport || !pport->IsOpen()) args.Quit("-E: port not open");
 
string opt;
char mode = 0;
 
int32_t rsize;
string rvname;
vector<uint8_t> rdata;
vector<uint8_t> wdata;
vector<uint8_t> edata;
vector<uint8_t> emask;
double timeout = 1.;
 
while (args.NextOpt(opt, optset)) {
if (opt == "-rblk") { // -rblk size ?varData ------------
if (mode) return args.Quit("-E: only one -rblk or -wblk allowed");
mode = 'r';
if (!args.GetArg("bsize", rsize, 1, 256)) return kERR;
if (!args.GetArg("??varData", rvname)) return kERR;
 
} else if (opt == "-wblk") { // -wblk block --------------------
if (mode) return args.Quit("-E: only one -rblk or -wblk allowed");
mode = 'w';
if (!args.GetArg("data", wdata, 1, 256)) return kERR;
 
} else if (opt == "-edata") { // -edata data ?mask --------------
if (mode != 'r') return args.Quit("-E: -edata only allowed after -rblk");
if (!args.GetArg("data", edata, 0, rsize)) return kERR;
if (!args.GetArg("??mask", emask, 0, rsize)) return kERR;
 
} else if (opt == "-timeout") { // -timeout tsec ------------------
if (!args.GetArg("tsec", timeout, 0.)) return kERR;
}
}
if (!args.AllDone()) return kERR;
 
if (!mode) return args.Quit("-E: no -rblk or -wblk given");
 
if (mode == 'r') { // handle -rblk ------------------
RerrMsg emsg;
double tused = 0.;
rdata.resize(rsize);
int irc = pport->RawRead(rdata.data(), rdata.size(), true, timeout,
tused, emsg);
if (irc == RlinkPort::kErr) return args.Quit("-E: timeout on -rblk");
if (irc != (int)rdata.size()) return args.Quit(emsg);
if (rvname.length()) {
RtclOPtr pres(Rtcl::NewListIntObj(rdata));
if(!Rtcl::SetVar(args.Interp(), rvname, pres)) return kERR;
}
if (edata.size()) {
size_t nerr=0;
for (size_t i=0; i<rdata.size(); i++) {
if (i >= edata.size()) break;
uint8_t eval = edata[i];
uint8_t emsk = (i < emask.size()) ? emask[i] : 0x0000;
if ((rdata[i]|emsk) != (eval|emsk)) nerr += 1;
}
if (nerr) errcnt += 1;
}
args.SetResult(tused);
 
} else { // handle -wblk ------------------
RerrMsg emsg;
int irc = pport->RawWrite(wdata.data(), wdata.size(), emsg);
if (irc != (int)wdata.size()) return args.Quit(emsg);
}
 
return kOK;
}
 
} // end namespace Retro
/Makefile
0,0 → 1,65
# $Id: Makefile 529 2013-08-02 17:15:43Z mueller $
#
# Revision History:
# Date Rev Version Comment
# 2013-02-01 479 1.1.32 use checkpath_cpp.mk
# 2013-01-27 478 1.1.2 add RtclRlinkPort
# 2012-12-24 464 1.1.1 add TCLINC
# 2011-07-31 401 1.1 rename realclean->distclean
# 2011-07-01 386 1.0.2 add BOOSTINC
# 2011-03-20 372 1.0.1 renamed ..tcl -> ..tpp
# 2011-02-12 360 1.0 Initial version
#---
#
# Name of the sharable library
#
SONAME = rlinktpp
SOMAJV = 1
SOMINV = 0
#
# Compile and Link search paths
#
include ../checkpath_cpp.mk
#
INCLFLAGS = -I${RETROBASE}/tools/src -I${TCLINC} -I${BOOSTINC}
LDLIBS = -L${RETROBASE}/tools/lib -lrtools -lrtcltools -lrlink
#
# Object files to be included
#
OBJ_all = Rlinktpp_Init.o RtclRlinkPort.o RtclRlinkConnect.o \
RtclRlinkServer.o RtclAttnShuttle.o
#
DEP_all = $(OBJ_all:.o=.dep)
#
#- generic part ----------------------------------------------------------------
#
SOFILE = lib$(SONAME).so
SOFILEV = lib$(SONAME).so.$(SOMAJV)
SOFILEVV = lib$(SONAME).so.$(SOMAJV).$(SOMINV)
#
include $(RETROBASE)/tools/make/generic_cpp.mk
include $(RETROBASE)/tools/make/generic_dep.mk
include $(RETROBASE)/tools/make/generic_so.mk
include $(RETROBASE)/tools/make/dontincdep.mk
#
# The magic auto-dependency include
#
ifndef DONTINCDEP
include $(DEP_all)
endif
#
# cleanup phonies:
#
.PHONY : clean cleandep distclean
clean :
@ rm -f $(OBJ_all)
@ echo "Object files removed"
#
cleandep :
@ rm -f $(DEP_all)
@ echo "Dependency files removed"
#
distclean : clean cleandep
@ rm -f $(SOPATH)/lib$(SONAME).a $(SOPATH)/lib$(SONAME).so*
@ echo "Libraries removed"
#
/RtclRlinkServer.cpp
0,0 → 1,293
// $Id: RtclRlinkServer.cpp 513 2013-05-01 14:02:06Z mueller $
//
// Copyright 2013- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2013-05-01 513 1.0.5 TraceLevel now uint32_t
// 2013-04-26 510 1.0.4 change M_attn, now -info instead of -show
// 2013-04-21 509 1.0.3 add server -resume
// 2013-02-05 483 1.0.2 ClassCmdConfig: use RtclArgs
// 2013-02-05 482 1.0.1 add shared_ptr to RlinkConnect object
// 2013-01-12 474 1.0 Initial version
// ---------------------------------------------------------------------------
 
/*!
\file
\version $Id: RtclRlinkServer.cpp 513 2013-05-01 14:02:06Z mueller $
\brief Implemenation of class RtclRlinkServer.
*/
 
#include <ctype.h>
 
#include <stdexcept>
#include <iostream>
#include <vector>
#include <string>
#include <memory>
 
#include "boost/bind.hpp"
 
#include "librtools/RosPrintBvi.hpp"
#include "librtcltools/Rtcl.hpp"
#include "librtcltools/RtclOPtr.hpp"
#include "librtcltools/RtclStats.hpp"
#include "librtcltools/RtclContext.hpp"
#include "RtclRlinkConnect.hpp"
 
#include "RtclRlinkServer.hpp"
 
using namespace std;
 
/*!
\class Retro::RtclRlinkServer
\brief FIXME_docs
*/
 
// all method definitions in namespace Retro
namespace Retro {
 
//------------------------------------------+-----------------------------------
//! Default constructor
 
RtclRlinkServer::RtclRlinkServer(Tcl_Interp* interp, const char* name)
: RtclProxyOwned<RlinkServer>("RlinkServer", interp, name,
new RlinkServer()),
fspConn()
{
AddMeth("server", boost::bind(&RtclRlinkServer::M_server, this, _1));
AddMeth("attn", boost::bind(&RtclRlinkServer::M_attn, this, _1));
AddMeth("stats", boost::bind(&RtclRlinkServer::M_stats, this, _1));
AddMeth("print", boost::bind(&RtclRlinkServer::M_print, this, _1));
AddMeth("dump", boost::bind(&RtclRlinkServer::M_dump, this, _1));
AddMeth("$default", boost::bind(&RtclRlinkServer::M_default, this, _1));
}
 
//------------------------------------------+-----------------------------------
//! Destructor
 
RtclRlinkServer::~RtclRlinkServer()
{
for (alist_it_t it = fAttnHdl.begin(); it != fAttnHdl.end(); it++) {
delete (*it);
}
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkServer::ClassCmdConfig(RtclArgs& args)
{
string parent;
if (!args.GetArg("parent", parent)) return kERR;
 
// locate RlinkConnect proxy and object -> setup Server->Connect linkage
RtclProxyBase* pprox = RtclContext::Find(args.Interp()).FindProxy(
"RlinkConnect", parent);
if (pprox == 0)
return args.Quit(string("-E: object '") + parent +
"' not found or not type RlinkConnect");
 
// make RtclRlinkServer object be co-owner of RlinkConnect object
fspConn = dynamic_cast<RtclRlinkConnect*>(pprox)->ObjSPtr();
// set RlinkConnect in RlinkServer (make RlinkServer also co-owner)
Obj().SetConnect(fspConn);
 
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkServer::M_server(RtclArgs& args)
{
static RtclNameSet optset("-start|-stop|-resume|-test|-trace");
string opt;
if (args.NextOpt(opt, optset)) {
if (opt == "-start") { // server -start
if (!args.AllDone()) return kERR;
Obj().Start();
} else if (opt == "-stop") { // server -stop
if (!args.AllDone()) return kERR;
Obj().Stop();
} else if (opt == "-resume") { // server -resume
if (!args.AllDone()) return kERR;
Obj().Resume();
} else if (opt == "-test") { // server -test
if (!args.AllDone()) return kERR;
args.SetResult(Obj().IsActive());
} else if (opt == "-trace") { // server -trace ...
uint32_t level;
if (!args.GetArg("?level", level)) return kERR;
if (args.NOptMiss()==0) { // server -trace level
Obj().SetTraceLevel(level);
} else { // server -trace
args.SetResult((int)Obj().TraceLevel());
}
}
} else { // server
if (!args.OptValid()) return kERR;
if (!args.AllDone()) return kERR;
args.SetResult(Obj().IsActive());
}
 
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkServer::M_attn(RtclArgs& args)
{
static RtclNameSet optset("-add|-remove|-info|-test|-list");
 
Tcl_Interp* interp = args.Interp();
 
string opt;
 
if (args.NextOpt(opt, optset)) {
if (opt == "-add") { // attn -add mask script
uint16_t mask=0;
Tcl_Obj* script=0;
if (!args.GetArg("mask", mask,0xff,1)) return kERR;
if (!args.GetArg("script", script)) return kERR;
if (!args.AllDone()) return kERR;
 
unique_ptr<RtclAttnShuttle> p(new RtclAttnShuttle(mask, script));
try {
p->Add(&Obj(), interp);
} catch (exception& e) {
return args.Quit(string("-E: handler rejected: ")+e.what());
}
fAttnHdl.push_back(p.release());
return kOK;
 
} else if (opt == "-remove") { // attn -remove mask
uint16_t mask=0;
if (!args.GetArg("mask", mask)) return kERR;
if (!args.AllDone()) return kERR;
for (alist_it_t it = fAttnHdl.end(); it != fAttnHdl.begin(); ) {
it--;
if ((*it)->Mask() == mask) {
fAttnHdl.erase(it);
delete (*it);
return kOK;
}
}
return args.Quit(string("-E: no handler defined for '") +
args.PeekArgString(-1) + "'");
 
} else if (opt == "-info") { // attn -info mask
uint16_t mask=0;
if (!args.GetArg("mask", mask)) return kERR;
if (!args.AllDone()) return kERR;
RtclOPtr pres(Tcl_NewListObj(0,0));
for (alist_it_t it = fAttnHdl.begin(); it != fAttnHdl.end(); it++) {
if ((*it)->Mask() & mask) {
RtclOPtr pele(Tcl_NewListObj(0,0));
Tcl_ListObjAppendElement(NULL, pele, Tcl_NewIntObj((*it)->Mask()) );
Tcl_ListObjAppendElement(NULL, pele, (*it)->Script() );
Tcl_ListObjAppendElement(NULL, pres, pele);
}
}
args.SetResult(pres);
return kOK;
 
} else if (opt == "-test") { // attn -test mask
uint16_t mask=0;
if (!args.GetArg("mask", mask)) return kERR;
if (!args.AllDone()) return kERR;
int nhdl = 0;
for (alist_it_t it = fAttnHdl.begin(); it != fAttnHdl.end(); it++) {
if ((*it)->Mask() & mask) {
nhdl += 1;
int rc = Tcl_EvalObjEx(interp, (*it)->Script(), TCL_EVAL_GLOBAL);
if (rc != kOK) return rc;
}
}
if (nhdl) return kOK;
return args.Quit(string("-E: no handler defined for '") +
args.PeekArgString(-1) + "'");
 
} else if (opt == "-list") { // attn -list
if (!args.AllDone()) return kERR;
vector<uint16_t> vres;
for (alist_it_t it = fAttnHdl.begin(); it != fAttnHdl.end(); it++) {
vres.push_back((*it)->Mask());
}
args.SetResult(Rtcl::NewListIntObj(vres));
}
} else { // attn
if (!args.OptValid()) return kERR;
if (!args.AllDone()) return kERR;
uint16_t mask=0;
for (alist_it_t it = fAttnHdl.begin(); it != fAttnHdl.end(); it++) {
mask |= (*it)->Mask();
}
args.SetResult(mask);
}
 
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkServer::M_stats(RtclArgs& args)
{
RtclStats::Context cntx;
if (!RtclStats::GetArgs(args, cntx)) return kERR;
if (!RtclStats::Collect(args, cntx, Obj().Stats())) return kERR;
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkServer::M_print(RtclArgs& args)
{
if (!args.AllDone()) return kERR;
 
ostringstream sos;
Obj().Print(sos);
args.SetResult(sos);
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkServer::M_dump(RtclArgs& args)
{
if (!args.AllDone()) return kERR;
 
ostringstream sos;
Obj().Dump(sos, 0);
args.SetResult(sos);
return kOK;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
int RtclRlinkServer::M_default(RtclArgs& args)
{
if (!args.AllDone()) return kERR;
ostringstream sos;
sos << "no default output defined yet...\n";
args.AppendResultLines(sos);
return kOK;
}
 
} // end namespace Retro
/RtclRlinkPort.hpp
0,0 → 1,74
// $Id: RtclRlinkPort.hpp 492 2013-02-24 22:14:47Z mueller $
//
// Copyright 2013- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2013-02-23 492 1.0.1 use RlogFile.Name();
// 2013-01-27 478 1.0 Initial version
// ---------------------------------------------------------------------------
 
/*!
\file
\version $Id: RtclRlinkPort.hpp 492 2013-02-24 22:14:47Z mueller $
\brief Declaration of class RtclRlinkPort.
*/
 
#ifndef included_Retro_RtclRlinkPort
#define included_Retro_RtclRlinkPort 1
 
#include <cstddef>
#include <string>
 
#include "boost/shared_ptr.hpp"
 
#include "librtcltools/RtclProxyBase.hpp"
 
#include "librtools/RlogFile.hpp"
#include "librlink/RlinkPort.hpp"
 
namespace Retro {
 
class RtclRlinkPort : public RtclProxyBase {
public:
RtclRlinkPort(Tcl_Interp* interp, const char* name);
~RtclRlinkPort();
 
friend class RtclRlinkConnect;
 
protected:
int M_open(RtclArgs& args);
int M_close(RtclArgs& args);
int M_errcnt(RtclArgs& args);
int M_rawio(RtclArgs& args);
int M_stats(RtclArgs& args);
int M_log(RtclArgs& args);
int M_dump(RtclArgs& args);
int M_config(RtclArgs& args);
int M_default(RtclArgs& args);
 
bool TestOpen(RtclArgs& args);
 
static int DoRawio(RtclArgs& args, RlinkPort* pport, size_t& errcnt);
 
protected:
RlinkPort* fpObj; //!< ptr to managed object
boost::shared_ptr<RlogFile> fspLog; //!< port log file
uint32_t fTraceLevel; //!< 0=off,1=buf,2=char
size_t fErrCnt; //!< error count
};
} // end namespace Retro
 
//#include "RtclRlinkPort.ipp"
 
#endif
/RtclRlinkServer.hpp
0,0 → 1,70
// $Id: RtclRlinkServer.hpp 486 2013-02-10 22:34:43Z mueller $
//
// Copyright 2013- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2013-02-05 482 1.0.1 add shared_ptr to RlinkConnect object
// 2013-01-12 474 1.0 Initial version
// ---------------------------------------------------------------------------
 
/*!
\file
\version $Id: RtclRlinkServer.hpp 486 2013-02-10 22:34:43Z mueller $
\brief Declaration of class RtclRlinkServer.
*/
 
#ifndef included_Retro_RtclRlinkServer
#define included_Retro_RtclRlinkServer 1
 
#include <cstddef>
#include <list>
 
#include "boost/shared_ptr.hpp"
 
#include "librtcltools/RtclOPtr.hpp"
#include "librtcltools/RtclProxyOwned.hpp"
#include "RtclAttnShuttle.hpp"
#include "librlink/RlinkServer.hpp"
 
namespace Retro {
 
class RlinkConnect;
 
class RtclRlinkServer : public RtclProxyOwned<RlinkServer> {
public:
RtclRlinkServer(Tcl_Interp* interp, const char* name);
~RtclRlinkServer();
 
virtual int ClassCmdConfig(RtclArgs& args);
 
protected:
int M_server(RtclArgs& args);
int M_attn(RtclArgs& args);
int M_stats(RtclArgs& args);
int M_print(RtclArgs& args);
int M_dump(RtclArgs& args);
int M_default(RtclArgs& args);
 
protected:
typedef std::list<RtclAttnShuttle*> alist_t;
typedef alist_t::iterator alist_it_t;
 
boost::shared_ptr<RlinkConnect> fspConn;
alist_t fAttnHdl; //<! list of attn handlers
};
} // end namespace Retro
 
//#include "RtclRlinkServer.ipp"
 
#endif
/RtclRlinkConnect.hpp
0,0 → 1,78
// $Id: RtclRlinkConnect.hpp 492 2013-02-24 22:14:47Z mueller $
//
// Copyright 2011-2013 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2013-02-23 492 1.0.3 use RlogFile.Name(); use Context().ErrorCount()
// 2013-01-06 473 1.0.2 add M_rawio
// 2011-11-28 434 1.0.1 ConfigBase(): use uint32_t for lp64 compatibility
// 2011-03-27 374 1.0 Initial version
// 2011-02-11 360 0.1 First draft
// ---------------------------------------------------------------------------
 
/*!
\file
\version $Id: RtclRlinkConnect.hpp 492 2013-02-24 22:14:47Z mueller $
\brief Declaration of class RtclRlinkConnect.
*/
 
#ifndef included_Retro_RtclRlinkConnect
#define included_Retro_RtclRlinkConnect 1
 
#include <cstddef>
#include <string>
 
#include "librtcltools/RtclOPtr.hpp"
#include "librtcltools/RtclProxyOwned.hpp"
 
#include "librlink/RlinkConnect.hpp"
 
namespace Retro {
 
class RtclRlinkConnect : public RtclProxyOwned<RlinkConnect> {
public:
RtclRlinkConnect(Tcl_Interp* interp, const char* name);
~RtclRlinkConnect();
 
protected:
int M_open(RtclArgs& args);
int M_close(RtclArgs& args);
int M_exec(RtclArgs& args);
int M_amap(RtclArgs& args);
int M_errcnt(RtclArgs& args);
int M_wtlam(RtclArgs& args);
int M_oob(RtclArgs& args);
int M_rawio(RtclArgs& args);
int M_stats(RtclArgs& args);
int M_log(RtclArgs& args);
int M_print(RtclArgs& args);
int M_dump(RtclArgs& args);
int M_config(RtclArgs& args);
int M_default(RtclArgs& args);
 
bool GetAddr(RtclArgs& args, RlinkConnect& conn, uint16_t& addr);
bool GetVarName(RtclArgs& args, const char* argname,
size_t nind, std::vector<std::string>& varname);
bool ConfigBase(RtclArgs& args, uint32_t& base);
bool ClistNonEmpty(RtclArgs& args,
const RlinkCommandList& clist);
 
protected:
RtclOPtr fCmdnameObj[8];
};
} // end namespace Retro
 
//#include "RtclRlinkConnect.ipp"
 
#endif
/Rlinktpp_Init.cpp
0,0 → 1,68
// $Id: Rlinktpp_Init.cpp 504 2013-04-13 15:37:24Z mueller $
//
// Copyright 2011-2013 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2013-02-10 485 1.0.5 remove Tcl_InitStubs()
// 2013-01-27 478 1.0.4 add rlinkport
// 2013-01-12 474 1.0.3 add rlinkserver
// 2011-03-20 372 1.0.2 renamed ..tcl -> ..tpp
// 2011-03-19 371 1.0.1 moved Bvi into librtoolstcl
// 2011-03-14 370 1.0 Initial version
// 2011-02-11 360 0.1 First draft
// ---------------------------------------------------------------------------
 
/*!
\file
\version $Id: Rlinktpp_Init.cpp 504 2013-04-13 15:37:24Z mueller $
\brief Implemenation of Rlinktpp_Init .
*/
 
#include "tcl.h"
 
#include <stdexcept>
 
#include "librtcltools/RtclClassOwned.hpp"
#include "RtclRlinkPort.hpp"
#include "RtclRlinkConnect.hpp"
#include "RtclRlinkServer.hpp"
 
using namespace std;
using namespace Retro;
 
//------------------------------------------+-----------------------------------
extern "C" int Rlinktpp_Init(Tcl_Interp* interp)
{
int irc;
 
// declare package name and version
irc = Tcl_PkgProvide(interp, "rlinktpp", "1.0.0");
if (irc != TCL_OK) return irc;
 
try {
// register class commands
RtclClassOwned<RtclRlinkPort>::CreateClass(interp, "rlinkport",
"RlinkPort");
RtclClassOwned<RtclRlinkConnect>::CreateClass(interp, "rlinkconnect",
"RlinkConnect");
RtclClassOwned<RtclRlinkServer>::CreateClass(interp, "rlinkserver",
"RlinkServer");
return TCL_OK;
 
} catch (exception& e) {
Tcl_AppendResult(interp, "-E: exception caught in Rlinktpp_Init: '",
e.what(), "'", NULL);
}
return TCL_ERROR;
}
 
/RtclAttnShuttle.hpp
0,0 → 1,68
// $Id: RtclAttnShuttle.hpp 495 2013-03-06 17:13:48Z mueller $
//
// Copyright 2013- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2013-03-01 493 1.0 Initial version
// 2013-01-14 475 0.5 First draft
// ---------------------------------------------------------------------------
 
/*!
\file
\version $Id: RtclAttnShuttle.hpp 495 2013-03-06 17:13:48Z mueller $
\brief Declaration of class RtclAttnShuttle.
*/
 
#ifndef included_Retro_RtclAttnShuttle
#define included_Retro_RtclAttnShuttle 1
 
#include "tcl.h"
 
#include <cstdint>
 
#include "librtcltools/RtclOPtr.hpp"
#include "librlink/RlinkServer.hpp"
 
namespace Retro {
 
class RtclAttnShuttle {
public:
RtclAttnShuttle(uint16_t mask, Tcl_Obj* pobj);
~RtclAttnShuttle();
 
uint16_t Mask() const;
Tcl_Obj* Script() const;
 
void Add(RlinkServer* pserv, Tcl_Interp* interp);
void Remove();
 
protected:
int AttnHandler(const RlinkServer::AttnArgs& args);
void TclChannelHandler(int mask);
static void ThunkTclChannelHandler(ClientData cdata, int mask);
 
protected:
RlinkServer* fpServ; //!< RlinkServer used
Tcl_Interp* fpInterp; //!< Tcl interpreter used
int fFdPipeRead; //!< attn pipe read fd
int fFdPipeWrite; //!< attn pipe write fd
Tcl_Channel fShuttleChn; //!< Tcl channel
uint16_t fMask; //!< attn mask
RtclOPtr fpScript; //!< Tcl handler script (as Tcl_Obj)
};
} // end namespace Retro
 
#include "RtclAttnShuttle.ipp"
 
#endif
/RtclAttnShuttle.ipp
0,0 → 1,46
// $Id: RtclAttnShuttle.ipp 495 2013-03-06 17:13:48Z mueller $
//
// Copyright 2013- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2013-03-01 493 1.0 Initial version
// 2013-01-14 475 0.5 First draft
// ---------------------------------------------------------------------------
 
/*!
\file
\version $Id: RtclAttnShuttle.ipp 495 2013-03-06 17:13:48Z mueller $
\brief Implemenation (inline) of class RtclAttnShuttle.
*/
 
// all method definitions in namespace Retro
namespace Retro {
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
inline uint16_t RtclAttnShuttle::Mask() const
{
return fMask;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
inline Tcl_Obj* RtclAttnShuttle::Script() const
{
return fpScript;
}
 
} // end namespace Retro
 
/.cvsignore
0,0 → 1,46
*.dep
/.
. Property changes : Added: svn:ignore ## -0,0 +1,34 ## +*.dep_ghdl +*.dep_isim +*.dep_xst +work-obj93.cf +*.vcd +*.ghw +*.sav +*.tmp +*.exe +ise +xflow.his +*.ngc +*.ncd +*.pcf +*.bit +*.msk +isim +isim.log +isim.wdb +fuse.log +*_[sft]sim.vhd +*_tsim.sdf +*_xst.log +*_tra.log +*_twr.log +*_map.log +*_par.log +*_tsi.log +*_pad.log +*_bgn.log +*_svn.log +*_sum.log +*_[dsft]sim.log +*.dep

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.