1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
|
// license:BSD-3-Clause
// copyright-holders:Couriersud
///
/// \file param.h
///
#ifndef NL_CORE_BASE_OBJECTS_H_
#define NL_CORE_BASE_OBJECTS_H_
#include "../nltypes.h"
#include "netlist_state.h"
#include "state_var.h"
#include "../plib/palloc.h"
#include "../plib/pchrono.h"
#include "../plib/pexception.h"
#include "../plib/plists.h"
#include "../plib/pmempool.h"
#include <unordered_map>
namespace netlist::detail
{
template <typename C, typename T>
struct property_store_t
{
using value_type = T;
using key_type = const C *;
using store_type = std::unordered_map<key_type, value_type>;
static void add(key_type obj, const value_type &value) noexcept
{
try
{
store().insert({obj, value});
}
catch (...)
{
plib::terminate("exception in property_store_t.add()");
}
}
static const value_type &get(key_type obj) noexcept
{
try
{
typename store_type::iterator ret(store().find(obj));
if (ret == store().end())
plib::terminate(
"object not found in property_store_t.get()");
return ret->second;
}
catch (...)
{
plib::terminate("exception in property_store_t.get()");
}
}
static void remove(key_type obj) noexcept
{
try
{
store().erase(store().find(obj));
}
catch (...)
{
plib::terminate("exception in property_store_t.remove()");
}
}
static store_type &store() noexcept
{
static store_type static_store;
return static_store;
}
};
// -------------------------------------------------------------------------
// object_t
// -------------------------------------------------------------------------
/// \brief The base class for netlist devices, terminals and parameters.
///
/// This class serves as the base class for all device, terminal and
/// objects.
class object_t
{
public:
/// \brief Constructor.
/// Every class derived from the object_t class must have a name.
///
/// \param aname string containing name of the object
explicit object_t(const pstring &aname) { props::add(this, aname); }
PCOPYASSIGNMOVE(object_t, delete)
/// \brief return name of the object
///
/// \returns name of the object.
const pstring &name() const noexcept { return props::get(this); }
protected:
using props = property_store_t<object_t, pstring>;
// only childs should be destructible
~object_t() noexcept { props::remove(this); }
private:
};
/// \brief Base class for all objects being owned by a netlist
///
/// The object provides adds \ref netlist_state_t and \ref netlist_t
/// accessors.
///
class netlist_object_t : public object_t
{
public:
explicit netlist_object_t(netlist_t &nl, const pstring &name)
: object_t(name)
, m_netlist(nl)
{
}
~netlist_object_t() = default;
PCOPYASSIGNMOVE(netlist_object_t, delete)
netlist_state_t & state() noexcept;
const netlist_state_t &state() const noexcept;
constexpr netlist_t & exec() noexcept { return m_netlist; }
constexpr const netlist_t &exec() const noexcept { return m_netlist; }
// to ease template design
template <typename T, typename... Args>
device_arena::unique_ptr<T> make_pool_object(Args &&...args) noexcept(
false)
{
return state().make_pool_object<T>(std::forward<Args>(args)...);
}
private:
netlist_t &m_netlist;
};
// -------------------------------------------------------------------------
// device_object_t
// -------------------------------------------------------------------------
/// \brief Base class for all objects being owned by a device.
///
/// Serves as the base class of all objects being owned by a device.
///
/// The class also supports device-less objects. In this case,
/// nullptr is passed in as the device object.
///
class device_object_t : public object_t
{
public:
/// \brief Constructor.
///
/// \param dev pointer to device owning the object.
/// \param name string holding the name of the device
device_object_t(core_device_t *dev, const pstring &name);
/// \brief returns reference to owning device.
/// \returns reference to owning device.
core_device_t & device() noexcept { return *m_device; }
const core_device_t &device() const noexcept { return *m_device; }
/// \brief The netlist owning the owner of this object.
/// \returns reference to netlist object.
netlist_state_t & state() noexcept;
const netlist_state_t &state() const noexcept;
private:
core_device_t *m_device;
};
// -------------------------------------------------------------------------
// core_terminal_t
// -------------------------------------------------------------------------
/// \brief Base class for all terminals.
///
/// All terminals are derived from this class.
///
class core_terminal_t
: public device_object_t
, public plib::linked_list_t<core_terminal_t, 0>::element_t
#if NL_USE_INPLACE_CORE_TERMS
, public plib::linked_list_t<core_terminal_t, 1>::element_t
#endif
{
public:
/// \brief Number of signal bits
///
/// Going forward setting this to 8 will allow 8-bit signal
/// buses to be used in netlist, e.g. for more complex memory
/// arrangements.
/// Minimum value is 2 here to support tristate output on proxies.
static constexpr const unsigned int INP_BITS = 2;
static constexpr const unsigned int INP_MASK = (1 << INP_BITS) - 1;
static constexpr const unsigned int INP_HL_SHIFT = 0;
static constexpr const unsigned int INP_LH_SHIFT = INP_BITS;
static constexpr netlist_sig_t OUT_TRISTATE() { return INP_MASK; }
static_assert(INP_BITS * 2 <= sizeof(netlist_sig_t) * 8,
"netlist_sig_t size not sufficient");
enum state_e
{
STATE_INP_PASSIVE = 0,
STATE_INP_HL = (INP_MASK << INP_HL_SHIFT),
STATE_INP_LH = (INP_MASK << INP_LH_SHIFT),
STATE_INP_ACTIVE = STATE_INP_HL | STATE_INP_LH,
STATE_OUT = (1 << (2 * INP_BITS)),
STATE_BIDIR = (1 << (2 * INP_BITS + 1))
};
core_terminal_t(core_device_t &dev, const pstring &aname, state_e state,
nl_delegate delegate);
virtual ~core_terminal_t() noexcept = default;
PCOPYASSIGNMOVE(core_terminal_t, delete)
/// \brief The object type.
/// \returns type of the object
terminal_type type() const noexcept(false);
/// \brief Checks if object is of specified type.
/// \param atype type to check object against.
/// \returns true if object is of specified type else false.
bool is_type(const terminal_type atype) const noexcept(false)
{
return (type() == atype);
}
void set_net(net_t *anet) noexcept { m_net = anet; }
void clear_net() noexcept { m_net = nullptr; }
constexpr bool has_net() const noexcept { return (m_net != nullptr); }
constexpr net_t &net() const noexcept { return *m_net; }
bool is_logic() const noexcept;
bool is_logic_input() const noexcept;
bool is_logic_output() const noexcept;
bool is_tristate_output() const noexcept;
bool is_analog() const noexcept;
bool is_analog_input() const noexcept;
bool is_analog_output() const noexcept;
constexpr bool is_state(state_e state) const noexcept
{
return (m_state == state);
}
constexpr state_e terminal_state() const noexcept { return m_state; }
constexpr void set_state(state_e state) noexcept { m_state = state; }
void reset() noexcept
{
set_state(
is_type(terminal_type::OUTPUT) ? STATE_OUT : STATE_INP_ACTIVE);
}
constexpr void set_copied_input(
[[maybe_unused]] netlist_sig_t val) noexcept
{
if constexpr (config::use_copy_instead_of_reference::value)
{
m_Q_CIR = val;
}
}
void set_delegate(const nl_delegate &delegate) noexcept
{
m_delegate = delegate;
}
const nl_delegate &delegate() const noexcept { return m_delegate; }
void run_delegate() const noexcept { return m_delegate(); }
protected:
// std::conditional_t<config::use_copy_instead_of_reference::value,
// state_var_sig, void *> m_Q;
state_var_sig m_Q_CIR;
private:
nl_delegate m_delegate;
net_t * m_net;
state_var<state_e> m_state;
};
} // namespace netlist::detail
#endif // NL_CORE_BASE_OBJECTS_H_
|