netlist: Add tristate support for rom devices. [Couriersud]

Rom and prom devices now properly support tristate outputs. Native OC
output still on the todo list.

In addition this commit fixes a number of bugs around dealing with macro
level parameters and improves documentation by adding a parameter table.

Also srcclean.
This commit is contained in:
couriersud 2020-05-19 22:14:16 +02:00
parent 11af744ef3
commit e9a364dcc9
25 changed files with 372 additions and 153 deletions

View File

@ -293,6 +293,8 @@ namespace analog
NETLIB_RESET(QBJT_switch)
{
if (m_RB.solver() == nullptr && m_RC.solver() == nullptr)
throw nl_exception(MF_DEVICE_FRY_1(this->name()));
NETLIB_NAME(QBJT)::reset();
const auto zero(nlconst::zero());
@ -307,13 +309,11 @@ namespace analog
NETLIB_UPDATE(QBJT_switch)
{
// FIXME: this should never be called
if (!m_RB.P().net().is_rail_net())
m_RB.P().solve_now(); // Basis
else if (!m_RB.N().net().is_rail_net())
m_RB.N().solve_now(); // Emitter
else if (!m_RC.P().net().is_rail_net())
m_RC.P().solve_now(); // Collector
auto solv(m_RB.solver());
if (solv)
solv->solve_now();
else
m_RC.solver()->solve_now();
}
@ -371,20 +371,19 @@ namespace analog
// nld_Q - Ebers Moll
// ----------------------------------------------------------------------------------------
NETLIB_UPDATE(QBJT_EB)
{
// FIXME: this should never be called
if (!m_D_EB.P().net().is_rail_net())
m_D_EB.P().solve_now(); // Basis
else if (!m_D_EB.N().net().is_rail_net())
m_D_EB.N().solve_now(); // Emitter
auto solv(m_D_EB.solver());
if (solv)
solv->solve_now();
else
m_D_CB.N().solve_now(); // Collector
m_D_CB.solver()->solve_now();
}
NETLIB_RESET(QBJT_EB)
{
if (m_D_EB.solver() == nullptr && m_D_CB.solver() == nullptr)
throw nl_exception(MF_DEVICE_FRY_1(this->name()));
NETLIB_NAME(QBJT)::reset();
if (m_CJE)
{
@ -396,7 +395,6 @@ namespace analog
m_CJC->reset();
m_CJC->set_cap_embedded(m_modacc.m_CJC);
}
}
NETLIB_UPDATE_TERMINALS(QBJT_EB)
@ -425,7 +423,6 @@ namespace analog
-gce, 0, 0);
}
NETLIB_UPDATE_PARAM(QBJT_EB)
{
nl_fptype IS = m_modacc.m_IS;

View File

@ -177,8 +177,6 @@ namespace analog
m_trn = h;
return { G, - G * v };
}
if (step < 1e-9)
printf("Help %e\n", step);
const nl_fptype Gn = nlconst::two() * cap * m_trn;
const nl_fptype inp1 = Gn * v - (m_in + Gn * m_vn);
const nl_fptype G(nlconst::two() * cap * h);

View File

@ -51,7 +51,7 @@ namespace netlist
m_Q.push(stateQ, delay);
m_QQ.push(!stateQ, delay);
}
void newstate_setreset(const netlist_sig_t stateQ, const netlist_sig_t stateQQ)
{
// Q: 150 ns, QQ: 200 ns

View File

@ -30,13 +30,14 @@ namespace netlist
{
NETLIB_CONSTRUCTOR(generic_prom)
, m_enabled(*this, "m_enabled", true)
, m_TE(*this, "FORCE_TRISTATE_LOGIC", 0)
, m_A(*this, 0, "A{}", NETLIB_DELEGATE(generic_prom, addr))
, m_CEQ(*this, 1,
D::chip_enable_mask::value ^ static_cast<size_t>(0xffff), pstring("CE{}"),
std::array<nldelegate, 3>{ NETLIB_DELEGATE(generic_prom, ce<0>),
NETLIB_DELEGATE(generic_prom, ce<1>),
NETLIB_DELEGATE(generic_prom, ce<2>)})
, m_O(*this, D::data_name_offset::value, "O{}")
, m_O(*this, D::data_name_offset::value, "O{}", m_TE())
, m_ROM(*this, "ROM")
, m_power_pins(*this)
{
@ -51,11 +52,29 @@ namespace netlist
{
using cet = typename D::chip_enable_time;
m_enabled = (m_CEQ() == D::chip_enable_mask::value);
const auto delay = m_enabled ? D::access_time::value() : cet::value(N);
const data_type o = m_enabled ? m_ROM[m_A()] :
(1 << D::data_width::value) - 1; // FIXME tristate !
switch (D::output_id::value)
{
case 0: // logic
{
m_O.push(m_ROM[m_A()], D::access_time::value());
}
break;
case 1: // tristate
{
m_O.set_tristate(!m_enabled, cet::value(N), cet::value(N));
m_O.push(m_ROM[m_A()], D::access_time::value());
}
break;
default: // 2, open collector
{
const auto delay = m_enabled ? D::access_time::value() : cet::value(N);
const data_type o = m_enabled ? m_ROM[m_A()] :
(1 << D::data_width::value) - 1;
m_O.push(o, delay);
}
break;
}
m_O.push(o, delay);
}
inline
@ -63,7 +82,6 @@ namespace netlist
{
if (m_enabled)
{
// FIXME: Outputs are tristate. This needs to be properly implemented
m_O.push(m_ROM[m_A()], D::access_time::value());
}
}
@ -74,6 +92,7 @@ namespace netlist
}
state_var<bool> m_enabled;
param_logic_t m_TE;
object_array_t<logic_input_t, D::address_width::value> m_A;
object_array_t<logic_input_t, D::chip_enable_inputs::value> m_CEQ;
object_array_t<typename D::output_type, D::data_width::value> m_O;
@ -94,14 +113,15 @@ namespace netlist
using chip_enable_time = times_ns2<25, 25>;
using access_time = time_ns<40>;
using output_type = logic_output_t;
using output_type = tristate_output_t;
using output_id = desc_const<1>; // 0: logic, 1: tristate, 2: open collector
};
struct desc_74S287 : public desc_82S126
{
using chip_enable_time = times_ns2<15, 15>;
using access_time = time_ns<35>;
static constexpr const size_t data_name_offset = 0; // O0, O1, ..
using data_name_offset = desc_const<0>; // O0, O1, ... according to National Semiconductor datasheet
using chip_enable_time = times_ns2<15, 15>;
using access_time = time_ns<35>;
};
struct desc_82S123 : public desc_base
@ -117,7 +137,8 @@ namespace netlist
using chip_enable_time = times_ns1<35>;
using access_time = time_ns<45>;
using output_type = logic_output_t;
using output_type = tristate_output_t;
using output_id = desc_const<1>; // 0: logic, 1: tristate, 2: open collector
};
struct desc_2716 : public desc_base
@ -134,7 +155,8 @@ namespace netlist
using chip_enable_time = times_ns2<450, 100>; //CE, OE
using access_time = time_ns<450>;
using output_type = logic_output_t;
using output_type = tristate_output_t;
using output_id = desc_const<1>; // 0: logic, 1: tristate, 2: open collector
};

View File

@ -162,7 +162,7 @@ NETLIST_END()
* Naming conventions follow National Semiconductor datasheet
*
*/
static NETLIST_START(CD4069_DIP)
CD4069_GATE(A)
CD4069_GATE(B)
@ -170,7 +170,7 @@ static NETLIST_START(CD4069_DIP)
CD4069_GATE(D)
CD4069_GATE(E)
CD4069_GATE(F)
NET_C(A.VDD, B.VDD, C.VDD, D.VDD, E.VDD, E.VDD)
NET_C(A.VSS, B.VSS, C.VSS, D.VSS, E.VSS, F.VSS)
@ -268,7 +268,7 @@ NETLIST_START(CD4XXX_lib)
TT_LINE("1|0|55")
TT_FAMILY("CD4XXX")
TRUTHTABLE_END()
TRUTHTABLE_START(CD4070_GATE, 2, 1, "")
TT_HEAD("A,B|Q ")
TT_LINE("0,0|0|15")

View File

@ -17,11 +17,19 @@
//- for optimization of word expansion in bused organizations.
//-
//.
//- Pinalias: A6,A5,A4,A3,A0,A1,A2,GND,O3,O2,O1,O0,CE1Q,CE2Q,A7,VCC
//- Pinalias: A6,A5,A4,A3,A0,A1,A2,GND,O4,O3,O2,O1,CE1Q,CE2Q,A7,VCC
//- Package: DIP
//- Param: ROM
//- The name of the source to load the rom content from
//- Param: FORCE_TRISTATE_LOGIC
//- Set this parameter to 1 force tristate outputs into logic mode.
//- This should be done only if the device enable inputs are connected
//- in a way which always enables the device.
//- Param: MODEL
//- Overwrite the default model of the device. Use with care.
//- NamingConvention: Naming conventions follow Philips Components-Signetics datasheet
//- Limitations:
//- Currently neither OC nor Tristate is supported.
//- Currently OC is not supported.
//-
//- Example: 82S126.cpp,82S126_example
//- FunctionTable:
@ -33,7 +41,11 @@ static NETLIST_START(PROM_82S126_DIP)
PROM_82S126(A)
DEFPARAM(ROM, "unknown")
DEFPARAM(FORCE_TRISTATE_LOGIC, 0)
DEFPARAM(MODEL, "$(A.MODEL)")
PARAM(A.ROM, "$(@.ROM)")
PARAM(A.FORCE_TRISTATE_LOGIC, "$(@.FORCE_TRISTATE_LOGIC)")
PARAM(A.MODEL, "$(@.MODEL)")
ALIAS(1, A.A6)
ALIAS(2, A.A5)
ALIAS(3, A.A4)
@ -42,22 +54,58 @@ static NETLIST_START(PROM_82S126_DIP)
ALIAS(6, A.A1)
ALIAS(7, A.A2)
ALIAS(8, A.GND)
ALIAS(9, A.O3)
ALIAS(10, A.O2)
ALIAS(11, A.O1)
ALIAS(12, A.O0)
ALIAS(9, A.O4)
ALIAS(10, A.O3)
ALIAS(11, A.O2)
ALIAS(12, A.O1)
ALIAS(13, A.CE1Q)
ALIAS(14, A.CE2Q)
ALIAS(15, A.A7)
ALIAS(16, A.VCC)
NETLIST_END()
//- Identifier: PROM_74S287_DIP
//- Title: 74S287 (256 x 4) 1024-Bit TTL PROM
//- Description: This Schottky memory is organized in the popular 256 words by
//- 4 bits configuration. Memory enable inputs are provided to control the
//- output states. When the device is enabled, the outputs represent the
//- contents of the selected word. When disabled, the 4 outputs go to the
//- or high impedance state.
//-
//- PROMs are shipped from the factory with lows in all locations. A high
//- may be programmed into any selected location by following the
//- programming instructions.
//-
//.
//- Pinalias: A6,A5,A4,A3,A0,A1,A2,GND,O3,O2,O1,O0,CE1Q,CE2Q,A7,VCC
//- Package: DIP
//- Param: ROM
//- The name of the source to load the rom content from
//- Param: FORCE_TRISTATE_LOGIC
//- Set this parameter to 1 force tristate outputs into logic mode.
//- This should be done only if the device enable inputs are connected
//- in a way which always enables the device.
//- Param: MODEL
//- Overwrite the default model of the device. Use with care.
//- NamingConvention: Naming conventions follow National Semiconductor datasheet
//- Limitations:
//- None.
//-
//- Example: 74S287.cpp,74S287_example
//- FunctionTable:
//- http://pdf.datasheetcatalog.com/datasheet_pdf/national-semiconductor/DM54S287AJ_to_DM74S287V.pdf
//-
static NETLIST_START(PROM_74S287_DIP)
PROM_74S287(A)
DEFPARAM(ROM, "unknown")
DEFPARAM(FORCE_TRISTATE_LOGIC, 0)
DEFPARAM(MODEL, "$(A.MODEL)")
PARAM(A.ROM, "$(@.ROM)")
PARAM(A.FORCE_TRISTATE_LOGIC, "$(@.FORCE_TRISTATE_LOGIC)")
PARAM(A.MODEL, "$(@.MODEL)")
ALIAS(1, A.A6)
ALIAS(2, A.A5)
ALIAS(3, A.A4)
@ -88,12 +136,20 @@ NETLIST_END()
//- memory expansion. They feature either open collector or 3-State outputs
//- for optimization of word expansion in bused organizations.
//-
//.
//-
//- Pinalias: O1,O2,O3,O4,O5,O6,O7,GND,O8,A0,A1,A2,A3,A4,CEQ,VCC
//- Package: DIP
//- Param: ROM
//- The name of the source to load the rom content from
//- Param: FORCE_TRISTATE_LOGIC
//- Set this parameter to 1 force tristate outputs into logic mode.
//- This should be done only if the device enable inputs are connected
//- in a way which always enables the device.
//- Param: MODEL
//- Overwrite the default model of the device. Use with care.
//- NamingConvention: Naming conventions follow Philips Components-Signetics datasheet
//- Limitations:
//- Currently neither OC nor Tristate is supported.
//- Currently OC is not supported.
//-
//- Example: 82S123.cpp,82S123_example
//- FunctionTable:
@ -105,7 +161,11 @@ static NETLIST_START(PROM_82S123_DIP)
PROM_82S123(A)
DEFPARAM(ROM, "unknown")
DEFPARAM(FORCE_TRISTATE_LOGIC, 0)
DEFPARAM(MODEL, "$(A.MODEL)")
PARAM(A.ROM, "$(@.ROM)")
PARAM(A.FORCE_TRISTATE_LOGIC, "$(@.FORCE_TRISTATE_LOGIC)")
PARAM(A.MODEL, "$(@.MODEL)")
ALIAS(1, A.O0)
ALIAS(2, A.O1)
ALIAS(3, A.O2)
@ -151,9 +211,17 @@ NETLIST_END()
//-
//- Pinalias: A7,A6,A6,A4,A4,A2,A1,A0,O0,O1,O2,GND,O3,O4,O5,O6,O7,CE1Q/CE,A10,CE2Q/OE,VPP,A9,A8,VCC
//- Package: DIP
//- Param: ROM
//- The name of the source to load the rom content from
//- Param: FORCE_TRISTATE_LOGIC
//- Set this parameter to 1 force tristate outputs into logic mode.
//- This should be done only if the device enable inputs are connected
//- in a way which always enables the device.
//- Param: MODEL
//- Overwrite the default model of the device. Use with care.
//- NamingConvention: Naming conventions follow Intel datasheet
//- Limitations:
//- Currently Tristate is not supported.
//- Currently OC is not supported.
//-
//- Example: 2716.cpp,2716_example
//- FunctionTable:
@ -164,7 +232,11 @@ static NETLIST_START(EPROM_2716_DIP)
EPROM_2716(A)
DEFPARAM(ROM, "unknown")
DEFPARAM(FORCE_TRISTATE_LOGIC, 0)
DEFPARAM(MODEL, "$(A.MODEL)")
PARAM(A.ROM, "$(@.ROM)")
PARAM(A.FORCE_TRISTATE_LOGIC, "$(@.FORCE_TRISTATE_LOGIC)")
PARAM(A.MODEL, "$(@.MODEL)")
ALIAS(1, A.A7)
ALIAS(2, A.A6)
ALIAS(3, A.A5)

View File

@ -746,6 +746,10 @@ NETLIST_END()
//-
//- Pinalias: 1GQ,1A,1Y,2GQ,2A,2Y,GND,3Y,3A,3GQ,4Y,4A,4GQ,VCC
//- Package: DIP
//- Param: FORCE_TRISTATE_LOGIC
//- Set this parameter to 1 force tristate outputs into logic mode.
//- This should be done only if the device enable inputs are connected
//- in a way which always enables the device.
//- NamingConvention: Naming conventions follow Texas instruments datasheet
//- Limitations:
//- No limitations
@ -768,7 +772,8 @@ static NETLIST_START(TTL_74125_DIP)
TTL_74125_GATE(A3)
TTL_74125_GATE(A4)
DEFPARAM(FORCE_TRISTATE_LOGIC, 0)
DEFPARAM(FORCE_TRISTATE_LOGIC, "$(@.A1.FORCE_TRISTATE_LOGIC")
PARAM(A1.FORCE_TRISTATE_LOGIC, "$(@.FORCE_TRISTATE_LOGIC)")
PARAM(A2.FORCE_TRISTATE_LOGIC, "$(@.FORCE_TRISTATE_LOGIC)")
PARAM(A3.FORCE_TRISTATE_LOGIC, "$(@.FORCE_TRISTATE_LOGIC)")

View File

@ -753,10 +753,11 @@ namespace netlist
// logic_output_t
// ----------------------------------------------------------------------------------------
logic_output_t::logic_output_t(device_t &dev, const pstring &aname)
logic_output_t::logic_output_t(device_t &dev, const pstring &aname, bool dummy)
: logic_t(dev, aname, STATE_OUT)
, m_my_net(dev.state(), name() + ".net", this)
{
plib::unused_var(dummy);
this->set_net(&m_my_net);
state().register_net(owned_pool_ptr<logic_net_t>(&m_my_net, false));
state().setup().register_term(*this);
@ -803,12 +804,16 @@ namespace netlist
// Parameters ...
// ----------------------------------------------------------------------------------------
param_t::param_t(core_device_t *device, const pstring &name)
: device_object_t(device, (device ? device->name() + "." : "") + name)
// deviceless, it's the responsibility of the owner to register!
param_t::param_t(const pstring &name)
: device_object_t(nullptr, name)
{
// if deviceless, it's the responsibility of the owner to register!
if (device != nullptr)
device->state().setup().register_param_t(*this);
}
param_t::param_t(core_device_t &device, const pstring &name)
: device_object_t(&device, device.name() + "." + name)
{
device.state().setup().register_param_t(*this);
}
param_t::param_type_t param_t::param_type() const noexcept(false)
@ -829,23 +834,26 @@ namespace netlist
}
pstring param_t::get_initial(const core_device_t &dev, bool *found) const
pstring param_t::get_initial(const core_device_t *dev, bool *found) const
{
pstring res = dev.state().setup().get_initial_param_val(this->name(), "");
pstring res = dev->state().setup().get_initial_param_val(this->name(), "");
*found = (res != "");
return res;
}
param_str_t::param_str_t(core_device_t &device, const pstring &name, const pstring &val)
: param_t(&device, name)
: param_t(device, name)
{
m_param = plib::make_unique<pstring>(device.state().setup().get_initial_param_val(this->name(),val));
m_param = plib::make_unique<pstring>(val);
*m_param = device.state().setup().get_initial_param_val(this->name(),val);
}
param_str_t::param_str_t(netlist_state_t &state, const pstring &name, const pstring &val)
: param_t(nullptr, name)
: param_t(name)
{
m_param = plib::make_unique<pstring>(state.setup().get_initial_param_val(this->name(),val));
// deviceless parameter, no registration, owner is responsible
m_param = plib::make_unique<pstring>(val);
*m_param = state.setup().get_initial_param_val(this->name(),val);
}
void param_str_t::changed() noexcept
@ -853,7 +861,7 @@ namespace netlist
}
param_ptr_t::param_ptr_t(core_device_t &device, const pstring &name, uint8_t * val)
: param_t(&device, name)
: param_t(device, name)
{
m_param = val;
}

View File

@ -547,6 +547,11 @@ namespace netlist
private:
};
/// \brief Base class for all objects bejng owned by a netlist
///
/// The object provides adds \ref netlist_state_t and \ref netlist_t
/// accessors.
///
class netlist_object_t : public object_t
{
public:
@ -851,18 +856,31 @@ namespace netlist
solver::matrix_solver_t *solver() const noexcept;
};
// -----------------------------------------------------------------------------
// terminal_t
// -----------------------------------------------------------------------------
/// \brief Base clase for terminals.
///
/// Each \ref nld_twoterm object consists of two terminals. Terminals
/// are at the core of analog netlists and provide. \ref net_t objects
/// connect terminals.
///
class terminal_t : public analog_t
{
public:
/// \brief constructor
///
/// @param dev core_devict_t object owning the terminal
/// @param aname name of this terminal
/// @param otherterm pointer to the sibling terminal
terminal_t(core_device_t &dev, const pstring &aname, terminal_t *otherterm);
/// \brief Returns voltage of connected net
///
/// @return voltage of net this terminal is connected to
nl_fptype operator ()() const noexcept;
/// @brief sets conductivity value of this terminal
///
/// @param G Conductivity
void set_conductivity(nl_fptype G) const noexcept
{
set_go_gt_I(-G, G, nlconst::zero());
@ -884,14 +902,17 @@ namespace netlist
}
}
void solve_now() const;
/// @brief Solve the system this terminal is connected to.
///
/// \note deprecated - will be removed
void solve_now() const; // FIXME: remove this
void set_ptrs(nl_fptype *gt, nl_fptype *go, nl_fptype *Idr) noexcept(false);
private:
nl_fptype *m_Idr; // drive current
nl_fptype *m_go; // conductance for Voltage from other term
nl_fptype *m_gt; // conductance for total conductance
nl_fptype *m_Idr; ///< drive current
nl_fptype *m_go; ///< conductance for Voltage from other term
nl_fptype *m_gt; ///< conductance for total conductance
};
@ -1007,7 +1028,16 @@ namespace netlist
{
public:
logic_output_t(device_t &dev, const pstring &aname);
/// \brief logic output constructor
///
/// The third parameter does nothing. It is provided only for
/// compatibility with tristate_output_t in templatized device models
///
/// \param dev Device owning this output
/// \param aname The name of this output
/// \param dummy Dummy parameter to allow construction like tristate output
///
logic_output_t(device_t &dev, const pstring &aname, bool dummy = false);
void initial(netlist_sig_t val) noexcept;
@ -1021,6 +1051,20 @@ namespace netlist
m_my_net.set_Q_time(newQ, at); // take the shortcut
}
/// \brief Dummy implementation for templatized generic devices
///
/// This function shall never be called. It is defined here so that
/// templatized generic device models do not have to do tons of
/// template magic.
///
/// This function throws an exception if actually called.
///
[[noreturn]] void set_tristate(bool v,
netlist_time ts_off_on, netlist_time ts_on_off) const
{
plib::unused_var(v, ts_off_on, ts_on_off);
throw nl_exception("set_tristate on logic_output should never be called!");
}
private:
logic_net_t m_my_net;
};
@ -1049,7 +1093,7 @@ namespace netlist
tristate_output_t(device_t &dev, const pstring &aname, bool force_logic)
: logic_output_t(dev, aname)
, m_last_logic(dev, name() + "." + "m_last_logic", 1) // force change
, m_tristate(dev, name() + "." + "m_tristate", 2) // force change
, m_tristate(dev, name() + "." + "m_tristate", force_logic ? 0 : 2) // force change
, m_force_logic(force_logic)
{}
@ -1063,7 +1107,6 @@ namespace netlist
void set_tristate(bool v,
netlist_time ts_off_on, netlist_time ts_on_off) noexcept
{
//printf("%s %d\n", this->name().c_str(), (int) m_force_logic);
if (!m_force_logic)
if (v != m_tristate)
{
@ -1103,10 +1146,9 @@ namespace netlist
analog_net_t m_my_net;
};
// -----------------------------------------------------------------------------
// param_t
// -----------------------------------------------------------------------------
/// @brief Base class for all device parameters
///
/// All device parameters classes derive from this object.
class param_t : public detail::device_object_t
{
public:
@ -1119,7 +1161,10 @@ namespace netlist
POINTER // Special-case which is always initialized at MAME startup time
};
param_t(core_device_t *device, const pstring &name);
//deviceless, it's the responsibility of the owner to register!
param_t(const pstring &name);
param_t(core_device_t &device, const pstring &name);
PCOPYASSIGNMOVE(param_t, delete)
virtual ~param_t() noexcept = default;
@ -1132,7 +1177,7 @@ namespace netlist
void update_param() noexcept;
pstring get_initial(const core_device_t &dev, bool *found) const;
pstring get_initial(const core_device_t *dev, bool *found) const;
template<typename C>
void set_and_update_param(C &p, const C v) noexcept
@ -1226,7 +1271,7 @@ namespace netlist
param_str_t(core_device_t &device, const pstring &name, const pstring &val);
param_str_t(netlist_state_t &state, const pstring &name, const pstring &val);
const pstring &operator()() const noexcept { return str(); }
pstring operator()() const noexcept { return str(); }
void set(const pstring &param)
{
if (*m_param != param)
@ -1242,7 +1287,7 @@ namespace netlist
}
protected:
virtual void changed() noexcept;
const pstring &str() const noexcept { return *m_param; }
pstring str() const noexcept { pstring ret = *m_param; return ret;}
private:
plib::unique_ptr<pstring> m_param;
};
@ -1279,7 +1324,9 @@ namespace netlist
using value_str_t = value_base_t<pstring>;
param_model_t(core_device_t &device, const pstring &name, const pstring &val)
: param_str_t(device, name, val) { }
: param_str_t(device, name, val)
{
}
pstring value_str(const pstring &entity);
nl_fptype value(const pstring &entity);
@ -1926,10 +1973,10 @@ namespace netlist
}
template<class D>
object_array_base_t(D &dev, std::size_t offset, const pstring &fmt)
object_array_base_t(D &dev, std::size_t offset, const pstring &fmt, bool force_logic = false)
{
for (std::size_t i = 0; i<N; i++)
this->emplace(i, dev, formatted(fmt, i+offset));
this->emplace(i, dev, formatted(fmt, i+offset), force_logic);
}
template<class D>
@ -1980,7 +2027,7 @@ namespace netlist
template<class D, std::size_t ND>
object_array_t(D &dev, std::size_t offset, std::size_t qmask,
// const pstring &fmt, std::initializer_list<nldelegate> &delegates)
// const pstring &fmt, std::initializer_list<nldelegate> &delegates)
const pstring &fmt, std::array<nldelegate, ND> &&delegates)
{
passert_always_msg(delegates.size() >= N, "initializer_list size mismatch");
@ -2052,6 +2099,47 @@ namespace netlist
for (std::size_t i = 8; i < N; i++)
(*this)[i].push((v >> i) & 1, t);
}
void set_tristate(bool v,
netlist_time ts_off_on, netlist_time ts_on_off) noexcept
{
for (std::size_t i = 0; i < N; i++)
(*this)[i].set_tristate(v, ts_off_on, ts_on_off);
}
};
template<std::size_t N>
class object_array_t<tristate_output_t,N> : public object_array_base_t<tristate_output_t, N>
{
public:
using base_type = object_array_base_t<tristate_output_t, N>;
using base_type::base_type;
using value_type = std::uint_fast32_t;
//using value_type = typename plib::least_type_for_bits<N>::type;
void push(value_type v, netlist_time t)
{
if (N >= 1) (*this)[0].push((v >> 0) & 1, t);
if (N >= 2) (*this)[1].push((v >> 1) & 1, t);
if (N >= 3) (*this)[2].push((v >> 2) & 1, t);
if (N >= 4) (*this)[3].push((v >> 3) & 1, t);
if (N >= 5) (*this)[4].push((v >> 4) & 1, t);
if (N >= 6) (*this)[5].push((v >> 5) & 1, t);
if (N >= 7) (*this)[6].push((v >> 6) & 1, t);
if (N >= 8) (*this)[7].push((v >> 7) & 1, t);
for (std::size_t i = 8; i < N; i++)
(*this)[i].push((v >> i) & 1, t);
}
void set_tristate(bool v,
netlist_time ts_off_on, netlist_time ts_on_off) noexcept
{
for (std::size_t i = 0; i < N; i++)
(*this)[i].set_tristate(v, ts_off_on, ts_on_off);
}
};
// -----------------------------------------------------------------------------
@ -2108,7 +2196,6 @@ namespace netlist
return state().make_object<T>(std::forward<Args>(args)...);
}
inline void param_t::update_param() noexcept
{
device().update_param();
@ -2116,11 +2203,11 @@ namespace netlist
template <typename T>
param_num_t<T>::param_num_t(core_device_t &device, const pstring &name, const T val)
: param_t(&device, name)
: param_t(device, name)
, m_param(val)
{
//m_param = device.setup().get_initial_param_val(this->name(),val);
bool found = false;
pstring p = this->get_initial(device, &found);
pstring p = this->get_initial(&device, &found);
if (found)
{
plib::pfunction<nl_fptype> func;
@ -2131,18 +2218,17 @@ namespace netlist
throw nl_exception(MF_INVALID_NUMBER_CONVERSION_1_2(device.name() + "." + name, p));
m_param = static_cast<T>(valx);
}
else
m_param = val;
device.state().save(*this, m_param, this->name(), "m_param");
}
template <typename T>
param_enum_t<T>::param_enum_t(core_device_t &device, const pstring &name, const T val)
: param_t(&device, name), m_param(val)
: param_t(device, name)
, m_param(val)
{
bool found = false;
pstring p = this->get_initial(device, &found);
pstring p = this->get_initial(&device, &found);
if (found)
{
T temp(val);
@ -2317,8 +2403,6 @@ namespace netlist
inline netlist_sig_t logic_input_t::Q() const noexcept
{
nl_assert(terminal_state() != STATE_INP_PASSIVE);
//if (net().Q() != m_Q)
// printf("term: %s, %d %d TS %d\n", this->name().c_str(), net().Q(), m_Q, terminal_state());
#if NL_USE_COPY_INSTEAD_OF_REFERENCE
return m_Q;
#else

View File

@ -98,12 +98,12 @@ namespace netlist
PERRMSGV(ME_TERMINAL_1_WITHOUT_NET, 1, "Found terminal {1} without a net")
PERRMSGV(MF_TERMINALS_WITHOUT_NET, 0, "Found terminals without a net")
PERRMSGV(ME_TRISTATE_NO_PROXY_FOUND_2, 2,
PERRMSGV(ME_TRISTATE_NO_PROXY_FOUND_2, 2,
"Tristate output {1} on device {2} is not connected to a proxy. You "
"need to set parameter FORCE_TRISTATE_LOGIC for device {2} if "
"tristate enable inputs are all connected to fixed inputs. If this "
"is not the case: Review your netlist. Something is wrong.")
PERRMSGV(ME_TRISTATE_PROXY_FOUND_2, 2,
PERRMSGV(ME_TRISTATE_PROXY_FOUND_2, 2,
"The tristate output {1} on device {2} is connected to an analog net "
"but has been forced to act as a logic output. Parameter "
" FORCE_TRISTATE_LOGIC for device {2} needs to be disabled!.")
@ -147,6 +147,14 @@ namespace netlist
PERRMSGV(MW_MOSFET_THRESHOLD_VOLTAGE, 1, "Mosfet: Threshold voltage not specified for {1}")
// nld_bjt.cpp
PERRMSGV(MF_DEVICE_FRY_1, 1,
"Please don't fry device {}. Most likely this error is caused by the"
" fact that you want to exclude the analog device from the netlist."
" This is not the right approach. If you want to exclude the device,"
" exclude the device altogether, i.e. by using #ifdef/#if statements.")
// nl_tool.cpp
PERRMSGV(MF_FILE_OPEN_ERROR, 1, "Error opening file: {1}")

View File

@ -15,11 +15,11 @@ namespace netlist {
namespace factory {
// FIXME: this doesn't do anything, check how to remove
class NETLIB_NAME(wrapper) : public device_t
class NETLIB_NAME(wrapper) : public base_device_t
{
public:
NETLIB_NAME(wrapper)(netlist_state_t &anetlist, const pstring &name)
: device_t(anetlist, name)
: base_device_t(anetlist, name)
{
}
protected:

View File

@ -198,8 +198,6 @@ namespace netlist
pstring fqn = build_fqn(param);
pstring val(value);
//printf("RegParam %s %s\n", fqn.c_str(), val.c_str());
// strip " from stringified strings
if (plib::startsWith(value, "\"") && plib::endsWith(value, "\""))
val = value.substr(1, value.length() - 2);
@ -229,8 +227,13 @@ namespace netlist
void nlparse_t::defparam(const pstring &name, const pstring &def)
{
//printf("Registering %s\n", name.c_str());
m_abstract.m_defparams.emplace_back(namespace_prefix() + name, def);
// strip " from stringified strings
pstring val(def);
if (plib::startsWith(def, "\"") && plib::endsWith(def, "\""))
val = def.substr(1, def.length() - 2);
// Replace "@." with the current namespace
val = plib::replace_all(val, "@.", namespace_prefix());
m_abstract.m_defparams.emplace_back(namespace_prefix() + name, val);
}
void nlparse_t::register_lib_entry(const pstring &name, factory::properties &&props)
@ -422,37 +425,40 @@ pstring setup_t::termtype_as_str(detail::core_terminal_t &in)
pstring setup_t::get_initial_param_val(const pstring &name, const pstring &def) const
{
auto i = m_abstract.m_param_values.find(name);
pstring v = (i != m_abstract.m_param_values.end()) ? i->second : def;
auto found_pat(false);
pstring v = (i == m_abstract.m_param_values.end()) ? def : i->second;
//printf("%s -> %s\n", name.c_str(), v.c_str());
auto sp(plib::psplit(v, std::vector<pstring>({"$(", ")"})));
std::size_t p(0);
v = "";
while (p < sp.size())
do
{
if (sp[p] == "$(")
found_pat = false;
auto sp(plib::psplit(v, std::vector<pstring>({"$(", ")"})));
std::size_t p(0);
v = "";
while (p < sp.size())
{
p++;
pstring r;
while (p < sp.size() && sp[p] != ")")
r += sp[p++];
p++;
auto k = m_params.find(r);
if (k != m_params.end())
if (sp[p] == "$(")
{
v = v + k->second.param().valstr();
p++;
pstring r;
while (p < sp.size() && sp[p] != ")")
r += sp[p++];
p++;
auto k = m_params.find(r);
if (k != m_params.end())
{
v = v + k->second.param().valstr();
found_pat = true;
}
else
{
// pass - on
v = v + "$(" + r + ")";
}
}
else
{
v = v + "UNDEFINED_" + r;
}
//v = v + get_initial_param_val(r, "UNDEFINED_" + r);
v += sp[p++];
}
else
v += sp[p++];
}
} while (found_pat);
return v;
}
@ -1172,7 +1178,7 @@ void models_t::model_parse(const pstring &model_in, map_t &map)
key = plib::ucase(model);
auto i = m_models.find(key);
if (i == m_models.end())
throw nl_exception(MF_MODEL_NOT_FOUND(model));
throw nl_exception(MF_MODEL_NOT_FOUND("xx" + model));
model = i->second;
}
pstring xmodel = plib::left(model, pos);
@ -1259,7 +1265,6 @@ nl_fptype models_t::model_t::value(const pstring &entity) const
if (factor != nlconst::one())
tmp = plib::left(tmp, tmp.size() - 1);
// FIXME: check for errors
//printf("%s %s %e %e\n", entity.c_str(), tmp.c_str(), plib::pstonum<nl_fptype>(tmp), factor);
bool err(false);
auto val = plib::pstonum_ne<nl_fptype>(tmp, err);
if (err)

View File

@ -270,7 +270,7 @@ namespace netlist
std::unordered_map<pstring, pstring> m_alias;
std::vector<link_t> m_links;
std::unordered_map<pstring, pstring> m_param_values;
models_t::raw_map_t m_models;
models_t::raw_map_t m_models;
// need to preserve order of device creation ...
std::vector<std::pair<pstring, factory::element_t *>> m_device_factory;
@ -491,7 +491,7 @@ namespace netlist
std::unordered_map<pstring, param_ref_t> m_params;
std::unordered_map<const detail::core_terminal_t *,
devices::nld_base_proxy *> m_proxies;
std::vector<plib::unique_ptr<param_t>> m_defparam_lifetime;
std::vector<plib::unique_ptr<param_t>> m_defparam_lifetime;
unsigned m_proxy_cnt;
};

View File

@ -202,7 +202,7 @@ namespace netlist
{
return NLTIME_FROM_NS(N == 0 ? value0 :
N == 1 ? value1 :
value2);
value2);
}
};
@ -211,7 +211,7 @@ namespace netlist
/// See the 74125 implementation
///
template <std::size_t V>
using desc_const = std::integral_constant<std::size_t, V>;
using desc_const = std::integral_constant<std::size_t, V>;
};

View File

@ -242,7 +242,6 @@ namespace plib
bool do_k(OPS &ops, VT &x, std::size_t &itr_used, FT rho_delta, bool dummy)
{
plib::unused_var(dummy);
//printf("%d\n", k);
if (do_k<k-1, OPS>(ops, x, itr_used, rho_delta, do_khelper<k-1>::value))
return true;

View File

@ -399,9 +399,7 @@ namespace plib {
{
static_assert(ALIGN >= alignof(T), "Alignment must be greater or equal to alignof(T)");
static_assert(is_pow2(ALIGN), "Alignment must be a power of 2");
//auto t = reinterpret_cast<std::uintptr_t>(p);
//if (t & (ALIGN-1))
// printf("alignment error!");
#if (PUSE_ALIGNED_HINTS)
return reinterpret_cast<T *>(__builtin_assume_aligned(p, ALIGN));
#else

View File

@ -275,9 +275,6 @@ namespace plib {
postfix.push_back(opstk.top());
opstk.pop();
}
//printf("e : %s\n", expr.c_str());
//for (auto &s : postfix)
// printf("x : %s\n", s.c_str());
compile_postfix(inputs, postfix, expr);
}

View File

@ -118,7 +118,6 @@ namespace plib {
mempool &mp = b->m_mempool;
b->m_num_alloc--;
mp.m_stat_cur_alloc -= size;
//printf("Freeing in block %p %lu\n", b, b->m_num_alloc);
if (b->m_num_alloc == 0)
{
auto itb = std::find(mp.m_blocks.begin(), mp.m_blocks.end(), b);

View File

@ -101,7 +101,6 @@ namespace plib {
if (bytes > m_buf.size())
bytes = m_buf.size();
std::copy(m_strm->m_outbuf.c_str() + m_strm->m_pos, m_strm->m_outbuf.c_str() + m_strm->m_pos + bytes, m_buf.data());
//printf("%ld\n", (long int)bytes);
this->setg(m_buf.data(), m_buf.data(), m_buf.data() + bytes);
m_strm->m_pos += static_cast<long>(bytes);

View File

@ -42,7 +42,6 @@ namespace plib
}
else
*idx = constants<std::size_t>::zero();
//printf("%s, %f, %lu %ld\n", arg, (double)x, *idx, (long int) ss.tellg());
return x;
}

View File

@ -694,6 +694,7 @@ struct doc_ext
pstring description;
std::vector<pstring> pinalias;
pstring package;
std::vector<std::pair<pstring, pstring>> params;
pstring namingconventions;
pstring limitations;
pstring functiontable;
@ -702,7 +703,6 @@ struct doc_ext
static doc_ext read_docsrc(const pstring &fname, const pstring &id)
{
//printf("file %s\n", fname.c_str());
plib::putf8_reader r = plib::putf8_reader(plib::make_unique<std::ifstream>(plib::filesystem::u8path(fname)));
if (r.stream().fail())
throw netlist::nl_exception(netlist::MF_FILE_OPEN_ERROR(fname));
@ -725,10 +725,12 @@ static doc_ext read_docsrc(const pstring &fname, const pstring &id)
throw netlist::nl_exception(l+" size mismatch");
pstring n(plib::trim(a[0]));
pstring v(a.size() < 2 ? "" : plib::trim(a[1]));
pstring v2(v);
if (n == "Identifier")
{
if (!r.readline(l) || ret.id == id)
return (ret.id == id ? ret : doc_ext());
ret = doc_ext();
ret.id = v;
}
else
@ -755,6 +757,8 @@ static doc_ext read_docsrc(const pstring &fname, const pstring &id)
ret.limitations = v;
else if (n == "FunctionTable")
ret.functiontable = v;
else if (n == "Param")
ret.params.push_back(std::pair<pstring, pstring>(v2, plib::trim(v.substr(v2.length()))));
else if (n == "Example")
{
ret.example = plib::psplit(plib::trim(v),",",true);
@ -929,25 +933,33 @@ void tool_app_t::create_docheader()
pout("\n");
std::vector<doc_ext> de_cache;
for (auto &e : nt.parser().factory())
{
pout("//! [{1} csynopsis]\n", e->name());
header_entry(e.get());
pout("//! [{1} csynopsis]\n", e->name());
pout("//! [{1} synopsis]\n", e->name());
mac(e.get());
pout("//! [{1} synopsis]\n", e->name());
auto d(read_docsrc(e->source().file_name(), e->name()));
if (d.id != "")
{
pout("//! [{1} csynopsis]\n", e->name());
header_entry(e.get());
pout("//! [{1} csynopsis]\n", e->name());
pout("//! [{1} synopsis]\n", e->name());
mac(e.get());
pout("//! [{1} synopsis]\n", e->name());
}
de_cache.push_back(std::move(d));
}
poutprefix("", "");
poutprefix("///", "");
//poutprefix("///", " @file ");
poutprefix("///", " @page '' "); // FIXME: snippets and pages need to be separate files
poutprefix("///", " @page ''"); // FIXME: snippets and pages need to be separate files
poutprefix("", "");
for (auto &e : nt.parser().factory())
for (auto &d : de_cache)
{
auto d(read_docsrc(e->source().file_name(), e->name()));
//auto d(read_docsrc(e->source().file_name(), e->name()));
if (d.id != "")
{
@ -967,7 +979,17 @@ void tool_app_t::create_docheader()
poutprefix("///", "");
poutprefix("///", " @snippet devsyn.dox.h {} csynopsis", d.id);
poutprefix("///", "");
poutprefix("///", " @section {}_2 Connection Diagram", d.id);
#if 1
poutprefix("///", " @section {}_2 Parameters", d.id);
poutprefix("///", "");
poutprefix("///", " <table>");
poutprefix("///", " <tr><th>Name</th><th>Description</th></tr>");
for (auto &e : d.params)
poutprefix("///", " <tr><td>{1}</td><td>{2}</td></tr>", e.first, e.second);
poutprefix("///", " </table>");
#endif
poutprefix("///", "");
poutprefix("///", " @section {}_3 Connection Diagram", d.id);
poutprefix("///", "");
if (!d.pinalias.empty())
@ -990,20 +1012,20 @@ void tool_app_t::create_docheader()
poutprefix("///", "");
poutprefix("///", " {}", d.namingconventions);
poutprefix("///", "");
poutprefix("///", " @section {}_3 Function Table", d.id);
poutprefix("///", " @section {}_4 Function Table", d.id);
poutprefix("///", "");
if (d.functiontable == "")
poutprefix("///", " Please refer to the datasheet.");
else
poutprefix("///", " {}", d.functiontable);
poutprefix("///", "");
poutprefix("///", " @section {}_4 Limitations", d.id);
poutprefix("///", " @section {}_5 Limitations", d.id);
poutprefix("///", "");
poutprefix("///", " {}", d.limitations);
if (!d.example.empty())
{
poutprefix("///", "");
poutprefix("///", " @section {}_5 Example", d.id);
poutprefix("///", " @section {}_6 Example", d.id);
poutprefix("///", " @snippet {1} {2}", d.example[0], d.example[1]);
poutprefix("///", "");
poutprefix("", "");

View File

@ -501,7 +501,6 @@ namespace solver
m_last_V[k] = v;
const nl_fptype hn = cur_ts;
//printf("%g %g %g %g\n", DD_n, hn, t.m_DD_n_m_1, t.m_h_n_m_1);
nl_fptype DD2 = (DD_n / hn - m_DD_n_m_1[k] / m_h_n_m_1[k]) / (hn + m_h_n_m_1[k]);
nl_fptype new_net_timestep(0);

View File

@ -487,6 +487,7 @@ NETLIST_START(dpatrol)
PROM_82S123(d7, GROUND, S1, S2, S3, S4, S5)
PARAM(d7.ROM, "004811.d7")
PARAM(d7.FORCE_TRISTATE_LOGIC, 1)
ALIAS(MAX_SCORE_Q, d7.O6)

View File

@ -54,6 +54,8 @@ NETLIST_START(hazelvid)
/* signal lookup PROM */
PROM_82S126(u71, low, low, u70.QA, u70.QB, u70.QC, u70.QD, u69.QA, u69.QB, u69.QC, low)
PARAM(u71.ROM, "u90_702128_82s129.bin")
// The prom is always enabled and outputs are only connected to logic inputs
PARAM(u71.FORCE_TRISTATE_LOGIC, 1)
/* signal decoding */
TTL_9334(u72, high, u81.Q1Q, u71.O4, u71.O1, u71.O2, u71.O3)
@ -222,6 +224,9 @@ NETLIST_START(hazelvid)
EPROM_2716(u78, low, low, lc20, lc21, lc22, lc23, u66.Q1, u66.Q2, u66.Q3, u66.Q4, u66.Q5, u66.Q6, u56.Q1)
PARAM(u78.ROM, "u83_chr.bin")
// The eprom is always enabled and outputs are only connected to logic inputs
PARAM(u78.FORCE_TRISTATE_LOGIC, 1)
TTL_74166(u77, video_clk, low, ndot, low, u78.O0, u78.O1, u78.O2, u78.O3, u78.O4, u78.O5, u78.O6, low, clr_vid_sr)
ALIAS(raw_dot, u77.QH)

View File

@ -457,6 +457,8 @@ NETLIST_START(stuntcyc)
PROM_82S123(d7, GROUND, S1, S2, S3, S4, S5)
PARAM(d7.ROM, "004811.d7")
// The eprom is always enabled and outputs are only connected to logic inputs
PARAM(d7.FORCE_TRISTATE_LOGIC, 1)
ALIAS(MAX_SCORE_Q, d7.O6)