23 {
"red",
"blue",
"black",
"green",
"yellow",
24 "orange",
"blueviolet",
"cyan",
"cadetblue",
"magenta",
"palegreen",
25 "deeppink",
"indigo",
"olivedrab"};
26 #define print_colour(u) colour_map[u%NB_COLOURS]
29 std::set<event_idt> &visited)
32 file << node_id <<
"[label=\"" << node <<
", " << node.
source_location <<
34 visited.insert(node_id);
36 for(wmm_grapht::edgest::const_iterator
37 it=
po_out(node_id).begin();
38 it!=
po_out(node_id).end(); ++it)
40 file << node_id <<
"->" << it->first <<
"[]\n";
41 file <<
"{rank=same; " << node_id <<
"; " << it->first <<
"}\n";
42 if(visited.find(it->first)==visited.end())
46 for(wmm_grapht::edgest::const_iterator
48 it!=
com_out(node_id).end(); ++it)
50 file << node_id <<
"->" << it->first <<
"[style=\"dotted\"]\n";
51 if(visited.find(it->first)==visited.end())
59 std::set<event_idt> visited;
62 file.open(
"graph.dot");
63 file <<
"digraph G {\n";
64 file <<
"rankdir=LR;\n";
77 if(explored.find(begin)!=explored.end())
80 explored.insert(begin);
85 for(wmm_grapht::edgest::const_iterator it=
po_out(begin).begin();
112 std::set<event_idt> covered;
124 std::map<event_idt, event_idt> orig2copy;
127 for(std::set<event_idt>::const_iterator it=covered.begin();
133 orig2copy[*it]=new_node;
141 for(std::set<event_idt>::const_iterator it_i=covered.begin();
145 for(std::set<event_idt>::const_iterator it_j=covered.begin();
163 for(std::set<event_idt>::const_iterator it_i=covered.begin();
184 return orig2copy[end];
195 for(; AC_it!=
end(); ++AC_it)
212 for(AC_it=
begin(); ; ++AC_it)
246 for(; BC_it!=begin(); --BC_it)
261 if(BC_it==begin() && egraph[back()].thread==first.
thread)
284 bool unsafe_met=
false;
291 unsigned thread=egraph[*begin()].thread;
294 th_it!=end() && thread==egraph[*th_it].thread; ++th_it)
295 thread=egraph[*th_it].thread;
303 for(; it!=end() && next!=end(); ++next, ++it)
351 if(check_AC(s_it, first, second))
354 if(check_BC(it, first, second))
364 && (first.
thread!=second.
thread || egraph.are_po_ordered(*it, *s_it)))
378 after_second=begin();
384 && egraph[*before_first].thread!=first.
thread
385 && egraph[*after_second].thread!=second.
thread)
396 unsafe_pairs.insert(delay);
406 && (first.
thread!=second.
thread || egraph.are_po_ordered(*it, *s_it)))
420 after_second=begin();
426 && egraph[*before_first].thread!=first.
thread
427 && egraph[*after_second].thread!=second.
thread)
438 unsafe_pairs.insert(delay);
483 if(check_AC(s_it, first, second))
486 if(check_BC(begin(), first, second))
494 && (first.
thread!=second.
thread || egraph.are_po_ordered(back(), *s_it)))
496 std::list<event_idt>::const_iterator before_first;
497 std::list<event_idt>::const_iterator after_second;
508 && egraph[*before_first].thread!=first.
thread
509 && egraph[*after_second].thread!=second.
thread)
518 unsafe_pairs.insert(delay);
528 && (first.
thread!=second.
thread || egraph.are_po_ordered(back(), *s_it)))
530 std::list<event_idt>::const_iterator before_first;
531 std::list<event_idt>::const_iterator after_second;
542 && egraph[*before_first].thread!=first.
thread
543 && egraph[*after_second].thread!=second.
thread)
552 unsafe_pairs.insert(delay);
568 bool unsafe_met=
false;
569 unsigned char fences_met=0;
576 unsigned thread=egraph[*begin()].thread;
579 th_it!=end() && thread==egraph[*th_it].thread; ++th_it)
580 thread=egraph[*th_it].thread;
610 fences_met |= egraph[*s_it].fence_value();
641 AC_it!=end() && egraph[*AC_it].thread==second.
thread;
644 && egraph[*AC_it].is_cumul()
645 && egraph[*AC_it].is_corresponding_fence(egraph[*it], egraph[*s_it]))
654 if(AC_it==end() && egraph[front()].thread==second.
thread)
657 !(egraph[*AC_it]==first) && egraph[*AC_it].thread==second.
thread;
660 egraph[*AC_it].is_cumul() &&
661 egraph[*AC_it].is_corresponding_fence(egraph[*it], egraph[*s_it]))
684 BC_it!=begin() && egraph[*BC_it].thread==first.
thread;
688 egraph[*BC_it].is_cumul() &&
689 egraph[*BC_it].is_corresponding_fence(egraph[*it], egraph[*s_it]))
699 if(BC_it==begin() && egraph[back()].thread==first.
thread)
702 !(egraph[*BC_it]==second) && egraph[*BC_it].thread==first.
thread;
705 egraph[*BC_it].is_cumul() &&
706 egraph[*BC_it].is_corresponding_fence(egraph[*it], egraph[*s_it]))
723 && (first.
thread!=second.
thread || egraph.are_po_ordered(*it, *s_it)))
730 unsafe_pairs.insert(delay);
741 && (first.
thread!=second.
thread || egraph.are_po_ordered(*it, *s_it)))
748 unsafe_pairs.insert(delay);
768 fences_met |= egraph[*s_it].fence_value();
796 AC_it!=end() && egraph[*AC_it].thread==second.
thread;
799 && egraph[*AC_it].is_cumul()
800 && egraph[*AC_it].is_corresponding_fence(first, second))
809 if(AC_it==end() && egraph[front()].thread==second.
thread)
812 !(egraph[*AC_it]==first) && egraph[*AC_it].thread==second.
thread;
815 egraph[*AC_it].is_cumul() &&
816 egraph[*AC_it].is_corresponding_fence(first, second))
831 BC_it!=begin() && egraph[*BC_it].thread==first.
thread;
834 && egraph[*BC_it].is_cumul()
835 && egraph[*BC_it].is_corresponding_fence(first, second))
844 if(BC_it==begin() && egraph[back()].thread==first.
thread)
849 !(egraph[*BC_it]==second) && egraph[*BC_it].thread==first.
thread;
852 && egraph[*BC_it].is_cumul()
853 && egraph[*BC_it].is_corresponding_fence(first, second))
868 && (first.
thread!=second.
thread || egraph.are_po_ordered(back(), *s_it)))
873 unsafe_pairs.insert(delay);
882 && (first.
thread!=second.
thread || egraph.are_po_ordered(back(), *s_it)))
887 unsafe_pairs.insert(delay);
901 for(; it!=end(); ++it)
914 const irep_idt &var=egraph[*it].variable;
918 if(!egraph.ignore_arrays &&
id2string(var).find(
"[]")!=std::string::npos)
921 for(; it!=end(); ++it)
939 for(; it!=end(); it++)
952 const irep_idt &var=egraph[*it].variable;
955 for(; it!=end(); prev=it, ++it)
996 if(dep.
dp(current, next))
1013 if(dep.
dp(current, next))
1021 std::string cycle=
"Cycle: ";
1024 return cycle +
" End of cycle.";
1029 std::string name=
"Unsafe pairs: ";
1030 for(std::set<delayt>::const_iterator it=unsafe_pairs.begin();
1031 it!=unsafe_pairs.end();
1076 std::string cycle=
"Cycle: ";
1083 return cycle+
" End of cycle.";
1101 std::map<std::string, std::string> &map_id2var,
1102 std::map<std::string, std::string> &map_var2id)
const
1110 if(map_var2id.find(var_name)!=map_var2id.end())
1113 cycle += map_var2id[var_name] +
") ";
1117 const std::string new_id=
"var@" +
std::to_string(map_var2id.size());
1118 map_var2id[var_name]=new_id;
1119 map_id2var[new_id]=var_name;
1121 cycle += new_id +
") ";
1129 std::map<std::string, std::string> &map_id2var,
1130 std::map<std::string, std::string> &map_var2id,
1131 bool hide_internals)
const
1141 this->hide_internals(reduced);
1143 cycle+=print_detail(reduced, map_id2var, map_var2id);
1145 cycle+=print_name(reduced, model);
1149 cycle+=print_detail(*
this, map_id2var, map_var2id);
1151 cycle+=print_name(*
this, model);
1160 std::set<event_idt> reduced_evts;
1164 for(first_it=begin(); first_it!=end(); ++first_it)
1167 if(prev_it!=end() && egraph[*prev_it].thread!=first.
thread
1174 reduced_evts.insert(*first_it);
1188 if(cur.
thread!=egraph[*next_it].thread)
1190 if(reduced_evts.find(*cur_it)==reduced_evts.end())
1193 reduced_evts.insert(*cur_it);
1195 for(; next_it!=end() && egraph[*next_it].is_fence(); ++next_it) {}
1197 if(reduced_evts.find(*next_it)==reduced_evts.end())
1200 reduced_evts.insert(*next_it);
1215 if(cur.
thread!=egraph[*next_it].thread)
1217 if(reduced_evts.find(*cur_it)==reduced_evts.end())
1220 reduced_evts.insert(*cur_it);
1222 for(; next_it!=end() && egraph[*next_it].is_fence(); ++next_it) {}
1224 if(reduced_evts.find(*next_it)==reduced_evts.end())
1227 reduced_evts.insert(*next_it);
1238 unsigned extra_fence_count=0;
1242 bool first_done=
false;
1247 if(prev_it!=reduced.
end())
1255 ++extra_fence_count;
1262 bool wraparound=
false;
1266 if(n_it==reduced.
end())
1268 INVARIANT(!wraparound,
"no prior wraparound");
1271 ++extra_fence_count;
1272 n_it=reduced.
begin();
1282 ++extra_fence_count;
1288 "operation is read or write");
1289 name += (model==
Power?
" Sync":
" MFence");
1296 std::string cand_name=
" LwSync";
1298 bool wraparound=
false;
1302 if(n_it==reduced.
end())
1304 INVARIANT(!wraparound,
"no prior wraparound");
1307 ++extra_fence_count;
1308 n_it=reduced.
begin();
1318 cand_name=(model==
Power?
" Sync":
" MFence");
1322 ++extra_fence_count;
1328 "operation is read or write");
1336 std::string cand_name;
1338 cand_name=(model==
Power?
" Sync":
" MFence");
1340 cand_name=
" LwSync";
1342 bool wraparound=
false;
1346 if(n_it==reduced.
end())
1348 INVARIANT(!wraparound,
"no prior wraparound");
1351 ++extra_fence_count;
1352 n_it=reduced.
begin();
1362 cand_name=(model==
Power?
" Sync":
" MFence");
1366 ++extra_fence_count;
1372 "operation is read or write");
1436 auto n_events=extra_fence_count;
1437 for(std::string::const_iterator it=name.begin();
1454 "operation is not a fence");
1460 std::string cand_name=
" LwSync";
1462 for( ; it!=reduced.
end(); ++it)
1473 cand_name=(model==
Power?
" Sync":
" MFence");
1480 "operation is read or write");
1518 dep.
dp(last, first))
1537 for(std::string::const_iterator it=name.begin();
1542 assert(n_events==reduced.
size());
1559 str <<
"/* " <<
id <<
" */\n";
1563 str <<
"{" << ev.
variable <<
"} {} @thread" << ev.
thread <<
"\"];\n";
1573 str <<
"/* " <<
id <<
" */\n";
1580 str << prev.
id <<
"->";
1586 n_it!=end() ? egraph[*n_it] : egraph[front()];
1587 str << succ.
id <<
"[label=\"";
1588 str << (model==
Power?
"Sync":
"MFence");
1597 n_it!=end() ? egraph[*n_it] : egraph[front()];
1598 str << succ.
id <<
"[label=\"";
1606 str << cur.
id <<
"[label=\"";
1613 str << cur.
id <<
"[label=\"";
1622 str << cur.
id <<
"[label=\"";
1628 str << cur.
id <<
"[label=\"";
1633 str << cur.
id <<
"[label=\"?";
1645 str <<
"/* " <<
id <<
" */\n";
1648 str << last.
id <<
"->";
1654 str << succ.
id <<
"[label=\"";
1655 str << (model==
Power?
"Sync":
"MFence");
1664 str << succ.
id <<
"[label=\"";
1672 str << first.
id <<
"[label=\"";
1679 str << first.
id <<
"[label=\"";
1688 str << first.
id <<
"[label=\"";
1694 str << first.
id <<
"[label=\"";
1699 str << first.
id <<
"[label=\"?";
bool unsafe_pair(const abstract_eventt &next, memory_modelt model) const
std::string get_operation() const
bool unsafe_pair_lwfence(const abstract_eventt &next, memory_modelt model) const
source_locationt source_location
bool unsafe_pair_asm(const abstract_eventt &next, memory_modelt model, unsigned char met) const
unsigned char fence_value() const
bool dp(const abstract_eventt &e1, const abstract_eventt &e2) const
search in N^2
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
std::string print_events() const
void hide_internals(critical_cyclet &reduced) const
data_typet::const_iterator const_iterator
std::string print_unsafes() const
bool is_unsafe(memory_modelt model, bool fast=false)
checks whether there is at least one pair which is unsafe (takes fences and dependencies into account...
bool is_unsafe_asm(memory_modelt model, bool fast=false)
same as is_unsafe, but with ASM fences
bool check_AC(data_typet::const_iterator s_it, const abstract_eventt &first, const abstract_eventt &second) const
bool is_not_uniproc() const
bool is_not_weak_uniproc() const
std::string print_name(const critical_cyclet &redyced, memory_modelt model) const
std::string print_all(memory_modelt model, std::map< std::string, std::string > &map_id2var, std::map< std::string, std::string > &map_var2id, bool hide_internals) const
bool check_BC(data_typet::const_iterator it, const abstract_eventt &first, const abstract_eventt &second) const
void print_dot(std::ostream &str, unsigned colour, memory_modelt model) const
std::string print_detail(const critical_cyclet &reduced, std::map< std::string, std::string > &map_id2var, std::map< std::string, std::string > &map_var2id) const
bool is_not_thin_air() const
std::string print_output() const
std::string print() const
grapht< abstract_eventt >::nodet & operator[](event_idt n)
bool has_com_edge(event_idt i, event_idt j) const
std::list< event_idt > po_order
void explore_copy_segment(std::set< event_idt > &explored, event_idt begin, event_idt end) const
copies the segment
event_idt copy_segment(event_idt begin, event_idt end)
bool has_po_edge(event_idt i, event_idt j) const
const wmm_grapht::edgest & com_out(event_idt n) const
const wmm_grapht::edgest & po_out(event_idt n) const
std::set< std::pair< const abstract_eventt &, const abstract_eventt & > > duplicated_bodies
void add_com_edge(event_idt a, event_idt b)
void add_po_edge(event_idt a, event_idt b)
void print_rec_graph(std::ofstream &file, event_idt node_id, std::set< event_idt > &visited)
mstreamt & status() const
const irep_idt & get_file() const
std::string as_string() const
static const char * colour_map[14]
wmm_grapht::node_indext event_idt
const std::string & id2string(const irep_idt &d)
#define CHECK_RETURN(CONDITION)
#define UNREACHABLE
This should be used to mark dead code.
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
#define PRECONDITION(CONDITION)
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.