bmv2
Designing your own switch target with bmv2
Loading...
Searching...
No Matches
stateful.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
34
35#ifndef BM_BM_SIM_STATEFUL_H_
36#define BM_BM_SIM_STATEFUL_H_
37
38#include <functional>
39#include <mutex>
40#include <string>
41#include <unordered_set>
42#include <unordered_map>
43#include <vector>
44
45#include <boost/thread/locks.hpp> // for boost::lock
46
47#include "bignum.h"
48#include "data.h"
49#include "named_p4object.h"
50#include "short_alloc.h"
51
52namespace bm {
53
54class RegisterArray; // forward declaration
55
58class Register : public Data {
59 public:
60 enum RegisterErrorCode {
61 SUCCESS = 0,
62 INVALID_REGISTER_NAME,
63 INVALID_INDEX,
64 ERROR
65 };
66
67 public:
68 Register(int nbits, const RegisterArray *register_array);
69
70 void export_bytes() override;
71
72 private:
73 Bignum mask{1};
74 // keep a pointer to parent RegisterArray so that export_bytes() can notify
75 // write operations
76 const RegisterArray *register_array;
77};
78
79using register_array_id_t = p4object_id_t;
80
93 friend class RegisterSync;
94 friend class Register;
95
96 public:
97 using iterator = std::vector<Register>::iterator;
98 using const_iterator = std::vector<Register>::const_iterator;
99
100 using UniqueLock = std::unique_lock<std::mutex>;
101
104 using Notifier = std::function<void(size_t idx)>;
105
106 RegisterArray(const std::string &name, p4object_id_t id,
107 size_t size, int bitwidth);
108
110 Register &operator[](size_t idx) {
111 assert(idx < size());
112 return registers[idx];
113 }
114
116 const Register &operator[](size_t idx) const {
117 assert(idx < size());
118 return registers[idx];
119 }
120
123 Register &at(size_t idx) {
124 return registers.at(idx);
125 }
126
128 const Register &at(size_t idx) const {
129 return registers.at(idx);
130 }
131
132 // iterators
133
135 iterator begin() { return registers.begin(); }
136
138 const_iterator begin() const { return registers.begin(); }
139
141 iterator end() { return registers.end(); }
142
144 const_iterator end() const { return registers.end(); }
145
148 size_t size() const { return registers.size(); }
149
150 void reset_state();
151
157
163 UniqueLock unique_lock() const { return UniqueLock(m_mutex); }
164 // NOLINTNEXTLINE(runtime/references)
165 void unlock(UniqueLock &lock) const { lock.unlock(); }
166
167 private:
168 void notify(const Register &reg) const;
169
170 std::vector<Register> registers{};
171 mutable std::mutex m_mutex{};
172 int bitwidth{};
173 std::vector<Notifier> notifiers{};
174};
175
176
177// This class was added to provide some measure of concurrency support for
178// register accesses. Every time an action is executed, this action is given
179// exclusive access to all the registers it is referring to. Same thing for a
180// parse state.
181class RegisterSync {
182 public:
183 using Lock = RegisterArray::UniqueLock;
184
185 template <size_t NumLocks = 4>
186 using LockVector = std::vector<
187 Lock, ::detail::short_alloc<Lock, NumLocks * sizeof(Lock), alignof(Lock)> >;
188
189 struct RegisterLocks {
190 LockVector<>::allocator_type::arena_type a;
191 LockVector<> v{a};
192 };
193
194 void add_register_array(const RegisterArray *register_array);
195
196 void merge_from(const RegisterSync &other);
197
198 // tried NRVO, but RegisterLocks not movable
199 void lock(RegisterLocks *RL) const {
200 for (auto m : mutexes) RL->v.emplace_back(*m, std::defer_lock);
201 boost::lock(RL->v.begin(), RL->v.end());
202 }
203
204 private:
205 mutable std::vector<std::mutex *> mutexes{};
206 std::unordered_set<const RegisterArray *> register_arrays{};
207};
208
209} // namespace bm
210
211#endif // BM_BM_SIM_STATEFUL_H_
Definition named_p4object.h:39
Definition stateful.h:92
const_iterator begin() const
NC.
Definition stateful.h:138
iterator begin()
NC.
Definition stateful.h:135
const_iterator end() const
NC.
Definition stateful.h:144
iterator end()
NC.
Definition stateful.h:141
const Register & at(size_t idx) const
Definition stateful.h:128
void register_notifier(Notifier notifier)
size_t size() const
Definition stateful.h:148
const Register & operator[](size_t idx) const
Access the register at position idx, asserts if bad idx.
Definition stateful.h:116
std::function< void(size_t idx)> Notifier
Definition stateful.h:104
Register & at(size_t idx)
Definition stateful.h:123
UniqueLock unique_lock() const
Definition stateful.h:163
Register & operator[](size_t idx)
Access the register at position idx, asserts if bad idx.
Definition stateful.h:110
Definition stateful.h:58