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
|
// license:BSD-3-Clause
// copyright-holders:Couriersud
///
/// \file param.h
///
#ifndef NL_CORE_ANALOG_H_
#define NL_CORE_ANALOG_H_
#include "../nltypes.h"
#include "base_objects.h"
#include "nets.h"
#include "../plib/plists.h"
#include "../plib/pstring.h"
#include <array>
#include <utility>
namespace netlist
{
// -------------------------------------------------------------------------
// analog_t
// -------------------------------------------------------------------------
class analog_t : public detail::core_terminal_t
{
public:
analog_t(core_device_t &dev, const pstring &aname, state_e state,
nl_delegate delegate);
const analog_net_t &net() const noexcept
{
return plib::downcast<const analog_net_t &>(core_terminal_t::net());
}
analog_net_t &net() noexcept
{
return plib::downcast<analog_net_t &>(core_terminal_t::net());
}
solver::matrix_solver_t *solver() const noexcept;
};
/// \brief Base class for terminals.
///
/// Each \ref nld_two_terminal object consists of two terminals. Terminals
/// are at the core of analog netlists and are connected to \ref net_t
/// objects.
///
class terminal_t : public analog_t
{
public:
/// \brief constructor
///
/// \param dev object owning the terminal
/// \param aname name of this terminal
/// \param other_terminal pointer to the sibling terminal
terminal_t(core_device_t &dev, const pstring &aname,
terminal_t *other_terminal, nl_delegate delegate);
terminal_t(core_device_t &dev, const pstring &aname,
terminal_t * other_terminal,
const std::array<terminal_t *, 2> &splitter_terms,
nl_delegate delegate);
/// \brief Returns voltage of connected net
///
/// \return voltage of net this terminal is connected to
nl_fptype operator()() const noexcept { return net().Q_Analog(); }
/// \brief sets conductivity value of this terminal
///
/// \param G Conductivity
void set_conductivity(nl_fptype G) const noexcept
{
set_go_gt_I(-G, G, nlconst::zero());
}
void set_go_gt(nl_fptype GO, nl_fptype GT) const noexcept
{
set_go_gt_I(GO, GT, nlconst::zero());
}
void set_go_gt_I(nl_fptype GO, nl_fptype GT,
nl_fptype I) const noexcept;
void set_ptrs(nl_fptype *gt, nl_fptype *go, nl_fptype *Idr) noexcept(
false);
private:
nl_fptype *m_Idr; //!< drive current
nl_fptype *m_go; //!< conductance for Voltage from other term
nl_fptype *m_gt; //!< conductance for total conductance
};
// -------------------------------------------------------------------------
// analog_input_t
// -------------------------------------------------------------------------
/// \brief terminal providing analog input voltage.
///
/// This terminal class provides a voltage measurement. The conductance
/// against ground is infinite.
class analog_input_t : public analog_t
{
public:
/// \brief Constructor
analog_input_t(core_device_t &dev, //!< owning device
const pstring & aname, //!< name of terminal
nl_delegate delegate //!< delegate
);
/// \brief returns voltage at terminal.
/// \returns voltage at terminal.
nl_fptype operator()() const noexcept { return Q_Analog(); }
/// \brief returns voltage at terminal.
/// \returns voltage at terminal.
nl_fptype Q_Analog() const noexcept { return net().Q_Analog(); }
};
// -------------------------------------------------------------------------
// analog_output_t
// -------------------------------------------------------------------------
class analog_output_t : public analog_t
{
public:
analog_output_t(core_device_t &dev, const pstring &aname);
void push(nl_fptype val) noexcept;
void initial(nl_fptype val) noexcept;
private:
analog_net_t m_my_net;
};
// -------------------------------------------------------------------------
// out of class
// -------------------------------------------------------------------------
inline solver::matrix_solver_t *analog_t::solver() const noexcept
{
return (this->has_net() ? net().solver() : nullptr);
}
inline void terminal_t::set_go_gt_I(nl_fptype GO, nl_fptype GT,
nl_fptype I) const noexcept
{
// Check for rail nets ...
if (m_go != nullptr)
{
*m_Idr = I;
*m_go = GO;
*m_gt = GT;
}
}
inline void analog_output_t::push(nl_fptype val) noexcept
{
if (val != m_my_net.Q_Analog())
{
m_my_net.set_Q_Analog(val);
m_my_net.toggle_and_push_to_queue(netlist_time::quantum());
}
}
} // namespace netlist
#endif // NL_CORE_ANALOG_H_
|