// license:BSD-3-Clause // copyright-holders:Couriersud /// /// \file setup.h /// #ifndef NL_CORE_SETUP_H_ #define NL_CORE_SETUP_H_ #include "../nl_config.h" #include "../nl_factory.h" #include "../nl_setup.h" #include "../nltypes.h" #include "../plib/pstream.h" #include "../plib/pstring.h" #include #include #include #include #include namespace netlist { // ---------------------------------------------------------------------------------------- // Collection of models // ---------------------------------------------------------------------------------------- class models_t { public: using raw_map_t = std::unordered_map; using map_t = std::unordered_map; class model_t { public: model_t(const pstring &model, const map_t &map) : m_model(model), m_map(map) { } pstring value_str(const pstring &entity) const; nl_fptype value(const pstring &entity) const; pstring type() const { return value_str("COREMODEL"); } private: static pstring model_string(const map_t &map); const pstring m_model; // only for error messages const map_t &m_map; }; models_t(const raw_map_t &models) : m_models(models) {} model_t get_model(const pstring &model); std::vector known_models() const { std::vector ret; for (const auto &e : m_models) ret.push_back(e.first); return ret; } private: void model_parse(const pstring &model, map_t &map); const raw_map_t &m_models; std::unordered_map m_cache; }; namespace detail { struct alias_t { alias_t(alias_type type, pstring alias, pstring references) : m_type(type) , m_alias(alias) , m_references(references) {} alias_t(const alias_t &) = default; alias_t &operator=(const alias_t &) = default; alias_t(alias_t &&) noexcept = default; alias_t &operator=(alias_t &&) noexcept = default; pstring name() const { return m_alias; } pstring references() const { return m_references; } alias_type type() const { return m_type; } private: alias_type m_type; pstring m_alias; pstring m_references; }; /// /// \brief class containing the abstract net list /// /// After parsing a net list this class contains all raw /// connections, parameter values and devices. struct abstract_t { using connection_t = std::pair; abstract_t(log_type &log) : m_factory(log) { } std::unordered_map m_aliases; std::vector m_connections; std::unordered_map m_param_values; models_t::raw_map_t m_models; // need to preserve order of device creation ... std::vector> m_device_factory; // lifetime control only - can be cleared before run std::vector> m_default_params; std::unordered_map m_hints; factory::list_t m_factory; }; } // namespace detail // ----------------------------------------------------------------------------- // param_ref_t // ----------------------------------------------------------------------------- struct param_ref_t { param_ref_t() noexcept : m_device(nullptr), m_param(nullptr) {} param_ref_t(core_device_t &device, param_t ¶m) noexcept : m_device(&device) , m_param(¶m) { } ~param_ref_t() = default; PCOPYASSIGNMOVE(param_ref_t, default) const core_device_t &device() const noexcept { return *m_device; } param_t ¶m() const noexcept { return *m_param; } bool is_valid() const noexcept { return (m_device != nullptr) && (m_param != nullptr); } private: core_device_t *m_device; param_t *m_param; }; // ---------------------------------------------------------------------------------------- // setup_t // ---------------------------------------------------------------------------------------- class setup_t { public: explicit setup_t(netlist_state_t &nlstate); ~setup_t() noexcept = default; PCOPYASSIGNMOVE(setup_t, delete) // called from param_t creation void register_param_t(param_t ¶m); pstring get_initial_param_val(const pstring &name, const pstring &def) const; void register_term(detail::core_terminal_t &term); void register_term(terminal_t &term, terminal_t *other_term, const std::array &splitter_terms); // called from matrix_solver_t::get_connected_net // returns the terminal being part of a two terminal device. terminal_t *get_connected_terminal(const terminal_t &term) const noexcept { auto ret(m_connected_terminals.find(&term)); return (ret != m_connected_terminals.end()) ? ret->second[0] : nullptr; } // called from net_splitter const std::array *get_connected_terminals(const terminal_t &term) const noexcept { auto ret(m_connected_terminals.find(&term)); return (ret != m_connected_terminals.end()) ? &ret->second : nullptr; } // get family -> truth table const logic_family_desc_t *family_from_model(const pstring &model); param_ref_t find_param(const pstring ¶m_in) const; // needed by nltool std::vector get_terminals_for_device_name(const pstring &devname) const; // needed by proxy device to check power terminals detail::core_terminal_t *find_terminal(const pstring &terminal_in, detail::terminal_type atype, bool required = true) const; detail::core_terminal_t *find_terminal(const pstring &terminal_in, bool required = true) const; pstring de_alias(const pstring &alias) const; // run preparation void prepare_to_run(); models_t &models() noexcept { return m_models; } const models_t &models() const noexcept { return m_models; } netlist_state_t &nlstate() noexcept { return m_nlstate; } const netlist_state_t &nlstate() const noexcept { return m_nlstate; } nlparse_t &parser() noexcept { return m_parser; } const nlparse_t &parser() const noexcept { return m_parser; } log_type &log() noexcept; const log_type &log() const noexcept; private: void resolve_inputs(); pstring resolve_alias(const pstring &name) const; void merge_nets(detail::net_t &this_net, detail::net_t &other_net); void connect_terminals(detail::core_terminal_t &t1, detail::core_terminal_t &t2); void connect_input_output(detail::core_terminal_t &input, detail::core_terminal_t &output); void connect_terminal_output(detail::core_terminal_t &terminal, detail::core_terminal_t &output); void connect_terminal_input(detail::core_terminal_t &terminal, detail::core_terminal_t &input); bool connect_input_input(detail::core_terminal_t &input1, detail::core_terminal_t &input2); bool connect(detail::core_terminal_t &t1, detail::core_terminal_t &t2); // helpers static pstring termtype_as_str(detail::core_terminal_t &in); devices::nld_base_proxy *get_d_a_proxy(const detail::core_terminal_t &out); devices::nld_base_proxy *get_a_d_proxy(detail::core_terminal_t &inp); detail::core_terminal_t &resolve_proxy(detail::core_terminal_t &term); // net manipulations //void remove_terminal(detail::net_t &net, detail::core_terminal_t &terminal) noexcept(false); void move_connections(detail::net_t &net, detail::net_t &dest_net); void delete_empty_nets(); detail::abstract_t m_abstract; nlparse_t m_parser; netlist_state_t &m_nlstate; models_t m_models; // FIXME: currently only used during setup devices::nld_netlistparams * m_netlist_params; // FIXME: can be cleared before run std::unordered_map m_terminals; // FIXME: Limited to 3 additional terminals std::unordered_map> m_connected_terminals; std::unordered_map m_params; std::unordered_map m_proxies; std::vector> m_defparam_lifetime; unsigned m_proxy_cnt; }; // ---------------------------------------------------------------------------------------- // Specific netlist `psource_t` implementations // ---------------------------------------------------------------------------------------- class source_netlist_t : public plib::psource_t { public: source_netlist_t() = default; PCOPYASSIGNMOVE(source_netlist_t, delete) ~source_netlist_t() noexcept override = default; virtual bool parse(nlparse_t &setup, const pstring &name); }; class source_data_t : public plib::psource_t { public: source_data_t() = default; PCOPYASSIGNMOVE(source_data_t, delete) ~source_data_t() noexcept override = default; }; class source_string_t : public source_netlist_t { public: explicit source_string_t(const pstring &source) : m_str(source) { } protected: plib::istream_uptr stream(const pstring &name) override; private: pstring m_str; }; class source_file_t : public source_netlist_t { public: explicit source_file_t(const pstring &filename) : m_filename(filename) { } protected: plib::istream_uptr stream(const pstring &name) override; private: pstring m_filename; }; class source_pattern_t : public source_netlist_t { public: explicit source_pattern_t(const pstring &pat, bool force_lowercase) : m_pattern(pat) , m_force_lowercase(force_lowercase) { } protected: plib::istream_uptr stream(const pstring &name) override; private: pstring m_pattern; bool m_force_lowercase; }; class source_mem_t : public source_netlist_t { public: explicit source_mem_t(const char *mem) : m_str(mem) { } protected: plib::istream_uptr stream(const pstring &name) override; private: std::string m_str; }; class source_proc_t : public source_netlist_t { public: source_proc_t(const pstring &name, nlsetup_func setup_func) : m_setup_func(setup_func) , m_setup_func_name(name) { } bool parse(nlparse_t &setup, const pstring &name) override; protected: plib::istream_uptr stream(const pstring &name) override; private: nlsetup_func m_setup_func; pstring m_setup_func_name; }; } // namespace netlist #endif // NL_CORE_SETUP_H_