Example #1
0
  /* The most complicated handling is for EXTRACTS. If a variable has parents that
 * are all extracts and each of those extracts is disjoint (i.e. reads different bits)
 * Then each of the extracts are replaced by a fresh variable. This is the only case
 * where a variable with multiple distinct parents is replaced by a fresh variable.
 * + We perform this check upfront, so will miss any extra cases the the unconstrained
 *   variable elimination introduces.
 * + It's all or nothing. So even if there's an extract of [0:2] [1:2] and [3:5], we wont
 *   replace the [3:5] (even though it could be).
 */
  void
  RemoveUnconstrained::splitExtractOnly(vector<MutableASTNode*> extracts)
  {
    assert(extracts.size() >0);

    // Going to be rebuilt later anyway, so discard.
    vector<MutableASTNode*> variables;

    for (int i =0; i <extracts.size(); i++)
      {
        ASTNode& var = extracts[i]->n;
        assert(var.GetKind() == SYMBOL);
        const int size = var.GetValueWidth();
        std::vector<ASTNode> toVar(size);

        // Create a mutable copy that we can iterate over.
        vector <MutableASTNode*> mut;
        mut.insert(mut.end(), extracts[i]->parents.begin(), extracts[i]->parents.end());

        for (vector<MutableASTNode*>::iterator it = mut.begin(); it != mut.end(); it++)
          {
            ASTNode parent_node = (*it)->n;
            assert(((**it)).children[0] == extracts[i]);
            assert(!parent_node.IsNull());
            assert(parent_node.GetKind() == BVEXTRACT);

            int lb = parent_node[2].GetUnsignedConst();
            // Replace each parent with a fresh.
            toVar[lb] = replaceParentWithFresh(**it,variables);
          }

      ASTVec concatVec;
      int empty =0;
      for (int j=0; j < size;j++)
      {
          if (toVar[j].IsNull())
            {
              empty++;
              continue;
            }

          if (empty > 0)
            {
              concatVec.push_back(bm.CreateFreshVariable(0, empty, "extract_unc"));
              empty = 0;
            }

          concatVec.push_back(toVar[j]);
          //cout << toVar[j];
          assert(toVar[j].GetValueWidth() > 0);
          j+=toVar[j].GetValueWidth()-1;
        }

      if (empty> 0)
        {
          concatVec.push_back(bm.CreateFreshVariable(0, empty, "extract_unc"));
        }

    ASTNode concat = concatVec[0];
    for (int i=1; i < concatVec.size();i++)
      {
          assert(!concat.IsNull());
          concat = bm.CreateTerm(BVCONCAT, concat.GetValueWidth() + concatVec[i].GetValueWidth(),concatVec[i], concat);
      }

    replace(var,concat);
        }
  }
Example #2
0
/********************************************************
 * TransformFormula()
 *
 * Get rid of DIV/MODs, ARRAY read/writes, FOR constructs
 ********************************************************/
ASTNode ArrayTransformer::TransformFormula(const ASTNode& simpleForm)
{
  assert(TransformMap != NULL);

  const Kind k = simpleForm.GetKind();
  if (!(is_Form_kind(k) && BOOLEAN_TYPE == simpleForm.GetType()))
  {
    // FIXME: "You have inputted a NON-formula"?
    FatalError("TransformFormula:"
               "You have input a NON-formula",
               simpleForm);
  }

  ASTNodeMap::const_iterator iter;
  if ((iter = TransformMap->find(simpleForm)) != TransformMap->end())
    return iter->second;

  ASTNode result;

  switch (k)
  {
    case TRUE:
    case FALSE:
    {
      result = simpleForm;
      break;
    }
    case NOT:
    {
      ASTVec c;
      c.push_back(TransformFormula(simpleForm[0]));
      result = nf->CreateNode(NOT, c);
      break;
    }
    case BOOLEXTRACT:
    {
      ASTVec c;
      c.push_back(TransformTerm(simpleForm[0]));
      c.push_back(simpleForm[1]);
      result = nf->CreateNode(BOOLEXTRACT, c);
      break;
    }
    case BVLT:
    case BVLE:
    case BVGT:
    case BVGE:
    case BVSLT:
    case BVSLE:
    case BVSGT:
    case BVSGE:
    {
      ASTVec c;
      c.push_back(TransformTerm(simpleForm[0]));
      c.push_back(TransformTerm(simpleForm[1]));
      result = nf->CreateNode(k, c);
      break;
    }
    case EQ:
    {
      ASTNode term1 = TransformTerm(simpleForm[0]);
      ASTNode term2 = TransformTerm(simpleForm[1]);
      if (bm->UserFlags.optimize_flag)
        result = simp->CreateSimplifiedEQ(term1, term2);
      else
        result = nf->CreateNode(EQ, term1, term2);
      break;
    }
    case AND: // These could shortcut. Not sure if the extra effort is
              // justified.
    case OR:
    case NAND:
    case NOR:
    case IFF:
    case XOR:
    case ITE:
    case IMPLIES:
    {
      ASTVec vec;
      vec.reserve(simpleForm.Degree());

      for (ASTVec::const_iterator it = simpleForm.begin(),
                                  itend = simpleForm.end();
           it != itend; it++)
      {
        vec.push_back(TransformFormula(*it));
      }

      result = nf->CreateNode(k, vec);
      break;
    }
    case PARAMBOOL:
    {
      // If the parameteric boolean variable is of the form
      // VAR(const), then convert it into a Boolean variable of the
      // form "VAR(const)".
      //
      // Else if the paramteric boolean variable is of the form
      // VAR(expression), then simply return it
      if (BVCONST == simpleForm[1].GetKind())
      {
        result = bm->NewParameterized_BooleanVar(simpleForm[0], simpleForm[1]);
      }
      else
      {
        result = simpleForm;
      }
      break;
    }
    default:
    {
      if (k == SYMBOL && BOOLEAN_TYPE == simpleForm.GetType())
        result = simpleForm;
      else
      {
        FatalError("TransformFormula: Illegal kind: ", ASTUndefined, k);
        std::cerr << "The input is: " << simpleForm << std::endl;
        std::cerr << "The valuewidth of input is : "
                  << simpleForm.GetValueWidth() << std::endl;
      }
      break;
    }
  }

  assert(!result.IsNull());
  if (simpleForm.Degree() > 0)
    (*TransformMap)[simpleForm] = result;
  return result;
} 
Example #3
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;
}
    // NB: This expects that the constructor was called with teh same node. Sorry.
    ASTNode
    ConstantBitPropagation::topLevelBothWays(const ASTNode& top)
    {
      assert(top.GetSTPMgr()->UserFlags.bitConstantProp_flag);
      assert (BOOLEAN_TYPE == top.GetType());

      propagate();
      status = NO_CHANGE;

      //Determine what must always be true.
      ASTNodeMap fromTo = getAllFixed();

      if (debug_cBitProp_messages)
        {
          cerr << "Number removed by bottom UP:" << fromTo.size() << endl;
        }

      setNodeToTrue(top);

      if (debug_cBitProp_messages)
        {
          cerr << "starting propagation" << endl;
          printNodeWithFixings();
          cerr << "Initial Tree:" << endl;
          cerr << top;
        }

      propagate();

      if (debug_cBitProp_messages)
        {
          cerr << "status:" << status <<endl;
          cerr << "ended propagation" << endl;
          printNodeWithFixings();
        }

      // propagate may have stopped with a conflict.
      if (CONFLICT == status)
          return top.GetSTPMgr()->CreateNode(FALSE);

      ASTVec toConjoin;

      // go through the fixedBits. If a node is entirely fixed.
      // "and" it onto the top. Creates redundancy. Check that the
      // node doesn't already depend on "top" directly.

      for (NodeToFixedBitsMap::NodeToFixedBitsMapType::iterator it = fixedMap->map->begin(); it != fixedMap->map->end(); it++) // iterates through all the pairs of node->fixedBits.
        {
          const FixedBits& bits = *it->second;

          if (!bits.isTotallyFixed())
            continue;

          const ASTNode& node = (it->first);

          // Don't constrain nodes we already know all about.
          if (node.isConstant())
            continue;

          // other nodes will contain the same information (the extract doesn't change the fixings).
          if (BVEXTRACT == node.GetKind() || BVCONCAT == node.GetKind())
            continue;

          // toAssign: conjoin it with the top level.
          // toReplace: replace all references to it (except the one conjoined to the top) with this.
          ASTNode propositionToAssert;
          ASTNode constantToReplaceWith;
          // skip the assigning and replacing.
          bool doAssign = true;

            {
              // If it is already contained in the fromTo map, then it's one of the values
              // that have fully been determined (previously). Not conjoined.
              if (fromTo.find(node) != fromTo.end())
                continue;

              ASTNode constNode = bitsToNode(node,bits);

              if (node.GetType() == BOOLEAN_TYPE)
                {
                  if (SYMBOL == node.GetKind())
                    {
                      bool r = simplifier->UpdateSubstitutionMap(node, constNode);
                      assert(r);
                      doAssign = false;
                    }
                  else if (bits.getValue(0))
                    {
                      propositionToAssert = node;
                      constantToReplaceWith = constNode;
                    }
                  else
                    {
                      propositionToAssert = nf->CreateNode(NOT, node);
                      constantToReplaceWith = constNode;
                    }
                }
              else if (node.GetType() == BITVECTOR_TYPE)
                {
                  assert(((unsigned)bits.getWidth()) == node.GetValueWidth());
                  if (SYMBOL == node.GetKind())
                    {
                      bool r = simplifier->UpdateSubstitutionMap(node, constNode);
                      assert(r);
                      doAssign = false;
                    }
                  else
                    {
                      propositionToAssert = nf->CreateNode(EQ, node, constNode);
                      constantToReplaceWith = constNode;
                    }
                }
              else
                FatalError("sadf234s");
            }

          if (doAssign && top != propositionToAssert
              && !dependents->nodeDependsOn(top, propositionToAssert))
            {
              assert(!constantToReplaceWith.IsNull());
              assert(constantToReplaceWith.isConstant());
              assert(propositionToAssert.GetType() == BOOLEAN_TYPE);
              assert(node.GetValueWidth() == constantToReplaceWith.GetValueWidth());

              fromTo.insert(make_pair(node, constantToReplaceWith));
              toConjoin.push_back(propositionToAssert);
            }
        }

     // Write the constants into the main graph.
      ASTNodeMap cache;
      ASTNode result = SubstitutionMap::replace(top, fromTo, cache,nf);

      if (0 != toConjoin.size())
        {
          // It doesn't happen very often. But the "toConjoin" might contain a variable
          // that was added to the substitution map (because the value was determined just now
          // during propagation.
          ASTNode conjunct = (1 == toConjoin.size())? toConjoin[0]: nf->CreateNode(AND,toConjoin);
          conjunct = simplifier->applySubstitutionMap(conjunct);

          result = nf->CreateNode(AND, result, conjunct); // conjoin the new conditions.
        }


  	if (debug_print_graph_after)
		{
			ofstream file;
			file.open("afterCbitp.gdl");
			PrintingHackfixedMap = fixedMap;
			printer::GDL_Print(file,top,&toString);
			file.close();
		}


      assert(BVTypeCheck(result));
      assert(status != CONFLICT); // conflict should have been seen earlier.
      return result;
    }