netlist: add hints for outputs not connected. [Couriersud, Aaron Giles]

* Logic and analogue outputs can now be flagged as "NC" (not connected).
* Example: "HINT(IC13.4, NC)".
* This will suppress info messages to be logged.
* The HINT must apply to an existing terminal. HINTs for non-existing
terminals are treated as fatal errors.
* Terminals and logic inputs not connected are still treated as
warnings. These need though and a proper fix.
This commit is contained in:
couriersud 2020-06-28 16:50:59 +02:00
parent 9dcaa32e10
commit 1408aab30c
4 changed files with 63 additions and 47 deletions

View File

@ -14,6 +14,7 @@ namespace netlist
{
static constexpr const char sHINT_NO_DEACTIVATE[] = ".HINT_NO_DEACTIVATE"; // NOLINT(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
static constexpr const char sHINT_NC[] = ".HINT_NC"; // NOLINT(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
static constexpr const char sPowerGND[] = "GND"; // NOLINT(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
static constexpr const char sPowerVCC[] = "VCC"; // NOLINT(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
@ -56,6 +57,8 @@ namespace netlist
PERRMSGV(MF_UNABLE_TO_PARSE_MODEL_1, 1, "Unable to parse model: {1}")
PERRMSGV(MF_MODEL_ALREADY_EXISTS_1, 1, "Model already exists: {1}")
PERRMSGV(MF_DEVICE_ALREADY_EXISTS_1, 1, "Device already exists: {1}")
PERRMSGV(MF_UNUSED_HINT_1, 1, "Error hint {1} is not used")
PERRMSGV(MF_ADDING_HINT_1, 1, "Error adding hint {1} to hint list")
PERRMSGV(MF_ADDING_ALI1_TO_ALIAS_LIST, 1, "Error adding alias {1} to alias list")
PERRMSGV(MF_DIP_PINS_MUST_BE_AN_EQUAL_NUMBER_OF_PINS_1, 1,"You must pass an equal number of pins to DIPPINS {1}")
PERRMSGV(MF_PARAM_COUNT_MISMATCH_2, 2, "Parameter count mismatch for {1} - only found {2}")

View File

@ -375,10 +375,10 @@ void parser_t::netdev_defparam()
void parser_t::netdev_hint()
{
require_token(m_tok_paren_left);
pstring dev(get_identifier());
pstring id(get_identifier());
require_token(m_tok_comma);
pstring hint(get_identifier());
m_setup.register_param_val(dev + ".HINT_" + hint, 1);
m_setup.register_hint(id + ".HINT_" + hint);
require_token(m_tok_paren_right);
}

View File

@ -150,6 +150,15 @@ namespace netlist
*felem = f;
}
void nlparse_t::register_hint(const pstring &name)
{
if (!m_abstract.m_hints.insert({name, false}).second)
{
log().fatal(MF_ADDING_HINT_1(name));
throw nl_exception(MF_ADDING_HINT_1(name));
}
}
void nlparse_t::register_link(const pstring &sin, const pstring &sout)
{
register_link_fqn(build_fqn(sin), build_fqn(sout));
@ -307,7 +316,6 @@ namespace netlist
log().fatal(MF_ADDING_ALI1_TO_ALIAS_LIST(alias));
throw nl_exception(MF_ADDING_ALI1_TO_ALIAS_LIST(alias));
}
}
void nlparse_t::register_link_fqn(const pstring &sin, const pstring &sout)
@ -1078,31 +1086,47 @@ void setup_t::resolve_inputs()
for (auto & i : m_terminals)
{
detail::core_terminal_t *term = i.second;
bool is_nc(dynamic_cast< devices::NETLIB_NAME(nc_pin) *>(&term->device()) != nullptr);
if (term->has_net() && is_nc)
const pstring name_da = de_alias(term->name());
bool is_nc_pin(dynamic_cast< devices::NETLIB_NAME(nc_pin) *>(&term->device()) != nullptr);
bool is_nc_flagged(false);
auto hnc = m_abstract.m_hints.find(name_da + sHINT_NC);
if (hnc != m_abstract.m_hints.end())
{
log().error(ME_NC_PIN_1_WITH_CONNECTIONS(term->name()));
hnc->second = true; // mark as used
is_nc_flagged = true;
}
if (term->has_net() && is_nc_pin)
{
log().error(ME_NC_PIN_1_WITH_CONNECTIONS(name_da));
err = true;
}
else if (is_nc)
else if (is_nc_pin)
{
/* ignore */
}
else if (!term->has_net())
{
log().error(ME_TERMINAL_1_WITHOUT_NET(de_alias(term->name())));
log().error(ME_TERMINAL_1_WITHOUT_NET(name_da));
err = true;
}
else if (!term->net().has_connections())
{
if (term->is_logic_input())
log().warning(MW_LOGIC_INPUT_1_WITHOUT_CONNECTIONS(term->name()));
log().warning(MW_LOGIC_INPUT_1_WITHOUT_CONNECTIONS(name_da));
else if (term->is_logic_output())
log().info(MI_LOGIC_OUTPUT_1_WITHOUT_CONNECTIONS(term->name()));
{
if (!is_nc_flagged)
log().info(MI_LOGIC_OUTPUT_1_WITHOUT_CONNECTIONS(name_da));
}
else if (term->is_analog_output())
log().info(MI_ANALOG_OUTPUT_1_WITHOUT_CONNECTIONS(term->name()));
{
if (!is_nc_flagged)
log().info(MI_ANALOG_OUTPUT_1_WITHOUT_CONNECTIONS(name_da));
}
else
log().warning(MW_TERMINAL_1_WITHOUT_CONNECTIONS(term->name()));
log().warning(MW_TERMINAL_1_WITHOUT_CONNECTIONS(name_da));
}
}
log().verbose("checking tristate consistency ...");
@ -1498,21 +1522,8 @@ void setup_t::prepare_to_run()
auto f = m_params.find(p.first);
if (f == m_params.end())
{
if (plib::endsWith(p.first, sHINT_NO_DEACTIVATE))
{
// FIXME: get device name, check for device
auto *dev = m_nlstate.find_device(plib::replace_all(p.first, sHINT_NO_DEACTIVATE, ""));
if (dev == nullptr)
{
log().error(ME_DEVICE_NOT_FOUND_FOR_HINT(p.first));
errcnt++;
}
}
else
{
log().error(ME_UNKNOWN_PARAMETER(p.first));
errcnt++;
}
log().error(ME_UNKNOWN_PARAMETER(p.first));
errcnt++;
}
}
@ -1520,28 +1531,17 @@ void setup_t::prepare_to_run()
for (auto &d : m_nlstate.devices())
{
if (use_deactivate)
auto p = m_abstract.m_hints.find(d.second->name() + sHINT_NO_DEACTIVATE);
if (p != m_abstract.m_hints.end())
{
auto p = m_abstract.m_param_values.find(d.second->name() + sHINT_NO_DEACTIVATE);
if (p != m_abstract.m_param_values.end())
{
//FIXME: check for errors ...
bool err(false);
auto v = plib::pstonum_ne<nl_fptype>(p->second, err);
if (err || plib::abs(v - plib::floor(v)) > nlconst::magic(1e-6) )
{
log().error(ME_HND_VAL_NOT_SUPPORTED(p->second));
errcnt++;
}
else
{
// FIXME comparison with zero
d.second->set_hint_deactivate(v == nlconst::zero());
}
}
p->second = true; // mark as used
if (use_deactivate)
d.second->set_hint_deactivate(false);
else
d.second->set_hint_deactivate(true);
}
else
d.second->set_hint_deactivate(false);
d.second->set_hint_deactivate(true);
}
if (errcnt > 0)
@ -1566,6 +1566,16 @@ void setup_t::prepare_to_run()
}
}
log().verbose("looking for unused hints ...");
for (auto &h : m_abstract.m_hints)
{
if (!h.second)
{
log().fatal(MF_UNUSED_HINT_1(h.first));
throw nl_exception(MF_UNUSED_HINT_1(h.first));
}
}
log().verbose("initialize solver ...\n");
if (solver == nullptr)

View File

@ -61,7 +61,7 @@
setup.defparam(NET_STR(name), NET_STR(val));
#define HINT(name, val) \
setup.register_param(# name ".HINT_" # val, "1");
setup.register_hint(# name ".HINT_" # val);
#define NETDEV_PARAMI(name, param, val) \
setup.register_param(# name "." # param, val);
@ -234,6 +234,7 @@ namespace netlist
std::vector<std::pair<pstring, factory::element_t *>> m_device_factory;
// lifetime control only - can be cleared before run
std::vector<std::pair<pstring, pstring>> m_defparams;
std::unordered_map<pstring, bool> m_hints;
};
nlparse_t(log_type &log, abstract_t &abstract);
@ -253,6 +254,8 @@ namespace netlist
register_dev(classname, name, std::vector<pstring>());
}
void register_hint(const pstring &name);
void register_link(const pstring &sin, const pstring &sout);
void register_link_arr(const pstring &terms);
// also called from devices for latebinding connected terminals