HAL
boolean_function.h
Go to the documentation of this file.
1 // MIT License
2 //
3 // Copyright (c) 2019 Ruhr University Bochum, Chair for Embedded Security. All Rights reserved.
4 // Copyright (c) 2019 Marc Fyrbiak, Sebastian Wallat, Max Hoffmann ("ORIGINAL AUTHORS"). All rights reserved.
5 // Copyright (c) 2021 Max Planck Institute for Security and Privacy. All Rights reserved.
6 // Copyright (c) 2021 Jörn Langheinrich, Julian Speith, Nils Albartus, René Walendy, Simon Klix ("ORIGINAL AUTHORS"). All Rights reserved.
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included in all
16 // copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 // SOFTWARE.
25 
26 #pragma once
27 
28 #include "hal_core/defines.h"
31 #include "z3++.h"
32 
33 #include <algorithm>
34 #include <cassert>
35 #include <map>
36 #include <ostream>
37 #include <set>
38 #include <unordered_map>
39 #include <vector>
40 
41 namespace hal
42 {
55  {
56  public:
58  // Forward Declarations
60 
61  /*
62  * We forward declare the abstract syntax tree nodes and types of the
63  * Boolean function in order to re-use BooleanFunction both as a class
64  * and a namespace for its underlying node data structures.
65  */
66 
67  struct Node;
68  struct NodeType;
69 
73  enum Value
74  {
75  ZERO = 0,
76  ONE = 1,
77  X = -1,
78  Z = -2
79  };
80 
87  static std::string to_string(Value value);
88 
96  static Result<std::string> to_string(const std::vector<BooleanFunction::Value>& value, u8 base = 2);
97 
104  static Result<u64> to_u64(const std::vector<BooleanFunction::Value>& value);
105 
113  friend std::ostream& operator<<(std::ostream& os, Value v);
114 
116  // Constructors / Factories, Destructors, Operators
118 
122  explicit BooleanFunction();
123 
130  static Result<BooleanFunction> build(std::vector<Node>&& nodes);
131 
139  static BooleanFunction Var(const std::string& name, u16 size = 1);
140 
147  static BooleanFunction Const(const BooleanFunction::Value& value);
148 
155  static BooleanFunction Const(const std::vector<BooleanFunction::Value>& value);
156 
164  static BooleanFunction Const(u64 value, u16 size);
165 
173  static BooleanFunction Index(u16 index, u16 size);
174 
185 
196 
205  static Result<BooleanFunction> Not(BooleanFunction&& p0, u16 size);
206 
218 
230 
242 
254 
265  static Result<BooleanFunction> Sdiv(BooleanFunction&& p0, BooleanFunction&& p1, u16 size);
266 
277  static Result<BooleanFunction> Udiv(BooleanFunction&& p0, BooleanFunction&& p1, u16 size);
278 
289  static Result<BooleanFunction> Srem(BooleanFunction&& p0, BooleanFunction&& p1, u16 size);
290 
301  static Result<BooleanFunction> Urem(BooleanFunction&& p0, BooleanFunction&& p1, u16 size);
302 
313  static Result<BooleanFunction> Slice(BooleanFunction&& p0, BooleanFunction&& p1, BooleanFunction&& p2, u16 size);
314 
323  static Result<BooleanFunction> Concat(BooleanFunction&& p0, BooleanFunction&& p1, u16 size);
324 
333  static Result<BooleanFunction> Zext(BooleanFunction&& p0, BooleanFunction&& p1, u16 size);
334 
343  static Result<BooleanFunction> Sext(BooleanFunction&& p0, BooleanFunction&& p1, u16 size);
344 
353  static Result<BooleanFunction> Shl(BooleanFunction&& p0, BooleanFunction&& p1, u16 size);
354 
363  static Result<BooleanFunction> Lshr(BooleanFunction&& p0, BooleanFunction&& p1, u16 size);
364 
373  static Result<BooleanFunction> Ashr(BooleanFunction&& p0, BooleanFunction&& p1, u16 size);
374 
383  static Result<BooleanFunction> Rol(BooleanFunction&& p0, BooleanFunction&& p1, u16 size);
384 
393  static Result<BooleanFunction> Ror(BooleanFunction&& p0, BooleanFunction&& p1, u16 size);
394 
403  static Result<BooleanFunction> Eq(BooleanFunction&& p0, BooleanFunction&& p1, u16 size);
404 
414 
424 
434 
444 
457 
465  friend std::ostream& operator<<(std::ostream& os, const BooleanFunction& f);
466 
475  BooleanFunction operator&(const BooleanFunction& other) const;
476 
485  BooleanFunction& operator&=(const BooleanFunction& other);
486 
492  BooleanFunction operator~() const;
493 
502  BooleanFunction operator|(const BooleanFunction& other) const;
503 
512  BooleanFunction& operator|=(const BooleanFunction& other);
513 
522  BooleanFunction operator^(const BooleanFunction& other) const;
523 
532  BooleanFunction& operator^=(const BooleanFunction& other);
533 
542  BooleanFunction operator+(const BooleanFunction& other) const;
543 
552  BooleanFunction& operator+=(const BooleanFunction& other);
553 
562  BooleanFunction operator-(const BooleanFunction& other) const;
563 
572  BooleanFunction& operator-=(const BooleanFunction& other);
573 
582  BooleanFunction operator*(const BooleanFunction& other) const;
583 
592  BooleanFunction& operator*=(const BooleanFunction& other);
593 
600  bool operator==(const BooleanFunction& other) const;
601 
608  bool operator!=(const BooleanFunction& other) const;
609 
616  bool operator<(const BooleanFunction& other) const;
617 
623  bool is_empty() const;
624 
626  // Interface: Nodes, Sizes, and Checks
628 
634  BooleanFunction clone() const;
635 
641  u16 size() const;
642 
649  bool is(u16 type) const;
650 
656  bool is_variable() const;
657 
664  bool has_variable_name(const std::string& variable_name) const;
665 
671  Result<std::string> get_variable_name() const;
672 
678  bool is_constant() const;
679 
686  bool has_constant_value(const std::vector<Value>& value) const;
687 
694  bool has_constant_value(u64 value) const;
695 
701  Result<std::vector<Value>> get_constant_value() const;
702 
708  Result<u64> get_constant_value_u64() const;
709 
715  bool is_index() const;
716 
723  bool has_index_value(u16 index) const;
724 
730  Result<u16> get_index_value() const;
731 
738  const BooleanFunction::Node& get_top_level_node() const;
739 
745  u32 length() const;
746 
752  const std::vector<BooleanFunction::Node>& get_nodes() const;
753 
759  std::vector<BooleanFunction> get_parameters() const;
760 
766  std::set<std::string> get_variable_names() const;
767 
769  // Interface: String Translation
771 
778  std::string to_string(std::function<Result<std::string>(const BooleanFunction::Node& node, std::vector<std::string>&& operands)>&& printer = default_printer) const;
779 
786  static Result<BooleanFunction> from_string(const std::string& expression);
787 
789  // Interface: Simplification / Substitution / Evaluation
791 
797  BooleanFunction simplify() const;
798 
804  BooleanFunction simplify_local() const;
805 
814  BooleanFunction substitute(const std::string& old_variable_name, const std::string& new_variable_name) const;
815 
824  Result<BooleanFunction> substitute(const std::string& variable_name, const BooleanFunction& function) const;
825 
833  BooleanFunction substitute(const std::map<std::string, std::string>& substitutions) const;
834 
842  Result<BooleanFunction> substitute(const std::map<std::string, BooleanFunction>& substitutions) const;
843 
850  Result<Value> evaluate(const std::unordered_map<std::string, Value>& inputs) const;
851 
858  Result<std::vector<Value>> evaluate(const std::unordered_map<std::string, std::vector<Value>>& inputs) const;
859 
868  Result<std::vector<std::vector<Value>>> compute_truth_table(const std::vector<std::string>& ordered_variables = {}, bool remove_unknown_variables = false) const;
869 
879  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;
880 
890  [[deprecated("Will be removed in a future version. Use z3_utils::from_bf() in the z3_utils plugin instead.")]] z3::expr to_z3(z3::context& context,
891  const std::map<std::string, z3::expr>& var2expr = {}) const;
892 
893  private:
895  // Constructors, Destructors, Operators
897 
899  explicit BooleanFunction(std::vector<BooleanFunction::Node>&& nodes);
900 
909  template<typename... T, typename = std::enable_if_t<std::conjunction_v<std::is_same<T, BooleanFunction>...>>>
910  explicit BooleanFunction(BooleanFunction::Node&& node, T&&... p)
911  {
912  auto size = 1;
913  ((size += p.size()), ...);
914  this->m_nodes.reserve(size);
915 
916  (this->m_nodes.insert(this->m_nodes.end(), p.m_nodes.begin(), p.m_nodes.end()), ...);
917  this->m_nodes.emplace_back(std::move(node));
918  }
919 
927  explicit BooleanFunction(BooleanFunction::Node&& node, std::vector<BooleanFunction>&& p);
928 
930  // Internal Interface
932 
934  std::string to_string_in_reverse_polish_notation() const;
935 
943  static Result<std::string> default_printer(const BooleanFunction::Node& node, std::vector<std::string>&& operands);
944 
952  static Result<std::string> algebraic_printer(const BooleanFunction::Node& node, std::vector<std::string>&& operands);
953 
957  static Result<BooleanFunction> validate(BooleanFunction&& function);
958 
960  std::vector<u32> compute_node_coverage() const;
961 
963  // Member
965 
967  std::vector<BooleanFunction::Node> m_nodes{};
968  };
969 
970  template<>
971  std::map<BooleanFunction::Value, std::string> EnumStrings<BooleanFunction::Value>::data;
972 
987  {
989  // Member
991 
997  std::vector<BooleanFunction::Value> constant{};
1001  std::string variable{};
1002 
1004  // Constructors, Destructors, Operators
1006 
1014  static Node Operation(u16 type, u16 size);
1015 
1022  static Node Constant(const std::vector<BooleanFunction::Value> value);
1023 
1031  static Node Index(u16 index, u16 size);
1032 
1040  static Node Variable(const std::string variable, u16 size);
1041 
1048  bool operator==(const Node& other) const;
1049 
1056  bool operator!=(const Node& other) const;
1057 
1064  bool operator<(const Node& other) const;
1065 
1067  // Interface
1069 
1075  Node clone() const;
1076 
1082  std::string to_string() const;
1083 
1089  u16 get_arity() const;
1090 
1096  static u16 get_arity_of_type(u16 type);
1097 
1104  bool is(u16 type) const;
1105 
1111  bool is_constant() const;
1112 
1119  bool has_constant_value(const std::vector<Value>& value) const;
1120 
1127  bool has_constant_value(u64 value) const;
1128 
1135 
1142 
1148  bool is_index() const;
1149 
1156  bool has_index_value(u16 value) const;
1157 
1163  Result<u16> get_index_value() const;
1164 
1170  bool is_variable() const;
1171 
1178  bool has_variable_name(const std::string& variable_name) const;
1179 
1186 
1192  bool is_operation() const;
1193 
1199  bool is_operand() const;
1200 
1206  bool is_commutative() const;
1207 
1208  private:
1210  // Constructors, Destructors, Operators
1212 
1214  Node(u16 _type, u16 _size, std::vector<BooleanFunction::Value> _constant, u16 _index, std::string variable);
1215  };
1216 
1223  {
1224  static constexpr u16 And = 0x0000;
1225  static constexpr u16 Or = 0x0001;
1226  static constexpr u16 Not = 0x0002;
1227  static constexpr u16 Xor = 0x0003;
1228 
1229  static constexpr u16 Add = 0x0010;
1230  static constexpr u16 Sub = 0x0011;
1231  static constexpr u16 Mul = 0x0012;
1232  static constexpr u16 Sdiv = 0x0013;
1233  static constexpr u16 Udiv = 0x0014;
1234  static constexpr u16 Srem = 0x0015;
1235  static constexpr u16 Urem = 0x0016;
1236 
1237  static constexpr u16 Concat = 0x0100;
1238  static constexpr u16 Slice = 0x0101;
1239  static constexpr u16 Zext = 0x0102;
1240  static constexpr u16 Sext = 0x0103;
1241 
1242  static constexpr u16 Shl = 0x0200;
1243  static constexpr u16 Lshr = 0x0201;
1244  static constexpr u16 Ashr = 0x0202;
1245  static constexpr u16 Rol = 0x0203;
1246  static constexpr u16 Ror = 0x0204;
1247 
1248  static constexpr u16 Eq = 0x0400;
1249  static constexpr u16 Sle = 0x0401;
1250  static constexpr u16 Slt = 0x0402;
1251  static constexpr u16 Ule = 0x0403;
1252  static constexpr u16 Ult = 0x0404;
1253  static constexpr u16 Ite = 0x0405;
1254 
1255  static constexpr u16 Constant = 0x1000;
1256  static constexpr u16 Index = 0x1001;
1257  static constexpr u16 Variable = 0x1002;
1258  };
1259 } // namespace hal
#define NETLIST_API
Definition: arch_linux.h:30
Value
represents the type of the node
uint64_t u64
Definition: defines.h:42
uint16_t u16
Definition: defines.h:40
uint8_t u8
Definition: defines.h:39
BooleanFunction Slt(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
BooleanFunction Or(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
BooleanFunction Not(const std::vector< BooleanFunction::Value > &p)
BooleanFunction Sle(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
BooleanFunction Ite(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1, const std::vector< BooleanFunction::Value > &p2)
BooleanFunction Ule(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
BooleanFunction Ult(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
BooleanFunction Mul(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
BooleanFunction Sub(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
BooleanFunction Add(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
BooleanFunction Xor(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
BooleanFunction And(const std::vector< BooleanFunction::Value > &p0, const std::vector< BooleanFunction::Value > &p1)
std::ostream & operator<<(std::ostream &os, BooleanFunction::Value v)
quint32 u32
PinType type
std::string name
std::vector< BooleanFunction::Value > constant
The (optional) constant value of the node.
u16 type
The type of the node.
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
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