23 #ifndef BM_BM_SIM_EXTERN_H_
24 #define BM_BM_SIM_EXTERN_H_
26 #include <unordered_map>
29 #include <type_traits>
40 class ExternFactoryMap {
42 using ExternFactoryFn = std::function<std::unique_ptr<ExternType>()>;
44 static ExternFactoryMap *get_instance();
46 int register_extern_type(
const char *extern_type_name, ExternFactoryFn fn);
48 std::unique_ptr<ExternType> get_extern_instance(
49 const std::string &extern_type_name)
const;
52 std::unordered_map<std::string, ExternFactoryFn> factory_map{};
55 #define _BM_EXTERN_TO_STRING(name) #name
57 #define BM_EXTERN_ADD_EXTERN_PREFIX(name) __extern_##name
59 #define BM_REGISTER_EXTERN_W_NAME(extern_name, extern__) \
60 static_assert(std::is_default_constructible<extern__>::value, \
61 "User-defined extern type " #extern__ \
62 " needs to be default-constructible"); \
63 int _extern_##extern_name##_create_ = \
64 ::bm::ExternFactoryMap::get_instance()->register_extern_type( \
66 [](){ return std::unique_ptr<::bm::ExternType>(new extern__()); });
68 #define BM_REGISTER_EXTERN(extern_name) \
69 BM_REGISTER_EXTERN_W_NAME(extern_name, extern_name)
71 #define BM_REGISTER_EXTERN_W_NAME_METHOD(extern_name, extern__, \
72 extern_method_name, ...) \
73 template <typename... Args> \
74 struct _##extern_name##_##extern_method_name##_0 \
75 : public ::bm::ActionPrimitive<::bm::ExternType *, Args...> { \
76 void operator ()(::bm::ExternType *instance, Args... args) override { \
77 auto lock = instance->_unique_lock(); \
78 instance->_set_packet_ptr(&this->get_packet()); \
79 dynamic_cast<extern__ *>(instance)->extern_method_name(args...); \
82 struct _##extern_name##_##extern_method_name \
83 : public _##extern_name##_##extern_method_name##_0<__VA_ARGS__> {}; \
84 REGISTER_PRIMITIVE_W_NAME( \
85 _BM_EXTERN_TO_STRING(_##extern_name##_##extern_method_name), \
86 _##extern_name##_##extern_method_name)
88 #define BM_REGISTER_EXTERN_METHOD(extern_name, extern_method_name, ...) \
89 template <typename... Args> \
90 struct _##extern_name##_##extern_method_name##_0 \
91 : public ::bm::ActionPrimitive<::bm::ExternType *, Args...> { \
92 void operator ()(::bm::ExternType *instance, Args... args) override { \
93 auto lock = instance->_unique_lock(); \
94 instance->_set_packet_ptr(&this->get_packet()); \
95 dynamic_cast<extern_name *>(instance)->extern_method_name(args...); \
98 struct _##extern_name##_##extern_method_name \
99 : public _##extern_name##_##extern_method_name##_0<__VA_ARGS__> {}; \
100 REGISTER_PRIMITIVE(_##extern_name##_##extern_method_name)
102 #define BM_REGISTER_EXTERN_FUNCTION_W_NAME(extern_function_name, \
103 __extern_func, ...) \
104 template <typename... Args> \
105 struct __extern_##__extern_func##_0 \
106 : public ::bm::ActionPrimitive<Args...> { \
107 void operator ()(Args... args) override { \
108 __extern_func(args...); \
111 struct __extern_##__extern_func \
112 : public __extern_##__extern_func##_0<__VA_ARGS__> {}; \
113 REGISTER_PRIMITIVE_W_NAME(_BM_EXTERN_TO_STRING(extern_function_name), \
114 __extern_##__extern_func)
116 #define BM_REGISTER_EXTERN_FUNCTION(extern_function_name, ...) \
117 BM_REGISTER_EXTERN_FUNCTION_W_NAME(extern_function_name, \
118 extern_function_name, __VA_ARGS__)
120 #define BM_EXTERN_ATTRIBUTES void _register_attributes() override
122 #define BM_EXTERN_ATTRIBUTE_ADD(attr_name) \
123 _add_attribute(#attr_name, static_cast<void *>(&attr_name));
130 virtual ~ExternType() { }
135 void _set_p4objects(P4Objects *p4objects);
137 template <
typename T>
138 void _set_attribute(
const std::string &attr_name,
const T &v) {
139 T *attr =
static_cast<T *
>(attributes.at(attr_name));
143 bool _has_attribute(
const std::string &attr_name)
const {
144 return attributes.find(attr_name) != attributes.end();
147 void _set_packet_ptr(Packet *pkt_ptr) { pkt = pkt_ptr; }
150 void _set_name_and_id(
const std::string &name, p4object_id_t
id);
152 const std::string &get_name()
const {
return name; }
153 p4object_id_t get_id()
const {
return id; }
155 using UniqueLock = std::unique_lock<std::mutex>;
156 UniqueLock _unique_lock() {
return UniqueLock(mutex); }
158 virtual void _register_attributes() = 0;
160 virtual void init() { }
163 void _add_attribute(
const std::string &name,
void *ptr) {
164 attributes[name] = ptr;
167 Packet &get_packet()
const {
return *pkt; }
169 P4Objects &get_p4objects()
const {
return *p4objects; }
173 std::unordered_map<std::string, void *> attributes;
174 mutable std::mutex mutex{};
175 Packet *pkt{
nullptr};
183 P4Objects *p4objects{
nullptr};
188 #endif // BM_BM_SIM_EXTERN_H_