mirror of https://github.com/KLayout/klayout.git
WIP: spice reader refactoring to support parametric subcircuits
This commit is contained in:
parent
2214345df2
commit
459de47448
|
|
@ -912,35 +912,67 @@ class SpiceCircuitDict
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::map<std::string, double> parameters_type;
|
typedef std::map<std::string, double> parameters_type;
|
||||||
|
typedef std::map<std::string, SpiceCachedCircuit *> circuits_type;
|
||||||
|
typedef circuits_type::const_iterator circuits_iterator;
|
||||||
|
typedef std::vector<std::string> global_nets_type;
|
||||||
|
typedef global_nets_type::const_iterator global_nets_iterator;
|
||||||
|
|
||||||
SpiceCircuitDict (NetlistSpiceReader *reader, NetlistSpiceReaderDelegate *delegate);
|
SpiceCircuitDict (NetlistSpiceReader *reader, Netlist *netlist, NetlistSpiceReaderDelegate *delegate);
|
||||||
~SpiceCircuitDict ();
|
~SpiceCircuitDict ();
|
||||||
|
|
||||||
void read (tl::InputStream &stream);
|
void read (tl::InputStream &stream);
|
||||||
void build (db::Netlist *netlist);
|
|
||||||
void finish ();
|
void finish ();
|
||||||
|
|
||||||
|
circuits_iterator begin_circuits () const
|
||||||
|
{
|
||||||
|
return m_cached_circuits.begin ();
|
||||||
|
}
|
||||||
|
|
||||||
|
circuits_iterator end_circuits () const
|
||||||
|
{
|
||||||
|
return m_cached_circuits.end ();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_top_circuit (const std::string &name) const
|
||||||
|
{
|
||||||
|
return m_called_circuits.find (name) == m_called_circuits.end ();
|
||||||
|
}
|
||||||
|
|
||||||
|
const SpiceCachedCircuit *anonymous_top_level_circuit () const
|
||||||
|
{
|
||||||
|
return mp_anonymous_top_level_circuit;
|
||||||
|
}
|
||||||
|
|
||||||
|
global_nets_iterator begin_global_nets () const
|
||||||
|
{
|
||||||
|
return m_global_nets.begin ();
|
||||||
|
}
|
||||||
|
|
||||||
|
global_nets_iterator end_global_nets () const
|
||||||
|
{
|
||||||
|
return m_global_nets.end ();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string &file_path (int file_id) const;
|
||||||
|
|
||||||
|
const SpiceCachedCircuit *cached_circuit (const std::string &name) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NetlistSpiceReader *mp_reader;
|
NetlistSpiceReader *mp_reader;
|
||||||
tl::weak_ptr<NetlistSpiceReaderDelegate> mp_delegate;
|
|
||||||
Netlist *mp_netlist;
|
Netlist *mp_netlist;
|
||||||
|
tl::weak_ptr<NetlistSpiceReaderDelegate> mp_delegate;
|
||||||
std::vector<std::string> m_paths;
|
std::vector<std::string> m_paths;
|
||||||
std::map<std::string, int> m_file_id_per_path;
|
std::map<std::string, int> m_file_id_per_path;
|
||||||
std::list<SpiceReaderStream> m_streams;
|
std::list<SpiceReaderStream> m_streams;
|
||||||
SpiceReaderStream m_stream;
|
SpiceReaderStream m_stream;
|
||||||
int m_file_id;
|
int m_file_id;
|
||||||
std::map<const SpiceCachedCircuit *, std::map<parameters_type, db::Circuit *, ParametersLessFunction> > m_circuits;
|
|
||||||
std::map<std::string, SpiceCachedCircuit *> m_cached_circuits;
|
std::map<std::string, SpiceCachedCircuit *> m_cached_circuits;
|
||||||
SpiceCachedCircuit *mp_circuit;
|
SpiceCachedCircuit *mp_circuit;
|
||||||
SpiceCachedCircuit *mp_anonymous_top_level_circuit;
|
SpiceCachedCircuit *mp_anonymous_top_level_circuit;
|
||||||
std::set<std::string> m_called_circuits;
|
std::set<std::string> m_called_circuits;
|
||||||
db::Circuit *mp_netlist_circuit;
|
|
||||||
db::Circuit *mp_anonymous_top_level_netlist_circuit;
|
|
||||||
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::map<std::string, double> m_variables;
|
std::map<std::string, double> m_variables;
|
||||||
|
std::set<std::string> m_global_net_names;
|
||||||
|
std::vector<std::string> m_global_nets;
|
||||||
|
|
||||||
void push_stream (const std::string &path);
|
void push_stream (const std::string &path);
|
||||||
void pop_stream ();
|
void pop_stream ();
|
||||||
|
|
@ -949,31 +981,17 @@ private:
|
||||||
void read_circuit (tl::Extractor &ex, const std::string &name);
|
void read_circuit (tl::Extractor &ex, const std::string &name);
|
||||||
bool read_card ();
|
bool read_card ();
|
||||||
void ensure_circuit ();
|
void ensure_circuit ();
|
||||||
Circuit *build_circuit (const SpiceCachedCircuit *circuit, const parameters_type &pv, bool anonymous_top_level = false);
|
|
||||||
std::string read_name (tl::Extractor &ex);
|
std::string read_name (tl::Extractor &ex);
|
||||||
std::string get_line ();
|
std::string get_line ();
|
||||||
void error (const std::string &msg);
|
void error (const std::string &msg);
|
||||||
void warn (const std::string &msg);
|
void warn (const std::string &msg);
|
||||||
void error (const std::string &msg, const SpiceCard &card);
|
|
||||||
void warn (const std::string &msg, const SpiceCard &card);
|
|
||||||
const std::string &file_path (int file_id) const;
|
|
||||||
int file_id (const std::string &path);
|
int file_id (const std::string &path);
|
||||||
db::Circuit *circuit_for (const SpiceCachedCircuit *cached_circuit, const parameters_type &pv);
|
|
||||||
void register_circuit_for (const SpiceCachedCircuit *cc, const parameters_type &pv, db::Circuit *circuit, bool anonymous_top_level);
|
|
||||||
const SpiceCachedCircuit *cached_circuit (const std::string &name) const;
|
|
||||||
SpiceCachedCircuit *create_cached_circuit (const std::string &name);
|
SpiceCachedCircuit *create_cached_circuit (const std::string &name);
|
||||||
Net *make_net(const std::string &name);
|
|
||||||
void process_card (const SpiceCard &card);
|
|
||||||
bool subcircuit_captured (const std::string &nc_name);
|
|
||||||
bool process_element (tl::Extractor &ex, const std::string &prefix, const std::string &name, const SpiceCard &card);
|
|
||||||
void build_global_nets ();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SpiceCircuitDict::SpiceCircuitDict (NetlistSpiceReader *reader, NetlistSpiceReaderDelegate *delegate)
|
SpiceCircuitDict::SpiceCircuitDict (NetlistSpiceReader *reader, Netlist *netlist, NetlistSpiceReaderDelegate *delegate)
|
||||||
: mp_reader (reader), mp_delegate (delegate)
|
: mp_reader (reader), mp_netlist (netlist), mp_delegate (delegate)
|
||||||
{
|
{
|
||||||
mp_netlist = 0;
|
|
||||||
mp_netlist_circuit = mp_anonymous_top_level_netlist_circuit = 0;
|
|
||||||
m_file_id = -1;
|
m_file_id = -1;
|
||||||
mp_circuit = mp_anonymous_top_level_circuit = 0;
|
mp_circuit = mp_anonymous_top_level_circuit = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -985,7 +1003,6 @@ SpiceCircuitDict::~SpiceCircuitDict ()
|
||||||
}
|
}
|
||||||
m_cached_circuits.clear ();
|
m_cached_circuits.clear ();
|
||||||
|
|
||||||
m_circuits.clear ();
|
|
||||||
mp_reader = 0;
|
mp_reader = 0;
|
||||||
mp_delegate = 0;
|
mp_delegate = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1015,29 +1032,6 @@ SpiceCircuitDict::file_id (const std::string &path)
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
db::Circuit *
|
|
||||||
SpiceCircuitDict::circuit_for (const SpiceCachedCircuit *cc, const parameters_type &pv)
|
|
||||||
{
|
|
||||||
auto c = m_circuits.find (cc);
|
|
||||||
if (c == m_circuits.end ()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
auto cp = c->second.find (pv);
|
|
||||||
if (cp == c->second.end ()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return cp->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
SpiceCircuitDict::register_circuit_for (const SpiceCachedCircuit *cc, const parameters_type &pv, db::Circuit *circuit, bool anonymous_top_level)
|
|
||||||
{
|
|
||||||
m_circuits [cc][pv] = circuit;
|
|
||||||
if (anonymous_top_level) {
|
|
||||||
mp_anonymous_top_level_netlist_circuit = circuit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const SpiceCachedCircuit *
|
const SpiceCachedCircuit *
|
||||||
SpiceCircuitDict::cached_circuit (const std::string &name) const
|
SpiceCircuitDict::cached_circuit (const std::string &name) const
|
||||||
{
|
{
|
||||||
|
|
@ -1063,14 +1057,12 @@ SpiceCircuitDict::read (tl::InputStream &stream)
|
||||||
{
|
{
|
||||||
m_stream.set_stream (stream);
|
m_stream.set_stream (stream);
|
||||||
|
|
||||||
mp_netlist = 0;
|
|
||||||
mp_netlist_circuit = 0;
|
|
||||||
mp_anonymous_top_level_netlist_circuit = 0;
|
|
||||||
mp_circuit = 0;
|
mp_circuit = 0;
|
||||||
mp_anonymous_top_level_circuit = 0;
|
mp_anonymous_top_level_circuit = 0;
|
||||||
m_global_nets.clear ();
|
|
||||||
m_called_circuits.clear ();
|
m_called_circuits.clear ();
|
||||||
m_variables.clear ();
|
m_variables.clear ();
|
||||||
|
m_global_net_names.clear ();
|
||||||
|
m_global_nets.clear ();
|
||||||
|
|
||||||
m_file_id = file_id (stream.source ());
|
m_file_id = file_id (stream.source ());
|
||||||
|
|
||||||
|
|
@ -1129,13 +1121,6 @@ SpiceCircuitDict::error (const std::string &msg)
|
||||||
throw tl::Exception (fmt_msg);
|
throw tl::Exception (fmt_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
SpiceCircuitDict::error (const std::string &msg, const SpiceCard &card)
|
|
||||||
{
|
|
||||||
std::string fmt_msg = tl::sprintf ("%s in %s, line %d", msg, file_path (card.file_id), card.line);
|
|
||||||
throw tl::Exception (fmt_msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SpiceCircuitDict::warn (const std::string &msg)
|
SpiceCircuitDict::warn (const std::string &msg)
|
||||||
{
|
{
|
||||||
|
|
@ -1143,13 +1128,6 @@ SpiceCircuitDict::warn (const std::string &msg)
|
||||||
tl::warn << fmt_msg;
|
tl::warn << fmt_msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
SpiceCircuitDict::warn (const std::string &msg, const SpiceCard &card)
|
|
||||||
{
|
|
||||||
std::string fmt_msg = tl::sprintf ("%s in %s, line %d", msg, file_path (card.file_id), card.line);
|
|
||||||
tl::warn << fmt_msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
SpiceCircuitDict::get_line ()
|
SpiceCircuitDict::get_line ()
|
||||||
{
|
{
|
||||||
|
|
@ -1337,32 +1315,106 @@ SpiceCircuitDict::finish ()
|
||||||
{
|
{
|
||||||
m_streams.clear ();
|
m_streams.clear ();
|
||||||
m_stream.close ();
|
m_stream.close ();
|
||||||
|
|
||||||
mp_netlist = 0;
|
|
||||||
mp_delegate = 0;
|
|
||||||
mp_circuit = 0;
|
|
||||||
mp_nets_by_name.reset (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// .........................
|
// ------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class SpiceNetlistBuilder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef std::map<std::string, double> parameters_type;
|
||||||
|
|
||||||
|
SpiceNetlistBuilder (SpiceCircuitDict *dict, Netlist *netlist, NetlistSpiceReaderDelegate *delegate);
|
||||||
|
|
||||||
|
void build ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const SpiceCircuitDict *mp_dict;
|
||||||
|
tl::weak_ptr<NetlistSpiceReaderDelegate> mp_delegate;
|
||||||
|
Netlist *mp_netlist;
|
||||||
|
const SpiceCachedCircuit *mp_circuit;
|
||||||
|
std::map<const SpiceCachedCircuit *, std::map<parameters_type, db::Circuit *, ParametersLessFunction> > m_circuits;
|
||||||
|
db::Circuit *mp_netlist_circuit;
|
||||||
|
db::Circuit *mp_anonymous_top_level_netlist_circuit;
|
||||||
|
std::unique_ptr<std::map<std::string, db::Net *> > mp_nets_by_name;
|
||||||
|
std::map<std::string, bool> m_captured;
|
||||||
|
std::map<std::string, double> m_variables;
|
||||||
|
|
||||||
|
db::Circuit *circuit_for (const SpiceCachedCircuit *cached_circuit, const parameters_type &pv);
|
||||||
|
void register_circuit_for (const SpiceCachedCircuit *cc, const parameters_type &pv, db::Circuit *circuit, bool anonymous_top_level);
|
||||||
|
Circuit *build_circuit (const SpiceCachedCircuit *circuit, const parameters_type &pv, bool anonymous_top_level = false);
|
||||||
|
std::string read_name (tl::Extractor &ex);
|
||||||
|
std::string get_line ();
|
||||||
|
void error (const std::string &msg, const SpiceCard &card);
|
||||||
|
void warn (const std::string &msg, const SpiceCard &card);
|
||||||
|
Net *make_net(const std::string &name);
|
||||||
|
void process_card (const SpiceCard &card);
|
||||||
|
bool subcircuit_captured (const std::string &nc_name);
|
||||||
|
bool process_element (tl::Extractor &ex, const std::string &prefix, const std::string &name, const SpiceCard &card);
|
||||||
|
void build_global_nets ();
|
||||||
|
};
|
||||||
|
|
||||||
|
SpiceNetlistBuilder::SpiceNetlistBuilder (SpiceCircuitDict *dict, Netlist *netlist, NetlistSpiceReaderDelegate *delegate)
|
||||||
|
: mp_dict (dict), mp_delegate (delegate), mp_netlist (netlist)
|
||||||
|
{
|
||||||
|
mp_netlist = 0;
|
||||||
|
mp_circuit = 0;
|
||||||
|
mp_netlist_circuit = 0;
|
||||||
|
mp_anonymous_top_level_netlist_circuit = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SpiceCircuitDict::build (db::Netlist *netlist)
|
SpiceNetlistBuilder::error (const std::string &msg, const SpiceCard &card)
|
||||||
|
{
|
||||||
|
std::string fmt_msg = tl::sprintf ("%s in %s, line %d", msg, mp_dict->file_path (card.file_id), card.line);
|
||||||
|
throw tl::Exception (fmt_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SpiceNetlistBuilder::warn (const std::string &msg, const SpiceCard &card)
|
||||||
|
{
|
||||||
|
std::string fmt_msg = tl::sprintf ("%s in %s, line %d", msg, mp_dict->file_path (card.file_id), card.line);
|
||||||
|
tl::warn << fmt_msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
db::Circuit *
|
||||||
|
SpiceNetlistBuilder::circuit_for (const SpiceCachedCircuit *cc, const parameters_type &pv)
|
||||||
|
{
|
||||||
|
auto c = m_circuits.find (cc);
|
||||||
|
if (c == m_circuits.end ()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
auto cp = c->second.find (pv);
|
||||||
|
if (cp == c->second.end ()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return cp->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SpiceNetlistBuilder::register_circuit_for (const SpiceCachedCircuit *cc, const parameters_type &pv, db::Circuit *circuit, bool anonymous_top_level)
|
||||||
|
{
|
||||||
|
m_circuits [cc][pv] = circuit;
|
||||||
|
if (anonymous_top_level) {
|
||||||
|
mp_anonymous_top_level_netlist_circuit = circuit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SpiceNetlistBuilder::build ()
|
||||||
{
|
{
|
||||||
m_variables.clear ();
|
m_variables.clear ();
|
||||||
mp_netlist_circuit = 0;
|
mp_netlist_circuit = 0;
|
||||||
mp_anonymous_top_level_netlist_circuit = 0;
|
mp_anonymous_top_level_netlist_circuit = 0;
|
||||||
mp_circuit = 0;
|
mp_circuit = 0;
|
||||||
mp_anonymous_top_level_circuit = 0;
|
|
||||||
mp_netlist = netlist;
|
|
||||||
m_captured.clear ();
|
m_captured.clear ();
|
||||||
|
|
||||||
mp_delegate->start (netlist);
|
mp_delegate->start (mp_netlist);
|
||||||
|
|
||||||
for (auto c = m_cached_circuits.begin (); c != m_cached_circuits.end (); ++c) {
|
for (auto c = mp_dict->begin_circuits (); c != mp_dict->end_circuits (); ++c) {
|
||||||
if (m_called_circuits.find (c->first) == m_called_circuits.end () && mp_delegate->wants_subcircuit (c->first)) {
|
if (mp_dict->is_top_circuit (c->first) && mp_delegate->wants_subcircuit (c->first)) {
|
||||||
// we have a top circuit candidate
|
// we have a top circuit candidate
|
||||||
build_circuit (c->second, c->second->parameters (), c->second == mp_anonymous_top_level_circuit);
|
build_circuit (c->second, c->second->parameters (), c->second == mp_dict->anonymous_top_level_circuit ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1411,7 +1463,7 @@ make_circuit_name (const std::string &name, const std::map<std::string, double>
|
||||||
}
|
}
|
||||||
|
|
||||||
db::Circuit *
|
db::Circuit *
|
||||||
SpiceCircuitDict::build_circuit (const SpiceCachedCircuit *cc, const parameters_type &pv, bool anonymous_top_level)
|
SpiceNetlistBuilder::build_circuit (const SpiceCachedCircuit *cc, const parameters_type &pv, bool anonymous_top_level)
|
||||||
{
|
{
|
||||||
db::Circuit *c = circuit_for (cc, pv);
|
db::Circuit *c = circuit_for (cc, pv);
|
||||||
if (c) {
|
if (c) {
|
||||||
|
|
@ -1469,7 +1521,7 @@ SpiceCircuitDict::build_circuit (const SpiceCachedCircuit *cc, const parameters_
|
||||||
}
|
}
|
||||||
|
|
||||||
db::Net *
|
db::Net *
|
||||||
SpiceCircuitDict::make_net (const std::string &name)
|
SpiceNetlistBuilder::make_net (const std::string &name)
|
||||||
{
|
{
|
||||||
if (! mp_nets_by_name.get ()) {
|
if (! mp_nets_by_name.get ()) {
|
||||||
mp_nets_by_name.reset (new std::map<std::string, db::Net *> ());
|
mp_nets_by_name.reset (new std::map<std::string, db::Net *> ());
|
||||||
|
|
@ -1494,7 +1546,7 @@ SpiceCircuitDict::make_net (const std::string &name)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SpiceCircuitDict::process_card (const SpiceCard &card)
|
SpiceNetlistBuilder::process_card (const SpiceCard &card)
|
||||||
{
|
{
|
||||||
tl::Extractor ex (card.text.c_str ());
|
tl::Extractor ex (card.text.c_str ());
|
||||||
|
|
||||||
|
|
@ -1528,7 +1580,7 @@ SpiceCircuitDict::process_card (const SpiceCard &card)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SpiceCircuitDict::subcircuit_captured (const std::string &nc_name)
|
SpiceNetlistBuilder::subcircuit_captured (const std::string &nc_name)
|
||||||
{
|
{
|
||||||
std::map<std::string, bool>::const_iterator c = m_captured.find (nc_name);
|
std::map<std::string, bool>::const_iterator c = m_captured.find (nc_name);
|
||||||
if (c != m_captured.end ()) {
|
if (c != m_captured.end ()) {
|
||||||
|
|
@ -1541,7 +1593,7 @@ SpiceCircuitDict::subcircuit_captured (const std::string &nc_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SpiceCircuitDict::process_element (tl::Extractor &ex, const std::string &prefix, const std::string &name, const SpiceCard &card)
|
SpiceNetlistBuilder::process_element (tl::Extractor &ex, const std::string &prefix, const std::string &name, const SpiceCard &card)
|
||||||
{
|
{
|
||||||
// generic parse
|
// generic parse
|
||||||
std::vector<std::string> nn;
|
std::vector<std::string> nn;
|
||||||
|
|
@ -1560,7 +1612,7 @@ SpiceCircuitDict::process_element (tl::Extractor &ex, const std::string &prefix,
|
||||||
|
|
||||||
if (prefix == "X" && ! subcircuit_captured (model)) {
|
if (prefix == "X" && ! subcircuit_captured (model)) {
|
||||||
|
|
||||||
const db::SpiceCachedCircuit *cc = cached_circuit (model);
|
const db::SpiceCachedCircuit *cc = mp_dict->cached_circuit (model);
|
||||||
if (! cc) {
|
if (! cc) {
|
||||||
error (tl::sprintf (tl::to_string (tr ("Subcircuit '%s' not found in netlist")), model), card);
|
error (tl::sprintf (tl::to_string (tr ("Subcircuit '%s' not found in netlist")), model), card);
|
||||||
}
|
}
|
||||||
|
|
@ -1586,11 +1638,11 @@ SpiceCircuitDict::process_element (tl::Extractor &ex, const std::string &prefix,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SpiceCircuitDict::build_global_nets ()
|
SpiceNetlistBuilder::build_global_nets ()
|
||||||
{
|
{
|
||||||
for (std::vector<std::string>::const_iterator gn = m_global_nets.begin (); gn != m_global_nets.end (); ++gn) {
|
for (auto gn = mp_dict->begin_global_nets (); gn != mp_dict->end_global_nets (); ++gn) {
|
||||||
|
|
||||||
for (db::Netlist::bottom_up_circuit_iterator c = mp_netlist->begin_bottom_up (); c != mp_netlist->end_bottom_up (); ++c) {
|
for (auto c = mp_netlist->begin_bottom_up (); c != mp_netlist->end_bottom_up (); ++c) {
|
||||||
|
|
||||||
if (c.operator-> () == mp_anonymous_top_level_netlist_circuit) {
|
if (c.operator-> () == mp_anonymous_top_level_netlist_circuit) {
|
||||||
// no pins for the anonymous top circuit
|
// no pins for the anonymous top circuit
|
||||||
|
|
@ -1650,21 +1702,17 @@ void NetlistSpiceReader::read (tl::InputStream &stream, db::Netlist &netlist)
|
||||||
// SPICE netlists are case insensitive
|
// SPICE netlists are case insensitive
|
||||||
netlist.set_case_sensitive (false);
|
netlist.set_case_sensitive (false);
|
||||||
|
|
||||||
SpiceCircuitDict dict (this, mp_delegate.get ());
|
SpiceCircuitDict dict (this, &netlist, mp_delegate.get ());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
dict.read (stream);
|
dict.read (stream);
|
||||||
dict.build (&netlist);
|
|
||||||
|
|
||||||
dict.finish ();
|
dict.finish ();
|
||||||
|
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
|
|
||||||
dict.finish ();
|
dict.finish ();
|
||||||
throw;
|
throw;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SpiceNetlistBuilder builder (&dict, &netlist, mp_delegate.get ());
|
||||||
|
builder.build ();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue