This commit is contained in:
Matthias Koefferlein 2023-02-20 22:06:45 +01:00
parent 432b542f3c
commit 40fd350d85
3 changed files with 819 additions and 502 deletions

File diff suppressed because it is too large Load Diff

View File

@ -127,7 +127,7 @@ public:
* @param nn Out parameter: the net names
* @param pv Out parameter: the parameter values (key/value pairs)
*/
virtual void parse_element (const std::string &s, const std::string &element, std::string &model, double &value, std::vector<std::string> &nn, std::map<std::string, double> &pv);
virtual void parse_element (const std::string &s, const std::string &element, std::string &model, double &value, std::vector<std::string> &nn, std::map<std::string, double> &pv, const std::map<std::string, double> &params);
/**
* @brief Produces an error with the given message
@ -138,22 +138,22 @@ public:
* @brief Reads a set of string components and parameters from the string
* A special key "param:" is recognized for starting a parameter list.
*/
void parse_element_components (const std::string &s, std::vector<std::string> &strings, std::map<std::string, double> &pv);
static void parse_element_components (const std::string &s, std::vector<std::string> &strings, std::map<std::string, double> &pv, const std::map<std::string, double> &variables);
/**
* @brief Reads a value from the extractor (with formula evaluation)
*/
double read_value (tl::Extractor &ex);
static double read_value (tl::Extractor &ex, const std::map<std::string, double> &variables);
/**
* @brief Tries to read a value from the extractor (with formula evaluation)
*/
bool try_read_value (const std::string &s, double &v);
static bool try_read_value (const std::string &s, double &v, const std::map<std::string, double> &variables);
private:
double read_atomic_value (tl::Extractor &ex);
double read_dot_expr (tl::Extractor &ex);
double read_bar_expr (tl::Extractor &ex);
static double read_atomic_value (tl::Extractor &ex, const std::map<std::string, double> &variables);
static double read_dot_expr (tl::Extractor &ex, const std::map<std::string, double> &variables);
static double read_bar_expr (tl::Extractor &ex, const std::map<std::string, double> &variables);
};
/**
@ -169,70 +169,7 @@ public:
virtual void read (tl::InputStream &stream, db::Netlist &netlist);
private:
class SpiceReaderStream
{
public:
SpiceReaderStream ();
~SpiceReaderStream ();
void set_stream (tl::InputStream &stream);
void set_stream (tl::InputStream *stream);
void close ();
std::pair<std::string, bool> get_line();
int line_number () const;
std::string source () const;
bool at_end () const;
void swap (SpiceReaderStream &other)
{
std::swap (mp_stream, other.mp_stream);
std::swap (m_owns_stream, other.m_owns_stream);
std::swap (mp_text_stream, other.mp_text_stream);
std::swap (m_line_number, other.m_line_number);
std::swap (m_stored_line, other.m_stored_line);
std::swap (m_has_stored_line, other.m_has_stored_line);
}
private:
tl::InputStream *mp_stream;
bool m_owns_stream;
tl::TextInputStream *mp_text_stream;
int m_line_number;
std::string m_stored_line;
bool m_has_stored_line;
};
db::Netlist *mp_netlist;
db::Circuit *mp_circuit;
db::Circuit *mp_anonymous_top_circuit;
tl::weak_ptr<NetlistSpiceReaderDelegate> mp_delegate;
std::list<SpiceReaderStream> m_streams;
SpiceReaderStream m_stream;
std::unique_ptr<std::map<std::string, db::Net *> > mp_nets_by_name;
std::map<std::string, bool> m_captured;
std::vector<std::string> m_global_nets;
std::set<std::string> m_global_net_names;
std::set<const db::Circuit *> m_circuits_read;
void push_stream (const std::string &path);
void pop_stream ();
bool at_end ();
bool read_element (tl::Extractor &ex, const std::string &element, const std::string &name);
void read_subcircuit (const std::string &sc_name, const std::string &nc_name, const std::vector<db::Net *> &nets);
void read_circuit (tl::Extractor &ex, const std::string &name);
void skip_circuit (tl::Extractor &ex);
bool read_card ();
std::string read_name (tl::Extractor &ex);
std::string get_line ();
void error (const std::string &msg);
void warn (const std::string &msg);
void finish ();
db::Net *make_net (const std::string &name);
void ensure_circuit ();
bool subcircuit_captured (const std::string &nc_name);
void build_global_nets ();
friend class SpiceReaderDict;
};
}

View File

@ -2456,7 +2456,7 @@ class NetlistSpiceReaderDelegateImpl
{
public:
NetlistSpiceReaderDelegateImpl ()
: db::NetlistSpiceReaderDelegate ()
: db::NetlistSpiceReaderDelegate (), mp_variables (0)
{
// .. nothing yet ..
}
@ -2566,15 +2566,16 @@ public:
ParseElementData parse_element_helper (const std::string &s, const std::string &element)
{
ParseElementData data;
db::NetlistSpiceReaderDelegate::parse_element (s, element, data.model_name_nc (), data.value_nc (), data.net_names_nc (), data.parameters_nc ());
db::NetlistSpiceReaderDelegate::parse_element (s, element, data.model_name_nc (), data.value_nc (), data.net_names_nc (), data.parameters_nc (), variables ());
return data;
}
virtual void parse_element (const std::string &s, const std::string &element, std::string &model, double &value, std::vector<std::string> &nn, std::map<std::string, double> &pv)
virtual void parse_element (const std::string &s, const std::string &element, std::string &model, double &value, std::vector<std::string> &nn, std::map<std::string, double> &pv, const std::map<std::string, double> &variables)
{
try {
m_error.clear ();
mp_variables = &variables;
ParseElementData data;
if (cb_parse_element.can_issue ()) {
@ -2588,12 +2589,18 @@ public:
nn = data.net_names ();
pv = data.parameters ();
mp_variables = 0;
} catch (tl::Exception &) {
mp_variables = 0;
if (! m_error.empty ()) {
db::NetlistSpiceReaderDelegate::error (m_error);
} else {
throw;
}
} catch (...) {
mp_variables = 0;
throw;
}
}
@ -2616,6 +2623,12 @@ public:
}
}
const std::map<std::string, double> &variables () const
{
static std::map<std::string, double> empty;
return mp_variables ? *mp_variables : empty;
}
gsi::Callback cb_start;
gsi::Callback cb_finish;
gsi::Callback cb_control_statement;
@ -2626,6 +2639,7 @@ public:
private:
std::string m_error;
const std::map<std::string, double> *mp_variables;
};
static void start_fb (NetlistSpiceReaderDelegateImpl *delegate, db::Netlist *netlist)
@ -2663,20 +2677,20 @@ static ParseElementData parse_element_fb (NetlistSpiceReaderDelegateImpl *delega
return delegate->parse_element_helper (s, element);
}
static tl::Variant value_from_string (NetlistSpiceReaderDelegateImpl *delegate, const std::string &s)
static tl::Variant value_from_string (NetlistSpiceReaderDelegateImpl * /*delegate*/, const std::string &s, const std::map<std::string, double> &variables)
{
tl::Variant res;
double v = 0.0;
if (delegate->try_read_value (s, v)) {
if (db::NetlistSpiceReaderDelegate::try_read_value (s, v, variables)) {
res = v;
}
return res;
}
static ParseElementComponentsData parse_element_components (NetlistSpiceReaderDelegateImpl *delegate, const std::string &s)
static ParseElementComponentsData parse_element_components (NetlistSpiceReaderDelegateImpl * /*delegate*/, const std::string &s, const std::map<std::string, double> &variables)
{
ParseElementComponentsData data;
delegate->parse_element_components (s, data.strings_nc (), data.parameters_nc ());
db::NetlistSpiceReaderDelegate::parse_element_components (s, data.strings_nc (), data.parameters_nc (), variables);
return data;
}
@ -2765,6 +2779,13 @@ Class<NetlistSpiceReaderDelegateImpl> db_NetlistSpiceReaderDelegate ("db", "Netl
"\n"
"This method has been introduced in version 0.27.1\n"
) +
gsi::method ("variables", &NetlistSpiceReaderDelegateImpl::variables,
"@brief Gets the variables defined inside the SPICE file during execution of 'parse_element'\n"
"In order to evaluate formulas, this method allows accessing the variables that are "
"present during the execution of the SPICE reader.\n"
"\n"
"This method has been introduced in version 0.28.7."
) +
gsi::callback ("parse_element", &NetlistSpiceReaderDelegateImpl::parse_element_helper, &NetlistSpiceReaderDelegateImpl::cb_parse_element,
gsi::arg ("s"), gsi::arg ("element"),
"@brief Parses an element card\n"
@ -2800,22 +2821,26 @@ Class<NetlistSpiceReaderDelegateImpl> db_NetlistSpiceReaderDelegate ("db", "Netl
"@brief Issues an error with the given message.\n"
"Use this method to generate an error."
) +
gsi::method_ext ("value_from_string", &value_from_string, gsi::arg ("s"),
gsi::method_ext ("value_from_string", &value_from_string, gsi::arg ("s"), gsi::arg ("variables", std::map<std::string, double> (), "{}"),
"@brief Translates a string into a value\n"
"This function simplifies the implementation of SPICE readers by providing a translation of a unit-annotated string "
"into double values. For example, '1k' is translated to 1000.0. In addition, simple formula evaluation is supported, e.g "
"'(1+3)*2' is translated into 8.0.\n"
"\n"
"This method has been introduced in version 0.27.1\n"
"The variables dictionary defines named variables with the given values.\n"
"\n"
"This method has been introduced in version 0.27.1. The variables argument has been added in version 0.28.7.\n"
) +
gsi::method_ext ("parse_element_components", &parse_element_components, gsi::arg ("s"),
gsi::method_ext ("parse_element_components", &parse_element_components, gsi::arg ("s"), gsi::arg ("variables", std::map<std::string, double> (), "{}"),
"@brief Parses a string into string and parameter components.\n"
"This method is provided to simplify the implementation of 'parse_element'. It takes a string and splits it into "
"string arguments and parameter values. For example, 'a b c=6' renders two string arguments in 'nn' and one parameter ('C'->6.0). "
"It returns data \\ParseElementComponentsData object with the strings and parameters.\n"
"The parameter names are already translated to upper case.\n"
"\n"
"This method has been introduced in version 0.27.1\n"
"The variables dictionary defines named variables with the given values.\n"
"\n"
"This method has been introduced in version 0.27.1. The variables argument has been added in version 0.28.7.\n"
),
"@brief Provides a delegate for the SPICE reader for translating device statements\n"
"Supply a customized class to provide a specialized reading scheme for devices. "