ilasynth  1.0
ILASynth: Template-based ILA Synthesis Engine
ast.hpp
Go to the documentation of this file.
1 #ifndef __AST_HPP_DEFINED__
2 #define __AST_HPP_DEFINED__
3 
4 #include <iostream>
5 #include <map>
6 #include <memory>
7 #include <string>
8 #include <utility>
9 #include <vector>
10 
11 #include <assert.h>
12 #include <ilasynth/type.hpp>
13 #include <z3++.h>
14 
15 #include <ilasynth/ast/bitvec.hpp>
16 #include <ilasynth/ast/bool.hpp>
18 #include <ilasynth/ast/choice.hpp>
19 #include <ilasynth/ast/func.hpp>
20 #include <ilasynth/ast/mem.hpp>
21 #include <ilasynth/ast/node.hpp>
22 #include <ilasynth/common.hpp>
23 
24 #include <boost/python.hpp>
25 #include <boost/shared_ptr.hpp>
26 
27 namespace ilasynth {
28 // ---------------------------------------------------------------------- //
29 struct NodeRef {
30  // ------------------------ MEMBERS ----------------------------- //
32 
33  // --------------- CONSTRUCTOR/DESTRUCTOR ----------------------- //
34  // Default constructor. DO NOT USE. Will throw an exception.
35  NodeRef();
36  // Constructor. DO NOT USE. Call factory methods in Context instead.
37  NodeRef(Node* node);
38  // Constructor from an existing shared_ptr.
39  NodeRef(const nptr_t& ptr);
40  // Copy constructor.
41  NodeRef(const NodeRef& nr);
42  // Destructor.
43  ~NodeRef();
44 
45  // assignment operator.
46  NodeRef& operator=(const NodeRef& other);
47 
48  // ---------------------- METHODS ------------------------------- //
49  std::string getName() const;
50  NodeType getType() const;
51  bool equal(NodeRef* other) const;
52 
53  // ---------------------- OPERATORS ----------------------------- //
54  NodeRef* complement() const;
55  NodeRef* negate() const;
56 
57  // and
58  NodeRef* logicalAnd(NodeRef* other) const;
59  NodeRef* logicalAndInt(int r) const;
60  NodeRef* logicalAndRInt(int r) const;
61  // or
62  NodeRef* logicalOr(NodeRef* other) const;
63  NodeRef* logicalOrInt(int r) const;
64  NodeRef* logicalOrRInt(int l) const;
65  // xor
66  NodeRef* logicalXor(NodeRef* other) const;
67  NodeRef* logicalXorInt(int r) const;
68  NodeRef* logicalXorRInt(int l) const;
69 
70  // add
71  NodeRef* add(NodeRef* other) const;
72  NodeRef* addInt(int r) const;
73  NodeRef* raddInt(int r) const;
74  // sub
75  NodeRef* sub(NodeRef* other) const;
76  NodeRef* subInt(int r) const;
77  NodeRef* rsubInt(int r) const;
78  // udiv
79  NodeRef* udiv(NodeRef* other) const;
80  NodeRef* udivInt(int r) const;
81  NodeRef* rudivInt(int r) const;
82  // urem
83  NodeRef* urem(NodeRef* r);
84  NodeRef* uremInt(int r);
85  NodeRef* ruremInt(int l);
86  // shl
87  NodeRef* shl(NodeRef* other) const;
88  NodeRef* shlInt(int r) const;
89  NodeRef* rshlInt(int r) const;
90  // shr
91  NodeRef* lshr(NodeRef* other) const;
92  NodeRef* lshrInt(int r) const;
93  NodeRef* rlshrInt(int r) const;
94  // mul
95  NodeRef* mul(NodeRef* other) const;
96  NodeRef* mulInt(int r) const;
97  NodeRef* rmulInt(int r) const;
98 
99  // comparison operators.
100  NodeRef* eq(NodeRef& other) const;
101  NodeRef* neq(NodeRef& other) const;
102  NodeRef* ult(NodeRef& other) const;
103  NodeRef* ugt(NodeRef& other) const;
104  NodeRef* ule(NodeRef& other) const;
105  NodeRef* uge(NodeRef& other) const;
106  NodeRef* eqInt(int r) const;
107  NodeRef* neqInt(int r) const;
108  NodeRef* ultInt(int r) const;
109  NodeRef* ugtInt(int r) const;
110  NodeRef* uleInt(int r) const;
111  NodeRef* ugeInt(int r) const;
112 
113  // slicing.
114  NodeRef* slice(int hi, int lo) const;
115  // get bit.
116  NodeRef* getItem(NodeRef* idx) const;
117  NodeRef* getItemInt(int idx) const;
118 
119  // set reference name.
120  void setRefName(const std::string& refName);
121  // does this object have a value?
122  py::object value() const;
123 
124  // static function for non-python operators.
125 
126  // read from memory.
127  static NodeRef* load(NodeRef* mem, NodeRef* addr);
128  static NodeRef* loadblock(NodeRef* mem, NodeRef* addr, int chunks);
129  static NodeRef* loadblockB(NodeRef* mem, NodeRef* addr, int chunks);
130  // write to memory.
131  static NodeRef* store(NodeRef* mem, NodeRef* addr, NodeRef* data);
132  static NodeRef* storeblock(NodeRef* mem, NodeRef* addr, NodeRef* data);
133  static NodeRef* storeblockB(NodeRef* mem, NodeRef* addr, NodeRef* data);
134 
135  // logical functions.
136  static NodeRef* logicalXnor(NodeRef* l, NodeRef* r);
137  static NodeRef* logicalNand(NodeRef* l, NodeRef* r);
138  static NodeRef* logicalNor(NodeRef* l, NodeRef* r);
139 
140  // arithmetic functions.
141  // div.
142  static NodeRef* sdiv(NodeRef* l, NodeRef* r);
143  static NodeRef* sdivInt(NodeRef* l, int r);
144  static NodeRef* rsdivInt(int l, NodeRef* r);
145  // smod
146  static NodeRef* smod(NodeRef* l, NodeRef* r);
147  static NodeRef* smodInt(NodeRef* l, int r);
148  static NodeRef* rsmodInt(int l, NodeRef* r);
149  // srem
150  static NodeRef* srem(NodeRef* l, NodeRef* r);
151  static NodeRef* sremInt(NodeRef* l, int r);
152  static NodeRef* rsremInt(int l, NodeRef* r);
153  // shr
154  static NodeRef* ashr(NodeRef* l, NodeRef* r);
155  static NodeRef* ashrInt(NodeRef* l, int r);
156  static NodeRef* rashrInt(int l, NodeRef* r);
157 
158  // comparison functions.
159  static NodeRef* slt(NodeRef& l, NodeRef& r);
160  static NodeRef* sgt(NodeRef& l, NodeRef& r);
161  static NodeRef* sle(NodeRef& l, NodeRef& r);
162  static NodeRef* sge(NodeRef& l, NodeRef& r);
163  static NodeRef* sltInt(NodeRef& l, int r);
164  static NodeRef* sgtInt(NodeRef& l, int r);
165  static NodeRef* sleInt(NodeRef& l, int r);
166  static NodeRef* sgeInt(NodeRef& l, int r);
167 
168  // bit manipulate functions.
169  static NodeRef* concat(NodeRef* lo, NodeRef* hi);
170  static NodeRef* concatList(const py::list& l);
171  static NodeRef* lrotate(NodeRef* obj, int par);
172  static NodeRef* rrotate(NodeRef* obj, int par);
173  static NodeRef* extract(const NodeRef* obj, int hi, int lo);
174  static NodeRef* zero_extend(NodeRef* obj, int outWidth);
175  static NodeRef* sign_extend(NodeRef* obg, int outWidth);
176 
177  // nnonzero
178  static NodeRef* nonzero(NodeRef* obj);
179 
180  // imply
181  static NodeRef* imply(NodeRef& p, NodeRef& q);
182 
183  // ite.
184  static NodeRef* ite(NodeRef& cond, NodeRef& trueExp, NodeRef& falseExp);
185 
186  // apply function.
187  static NodeRef* appfunc0(NodeRef* fun);
188  static NodeRef* appfunc1(NodeRef* fun, NodeRef* arg);
189  static NodeRef* appfunc2(NodeRef* fun, NodeRef* arg0, NodeRef* arg1);
190  static NodeRef* appfuncL(NodeRef* fun, const py::list& l);
191 
192  // choices
193  static NodeRef* choice2(const std::string& name, NodeRef* e1, NodeRef* e2);
194  static NodeRef* choice3(const std::string& name, NodeRef* e1, NodeRef* e2,
195  NodeRef* e3);
196  static NodeRef* choice4(const std::string& name, NodeRef* e1, NodeRef* e2,
197  NodeRef* e3, NodeRef* e4);
198  static NodeRef* choice5(const std::string& name, NodeRef* e1, NodeRef* e2,
199  NodeRef* e3, NodeRef* e4, NodeRef* e5);
200  static NodeRef* choice6(const std::string& name, NodeRef* e1, NodeRef* e2,
201  NodeRef* e3, NodeRef* e4, NodeRef* e5, NodeRef* e6);
202  static NodeRef* choiceL(const std::string& name, const py::list& l);
203  // in-range.
204  static NodeRef* inRange(const std::string& name, NodeRef* lo, NodeRef* hi);
205  // read-slice.
206  static NodeRef* readSlice(const std::string& name, NodeRef* bv, int w);
207  // read-chunk.
208  static NodeRef* readChunk(const std::string& name, NodeRef* bv, int w);
209  // write-slice.
210  static NodeRef* writeSlice(const std::string& name, NodeRef* bv, NodeRef* wr);
211  // write-chunk
212  static NodeRef* writeChunk(const std::string& name, NodeRef* bv, NodeRef* wr);
213 
214  // simplify.
215  static NodeRef* simplify(NodeRef& assump, NodeRef& exp);
216 
217  // hashing.
218  size_t hash() const;
219 
220 private:
221  // ---------------------- HELPERS ----------------------------- //
222  NodeRef* _unOp(BoolOp::Op boolOp, BitvectorOp::Op bvOp,
223  const char* opName) const;
224  NodeRef* _binOp(BoolOp::Op boolOp, BitvectorOp::Op bvOp, const char* opName,
225  NodeRef* other) const;
226  NodeRef* _binOp(BitvectorOp::Op op, NodeRef* other) const;
227  NodeRef* _binOp(BitvectorOp::Op op, int r) const;
228  NodeRef* _binOpR(BitvectorOp::Op op, int r) const;
229  NodeRef* _cmpOp(BoolOp::Op op, NodeRef& other, bool bvtype) const;
230  NodeRef* _cmpOp(BoolOp::Op op, int r) const;
231 
232  static NodeRef* _binOp(BoolOp::Op boolOp, BitvectorOp::Op bvOp,
233  const char* opName, NodeRef* l, NodeRef* r);
234  static NodeRef* _binOp(BoolOp::Op op, NodeRef& l, NodeRef& r);
235  static NodeRef* _binOp(BitvectorOp::Op op, NodeRef* l, NodeRef* r);
236  static NodeRef* _binOp(BitvectorOp::Op Op, NodeRef* l, int r);
237  static NodeRef* _binOpR(BitvectorOp::Op op, int l, NodeRef* r);
238  static NodeRef* _cmpOp(BoolOp::Op op, NodeRef& l, NodeRef& r, bool bvtype);
239  static NodeRef* _cmpOp(BoolOp::Op op, NodeRef& l, int r);
240  static NodeRef* _triOp(BoolOp::Op boolOp, BitvectorOp::Op bvOp,
241  MemOp::Op memOp, NodeRef& arg0, NodeRef& arg1,
242  NodeRef& arg2);
243  static NodeRef* _naryOp(BitvectorOp::Op bvOp, nptr_vec_t& args);
244  static NodeRef* _extractOp(const NodeRef* bv, int beg, int end);
245  static NodeRef* _choice(const std::string& name, const nptr_vec_t& args);
246 };
247 
248 // stream output.
249 std::ostream& operator<<(std::ostream& out, const NodeRef& node);
250 
251 // ---------------------------------------------------------------------- //
252 } // namespace ilasynth
253 
254 #endif
static NodeRef * readSlice(const std::string &name, NodeRef *bv, int w)
NodeRef * _unOp(BoolOp::Op boolOp, BitvectorOp::Op bvOp, const char *opName) const
static NodeRef * rsdivInt(int l, NodeRef *r)
std::string getName() const
static NodeRef * ashr(NodeRef *l, NodeRef *r)
NodeRef * getItem(NodeRef *idx) const
NodeRef * rsubInt(int r) const
static NodeRef * load(NodeRef *mem, NodeRef *addr)
NodeRef * ugt(NodeRef &other) const
NodeRef * logicalAnd(NodeRef *other) const
NodeRef * uremInt(int r)
NodeRef * ruremInt(int l)
NodeRef * ugeInt(int r) const
NodeRef * complement() const
static NodeRef * _triOp(BoolOp::Op boolOp, BitvectorOp::Op bvOp, MemOp::Op memOp, NodeRef &arg0, NodeRef &arg1, NodeRef &arg2)
NodeRef * logicalXor(NodeRef *other) const
NodeRef * add(NodeRef *other) const
NodeRef * mulInt(int r) const
static NodeRef * rsmodInt(int l, NodeRef *r)
NodeRef & operator=(const NodeRef &other)
NodeRef * ultInt(int r) const
static NodeRef * rrotate(NodeRef *obj, int par)
static NodeRef * sgtInt(NodeRef &l, int r)
static NodeRef * zero_extend(NodeRef *obj, int outWidth)
static NodeRef * sremInt(NodeRef *l, int r)
static NodeRef * _extractOp(const NodeRef *bv, int beg, int end)
static NodeRef * choiceL(const std::string &name, const py::list &l)
static NodeRef * writeSlice(const std::string &name, NodeRef *bv, NodeRef *wr)
NodeRef * logicalOrRInt(int l) const
Definition: type.hpp:11
static NodeRef * sgt(NodeRef &l, NodeRef &r)
static NodeRef * logicalXnor(NodeRef *l, NodeRef *r)
static NodeRef * ashrInt(NodeRef *l, int r)
NodeRef * eq(NodeRef &other) const
py::object value() const
std::vector< nptr_t > nptr_vec_t
Definition: node.hpp:27
NodeRef * uleInt(int r) const
Op
Definition: bool.hpp:84
NodeRef * rlshrInt(int r) const
static NodeRef * simplify(NodeRef &assump, NodeRef &exp)
static NodeRef * extract(const NodeRef *obj, int hi, int lo)
static NodeRef * smod(NodeRef *l, NodeRef *r)
static NodeRef * choice3(const std::string &name, NodeRef *e1, NodeRef *e2, NodeRef *e3)
static NodeRef * sltInt(NodeRef &l, int r)
NodeRef * ult(NodeRef &other) const
static NodeRef * storeblock(NodeRef *mem, NodeRef *addr, NodeRef *data)
static NodeRef * appfunc0(NodeRef *fun)
static NodeRef * appfuncL(NodeRef *fun, const py::list &l)
static NodeRef * rashrInt(int l, NodeRef *r)
static NodeRef * _choice(const std::string &name, const nptr_vec_t &args)
NodeRef * slice(int hi, int lo) const
boost::shared_ptr< Node > nptr_t
Definition: node.hpp:24
NodeRef * logicalXorInt(int r) const
NodeRef * logicalAndInt(int r) const
nptr_t node
Definition: ast.hpp:31
static NodeRef * choice2(const std::string &name, NodeRef *e1, NodeRef *e2)
static NodeRef * sdivInt(NodeRef *l, int r)
static NodeRef * srem(NodeRef *l, NodeRef *r)
static NodeRef * sign_extend(NodeRef *obg, int outWidth)
static NodeRef * nonzero(NodeRef *obj)
NodeRef * shl(NodeRef *other) const
NodeRef * addInt(int r) const
NodeRef * raddInt(int r) const
static NodeRef * appfunc1(NodeRef *fun, NodeRef *arg)
static NodeRef * storeblockB(NodeRef *mem, NodeRef *addr, NodeRef *data)
NodeRef * subInt(int r) const
static NodeRef * loadblock(NodeRef *mem, NodeRef *addr, int chunks)
static NodeRef * sgeInt(NodeRef &l, int r)
NodeRef * sub(NodeRef *other) const
NodeRef * getItemInt(int idx) const
static NodeRef * store(NodeRef *mem, NodeRef *addr, NodeRef *data)
static NodeRef * appfunc2(NodeRef *fun, NodeRef *arg0, NodeRef *arg1)
NodeRef * logicalOrInt(int r) const
NodeRef * uge(NodeRef &other) const
Definition: abstraction.hpp:21
NodeRef * urem(NodeRef *r)
NodeRef * neq(NodeRef &other) const
Definition: node.hpp:55
NodeRef * mul(NodeRef *other) const
NodeRef * logicalXorRInt(int l) const
NodeRef * ule(NodeRef &other) const
static NodeRef * sle(NodeRef &l, NodeRef &r)
NodeRef * udivInt(int r) const
NodeRef * lshrInt(int r) const
static NodeRef * sleInt(NodeRef &l, int r)
NodeRef * logicalAndRInt(int r) const
static NodeRef * readChunk(const std::string &name, NodeRef *bv, int w)
static NodeRef * sdiv(NodeRef *l, NodeRef *r)
NodeRef * _binOp(BoolOp::Op boolOp, BitvectorOp::Op bvOp, const char *opName, NodeRef *other) const
NodeRef * rmulInt(int r) const
static NodeRef * lrotate(NodeRef *obj, int par)
static NodeRef * ite(NodeRef &cond, NodeRef &trueExp, NodeRef &falseExp)
NodeType getType() const
NodeRef * rshlInt(int r) const
NodeRef * negate() const
size_t hash() const
NodeRef * _cmpOp(BoolOp::Op op, NodeRef &other, bool bvtype) const
static NodeRef * writeChunk(const std::string &name, NodeRef *bv, NodeRef *wr)
NodeRef * ugtInt(int r) const
static NodeRef * _naryOp(BitvectorOp::Op bvOp, nptr_vec_t &args)
static NodeRef * inRange(const std::string &name, NodeRef *lo, NodeRef *hi)
static NodeRef * logicalNor(NodeRef *l, NodeRef *r)
static NodeRef * logicalNand(NodeRef *l, NodeRef *r)
static NodeRef * imply(NodeRef &p, NodeRef &q)
bool equal(NodeRef *other) const
Op
Definition: bitvec.hpp:89
NodeRef * _binOpR(BitvectorOp::Op op, int r) const
Definition: ast.hpp:29
void setRefName(const std::string &refName)
Op
Definition: mem.hpp:69
static NodeRef * loadblockB(NodeRef *mem, NodeRef *addr, int chunks)
NodeRef * neqInt(int r) const
static NodeRef * choice6(const std::string &name, NodeRef *e1, NodeRef *e2, NodeRef *e3, NodeRef *e4, NodeRef *e5, NodeRef *e6)
NodeRef * shlInt(int r) const
static NodeRef * choice4(const std::string &name, NodeRef *e1, NodeRef *e2, NodeRef *e3, NodeRef *e4)
NodeRef * lshr(NodeRef *other) const
NodeRef * logicalOr(NodeRef *other) const
static NodeRef * concat(NodeRef *lo, NodeRef *hi)
NodeRef * rudivInt(int r) const
std::ostream & operator<<(std::ostream &out, const Node &that)
static NodeRef * concatList(const py::list &l)
NodeRef * eqInt(int r) const
static NodeRef * smodInt(NodeRef *l, int r)
static NodeRef * rsremInt(int l, NodeRef *r)
static NodeRef * slt(NodeRef &l, NodeRef &r)
static NodeRef * choice5(const std::string &name, NodeRef *e1, NodeRef *e2, NodeRef *e3, NodeRef *e4, NodeRef *e5)
static NodeRef * sge(NodeRef &l, NodeRef &r)
NodeRef * udiv(NodeRef *other) const