00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "NetAnimTrace.h"
00019
00020 #if OMNETPP_VERSION >= 0x0401
00021
00022 Define_Module(NetAnimTrace);
00023
00024 simsignal_t NetAnimTrace::messageSentSignal;
00025
00026
00027
00028 void NetAnimTrace::initialize()
00029 {
00030 if (!par("enabled").boolValue())
00031 return;
00032
00033 const char *filename = par("filename");
00034 f.open(filename, std::ios::out | std::ios::trunc);
00035 if (f.fail())
00036 throw cRuntimeError("Cannot open file \"%s\" for writing", filename);
00037
00038 dump();
00039
00040 messageSentSignal = registerSignal("messageSent");
00041 simulation.getSystemModule()->subscribe(POST_MODEL_CHANGE, this);
00042 simulation.getSystemModule()->subscribe(messageSentSignal, this);
00043 }
00044
00045 void NetAnimTrace::handleMessage(cMessage *msg)
00046 {
00047 throw cRuntimeError("This module does not handle messages");
00048 }
00049
00050 void NetAnimTrace::finish()
00051 {
00052 f.close();
00053 }
00054
00055 void NetAnimTrace::dump()
00056 {
00057 cModule *parent = simulation.getSystemModule();
00058 for (cModule::SubmoduleIterator it(parent); !it.end(); it++)
00059 if (it() != this)
00060 addNode(it());
00061 for (cModule::SubmoduleIterator it(parent); !it.end(); it++)
00062 if (it() != this)
00063 for (cModule::GateIterator ig(it()); !ig.end(); ig++)
00064 if (ig()->getType()==cGate::OUTPUT && ig()->getNextGate())
00065 addLink(ig());
00066 }
00067
00068 void NetAnimTrace::receiveSignal(cComponent *source, simsignal_t signalID, cObject *obj)
00069 {
00070 if (signalID == messageSentSignal && !source->isModule())
00071 {
00072
00073 cChannel *channel = (cChannel *)source;
00074 cModule *srcModule = channel->getSourceGate()->getOwnerModule();
00075 if (isRelevantModule(srcModule))
00076 {
00077 cModule *destModule = channel->getSourceGate()->getNextGate()->getOwnerModule();
00078 cITimestampedValue *v = check_and_cast<cITimestampedValue *>(obj);
00079 if (dynamic_cast<cDatarateChannel *>(channel))
00080 {
00081 cDatarateChannel *datarateChannel = (cDatarateChannel *)channel;
00082 cMessage *msg = check_and_cast<cMessage *>(v->objectValue(signalID));
00083 simtime_t duration = msg->isPacket() ? ((cPacket*)msg)->getBitLength() / datarateChannel->getDatarate() : 0.0;
00084 simtime_t delay = datarateChannel->getDelay();
00085 simtime_t fbTx = v->getTimestamp(signalID);
00086 simtime_t lbTx = fbTx + duration;
00087 simtime_t fbRx = fbTx + delay;
00088 simtime_t lbRx = lbTx + delay;
00089 f << fbTx << " P " << srcModule->getId() << " " << destModule->getId() << " " << lbTx << " " << fbRx << " " << lbRx << "\n";
00090 }
00091 else if (dynamic_cast<cDelayChannel *>(channel))
00092 {
00093 cDelayChannel *delayChannel = (cDelayChannel *)channel;
00094 simtime_t fbTx = v->getTimestamp(signalID);
00095 simtime_t fbRx = fbTx + delayChannel->getDelay();
00096 f << fbTx << " P " << srcModule->getId() << " " << destModule->getId() << " " << fbTx << " " << fbRx << " " << fbRx << "\n";
00097 }
00098 }
00099 }
00100 else if (signalID == POST_MODEL_CHANGE)
00101 {
00102
00103
00104 if (dynamic_cast<cPostModuleAddNotification *>(obj))
00105 {
00106 cPostModuleAddNotification *notification = (cPostModuleAddNotification *)obj;
00107 if (isRelevantModule(notification->module))
00108 addNode(notification->module);
00109 }
00110 else if (dynamic_cast<cPostGateConnectNotification *>(obj))
00111 {
00112 cPostGateConnectNotification *notification = (cPostGateConnectNotification *)obj;
00113 if (isRelevantModule(notification->gate->getOwnerModule()))
00114 addLink(notification->gate);
00115 }
00116 }
00117 }
00118
00119 bool NetAnimTrace::isRelevantModule(cModule *mod)
00120 {
00121 return mod->getParentModule() == simulation.getSystemModule();
00122 }
00123
00124 void NetAnimTrace::addNode(cModule *mod)
00125 {
00126 double x, y;
00127 resolveNodeCoordinates(mod, x, y);
00128 f << simTime() << " N " << mod->getId() << " " << x << " " << y << "\n";
00129 }
00130
00131 void NetAnimTrace::addLink(cGate *gate)
00132 {
00133 f << simTime() << " L " << gate->getOwnerModule()->getId() << " " << gate->getNextGate()->getOwnerModule()->getId() << "\n";
00134 }
00135
00136 double toDouble(const char *s, double defaultValue)
00137 {
00138 if (!s || !*s)
00139 return defaultValue;
00140 char *end;
00141 double d = strtod(s, &end);
00142 return (end && *end) ? 0.0 : d;
00143 }
00144
00145 void NetAnimTrace::resolveNodeCoordinates(cModule *submod, double& x, double& y)
00146 {
00147
00148 x = 600 * dblrand();
00149 y = 400 * dblrand();
00150
00151
00152 cDisplayString& ds = submod->getDisplayString();
00153 if (!ds.containsTag("p"))
00154 return;
00155
00156
00157
00158
00159 x = toDouble(ds.getTagArg("p",0), x);
00160 y = toDouble(ds.getTagArg("p",1), y);
00161
00162 double sx = 20;
00163 double sy = 20;
00164
00165 const char *layout = ds.getTagArg("p",2);
00166
00167
00168 if (!layout || !*layout)
00169 {
00170
00171 }
00172 else if (!strcmp(layout,"e") || !strcmp(layout,"x") || !strcmp(layout,"exact"))
00173 {
00174 int dx = toDouble(ds.getTagArg("p",3), 0);
00175 int dy = toDouble(ds.getTagArg("p",4), 0);
00176 x += dx;
00177 y += dy;
00178 }
00179 else if (!strcmp(layout,"r") || !strcmp(layout,"row"))
00180 {
00181 int dx = toDouble(ds.getTagArg("p",3), 2*sx);
00182 x += submod->getIndex()*dx;
00183 }
00184 else if (!strcmp(layout,"c") || !strcmp(layout,"col") || !strcmp(layout,"column"))
00185 {
00186 int dy = toDouble(ds.getTagArg("p",3), 2*sy);
00187 y += submod->getIndex()*dy;
00188 }
00189 else if (!strcmp(layout,"m") || !strcmp(layout,"matrix"))
00190 {
00191 int columns = toDouble(ds.getTagArg("p",3), 5);
00192 int dx = toDouble(ds.getTagArg("p",4), 2*sx);
00193 int dy = toDouble(ds.getTagArg("p",5), 2*sy);
00194 x += (submod->getIndex() % columns)*dx;
00195 y += (submod->getIndex() / columns)*dy;
00196 }
00197 else if (!strcmp(layout,"i") || !strcmp(layout,"ri") || !strcmp(layout,"ring"))
00198 {
00199 int rx = toDouble(ds.getTagArg("p",3), (sx+sy)*submod->size()/4);
00200 int ry = toDouble(ds.getTagArg("p",4), rx);
00201
00202 x += (int) floor(rx - rx*sin(submod->getIndex()*2*PI/submod->size()));
00203 y += (int) floor(ry - ry*cos(submod->getIndex()*2*PI/submod->size()));
00204 }
00205 else
00206 {
00207 throw cRuntimeError("invalid layout `%s' in `p' tag of display string", layout);
00208 }
00209 }
00210
00211 #endif // OMNETPP_VERSION
00212
00213
00214