bmv2
Designing your own switch target with bmv2
Loading...
Searching...
No Matches
expressions.h
1/* Copyright 2013-2019 Barefoot Networks, Inc.
2 * Copyright 2019 VMware, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 * Antonin Bas
19 *
20 */
21
22#ifndef BM_BM_SIM_EXPRESSIONS_H_
23#define BM_BM_SIM_EXPRESSIONS_H_
24
25#include <unordered_map>
26#include <string>
27#include <vector>
28
29#include "data.h"
30#include "headers.h"
31#include "header_unions.h"
32#include "phv_forward.h"
33#include "stacks.h"
34
35namespace bm {
36
37class RegisterArray;
38class RegisterSync;
39
40struct ExpressionTemps;
41
42enum class ExprOpcode {
43 LOAD_FIELD, LOAD_HEADER, LOAD_HEADER_STACK, LOAD_LAST_HEADER_STACK_FIELD,
44 LOAD_UNION, LOAD_UNION_STACK, LOAD_BOOL, LOAD_CONST, LOAD_LOCAL,
45 LOAD_REGISTER_REF, LOAD_REGISTER_GEN,
46 ADD, SUB, MOD, DIV, MUL, SHIFT_LEFT, SHIFT_RIGHT,
47 EQ_DATA, NEQ_DATA, GT_DATA, LT_DATA, GET_DATA, LET_DATA,
48 EQ_HEADER, NEQ_HEADER,
49 EQ_UNION, NEQ_UNION,
50 EQ_BOOL, NEQ_BOOL,
51 AND, OR, NOT,
52 BIT_AND, BIT_OR, BIT_XOR, BIT_NEG,
53 VALID_HEADER, VALID_UNION,
54 TERNARY_OP, SKIP,
55 TWO_COMP_MOD,
56 USAT_CAST, SAT_CAST,
57 DATA_TO_BOOL, BOOL_TO_DATA,
58 DEREFERENCE_HEADER_STACK,
59 DEREFERENCE_UNION_STACK,
60 LAST_STACK_INDEX, SIZE_STACK,
61 ACCESS_FIELD,
62 ACCESS_UNION_HEADER,
63};
64
65enum class ExprType {
66 UNKNOWN, DATA, HEADER, HEADER_STACK, BOOL, UNION, UNION_STACK
67};
68
69class ExprOpcodesMap {
70 public:
71 static ExprOpcode get_opcode(std::string expr_name);
72
73 private:
74 static ExprOpcodesMap *get_instance();
75
76 ExprOpcodesMap();
77
78 private:
79 std::unordered_map<std::string, ExprOpcode> opcodes_map{};
80};
81
82class ExprOpcodesUtils {
83 public:
84 static ExprOpcode get_eq_opcode(ExprType expr_type);
85 static ExprOpcode get_neq_opcode(ExprType expr_type);
86
87 static ExprType get_opcode_type(ExprOpcode opcode);
88};
89
90struct Op {
91 ExprOpcode opcode;
92
93 union {
94 int data_dest_index;
95
96 struct {
97 header_id_t header;
98 int field_offset;
99 } field;
100
101 header_id_t header;
102
103 header_stack_id_t header_stack;
104
105 struct {
106 header_stack_id_t header_stack;
107 int field_offset;
108 } stack_field;
109
110 header_union_id_t header_union;
111
112 header_union_stack_id_t header_union_stack;
113
114 bool bool_value;
115
116 int const_offset;
117
118 int local_offset;
119
120 int field_offset;
121
122 int header_offset;
123
124 // In theory, if registers cannot be resized, I could directly store a
125 // pointer to the correct register cell, i.e. &(*array)[idx]. However, this
126 // gives me more flexibility in case I want to be able to resize the
127 // registers arbitrarily in the future.
128 struct {
129 RegisterArray *array;
130 unsigned int idx;
131 } register_ref;
132
133 RegisterArray *register_array;
134
135 int skip_num;
136 };
137};
138
139class Expression {
140 public:
141 Expression();
142
143 virtual ~Expression() { }
144
145 void push_back_load_field(header_id_t header, int field_offset);
146 void push_back_load_bool(bool value);
147 void push_back_load_header(header_id_t header);
148 void push_back_load_header_stack(header_stack_id_t header_stack);
149 void push_back_load_last_header_stack_field(header_stack_id_t header_stack,
150 int field_offset);
151 void push_back_load_header_union(header_union_id_t header_union);
152 void push_back_load_header_union_stack(
153 header_union_stack_id_t header_union_stack);
154 void push_back_load_const(const Data &data);
155 void push_back_load_local(const int offset);
156 void push_back_load_register_ref(RegisterArray *register_array,
157 unsigned int idx);
158 void push_back_load_register_gen(RegisterArray *register_array);
159 void push_back_op(ExprOpcode opcode);
160 void push_back_ternary_op(const Expression &e1, const Expression &e2);
161 void push_back_access_field(int field_offset);
162 void push_back_access_union_header(int header_offset);
163
164 void build();
165
166 void grab_register_accesses(RegisterSync *register_sync) const;
167
168 bool eval_bool(const PHV &phv, const std::vector<Data> &locals = {}) const;
169 Data eval_arith(const PHV &phv, const std::vector<Data> &locals = {}) const;
170 void eval_arith(const PHV &phv, Data *data,
171 const std::vector<Data> &locals = {}) const;
172 Data &eval_arith_lvalue(PHV *phv, const std::vector<Data> &locals = {}) const;
173 Header &eval_header(PHV *phv, const std::vector<Data> &locals = {}) const;
174 HeaderStack &eval_header_stack(
175 PHV *phv, const std::vector<Data> &locals = {}) const;
176 HeaderUnion &eval_header_union(
177 PHV *phv, const std::vector<Data> &locals = {}) const;
178 HeaderUnionStack &eval_header_union_stack(
179 PHV *phv, const std::vector<Data> &locals = {}) const;
180
181 bool empty() const;
182
183 // I am authorizing copy for this object
184 Expression(const Expression &other) = default;
185 Expression &operator=(const Expression &other) = default;
186
187 Expression(Expression &&other) /*noexcept*/ = default;
188 Expression &operator=(Expression &&other) /*noexcept*/ = default;
189
190 private:
191 int assign_dest_registers();
192 void eval_(const PHV &phv,
193 const std::vector<Data> &locals,
194 ExpressionTemps *temps) const;
195 size_t get_num_ops() const;
196 void append_expression(const Expression &e);
197
198 private:
199 std::vector<Op> ops{};
200 std::vector<Data> const_values{};
201 int data_registers_cnt{0};
202 bool built{false};
203
204 friend class VLHeaderExpression;
205};
206
207
208class ArithExpression : public Expression {
209 public:
210 void eval(const PHV &phv, Data *data,
211 const std::vector<Data> &locals = {}) const {
212 eval_arith(phv, data, locals);
213 }
214
215 Data &eval_lvalue(PHV *phv, const std::vector<Data> &locals = {}) const {
216 return eval_arith_lvalue(phv, locals);
217 }
218};
219
220
221class BoolExpression : public Expression {
222 public:
223 bool eval(const PHV &phv, const std::vector<Data> &locals = {}) const {
224 return eval_bool(phv, locals);
225 }
226};
227
228
229class VLHeaderExpression {
230 public:
231 explicit VLHeaderExpression(const ArithExpression &expr);
232
233 ArithExpression resolve(header_id_t header_id);
234
235 const std::vector<int> &get_input_offsets() const;
236
237 private:
238 ArithExpression expr;
239 std::vector<int> offsets{};
240};
241
242} // namespace bm
243
244#endif // BM_BM_SIM_EXPRESSIONS_H_
detail::MyStack< Header > HeaderStack
Definition stacks.h:212
detail::MyStack< HeaderUnion > HeaderUnionStack
Definition stacks.h:223