source: icGREP/icgrep-devel/icgrep/pablo/codegenstate.h @ 4410

Last change on this file since 4410 was 4410, checked in by nmedfort, 5 years ago

Changes to support 3-operand form for all instructions. CSE disabled but partially redundant now.

File size: 7.6 KB
Line 
1/*
2 *  Copyright (c) 2014 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icgrep is a trademark of International Characters.
5 */
6
7#ifndef PS_PABLOS_H
8#define PS_PABLOS_H
9
10#include <pablo/pabloAST.h>
11#include <pablo/pabloAST.h>
12#include <pablo/pe_advance.h>
13#include <pablo/pe_and.h>
14#include <pablo/pe_call.h>
15#include <pablo/pe_matchstar.h>
16#include <pablo/pe_next.h>
17#include <pablo/pe_not.h>
18#include <pablo/pe_ones.h>
19#include <pablo/pe_or.h>
20#include <pablo/pe_scanthru.h>
21#include <pablo/pe_sel.h>
22#include <pablo/pe_string.h>
23#include <pablo/pe_var.h>
24#include <pablo/pe_xor.h>
25#include <pablo/pe_zeroes.h>
26#include <pablo/ps_assign.h>
27#include <pablo/ps_if.h>
28#include <pablo/ps_while.h>
29#include <pablo/symbol_generator.h>
30#include <map>
31#include <vector>
32#include <string>
33#include <array>
34#include <tuple>
35#include <pablo/printer_pablos.h>
36
37namespace pablo {
38
39class PabloBlock : public StatementList {
40    friend class pablo::PabloAST;
41public:
42
43    inline static PabloBlock & Create() {
44        return *(new PabloBlock());
45    }
46
47    inline static PabloBlock & Create(PabloBlock & predecessor) {
48        return *(new PabloBlock(&predecessor));
49    }
50
51    PabloAST * createAdvance(PabloAST * expr, const int shiftAmount);
52
53    inline Zeroes * createZeroes() const {
54        return mZeroes;
55    }
56
57    inline Ones * createOnes() const {
58        return mOnes;
59    }
60
61    Call * createCall(const std::string name);
62
63    Assign * createAssign(const std::string prefix, PabloAST * expr, const int outputIndex = -1)  {
64        // Note: we cannot just use the findOrMake method to obtain this; an Assign node cannot be considered
65        // unique until we prove it has no Next node associated with it. But the Assign node must be created
66        // before the Next node. Should we create a "Constant" flag for this?
67        Assign * assign = new Assign(expr, outputIndex, mSymbolGenerator->make(prefix), this);
68        push_back(assign);
69        return assign;
70    }
71
72    Var * createVar(const std::string);
73
74    PabloAST * createVar(const PabloAST * const) {
75        throw std::runtime_error("Var objects should only refer to external Vars (i.e., input basis bit streams). Use Assign object directly.");
76    }
77
78    Next * createNext(Assign * assign, PabloAST * expr);
79
80    PabloAST * createAnd(PabloAST * expr1, PabloAST * expr2);
81
82    PabloAST * createNot(PabloAST * expr);
83
84    PabloAST * createOr(PabloAST * expr1, PabloAST * expr2);
85
86    PabloAST * createXor(PabloAST * expr1, PabloAST * expr2);
87
88    PabloAST * createMatchStar(PabloAST * marker, PabloAST * charclass);
89
90    PabloAST * createScanThru(PabloAST * from, PabloAST * thru);
91
92    PabloAST * createSel(PabloAST * condition, PabloAST * trueExpr, PabloAST * falseExpr);
93
94    And * createAndImm(PabloAST * expr1, PabloAST * expr2);
95
96    Not * createNotImm(PabloAST * expr);
97
98    Or * createOrImm(PabloAST * expr1, PabloAST * expr2);
99
100    Xor * createXorImm(PabloAST * expr1, PabloAST * expr2);
101
102    Sel * createSelImm(PabloAST * condition, PabloAST * trueExpr, PabloAST * falseExpr);
103
104    inline If * createIf(PabloAST * condition, std::vector<Assign *> && definedVars, PabloBlock & body) {
105        If * statement = new If(condition, std::move(definedVars), body, this);
106        push_back(statement);
107        return statement;
108    }
109
110    inline While * createWhile(PabloAST * cond, PabloBlock & body) {
111        While * statement = new While(cond, body, this);
112        push_back(statement);
113        return statement;
114    }
115
116    template<typename... Args>
117    struct ExpressionMap {
118        enum {N = sizeof...(Args)};
119        typedef ExpressionMap<Args...> MapType;
120        typedef std::tuple<PabloAST::ClassTypeId, Args...> Key;
121
122        inline ExpressionMap(MapType * predecessor)
123        : mPredecessor(predecessor)
124        {
125
126        }
127
128        template <class Type, typename... Params>
129        inline std::pair<Type *, bool> findOrMake(const PabloAST::ClassTypeId type, Args... args, Params... params) {
130            Key key = std::make_tuple(type, args...);
131            PabloAST * const f = find(key);
132            if (f) {
133                return std::make_pair(cast<Type>(f), false);
134            }
135            PabloAST * const expr = new Type(std::forward<Args>(args)..., std::forward<Params>(params)...);
136            insert(std::move(key), expr);
137            return std::make_pair(cast<Type>(expr), isa<Statement>(expr));
138        }
139
140        template <class Functor, typename... Params>
141        inline PabloAST * findOrCall(const PabloAST::ClassTypeId type, Args... args, Params... params) {
142            Key key = std::make_tuple(type, args...);
143            PabloAST * const f = find(key);
144            if (f) {
145                return f;
146            }
147            Functor mf;
148            PabloAST * const expr = mf(std::forward<Args>(args)..., std::forward<Params>(params)...);
149            insert(std::move(key), expr);
150            return expr;
151        }
152
153        inline void insert(Key && key, PabloAST * expr) {
154            mMap.insert(std::make_pair(std::move(key), expr));
155        }
156
157        inline PabloAST * find(const Key & key) const {
158            // check this map to see if we have it
159            auto itr = mMap.find(key);
160            if (itr != mMap.end()) {
161                return itr->second;
162            }
163            // check any previous maps to see if it exists
164            auto * pred = mPredecessor;
165            while (pred) {
166                itr = pred->mMap.find(key);
167                if (itr == pred->mMap.end()) {
168                    pred = pred->mPredecessor;
169                    continue;
170                }
171                return itr->second;
172            }
173            return nullptr;
174        }
175
176    private:
177        MapType * const             mPredecessor;
178        std::map<Key, PabloAST *>   mMap;
179    };
180
181    inline StatementList & statements() {
182        return *this;
183    }
184
185    inline const StatementList & statements() const {
186        return *this;
187    }
188    inline String * getName(const std::string name) const {
189        return mSymbolGenerator->get(name);
190    }
191    inline String * makeName(const std::string prefix) const {
192        return mSymbolGenerator->make(prefix);
193    }
194protected:
195    PabloBlock()
196    : mZeroes(new Zeroes())
197    , mOnes(new Ones())
198    , mSymbolGenerator(new SymbolGenerator())
199    , mUnary(nullptr)
200    , mUnaryWithInt(nullptr)
201    , mBinary(nullptr)
202    , mTernary(nullptr)
203    {
204
205    }
206
207    PabloBlock(PabloBlock * predecessor)
208    : mZeroes(predecessor->mZeroes) // inherit the original "Zeroes" variable for simplicity
209    , mOnes(predecessor->mOnes) // inherit the original "Ones" variable for simplicity
210    , mSymbolGenerator(predecessor->mSymbolGenerator)
211    , mUnary(&(predecessor->mUnary))
212    , mUnaryWithInt(&(predecessor->mUnaryWithInt))
213    , mBinary(&(predecessor->mBinary))
214    , mTernary(&(predecessor->mTernary))
215    {
216
217    }
218
219    void* operator new (std::size_t size) noexcept {
220        return PabloAST::mAllocator.allocate(size);
221    }
222
223    template<typename Type>
224    inline Type appendIfNew(std::pair<Type, bool> retVal) {
225        if (std::get<1>(retVal)) {
226            push_back(cast<Statement>(std::get<0>(retVal)));
227        }
228        return std::get<0>(retVal);
229    }
230
231private:       
232    Zeroes * const                                      mZeroes;
233    Ones * const                                        mOnes;
234    SymbolGenerator * const                             mSymbolGenerator;
235    ExpressionMap<PabloAST *>                           mUnary;
236    ExpressionMap<PabloAST *, int>                      mUnaryWithInt;
237    ExpressionMap<PabloAST *, PabloAST *>               mBinary;
238    ExpressionMap<PabloAST *, PabloAST *, PabloAST *>   mTernary;
239};
240
241}
242
243#endif // PS_PABLOS_H
Note: See TracBrowser for help on using the repository browser.