1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606
|
(****************************************************************************)
(* the diy toolsuite *)
(* *)
(* Jade Alglave, University College London, UK. *)
(* Luc Maranget, INRIA Paris-Rocquencourt, France. *)
(* *)
(* Copyright 2010-present Institut National de Recherche en Informatique et *)
(* en Automatique and the authors. All rights reserved. *)
(* *)
(* This software is governed by the CeCILL-B license under French law and *)
(* abiding by the rules of distribution of free software. You can use, *)
(* modify and/ or redistribute the software under the terms of the CeCILL-B *)
(* license as circulated by CEA, CNRS and INRIA at the following URL *)
(* "http://www.cecill.info". We also give a copy in LICENSE.txt. *)
(****************************************************************************)
(** Producing .dot output *)
open Test_herd
open Printf
module type S = sig
module S : SemExtra.S
open S
val init_pretty : unit -> unit
val pp_no_solutions : out_channel -> S.test -> string -> unit
(* Standard dump (to dot file)
just_dump chan test es rfm rels vos.
- chan is output channel
- es is event_structure (includes intra_causality and atomicity)
- legend is a legend.
- rels is a list of (tags,relation) to be pictured
tag will label the edges
*)
val dump_legend :
out_channel ->S.test -> string ->
S.concrete -> ?sets : S.set_pp -> S.rel_pp -> unit
(* Simpler function, just to dump event structures with and without rfmaps *)
val dump_es :
out_channel -> test -> event_structure -> unit
val dump_es_rfm :
out_channel -> test -> event_structure -> rfmap -> unit
(************************************)
(* Show feature: pop up a gv window *)
(************************************)
val show_es_rfm : test -> event_structure -> rfmap -> unit
val show_legend :
S.test -> string -> S.concrete ->
?sets : S.set_pp -> S.rel_pp -> unit
end
module Make (S:SemExtra.S) : S with module S = S = struct
module S = S
module A = S.A
module E = S.E
module PC = S.O.PC
let dbg = false
let pc_symetric = StringSet.union PC.symetric PC.noid
(* One init *)
let one_init = match PC.graph with
| Graph.Columns -> PC.oneinit
| Graph.Free|Graph.Cluster -> false
(* Attempt *)
let _reduces_more r1 r2 =
let open E.EventRel in
filter
(fun (e1,_e2) ->
not
(E.EventSet.is_empty (succs r2 e1)) &&
not
(E.EventSet.is_empty (preds r2 e1)))
r1
open PrettyConf
open PPMode
let show_all_events = match PC.showevents with
| AllEvents -> true
| MemEvents|NonRegEvents|MemFenceEvents -> false
(* Printing the program with the nice_prog field *)
(* Please avoid insterting references to Global in,
for instance X86Base.ml, since this
source file is shared with litmus.new & gen.new,
It is nicer if TeX processing belongs to this module, Pretty *)
(* partial escaping of strings into legal tex command identifiers *)
let escape_tex s =
let buff = Buffer.create 16 in
for k=0 to String.length s-1 do
let c = s.[k] in
begin match c with
| '_' -> Buffer.add_char buff '\\'
| _ -> ()
end ;
Buffer.add_char buff c
done ;
Buffer.contents buff
let escape_dot s =
let buff = Buffer.create 16 in
for k=0 to String.length s-1 do
let c = s.[k] in
begin match c with
| '\\'|'"' -> Buffer.add_char buff '\\'
| _ -> ()
end ;
Buffer.add_char buff c
done ;
Buffer.contents buff
let escape_html s =
let buff = Buffer.create 16 in
for k=0 to String.length s-1 do
let c = s.[k] in
begin match c with
| '<' -> Buffer.add_string buff "<"
| '>' -> Buffer.add_string buff ">"
| '&' -> Buffer.add_string buff "&er;"
| _ -> Buffer.add_char buff c
end
done ;
Buffer.contents buff
let escape_label dm = match dm with
| Plain -> escape_dot
| Fig -> (fun s -> escape_dot (escape_tex s))
let a_pp_instruction dm m i =
let bodytext = A.pp_instruction m i in
let pp =
if PC.texmacros
then "\\asm{" ^ bodytext ^ "}"
else bodytext in
escape_label dm pp
(* Pretty printing and display *)
let pp_color chan color =
if not PC.mono then
fprintf chan "[color=%s]" color
(* dot pretty printing *)
let pp_no_solutions chan test msg =
let legend =
escape_dot(readable_name test) ^ ": " ^ test.Test_herd.name.Name.doc in
fprintf chan "digraph G {\n\n" ;
fprintf chan "/* legend */\n" ;
fprintf chan "label=\"%s\" ; \n\n" legend ;
fprintf chan "no_solns [shape=box] %a" pp_color "red" ;
fprintf chan "[label=\" %s\\l\"]\n}\n" msg
let pp_instruction dm m chan iiid = match iiid with
| E.IdInit -> fprintf chan "Init"
| E.IdSpurious -> fprintf chan "Spurious"
| E.IdSome iiid ->
let instruction = iiid.A.inst in
fprintf chan "%s" (a_pp_instruction dm m instruction)
let extra_thick = "setlinewidth(3)"
(* Scales that depend upon font size *)
let pt2inch f = f /. 72.0
let defaultpenwidth = 1.0
let scalepenwidth = match PC.penwidth with
| Some f -> fun x -> ((x *. f) /. defaultpenwidth)
| None -> fun x -> x
let defaultfontsize = 14.0
let dsize = defaultfontsize /. 72.0
let fscale = match PC.fontsize with
| None -> 1.0
| Some f -> float_of_int f /. defaultfontsize
(*
let condensednode =
sprintf "[fixedsize=\"true\"][width=\"%f\"][height=\"%f\"]"
(fscale *.0.4) (fscale *. 0.1)
*)
let pp_po_edge = PC.showpo
let do_pp_fontsize sep chan = match PC.fontsize with
| None -> ()
| Some f -> fprintf chan "%c fontsize=%i" sep f
let pp_fontsize = do_pp_fontsize ','
let do_pp_fontsize_edge sep chan = match PC.fontsize with
| None -> ()
| Some f -> fprintf chan "%c fontsize=%i" sep (f+PC.edgedelta)
let pp_fontsize_edge = do_pp_fontsize_edge ','
let pp_penwidth chan = match PC.penwidth with
| Some f -> fprintf chan ", penwidth=\"%f\"" f
| None -> ()
let pp_arrowsize chan = match PC.arrowsize with
| Some f -> fprintf chan ", arrowsize=\"%f\"" f
| None -> ()
(* Edges attributes as a function of label, or
of prefix label.... *)
type edge_attr =
{
color:string ;
style:string ;
}
let ea_t = Hashtbl.create 17
let def_ea = {color="black" ; style="" }
let add_ea key a1 a2 = Hashtbl.add ea_t key (a1,a2)
let add_eas lbls a1 a2 =
List.iter (fun lbl -> add_ea lbl a1 a2) lbls
let relabel_t = Hashtbl.create 17
let merge_labels2 lbl lbl2 nlbl =
Hashtbl.add relabel_t lbl nlbl ;
Hashtbl.add relabel_t lbl2 nlbl
let merge_labels lbl lbl2 =
let nlbl = sprintf "%s/%s" lbl lbl2 in
merge_labels2 lbl lbl2 nlbl
let relabel lbl =
try Hashtbl.find relabel_t lbl
with Not_found -> lbl
let init_pretty () =
(* Relabeling *)
if PC.relabel then begin
merge_labels "dmb" "sync" ;
merge_labels "isb" "isync" ;
merge_labels2 "ctrlisb" "ctrlisync" "ctrlisb/isync";
()
end ;
(* Colors *)
add_ea "rf"
{color="red" ; style = "" ; }
{color="black" ; style="" ; } ;
add_eas ["vo:" ; "seq"; ]
{def_ea with color="magenta"; }
{def_ea with color="grey30"; } ;
add_eas ["po"; "po:"]
def_ea {color="black" ; style="" ; } ;
add_eas
["grf" ; "ppo"; "A/B:" ; "ppo-ext:";"ppoext";
"membar:"; "poloc"; "w*w*"; "ppo-direct"]
{ color="brown" ; style="" ; }
{ color="black" ; style="" ; } ;
add_eas
["ppo-sela";]
{ color="#00b000" ; style="" ; }
{ color="black" ; style="" ; } ;
add_eas
["fr" ]
{color="#ffa040"; style=""; }
{color="black" ; style =""; };
add_eas
[ "lwfence"; "lwf"; "ffence"; "ff";
"implied"; "mfence"; "dmb"; "lwsync"; "eieio" ; "sync" ; "dmb-cumul" ; "dsb";
"dmb.st"; "dsb.st" ;
"dmb.ld"; "dsb.ld" ;
"dmb.sy"; "dsb.sy";
"dmbst"; "dsbst" ;
"dsb-cumul"; "sync-cumul"; "lwsync-cumul";
"sync_cumul" ; "lwsync_cumul" ;
"syncext";"lwsyncext";"dmbext";"dsbext";]
{color="darkgreen"; style=""; }
{color="black"; style="" ; } ;
add_eas ["A" ; "B"; "co"; "ws"; "ca";]
{color="blue" ; style = "" ; }
{color="black" ; style = "" ; } ;
add_eas ["LL" ; "LS" ; "PML"; "ll" ; "ls"; "pml"; "isync"; "dep"; "ctrl"; "data"; "addr"; "ctrlisync"; "isync"; "isb"; "ctrlisb";"ppo";"success";]
{ color="indigo" ; style = "" ; }
{ color="black" ; style = "" ; } ;
add_ea "iico"
{ def_ea with color="black" ; }
{ def_ea with color="black" ; } ;
add_ea "iico_data"
{ def_ea with color="black" ; }
{ def_ea with color="black" ; } ;
add_ea "iico_ctrl"
{ def_ea with color="grey" ; }
{ def_ea with color="grey" ; } ;
add_ea "iico_order"
{ def_ea with color="darkgrey" ; }
{ def_ea with color="darkgrey" ; } ;
add_eas ["After";]
{color="orange" ; style = extra_thick ; }
{color="black" ; style= extra_thick ; } ;
add_eas ["Before";]
{color="blue" ; style = extra_thick ; }
{color="black" ; style= extra_thick ; } ;
add_eas ["CY";]
{color="black" ; style = extra_thick ; }
{color="black" ; style= extra_thick ; } ;
()
let () = init_pretty ()
(* Get complexified *)
let get_ea def_color lbl =
let col,mono =
let key =
try let idx = String.index lbl ':' in
String.sub lbl 0 (idx+1)
with Not_found -> lbl in
try Hashtbl.find ea_t key
with Not_found -> def_color def_ea ,def_ea in
if PC.mono then mono else col
let pp_attr chan attr value = match value with
| "" -> ()
| _ -> fprintf chan ", %s=\"%s\"" attr value
and pp_extra chan attr_value = match attr_value with
| "" -> ()
| _ -> fprintf chan ", %s" attr_value
(*******************)
(* Sort out events *)
(*******************)
(* Collect events (1) by proc, (2) by poi.
As a list of list of events.
The second "list of" follows po order *)
module PU = PrettyUtils.Make(S)
let rec order_one_proc = function
| []|[_] -> []
| i1::(i2::_ as rem) ->
E.EventRel.cartesian i1 i2::order_one_proc rem
let shift_max =
let r = ref 0.0 in
for k = 0 to Array.length PC.shift-1 do
let x = PC.shift.(k) in
if !r < x then r := x
done ;
!r
let get_shift p =
if p >= Array.length PC.shift then 0.0
else PC.shift.(p)
let make_posy y env (p,es) =
let s = get_shift p in
let rec do_make_posy y env = function
| [] -> env
| e::es -> do_make_posy (y -. 1.0) (E.EventMap.add e y env) es in
do_make_posy (y -. s) env es
let order_events es by_proc_and_poi =
let iico = E.iico es in
let iicos = E.proj_rel es iico in
let rs =
List.map2
(fun ess iico ->
let r = S.unions (iico::order_one_proc ess)
and es = E.EventSet.unions ess in
try E.EventRel.topo es r
with E.EventRel.Cyclic -> assert false)
by_proc_and_poi iicos in
let max =
List.fold_left
(fun n es -> max n (List.length es)) 0 rs in
let max = max-1 in
let max = float_of_int max in
let max = max +. shift_max in
let rs = List.mapi (fun k es -> k,es) rs in
let env = List.fold_left (make_posy max) E.EventMap.empty rs in
max,env,E.EventMap.empty
let debug_event_set chan s =
output_char chan '{' ;
E.EventSet.pp chan "," (fun chan e -> fprintf chan "%s" (E.pp_eiid e)) s;
output_char chan '}'
let pp_by_proc_and_poi chan s =
List.iteri
(fun i ess ->
fprintf chan "P%i:" i ;
List.iter (fun es -> fprintf stderr " %a" debug_event_set es) ess ;
eprintf "\n")
s ;
flush stderr
let make_posy_mult y env (p,ess) =
let s = get_shift p in
let rec do_make_posy y env = function
| [] -> env
| es::ess ->
let env =
E.EventSet.fold
(fun e env -> E.EventMap.add e y env)
es env in
do_make_posy (y -. 1.0) env ess in
do_make_posy (y -. s) env ess
let dsiy = PC.dsiy
let siwidth = PC.siwidth
let order_events_mult es by_proc_and_poi =
let iico = E.iico es in
let by_proc_and_poi =
List.map
(fun ess ->
List.fold_right
(fun es k -> E.EventRel.strata es iico @ k)
ess [])
by_proc_and_poi in
if dbg then
pp_by_proc_and_poi stderr by_proc_and_poi ;
let max =
List.fold_left
(fun n ess -> max n (List.length ess)) 0 by_proc_and_poi in
let max = max-1 in
let max = float_of_int max in
let max = max +. shift_max in
if dbg then eprintf "max=%.02f\n%!" max ;
let ps = List.mapi (fun k es -> k,es) by_proc_and_poi in
let envy = List.fold_left (make_posy_mult max) E.EventMap.empty ps in
let envx,envy =
List.fold_left
(fun envp (k,ess) ->
let kf = float_of_int k in
List.fold_left
(fun (envx,envy as envp) es ->
let n = E.EventSet.cardinal es in
match n with
| 1 ->
E.EventSet.fold
(fun e env -> E.EventMap.add e kf env)
es envx,envy
| n ->
assert (n > 1) ;
let nf = float_of_int n in
let delta = siwidth /. (nf -. 1.0) in
let _,envp =
E.EventSet.fold
(fun e ((dx,dy),(envx,envy)) ->
let envx = E.EventMap.add e dx envx
and envy =
try
let old = E.EventMap.find e envy in
E.EventMap.add e (old +. dy) envy
with Not_found -> envy in
(dx +. delta,0.0 -. dy),(envx,envy))
es ((kf -.0.5 +. (1.0 -. siwidth) *. 0.5,if k mod 2 = 0 then dsiy else -. dsiy),envp) in
envp)
envp ess)
(E.EventMap.empty,envy) ps in
max,envy,envx
(*******************************)
(* Build "visible" po relation *)
(*******************************)
(*
Only successor edges are shown,
and only from maximal intra-causality to minimal intra-causality.
*)
(* Non deps mode *)
let rec min_max_to_succ = function
| []|[_] -> E.EventRel.empty
| (_xmin,xmax)::((ymin,_ymax)::_ as rem) ->
E.EventRel.union
(E.EventRel.cartesian xmax ymin)
(min_max_to_succ rem)
let make_visible_po_nodeps es by_proc_and_poi =
let intra =
E.EventRel.transitive_closure (E.iico es) in
let min_max_list =
List.map
(List.map
(fun es ->
let mins =
E.EventSet.filter
(fun e -> not (E.EventRel.exists_pred intra e))
es
and maxs =
E.EventSet.filter
(fun e -> not (E.EventRel.exists_succ intra e))
es in
mins,maxs))
by_proc_and_poi in
E.EventRel.unions
(List.map min_max_to_succ min_max_list)
(* Deps mode *)
let make_visible_po_deps es by_proc_and_poi =
let iico =
E.EventRel.transitive_closure (E.iico es) in
let _,po0 = es.E.po in
let po = E.EventRel.diff po0 iico in
let po = E.EventRel.remove_transitive_edges po in
let mins,maxs =
List.fold_left
(fun p ess ->
List.fold_left
(fun (min,max) es ->
let min2 =
E.EventSet.filter
(fun e -> not (E.EventRel.exists_pred (*po_*)iico e))
es
and max2 =
E.EventSet.filter
(fun e -> not (E.EventRel.exists_succ (*po_*)iico e))
es in
E.EventSet.union min min2,E.EventSet.union max max2) p ess
)
(E.EventSet.empty, E.EventSet.empty) by_proc_and_poi in
let r =
E.EventRel.filter (fun (e1,e2) -> E.EventSet.mem e1 maxs && E.EventSet.mem e2 mins) po
in
if dbg then
eprintf "make_visible_po {%a} => \n {%a} \n%!" E.debug_rel po0 E.debug_rel r;
r
let make_visible_po =
if S.do_deps then make_visible_po_deps
else make_visible_po_nodeps
let dm = PC.dotmode
let m = match dm with | Plain -> Ascii| Fig -> DotFig
let mmode = m
let pp_edge_label movelabel lbl =
let lbl =
if PC.relabel then relabel lbl
else lbl in
let lbl =
if PC.movelabel && movelabel then
let sz = String.length lbl in
if PC.texmacros then
sprintf "%s" lbl
else
lbl ^ String.make sz ' '
else lbl in
let lbl =
if PC.tikz then
sprintf "{\\small %s}" lbl
else lbl in
escape_label dm lbl
let pp_thread chan i =
let pp =
if PC.showthread then
if PC.texmacros then
sprintf "\\myth{%i}" i
else
sprintf "Thread %i" i
else "" in
fprintf chan "%s" (escape_label dm pp)
module StringPair = struct
type t = string * string
let compare (e1,e2) (e3,e4) =
match String.compare e1 e3 with
| 0 -> String.compare e2 e4
| r -> r
end
module PairSet = MySet.Make(StringPair)
module PairMap = MyMap.Make(StringPair)
type info = { ikey:string; icolor:string; }
let edges = ref PairMap.empty
let edges_seen = ref StringMap.empty
let reset_pairs () =
edges := PairMap.empty ;
edges_seen := StringMap.empty ;
()
let find_pair p m =
try PairMap.find p m with Not_found -> []
let add_if_new p i m add =
let old = find_pair p m in
if
List.exists
(fun {ikey=k; _} -> k = i.ikey)
old
then m
else
PairMap.add p (add i old) m
let do_add_pair p i m =
add_if_new p i m (fun i old -> i::old)
let add_end p i m =
add_if_new p i m (fun i old -> old@[i])
let handle_symetric m =
let yes,no =
PairMap.fold
(fun (n1,n2 as p) infos (m_yes,m_no) ->
let yes,no =
List.partition
(fun i -> StringSet.mem i.ikey pc_symetric)
infos in
let m_yes =
let q =
if String.compare n2 n1 < 0 then (n2,n1) else p in
List.fold_left
(fun m_yes i -> ((q,i)::m_yes))
m_yes yes
and m_no =
match no with
| [] -> m_no
| _ -> PairMap.add p no m_no in
m_yes,m_no)
m ([],PairMap.empty) in
let new_m,rem =
List.fold_left
(fun (new_m,rem) ((n1,n2 as p),i) ->
let q = n2,n1 in
let no_p = find_pair p no
and no_q = find_pair q no in
match no_p,no_q with
| [],[] -> new_m,(p,i)::rem
| [],_ -> add_end q i new_m,rem
| _,[] -> add_end p i new_m,rem
| _,_ -> add_end p i (add_end q i new_m),rem)
(no,[]) yes in
List.fold_left
(fun m (p,i) -> do_add_pair p i m) new_m rem
let compute_colors cs = (* NB keep order *)
let rec do_rec = function
| [] -> []
| c::cs ->
if List.mem c cs then do_rec cs
else c::do_rec cs in
String.concat ":" (do_rec cs)
let fmt_merged_label fst i =
let pp_label = escape_html i.ikey in
let pp_label = pp_edge_label false pp_label in
sprintf "<font color=\"%s\">%s%s</font>" i.icolor
(if fst then "" else "") pp_label
let fmt_merged_labels infos = match infos with
| [] -> []
| i::rem ->
fmt_merged_label true i::
List.map (fmt_merged_label false) rem
let dump_pairs chan =
let new_edges = handle_symetric !edges in
PairMap.iter
(fun (n1,n2) infos ->
let all_syms =
List.for_all
(fun i -> StringSet.mem i.ikey pc_symetric)
infos in
let colors = compute_colors (List.map (fun i -> i.icolor) infos)
and lbl = String.concat "" (fmt_merged_labels infos) in
fprintf chan "%s -> %s [label=<%s>, color=\"%s\""
n1 n2 lbl colors ;
pp_fontsize_edge chan ;
pp_penwidth chan ;
pp_arrowsize chan ;
if all_syms then pp_attr chan "arrowhead" "none" ;
fprintf chan "];\n" ;
())
new_edges ;
reset_pairs ()
let add_pair p i = edges := do_add_pair p i !edges
let do_merge_edge n1 n2 lbl def_color =
let color =
try
DotEdgeAttr.find lbl "color" PC.edgeattrs
with Not_found ->
let {color;_} = get_ea def_color lbl in
color in
add_pair (n1,n2) {ikey=lbl; icolor=color; }
let real_do_pp_edge
chan n1 n2 lbl def_color override_style extra_attr backwards
movelbl
=
let backwards = match PC.graph with
| Graph.Cluster|Graph.Free -> false
| Graph.Columns ->
if lbl = "po" then false
else backwards in
let overridden a =
try
ignore (DotEdgeAttr.find lbl a PC.edgeattrs) ; true
with Not_found -> false in
let checklabel a =
try begin match DotEdgeAttr.find a "label" PC.edgeattrs with
| "tail" -> "taillabel"
| "head" -> "headlabel"
| _ -> "label"
end with
| Not_found -> "label" in
let {color=color ; style=style; } = get_ea def_color lbl in
fprintf chan "%s -> %s [%s=\"%s\""
(if backwards then n2 else n1)
(if backwards then n1 else n2)
(if not (overridden "label") && PC.movelabel && movelbl then "taillabel"
else checklabel lbl)
(pp_edge_label movelbl lbl) ;
if StringSet.mem lbl pc_symetric then pp_attr chan "arrowhead" "none" ;
if not (overridden "color") then begin
pp_attr chan "color" color ;
if not (PC.tikz) then
pp_attr chan "fontcolor" color
end ;
if PC.tikz then
pp_attr chan "lblstyle" "auto, midway, inner sep=0.7mm";
if not PC.tikz && not (overridden "fontsize") then
pp_fontsize_edge chan;
if not (overridden "penwidth") then pp_penwidth chan ;
if not (overridden "arrowsize") then pp_arrowsize chan ;
if not (overridden "style") then
pp_attr chan "style"
(if override_style = "" then style else override_style) ;
pp_extra chan extra_attr ;
if backwards then pp_attr chan "dir" "back" ;
List.iter
(fun (a,v) -> match a with
| "color" ->
pp_attr chan "color" v ;
pp_attr chan "fontcolor" v
| "label" -> ()
| _ ->
pp_attr chan a v)
(DotEdgeAttr.find_all lbl PC.edgeattrs) ;
fprintf chan "];\n" ;
()
let get_edge_seen lbl = StringMap.safe_find PairSet.empty lbl !edges_seen
let known_edge n1 n2 lbl =
let seen = get_edge_seen lbl in
PairSet.mem (n1,n2) seen || PairSet.mem (n2,n1) seen
let record_edge_seen n1 n2 lbl =
let seen = get_edge_seen lbl in
edges_seen := StringMap.add lbl (PairSet.add (n1,n2) seen) !edges_seen
let do_pp_edge
chan n1 n2 lbl def_color override_style extra_attr backwards
movelbl
=
try
if StringSet.mem lbl PC.unshow then raise Exit ;
let is_symetric = StringSet.mem lbl pc_symetric in
if is_symetric then begin
if known_edge n1 n2 lbl then raise Exit ;
record_edge_seen n1 n2 lbl
end ;
if PC.edgemerge then
do_merge_edge n1 n2 lbl def_color
else
real_do_pp_edge
chan n1 n2 lbl def_color override_style extra_attr (backwards && not is_symetric)
movelbl
with Exit -> ()
let pp_edge chan n1 n2 lbl backwards =
do_pp_edge chan n1 n2 lbl (fun x -> x) "" "" backwards
let pp_point chan n lbl pos =
let {color=color;_} = get_ea (fun x -> x) lbl in
let sz = (pt2inch (scalepenwidth PC.ptscale)) in
fprintf chan "%s [shape=point, height=%.2f, width=%.2f" n sz sz ;
pp_attr chan "color" color ;
pp_extra chan pos ;
fprintf chan "];\n"
let pp_none chan n pos =
fprintf chan "%s [shape=none, height=0.0, width=0.0, label=\"\"" n ;
pp_extra chan pos ;
fprintf chan "];\n"
let pp_node_eiid_label e = match dm with
| Plain | Fig -> sprintf "%s: " (E.pp_eiid e)
let pp_node_eiid e = sprintf "eiid%i" e.E.eiid
let pp_node_ii chan ii = match ii with
| E.IdInit|E.IdSpurious -> ()
| E.IdSome ii ->
fprintf chan "proc:%s poi:%i\\l"
(Proc.pp ii.A.proc)
ii.A.program_order_index
(*
This complex function is not meant to be used directly,
in case you wish, here is its type...
val pp_dot_event_structure :
out_channel ->
test ->
string option -> (* Legend *)
event_structure ->
rfmap ->
rel_pp -> (* Relations *)
event_set -> (* Nodes to be marked *)
-> unit
*)
let do_pp_dot_event_structure chan _test legend es rfmap sets vbss mark =
if dbg then begin
prerr_endline "SETS:" ;
StringMap.iter
(fun tag evts -> eprintf "%s: %a\n" tag debug_event_set evts)
sets
end ;
let stes =
StringMap.fold
(fun tag es m ->
E.EventSet.fold
(fun e m ->
let tags = S.E.EventMap.safe_find StringSet.empty e m in
S.E.EventMap.add e (StringSet.add tag tags) m)
es m)
sets S.E.EventMap.empty in
let stes =
S.E.EventMap.map
(fun tags ->
StringSet.map
(fun tag -> (get_ea Misc.identity tag).color)
tags)
stes in
let vbss =
List.fold_right
(fun (tag,r) k ->
if StringSet.mem tag PC.unshow then k
else
let r =
if StringSet.mem tag PC.noid then
E.EventRel.filter
(fun (e1,e2) -> not (E.event_equal e1 e2))
r
else r in
(tag,r)::k)
vbss [] in
let pl = fprintf chan "%s\n"
and pf fmt = fprintf chan fmt in
(************************)
(* Position computation *)
(************************)
let max_proc = Misc.last (E.procs_of es) in
(* Collect events (1) by proc, then (2) by poi *)
let events_by_proc_and_poi = PU.make_by_proc_and_poi es in
let maxy,envy,envx =
let mult = true in
if mult then order_events_mult es events_by_proc_and_poi
else order_events es events_by_proc_and_poi in
let inits = E.mem_stores_init_of es.E.events in
let n_inits = E.EventSet.cardinal inits in
let init_envx =
if one_init then
let w1 = float_of_int max_proc in
let x =
match PC.initpos with
| Some (x,_) -> x
| None ->
match max_proc with
| 1 -> -0.3333
| _ -> (w1 /. 2.0) -. 0.5 in
E.EventSet.fold
(fun e env ->
E.EventMap.add e x env)
inits E.EventMap.empty
else
let delta = if max_proc+1 >= n_inits then 1.0 else 0.75 in
let w1 = float_of_int (max_proc+1)
and w2 = float_of_int n_inits *. delta in
let xinit = Misc.proj_opt 0.0 (Misc.app_opt fst PC.initpos) in
(* eprintf "w1=%f, w2=%f\n" w1 w2 ; *)
let shift = (w1 -. w2) /. 2.0 +. xinit in
let _,r = E.EventSet.fold
(fun e (k,env) ->
k+1,
let x = shift +. (float_of_int k) *. delta in
(* eprintf "k=%i, x=%f\n" k x ; *)
E.EventMap.add e x env)
inits (0,E.EventMap.empty) in
r in
let pp_node_eiid =
if one_init then
fun e ->
if E.EventSet.mem e inits then "eiidinit" else pp_node_eiid e
else pp_node_eiid in
let yinit = Misc.proj_opt 0.66667 (Misc.app_opt snd PC.initpos) in
let maxy =
if E.EventSet.is_empty inits then maxy
else maxy +. yinit in
let get_proc e = match E.proc_of e with
| Some p -> p
| None -> (-1) in
let get_posx_int e = get_proc e in
let get_posx e =
if E.is_mem_store_init e then
try E.EventMap.find e init_envx
with Not_found -> assert false
else try E.EventMap.find e envx
with Not_found -> float_of_int (get_posx_int e) in
let get_posy e =
if E.is_mem_store_init e then maxy
else
try E.EventMap.find e envy
with Not_found -> 10.0 in
let is_even e1 e2 =
let d = abs (get_posx_int e1 - get_posx_int e2) in
d >= 2 && (d mod 2) = 0 in
(* Hum...
At least it seems that, -> right label below
<- left label above
Or...
*)
let is_up e1 e2 =
let d = abs (get_posx_int e1 - get_posx_int e2) in
d >= 2 &&
not (is_even e1 e2) &&
get_posy e1 < get_posy e2 in
let back = false in
let is_back e1 e2 = back && get_posx_int e1 < get_posx_int e2 in
let xorigin=1.0 in
(* Size of one step, horizontal *)
let xstep = 1.0 in
(*Was
begin match max_proc with
| 3 -> if PC.condensed then 0.7 else 2.0
| 2 -> if PC.condensed then 0.7 (*WAS 1.0*) else 2.5
| _ -> if PC.condensed then 0.7 (*WAS 1.0*) else 3.0
end
*)
(* size of one step, vertical *)
let ystep = 0.75 in
(* WAS
begin match maxy with
| 2 -> if PC.condensed then 0.35 else 2.0
| 5 -> if PC.condensed then 0.35 else 1.0
(* SS: HACK!! for ppo1/ppo3. We should take this as input maybe *)
| _ -> if PC.condensed then 0.35 else 3.0
end
*)
let xscale= PC.scale *. PC.xscale *. xstep in
let yscale= PC.scale *. PC.yscale *. ystep in
(*
Pick out the vertical edges of the last thread.
so that the edge label can be put on their rhs,
to reduce the label overlaps
*)
let last_thread e e' =
let p = get_proc e and p' = get_proc e' in
p = p' && p = max_proc in
(* Position of events *)
let xfinal f = xscale *. f +. xorigin
and yfinal f = yscale *. f in
let xevent e = xfinal (get_posx e) in
let yevent e = yfinal (get_posy e) in
let pp_event_position = match PC.graph with
| Graph.Columns ->
fun chan e ->
fprintf chan ", pos=\"%f,%f!\"" (xevent e) (yevent e)
| Graph.Free|Graph.Cluster ->
fun _chan _e -> () in
let pp_init_rf_position = match PC.graph with
| Graph.Cluster|Graph.Free -> fun _e -> ""
| Graph.Columns ->
fun e ->
let x = xevent e
and y = yevent e in
let dx,dy = PC.initdotpos in
sprintf "pos=\"%f,%f!\""
(x +. xscale *. dx)
(y +. yscale *. dy) in
let pp_final_rf_position = match PC.graph with
| Graph.Cluster|Graph.Free -> fun _e -> ""
| Graph.Columns ->
fun e ->
let x = xevent e
and y = yevent e in
let dx,dy = PC.finaldotpos in
sprintf "pos=\"%f,%f!\""
(x +. xscale *. dx)
(y +. yscale *. dy) in
let pp_action e =
let pp = E.pp_action e in
let pp =
if E.EventSet.mem e mark then
sprintf "*%s*" pp
else pp in
pp in
let boxwidth = xscale *. 0.65 *. PC.boxscale in
let boxheight = yscale *. 0.25 in
let pp_loc e = match E.location_of e with
| None -> assert false
| Some (A.Location_global v) -> (* No brackets, old style *)
A.V.pp_v_old v
| Some loc ->
A.pp_location loc in
let pp_event ?lbl isinit color chan e =
let act = pp_action e in
let act =
if PC.verbose > 0 then begin
if E.EventSet.mem e es.E.data_ports then
act ^ " (data)"
else if E.EventSet.mem e es.E.success_ports then
act ^ " (success)"
else act
end else act in
let is_ghost = E.EventSet.mem e es.E.speculated in
if not PC.squished then begin
begin match lbl with
| None ->
fprintf chan "%s [label=\"%s%s%s%s\\l%a%a\""
(pp_node_eiid e) (pp_node_eiid_label e)
(escape_label dm act)
(if is_ghost then " (ghost)" else "")
(if E.EventSet.mem e es.E.data_ports then " (data)" else "")
pp_node_ii e.E.iiid
(pp_instruction dm m) e.E.iiid
| Some _ ->
fprintf chan "eiidinit [label=\"Init\""
end ;
pp_attr chan "shape" "box" ;
pp_fontsize chan ;
pp_attr chan "color" color ;
fprintf chan "];\n"
end else begin
let act =
if is_ghost then act^" (ghost)"
else act in
let act =
match lbl with
| None ->
let eiid_lab =
if PC.labelinit && isinit then
sprintf "i%s:" (pp_loc e)
else
pp_node_eiid_label e in
fprintf chan "%s [%slabel=\"%s%s\""
(pp_node_eiid e)
(if is_ghost then "fontcolor=\"grey64\", " else "")
(eiid_lab)
(escape_label dm act) ;
act
| Some es ->
let acts =
E.EventSet.fold
(fun e k ->
let act = pp_action e in
if PC.labelinit then
let loc = pp_loc e in
sprintf "i%s: %s" loc act::k
else
act::k)
es [] in
let acts = String.concat ", " acts in
fprintf chan "eiidinit [label=\"%s\""
(escape_label dm acts) ;
acts in
let cl =
try
let cl = StringSet.choose (S.E.EventMap.find e stes) in
Some cl
with Not_found -> None in
let is_shape,color =
(PC.verbose > 2 || cl <> None),
(match cl with| None -> color | Some cl -> cl) in
pp_attr chan "shape"
(if is_shape then "box" else "none") ;
pp_fontsize chan ;
if is_shape then pp_attr chan "color" color ;
pp_event_position chan e ;
pp_attr chan "fixedsize" (if PC.fixedsize then "true" else "false") ;
pp_attr chan "height"
(sprintf "%f"
(if PC.fixedsize then boxheight
else fscale *. dsize)) ;
pp_attr chan "width"
(sprintf "%f"
(* For neato to route splines... *)
(if PC.fixedsize then boxwidth
else
(float_of_int (String.length act) +. PC.extrachars)
*. PC.boxscale *. fscale *. dsize)) ;
fprintf chan "];\n"
end in
let pp_init_event color chan inits =
let e = try E.EventSet.choose inits with Not_found -> assert false in
pp_event ~lbl:inits false color chan e in
let pp_event_structure chan vbss es =
(* Extract relation to represent as classes, if any *)
let asclass = match PC.classes with
| Some n ->
begin try
eprintf "classes=\"%s\"\n" n ;
let equiv = List.assoc n vbss in
let cls = E.EventRel.classes equiv in
eprintf
"%s\n"
(E.EventRel.pp_str " "
(fun (e1,e2) ->
sprintf "%s-%s" (E.pp_eiid e1) (E.pp_eiid e2))
equiv) ;
List.iter
(fun es ->
eprintf " {%s}" (E.EventSet.pp_str "," E.pp_eiid es))
cls ;
eprintf "\n" ;
Some (n,cls)
with Not_found -> None
end
| None -> None in
let pl = fprintf chan "%s\n" in
(* Init events, if any *)
if not (E.EventSet.is_empty inits) then begin
pl "" ;
pl "/* init events */" ;
if one_init then
pp_init_event "blue" chan inits
else
E.EventSet.iter
(fun ew -> pp_event true "blue" chan ew)
inits
end ;
pl "" ;
pl "/* the unlocked events */" ;
Misc.iteri
(fun n evtss ->
(* Prelude *)
begin match PC.graph with
| Graph.Cluster ->
fprintf chan "subgraph cluster_proc%i" n ;
fprintf chan
" { rank=sink; label = \"%a\"%a; %sshape=box;\n"
pp_thread n
(fun chan () -> do_pp_fontsize ';' chan) ()
(if not PC.mono then "color=magenta; " else "")
| Graph.Columns ->
if PC.showthread then begin
let pos =
sprintf "%f,%f"
(xfinal (float_of_int n))
(yfinal (maxy +. PC.threadposy)) in
fprintf chan
"proc%i_label_node [shape=%s%a, label=\"%a\", pos=\"%s!\", fixedsize=true, width=%f, height=%f]\n"
n (if PC.verbose > 2 then "box" else "none")
(fun chan () -> pp_fontsize chan) ()
pp_thread n pos boxwidth boxheight
end
| Graph.Free -> ()
end ;
(* Now output events *)
let pp_events = match asclass with
| None ->
fun _m pp_evt evts ->
E.EventSet.pp chan "" pp_evt evts
| Some (name,cls) ->
let color =
lazy begin
try DotEdgeAttr.find name "color" PC.edgeattrs
with Not_found ->
let {color;_} =
get_ea (fun r -> { r with color="blue";}) name in
color end in
fun m pp_evt evts ->
let cls,evts =
List.fold_left
(fun (cls,k) cl ->
let cl = E.EventSet.inter cl evts in
if E.EventSet.is_empty cl then (cls,k)
else (cl::cls, E.EventSet.diff k cl))
([],evts) cls in
E.EventSet.pp chan "" pp_evt evts ;
Misc.iteri
(fun j cl ->
let color = Lazy.force color in
fprintf chan "subgraph cluster_class_%02i_%02i_%02i" n m j ;
fprintf chan
" { %s label=\"%s\"; shape=box;\n"
(if not PC.mono then
sprintf "color=%s;" color
else "color=\"grey30\"; style=dashed; ")
"" ;
E.EventSet.pp chan "" pp_evt cl ;
fprintf chan "}\n")
cls in
Misc.iteri
(fun m evts -> (* evts = all events from one instruction.. *)
if
PC.withbox &&
(show_all_events || not (E.EventSet.is_singleton evts))
then begin
let pp_ins =
if PC.labelbox then
let e0 =
try E.EventSet.choose evts
with Not_found -> assert false in
let ins =
match e0.E.iiid with
| E.IdSome iiid -> iiid.A.inst
| E.IdInit|E.IdSpurious -> assert false in
E.pp_instance e0 ^ " " ^
a_pp_instruction dm mmode ins
else "" in
fprintf chan "subgraph cluster_proc%i_poi%i" n m ;
fprintf chan
" { %s label = \"%s\"; labelloc=\"b\"; shape=box;\n"
(if not PC.mono then
"color=green;"
else "color=\"grey30\"; style=dashed; ")
pp_ins ;
(* assuming atomicity sets are always full instructions *)
pp_events m (pp_event false "blue") evts ;
fprintf chan "}\n"
end else begin (* no green box around one event only *)
pp_events m (pp_event false "blue") evts
end)
evtss;
(* Postlude *)
begin match PC.graph with
| Graph.Cluster -> fprintf chan "}\n"
| Graph.Free|Graph.Columns -> ()
end)
events_by_proc_and_poi ;
pl "" ;
let spurious_es = PU.spurious_events es in
if not (E.EventSet.is_empty spurious_es) then begin
pl "/* Spurious events */" ;
E.EventSet.pp chan "" (pp_event false "red") spurious_es ;
()
end ;
pl "/* the intra_causality_data edges */\n" ;
E.EventRel.pp chan ""
(fun chan (e,e') ->
pp_edge chan (pp_node_eiid e) (pp_node_eiid e') "iico_data"
false false)
es.E.intra_causality_data ;
pl "" ;
pl "/* the intra_causality_control edges */" ;
E.EventRel.pp chan ""
(fun chan (e,e') ->
pp_edge chan
(pp_node_eiid e) (pp_node_eiid e')
"iico_ctrl" false false)
es.E.intra_causality_control ;
E.EventRel.pp chan ""
(fun chan (e,e') ->
pp_edge chan
(pp_node_eiid e) (pp_node_eiid e')
"iico_order" false false)
es.E.intra_causality_order ;
(****************)
(* new po edges *)
(****************)
let make_rf_from_rfmap rfmap =
S.RFMap.fold
(fun wt rf k -> match wt,rf with
| S.Load er,S.Store ew when E.is_mem er ->
E.EventRel.add (ew,er) k
| _ -> k)
rfmap
E.EventRel.empty in
if pp_po_edge then begin
let replaces_po =
match PC.graph with
| Graph.Columns|Graph.Cluster ->
let all_vbss = E.EventRel.unions (List.map snd vbss) in
let rf = make_rf_from_rfmap rfmap in
let r = E.EventRel.union rf all_vbss in
E.EventRel.union r (E.EventRel.inverse r)
| Graph.Free -> E.EventRel.empty in
let po_edges = make_visible_po es events_by_proc_and_poi in
let po_edges = E.EventRel.diff po_edges replaces_po in
(* let po_edges = reduces_more po_edges replaces_po in *)
pl "" ;
pl "/* the poi edges */" ;
E.EventRel.pp chan ""
(fun chan (e,e') ->
let lbl = match PC.graph with
| Graph.Free ->
if PC.showthread then
sprintf "po:%i" (get_proc e)
else "po"
| Graph.Columns|Graph.Cluster ->
"po" in
pp_edge chan
(pp_node_eiid e) (pp_node_eiid e') lbl
(last_thread e e') (is_even e e'))
po_edges
end ;
vbss in
reset_pairs () ;
pl "digraph G {" ;
pl "" ;
begin match PC.dotheader with
| Some h -> pl h
| None ->
(* Best trade-off for those two parameters, beware of changes... *)
begin match PC.splines with
| Some s -> pf "splines=%s;\n" (Splines.pp s)
| None -> ()
end ;
begin match PC.overlap with
| Some s -> pf "overlap=%s;\n" s
| None -> ()
end ;
(* pl "compound=true;\n " ; *)
begin match PC.margin with
| None -> ()
| Some f ->
pf "margin=\"%f\";\n" f
end ;
begin match PC.pad with
| None -> ()
| Some f ->
pf "pad=\"%f\";\n" f
end ;
begin match PC.fontname with
| Some s -> pf "fontname=\"%s\";\n" s
| None -> ()
end ;
begin match PC.sep with
| None-> ()
| Some s ->
pf "sep=\"%s\"\n" s
end ;
(* pl "bgcolor=\"transparent\";\n " ; *)
end ;
pl "" ;
begin match legend with
| Some legend ->
pl "/* legend */" ;
begin match PC.fontsize with
| None -> ()
| Some f ->
pf "fontsize=%i;\n" f
end ;
pf "label=\"%s\";\n\n" (escape_dot legend) ;
()
| None -> ()
end ;
let vbss = pp_event_structure chan vbss es in
pl "/* the rfmap edges */" ;
let show_ref_rel = List.exists (fun (lab,_) -> lab = "rf") vbss in
S.pp_rfmap chan ""
(fun chan wt rf -> match wt,rf with
| S.Load er,S.Store ew ->
if not show_ref_rel then
pp_edge chan
(pp_node_eiid ew)
(pp_node_eiid er)
"rf"
(last_thread ew er || is_up ew er || is_back ew er)
(is_even ew er)
| S.Final _,S.Store ew ->
if PC.showfinalrf then
let final_id = "final"^pp_node_eiid ew in
pp_none chan final_id (pp_final_rf_position ew);
pp_edge chan (pp_node_eiid ew) final_id "rf" false false
else ()
| S.Load er,S.Init ->
if PC.showinitrf then begin
let init_id = "init"^pp_node_eiid er in
pp_point chan init_id "rf" (pp_init_rf_position er);
pp_edge chan init_id (pp_node_eiid er) "rf" false false
end
| S.Final _,S.Init -> ())
rfmap ;
pl "" ;
(* A bunch of arrows *)
pl "" ;
pl "/* The viewed-before edges */" ;
if dbg then begin
let ns = List.map fst vbss in
eprintf "Names: {%s}\n" (String.concat "," ns)
end ;
List.iter
(fun (label,vbs) ->
if dbg then eprintf "label=%s\n%!" label;
E.EventRel.pp chan ""
(fun chan (e,e') ->
do_pp_edge chan (pp_node_eiid e) (pp_node_eiid e') label
(* Overides default color... *)
(fun s -> { s with color="brown" ; })
(* Overides any style given *)
(if (try "mo" = String.sub label 0 2 with Invalid_argument _ -> false) && E.is_mem_store e && E.is_mem_store e' then "" (*"penwidth=10.0"*) else "")
(* Extra attributes, overrides nothing *)
""
(last_thread e e' || is_up e e' || is_back e e')
(is_even e e'))
vbs)
vbss ;
dump_pairs chan ;
pl "}"
(*********************************************)
(* get rid of register events before dumping *)
(*********************************************)
let select_non_init =
if PC.showinitwrites then
fun _ -> true
else
fun e -> not (E.is_mem_store_init e)
let select_event = match PC.showevents with
| AllEvents -> (fun _ -> true)
| MemEvents -> E.is_mem
| NonRegEvents -> (fun e -> not (E.is_reg_any e))
| MemFenceEvents -> let open Misc in E.is_mem ||| E.is_barrier
let select_event = let open Misc in select_event &&& select_non_init
let select_events = E.EventSet.filter select_event
let select_rel =
E.EventRel.filter (fun (e1,e2) -> select_event e1 && select_event e2)
let select_es es =
{ es with
E.events = select_events
es.E.events ;
speculated = select_events
es.E.speculated;
po = begin
let s,po = es.E.po in
s,select_rel po
end;
intra_causality_data = select_rel
es.E.intra_causality_data;
intra_causality_control = select_rel
es.E.intra_causality_control;
intra_causality_order = select_rel
es.E.intra_causality_order;
}
let select_rfmap rfm =
S.RFMap.fold
(fun wt rf k -> match wt,rf with
| (S.Load e1,S.Store e2) ->
begin match select_event e1, select_event e2 with
| true,true -> S.RFMap.add wt rf k
| true,false ->
if E.is_mem_store_init e2 then
S.RFMap.add wt S.Init k
else k
| _,_ -> k
end
| (S.Final _,S.Store e)
| (S.Load e,S.Init)
->
if select_event e then
S.RFMap.add wt rf k
else k
| S.Final _,S.Init -> k)
rfm S.RFMap.empty
let pp_dot_event_structure chan test legend es rfmap sets vbss _conc =
let obs =
if PC.showobserved then
PU.observed test es
else
E.EventSet.empty in
do_pp_dot_event_structure chan
test
legend
(select_es es)
(select_rfmap rfmap)
(StringMap.map (fun s -> select_events s) sets)
(List.map
(fun (tag,rel) -> tag,select_rel rel)
vbss)
obs
let dump_legend chan test legend conc ?(sets=StringMap.empty) vbs =
pp_dot_event_structure
chan test (if PC.showlegend then Some legend else None)
conc.S.str conc.S.rfmap sets vbs S.conc_zero
let dump_es_rfm_legend chan legend test es rfm =
pp_dot_event_structure chan test legend es rfm
StringMap.empty [] S.conc_zero
let dump_es chan test es = dump_es_rfm_legend chan None test es S.RFMap.empty
let dump_es_rfm chan = dump_es_rfm_legend chan None
(* Showed versions of dump functions *)
module SHOW = Show.Make(PC)
let show_es_rfm test es rfm =
SHOW.show (fun chan -> dump_es_rfm chan test es rfm)
let show_legend test legend conc ?(sets = StringMap.empty) vbs =
SHOW.show
(fun chan ->
let legend = if PC.showlegend then Some legend else None in
pp_dot_event_structure
chan test legend conc.S.str conc.S.rfmap sets vbs conc)
end
|