11 #include <boost/spirit/home/x3.hpp> 
   20                                                                                                {BooleanFunction::Value::ONE, 
"1"},
 
   21                                                                                                {BooleanFunction::Value::X, 
"X"},
 
   22                                                                                                {BooleanFunction::Value::Z, 
"Z"}};
 
   29                 return std::string(
"0");
 
   31                 return std::string(
"1");
 
   33                 return std::string(
"X");
 
   35                 return std::string(
"Z");
 
   38         return std::string(
"X");
 
   43         static std::vector<char> char_map = {
'0', 
'1', 
'2', 
'3', 
'4', 
'5', 
'6', 
'7', 
'8', 
'9', 
'A', 
'B', 
'C', 
'D', 
'E', 
'F'};
 
   46         static Result<std::string> to_bin(
const std::vector<BooleanFunction::Value>& value)
 
   48             if (value.size() == 0)
 
   50                 return ERR(
"could not convert bit-vector to binary string: bit-vector is empty");
 
   54             res.reserve(value.size());
 
   58                 res += enum_to_string<BooleanFunction::Value>(v);
 
   64         static Result<std::string> to_oct(
const std::vector<BooleanFunction::Value>& value)
 
   66             int bitsize = value.size();
 
   69                 return ERR(
"could not convert bit-vector to octal string: bit-vector is empty");
 
   72             u8 first_bits = bitsize % 3;
 
   81             res.reserve((bitsize + 2) / 3);
 
   84             for (
u8 i = 0; i < first_bits; i++)
 
   87                 index = (index << 1) | v1;
 
   90             mask = -((mask >> 1) & 0x1);
 
   93                 res += (char_map[index] & ~mask) | (
'X' & mask);
 
   97             for (
int i = bitsize % 3; i < bitsize; i += 3)
 
  103                 index = (v1 << 2) | (v2 << 1) | v3;    
 
  104                 mask  = -(((v1 | v2 | v3) >> 1) & 0x1);
 
  106                 res += (char_map[index] & ~mask) | (
'X' & mask);
 
  111         static Result<std::string> to_dec(
const std::vector<BooleanFunction::Value>& value)
 
  113             int bitsize = value.size();
 
  116                 return ERR(
"could not convert bit-vector to decimal string: bit-vector is empty");
 
  121                 return ERR(
"could not convert bit-vector to decimal string: bit-vector has length " + std::to_string(bitsize) + 
", but only up to 64 bits are supported for decimal conversion");
 
  127             for (
auto it = value.rbegin(); it != value.rend(); it++)
 
  136                 return OK(std::string(
"X"));
 
  138             return OK(std::to_string(tmp));
 
  141         static Result<std::string> to_hex(
const std::vector<BooleanFunction::Value>& value)
 
  143             int bitsize = value.size();
 
  146                 return ERR(
"could not convert bit-vector to hexadecimal string: bit-vector is empty");
 
  149             u8 first_bits = bitsize & 0x3;
 
  157             std::string res = 
"";
 
  158             res.reserve((bitsize + 3) / 4);
 
  161             for (
u8 i = 0; i < first_bits; i++)
 
  164                 index = (index << 1) | v1;
 
  167             mask = -((mask >> 1) & 0x1);
 
  170                 res += (char_map[index] & ~mask) | (
'X' & mask);
 
  174             for (
int i = bitsize & 0x3; i < bitsize; i += 4)
 
  181                 index = ((v1 << 3) | (v2 << 2) | (v3 << 1) | v4) & 0xF;
 
  182                 mask  = -(((v1 | v2 | v3 | v4) >> 1) & 0x1);
 
  184                 res += (char_map[index] & ~mask) | (
'X' & mask);
 
  196                 return to_bin(value);
 
  198                 return to_oct(value);
 
  200                 return to_dec(value);
 
  202                 return to_hex(value);
 
  204                 return ERR(
"could not convert bit-vector to string: invalid value '" + std::to_string(base) + 
"' given for base");
 
  210         if (value.size() > 64)
 
  212             return ERR(
"cannot translate vector of values to u64 numeral: can only support vectors up to 64 bits and got vector of size " + std::to_string(value.size()) + 
".");
 
  216         for (
auto it = value.rbegin(); it != value.rend(); it++)
 
  218             if ((*it != BooleanFunction::Value::ZERO) && (*it != BooleanFunction::Value::ONE))
 
  220                 return ERR(
"cannot translate vector of values to u64 numeral: found value other than ZERO or ONE: " + 
BooleanFunction::to_string(*it) + 
".");
 
  241         if (
auto res = BooleanFunction::validate(
BooleanFunction(std::move(nodes))); res.is_error())
 
  243             return ERR_APPEND(res.get_error(), 
"could not build Boolean function from vector of nodes: failed to validate Boolean function");
 
  268         auto values = std::vector<BooleanFunction::Value>();
 
  269         values.reserve(
size);
 
  270         for (
auto i = 0; i < 
size; i++)
 
  272             values.emplace_back(((value >> i) & 1) ? BooleanFunction::Value::ONE : BooleanFunction::Value::ZERO);
 
  285         if ((p0.size() != p1.size()) || (p0.size() != 
size))
 
  287             return ERR(
"could not join Boolean functions using AND operation: bit-sizes do not match (p0 = " + std::to_string(p0.size()) + 
", p1 = " + std::to_string(p1.size())
 
  288                        + 
", size = " + std::to_string(
size) + 
")");
 
  296         if ((p0.size() != p1.size()) || (p0.size() != 
size))
 
  298             return ERR(
"could not join Boolean functions using OR operation: bit-sizes do not match (p0 = " + std::to_string(p0.size()) + 
", p1 = " + std::to_string(p1.size())
 
  299                        + 
", size = " + std::to_string(
size) + 
").");
 
  307         if (p0.size() != 
size)
 
  309             return ERR(
"could not invert Boolean function using NOT operation: bit-sizes do not match (p0 = " + std::to_string(p0.size()) + 
", size = " + std::to_string(
size) + 
").");
 
  317         if ((p0.size() != p1.size()) || (p0.size() != 
size))
 
  319             return ERR(
"could not join Boolean functions using XOR operation: bit-sizes do not match (p0 = " + std::to_string(p0.size()) + 
", p1 = " + std::to_string(p1.size())
 
  320                        + 
", size = " + std::to_string(
size) + 
").");
 
  328         if ((p0.size() != p1.size()) || (p0.size() != 
size))
 
  330             return ERR(
"could not join Boolean functions using ADD operation: bit-sizes do not match (p0 = " + std::to_string(p0.size()) + 
", p1 = " + std::to_string(p1.size())
 
  331                        + 
", size = " + std::to_string(
size) + 
").");
 
  339         if ((p0.size() != p1.size()) || (p0.size() != 
size))
 
  341             return ERR(
"could not join Boolean functions using SUB operation: bit-sizes do not match (p0 = " + std::to_string(p0.size()) + 
", p1 = " + std::to_string(p1.size())
 
  342                        + 
", size = " + std::to_string(
size) + 
").");
 
  350         if ((p0.size() != p1.size()) || (p0.size() != 
size))
 
  352             return ERR(
"could not join Boolean functions using MUL operation: bit-sizes do not match (p0 = " + std::to_string(p0.size()) + 
", p1 = " + std::to_string(p1.size())
 
  353                        + 
", size = " + std::to_string(
size) + 
").");
 
  361         if ((p0.size() != p1.size()) || (p0.size() != 
size))
 
  363             return ERR(
"could not join Boolean functions using SDIV operation: bit-sizes do not match (p0 = " + std::to_string(p0.size()) + 
", p1 = " + std::to_string(p1.size())
 
  364                        + 
", size = " + std::to_string(
size) + 
").");
 
  372         if ((p0.size() != p1.size()) || (p0.size() != 
size))
 
  374             return ERR(
"could not join Boolean functions using UDIV operation: bit-sizes do not match (p0 = " + std::to_string(p0.size()) + 
", p1 = " + std::to_string(p1.size())
 
  375                        + 
", size = " + std::to_string(
size) + 
").");
 
  383         if ((p0.size() != p1.size()) || (p0.size() != 
size))
 
  385             return ERR(
"could not join Boolean functions using SREM operation: bit-sizes do not match (p0 = " + std::to_string(p0.size()) + 
", p1 = " + std::to_string(p1.size())
 
  386                        + 
", size = " + std::to_string(
size) + 
").");
 
  394         if ((p0.size() != p1.size()) || (p0.size() != 
size))
 
  396             return ERR(
"could not join Boolean functions using UREM operation: bit-sizes do not match (p0 = " + std::to_string(p0.size()) + 
", p1 = " + std::to_string(p1.size())
 
  397                        + 
", size = " + std::to_string(
size) + 
").");
 
  405         if (!p1.is_index() || !p2.is_index())
 
  407             return ERR(
"could not apply slice operation: function types do not match (p1 and p2 must be of type 'BooleanFunction::Index')");
 
  409         if ((p0.size() != p1.size()) || (p1.size() != p2.size()))
 
  411             return ERR(
"could not apply slice operation: bit-sizes do not match (p0 = " + std::to_string(p0.size()) + 
", p1 = " + std::to_string(p1.size()) + 
", p2 = " + std::to_string(p2.size())
 
  412                        + 
" - sizes must be equal)");
 
  415         auto start = p1.get_index_value().get();
 
  416         auto end   = p2.get_index_value().get();
 
  417         if ((start > end) || (start >= p0.size()) || (end >= p0.size()) || (end - start + 1) != 
size)
 
  419             return ERR(
"could not apply SLICE operation: bit indices are not valid, p1 must be larger or equal than p1 and smaller than p0 (p0 = " + std::to_string(p0.size())
 
  420                        + 
", p1 = " + std::to_string(start) + 
", p2 = " + std::to_string(end) + 
")");
 
  428         if ((p0.size() + p1.size()) != 
size)
 
  430             return ERR(
"could not apply CONCAT operation: function input widths do not match (p0 = " + std::to_string(p0.size()) + 
"-bit, p1 = " + std::to_string(p1.size())
 
  431                        + 
"-bit, size = " + std::to_string(
size) + 
").");
 
  439         if (p0.size() > 
size || p1.size() != 
size)
 
  441             return ERR(
"could not apply ZEXT operation: function input width does not match (p0 = " + std::to_string(p0.size()) + 
"-bit, p1 = " + std::to_string(p1.size())
 
  442                        + 
"-bit, size = " + std::to_string(
size) + 
").");
 
  445         if (!p1.has_index_value(
size))
 
  447             return ERR(
"could not apply ZEXT operation: p1 does not encode size (p1 = " + p1.to_string() + 
", size = " + std::to_string(
size) + 
").");
 
  455         if (p0.size() > 
size || p1.size() != 
size)
 
  457             return ERR(
"could not apply SEXT operation: function input width does not match (p0 = " + std::to_string(p0.size()) + 
"-bit, p1 = " + std::to_string(p1.size())
 
  458                        + 
"-bit, size = " + std::to_string(
size) + 
").");
 
  461         if (!p1.has_index_value(
size))
 
  463             return ERR(
"could not apply SEXT operation: p1 does not encode size (p1 = " + p1.to_string() + 
", size = " + std::to_string(
size) + 
").");
 
  471         if (p0.size() != 
size || p1.size() != 
size)
 
  473             return ERR(
"could not apply SHL operation: function input width does not match (p0 = " + std::to_string(p0.size()) + 
"-bit, p1 = " + std::to_string(p1.size())
 
  474                        + 
"-bit, size = " + std::to_string(
size) + 
").");
 
  479             return ERR(
"could not apply SHL operation: p1 is not an index.");
 
  487         if (p0.size() != 
size || p1.size() != 
size)
 
  489             return ERR(
"could not apply LSHR operation: function input width does not match (p0 = " + std::to_string(p0.size()) + 
"-bit, p1 = " + std::to_string(p1.size())
 
  490                        + 
"-bit, size = " + std::to_string(
size) + 
").");
 
  495             return ERR(
"could not apply LSHR operation: p1 is not an index.");
 
  503         if (p0.size() != 
size || p1.size() != 
size)
 
  505             return ERR(
"could not apply ASHR operation: function input width does not match (p0 = " + std::to_string(p0.size()) + 
"-bit, p1 = " + std::to_string(p1.size())
 
  506                        + 
"-bit, size = " + std::to_string(
size) + 
").");
 
  511             return ERR(
"could not apply ASHR operation: p1 is not an index.");
 
  519         if (p0.size() != 
size || p1.size() != 
size)
 
  521             return ERR(
"could not apply ROL operation: function input width does not match (p0 = " + std::to_string(p0.size()) + 
"-bit, p1 = " + std::to_string(p1.size())
 
  522                        + 
"-bit, size = " + std::to_string(
size) + 
").");
 
  527             return ERR(
"could not apply ROL operation: p1 is not an index.");
 
  535         if (p0.size() != 
size || p1.size() != 
size)
 
  537             return ERR(
"could not apply ROR operation: function input width does not match (p0 = " + std::to_string(p0.size()) + 
"-bit, p1 = " + std::to_string(p1.size())
 
  538                        + 
"-bit, size = " + std::to_string(
size) + 
").");
 
  543             return ERR(
"could not apply ROR operation: p1 is not an index.");
 
  551         if (p0.size() != p1.size() || 
size != 1)
 
  553             return ERR(
"could not apply EQ operation: function input width does not match (p0 = " + std::to_string(p0.size()) + 
"-bit, p1 = " + std::to_string(p1.size())
 
  554                        + 
"-bit, size = " + std::to_string(
size) + 
").");
 
  562         if (p0.size() != p1.size() || 
size != 1)
 
  564             return ERR(
"could not apply SLE operation: function input width does not match (p0 = " + std::to_string(p0.size()) + 
"-bit, p1 = " + std::to_string(p1.size())
 
  565                        + 
"-bit, size = " + std::to_string(
size) + 
").");
 
  573         if (p0.size() != p1.size() || 
size != 1)
 
  575             return ERR(
"could not apply SLT operation: function input width does not match (p0 = " + std::to_string(p0.size()) + 
"-bit, p1 = " + std::to_string(p1.size())
 
  576                        + 
"-bit, size = " + std::to_string(
size) + 
").");
 
  584         if (p0.size() != p1.size() || 
size != 1)
 
  586             return ERR(
"could not apply ULE operation: function input width does not match (p0 = " + std::to_string(p0.size()) + 
"-bit, p1 = " + std::to_string(p1.size())
 
  587                        + 
"-bit, size = " + std::to_string(
size) + 
").");
 
  595         if (p0.size() != p1.size() || 
size != 1)
 
  597             return ERR(
"could not apply ULT operation: function input width does not match (p0 = " + std::to_string(p0.size()) + 
"-bit, p1 = " + std::to_string(p1.size())
 
  598                        + 
"-bit, size = " + std::to_string(
size) + 
").");
 
  606         if (p0.size() != 1 || p1.size() != 
size || p2.size() != 
size)
 
  608             return ERR(
"could not apply ITE operation: function input width does not match (p0 = " + std::to_string(p0.size()) + 
"-bit, p1 = " + std::to_string(p1.size())
 
  609                        + 
"-bit, p2 = " + std::to_string(p2.size()) + 
"-bit, size = " + std::to_string(
size) + 
").");
 
  693         if (this->m_nodes.size() != other.m_nodes.size())
 
  698         for (
auto i = 0ul; i < this->m_nodes.size(); i++)
 
  700             if (this->m_nodes[i] != other.m_nodes[i])
 
  710         return !(*
this == other);
 
  715         if (this->m_nodes.size() < other.m_nodes.size())
 
  719         if (this->m_nodes.size() > other.m_nodes.size())
 
  724         return this->to_string_in_reverse_polish_notation() < other.to_string_in_reverse_polish_notation();
 
  729         return this->m_nodes.empty();
 
  735         function.m_nodes.reserve(this->m_nodes.size());
 
  737         for (
const auto& node : this->m_nodes)
 
  739             function.m_nodes.emplace_back(node);
 
  769             return ERR(
"Boolean function is empty");
 
  794             return ERR(
"Boolean function is empty");
 
  804             return ERR(
"Boolean function is empty");
 
  824             return ERR(
"Boolean function is empty");
 
  832         return this->m_nodes.back();
 
  837         return this->m_nodes.size();
 
  842         return this->m_nodes;
 
  854         auto coverage = this->compute_node_coverage();
 
  861                 return {
BooleanFunction(std::vector<Node>({this->m_nodes.begin(), this->m_nodes.end() - 1}))};
 
  864                 auto index = this->
length() - coverage[this->
length() - 2] - 1;
 
  866                 return {
BooleanFunction(std::vector<Node>({this->m_nodes.begin(), this->m_nodes.begin() + index})),
 
  867                         BooleanFunction(std::vector<Node>({this->m_nodes.begin() + index, this->m_nodes.end() - 1}))};
 
  870                 auto index0 = this->
length() - coverage[this->
length() - 3] - coverage[this->
length() - 2] - 1;
 
  871                 auto index1 = this->
length() - coverage[this->
length() - 2] - 1;
 
  873                 return {
BooleanFunction(std::vector<Node>({this->m_nodes.begin(), this->m_nodes.begin() + index0})),
 
  874                         BooleanFunction(std::vector<Node>({this->m_nodes.begin() + index0, this->m_nodes.begin() + index1})),
 
  875                         BooleanFunction(std::vector<Node>({this->m_nodes.begin() + index1, this->m_nodes.end() - 1}))};
 
  879                 assert(
false && 
"not implemented reached.");
 
  887         auto variable_names = std::set<std::string>();
 
  888         for (
const auto& node : this->m_nodes)
 
  890             if (node.is_variable())
 
  892                 variable_names.insert(node.variable);
 
  895         return variable_names;
 
  902             return ERR(
"could not print Boolean function: node arity of " + std::to_string(node.
get_arity()) + 
" does not match number of operands of " + std::to_string(operands.size()));
 
  913                 return OK(
"(" + operands[0] + 
" & " + operands[1] + 
")");
 
  915                 return OK(
"(! " + operands[0] + 
")");
 
  917                 return OK(
"(" + operands[0] + 
" | " + operands[1] + 
")");
 
  919                 return OK(
"(" + operands[0] + 
" ^ " + operands[1] + 
")");
 
  922                 return OK(
"(" + operands[0] + 
" + " + operands[1] + 
")");
 
  924                 return OK(
"(" + operands[0] + 
" - " + operands[1] + 
")");
 
  926                 return OK(
"(" + operands[0] + 
" * " + operands[1] + 
")");
 
  928                 return OK(
"(" + operands[0] + 
" /s " + operands[1] + 
")");
 
  930                 return OK(
"(" + operands[0] + 
" / " + operands[1] + 
")");
 
  932                 return OK(
"(" + operands[0] + 
" \%s " + operands[1] + 
")");
 
  934                 return OK(
"(" + operands[0] + 
" \% " + operands[1] + 
")");
 
  937                 return OK(
"(" + operands[0] + 
" ++ " + operands[1] + 
")");
 
  939                 return OK(
"Slice(" + operands[0] + 
", " + operands[1] + 
", " + operands[2] + 
")");
 
  941                 return OK(
"Zext(" + operands[0] + 
", " + operands[1] + 
")");
 
  943                 return OK(
"Sext(" + operands[0] + 
", " + operands[1] + 
")");
 
  946                 return OK(
"(" + operands[0] + 
" << " + operands[1] + 
")");
 
  948                 return OK(
"(" + operands[0] + 
" >> " + operands[1] + 
")");
 
  950                 return OK(
"(" + operands[0] + 
" >>a " + operands[1] + 
")");
 
  952                 return OK(
"(" + operands[0] + 
" <<r " + operands[1] + 
")");
 
  954                 return OK(
"(" + operands[0] + 
" >>r " + operands[1] + 
")");
 
  957                 return OK(
"(" + operands[0] + 
" == " + operands[1] + 
")");
 
  959                 return OK(
"(" + operands[0] + 
" <s " + operands[1] + 
")");
 
  961                 return OK(
"(" + operands[0] + 
" <=s " + operands[1] + 
")");
 
  963                 return OK(
"(" + operands[0] + 
" < " + operands[1] + 
")");
 
  965                 return OK(
"(" + operands[0] + 
" <= " + operands[1] + 
")");
 
  967                 return OK(
"Ite(" + operands[0] + 
", " + operands[1] + 
", " + operands[2] + 
")");
 
  970                 return ERR(
"could not print Boolean function: unsupported node type '" + std::to_string(node.
type) + 
"'");
 
  974     Result<std::string> BooleanFunction::algebraic_printer(
const BooleanFunction::Node& node, std::vector<std::string>&& operands)
 
  976         if (node.get_arity() != operands.size())
 
  978             return ERR(
"could not print Boolean function: node arity of " + std::to_string(node.get_arity()) + 
" does not match number of operands of " + std::to_string(operands.size()));
 
  985                 return OK(node.to_string());
 
  988                 return OK(
"CONST" + std::string(node.has_constant_value(0) ? 
"0" : 
"1"));
 
  991                 return OK(
"(" + operands[0] + 
"*" + operands[1] + 
")");
 
  993                 return OK(
"(! " + operands[0] + 
")");
 
  995                 return OK(
"(" + operands[0] + 
"+" + operands[1] + 
")");
 
  998                 return ERR(
"could not print Boolean function: unsupported node type '" + std::to_string(node.type) + 
"'");
 
 1005         if (this->m_nodes.empty())
 
 1011         std::vector<std::string> stack;
 
 1012         for (
const auto& node : this->m_nodes)
 
 1014             std::vector<std::string> operands;
 
 1022             std::move(stack.end() - 
static_cast<u64>(node.
get_arity()), stack.end(), std::back_inserter(operands));
 
 1023             stack.erase(stack.end() - 
static_cast<u64>(node.
get_arity()), stack.end());
 
 1025             if (
auto res = printer(node, std::move(operands)); res.is_ok())
 
 1027                 stack.emplace_back(res.get());
 
 1031                 log_error(
"netlist", 
"Cannot translate BooleanFunction::Node '{}' to a string: {}.", node.
to_string(), res.get_error().get());
 
 1036         switch (stack.size())
 
 1039                 return stack.back();
 
 1052         static const std::vector<std::tuple<ParserType, std::function<Result<std::vector<Token>>(
const std::string&)>>> parsers = {
 
 1057         for (
const auto& [parser_type, 
parser] : parsers)
 
 1059             auto tokens = 
parser(expression);
 
 1061             if (tokens.is_error())
 
 1068             if (tokens.is_error())
 
 1074             if (
function.is_error())
 
 1080         return ERR(
"could not parse Boolean function from string: no parser available for '" + expression + 
"'");
 
 1089         return (simplified.is_ok()) ? simplified.get() : this->
clone();
 
 1096         return (simplified.is_ok()) ? simplified.get() : this->
clone();
 
 1101         auto function = this->
clone();
 
 1102         for (
auto i = 0u; i < this->m_nodes.size(); i++)
 
 1116         auto substitute_variable = [](
const auto& node, 
auto&& operands, 
auto var_name, 
auto repl) -> 
BooleanFunction {
 
 1117             if (node.has_variable_name(var_name))
 
 1119                 return repl.
clone();
 
 1124         std::vector<BooleanFunction> stack;
 
 1125         for (
const auto& node : this->m_nodes)
 
 1127             std::vector<BooleanFunction> operands;
 
 1128             std::move(stack.end() - 
static_cast<i64>(node.get_arity()), stack.end(), std::back_inserter(operands));
 
 1129             stack.erase(stack.end() - 
static_cast<i64>(node.get_arity()), stack.end());
 
 1131             stack.emplace_back(substitute_variable(node, std::move(operands), 
name, replacement));
 
 1134         switch (stack.size())
 
 1137                 return OK(stack.back());
 
 1139                 return ERR(
"could not replace variable '" + 
name + 
"' with Boolean function '" + replacement.
to_string() + 
"': validation failed, the operations may be imbalanced");
 
 1145         auto function = this->
clone();
 
 1146         for (
auto i = 0u; i < this->m_nodes.size(); i++)
 
 1148             if (
const auto var_name_res = this->m_nodes[i].
get_variable_name(); var_name_res.is_ok())
 
 1150                 if (
const auto it = substitutions.find(var_name_res.get()); it != substitutions.end())
 
 1152                     function.m_nodes[i] = 
Node::Variable(it->second, this->m_nodes[i].size);
 
 1167         auto substitute_variable = [substitutions](
const auto& node, 
auto&& operands) -> 
BooleanFunction {
 
 1168             if (node.is_variable())
 
 1170                 if (
auto repl_it = substitutions.find(node.variable); repl_it != substitutions.end())
 
 1172                     return repl_it->second.
clone();
 
 1178         std::vector<BooleanFunction> stack;
 
 1179         for (
const auto& node : this->m_nodes)
 
 1181             std::vector<BooleanFunction> operands;
 
 1182             std::move(stack.end() - 
static_cast<i64>(node.get_arity()), stack.end(), std::back_inserter(operands));
 
 1183             stack.erase(stack.end() - 
static_cast<i64>(node.get_arity()), stack.end());
 
 1185             stack.emplace_back(substitute_variable(node, std::move(operands)));
 
 1188         switch (stack.size())
 
 1191                 return OK(stack.back());
 
 1193                 return ERR(
"could not carry out multiple substitutions: validation failed, the operations may be imbalanced");
 
 1200         if (this->m_nodes.empty())
 
 1202             return OK(BooleanFunction::Value::X);
 
 1206         if (this->
size() != 1)
 
 1208             return ERR(
"could not evaluate Boolean function '" + this->
to_string() + 
"': using single-bit evaluation on a Boolean function of size " + std::to_string(this->
size()) + 
" is illegal");
 
 1212         auto generic_inputs = std::unordered_map<std::string, std::vector<Value>>();
 
 1213         for (
const auto& [
name, value] : inputs)
 
 1215             generic_inputs.emplace(
name, std::vector<Value>({value}));
 
 1218         auto value = this->
evaluate(generic_inputs);
 
 1222             return OK(value.get()[0]);
 
 1225         return ERR(value.get_error());
 
 1231         if (this->m_nodes.empty())
 
 1233             return OK(std::vector<BooleanFunction::Value>({BooleanFunction::Value::X}));
 
 1237         for (
const auto& [
name, value] : inputs)
 
 1239             for (
const auto& node : this->m_nodes)
 
 1241                 if (node.has_variable_name(
name) && node.size != value.size())
 
 1243                     return ERR(
"could not evaluate Boolean function '" + this->
to_string() + 
"': as the size of vairbale " + 
name + 
" with size " + std::to_string(node.size)
 
 1244                                + 
" does not match the size of the provided input (" + std::to_string(value.size()) + 
")");
 
 1251         for (
const auto& [
name, value] : inputs)
 
 1258         auto result = symbolic_execution.evaluate(*
this);
 
 1261             if (
auto value = result.get(); value.is_constant())
 
 1263                 return OK(value.get_top_level_node().constant);
 
 1265             return OK(std::vector<BooleanFunction::Value>(this->
size(), BooleanFunction::Value::X));
 
 1267         return ERR(result.get_error());
 
 1276         for (
const auto& node : this->m_nodes)
 
 1278             if (node.is_variable() && node.size != 1)
 
 1280                 return ERR(
"could not compute truth table for Boolean function '" + this->
to_string() + 
"': unable to generate a truth-table for Boolean function with variables of > 1-bit");
 
 1285         auto variables = ordered_variables;
 
 1286         if (variables.empty())
 
 1288             variables = std::vector<std::string>(variable_names_in_function.begin(), variable_names_in_function.end());
 
 1292         if (remove_unknown_variables)
 
 1295                 std::remove_if(variables.begin(), variables.end(), [&variable_names_in_function](
const auto& s) { return variable_names_in_function.find(s) == variable_names_in_function.end(); }),
 
 1301         if (this->m_nodes.empty())
 
 1303             return OK(std::vector<std::vector<Value>>(1, std::vector<Value>(1 << variables.size(), Value::X)));
 
 1307         if (variables.size() > 10)
 
 1309             return ERR(
"could not compute truth table for Boolean function '" + this->
to_string() + 
"': unable to generate truth-table with more than 10 variables");
 
 1312         std::vector<std::vector<Value>> truth_table(this->
size(), std::vector<Value>(1 << variables.size(), Value::ZERO));
 
 1315         for (
auto value = 0u; value < ((
u32)1 << variables.size()); value++)
 
 1317             std::unordered_map<std::string, std::vector<Value>> 
input;
 
 1319             for (
const auto& variable : variables)
 
 1321                 input[variable] = ((tmp & 1) == 0) ? std::vector<Value>({Value::ZERO}) : std::vector<Value>({Value::ONE});
 
 1324             auto result = this->
evaluate(input);
 
 1325             if (result.is_error())
 
 1327                 return ERR(result.get_error());
 
 1329             auto output = result.get();
 
 1330             for (
auto index = 0u; index < truth_table.size(); index++)
 
 1332                 truth_table[index][value] = 
output[index];
 
 1336         return OK(truth_table);
 
 1341         std::vector<std::string> inputs;
 
 1343         if (ordered_inputs.empty())
 
 1345             inputs = std::vector<std::string>(inputs_set.begin(), inputs_set.end());
 
 1349             inputs = ordered_inputs;
 
 1352         if (remove_unknown_inputs)
 
 1354             inputs.erase(std::remove_if(inputs.begin(), inputs.end(), [&inputs_set](
const auto& s) { return inputs_set.find(s) == inputs_set.end(); }), inputs.end());
 
 1360             return ERR_APPEND(res.get_error(), 
"could not print truth table for Boolean function '" + this->to_string() + 
"': unable to compute truth table");
 
 1362         const auto truth_table = res.get();
 
 1364         std::stringstream 
str(
"");
 
 1366         u32 num_inputs  = inputs.size();
 
 1367         u32 num_outputs = truth_table.size();
 
 1370         std::vector<u32> in_widths;
 
 1371         for (
const auto& var : inputs)
 
 1373             in_widths.push_back(var.size());
 
 1374             str << 
" " << var << 
" |";
 
 1377         std::vector<u32> out_widths;
 
 1378         if (function_name.empty())
 
 1380             function_name = 
"O";
 
 1382         if (num_outputs == 1)
 
 1384             str << 
"| " << function_name << 
" ";
 
 1385             out_widths.push_back(function_name.size());
 
 1389             for (
u32 i = 0; i < num_outputs; i++)
 
 1391                 std::string var = function_name + 
"(" + std::to_string(i) + 
")";
 
 1392                 str << 
"| " << var << 
" ";
 
 1393                 out_widths.push_back(var.size());
 
 1399         for (
u32 i = 0; i < num_inputs; i++)
 
 1401             str << std::setw(in_widths.at(i) + 3) << std::setfill(
'-') << 
"+";
 
 1403         for (
u32 i = 0; i < num_outputs; i++)
 
 1405             str << 
"+" << std::setw(out_widths.at(i) + 2) << std::setfill(
'-') << 
"-";
 
 1410         for (
u32 i = 0; i < (
u32)(1 << num_inputs); i++)
 
 1412             for (
u32 j = 0; j < num_inputs; j++)
 
 1414                 str << 
" " << std::left << std::setw(in_widths.at(j)) << std::setfill(
' ') << ((i >> j) & 1) << 
" |";
 
 1417             for (
u32 k = 0; k < num_outputs; k++)
 
 1419                 str << 
"| " << std::left << std::setw(out_widths.at(k)) << std::setfill(
' ') << truth_table.at(k).at(i) << 
" ";
 
 1423         return OK(
str.str());
 
 1434         auto reduce_to_z3 = [&context, &var2expr](
const auto& node, 
auto&& p) -> std::tuple<bool, z3::expr> {
 
 1435             if (node.get_arity() != p.size())
 
 1437                 return {
false, z3::expr(context)};
 
 1443                     return {
true, context.bv_val(node.index, node.size)};
 
 1447                     auto constant = context.bv_val(node.constant.front(), 1);
 
 1448                     for (
u32 i = 1; i < node.constant.size(); i++)
 
 1450                         const auto bit = node.constant.at(i);
 
 1451                         constant       = z3::concat(context.bv_val(bit, 1), constant);
 
 1453                     return {
true, constant};
 
 1456                     if (
auto it = var2expr.find(node.variable); it != var2expr.end())
 
 1458                         return {
true, it->second};
 
 1460                     return {
true, context.bv_const(node.variable.c_str(), node.size)};
 
 1464                     return {
true, p[0] & p[1]};
 
 1466                     return {
true, p[0] | p[1]};
 
 1468                     return {
true, ~p[0]};
 
 1470                     return {
true, p[0] ^ p[1]};
 
 1472                     return {
true, p[0].extract(p[2].get_numeral_uint(), p[1].get_numeral_uint())};
 
 1474                     return {
true, z3::concat(p[0], p[1])};
 
 1476                     return {
true, z3::sext(p[0], p[1].get_numeral_uint())};
 
 1479                     log_error(
"netlist", 
"Not implemented reached for nodetype {} in z3 conversion", node.type);
 
 1480                     return {
false, z3::expr(context)};
 
 1484         std::vector<z3::expr> stack;
 
 1485         for (
const auto& node : this->m_nodes)
 
 1487             std::vector<z3::expr> operands;
 
 1488             std::move(stack.end() - 
static_cast<i64>(node.get_arity()), stack.end(), std::back_inserter(operands));
 
 1489             stack.erase(stack.end() - 
static_cast<i64>(node.get_arity()), stack.end());
 
 1491             if (
auto [ok, reduction] = reduce_to_z3(node, std::move(operands)); ok)
 
 1493                 stack.emplace_back(reduction);
 
 1497                 return z3::expr(context);
 
 1501         switch (stack.size())
 
 1504                 return stack.back();
 
 1506                 return z3::expr(context);
 
 1517         for (
const auto& parameter : p)
 
 1519             size += parameter.size();
 
 1521         this->m_nodes.reserve(
size);
 
 1523         for (
auto&& parameter : p)
 
 1525             this->m_nodes.insert(this->m_nodes.end(), parameter.m_nodes.begin(), parameter.m_nodes.end());
 
 1527         this->m_nodes.emplace_back(node);
 
 1530     std::string BooleanFunction::to_string_in_reverse_polish_notation()
 const 
 1533         for (
const auto& node : this->m_nodes)
 
 1535             s += node.to_string() + 
" ";
 
 1540     Result<BooleanFunction> BooleanFunction::validate(BooleanFunction&& 
function)
 
 1546         if (
auto coverage = 
function.compute_node_coverage(); coverage.back() != 
function.
length())
 
 1548             auto str = 
function.to_string_in_reverse_polish_notation();
 
 1549             return ERR(
"could not validate '" + 
str + 
"': imbalanced function with coverage '" + std::to_string(coverage.back()) + 
" != " + std::to_string(
function.length()));
 
 1552         return OK(std::move(
function));
 
 1555     std::vector<u32> BooleanFunction::compute_node_coverage()
 const 
 1557         auto coverage = std::vector<u32>(this->m_nodes.size(), (
u32)-1);
 
 1564         auto get = [](
const auto& cov, 
size_t index) -> 
u32 { 
return (index < cov.size()) ? cov[index] : -1; };
 
 1573         auto set = [](
auto& cov, 
size_t index, 
u32 x = 0, 
u32 y = 0, 
u32 z = 0) { cov[index] = ((x != (
u32)-1) && (y != (
u32)-1) && (z != (
u32)-1)) ? (x + y + z + 1) : (
u32)-1; };
 
 1575         for (
auto i = 0ul; i < this->m_nodes.size(); i++)
 
 1577             auto arity = this->m_nodes[i].get_arity();
 
 1586                     auto x = get(coverage, i - 1);
 
 1587                     set(coverage, i, x);
 
 1591                     auto x = get(coverage, i - 1);
 
 1592                     auto y = get(coverage, i - 1 - x);
 
 1593                     set(coverage, i, x, y);
 
 1597                     auto x = get(coverage, i - 1);
 
 1598                     auto y = get(coverage, i - 1 - x);
 
 1599                     auto z = get(coverage, i - 1 - x - y);
 
 1600                     set(coverage, i, x, y, z);
 
 1611         return Node(_type, _size, {}, {}, {});
 
 1636         return !(*
this == other);
 
 1646         return Node(this->
type, this->
size, this->constant, this->index, this->variable);
 
 1655                 for (
const auto& value : this->constant)
 
 1663                 return std::to_string(this->index);
 
 1665                 return this->variable;
 
 1725                 return "unsupported node type '" + std::to_string(this->
type) + 
"'.";
 
 1736         static const std::map<u16, u16> type2arity = {
 
 1747         return type2arity.at(
type);
 
 1752         return this->
type == _type;
 
 1762         return this->
is_constant() && (this->constant == value);
 
 1772         auto bv_value = std::vector<BooleanFunction::Value>({});
 
 1773         bv_value.reserve(this->
size);
 
 1774         for (
auto i = 0u; i < this->constant.size(); i++)
 
 1776             bv_value.emplace_back((value & (1 << i)) ? BooleanFunction::Value::ONE : BooleanFunction::Value::ZERO);
 
 1778         return this->constant == bv_value;
 
 1785             return ERR(
"Node is not a constant");
 
 1788         return OK(this->constant);
 
 1795             return ERR(
"Node is not a constant");
 
 1798         if (this->
size > 64)
 
 1800             return ERR(
"Node constant has size > 64");
 
 1803         if (std::any_of(this->constant.begin(), this->constant.end(), [](
auto v) { return v != BooleanFunction::Value::ONE && v != BooleanFunction::Value::ZERO; }))
 
 1805             return ERR(
"Node constant is undefined or high-impedance");
 
 1809         for (
auto it = this->constant.rbegin(); it != this->constant.rend(); it++)
 
 1825         return this->
is_index() && (this->index == value);
 
 1832             return ERR(
"Node is not an index");
 
 1835         return OK(this->index);
 
 1845         return this->
is_variable() && (this->variable == value);
 
 1852             return ERR(
"Node is not a variable");
 
 1855         return OK(this->variable);
 
 1860         return !this->is_operand();
 
 1874     BooleanFunction::Node::Node(
u16 _type, 
u16 _size, std::vector<BooleanFunction::Value> _constant, 
u16 _index, std::string _variable)
 
 1875         : 
type(_type), 
size(_size), constant(_constant), index(_index), variable(_variable)
 
static Result< BooleanFunction > Slt(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
 
bool has_index_value(u16 index) const
 
BooleanFunction operator+(const BooleanFunction &other) const
 
static Result< BooleanFunction > Ite(BooleanFunction &&p0, BooleanFunction &&p1, BooleanFunction &&p2, u16 size)
 
BooleanFunction operator&(const BooleanFunction &other) const
 
static Result< BooleanFunction > Eq(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
 
static BooleanFunction Var(const std::string &name, u16 size=1)
 
static Result< BooleanFunction > Xor(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
 
bool operator==(const BooleanFunction &other) const
 
Result< std::string > get_variable_name() const
 
BooleanFunction operator^(const BooleanFunction &other) const
 
const BooleanFunction::Node & get_top_level_node() const
 
static Result< BooleanFunction > Add(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
 
std::set< std::string > get_variable_names() const
 
static Result< BooleanFunction > Lshr(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
 
bool has_constant_value(const std::vector< Value > &value) const
 
static Result< BooleanFunction > Zext(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
 
Result< std::vector< Value > > get_constant_value() const
 
static Result< BooleanFunction > Mul(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
 
bool has_variable_name(const std::string &variable_name) const
 
static Result< BooleanFunction > Ule(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
 
static Result< BooleanFunction > Sub(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
 
static Result< BooleanFunction > Sext(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
 
static Result< BooleanFunction > Udiv(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
 
BooleanFunction operator~() const
 
static Result< BooleanFunction > Concat(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
 
static Result< BooleanFunction > Ult(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
 
static BooleanFunction Index(u16 index, u16 size)
 
z3::expr to_z3(z3::context &context, const std::map< std::string, z3::expr > &var2expr={}) const
 
Result< std::vector< std::vector< Value > > > compute_truth_table(const std::vector< std::string > &ordered_variables={}, bool remove_unknown_variables=false) const
 
BooleanFunction & operator-=(const BooleanFunction &other)
 
Result< Value > evaluate(const std::unordered_map< std::string, Value > &inputs) const
 
static Result< BooleanFunction > Sle(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
 
static Result< BooleanFunction > build(std::vector< Node > &&nodes)
 
BooleanFunction operator|(const BooleanFunction &other) const
 
static Result< BooleanFunction > from_string(const std::string &expression)
 
static Result< BooleanFunction > Slice(BooleanFunction &&p0, BooleanFunction &&p1, BooleanFunction &&p2, u16 size)
 
const std::vector< BooleanFunction::Node > & get_nodes() const
 
BooleanFunction & operator*=(const BooleanFunction &other)
 
BooleanFunction simplify() const
 
BooleanFunction operator-(const BooleanFunction &other) const
 
Result< std::string > get_truth_table_as_string(const std::vector< std::string > &ordered_variables={}, std::string function_name="", bool remove_unknown_variables=false) const
 
bool operator<(const BooleanFunction &other) const
 
BooleanFunction & operator&=(const BooleanFunction &other)
 
BooleanFunction clone() const
 
Value
represents the type of the node
 
static Result< BooleanFunction > Or(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
 
bool operator!=(const BooleanFunction &other) const
 
static Result< BooleanFunction > Urem(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
 
BooleanFunction & operator^=(const BooleanFunction &other)
 
static Result< BooleanFunction > Ror(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
 
BooleanFunction & operator+=(const BooleanFunction &other)
 
static Result< BooleanFunction > Sdiv(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
 
BooleanFunction & operator|=(const BooleanFunction &other)
 
static std::string to_string(Value value)
 
BooleanFunction simplify_local() const
 
static BooleanFunction Const(const BooleanFunction::Value &value)
 
BooleanFunction operator*(const BooleanFunction &other) const
 
static Result< BooleanFunction > Ashr(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
 
static Result< u64 > to_u64(const std::vector< BooleanFunction::Value > &value)
 
static Result< BooleanFunction > Not(BooleanFunction &&p0, u16 size)
 
static Result< BooleanFunction > And(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
 
std::vector< BooleanFunction > get_parameters() const
 
Result< u16 > get_index_value() const
 
BooleanFunction substitute(const std::string &old_variable_name, const std::string &new_variable_name) const
 
static Result< BooleanFunction > Shl(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
 
Result< u64 > get_constant_value_u64() const
 
static Result< BooleanFunction > Rol(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
 
static Result< BooleanFunction > Srem(BooleanFunction &&p0, BooleanFunction &&p1, u16 size)
 
#define log_error(channel,...)
 
#define ERR_APPEND(prev_error, message)
 
Result< std::vector< Token > > parse_with_standard_grammar(const std::string &expression)
 
Result< std::vector< Token > > parse_with_liberty_grammar(const std::string &expression)
 
ParserType
ParserType refers to the parser identifier.
 
Result< BooleanFunction > translate(std::vector< Token > &&tokens, const std::string &expression)
 
Result< std::vector< Token > > reverse_polish_notation(std::vector< Token > &&tokens, const std::string &expression, const ParserType &parser)
 
Result< BooleanFunction > local_simplification(const BooleanFunction &function)
 
std::ostream & operator<<(std::ostream &os, BooleanFunction::Value v)
 
std::string enum_to_string(T e)
 
include set(SRCROOT ${CMAKE_CURRENT_SOURCE_DIR}/src) set(UIROOT $
 
std::vector< BooleanFunction::Value > constant
The (optional) constant value of the node.
 
u16 type
The type of the node.
 
bool is_operation() const
 
u16 size
The bit-size of the node.
 
static u16 get_arity_of_type(u16 type)
 
static Node Constant(const std::vector< BooleanFunction::Value > value)
 
bool has_index_value(u16 value) const
 
std::string variable
The (optional) variable name of the node.
 
bool has_variable_name(const std::string &variable_name) const
 
static Node Operation(u16 type, u16 size)
 
bool has_constant_value(const std::vector< Value > &value) const
 
bool is_commutative() const
 
std::string to_string() const
 
Result< std::vector< Value > > get_constant_value() const
 
static Node Index(u16 index, u16 size)
 
Result< u16 > get_index_value() const
 
bool operator!=(const Node &other) const
 
bool operator==(const Node &other) const
 
bool operator<(const Node &other) const
 
u16 index
The (optional) index value of the node.
 
static Node Variable(const std::string variable, u16 size)
 
Result< std::string > get_variable_name() const
 
Result< u64 > get_constant_value_u64() const
 
static constexpr u16 Constant
 
static constexpr u16 Srem
 
static constexpr u16 Udiv
 
static constexpr u16 Sdiv
 
static constexpr u16 Urem
 
static constexpr u16 Lshr
 
static constexpr u16 Sext
 
static constexpr u16 Ashr
 
static constexpr u16 Index
 
static constexpr u16 Concat
 
static constexpr u16 Slice
 
static constexpr u16 Zext
 
static constexpr u16 Variable
 
Token refers to a token identifier and accompanied data.