netlist: refactor model code. (nw)

This commit is contained in:
couriersud 2019-03-18 22:12:14 +01:00
parent 17ad7648ce
commit deacff7ffa
8 changed files with 114 additions and 80 deletions

View File

@ -291,7 +291,6 @@ namespace analog
NETLIB_SUBXX(analog, C) m_CJE;
NETLIB_SUBXX(analog, C) m_CJC;
};

View File

@ -988,12 +988,9 @@ pstring param_t::get_initial(const device_t &dev, bool *found)
return res;
}
const pstring param_model_t::model_type()
{
if (m_map.size() == 0)
state().setup().model_parse(this->Value(), m_map);
return m_map["COREMODEL"];
return state().setup().models().model_type(value());
}
param_str_t::param_str_t(device_t &device, const pstring &name, const pstring &val)
@ -1016,27 +1013,22 @@ param_ptr_t::param_ptr_t(device_t &device, const pstring &name, uint8_t * val)
void param_model_t::changed()
{
state().log().fatal(MF_1_MODEL_1_CAN_NOT_BE_CHANGED_AT_RUNTIME, name());
m_map.clear();
}
const pstring param_model_t::model_value_str(const pstring &entity)
{
if (m_map.size() == 0)
state().setup().model_parse(this->Value(), m_map);
return state().setup().model_value_str(m_map, entity);
return state().setup().models().model_value_str(value(), entity);
}
nl_double param_model_t::model_value(const pstring &entity)
{
if (m_map.size() == 0)
state().setup().model_parse(this->Value(), m_map);
return state().setup().model_value(m_map, entity);
return state().setup().models().model_value(value(), entity);
}
plib::unique_ptr<plib::pistream> param_data_t::stream()
{
return device().setup().get_data_stream(Value());
return device().setup().get_data_stream(value());
}
bool detail::core_terminal_t::is_logic() const NL_NOEXCEPT

View File

@ -162,7 +162,7 @@ class NETLIB_NAME(name) : public device_t
#define nl_assert(x) do { if (0) if (!(x)) { /*throw nl_exception(plib::pfmt("assert: {1}:{2}: {3}")(__FILE__)(__LINE__)(#x) ); */} } while (0)
#define NL_NOEXCEPT noexcept
#endif
#define nl_assert_always(x, msg) do { if (!(x)) throw nl_exception(plib::pfmt("Fatal error: {1}\nCaused by assert: {2}:{3}: {4}")(msg)(__FILE__)(__LINE__)(#x)); } while (0)
#define nl_assert_always(x, msg) do { if (!(x)) throw nl_exception("Fatal error: {1}\nCaused by assert: {2}:{3}: {4}", msg, __FILE__, __LINE__, #x); } while (0)
//============================================================
// Namespace starts
@ -223,6 +223,12 @@ namespace netlist
explicit nl_exception(const pstring &text //!< text to be passed
)
: plib::pexception(text) { }
template<typename... Args>
explicit nl_exception(const pstring &fmt //!< format to be used
, Args&&... args //!< arguments to be passed
)
: plib::pexception(plib::pfmt(fmt)(std::forward<Args>(args)...)) { }
};
/*! Logic families descriptors are used to create proxy devices.
@ -1004,7 +1010,7 @@ namespace netlist
public:
param_str_t(device_t &device, const pstring &name, const pstring &val);
const pstring &operator()() const NL_NOEXCEPT { return Value(); }
const pstring &operator()() const NL_NOEXCEPT { return value(); }
void setTo(const pstring &param) NL_NOEXCEPT
{
if (m_param != param)
@ -1016,7 +1022,7 @@ namespace netlist
}
protected:
virtual void changed();
const pstring &Value() const NL_NOEXCEPT { return m_param; }
const pstring &value() const NL_NOEXCEPT { return m_param; }
private:
pstring m_param;
};
@ -1055,7 +1061,6 @@ namespace netlist
void changed() override;
nl_double model_value(const pstring &entity) /*const*/;
private:
detail::model_map_t m_map;
};
// -----------------------------------------------------------------------------
@ -1552,7 +1557,7 @@ namespace netlist
if (f != nullptr)
f->read(reinterpret_cast<plib::pistream::value_type *>(&m_data[0]),1<<AW);
else
device.state().log().warning("Rom {1} not found", Value());
device.state().log().warning("Rom {1} not found", value());
}
inline void logic_input_t::inactivate() NL_NOEXCEPT

View File

@ -32,17 +32,6 @@ namespace netlist
, m_frontier_cnt(0)
{ }
void nlparse_t::register_model(const pstring &model_in)
{
auto pos = model_in.find(" ");
if (pos == pstring::npos)
log().fatal(MF_1_UNABLE_TO_PARSE_MODEL_1, model_in);
pstring model = plib::ucase(plib::trim(plib::left(model_in, pos)));
pstring def = plib::trim(model_in.substr(pos + 1));
if (!m_models.insert({model, def}).second)
log().fatal(MF_1_MODEL_ALREADY_EXISTS_1, model_in);
}
void nlparse_t::register_alias(const pstring &alias, const pstring &out)
{
pstring alias_fqn = build_fqn(alias);
@ -818,19 +807,21 @@ const log_type &setup_t::log() const
// ----------------------------------------------------------------------------------------
// Model
// Models
// ----------------------------------------------------------------------------------------
static pstring model_string(detail::model_map_t &map)
void models_t::register_model(pstring model_in)
{
pstring ret = map["COREMODEL"] + "(";
for (auto & i : map)
ret = ret + i.first + "=" + i.second + " ";
return ret + ")";
auto pos = model_in.find(" ");
if (pos == pstring::npos)
throw nl_exception(MF_1_UNABLE_TO_PARSE_MODEL_1, model_in);
pstring model = plib::ucase(plib::trim(plib::left(model_in, pos)));
pstring def = plib::trim(model_in.substr(pos + 1));
if (!m_models.insert({model, def}).second)
throw nl_exception(MF_1_MODEL_ALREADY_EXISTS_1, model_in);
}
void setup_t::model_parse(const pstring &model_in, detail::model_map_t &map)
void models_t::model_parse(const pstring &model_in, model_map_t &map)
{
pstring model = model_in;
std::size_t pos = 0;
@ -844,7 +835,7 @@ void setup_t::model_parse(const pstring &model_in, detail::model_map_t &map)
key = plib::ucase(model);
auto i = m_models.find(key);
if (i == m_models.end())
log().fatal(MF_1_MODEL_NOT_FOUND, model);
throw nl_exception(MF_1_MODEL_NOT_FOUND, model);
model = i->second;
}
pstring xmodel = plib::left(model, pos);
@ -857,12 +848,12 @@ void setup_t::model_parse(const pstring &model_in, detail::model_map_t &map)
if (i != m_models.end())
model_parse(xmodel, map);
else
log().fatal(MF_1_MODEL_NOT_FOUND, model_in);
throw nl_exception(MF_1_MODEL_NOT_FOUND, model_in);
}
pstring remainder = plib::trim(model.substr(pos + 1));
if (!plib::endsWith(remainder, ")"))
log().fatal(MF_1_MODEL_ERROR_1, model);
throw nl_exception(MF_1_MODEL_ERROR_1, model);
// FIMXE: Not optimal
remainder = plib::left(remainder, remainder.size() - 1);
@ -871,29 +862,48 @@ void setup_t::model_parse(const pstring &model_in, detail::model_map_t &map)
{
auto pose = pe.find("=");
if (pose == pstring::npos)
log().fatal(MF_1_MODEL_ERROR_ON_PAIR_1, model);
throw nl_exception(MF_1_MODEL_ERROR_ON_PAIR_1, model);
map[plib::ucase(plib::left(pe, pose))] = pe.substr(pose + 1);
}
}
const pstring setup_t::model_value_str(detail::model_map_t &map, const pstring &entity)
pstring models_t::model_string(model_map_t &map)
{
pstring ret = map["COREMODEL"] + "(";
for (auto & i : map)
ret = ret + i.first + "=" + i.second + " ";
return ret + ")";
}
pstring models_t::model_value_str(pstring model, pstring entity)
{
model_map_t &map = m_cache[model];
if (map.size() == 0)
model_parse(model , map);
pstring ret;
if (entity != plib::ucase(entity))
log().fatal(MF_2_MODEL_PARAMETERS_NOT_UPPERCASE_1_2, entity,
throw nl_exception(MF_2_MODEL_PARAMETERS_NOT_UPPERCASE_1_2, entity,
model_string(map));
if (map.find(entity) == map.end())
log().fatal(MF_2_ENTITY_1_NOT_FOUND_IN_MODEL_2, entity, model_string(map));
throw nl_exception(MF_2_ENTITY_1_NOT_FOUND_IN_MODEL_2, entity, model_string(map));
else
ret = map[entity];
return ret;
}
nl_double setup_t::model_value(detail::model_map_t &map, const pstring &entity)
nl_double models_t::model_value(pstring model, pstring entity)
{
pstring tmp = model_value_str(map, entity);
model_map_t &map = m_cache[model];
if (map.size() == 0)
model_parse(model , map);
pstring tmp = model_value_str(model, entity);
nl_double factor = plib::constants<nl_double>::one();
auto p = std::next(tmp.begin(), static_cast<pstring::difference_type>(tmp.size() - 1));
@ -909,7 +919,7 @@ nl_double setup_t::model_value(detail::model_map_t &map, const pstring &entity)
case 'a': factor = 1e-18; break;
default:
if (*p < '0' || *p > '9')
log().fatal(MF_1_UNKNOWN_NUMBER_FACTOR_IN_1, entity);
throw nl_exception(MF_1_UNKNOWN_NUMBER_FACTOR_IN_1, entity);
}
if (factor != plib::constants<nl_double>::one())
tmp = plib::left(tmp, tmp.size() - 1);
@ -940,12 +950,10 @@ pool_owned_ptr<devices::nld_base_a_to_d_proxy> logic_family_std_proxy_t::create_
const logic_family_desc_t *setup_t::family_from_model(const pstring &model)
{
detail::model_map_t map;
model_parse(model, map);
if (model_value_str(map, "TYPE") == "TTL")
if (m_models.model_value_str(model, "TYPE") == "TTL")
return family_TTL();
if (model_value_str(map, "TYPE") == "CD4XXX")
if (m_models.model_value_str(model, "TYPE") == "CD4XXX")
return family_CD4XXX();
for (auto & e : m_nlstate.m_family_cache)
@ -954,13 +962,13 @@ const logic_family_desc_t *setup_t::family_from_model(const pstring &model)
auto ret = plib::make_unique<logic_family_std_proxy_t>();
ret->m_fixed_V = model_value(map, "FV");
ret->m_low_thresh_PCNT = model_value(map, "IVL");
ret->m_high_thresh_PCNT = model_value(map, "IVH");
ret->m_low_VO = model_value(map, "OVL");
ret->m_high_VO = model_value(map, "OVH");
ret->m_R_low = model_value(map, "ORL");
ret->m_R_high = model_value(map, "ORH");
ret->m_fixed_V = m_models.model_value(model, "FV");
ret->m_low_thresh_PCNT = m_models.model_value(model, "IVL");
ret->m_high_thresh_PCNT = m_models.model_value(model, "IVH");
ret->m_low_VO = m_models.model_value(model, "OVL");
ret->m_high_VO = m_models. model_value(model, "OVH");
ret->m_R_low = m_models.model_value(model, "ORL");
ret->m_R_high = m_models.model_value(model, "ORH");
auto retp = ret.get();

View File

@ -202,8 +202,35 @@ namespace netlist
const type_t m_type;
};
// ----------------------------------------------------------------------------------------
// setup_t
// Collection of models
// ----------------------------------------------------------------------------------------
class models_t
{
public:
void register_model(pstring model_in);
/* model / family related */
pstring model_value_str(pstring model, pstring entity);
double model_value(pstring model, pstring entity);
pstring model_type(pstring model) { return model_value_str(model, "COREMODEL"); }
private:
using model_map_t = std::unordered_map<pstring, pstring>;
void model_parse(const pstring &model, model_map_t &map);
pstring model_string(model_map_t &map);
std::unordered_map<pstring, pstring> m_models;
std::unordered_map<pstring, model_map_t> m_cache;
};
// ----------------------------------------------------------------------------------------
// nlparse_t
// ----------------------------------------------------------------------------------------
class nlparse_t
@ -213,7 +240,7 @@ namespace netlist
nlparse_t(setup_t &netlist, log_type &log);
void register_model(const pstring &model_in);
void register_model(const pstring &model_in) { m_models.register_model(model_in); }
void register_alias(const pstring &alias, const pstring &out);
void register_dippins_arr(const pstring &terms);
void register_dev(const pstring &classname, const pstring &name);
@ -240,7 +267,6 @@ namespace netlist
/* include other files */
void include(const pstring &netlist_name);
/* parse a source */
pstring build_fqn(const pstring &obj_name) const;
void register_alias_nofqn(const pstring &alias, const pstring &out);
@ -276,8 +302,12 @@ namespace netlist
*/
setup_t &setup() { return m_setup; }
const setup_t &setup() const { return m_setup; }
models_t &models() { return m_models; }
const models_t &models() const { return m_models; }
protected:
std::unordered_map<pstring, pstring> m_models;
models_t m_models;
std::stack<pstring> m_namespace_stack;
std::unordered_map<pstring, pstring> m_alias;
std::vector<link_t> m_links;
@ -299,6 +329,10 @@ namespace netlist
unsigned m_frontier_cnt;
};
// ----------------------------------------------------------------------------------------
// setup_t
// ----------------------------------------------------------------------------------------
class setup_t : public nlparse_t
{
public:
@ -323,24 +357,17 @@ namespace netlist
param_t *find_param(const pstring &param_in, bool required = true) const;
/* get family */
const logic_family_desc_t *family_from_model(const pstring &model);
void register_dynamic_log_devices();
void resolve_inputs();
plib::unique_ptr<plib::pistream> get_data_stream(const pstring &name);
factory::list_t &factory() { return m_factory; }
const factory::list_t &factory() const { return m_factory; }
/* model / family related */
const pstring model_value_str(detail::model_map_t &map, const pstring &entity);
double model_value(detail::model_map_t &map, const pstring &entity);
void model_parse(const pstring &model, detail::model_map_t &map);
const logic_family_desc_t *family_from_model(const pstring &model);
/* helper - also used by nltool */
const pstring resolve_alias(const pstring &name) const;

View File

@ -108,11 +108,6 @@ namespace netlist
OUTPUT = 2, /*!< object is an output */
};
/*! Type of the model map used.
* This is used to hold all #Models in an unordered map
*/
using model_map_t = std::unordered_map<pstring, pstring>;
} // namespace detail
#if (PHAS_INT128)

View File

@ -191,6 +191,12 @@ public:
return format_element(ptype_traits<T *>::size_spec(), ptype_traits<T *>::fmt_spec(), ptype_traits<T *>::cast(x));
}
template<typename X, typename Y, typename... Args>
pfmt &operator()(X&& x, Y && y, Args&&... args)
{
return ((*this)(std::forward<X>(x)))(std::forward<Y>(y), std::forward<Args>(args)...);
}
template<typename T>
pfmt &x(const T &x)
{

View File

@ -181,9 +181,11 @@ CIRCUIT_LAYOUT( breakout )
DIODE(CR5, "1N914")
DIODE(CR7, "1N914")
QBJT_EB(Q1, "2N3644")
QBJT_EB(Q2, "2N3643")
QBJT_EB(Q3, "2N3643")
// No need to model capacitance
QBJT_EB(Q1, "2N3644(CJC=0 CJE=0)")
QBJT_EB(Q2, "2N3643(CJC=0 CJE=0)")
QBJT_EB(Q3, "2N3643(CJC=0 CJE=0)")
CAP(C19, CAP_U(0.1))
CAP(C16, CAP_U(0.1))