use of com.dat3m.dartagnan.wmm.utils.Tuple in project Dat3M by hernanponcedeleon.
the class RelMinus method encodeApprox.
@Override
protected BooleanFormula encodeApprox(SolverContext ctx) {
BooleanFormulaManager bmgr = ctx.getFormulaManager().getBooleanFormulaManager();
BooleanFormula enc = bmgr.makeTrue();
TupleSet min = getMinTupleSet();
for (Tuple tuple : encodeTupleSet) {
if (min.contains(tuple)) {
enc = bmgr.and(enc, bmgr.equivalence(this.getSMTVar(tuple, ctx), getExecPair(tuple, ctx)));
continue;
}
BooleanFormula opt1 = r1.getSMTVar(tuple, ctx);
BooleanFormula opt2 = bmgr.not(r2.getSMTVar(tuple, ctx));
if (Relation.PostFixApprox) {
enc = bmgr.and(enc, bmgr.implication(bmgr.and(opt1, opt2), this.getSMTVar(tuple, ctx)));
} else {
enc = bmgr.and(enc, bmgr.equivalence(this.getSMTVar(tuple, ctx), bmgr.and(opt1, opt2)));
}
}
return enc;
}
use of com.dat3m.dartagnan.wmm.utils.Tuple in project Dat3M by hernanponcedeleon.
the class BasicRegRelation method doEncodeApprox.
BooleanFormula doEncodeApprox(Collection<Event> regReaders, SolverContext ctx) {
FormulaManager fmgr = ctx.getFormulaManager();
BooleanFormulaManager bmgr = fmgr.getBooleanFormulaManager();
BooleanFormula enc = bmgr.makeTrue();
ImmutableMap<Register, ImmutableList<Event>> regWriterMap = task.getProgram().getCache().getRegWriterMap();
for (Event regReader : regReaders) {
Set<Tuple> writerReaders = maxTupleSet.getBySecond(regReader);
for (Register register : getRegisters(regReader)) {
List<Event> writers = regWriterMap.getOrDefault(register, ImmutableList.of());
List<Event> possibleWriters = writers.stream().filter(x -> writerReaders.contains(new Tuple(x, regReader))).collect(Collectors.toList());
if (writers.isEmpty() || writers.get(0).getCId() >= regReader.getCId()) {
BooleanFormula equal = generalEqual(register.toIntFormula(regReader, ctx), new IValue(BigInteger.ZERO, register.getPrecision()).toIntFormula(ctx), ctx);
enc = bmgr.and(enc, equal);
} else {
for (int i = 0; i < possibleWriters.size(); i++) {
Event regWriter = possibleWriters.get(i);
// RegReader uses the value of RegWriter if it is executed ..
BooleanFormula clause = getExecPair(regWriter, regReader, ctx);
BooleanFormula edge = this.getSMTVar(regWriter, regReader, ctx);
// .. and no other write to the same register is executed in between
for (int j = i + 1; j < possibleWriters.size(); j++) {
clause = bmgr.and(clause, bmgr.not(possibleWriters.get(j).exec()));
}
// Encode edge and value binding
enc = bmgr.and(enc, bmgr.equivalence(edge, clause));
BooleanFormula equal = generalEqual(((RegWriter) regWriter).getResultRegisterExpr(), register.toIntFormula(regReader, ctx), ctx);
enc = bmgr.and(enc, bmgr.implication(edge, equal));
}
}
}
}
return enc;
}
use of com.dat3m.dartagnan.wmm.utils.Tuple in project Dat3M by hernanponcedeleon.
the class BasicRegRelation method mkTupleSets.
void mkTupleSets(Collection<Event> regReaders) {
maxTupleSet = new TupleSet();
minTupleSet = new TupleSet();
ExecutionAnalysis exec = analysisContext.requires(ExecutionAnalysis.class);
ImmutableMap<Register, ImmutableList<Event>> regWriterMap = task.getProgram().getCache().getRegWriterMap();
for (Event regReader : regReaders) {
for (Register register : getRegisters(regReader)) {
List<Event> writers = regWriterMap.getOrDefault(register, ImmutableList.of());
// =============== Reduce set of writes ==================
// TODO: We assume that any Register-Write is always executed
// if it is contained in the program flow
// This may fail for RMWReadCond?! It seems to work fine for the litmus tests though.
// =========================
List<Event> possibleWriters = writers.stream().filter(x -> x.getCId() < regReader.getCId() && !exec.areMutuallyExclusive(x, regReader)).collect(Collectors.toList());
List<Event> impliedWriters = possibleWriters.stream().filter(x -> exec.isImplied(regReader, x)).collect(Collectors.toList());
if (!impliedWriters.isEmpty()) {
Event lastImplied = impliedWriters.get(impliedWriters.size() - 1);
possibleWriters.removeIf(x -> x.getCId() < lastImplied.getCId());
}
possibleWriters.removeIf(x -> possibleWriters.stream().anyMatch(y -> x.getCId() < y.getCId() && exec.isImplied(x, y)));
// --- Min sets ---
if (possibleWriters.size() == 1) {
// there is only a single regWriter
minTupleSet.add(new Tuple(possibleWriters.stream().findAny().get(), regReader));
} else {
// there are multiple regWriters, but some are exclusive to all others
for (Event writer : possibleWriters) {
if (possibleWriters.stream().allMatch(x -> x == writer || exec.areMutuallyExclusive(x, writer))) {
minTupleSet.add(new Tuple(writer, regReader));
}
}
}
// --- Max sets ---
for (Event regWriter : possibleWriters) {
maxTupleSet.add(new Tuple(regWriter, regReader));
}
}
}
}
use of com.dat3m.dartagnan.wmm.utils.Tuple in project Dat3M by hernanponcedeleon.
the class PropertyEncoder method encodeLiveness.
public BooleanFormula encodeLiveness(SolverContext ctx) {
// Further, we assume that the spinloops are indeed correct, i.e., side-effect free
class SpinLoop {
public List<Load> loads = new ArrayList<>();
public Event bound;
}
logger.info("Encoding liveness");
Map<Thread, List<SpinLoop>> spinloopsMap = new HashMap<>();
// Find spinloops of all threads
for (Thread t : program.getThreads()) {
List<Event> spinStarts = t.getEvents().stream().filter(e -> e instanceof Label && e.is(Tag.SPINLOOP)).collect(Collectors.toList());
List<SpinLoop> spinLoops = new ArrayList<>();
spinloopsMap.put(t, spinLoops);
for (Event start : spinStarts) {
SpinLoop loop = new SpinLoop();
Event cur = start.getSuccessor();
while (!cur.is(Tag.SPINLOOP)) {
if (cur.is(Tag.READ)) {
loop.loads.add((Load) cur);
}
cur = cur.getSuccessor();
}
loop.bound = cur;
spinLoops.add(loop);
}
}
BooleanFormulaManager bmgr = ctx.getFormulaManager().getBooleanFormulaManager();
RelRf rf = (RelRf) memoryModel.getRelationRepository().getRelation(RelationNameRepository.RF);
RelCo co = (RelCo) memoryModel.getRelationRepository().getRelation(RelationNameRepository.CO);
// Compute "stuckness": A thread is stuck if it reaches a spinloop bound event
// while reading from a co-maximal write.
Map<Thread, BooleanFormula> isStuckMap = new HashMap<>();
for (Thread t : program.getThreads()) {
List<SpinLoop> loops = spinloopsMap.get(t);
if (loops.isEmpty()) {
continue;
}
BooleanFormula isStuck = bmgr.makeFalse();
for (SpinLoop pair : loops) {
BooleanFormula allCoMaximalLoad = bmgr.makeTrue();
for (Load load : pair.loads) {
BooleanFormula coMaximalLoad = bmgr.makeFalse();
for (Tuple rfEdge : rf.getMaxTupleSet().getBySecond(load)) {
coMaximalLoad = bmgr.or(coMaximalLoad, bmgr.and(rf.getSMTVar(rfEdge, ctx), co.getLastCoVar(rfEdge.getFirst(), ctx)));
}
allCoMaximalLoad = bmgr.and(allCoMaximalLoad, coMaximalLoad);
}
isStuck = bmgr.or(isStuck, bmgr.and(pair.bound.exec(), allCoMaximalLoad));
}
isStuckMap.put(t, isStuck);
}
// LivenessViolation <=> allStuckOrDone /\ atLeastOneStuck
BooleanFormula allStuckOrDone = bmgr.makeTrue();
BooleanFormula atLeastOneStuck = bmgr.makeFalse();
for (Thread t : program.getThreads()) {
BooleanFormula isStuck = isStuckMap.getOrDefault(t, bmgr.makeFalse());
BooleanFormula isDone = t.getCache().getEvents(FilterBasic.get(Tag.BOUND)).stream().map(e -> bmgr.not(e.exec())).reduce(bmgr.makeTrue(), bmgr::and);
atLeastOneStuck = bmgr.or(atLeastOneStuck, isStuck);
allStuckOrDone = bmgr.and(allStuckOrDone, bmgr.or(isStuck, isDone));
}
// We use the SMT variable to extract from the model if the property was violated
BooleanFormula enc = bmgr.equivalence(LIVENESS.getSMTVariable(ctx), bmgr.and(allStuckOrDone, atLeastOneStuck));
return bmgr.and(LIVENESS.getSMTVariable(ctx), enc);
}
use of com.dat3m.dartagnan.wmm.utils.Tuple in project Dat3M by hernanponcedeleon.
the class SymmetryEncoder method sort.
private void sort(List<Tuple> row) {
if (!breakBySyncDegree) {
// ===== Natural order =====
row.sort(Comparator.naturalOrder());
return;
}
// ====== Sync-degree based order ======
// Setup of data structures
Set<Event> inEvents = new HashSet<>();
Set<Event> outEvents = new HashSet<>();
for (Tuple t : row) {
inEvents.add(t.getFirst());
outEvents.add(t.getSecond());
}
Map<Event, Integer> combInDegree = new HashMap<>(inEvents.size());
Map<Event, Integer> combOutDegree = new HashMap<>(outEvents.size());
List<Axiom> axioms = memoryModel.getAxioms();
for (Event e : inEvents) {
int syncDeg = axioms.stream().mapToInt(ax -> ax.getRelation().getMinTupleSet().getBySecond(e).size() + 1).max().orElse(0);
combInDegree.put(e, syncDeg);
}
for (Event e : outEvents) {
int syncDec = axioms.stream().mapToInt(ax -> ax.getRelation().getMinTupleSet().getByFirst(e).size() + 1).max().orElse(0);
combOutDegree.put(e, syncDec);
}
// Sort by sync degrees
row.sort(Comparator.<Tuple>comparingInt(t -> combInDegree.get(t.getFirst()) * combOutDegree.get(t.getSecond())).reversed());
}
Aggregations