[tools] Enhance compatibility of tools that read logs - #1970
Conversation
3f8436a to
89e42ae
Compare
4239e5d to
394ba68
Compare
fsestini
left a comment
There was a problem hiding this comment.
Hi @maranget , I've left some comments.
Could you also please provide some example inputs that I can use to reproduce the issue, and to see for myself how this PR impacts the output?
On a similar note, I think this PR should also include some dune cram tests, as those are designed to check expected input-output behaviour of CLI programs, which seems appropriate here. In particular it would be useful to have tests that show mcompare and mcmp side by side on equal inputs.
| "<bool> consider fault types, default %b" !ft) | ||
|
|
||
| let parse_datafault ft = | ||
| ("-datafault", Arg.Bool (fun b -> ft := b), |
There was a problem hiding this comment.
I wonder if we could use a more informative name for this option. Maybe something along the lines of -mmu-faults-as-data?
| let parse_datafault ft = | ||
| ("-datafault", Arg.Bool (fun b -> ft := b), | ||
| Printf.sprintf | ||
| "<bool> all MMU faults are from data, default %b" !ft) |
There was a problem hiding this comment.
all MMU faults are from data
If I understand correctly, this is not quite the case. For example, a fault that already has a I- prefix is not treated as being from data, regardless of the status of this option. If so, can we make this documentation text more precise?
There was a problem hiding this comment.
Yes we can! What about all non-specific MMU faults are from data (i.e. are implicitly prefixed with "D-")
| let split_at_diprefix s = | ||
| let len = String.length s in | ||
| if len > 2 then | ||
| match String.sub s 0 2 with | ||
| | ("D-"|"I-") as pref -> pref,String.sub s 2 (len-2) | ||
| | _ -> "",s | ||
| else "",s |
There was a problem hiding this comment.
split_at_diprefix could reuse has_diprefix for checking the presence of a DI prefix.
Moreover, this function uses "" as a sentinel to signal "no prefix", which feels stringly typed, since callers never actually use the first pair component and only need the stripped suffix when a prefix exists. Therefore, returning an optional like this would be clearer IMO:
let strip_diprefix s =
if has_diprefix s then
let len = String.length s in
Some (String.sub s 2 (len - 2))
else
NoneThere was a problem hiding this comment.
Of course, strip_diprefix should reuse `has_diprefix". Ok for the new return type.
394ba68 to
9c946af
Compare
I'll know little about cram test, I'll have a go. |
3474bd1 to
9b395d9
Compare
|
Significant rewriting of diff and compare functions under way -> draft |
2d42c8e to
429106a
Compare
|
Hi @fsestini, @psafont and @relokin. I have finally decided not to rely on state lines to be totally ordered (which they are not) for merging, diffing and intersecting them. Instead, I have adopted a two level algorithm: group lines by identical bindings, those groups of lines are totally ordered, and then rely on, naive, quadratic algorithms for operating inside these groups. See commit 7715bee for details. I have also added a small cram test. The test checks that mcompare7 and mcmp7 produce the same result on a small example. |
f6e1411 to
7465906
Compare
psafont
left a comment
There was a problem hiding this comment.
I'm surprised by the amount of files and code changes needed to do this change, but I can't really say I would approach it in a different way, or why. I do have some questions to understand these changes better
| ("-faulttype", Arg.Bool (fun b -> ft := b), | ||
| Printf.sprintf | ||
| "<bool> consider fault types, default %b" !ft); | ||
| "<bool> consider fault types in comparisons, default %b" !ft) |
There was a problem hiding this comment.
Please bear with me for a minute. I'm trying to understand the reason why is this PR changing the code is changing, and I'm confused regarding the relation between parsing a boolean argument and the module "checkName".
From what I understand this module was made to parse names of litmus tests coming from user-provided CLI arguments.
What's has this with parsing the faults?
There was a problem hiding this comment.
The module "CheckName" functionality is to select the input tests. It includes the definition of command line options such as -names, -excl etc. The place looked convenient to host other command line definitions that are common to several tools (-int32 for instance). This is a mistake and it sould be fixed, perhaps not in this PR?
There was a problem hiding this comment.
This is a mistake and it sould be fixed, perhaps not in this PR?
Absolutely, I've seen other modules for handling args, so it might make sense to consolidate the code into a single module or something like that.
| then | ||
| Printf.eprintf "Found heterogeneous test %s\n%!" name ; | ||
| if FaultKinds.equal fk1 fk2 | ||
| then opt xs ys |
There was a problem hiding this comment.
Is the opt diffing safe to use when both tests are not homogeneous with regards to the fault kinds, even when these are equal?
There was a problem hiding this comment.
I guess not. I had assumed that outcomes with equal bindings have fault types of the same kind. There is no reason for this to be true. I'll fix it. Nice catch.
There was a problem hiding this comment.
I think union_faults solves it nicely now
There was a problem hiding this comment.
Well, some work still under way. I have decided to have a proper compare function on faults that will distinguish fauts syntactically, as correct hashconsing of states rely on it. That some syntactically different faults are the same will be handled in a more explicit way, by a equivalent function.
There was a problem hiding this comment.
Well, some work still under way. I have decided to have a proper compare function on faults that will distinguish fauts syntactically, as correct hashconsing of states rely on it. That some syntactically different faults are the same will be handled in a more explicit way, by a
equivalentfunction.
@maranget I don't see these changes reflected in the PR, so just wanted to check whether you are still planning to work on this, or if you think this PR is ready for re-review.
I am surprised too. Maybe the |
7465906 to
d476ff0
Compare
d476ff0 to
fba068e
Compare
be78c39 to
1fdbc1e
Compare
There was a problem hiding this comment.
I think we should add a few more cases to this test. In particular, the current cram test does not exercise the new -mmu-faults-as-data flag in the false case. In would appear that mcompare7 and mcmp7 disagree under -mmu-faults-as-data false, which I don't think is intended:
$ cat old.log
Test T Allowed
States 1
~Fault(P0:L0,x,MMU:Translation);
Ok
Hash=x
$ cat new.log
Test T Allowed
States 1
~Fault(P0:L0,x,D-MMU:Translation);
Ok
Hash=x
$ dune exec mcompare7 -- -mmu-faults-as-data false old.log new.log
*Diffs*
|Kind | old.log new.log
--------------------------------------------------
--------------------------------------------------
T|Allow| [~fault(P0:L0,x,MMU:Translation)] ==
|Ok |
$ dune exec mcmp7 -- -mmu-faults-as-data false old.log new.log
TThere was a problem hiding this comment.
Interesting. If I am not wrong mcompare7 ignores negative fault occurrences. The fast path of mcmp7 does not ignore them, as it relies on hashedconsed identity nodes to perform comparisons.
There was a problem hiding this comment.
Well, if mcompare7 ignore negative fault occurrences, mcmp7 can also ignore them, by simply not inserting them in its internal data structure. I'll implement this technique.
d9fd7f6 to
a703b50
Compare
|
Here is a copy of a comment that might otherwise get lost. I had overwritten significant changes changes by an untimely "git push --force". Namely I have separated the ordering of state llnes (or outcomes) and the equivalence of faults. They are now present again. See here for the definitions of the |
|
Hi @psafont and @relokin (and maybe @artkhyzha, I guess you have been involved in adding the "D-" and "I-" prefixes) . This PR experienced many adventures, resulting in partial and total rewrites. Things went far beyond to where I initially expected: fixing the compare tools so that I can compare new herd vmsa logs to old logs from before the introduction of the "D-" and "I-" prefixes... Thanks to all the remarks and suggestions that have been made, the situation of log comparisions is now much cleaner than before: from series of fixes to the clear understanding that we cannot totally order the lines of a test log, especially when those logs have been recorded at different times. But the compare tools must still evolve now. I'd really like to have your informed opinion once more before merging. |
a703b50 to
419ad69
Compare
| let datafault_key = "-mmu-faults-as-data" | ||
|
|
||
| let parse_datafault ft = | ||
| (datafault_key, Arg.Bool (fun b -> ft := b), | ||
| Printf.sprintf |
There was a problem hiding this comment.
I think this is fine but also not necessary, all old logs that said MMU:<type> should match with D-MMU:<type>. I don't see a situation where we would set the parameter to false.
There was a problem hiding this comment.
Hi @relokin. I agree with you that MMU: in old logs most certainly refer to D-MMU:. Setting the switch "-mmu-faults-as-data" to false may help debugging by having the internal functions to operate on stuctures as close as possible to the input.
| let equivalent_ftype_names s1 s2 = | ||
| match strip_diprefix s1,strip_diprefix s2 with | ||
| | None,Some s2 -> String.equal s1 s2 | ||
| | Some s1,None -> String.equal s1 s2 | ||
| | _,_ -> String.equal s1 s2 |
There was a problem hiding this comment.
Maybe I have misunderstood this, but wouldn't we want to just change D-MMU to MMU for backwards compatibility but maintain I-MMU?
There was a problem hiding this comment.
This would contradict the intuitive meaning of faults in final conditions. For instance exists Fault(..,..,MMU:Permission) is intuitively understood as: "there exists a permission fault, would it be from data or instruction". This "intuitive" semantics already governs the behaviour of herd7, while PR #1988 adjusts litmus7.
I mean I saw no reason for tools and herd7 to interpret prefixless MMU fault types differently. Given our hypothesis on old logs tests generating only "D-MMU:..." faults, there should be no practical implications for log comparisons and sums.
419ad69 to
c5f8eea
Compare
MMU fault types have been prefixed with "D-" or "I-" (PR #1518). This commit ignores such prefixes in comparisons of final states and select the prefixed names for unions. The tools that read logs such as **mcompare7** and **msum7** should now be able to handle new and old logs to compare and sum them. Let us defined "states" as lists of outcomes, an outcome being a list of final location values, faults and fault absence. For instance: ``` 0:x0=1; [x]=1; Fault(P0:L0,D-MMU:Permission); ~Fault(P1:L1,y); ``` Given the change of format of faults over time, it cannot be guaranted that list of outcomes are totally ordered. As a consequent the traditional linear algorithm on sorted list cannot be trusted. However, location bindings are totally ordered. Hence, we can group states that are identical up to faults, apply the linear algorithms at this level and apply the naive, quadratic algorithms, to those groups of states with identical bindings. For instance consider aggregating (unioning): ``` [x]=0; ~Fault(P0); ~Fault(P1); [x]=1; Fault(P0,x,D-MMU:Permission); ~Fault(P1,x); [x]=1; Fault(P0,x,D-MMU:Permission); Fault(P1,x,D-MMU:Translation); ``` and the old, without fault types, log: ``` [x]=1; Fault(P0,x); ~Fault(P1,x); [x]=1; Fault(P0,x); Fault(P1,x); [x]=1; ~Fault(P0,x); Fault(P1,x); [x]=2; Fault(P0); ~Fault(P1); ``` The `[x]=0;...` and `[x]=2;...` find their way to the result by the sole comparison of their binding components. By contrast the `[x]=1;...` outcomes undergo pairwise comparisons, resulting in the three outcomes: ``` [x]=1; Fault(P0,x,D-MMU:Permission); ~Fault(P1,x); [x]=1; Fault(P0,x,D-MMU:Permission); Fault(P1,x,D-MMU:Translation); [x]=1; ~Fault(P0,x); Fault(P1,x); ``` Notice that, when possible, the newer and more precise ouctome is selected We also add a new option `-mmu-faults-as-data <bool>` When true (default), all MMU faults that are not prefixed by "D-" or "I-" are considered to be from data. That is, the names of faults that start with "MMU:" are implicitly prefixed with "D-". This treatement of old logs is not strictly necessary. It offers a simple solution to the "new prefixes" problem though.
c5f8eea to
c1e4ae6
Compare
[tools] Fix bug in state comparison Very unfortunate error in implementing the difference of two sorted lists, introduced by PR #1970.
The printing of faults has changed over time:
Tools that compare or compute on logs , such as mcompare7 and msum7 are impacted. It is always possible to use the
-faulttype falseoption to ignore fault types for tools to produce correct results.However those results are not as precise as they should. This PR is an attempt to fix the problem by:
-mmu-faults-as-data true).Notice that the default for all tools are
-faulttype true mmu-faults-as-data true.