bmv2
Designing your own switch target with bmv2
Loading...
Searching...
No Matches
fields.h
Go to the documentation of this file.
1/* Copyright 2013-present Barefoot Networks, Inc.
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16/*
17 * Antonin Bas (antonin@barefootnetworks.com)
18 *
19 */
20
22
23#ifndef BM_BM_SIM_FIELDS_H_
24#define BM_BM_SIM_FIELDS_H_
25
26#include <bm/config.h>
27
28#include <algorithm> // for std::copy
29
30#include <cassert>
31
32#include "data.h"
33#include "bytecontainer.h"
34#include "bignum.h"
35#include "debugger.h"
36
37namespace bm {
38
39class Header;
40
46class Field : public Data {
47 public:
48 // Data() is called automatically
49 // I wanted to have a separate class for signed fields, inheriting from
50 // Field. Unfortunately that would require adding an extra level of
51 // indirection in Header (for the field vector), so I am sticking to this for
52 // now.
53 explicit Field(int nbits, Header *parent_hdr, bool arith_flag = true,
54 bool is_signed = false, bool hidden = false, bool VL = false,
55 bool is_saturating = false);
56
57 // to avoid dynamic resizing of the Bytecontainer, which would invalide field
58 // references
59 void reserve_VL(size_t max_bytes);
60
61 // Overload set? Make it more generic (arbitary length) ?
62 // It is probably only going to be used by the checksum engine anyway...
63 void set_bytes(const char *src_bytes, int len) {
64 assert(len == nbytes);
65 std::copy(src_bytes, src_bytes + len, bytes.begin());
66 if (arith) sync_value();
67 }
68
69 void sync_value() {
70 bignum::import_bytes(&value, bytes.data(), nbytes);
71 if (is_signed && bignum::test_bit(value, nbits - 1)) {
72 bignum::clear_bit(&value, nbits - 1);
73 value += min;
74 }
75 written_to = true;
76 // TODO(antonin): should notifications be disabled for hidden fields?
77 DEBUGGER_NOTIFY_UPDATE(*packet_id, my_id, bytes.data(), nbits);
78 }
79
83 const ByteContainer &get_bytes() const {
84 return bytes;
85 }
86
90 int get_nbytes() const {
91 return nbytes;
92 }
93
95 int get_nbits() const {
96 return nbits;
97 }
98
99 void set_arith(bool arith_flag) { arith = arith_flag; }
100
101 bool get_arith_flag() const { return arith; }
102
103 void export_bytes() override {
104 std::fill(bytes.begin(), bytes.end(), 0); // very important !
105
106 if (is_saturating) {
107 if (value < min) value = min;
108 else if (value > max) value = max;
109 }
110
111 if (!is_signed) {
112 // is this efficient enough?
113 value &= mask;
114 bignum::export_bytes(bytes.data(), nbytes, value);
115 } else {
116 if (value < min || value > mask) {
117 value &= mask;
118 if (value > max) value -= (mask + 1);
119 }
120 if (value >= 0) {
121 bignum::export_bytes(bytes.data(), nbytes, value);
122 } else {
123 // e.g. if width is 8 and value is -127 (1000 0001), subtracting min
124 // (-128) one time gives us 1, a second time gives us 129, 129 has a
125 // bignum representation of 1000 0001, which is what we wanted
126 bignum::export_bytes(bytes.data(), nbytes, value - min - min);
127 }
128 }
129 written_to = true;
130 DEBUGGER_NOTIFY_UPDATE(*packet_id, my_id, bytes.data(), nbits);
131 }
132
133 // useful for header stacks
134 void swap_values(Field *other);
135
136 // returns the number of bits extracted
137 int extract(const char *data, int hdr_offset);
138
139 int extract_VL(const char *data, int hdr_offset, int computed_nbits);
140
141 // returns the number of bits deparsed
142 int deparse(char *data, int hdr_offset) const;
143
144 void assign_VL(const Field &src);
145
146 void reset_VL();
147
148#ifdef BM_DEBUG_ON
149 void set_id(uint64_t id) { my_id = id; }
150 void set_packet_id(const Debugger::PacketId *id) { packet_id = id; }
151#else
152 void set_id(uint64_t) { }
153 void set_packet_id(const Debugger::PacketId *) { }
154#endif
155
156 // it's important to have a way of copying a field value without the packet_id
157 // pointer. This is used by PHV::copy_headers().
158 void copy_value(const Field &src);
159
160 bool is_hidden() const {
161 return hidden;
162 }
163
164 bool is_VL() const {
165 return VL;
166 }
167
171 void set_written_to(bool v) {
172 written_to = v;
173 }
174
177 bool get_written_to() const {
178 return written_to;
179 }
180
181 private:
182 int nbits;
183 int nbytes;
184 ByteContainer bytes;
185 Header *parent_hdr;
186 bool is_signed{false};
187 bool hidden{false};
188 bool VL{false};
189 bool is_saturating{false};
190 bool written_to{false}; // used to keep track of whether a field was modified
191 Bignum mask{1};
192 Bignum max{1};
193 Bignum min{1};
194#ifdef BM_DEBUG_ON
195 uint64_t my_id{};
196 const Debugger::PacketId *packet_id{&Debugger::dummy_PacketId};
197#endif
198};
199
200} // namespace bm
201
202#endif // BM_BM_SIM_FIELDS_H_
Definition bytecontainer.h:39
char * data() noexcept
Definition bytecontainer.h:223
iterator begin()
NC.
Definition bytecontainer.h:125
iterator end()
NC.
Definition bytecontainer.h:131
Definition fields.h:46
const ByteContainer & get_bytes() const
Definition fields.h:83
void set_written_to(bool v)
Definition fields.h:171
bool get_written_to() const
Definition fields.h:177
int get_nbytes() const
Definition fields.h:90
int get_nbits() const
Get the number of bits occupied by this field in the packet header.
Definition fields.h:95
Definition headers.h:147