Beispiel #1
0
void OutputInputs(ostream &os, const ASTNode& n, hash_set<int> *alreadyOutput)
{
	if (alreadyOutput->find(n.GetNodeNum()) != alreadyOutput->end())
		return;

	alreadyOutput->insert(n.GetNodeNum());

	if (n.GetKind() == BVGETBIT)
	{
		assert(n[1].GetKind() == BVCONST);
		std::stringstream nn;
		n[0].nodeprint(nn);
		nn << "_" << bvconstToString(n[1]);
		os << "INPUT(" << nn.str() << ")" << endl;
		return;
	}

	// A boolean symbol.
	if (n.GetKind() == SYMBOL)
	{
		os << "INPUT(" << symbolToString(n) << ")" << endl;
		return;
	}

	for (unsigned i = 0; i < n.Degree(); i++)
	{
		OutputInputs(os, n[i], alreadyOutput);
	}
}
Beispiel #2
0
bool VariablesInExpression::VarSeenInTerm(const ASTNode& var,
		const ASTNode& term) {
	// This only returns true if we are searching for variables that aren't arrays.
	assert(var.GetKind() == SYMBOL && var.GetIndexWidth() == 0);
	if (term.isConstant())
		return false;

	getSymbol(term);

	SymbolPtrSet visited;
	ASTNodeSet *symbols = new ASTNodeSet();
	vector<Symbols*> av;
	VarSeenInTerm(symbol_graph[term.GetNodeNum()], visited, *symbols, av);

	bool result = (symbols->count(var) != 0);

	//cerr << "visited:" << visited.size() << endl;
	//cerr << "av:" << av.size() << endl;
	//cerr << "Term is const" << term.isConstant() << endl;


	if (visited.size() > 250) // No use caching it, unless we've done some work.
	{
		sort(av.begin(), av.end());

		//cout << "===" << endl;
		for (size_t i = 0; i < av.size(); i++) {
			if (i!=0 && av[i] == av[i-1])
				continue;

			const ASTNodeSet& sym = *TermsAlreadySeenMap.find(av[i])->second;
			//cout << "set: " << i << " " << sym.size() << endl;
			symbols->insert(sym.begin(), sym.end());
		}
		TermsAlreadySeenMap.insert(make_pair(symbol_graph[term.GetNodeNum()], symbols));
		//cout << "finish" << symbols->size() << endl;
		//cout << "===" << endl;
		result = (symbols->count(var) != 0);
	} else {
		const int size = av.size();
		for (int i = 0; i < size; i++) {
			if (result)
				break;
			const ASTNodeSet& sym = *TermsAlreadySeenMap.find(av[i])->second;
			result |= (sym.find(var) != sym.end());
		}
		delete symbols;
	}
	return result;
}
Beispiel #3
0
void CNFMgr::doRenamingNeg(const ASTNode& varphi, ClauseList* defs)
{
    CNFInfo* x = info[varphi];

    //########################################
    // step 2, calc new variable
    //########################################

    ostringstream oss;
    oss << "cnf" << "{" << varphi.GetNodeNum() << "}";
    ASTNode psi = bm->CreateSymbol(oss.str().c_str(),0,0);

    //########################################
    // step 3, add defs
    //########################################

    ASTNode* copy = ASTNodeToASTNodePtr(psi);
    ClauseList* cl = info[varphi]->clausesneg;
    cl->appendToAllClauses(copy);
    defs->insert(cl);
    delete cl;

    //########################################
    // step 4, update info[varphi]
    //########################################

    x->clausesneg = SINGLETON(bm->CreateNode(NOT, psi));
    setWasRenamedNeg(*x);
} //End of doRenamingNeg()
Beispiel #4
0
void CNFMgr::doRenamingPosXor(const ASTNode& varphi)
{
    CNFInfo* x = info[varphi];

    //########################################
    // step 1, calc new variable
    //########################################

    ostringstream oss;
    oss << "cnf" << "{" << varphi.GetNodeNum() << "}";
    ASTNode psi = bm->CreateSymbol(oss.str().c_str(),0,0);

    //########################################
    // step 2, add defs
    //########################################

    //     ClauseList* cl1;
    //     cl1 = SINGLETON(bm->CreateNode(NOT, psi));
    //     ClauseList* cl2 = PRODUCT(*(info[varphi]->clausespos), *cl1);
    //     defs->insert(defs->end(), cl2->begin(), cl2->end());
    //     DELETE(info[varphi]->clausespos);
    //     DELETE(cl1);
    //     delete cl2;

    //########################################
    // step 3, update info[varphi]
    //########################################

    x->clausespos = SINGLETON(psi);
    x->clausesneg = SINGLETON(bm->CreateNode(NOT, psi));
    setWasRenamedPos(*x);
}//End of doRenamingPos
Beispiel #5
0
  void Dot_Print1(ostream &os, const ASTNode n, hash_set<int> *alreadyOutput)
  {

    // check if this node has already been printed. If so return.
    if (alreadyOutput->find(n.GetNodeNum()) != alreadyOutput->end())
      return;

    alreadyOutput->insert(n.GetNodeNum());

    os << "n" << n.GetNodeNum() << "[label =\"";
    switch (n.GetKind())
      {
      case SYMBOL:
        n.nodeprint(os);
        break;

      case BITVECTOR:
      case BVCONST:
        outputBitVec(n, os);
        break;

      default:
        os << _kind_names[n.GetKind()];
      }

    os << "\"];" << endl;

    // print the edges to each child.
    ASTVec ch = n.GetChildren();
    ASTVec::iterator itend = ch.end();
    int i = 0;
    for (ASTVec::iterator it = ch.begin(); it < itend; it++)
      {
        os << "n" << n.GetNodeNum() 
           << " -> " << "n" 
           << it->GetNodeNum() 
           << "[label=" << i++ 
           << "];" << endl;
      }

    // print each of the children.
    for (ASTVec::iterator it = ch.begin(); it < itend; it++)
      {
        Dot_Print1(os, *it, alreadyOutput);
      }
  }
bool containsArrayOps(const ASTNode& n, hash_set<int> & visited)
{
        if (n.GetIndexWidth() > 0)
            return true;

        if (n.Degree() ==0)
            return false;

        if (visited.find(n.GetNodeNum()) != visited.end())
            return false;

        visited.insert(n.GetNodeNum());

	for (int i =0; i < n.Degree();i++)
		if (containsArrayOps(n[i],visited))
			return true;

	return false;
}
Beispiel #7
0
// counts the number of reads. Shortcut when we get to the limit.
void numberOfReadsLessThan(const ASTNode& n, hash_set<int>& visited, int& soFar,
                           const int limit)
{
  if (n.isAtom())
    return;

  if (visited.find(n.GetNodeNum()) != visited.end())
    return;

  if (n.GetKind() == READ)
    soFar++;

  if (soFar > limit)
    return;

  visited.insert(n.GetNodeNum());

  for (size_t i = 0; i < n.Degree(); i++)
    numberOfReadsLessThan(n[i], visited, soFar, limit);
}
  // This is for sorting by arithmetic expressions (for
  // combining like terms, etc.)
  bool arithless(const ASTNode n1, const ASTNode n2)
  {
    Kind k1 = n1.GetKind();
    Kind k2 = n2.GetKind();

    if (n1 == n2)
      {
        // necessary for "strict weak ordering"
        return false;
      }
    else if (BVCONST == k1 && BVCONST != k2)
      {
        // put consts first
        return true;
      }
    else if (BVCONST != k1 && BVCONST == k2)
      {
        // put consts first
        return false;
      }
    else if (SYMBOL == k1 && SYMBOL != k2)
      {
        // put symbols next
        return true;
      }
    else if (SYMBOL != k1 && SYMBOL == k2)
      {
        // put symbols next
        return false;
      }
    else
      {
        // otherwise, sort by exprnum (descendents will appear
        // before ancestors).
        return (n1.GetNodeNum() < n2.GetNodeNum());
      }
  } //end of arithless
Beispiel #9
0
// If n0 is replaced by n1 in the substitution map. Will it cause a loop?
// i.e. will the dependency graph be an acyclic graph still.
// For example, if we have x = F(y,z,w), it would make the substitutionMap loop
// if there's already z = F(x).
bool SubstitutionMap::loops(const ASTNode& n0, const ASTNode& n1)
{
  if (n0.GetKind() != SYMBOL)
    return false; // sometimes this function is called with constants on the
                  // lhs.

  if (n1.isConstant())
    return false; // constants contain no variables. Can't loop.

  // We are adding an edge FROM n0, so unless there is already an edge TO n0,
  // there is no change it can loop. Unless adding this would add a TO and FROM
  // edge.
  if (rhs.find(n0) == rhs.end())
  {
    return vars.VarSeenInTerm(n0, n1);
  }

  if (n1.GetKind() == SYMBOL && dependsOn.find(n1) == dependsOn.end())
    return false; // The rhs is a symbol and doesn't appear.

  if (debug_substn)
    cout << loopCount++ << endl;

  bool destruct = true;
  ASTNodeSet* dependN = vars.SetofVarsSeenInTerm(n1, destruct);

  if (debug_substn)
  {
    cout << n0 << " "
         << n1.GetNodeNum(); //<< " Expression size:" << bm->NodeSize(n1,true);
    cout << "Variables in expression: " << dependN->size() << endl;
  }

  set<ASTNode> depend(dependN->begin(), dependN->end());

  if (destruct)
    delete dependN;

  set<ASTNode> visited;
  loops_helper(depend, visited);

  bool loops = visited.find(n0) != visited.end();

  if (debug_substn)
    cout << "Visited:" << visited.size() << "Loops:" << loops << endl;

  return (loops);
}
Beispiel #10
0
void VariablesInExpression::insert(const ASTNode& n, Symbols *s)
{
	assert (s!= NULL);
	symbol_graph.insert(std::make_pair(n.GetNodeNum(), s));
}
 // Sort ASTNodes by expression numbers
 bool exprless(const ASTNode n1, const ASTNode n2)
 {
   return (n1.GetNodeNum() < n2.GetNodeNum());
 }
Beispiel #12
0
string Bench_Print1(ostream &os, const ASTNode& n,
		map<ASTNode, string> *alreadyOutput)
{

	assert(((n.GetKind() == SYMBOL) || (n.GetKind() == BVCONST) || n.GetValueWidth() <= 1));
	assert(!n.IsNull());

	map<ASTNode, string>::iterator it;
	if ((it = alreadyOutput->find(n)) != alreadyOutput->end())
		return it->second;

	if (n.GetKind() == BVCONST)
	{
		(*alreadyOutput)[n] = bvconstToString(n);
		return (*alreadyOutput)[n];
	}

	if (n.GetKind() == SYMBOL)
	{
		(*alreadyOutput)[n] = symbolToString(n);
		return (*alreadyOutput)[n];
	}

	if (n.GetKind() == TRUE)
		{
		return "vdd";
		}

	if (n.GetKind() == FALSE)
		{
		return "gnd";
		}

	if (n.GetKind() == BVGETBIT)
	{
		assert(n[1].GetKind() == BVCONST);
		std::stringstream nn;
		nn << Bench_Print1(os, n[0], alreadyOutput) << "_" << Bench_Print1(os, n[1], alreadyOutput);
		(*alreadyOutput)[n] = nn.str();
		return (*alreadyOutput)[n];
	}

	std::stringstream nodeNameSS;
	nodeNameSS << "n" << n.GetNodeNum();

	string thisNode = nodeNameSS.str();
	(*alreadyOutput)[n] = thisNode;

	assert(n.Degree() > 0);
	std::stringstream output;

	// The bench format doesn't accept propositional ITEs.
	if (n.GetKind() == ITE)
	{
		assert(n.Degree() == 3);
		string p = Bench_Print1(os, n[0], alreadyOutput);
		string p1 = Bench_Print1(os, n[1], alreadyOutput);
		string p2 = Bench_Print1(os, n[2], alreadyOutput);

		os << thisNode << "_1 = AND(" << p << "," << p1 << ")" << endl;
		os << thisNode << "_2" << " = NOT(" << p << ")," << endl;
		os << thisNode << "_3" << " = AND(" << thisNode << "_2"
				<< "," << p2 << ")" << endl;
		os << thisNode << "=" << "OR(," << thisNode << "_1" << ","
				<< thisNode << "_3)" << endl;
	}
	else
	{
		if (n.Degree() > 2)
		{
			assert(n.GetKind() == AND || n.GetKind() == XOR || n.GetKind() == OR); // must be associative.
			std::deque<string> names;

			for (unsigned i = 0; i < n.Degree(); i++)
				names.push_back(Bench_Print1(os, n[i], alreadyOutput));

			int id = 0;

			while (names.size() > 2)
			{
				string a = names.front();
				names.pop_front();

				string b = names.front();
				names.pop_front();

				std::stringstream thisName;
				thisName << thisNode << "___" << id++;

				output << thisName.str() << "=" << name(n.GetKind()) << "("
						<< a << "," << b << ")" << endl;

				names.push_back(thisName.str());
			}

			assert(names.size() == 2);
			// last two now.

			string a = names.front();
			names.pop_front();
			string b = names.front();
			names.pop_front();

			output << thisNode << "=" << name(n.GetKind()) << "(" << a
					<< "," << b << ")" << endl;
			os << output.str();
		}
		else
		{
			output << thisNode << "=" << name(n.GetKind()) << "(";
			for (unsigned i = 0; i < n.Degree(); i++)
			{
				if (i >= 1)
					output << " , ";
				output << Bench_Print1(os, n[i], alreadyOutput);

			}
			os << output.str() << ")" << endl;
		}
	}
	return thisNode;
}
Beispiel #13
0
void GDL_Print1(ostream& os, const ASTNode& n, hash_set<int>* alreadyOutput,
                string (*annotate)(const ASTNode&))
{
  // check if this node has already been printed. If so return.
  if (alreadyOutput->find(n.GetNodeNum()) != alreadyOutput->end())
    return;

  alreadyOutput->insert(n.GetNodeNum());

  os << "node: { title:\"n" << n.GetNodeNum() << "\" label: \"";
  switch (n.GetKind())
  {
    case SYMBOL:
      n.nodeprint(os);
      break;

    case BITVECTOR:
    case BVCONST:
      outputBitVec(n, os);
      break;

    default:
      os << _kind_names[n.GetKind()];
  }

  os << annotate(n);
  os << "\"}" << endl;

  // print the edges to each child.
  const ASTVec ch = n.GetChildren();
  const ASTVec::const_iterator itend = ch.end();

  // If a node has the child 'TRUE' twice, we only want to output one TRUE node.
  ASTNodeSet constantOutput;

  int i = 0;
  for (ASTVec::const_iterator it = ch.begin(); it < itend; it++)
  {
    std::stringstream label;

    if (!isCommutative(n.GetKind()))
      label << " label:\"" << i << "\"";

    if (it->isConstant())
    {
      std::stringstream ss;
      ss << n.GetNodeNum() << "_" << it->GetNodeNum();

      if (constantOutput.end() == constantOutput.find(*it))
      {
        os << "node: { title:\"n";

        os << ss.str() << "\" label: \"";
        if (it->GetType() == BEEV::BOOLEAN_TYPE)
          os << _kind_names[it->GetKind()];
        else
          outputBitVec(*it, os);
        os << "\"}" << endl;
        constantOutput.insert(*it);
      }

      os << "edge: { source:\"n" << n.GetNodeNum() << "\" target: \""
         << "n" << ss.str() << "\"" << label.str() << "}" << endl;
    }
    else
      os << "edge: { source:\"n" << n.GetNodeNum() << "\" target: \""
         << "n" << it->GetNodeNum() << "\"" << label.str() << "}" << endl;
    i++;
  }

  // print each of the children.
  for (ASTVec::const_iterator it = ch.begin(); it < itend; it++)
  {
    if (!it->isConstant())
      GDL_Print1(os, *it, alreadyOutput, annotate);
  }
}
// This doesn't rewrite changes through properly so needs to have a substitution
// applied to its output.
ASTNode PropagateEqualities::propagate(const ASTNode& a, ArrayTransformer* at)
{
  ASTNode output;
  // if the variable has been solved for, then simply return it
  if (simp->InsideSubstitutionMap(a, output))
    return output;

  if (!alreadyVisited.insert(a.GetNodeNum()).second)
  {
    return a;
  }

  output = a;

  // traverse a and populate the SubstitutionMap
  const Kind k = a.GetKind();
  if (SYMBOL == k && BOOLEAN_TYPE == a.GetType())
  {
    bool updated = simp->UpdateSubstitutionMap(a, ASTTrue);
    output = updated ? ASTTrue : a;
  }
  else if (NOT == k)
  {
    bool updated = searchXOR(a[0], ASTFalse);
    output = updated ? ASTTrue : a;
  }
  else if (IFF == k || EQ == k)
  {
    const ASTVec& c = a.GetChildren();

    if (c[0] == c[1])
      return ASTTrue;

    bool updated = simp->UpdateSubstitutionMap(c[0], c[1]);

    if (updated)
    {
      // fill the arrayname readindices vector if e0 is a
      // READ(Arr,index) and index is a BVCONST
      int to;
      if ((to = TermOrder(c[0], c[1])) == 1 && c[0].GetKind() == READ)
        at->FillUp_ArrReadIndex_Vec(c[0], c[1]);
      else if (to == -1 && c[1].GetKind() == READ)
        at->FillUp_ArrReadIndex_Vec(c[1], c[0]);
    }

    if (!updated)
      updated = searchTerm(c[0], c[1]);

    if (!updated)
      updated = searchTerm(c[1], c[0]);

    output = updated ? ASTTrue : a;
  }
  else if (XOR == k)
  {
    bool updated = searchXOR(a, ASTTrue);
    output = updated ? ASTTrue : a;

    if (updated)
      return output;

// The below block should be subsumed by the searchXOR function which
// generalises it.
// So the below block should never do anything..
#ifndef NDEBUG
    if (a.Degree() != 2)
      return output;

    int to = TermOrder(a[0], a[1]);
    if (0 == to)
    {
      if (a[0].GetKind() == NOT && a[0][0].GetKind() == EQ &&
          a[0][0][0].GetValueWidth() == 1 && a[0][0][1].GetKind() == SYMBOL)
      {
        // (XOR (NOT(= (1 v)))  ... )
        const ASTNode& symbol = a[0][0][1];
        const ASTNode newN = nf->CreateTerm(
            ITE, 1, a[1], a[0][0][0], nf->CreateTerm(BVNEG, 1, a[0][0][0]));

        if (simp->UpdateSolverMap(symbol, newN))
        {
          assert(false);
          output = ASTTrue;
        }
      }
      else if (a[1].GetKind() == NOT && a[1][0].GetKind() == EQ &&
               a[1][0][0].GetValueWidth() == 1 &&
               a[1][0][1].GetKind() == SYMBOL)
      {
        const ASTNode& symbol = a[1][0][1];
        const ASTNode newN = nf->CreateTerm(
            ITE, 1, a[0], a[1][0][0], nf->CreateTerm(BVNEG, 1, a[1][0][0]));

        if (simp->UpdateSolverMap(symbol, newN))
        {
          assert(false);
          output = ASTTrue;
        }
      }
      else if (a[0].GetKind() == EQ && a[0][0].GetValueWidth() == 1 &&
               a[0][1].GetKind() == SYMBOL)
      {
        // XOR ((= 1 v) ... )

        const ASTNode& symbol = a[0][1];
        const ASTNode newN = nf->CreateTerm(
            ITE, 1, a[1], nf->CreateTerm(BVNEG, 1, a[0][0]), a[0][0]);

        if (simp->UpdateSolverMap(symbol, newN))
        {
          assert(false);
          output = ASTTrue;
        }
      }
      else if (a[1].GetKind() == EQ && a[1][0].GetValueWidth() == 1 &&
               a[1][1].GetKind() == SYMBOL)
      {
        const ASTNode& symbol = a[1][1];
        const ASTNode newN = nf->CreateTerm(
            ITE, 1, a[0], nf->CreateTerm(BVNEG, 1, a[1][0]), a[1][0]);

        if (simp->UpdateSolverMap(symbol, newN))
        {
          assert(false);
          output = ASTTrue;
        }
      }
      else
        return output;
    }
    else
    {
      ASTNode symbol, rhs;
      if (to == 1)
      {
        symbol = a[0];
        rhs = a[1];
      }
      else
      {
        symbol = a[1];
        rhs = a[0];
      }

      assert(symbol.GetKind() == SYMBOL);

      if (simp->UpdateSolverMap(symbol, nf->CreateNode(NOT, rhs)))
      {
        assert(false);
        output = ASTTrue;
      }
    }
#endif
  }
  else if (AND == k)
  {
    const ASTVec& c = a.GetChildren();
    ASTVec o;
    o.reserve(c.size());

    for (ASTVec::const_iterator it = c.begin(), itend = c.end(); it != itend;
         it++)
    {
      if (always_true)
        simp->UpdateAlwaysTrueFormSet(*it);
      ASTNode aaa = propagate(*it, at);

      if (ASTTrue != aaa)
      {
        if (ASTFalse == aaa)
          return ASTFalse;
        else
          o.push_back(aaa);
      }
    }
    if (o.size() == 0)
      output = ASTTrue;
    else if (o.size() == 1)
      output = o[0];
    else if (o != c)
      output = nf->CreateNode(AND, o);
    else
      output = a;
  }

  return output;
}