40 using std::ostream_iterator;
51 verbosity(0), title(_title), cTA(NULL), cP(NULL), inp(false), out(false),
52 sync(false), paramsExpanded(false)
60 for (list<instance_t>::iterator it=ps.begin(), e=ps.end(); it!=e; ++it)
68 for (procs_t::const_iterator p=
procs.begin(), e=
procs.end(); p!=e; ++p)
70 os << (*p)->name <<
":\n ";
72 for_each((*p)->inChans.begin(), (*p)->inChans.end(),
76 for_each((*p)->outChans.begin(), (*p)->outChans.end(),
79 str2strs_t::const_iterator v;
81 for (v = (*p)->rdVars.begin(); v != (*p)->rdVars.end(); ++v)
83 os <<
" " << v->first <<
"(";
84 for_each(v->second.begin(), v->second.end(),
90 for (v = (*p)->wtVars.begin(); v != (*p)->wtVars.end(); ++v)
92 os <<
" " << v->first <<
"(";
93 for_each(v->second.begin(), v->second.end(),
104 os <<
" subgraph procs {\n";
107 os<<
" node [shape=rectangle,style=filled];\n";
111 os<<
" node [shape=ellipse,style=filled];\n";
115 for (procs_t::const_iterator p=
procs.begin(), e=
procs.end(); p!=e; ++p)
116 os << (*p)->name <<
"; ";
124 os <<
" subgraph cluste_vars {\n";
125 os <<
" style=invis;\n";
128 os <<
" rank=min;\n";
132 os <<
" node [shape=diamond,color=blue];\n ";
136 os <<
" node [shape=rectangle,color=blue];\n ";
147 os << *i <<
"[style=bold]; ";
156 os<<
" edge [style=bold,color=blue,fontcolor=blue,weight=100];\n";
158 for (procs_t::const_iterator a=
procs.begin(), ae=
procs.end(); a!=ae; ++a)
160 if (!(*a)->wtVars.empty())
162 for (str2strs_t::const_iterator v=(*a)->wtVars.begin(),
163 ve=(*a)->wtVars.end(); v!=ve; ++v)
165 os<<
" "<<(*a)->name<<
" -> " << v->first <<
" [label=\"(";
167 for_each(v->second.begin(), v->second.end(),
178 os<<
" edge [style=solid,color=blue,fontcolor=blue,weight=1];\n";
180 for (procs_t::const_iterator a=
procs.begin(),ae=
procs.end(); a!=ae; ++a)
182 if (!(*a)->rdVars.empty())
184 for (str2strs_t::const_iterator v = (*a)->rdVars.begin(),
185 ve=(*a)->rdVars.end(); v!=ve; ++v)
187 os<<
" " << v->first <<
" -> " <<(*a)->name<<
" [label=\"(";
189 for_each(v->second.begin(), v->second.end(),
200 const char* src =
"NO_SRC";
201 const char* dst =
"NO_DST";
203 for (procs_t::const_iterator a=
procs.begin(),ae=
procs.end(); a!=ae; ++a)
206 for (strs_t::const_iterator i=(*a)->outChans.begin(),
207 e=(*a)->outChans.end(); i!=e; ++i)
209 str2procs_t::const_iterator dests =
receivers.find(*i);
212 for (procs_t::const_iterator rec = dests->second.begin();
213 rec != dests->second.end(); ++rec)
215 (*a)->outEdges[*rec].insert(*i);
220 (*a)->outEdges[NULL].insert(*i);
226 os<<
" edge[style=solid,color=black,fontcolor=black,weight=50];\n";
227 for (procs_t::const_iterator a=
procs.begin(),ae=
procs.end(); a!=ae; ++a)
230 for (proc2strs_t::const_iterator edge = (*a)->outEdges.begin(),
231 edgeEnd=(*a)->outEdges.end(); edge!=edgeEnd; ++edge)
234 if (edge->first != NULL)
237 os<<
" " <<(*a)->name <<
" -> " << edge->first->name
245 <<
" [style=filled,fillcolor=red];\n";
248 os<<
" " <<(*a)->name <<
" -> " << dst
252 strs_t::const_iterator
ch=edge->second.begin();
257 if (ch != edge->second.end())
271 for (strs_t::const_iterator i=(*a)->inChans.begin(),
272 e=(*a)->inChans.end(); i!=e; ++i)
274 str2procs_t::const_iterator trans =
transmitters.find(*i);
280 <<
" [style=filled,fillcolor=red];\n";
283 os<<
" "<<src<<
" -> " << (*a)->name <<
" [label=\"" 293 os<<
" subgraph cluste_chans {\n";
294 os<<
" style=invis;\n";
301 os<<
" node [shape=diamond,color=red];\n ";
305 os<<
" node [shape=diamond,color=red];\n ";
311 for (procs_t::const_iterator a=
procs.begin(),ae=
procs.end(); a!=ae; ++a)
313 for (strs_t::const_iterator i=(*a)->inChans.begin(),
314 e=(*a)->inChans.end(); i!=e; ++i)
316 os <<
" " << *i <<
" -> " << (*a)->name <<
";\n";
318 for (strs_t::const_iterator i=(*a)->outChans.begin(),
319 e=(*a)->outChans.end(); i!=e; ++i)
321 os <<
" " << (*a)->name <<
" -> " << *i <<
" [style=bold];\n";
328 char* name = strcpy(
new char[strlen(
title)+1],
title);
329 for (uint32_t i=0, len=strlen(name); i<len; ++i)
331 if (!isalpha((
unsigned char)name[i]))
337 os <<
"digraph " << name <<
" {\n";
338 os <<
" model=subset; remincross=true;\n";
366 map<symbol_t, expression_t>::iterator e =
cP->
mapping.find(s);
375 cerr <<
"mapping param '"<< s.
getName() <<
"' failed"<<endl;
397 strs_t::iterator it =
channels.find(s.c_str());
399 s2 = strdup(s.c_str());
403 index[s2].insert(
cTA);
427 deque<state_t>::const_iterator s = temp->
states.begin();
428 while (s != temp->
states.end())
434 deque<edge_t>::const_iterator t;
435 for (t = temp->
edges.begin(); t != temp->
edges.end(); ++t)
481 for (uint32_t i=0; i<e.
getSize(); ++i)
511 inp =
false;
out =
true;
513 for (uint32_t i=1; i<e.
getSize(); ++i)
540 exprref_t::const_iterator exi =
refparams.top().find(sym);
564 std::ostringstream os;
573 for (uint32_t i=1; i<e.
getSize(); ++i)
599 for (uint32_t i=0; i<e.
getSize(); ++i)
607 for (uint32_t i=0; i<e.
getSize(); ++i)
615 for (uint32_t i=1; i<e.
getSize(); ++i)
625 for (uint32_t i=0; i<e.
getSize()-1; ++i)
672 for (
size_t i=0; i<e.
getSize()-1; ++i) {
685 cerr <<
"unsupported kind (" << e.
getKind()
686 <<
") of expression, please report it to developers."<<endl;
733 while (it != stat->
end())
735 res = (*it)->accept(
this);
791 procs_t::const_iterator p;
792 for (p =
procs.begin(); p !=
procs.end(); ++p)
delete *p;
793 strs_t::const_iterator c;
799 strs_t::const_iterator s;
800 for (s=chansInp.begin(); s!=chansInp.end(); ++s)
free((
char*)*s);
801 for (s=chansOut.begin(); s!=chansOut.end(); ++s)
free((
char*)*s);
802 chansInp.clear(); chansOut.clear();
808 cerr <<
"Violated rule \"" << rule <<
"\" for process \"" 809 << proc->
name <<
"\" accessing \"" << var <<
"\"" << endl;
821 for (strs_t::const_iterator c=chans.begin(), ce=chans.end(); c!=ce; ++c)
823 str2procs_t::const_iterator c2p;
824 c2p = index.find(*c);
825 if (c2p != index.end()) {
826 for (procs_t::const_iterator p=c2p->second.begin(),
827 pe=c2p->second.end(); p!=pe; ++p)
829 if (exclude.erase(*p) > 0) {
831 printViolation(*p, *c);
832 }
else if (result.find(*p) == result.end() &&
833 procsBad.find(*p) == procsBad.end()) {
836 cerr <<
"Adding \""<<(*p)->name <<
"\" using \""<<(*c)
837 <<
"\" by rule \""<<rule<<
"\""<<endl;
853 for (procs_t::const_iterator p=procs.begin(), pe=procs.end(); p!=pe; ++p)
855 for (strs_t::const_iterator c=(*p)->inChans.begin(),
856 ce=(*p)->inChans.end(); c!=ce; ++c)
858 if (observable.find(*c) == observable.end()) {
859 if (exclude.erase(*c) > 0) {
861 printViolation(*p, *c);
862 }
else if (result.find(*c) == result.end() &&
863 chansBad.find(*c) == chansBad.end()) {
865 cerr <<
"Adding \""<<(*c)<<
"\" because of \"" 866 <<(*p)->name <<
"\" by rule \""<<rule
872 for (strs_t::const_iterator c=(*p)->outChans.begin(),
873 ce=(*p)->outChans.end(); c!=ce; ++c)
875 if (observable.find(*c) == observable.end()) {
876 if (exclude.erase(*c) > 0) {
878 printViolation(*p, *c);
879 }
else if (result.find(*c) == result.end() &&
880 chansBad.find(*c) == chansBad.end()) {
882 cerr <<
"Adding \""<<(*c)<<
"\" because of \"" 883 <<(*p)->name <<
"\" by rule \""<<rule
899 for (procs_t::const_iterator p=procs.begin(), pe=procs.end(); p!=pe; ++p)
902 for (str2strs_t::const_iterator v2c=(*p)->rdVars.begin(),
903 v2ce=(*p)->rdVars.end(); v2c!=v2ce; ++v2c)
905 if (!includes(observable.begin(), observable.end(),
906 v2c->second.begin(), v2c->second.end(),
less_str()))
908 if (exclude.erase(v2c->first) > 0) {
909 varsBad.insert(v2c->first);
910 printViolation(*p, v2c->first);
911 }
else if (result.find(v2c->first) == result.end() &&
912 varsBad.find(v2c->first) == varsBad.end()) {
914 cerr <<
"Adding \""<<(v2c->first)<<
"\" because of \"" 915 <<(*p)->name <<
"\" by rule \""<<rule<<
"\""<<endl;
916 result.insert(v2c->first);
920 for (str2strs_t::const_iterator v2c=(*p)->wtVars.begin(),
921 v2ce=(*p)->wtVars.end(); v2c!=v2ce; ++v2c)
923 if (!includes(observable.begin(), observable.end(),
924 v2c->second.begin(), v2c->second.end(),
less_str()))
926 if (exclude.erase(v2c->first) > 0) {
927 varsBad.insert(v2c->first);
928 printViolation(*p, v2c->first);
929 }
else if (result.find(v2c->first) == result.end() &&
930 varsBad.find(v2c->first) == varsBad.end()) {
932 cerr <<
"Adding \""<<(v2c->first)<<
"\" because of \"" 933 <<(*p)->name <<
"\" by rule \""<<rule<<
"\""<<endl;
934 result.insert(v2c->first);
948 str2procs_t::const_iterator v2p;
949 str2strs_t::const_iterator v2c;
950 for (strs_t::const_iterator v=vars.begin(), ve=vars.end(); v!=ve; ++v)
954 for(procs_t::const_iterator p=v2p->second.begin(),
955 pe=v2p->second.end(); p!=pe; ++p)
957 v2c = (*p)->rdVars.find(*v);
958 if (v2c != (*p)->rdVars.end()) {
959 if (!includes(observable.begin(), observable.end(),
960 v2c->second.begin(), v2c->second.end(),
963 if (exclude.erase(*p) > 0) {
965 printViolation(*p, *v);
966 }
else if (procs.find(*p) == procs.end() &&
967 procsBad.find(*p) == procsBad.end()) {
969 cerr <<
"Adding \""<<(*p)->name
970 <<
"\" using \""<<(*v)
971 <<
"\" by rule \""<<rule<<
"\""<<endl;
977 cerr<<
"addProcsByVars could not find in rdVars"<<endl;
982 cerr <<
"addProcsByVars could not find readers"<<endl;
986 for(procs_t::const_iterator p=v2p->second.begin(),
987 pe=v2p->second.end(); p!=pe; ++p)
989 v2c = (*p)->wtVars.find(*v);
990 if (v2c != (*p)->wtVars.end()) {
991 if (!includes(observable.begin(), observable.end(),
992 v2c->second.begin(), v2c->second.end(),
995 if (exclude.erase(*p) > 0) {
997 printViolation(*p, *v);
998 }
else if (procs.find(*p) == procs.end() &&
999 procsBad.find(*p) == procsBad.end()) {
1001 cerr <<
"Adding \""<<(*p)->name
1002 <<
"\" using \""<<(*v)
1003 <<
"\" by rule \""<<rule<<
"\""<<endl;
1009 cerr<<
"addProcsByVars could not find in wtVars"<<endl;
1014 cerr<<
"addProcsByVars could not find writers for "<<(*v)<<endl;
1024 if (isalnum((
unsigned char)c) || c==
'_' || c==
'[' || c==
']') buffer += c;
1026 if (c==
'(')
while (in.get(c) && c!=
')') ;
1027 if (buffer.length()>0)
1028 return strdup(buffer.c_str());
1031 if (buffer.length()>0)
return strdup(buffer.c_str());
1039 std::ios::fmtflags flags = ioinfo.flags();
1040 ioinfo.unsetf(std::ios::skipws);
1043 if (strcmp(token,
"input")!=0) {
1044 cerr <<
"\"input\" is expected instead of \""<<token<<
"\"" << endl;
1049 while ((token =
get_token(ioinfo)) != NULL &&
1050 strcmp(token,
"output") != 0)
1051 inputs.insert(token);
1053 if (token == NULL) {
1054 cerr <<
"\"output\" expected, but EOF found" << endl;
1058 while ((token =
get_token(ioinfo)) != NULL &&
1059 strcmp(token,
"precision")!=0 && strcmp(token,
"timeout")!=0)
1060 outputs.insert(token);
1061 if (token != NULL)
free(token);
1063 ioinfo.flags(flags);
1064 int res = partition(inputs, outputs);
1065 strs_t::const_iterator s;
1066 for (s=inputs.begin(); s!=inputs.end(); ++s)
free((
char*)*s);
1067 for (s=outputs.begin(); s!=outputs.end(); ++s)
free((
char*)*s);
1073 procsEnv.clear(); procsIUT.clear();
1074 chansIntEnv.clear(); chansIntIUT.clear();
1075 varsEnv.clear(); varsIUT.clear();
1076 strs_t::const_iterator s;
1077 for (s=chansInp.begin(); s!=chansInp.end(); ++s)
free((
char*)*s);
1078 for (s=chansOut.begin(); s!=chansOut.end(); ++s)
free((
char*)*s);
1079 chansInp.clear(); chansOut.clear();
1081 for (s=inputs.begin(); s!=inputs.end(); ++s)
1082 chansInp.insert(strdup(*s));
1083 for (s=outputs.begin(); s!=outputs.end(); ++s)
1084 chansOut.insert(strdup(*s));
1087 observable.insert(chansInp.begin(), chansInp.end());
1088 observable.insert(chansOut.begin(), chansOut.end());
1091 cerr <<
"Inputs: " << chansInp << endl;
1092 cerr <<
"Outputs: " << chansOut << endl;
1095 size_t oldProgress=0, progress=0;
1097 oldProgress = progress;
1100 rule=
"transmitters on input channels belong to Env";
1102 rule=
"receivers on output channels belong to Env";
1103 addProcs(outputs,
receivers, procsEnv, procsIUT);
1104 rule=
"receivers on input channels belong IUT";
1105 addProcs(inputs,
receivers, procsIUT, procsEnv);
1106 rule=
"transmitters on output channels belong IUT";
1116 rule=
"internal channel belongs to Env if it is used by Env";
1117 addIntChans(procsEnv, chansIntEnv, chansIntIUT);
1118 rule=
"internal channel belongs to IUT if it is used by IUT";
1119 addIntChans(procsIUT, chansIntIUT, chansIntEnv);
1123 rule=
"process belongs to Env if it shouts on internal Env channel";
1124 addProcs(chansIntEnv,
transmitters, procsEnv, procsIUT);
1125 rule=
"process belongs to Env if it listens to internal Env channel";
1126 addProcs(chansIntEnv,
receivers, procsEnv, procsIUT);
1127 rule=
"process belongs to IUT if it shouts on internal IUT channel";
1128 addProcs(chansIntIUT,
transmitters, procsIUT, procsEnv);
1129 rule=
"process belongs to IUT if it listens to internal IUT channel";
1130 addProcs(chansIntIUT,
receivers, procsIUT, procsEnv);
1136 rule=
"variable belongs to Env if accessed by Env without observable sync";
1137 addIntVars(procsEnv, varsEnv, varsIUT);
1138 rule=
"variable belongs to IUT if accessed by IUT without observable sync";
1139 addIntVars(procsIUT, varsIUT, varsEnv);
1143 rule=
"process belongs to Env if it access Env variable without observable synchronization";
1144 addProcsByVars(varsEnv, procsEnv, procsIUT);
1145 rule=
"process belongs to IUT if it access IUT variable without observable synchronization";
1146 addProcsByVars(varsIUT, procsIUT, procsEnv);
1147 progress = procsEnv.size() + procsIUT.size() + procsBad.size();
1148 }
while (progress>oldProgress);
1149 procs_t::const_iterator p;
1152 cerr <<
"==== Partitioned =========================================\n";
1153 cerr <<
"Env procs: " << procsEnv << endl;
1154 cerr <<
"Env chans: " << chansIntEnv << endl;
1155 cerr <<
"Env vars: " << varsEnv << endl;
1156 cerr <<
"----------------------------------------------------------\n";
1157 cerr <<
"IUT procs: " << procsIUT << endl;
1158 cerr <<
"IUT chans: " << chansIntIUT << endl;
1159 cerr <<
"IUT vars: " << varsIUT << endl;
1160 cerr <<
"==========================================================\n";
1163 if (!procsBad.empty())
1164 cerr <<
"Inconsistent procs: " << procsBad << endl;
1165 if (!chansBad.empty())
1166 cerr <<
"Inconsistent chans: " << chansBad << endl;
1167 if (!varsBad.empty())
1168 cerr <<
"Inconsistent vars: " << varsBad << endl;
1173 if (procsEnv.find(*p) == procsEnv.end() &&
1174 procsIUT.find(*p) == procsIUT.end())
1175 leftovers.insert(*p);
1176 if (!leftovers.empty()) {
1177 cerr <<
"==== Not partitioned: ====================================\n";
1178 cerr <<
"procs: " << leftovers << endl;
1182 if (!procsBad.empty() || !chansBad.empty() || !varsBad.empty())
return 2;
1183 if (progress==
procs.size())
return 0;
1187 #define BADSTYLE "style=filled,fillcolor=\"#FF8080\"" 1188 #define IUTSTYLE "style=filled,fillcolor=\"#B8C0FF\"" 1189 #define ENVSTYLE "style=filled,fillcolor=\"#C8FFC8\"" 1190 #define MEDSTYLE "style=filled,fillcolor=\"#C0C0C0\"" 1195 for (SignalFlow::strs_t::const_iterator b=what.begin(), e=what.end();
1200 struct surround:
public std::unary_function<const char*, void>
1205 surround(ostream &os,
const char* prefix,
const char* postfix):
1206 out(os), pre(prefix), post(postfix) {}
1207 void operator()(
const char* x) {
1208 out << pre << x << post;
1215 char* name = strcpy(
new char[strlen(
title)+1],
title);
1216 for (uint32_t i=0; i<strlen(name); ++i)
1218 if (!isalpha((
unsigned char)name[i]))
1224 os <<
"digraph " << name <<
" {\n";
1226 os <<
"// printer friendly options, fill A4 landscape:\n" 1227 " size=\"10.2,7.8\"; ratio=fill; margin=0.2;\n" 1228 " nodesep=0.3; // separation of labelled edges\n\n" 1231 "// neato options:\n" 1232 " epsilon=0.0001;\n\n" 1233 " node[fontname=\"Helvetica-Bold\"];\n" 1234 " edge[fontname=\"Helvetica\",fontsize=10];\n\n" 1236 "// process[shape=ellipse]; int[shape=rectangle]; chan[shape=diamond];\n\n";
1238 procs_t::const_iterator p, pe;
1241 ostream_iterator<const char*> osi(os,
"; ");
1243 if (!procsBad.empty()) {
1244 os <<
"// processes in conflict:\n" 1245 " node [shape=ellipse,peripheries=1," BADSTYLE "];\n ";
1246 for (p = procsBad.begin(), pe = procsBad.end(); p!=pe; ++p) {
1247 os << (*p)->name <<
"; ";
1248 procsR.erase((*p)->name);
1252 if (!chansBad.empty()) {
1253 os <<
"// channels in conflict:\n" 1254 " node [shape=diamond,peripheries=1," BADSTYLE "];\n ";
1255 for_each(chansBad.begin(), chansBad.end(),
1256 surround(os,
"\"",
"\"; "));
1261 if (!varsBad.empty()) {
1262 os <<
"// variables in conflict:\n" 1263 " node [shape=diamond,peripheries=1," BADSTYLE "];\n ";
1264 copy(varsBad.begin(), varsBad.end(), osi);
1269 if (!procsIUT.empty()) {
1270 os <<
"// IUT processes:\n";
1271 os <<
" node [shape=ellipse,peripheries=1," IUTSTYLE "];\n ";
1272 for (p = procsIUT.begin(), pe = procsIUT.end(); p!=pe; ++p) {
1273 os << (*p)->name <<
"; ";
1274 procsR.erase((*p)->name);
1278 if (!chansIntIUT.empty()) {
1279 os <<
"// IUT channels:\n";
1280 os <<
" node [shape=diamond,peripheries=1," IUTSTYLE "];\n ";
1281 for_each(chansIntIUT.begin(), chansIntIUT.end(),
1282 surround(os,
"\"",
"\"; "));
1287 if (!varsIUT.empty()) {
1288 os <<
"// IUT variables:\n";
1289 os <<
" node [shape=rectangle,peripheries=1," IUTSTYLE "];\n ";
1290 copy(varsIUT.begin(), varsIUT.end(), osi);
1295 if (!chansOut.empty()) {
1296 os <<
"// observable output channels (controlled by IUT):\n" 1297 " node [shape=diamond,peripheries=2," IUTSTYLE "];\n ";
1298 for_each(chansOut.begin(), chansOut.end(),
1299 surround(os,
"\"",
"\"; "));
1304 if (!chansInp.empty()) {
1305 os <<
"// observable input channels (controlled by Env):\n" 1306 " node [shape=diamond,peripheries=2," ENVSTYLE "];\n ";
1307 for_each(chansInp.begin(), chansInp.end(),
1308 surround(os,
"\"",
"\"; "));
1314 if (!procsEnv.empty()) {
1315 os <<
"// Env processes:\n";
1316 os <<
" node [shape=ellipse,peripheries=1," ENVSTYLE "];\n ";
1317 for (p = procsEnv.begin(), pe = procsEnv.end(); p!=pe; ++p) {
1318 os << (*p)->name <<
"; ";
1319 procsR.erase((*p)->name);
1323 if (!chansIntEnv.empty()) {
1324 os <<
"// Env channels:\n";
1325 os <<
" node [shape=diamond,peripheries=1," ENVSTYLE "];\n ";
1326 for_each(chansIntEnv.begin(), chansIntEnv.end(),
1327 surround(os,
"\"",
"\"; "));
1332 if (!varsEnv.empty()) {
1333 os <<
"// Env variables:\n";
1334 os <<
" node [shape=rectangle,peripheries=1," ENVSTYLE "];\n ";
1335 copy(varsEnv.begin(), varsEnv.end(), osi);
1339 os <<
"// set attributes for non-partitioned procs/chans/vars:\n";
1340 if (!procsR.empty()) {
1341 os <<
" node [shape=ellipse,peripheries=1," MEDSTYLE "];\n";
1342 copy(procsR.begin(), procsR.end(), osi);
1345 if (!chansR.empty()) {
1346 os <<
" node [shape=diamond,peripheries=1," MEDSTYLE "];\n";
1347 for_each(chansR.begin(), chansR.end(),
1348 surround(os,
"\"",
"\"; "));
1352 if (!varsR.empty()) {
1353 os <<
" node [shape=rectangle,peripheries=1," MEDSTYLE "];\n";
1354 copy(varsR.begin(), varsR.end(), osi);
1360 str2strs_t::const_iterator v2c;
1361 os <<
"// edges for write to variable:\n" 1362 <<
" edge [style=bold];\n";
1363 for (p =
procs.begin(), pe =
procs.end(); p!=pe; ++p) {
1364 if (!(*p)->wtVars.empty()) {
1365 for (v2c = (*p)->wtVars.begin(); v2c != (*p)->wtVars.end(); ++v2c){
1366 os<<
" "<<(*p)->name<<
" -> " << v2c->first <<
" [label=\"(";
1368 for_each(v2c->second.begin(), v2c->second.end(),
1374 os <<
"// edges for read of variable:\n" 1375 <<
" edge [style=solid];\n";
1376 for (p =
procs.begin(), pe =
procs.end(); p!=pe; ++p) {
1377 if (!(*p)->rdVars.empty()) {
1378 for (v2c = (*p)->rdVars.begin(); v2c != (*p)->rdVars.end(); ++v2c){
1379 os<<
" " << v2c->first <<
" -> " <<(*p)->name<<
" [label=\"(";
1381 for_each(v2c->second.begin(), v2c->second.end(),
1394 os <<
"// channel transmit edges:\n" 1395 <<
" edge [style=bold];\n";
1396 for (p =
procs.begin(), pe =
procs.end(); p!=pe; ++p) {
1397 for (strs_t::const_iterator c=(*p)->outChans.begin(),
1398 ce=(*p)->outChans.end(); c!=ce; ++c)
1400 os <<
" " << (*p)->name <<
" -> \"" << *c <<
"\";\n";
1403 os <<
"// channel receive edges:\n" 1404 <<
" edge [style=solid];\n";
1405 for (p =
procs.begin(), pe =
procs.end(); p!=pe; ++p) {
1406 for (strs_t::const_iterator c=(*p)->inChans.begin(),
1407 ce=(*p)->inChans.end(); c!=ce; ++c)
1409 os <<
" \"" << *c <<
"\" -> " << (*p)->name <<
";\n";
1413 const char* src =
"NO_SRC";
1414 const char* dst =
"NO_DST";
1416 for (p =
procs.begin(), pe =
procs.end(); p!=pe; ++p)
1419 for (strs_t::const_iterator c=(*p)->outChans.begin(),
1420 ce=(*p)->outChans.end(); c!=ce; ++c)
1422 str2procs_t::const_iterator dests =
receivers.find(*c);
1425 for (procs_t::const_iterator rec =
1426 dests->second.begin();
1427 rec != dests->second.end(); ++rec)
1429 (*p)->outEdges[*rec].insert(*c);
1434 (*p)->outEdges[NULL].insert(*c);
1440 os<<
" edge[style=solid];\n";
1441 for (p =
procs.begin(), pe =
procs.end(); p!=pe; ++p)
1444 for (proc2strs_t::const_iterator edge = (*p)->outEdges.begin();
1445 edge != (*p)->outEdges.end(); ++edge)
1448 if (edge->first != NULL)
1451 os<<
" " <<(*p)->name <<
" -> " << edge->first->name
1459 <<
" [style=filled,fillcolor=red];\n";
1462 os<<
" " <<(*p)->name <<
" -> " << dst
1466 strs_t::const_iterator
ch=edge->second.begin();
1469 os<<
"\"" << *ch <<
"\"";
1471 if (ch != edge->second.end())
1485 for (strs_t::const_iterator c=(*p)->inChans.begin(),
1486 ce=(*p)->inChans.end(); c!=ce; ++c)
1488 str2procs_t::const_iterator trans =
transmitters.find(*c);
1494 <<
" [style=filled,fillcolor=red];\n";
1497 os<<
" "<<src<<
" -> " << (*p)->name <<
" [label=\"" 1509 for (procs_t::const_iterator p=procsEnv.begin(); p!=procsEnv.end(); ++p)
1510 procs.insert((*p)->name);
1515 for (procs_t::const_iterator p=procsIUT.begin(); p!=procsIUT.end(); ++p)
1516 procs.insert((*p)->name);
1523 distancesUpToDate =
false;
1524 const char* dot = strchr(var,
'.');
1525 size_t length = dot == NULL ? strlen(var) : dot - var;
1526 char* name = strncpy(
new char[length+1], var, length);
1527 name[length] =
'\0';
1530 cerr <<
"Variable not found: " << var << endl;
1534 dist_t* distance = NULL;
1535 str2dist_t::iterator i = distances.find(name);
1536 if (i==distances.end()) {
1537 varNeedles.insert(name);
1538 distances[name] = dist_t(0, 1, 0);
1541 distance = &(i->second);
1542 if (distance->hops==0 && distance->distance==0) {
1544 distance->complexity = 2 * distance->complexity;
1547 distance->distance = 0;
1555 distancesUpToDate =
false;
1556 const char* dot = strchr(proc,
'.');
1557 size_t length = dot == NULL ? strlen(proc) : dot - proc;
1558 char* name = strncpy(
new char[length+1], proc, length);
1559 name[length] =
'\0';
1562 cerr <<
"AddNeedle: Process not found: " << proc << endl;
1567 dist_t* distance = NULL;
1568 str2dist_t::iterator i = distances.find(name);
1569 if (i==distances.end()) {
1570 procNeedles.insert(name);
1571 distances[name] = dist_t(0, calcComplexity(name), 0);
1574 distance = &(i->second);
1575 if (distance->hops==0 && distance->distance==0) {
1577 distance->complexity = 2 * distance->complexity;
1580 distance->distance = 0;
1586 void DistanceCalculator::updateDistancesFromVariable(
const char* name,
1590 str2procs_t::const_iterator t =
transmitters.find(name);
1592 for (procs_t::const_iterator p=t->second.begin(),e=t->second.end();
1595 dist_t* distance = NULL;
1596 str2dist_t::iterator i = distances.find((*p)->name);
1597 if (i==distances.end()) {
1598 procNeedles.insert(strcpy(
new char[strlen((*p)->name)+1],
1600 distances[(*p)->name] = dist_t(d->hops+1,
1601 calcComplexity((*p)->name),
1602 d->distance + d->complexity);
1603 distance = &distances[(*p)->name];
1605 distance = &(i->second);
1606 if (distance->distance <= d->distance + d->complexity)
1609 distance->hops = d->hops+1;
1610 distance->distance = d->distance + d->complexity;
1613 updateDistancesFromProcess((*p)->name, distance);
1617 void DistanceCalculator::updateDistancesFromProcess(
const char* name,
1621 procs_t::const_iterator s =
procs.begin();
1622 while (s !=
procs.end())
1623 if (strcmp((*s)->name, name)==0)
break;
1625 if (s ==
procs.end()) {
1626 cerr <<
"UpdateDistancesFromProcess: Process not found: "<<name<<endl;
1630 for (strs_t::const_iterator c=(*s)->inChans.begin(),ce=(*s)->inChans.end();
1636 for (procs_t::const_iterator p=t->second.begin(),e=t->second.end();
1639 dist_t* distance = NULL;
1640 str2dist_t::iterator i = distances.find((*p)->name);
1641 if (i==distances.end()) {
1642 procNeedles.insert(strcpy(
new char[strlen((*p)->name)+1],
1644 distances[(*p)->name] = dist_t(d->hops+1,
1645 calcComplexity((*p)->name),
1646 d->distance + d->complexity);
1647 distance = &distances[(*p)->name];
1649 distance = &(i->second);
1650 if (distance->distance <= d->distance + d->complexity)
1653 distance->hops = d->hops+1;
1654 distance->distance = d->distance + d->complexity;
1657 updateDistancesFromProcess((*p)->name, distance);
1661 for (str2strs_t::const_iterator v=(*s)->rdVars.begin(),
1662 ve=(*s)->rdVars.end(); v!=ve; ++v)
1664 dist_t* distance = NULL;
1665 str2dist_t::iterator i = distances.find(v->first);
1666 if (i==distances.end()) {
1667 varNeedles.insert(strcpy(
new char[strlen(v->first)+1], v->first));
1668 distances[v->first] = dist_t(d->hops+1, 1,
1669 d->distance + d->complexity);
1670 distance = &distances[v->first];
1672 distance = &(i->second);
1673 if (distance->distance <= d->distance + d->complexity)
1676 distance->hops = d->hops+1;
1677 distance->distance = d->distance + d->complexity;
1680 updateDistancesFromVariable(v->first, distance);
1684 int DistanceCalculator::calcComplexity(
const char* process)
1687 list<instance_t> &ps(taSystem.getProcesses());
1688 for (list<instance_t>::iterator i=ps.begin(), e=ps.end(); i!=e; ++i)
1690 if (i->uid.getName()==process) {
1692 deque<edge_t>::const_iterator t = i->
templ->
edges.begin();
1693 while (t != temp->
edges.end()) { result++; t++; }
1702 os <<
" subgraph procs {\n";
1705 os<<
" node [shape=rectangle,style=filled];\n";
1709 os<<
" node [shape=ellipse,style=filled];\n";
1713 for (procs_t::const_iterator p=
procs.begin(), e=
procs.end(); p!=e; ++p)
1715 str2dist_t::const_iterator d = distances.find((*p)->name);
1716 if (d==distances.end()) {
1717 os << (*p)->name <<
"[label=\"\\N\\n(( ?, ?))\"]; ";
1719 os << (*p)->name <<
"[label=\"\\N\\n((" << d->second.hops
1720 <<
", "<< d->second.distance <<
"))\"]; ";
1731 os <<
" subgraph cluste_vars {\n";
1732 os <<
" style=invis;\n";
1735 os <<
" rank=min;\n";
1739 os <<
" node [shape=diamond,color=blue];\n ";
1743 os <<
" node [shape=rectangle,color=blue];\n ";
1748 str2dist_t::const_iterator d = distances.find(*i);
1749 if (d==distances.end()) {
1750 os << *i <<
"[label=\"\\N\\n(( ?, ?))\"";
1752 os << *i <<
"[label=\"\\N\\n((" << d->second.hops
1753 <<
", "<< d->second.distance <<
"))\"";
1756 else os <<
",style=bold]; ";
1763 for(strs_t::iterator i=varNeedles.begin(),e=varNeedles.end(); i!=e; ++i)
1767 for(strs_t::iterator i=procNeedles.begin(),e=procNeedles.end(); i!=e; ++i)
1769 procNeedles.clear();
1774 if (!distancesUpToDate) updateDistances();
1776 str2dist_t::iterator f = distances.find(element);
1777 if (f == distances.end()) {
1781 return f->second.distance;
1787 if (!distancesUpToDate) updateDistances();
1795 for (str2dist_t::iterator i=distances.begin(), e=distances.end();
1798 if (i->second.hops>0) {
1799 i->second.hops = INT_MAX;
1800 i->second.distance = INT_MAX;
1804 for(strs_t::iterator i=varNeedles.begin(),e=varNeedles.end();
1807 str2dist_t::iterator f = distances.find(*i);
1808 if (f == distances.end()) {
1809 cerr <<
"Variable not found: " << *i << endl;
1812 updateDistancesFromVariable(*i, &(f->second));
1815 for(strs_t::iterator i=procNeedles.begin(),e=procNeedles.end();
1818 str2dist_t::iterator f = distances.find(*i);
1819 if (f == distances.end()) {
1820 cerr <<
"Process not found: " << *i << endl;
1823 updateDistancesFromProcess(*i, &(f->second));
1825 distancesUpToDate =
true;
virtual void printChansOnEdgesForDot(std::ostream &os)
Class SignalFlow is for analysing UPPAAL specifications and extracting the timed automata input/outpu...
Constants::kind_t getKind() const
Returns the kind of the expression.
Partial instance of a template.
int32_t visitWhileStatement(WhileStatement *stat) override
static ParserBuilder * ch
struct template_t * templ
int32_t visitBreakStatement(BreakStatement *stat) override
void addProcsByVars(const strs_t &vars, procs_t &procs, procs_t &exclude)
Take all variables and add all accessing processes to the list.
void printForDot(std::ostream &os, bool ranked, bool erd, bool cEdged) override
Print I/O information in DOT format into given output stream.
void visitExpression(const expression_t &)
void printProcsForDot(std::ostream &os, bool erd) override
bool empty() const
Returns true if this is an empty expression.
bool hasParent() const
Returns true if this frame has a parent.
DistanceCalculator is used in TargetFirst heuristic search order of Uppaal.
int32_t visitCaseStatement(CaseStatement *stat) override
std::deque< state_t > states
Locations.
const_iterator end() const
void addIntVars(const procs_t &procs, strs_t &result, strs_t &exclude)
Takes the variables of each process from procs list and adds them to the result list.
virtual void printVarsReadForDot(std::ostream &os)
virtual void printForDot(std::ostream &os, bool ranked, bool erd, bool cEdged)
Print I/O information in DOT format into given output stream.
virtual ~SignalFlow()
All strings are from TASystem (don't dispose TASystem before SignalFlow).
int32_t visitIfStatement(IfStatement *stat) override
std::string getName() const
Returns the name (identifier) of this symbol.
symbol_t getSymbol()
Returns the symbol of a variable reference.
void fillWithIUTProcs(strs_t &procs)
void visitProcess(instance_t &)
std::vector< Statement * >::iterator iterator
static const char * noChan
int32_t visitContinueStatement(ContinueStatement *stat) override
frame_t parameters
The parameters.
Statement class for the iterator loop-construction.
void addChan(const std::string &, strs_t &, str2procs_t &)
int32_t visitDefaultStatement(DefaultStatement *stat) override
int32_t visitEmptyStatement(EmptyStatement *stat) override
System visitor pattern extracts read/write information from UCode.
void printVarsForDot(std::ostream &os, bool ranked, bool erd) override
virtual void printProcsForDot(std::ostream &os, bool erd)
std::set< proc_t * > procs_t
int32_t visitBlockStatement(BlockStatement *stat) override
std::list< instance_t > & getProcesses()
Returns the processes of the system.
Partitions the system into environment and IUT according to TRON assumptions.
std::map< const char *, strs_t > str2strs_t
void set_remove(SignalFlow::strs_t &from, const SignalFlow::strs_t &what)
void addProcessNeedle(const char *proc)
adds a variable needle to I/O map
int partition(const strs_t &inputs, const strs_t &outputs)
void updateDistances()
Recalculates the distances to needles.
std::deque< edge_t > edges
Edges.
std::set< const char *, const less_str > strs_t
virtual void printChansSeparateForDot(std::ostream &os, bool ranked, bool erd)
std::stack< exprref_t > valparams
std::stack< exprref_t > refparams
virtual void printVarsForDot(std::ostream &os, bool ranked, bool erd)
int32_t visitIterationStatement(IterationStatement *stat) override
uint32_t getDistance(const char *element)
Finds a distance measure for given element.
print – template for pretty printing lists.
bool checkParams(const symbol_t &s)
void fillWithEnvProcs(strs_t &procs)
int32_t visitReturnStatement(ReturnStatement *stat) override
std::map< const symbol_t, expression_t > exprref_t
const_iterator begin() const
void addVariableNeedle(const char *var)
adds a variable needle to I/O map
SignalFlow(const char *_title, TimedAutomataSystem &ta)
Analyse the system and extract I/O information:
virtual ~DistanceCalculator()
int32_t accept(StatementVisitor *visitor) override
char * get_token(istream &in)
void printForDot(std::ostream &os, bool ranked, bool erd, bool cEdged) override
Print I/O information in DOT format into given output stream.
std::map< symbol_t, expression_t > mapping
The arguments.
type_t getType() const
Returns the type of this symbol.
void addVar(const symbol_t &, str2strs_t &, str2procs_t &)
void printForTron(std::ostream &os)
Print I/O information in TRON format into given output stream.
int32_t visitSwitchStatement(SwitchStatement *stat) override
A reference to an expression.
Information about a function.
int32_t visitForStatement(ForStatement *stat) override
type_t getType() const
Returns the type of the expression.
void * getData()
Returns the user data of this symbol.
void addProcs(const strs_t &chans, const str2procs_t &index, procs_t &result, procs_t &exclude)
Adds processes to the result which use the channels from chans list according to index.
virtual int32_t accept(StatementVisitor *visitor)=0
int32_t getValue() const
Returns the value field of this expression.
size_t getSize() const
Returns the number of subexpression.
bool is(Constants::kind_t kind) const
Returns true if the type has kind kind or if type is a prefix, RANGE or REF type and the getChild()...
void printViolation(const proc_t *process, const char *variable)
std::map< const char *, procs_t, less_str > str2procs_t
frame_t getFrame()
Get frame this symbol belongs to.
int32_t visitExprStatement(ExprStatement *stat) override
Constants::synchronisation_t getSync() const
Returns the synchronisation type of SYNC operations.
void addIntChans(const procs_t &procs, strs_t &result, strs_t &exclude)
Takes the internal channels of each process from procs list and adds them to the result list...
int32_t visitDoWhileStatement(DoWhileStatement *stat) override
int32_t getIndexOf(const std::string &name) const
Returns the index of the symbol with the given name.
Constants::kind_t getKind() const
Returns the kind of type object.
virtual void printVarsWriteForDot(std::ostream &os)
int32_t visitAssertStatement(UTAP::AssertStatement *stat) override