Moved more device definitions into cpp files. New prefix "nlid" for

include files flags purely internal include files not to be leaked into
userland. (nw)
This commit is contained in:
couriersud 2016-05-29 17:42:47 +02:00
parent b6ad2435b9
commit 99530d0777
18 changed files with 1125 additions and 1117 deletions

View File

@ -136,9 +136,10 @@ project "netlist"
MAME_DIR .. "src/lib/netlist/devices/nld_log.h",
MAME_DIR .. "src/lib/netlist/devices/nld_system.cpp",
MAME_DIR .. "src/lib/netlist/devices/nld_system.h",
MAME_DIR .. "src/lib/netlist/devices/nld_cmos.h",
MAME_DIR .. "src/lib/netlist/devices/nld_truthtable.cpp",
MAME_DIR .. "src/lib/netlist/devices/nld_truthtable.h",
MAME_DIR .. "src/lib/netlist/devices/nlid_cmos.h",
MAME_DIR .. "src/lib/netlist/devices/nlid_system.h",
MAME_DIR .. "src/lib/netlist/macro/nlm_ttl74xx.cpp",
MAME_DIR .. "src/lib/netlist/macro/nlm_ttl74xx.h",
MAME_DIR .. "src/lib/netlist/macro/nlm_cd4xxx.cpp",

View File

@ -85,23 +85,23 @@ void initialize_factory(factory_list_t &factory)
ENTRY(VS, VS, "V")
ENTRY(CS, CS, "I")
ENTRY(OPAMP, OPAMP, "MODEL")
ENTRY(dummy_input, DUMMY_INPUT, "-")
ENTRY(frontier, FRONTIER_DEV, "+I,G,Q") // not intended to be used directly
ENTRY(function, AFUNC, "N,FUNC") // only for macro devices - NO FEEDBACK loops
ENTRYX(dummy_input, DUMMY_INPUT, "-")
ENTRYX(frontier, FRONTIER_DEV, "+I,G,Q") // not intended to be used directly
ENTRYX(function, AFUNC, "N,FUNC") // only for macro devices - NO FEEDBACK loops
ENTRY(QBJT_EB, QBJT_EB, "MODEL")
ENTRY(QBJT_switch, QBJT_SW, "MODEL")
ENTRY(logic_input, TTL_INPUT, "IN")
ENTRY(logic_input, LOGIC_INPUT, "IN,FAMILY")
ENTRY(analog_input, ANALOG_INPUT, "IN")
ENTRYX(logic_input, TTL_INPUT, "IN")
ENTRYX(logic_input, LOGIC_INPUT, "IN,FAMILY")
ENTRYX(analog_input, ANALOG_INPUT, "IN")
ENTRYX(log, LOG, "+I")
ENTRYX(logD, LOGD, "+I,I2")
ENTRY(clock, CLOCK, "FREQ")
ENTRY(extclock, EXTCLOCK, "FREQ")
ENTRY(mainclock, MAINCLOCK, "FREQ")
ENTRY(gnd, GND, "-")
ENTRY(netlistparams, PARAMETER, "-")
ENTRYX(clock, CLOCK, "FREQ")
ENTRYX(extclock, EXTCLOCK, "FREQ")
ENTRYX(mainclock, MAINCLOCK, "FREQ")
ENTRYX(gnd, GND, "-")
ENTRYX(netlistparams, PARAMETER, "-")
ENTRY(solver, SOLVER, "FREQ")
ENTRY(res_sw, RES_SWITCH, "+IN,P1,P2")
ENTRYX(res_sw, RES_SWITCH, "+IN,P1,P2")
ENTRY(switch1, SWITCH, "-")
ENTRY(switch2, SWITCH2, "-")
ENTRYX(nicRSFF, NETDEV_RSFF, "+S,R")
@ -130,8 +130,8 @@ void initialize_factory(factory_list_t &factory)
/* entries with suffix WI are legacy only */
ENTRYX(CD4020, CD4020_WI, "+IP,RESET,VDD,VSS")
//ENTRY(4066, CD_4066, "+A,B")
ENTRY(NE555, NE555, "-")
ENTRY(r2r_dac, R2R_DAC, "+VIN,R,N")
ENTRYX(NE555, NE555, "-")
ENTRYX(r2r_dac, R2R_DAC, "+VIN,R,N")
ENTRYX(4538_dip, CD4538_DIP, "-")
ENTRYX(7448_dip, TTL_7448_DIP, "-")
ENTRYX(7450_dip, TTL_7450_DIP, "-")
@ -152,8 +152,8 @@ void initialize_factory(factory_list_t &factory)
ENTRYX(9312_dip, TTL_9312_DIP, "-")
ENTRYX(9316_dip, TTL_9316_DIP, "-")
ENTRYX(SN74LS629_dip, SN74LS629_DIP, "1.CAP1,2.CAP2")
ENTRY(NE555_dip, NE555_DIP, "-")
ENTRY(MM5837_dip, MM5837_DIP, "-")
ENTRYX(NE555_dip, NE555_DIP, "-")
ENTRYX(MM5837_dip, MM5837_DIP, "-")
}
} //namespace devices

View File

@ -5,8 +5,8 @@
*
*/
#include <devices/nlid_cmos.h>
#include "nld_4020.h"
#include "nld_cmos.h"
namespace netlist
{

View File

@ -5,8 +5,8 @@
*
*/
#include <devices/nlid_cmos.h>
#include "nld_4066.h"
#include "nld_cmos.h"
namespace netlist
{

View File

@ -7,7 +7,7 @@
#include "nld_74123.h"
#include "nld_system.h"
#include "nlid_system.h"
#include "analog/nld_twoterm.h"
#define R_OFF (1E20)

View File

@ -1,41 +0,0 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
* nld_cmos.h
*
*/
#ifndef NLD_CMOS_H_
#define NLD_CMOS_H_
#include "nl_base.h"
#include "analog/nld_twoterm.h"
namespace netlist
{
namespace devices
{
NETLIB_OBJECT(vdd_vss)
{
NETLIB_CONSTRUCTOR(vdd_vss)
{
enregister("VDD", m_vdd);
enregister("VSS", m_vss);
}
NETLIB_UPDATEI() {};
NETLIB_RESETI() {};
public:
ATTR_HOT inline nl_double vdd() { return INPANALOG(m_vdd); }
ATTR_HOT inline nl_double vss() { return INPANALOG(m_vss); }
analog_input_t m_vdd;
analog_input_t m_vss;
};
} //namespace devices
} // namespace netlist
#endif /* NLD_CMOS_H_ */

View File

@ -5,58 +5,110 @@
*
*/
#include <solver/nld_matrix_solver.h>
#include "nld_mm5837.h"
#include "nl_setup.h"
#include <solver/nld_matrix_solver.h>
#include "analog/nld_twoterm.h"
#define R_LOW (1000)
#define R_HIGH (1000)
#define R_LOW (1000.0)
#define R_HIGH (1000.0)
namespace netlist
{
namespace devices
{
NETLIB_RESET(MM5837_dip)
{
//m_V0.initial(0.0);
//m_RV.do_reset();
m_RV.set(NL_FCONST(1.0) / R_LOW, 0.0, 0.0);
m_shift = 0x1ffff;
m_is_timestep = m_RV.m_P.net().solver()->is_timestep();
}
NETLIB_UPDATE(MM5837_dip)
{
OUTLOGIC(m_Q, !m_Q.net().as_logic().new_Q(), m_inc );
/* shift register
*
* 17 bits, bits 17 & 14 feed back to input
*
*/
const UINT32 last_state = m_shift & 0x01;
/* shift */
m_shift = (m_shift >> 1) | (((m_shift & 0x01) ^ ((m_shift >> 3) & 0x01)) << 16);
const UINT32 state = m_shift & 0x01;
if (state != last_state)
NETLIB_OBJECT(MM5837_dip)
{
const nl_double R = state ? R_HIGH : R_LOW;
const nl_double V = state ? INPANALOG(m_VDD) : INPANALOG(m_VSS);
NETLIB_CONSTRUCTOR(MM5837_dip)
, m_RV(*this, "RV")
, m_is_timestep(false)
{
/* clock */
enregister("Q", m_Q);
enregister("FB", m_feedback);
m_inc = netlist_time::from_hz(56000);
connect_late(m_feedback, m_Q);
// We only need to update the net first if this is a time stepping net
if (m_is_timestep)
m_RV.update_dev();
m_RV.set(NL_FCONST(1.0) / R, V, 0.0);
m_RV.m_P.schedule_after(NLTIME_FROM_NS(1));
/* output */
enregister("_RV1", m_RV.m_P);
enregister("_RV2", m_RV.m_N);
enregister("_Q", m_V0);
connect_late(m_RV.m_N, m_V0);
/* device */
enregister("1", m_VDD);
enregister("2", m_VGG);
register_subalias("3", m_RV.m_P);
enregister("4", m_VSS);
save(NLNAME(m_shift));
}
NETLIB_RESETI();
NETLIB_UPDATEI();
protected:
NETLIB_SUB(twoterm) m_RV;
analog_input_t m_VDD;
analog_input_t m_VGG;
analog_input_t m_VSS;
/* output stage */
analog_output_t m_V0; /* could be gnd as well */
/* clock stage */
logic_input_t m_feedback;
logic_output_t m_Q;
netlist_time m_inc;
/* state */
UINT32 m_shift;
/* cache */
bool m_is_timestep;
};
NETLIB_RESET(MM5837_dip)
{
//m_V0.initial(0.0);
//m_RV.do_reset();
m_RV.set(NL_FCONST(1.0) / R_LOW, 0.0, 0.0);
m_shift = 0x1ffff;
m_is_timestep = m_RV.m_P.net().solver()->is_timestep();
}
}
NETLIB_UPDATE(MM5837_dip)
{
OUTLOGIC(m_Q, !m_Q.net().as_logic().new_Q(), m_inc );
/* shift register
*
* 17 bits, bits 17 & 14 feed back to input
*
*/
const UINT32 last_state = m_shift & 0x01;
/* shift */
m_shift = (m_shift >> 1) | (((m_shift & 0x01) ^ ((m_shift >> 3) & 0x01)) << 16);
const UINT32 state = m_shift & 0x01;
if (state != last_state)
{
const nl_double R = state ? R_HIGH : R_LOW;
const nl_double V = state ? INPANALOG(m_VDD) : INPANALOG(m_VSS);
// We only need to update the net first if this is a time stepping net
if (m_is_timestep)
m_RV.update_dev();
m_RV.set(NL_FCONST(1.0) / R, V, 0.0);
m_RV.m_P.schedule_after(NLTIME_FROM_NS(1));
}
}
NETLIB_DEVICE_IMPL(MM5837_dip)
} //namespace devices
} // namespace netlist

View File

@ -19,69 +19,9 @@
#ifndef NLD_MM5837_H_
#define NLD_MM5837_H_
#include "nl_base.h"
#include "analog/nld_twoterm.h"
#include "nl_setup.h"
#define MM5837_DIP(name) \
NET_REGISTER_DEV(MM5837_DIP, name)
namespace netlist
{
namespace devices
{
NETLIB_OBJECT(MM5837_dip)
{
NETLIB_CONSTRUCTOR(MM5837_dip)
,m_RV(*this, "RV")
{
/* clock */
enregister("Q", m_Q);
enregister("FB", m_feedback);
m_inc = netlist_time::from_hz(56000);
connect_late(m_feedback, m_Q);
/* output */
enregister("_RV1", m_RV.m_P);
enregister("_RV2", m_RV.m_N);
enregister("_Q", m_V0);
connect_late(m_RV.m_N, m_V0);
/* device */
enregister("1", m_VDD);
enregister("2", m_VGG);
register_subalias("3", m_RV.m_P);
enregister("4", m_VSS);
save(NLNAME(m_shift));
}
NETLIB_RESETI();
NETLIB_UPDATEI();
protected:
NETLIB_SUB(twoterm) m_RV;
analog_input_t m_VDD;
analog_input_t m_VGG;
analog_input_t m_VSS;
/* output stage */
analog_output_t m_V0; /* could be gnd as well */
/* clock stage */
logic_input_t m_feedback;
logic_output_t m_Q;
netlist_time m_inc;
/* state */
UINT32 m_shift;
/* cache */
bool m_is_timestep;
};
} //namespace devices
} // namespace netlist
#endif /* NLD_MM5837_H_ */

View File

@ -5,9 +5,9 @@
*
*/
#include <solver/nld_solver.h>
#include "nld_ne555.h"
#include "nl_setup.h"
#include "analog/nld_twoterm.h"
#include <solver/nld_solver.h>
#define R_OFF (1E20)
#define R_ON (25) // Datasheet states a maximum discharge of 200mA, R = 5V / 0.2
@ -17,68 +17,135 @@ namespace netlist
namespace devices
{
inline nl_double NETLIB_NAME(NE555)::clamp(const nl_double v, const nl_double a, const nl_double b)
{
nl_double ret = v;
nl_double vcc = TERMANALOG(m_R1.m_P);
if (ret > vcc - a)
ret = vcc - a;
if (ret < b)
ret = b;
return ret;
}
NETLIB_RESET(NE555)
{
m_R1.do_reset();
m_R2.do_reset();
m_R3.do_reset();
m_RDIS.do_reset();
m_R1.set_R(5000);
m_R2.set_R(5000);
m_R3.set_R(5000);
m_RDIS.set_R(R_OFF);
m_last_out = true;
}
NETLIB_UPDATE(NE555)
{
// FIXME: assumes GND is connected to 0V.
nl_double vt = clamp(TERMANALOG(m_R2.m_P), 0.7, 1.4);
bool bthresh = (INPANALOG(m_THRES) > vt);
bool btrig = (INPANALOG(m_TRIG) > clamp(TERMANALOG(m_R2.m_N), 0.7, 1.4));
if (!btrig)
NETLIB_OBJECT(NE555)
{
m_ff = true;
}
else if (bthresh)
NETLIB_CONSTRUCTOR(NE555)
, m_R1(*this, "R1")
, m_R2(*this, "R2")
, m_R3(*this, "R3")
, m_RDIS(*this, "RDIS")
, m_last_out(false)
, m_ff(false)
{
register_subalias("GND", m_R3.m_N); // Pin 1
enregister("TRIG", m_TRIG); // Pin 2
enregister("OUT", m_OUT); // Pin 3
enregister("RESET", m_RESET); // Pin 4
register_subalias("CONT", m_R1.m_N); // Pin 5
enregister("THRESH", m_THRES); // Pin 6
register_subalias("DISCH", m_RDIS.m_P); // Pin 7
register_subalias("VCC", m_R1.m_P); // Pin 8
connect_late(m_R1.m_N, m_R2.m_P);
connect_late(m_R2.m_N, m_R3.m_P);
connect_late(m_RDIS.m_N, m_R3.m_N);
save(NLNAME(m_last_out));
save(NLNAME(m_ff));
}
NETLIB_UPDATEI();
NETLIB_RESETI();
protected:
NETLIB_SUB(R) m_R1;
NETLIB_SUB(R) m_R2;
NETLIB_SUB(R) m_R3;
NETLIB_SUB(R) m_RDIS;
logic_input_t m_RESET;
analog_input_t m_THRES;
analog_input_t m_TRIG;
analog_output_t m_OUT;
private:
bool m_last_out;
bool m_ff;
inline nl_double clamp(const nl_double v, const nl_double a, const nl_double b);
};
NETLIB_OBJECT_DERIVED(NE555_dip, NE555)
{
m_ff = false;
NETLIB_CONSTRUCTOR_DERIVED(NE555_dip, NE555)
{
register_subalias("1", m_R3.m_N); // Pin 1
register_subalias("2", m_TRIG); // Pin 2
register_subalias("3", m_OUT); // Pin 3
register_subalias("4", m_RESET); // Pin 4
register_subalias("5", m_R1.m_N); // Pin 5
register_subalias("6", m_THRES); // Pin 6
register_subalias("7", m_RDIS.m_P); // Pin 7
register_subalias("8", m_R1.m_P); // Pin 8
}
};
inline nl_double NETLIB_NAME(NE555)::clamp(const nl_double v, const nl_double a, const nl_double b)
{
nl_double ret = v;
nl_double vcc = TERMANALOG(m_R1.m_P);
if (ret > vcc - a)
ret = vcc - a;
if (ret < b)
ret = b;
return ret;
}
bool out = (!INPLOGIC(m_RESET) ? false : m_ff);
NETLIB_RESET(NE555)
{
m_R1.do_reset();
m_R2.do_reset();
m_R3.do_reset();
m_RDIS.do_reset();
if (m_last_out && !out)
{
m_RDIS.update_dev();
OUTANALOG(m_OUT, TERMANALOG(m_R3.m_N));
m_RDIS.set_R(R_ON);
}
else if (!m_last_out && out)
{
m_RDIS.update_dev();
// FIXME: Should be delayed by 100ns
OUTANALOG(m_OUT, TERMANALOG(m_R1.m_P));
m_R1.set_R(5000);
m_R2.set_R(5000);
m_R3.set_R(5000);
m_RDIS.set_R(R_OFF);
}
m_last_out = out;
}
m_last_out = true;
}
NETLIB_UPDATE(NE555)
{
// FIXME: assumes GND is connected to 0V.
nl_double vt = clamp(TERMANALOG(m_R2.m_P), 0.7, 1.4);
bool bthresh = (INPANALOG(m_THRES) > vt);
bool btrig = (INPANALOG(m_TRIG) > clamp(TERMANALOG(m_R2.m_N), 0.7, 1.4));
if (!btrig)
{
m_ff = true;
}
else if (bthresh)
{
m_ff = false;
}
bool out = (!INPLOGIC(m_RESET) ? false : m_ff);
if (m_last_out && !out)
{
m_RDIS.update_dev();
OUTANALOG(m_OUT, TERMANALOG(m_R3.m_N));
m_RDIS.set_R(R_ON);
}
else if (!m_last_out && out)
{
m_RDIS.update_dev();
// FIXME: Should be delayed by 100ns
OUTANALOG(m_OUT, TERMANALOG(m_R1.m_P));
m_RDIS.set_R(R_OFF);
}
m_last_out = out;
}
NETLIB_DEVICE_IMPL(NE555)
NETLIB_DEVICE_IMPL(NE555_dip)
} //namespace devices
} // namespace netlist

View File

@ -19,86 +19,12 @@
#ifndef NLD_NE555_H_
#define NLD_NE555_H_
#include "nl_base.h"
#include "analog/nld_twoterm.h"
#include "nl_setup.h"
#define NE555(name) \
#define NE555(name) \
NET_REGISTER_DEV(NE555, name)
namespace netlist
{
namespace devices
{
NETLIB_OBJECT(NE555)
{
NETLIB_CONSTRUCTOR(NE555)
, m_R1(*this, "R1")
, m_R2(*this, "R2")
, m_R3(*this, "R3")
, m_RDIS(*this, "RDIS")
, m_last_out(false)
, m_ff(false)
{
register_subalias("GND", m_R3.m_N); // Pin 1
enregister("TRIG", m_TRIG); // Pin 2
enregister("OUT", m_OUT); // Pin 3
enregister("RESET", m_RESET); // Pin 4
register_subalias("CONT", m_R1.m_N); // Pin 5
enregister("THRESH", m_THRES); // Pin 6
register_subalias("DISCH", m_RDIS.m_P); // Pin 7
register_subalias("VCC", m_R1.m_P); // Pin 8
connect_late(m_R1.m_N, m_R2.m_P);
connect_late(m_R2.m_N, m_R3.m_P);
connect_late(m_RDIS.m_N, m_R3.m_N);
save(NLNAME(m_last_out));
save(NLNAME(m_ff));
}
NETLIB_UPDATEI();
NETLIB_RESETI();
protected:
NETLIB_SUB(R) m_R1;
NETLIB_SUB(R) m_R2;
NETLIB_SUB(R) m_R3;
NETLIB_SUB(R) m_RDIS;
logic_input_t m_RESET;
analog_input_t m_THRES;
analog_input_t m_TRIG;
analog_output_t m_OUT;
private:
bool m_last_out;
bool m_ff;
inline nl_double clamp(const nl_double v, const nl_double a, const nl_double b);
};
#define NE555_DIP(name) \
NET_REGISTER_DEV(NE555_DIP, name)
NETLIB_OBJECT_DERIVED(NE555_dip, NE555)
{
NETLIB_CONSTRUCTOR_DERIVED(NE555_dip, NE555)
{
register_subalias("1", m_R3.m_N); // Pin 1
register_subalias("2", m_TRIG); // Pin 2
register_subalias("3", m_OUT); // Pin 3
register_subalias("4", m_RESET); // Pin 4
register_subalias("5", m_R1.m_N); // Pin 5
register_subalias("6", m_THRES); // Pin 6
register_subalias("7", m_RDIS.m_P); // Pin 7
register_subalias("8", m_R1.m_P); // Pin 8
}
};
} //namespace devices
} // namespace netlist
#endif /* NLD_NE555_H_ */

View File

@ -6,20 +6,47 @@
*/
#include "nld_r2r_dac.h"
#include "analog/nld_twoterm.h"
namespace netlist
{
namespace devices
{
NETLIB_UPDATE_PARAM(r2r_dac)
{
update_dev();
NETLIB_OBJECT_DERIVED(r2r_dac, twoterm)
{
NETLIB_CONSTRUCTOR_DERIVED(r2r_dac, twoterm)
, m_VIN(*this, "VIN", 1.0)
, m_R(*this, "R", 1.0)
, m_num(*this, "N", 1)
, m_val(*this, "VAL", 1)
{
enregister("VOUT", m_P);
enregister("VGND", m_N);
}
nl_double V = m_VIN.Value() / (nl_double) (1 << m_num.Value()) * (nl_double) m_val.Value();
NETLIB_UPDATE_PARAMI();
//NETLIB_RESETI();
//NETLIB_UPDATEI();
this->set(1.0 / m_R.Value(), V, 0.0);
}
protected:
param_double_t m_VIN;
param_double_t m_R;
param_int_t m_num;
param_int_t m_val;
};
NETLIB_UPDATE_PARAM(r2r_dac)
{
update_dev();
nl_double V = m_VIN.Value() / (nl_double) (1 << m_num.Value()) * (nl_double) m_val.Value();
this->set(1.0 / m_R.Value(), V, 0.0);
}
NETLIB_DEVICE_IMPL(r2r_dac)
} //namespace devices
} // namespace netlist

View File

@ -46,45 +46,12 @@
#ifndef NLD_R2R_DAC_H_
#define NLD_R2R_DAC_H_
#include "nl_base.h"
#include "analog/nld_twoterm.h"
#include "nl_setup.h"
#define R2R_DAC(name, p_VIN, p_R, p_N) \
NET_REGISTER_DEV(R2R_DAC, name) \
NETDEV_PARAMI(name, VIN, p_VIN) \
NETDEV_PARAMI(name, R, p_R) \
#define R2R_DAC(name, p_VIN, p_R, p_N) \
NET_REGISTER_DEV(R2R_DAC, name) \
NETDEV_PARAMI(name, VIN, p_VIN) \
NETDEV_PARAMI(name, R, p_R) \
NETDEV_PARAMI(name, N, p_N)
namespace netlist
{
namespace devices
{
NETLIB_OBJECT_DERIVED(r2r_dac, twoterm)
{
NETLIB_CONSTRUCTOR_DERIVED(r2r_dac, twoterm)
, m_VIN(*this, "VIN", 1.0)
, m_R(*this, "R", 1.0)
, m_num(*this, "N", 1)
, m_val(*this, "VAL", 1)
{
enregister("VOUT", m_P);
enregister("VGND", m_N);
}
NETLIB_UPDATE_PARAMI();
//NETLIB_RESETI();
//NETLIB_UPDATEI();
protected:
param_double_t m_VIN;
param_double_t m_R;
param_int_t m_num;
param_int_t m_val;
};
} //namespace devices
} // namespace netlist
#endif /* NLD_R2R_DAC_H_ */

View File

@ -7,211 +7,223 @@
#include <solver/nld_solver.h>
#include <solver/nld_matrix_solver.h>
#include "nld_system.h"
#include "nlid_system.h"
namespace netlist
{
namespace devices
{
// ----------------------------------------------------------------------------------------
// netlistparams
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// netlistparams
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// clock
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// clock
// ----------------------------------------------------------------------------------------
NETLIB_UPDATE_PARAM(clock)
{
m_inc = netlist_time::from_hz(m_freq.Value()*2);
}
NETLIB_UPDATE(clock)
{
OUTLOGIC(m_Q, !m_Q.net().as_logic().new_Q(), m_inc );
}
// ----------------------------------------------------------------------------------------
// extclock
// ----------------------------------------------------------------------------------------
NETLIB_RESET(extclock)
{
m_cnt = 0;
m_off = netlist_time::from_double(m_offset.Value());
//m_Q.initial(0);
}
NETLIB_UPDATE(extclock)
{
#if 0
if (m_off == netlist_time::zero)
NETLIB_UPDATE_PARAM(clock)
{
OUTLOGIC(m_Q, (m_cnt & 1) ^ 1, m_inc[m_cnt]);
m_cnt = (m_cnt + 1) % m_size;
m_inc = netlist_time::from_hz(m_freq.Value()*2);
}
else
NETLIB_UPDATE(clock)
{
OUTLOGIC(m_Q, (m_cnt & 1) ^ 1, m_inc[0] + m_off);
m_cnt = 1;
m_off = netlist_time::zero;
OUTLOGIC(m_Q, !m_Q.net().as_logic().new_Q(), m_inc );
}
#else
OUTLOGIC(m_Q, (m_cnt & 1) ^ 1, m_inc[m_cnt] + m_off);
m_cnt = (m_cnt + 1) % m_size;
m_off = netlist_time::zero;
#endif
}
// ----------------------------------------------------------------------------------------
// logic_input
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// extclock
// ----------------------------------------------------------------------------------------
NETLIB_RESET(logic_input)
{
//FIXME: causes issues in breakout (lots of pings after first player 1 start)
//m_Q.initial(m_IN.Value() & 1);
}
NETLIB_UPDATE(logic_input)
{
OUTLOGIC(m_Q, m_IN.Value() & 1, netlist_time::from_nsec(1));
}
NETLIB_UPDATE_PARAM(logic_input)
{
}
// ----------------------------------------------------------------------------------------
// analog_input
// ----------------------------------------------------------------------------------------
NETLIB_RESET(analog_input)
{
// m_Q.initial(m_IN.Value() * 0.999);
}
NETLIB_UPDATE(analog_input)
{
OUTANALOG(m_Q, m_IN.Value());
}
NETLIB_UPDATE_PARAM(analog_input)
{
}
// ----------------------------------------------------------------------------------------
// nld_d_to_a_proxy
// ----------------------------------------------------------------------------------------
void nld_d_to_a_proxy::reset()
{
//m_Q.initial(0.0);
m_last_state = -1;
m_RV.do_reset();
m_is_timestep = m_RV.m_P.net().solver()->has_timestep_devices();
m_RV.set(NL_FCONST(1.0) / logic_family().m_R_low, logic_family().m_low_V, 0.0);
}
NETLIB_UPDATE(d_to_a_proxy)
{
const int state = INPLOGIC(m_I);
if (state != m_last_state)
NETLIB_RESET(extclock)
{
m_last_state = state;
const nl_double R = state ? logic_family().m_R_high : logic_family().m_R_low;
const nl_double V = state ? logic_family().m_high_V : logic_family().m_low_V;
m_cnt = 0;
m_off = netlist_time::from_double(m_offset.Value());
//m_Q.initial(0);
}
// We only need to update the net first if this is a time stepping net
if (m_is_timestep)
NETLIB_UPDATE(extclock)
{
#if 0
if (m_off == netlist_time::zero)
{
m_RV.update_dev();
}
m_RV.set(NL_FCONST(1.0) / R, V, 0.0);
m_RV.m_P.schedule_after(NLTIME_FROM_NS(1));
}
}
// -----------------------------------------------------------------------------
// nld_res_sw
// -----------------------------------------------------------------------------
NETLIB_UPDATE(res_sw)
{
const int state = INPLOGIC(m_I);
if (state != m_last_state)
{
m_last_state = state;
const nl_double R = state ? m_RON.Value() : m_ROFF.Value();
// We only need to update the net first if this is a time stepping net
if (0) // m_R->m_P.net().as_analog().solver()->is_timestep())
{
m_R.update_dev();
m_R.set_R(R);
m_R.m_P.schedule_after(NLTIME_FROM_NS(1));
OUTLOGIC(m_Q, (m_cnt & 1) ^ 1, m_inc[m_cnt]);
m_cnt = (m_cnt + 1) % m_size;
}
else
{
m_R.set_R(R);
m_R.m_P.schedule_after(NLTIME_FROM_NS(1));
//m_R->update_dev();
OUTLOGIC(m_Q, (m_cnt & 1) ^ 1, m_inc[0] + m_off);
m_cnt = 1;
m_off = netlist_time::zero;
}
#else
OUTLOGIC(m_Q, (m_cnt & 1) ^ 1, m_inc[m_cnt] + m_off);
m_cnt = (m_cnt + 1) % m_size;
m_off = netlist_time::zero;
#endif
}
}
/* -----------------------------------------------------------------------------
* nld_function
* ----------------------------------------------------------------------------- */
// ----------------------------------------------------------------------------------------
// logic_input
// ----------------------------------------------------------------------------------------
NETLIB_RESET(function)
{
//m_Q.initial(0.0);
}
NETLIB_UPDATE(function)
{
//nl_double val = INPANALOG(m_I[0]) * INPANALOG(m_I[1]) * 0.2;
//OUTANALOG(m_Q, val);
nl_double stack[20];
unsigned ptr = 0;
unsigned e = m_precompiled.size();
for (unsigned i = 0; i<e; i++)
NETLIB_RESET(logic_input)
{
rpn_inst &rc = m_precompiled[i];
switch (rc.m_cmd)
//FIXME: causes issues in breakout (lots of pings after first player 1 start)
//m_Q.initial(m_IN.Value() & 1);
}
NETLIB_UPDATE(logic_input)
{
OUTLOGIC(m_Q, m_IN.Value() & 1, netlist_time::from_nsec(1));
}
NETLIB_UPDATE_PARAM(logic_input)
{
}
// ----------------------------------------------------------------------------------------
// analog_input
// ----------------------------------------------------------------------------------------
NETLIB_RESET(analog_input)
{
// m_Q.initial(m_IN.Value() * 0.999);
}
NETLIB_UPDATE(analog_input)
{
OUTANALOG(m_Q, m_IN.Value());
}
NETLIB_UPDATE_PARAM(analog_input)
{
}
// ----------------------------------------------------------------------------------------
// nld_d_to_a_proxy
// ----------------------------------------------------------------------------------------
void nld_d_to_a_proxy::reset()
{
//m_Q.initial(0.0);
m_last_state = -1;
m_RV.do_reset();
m_is_timestep = m_RV.m_P.net().solver()->has_timestep_devices();
m_RV.set(NL_FCONST(1.0) / logic_family().m_R_low, logic_family().m_low_V, 0.0);
}
NETLIB_UPDATE(d_to_a_proxy)
{
const int state = INPLOGIC(m_I);
if (state != m_last_state)
{
case ADD:
ptr--;
stack[ptr-1] = stack[ptr] + stack[ptr-1];
break;
case MULT:
ptr--;
stack[ptr-1] = stack[ptr] * stack[ptr-1];
break;
case SUB:
ptr--;
stack[ptr-1] = stack[ptr-1] - stack[ptr];
break;
case DIV:
ptr--;
stack[ptr-1] = stack[ptr-1] / stack[ptr];
break;
case PUSH_INPUT:
stack[ptr++] = INPANALOG(m_I[(int) rc.m_param]);
break;
case PUSH_CONST:
stack[ptr++] = rc.m_param;
break;
m_last_state = state;
const nl_double R = state ? logic_family().m_R_high : logic_family().m_R_low;
const nl_double V = state ? logic_family().m_high_V : logic_family().m_low_V;
// We only need to update the net first if this is a time stepping net
if (m_is_timestep)
{
m_RV.update_dev();
}
m_RV.set(NL_FCONST(1.0) / R, V, 0.0);
m_RV.m_P.schedule_after(NLTIME_FROM_NS(1));
}
}
OUTANALOG(m_Q, stack[ptr-1]);
}
// -----------------------------------------------------------------------------
// nld_res_sw
// -----------------------------------------------------------------------------
NETLIB_UPDATE(res_sw)
{
const int state = INPLOGIC(m_I);
if (state != m_last_state)
{
m_last_state = state;
const nl_double R = state ? m_RON.Value() : m_ROFF.Value();
// We only need to update the net first if this is a time stepping net
if (0) // m_R->m_P.net().as_analog().solver()->is_timestep())
{
m_R.update_dev();
m_R.set_R(R);
m_R.m_P.schedule_after(NLTIME_FROM_NS(1));
}
else
{
m_R.set_R(R);
m_R.m_P.schedule_after(NLTIME_FROM_NS(1));
//m_R->update_dev();
}
}
}
/* -----------------------------------------------------------------------------
* nld_function
* ----------------------------------------------------------------------------- */
NETLIB_RESET(function)
{
//m_Q.initial(0.0);
}
NETLIB_UPDATE(function)
{
//nl_double val = INPANALOG(m_I[0]) * INPANALOG(m_I[1]) * 0.2;
//OUTANALOG(m_Q, val);
nl_double stack[20];
unsigned ptr = 0;
unsigned e = m_precompiled.size();
for (unsigned i = 0; i<e; i++)
{
rpn_inst &rc = m_precompiled[i];
switch (rc.m_cmd)
{
case ADD:
ptr--;
stack[ptr-1] = stack[ptr] + stack[ptr-1];
break;
case MULT:
ptr--;
stack[ptr-1] = stack[ptr] * stack[ptr-1];
break;
case SUB:
ptr--;
stack[ptr-1] = stack[ptr-1] - stack[ptr];
break;
case DIV:
ptr--;
stack[ptr-1] = stack[ptr-1] / stack[ptr];
break;
case PUSH_INPUT:
stack[ptr++] = INPANALOG(m_I[(int) rc.m_param]);
break;
case PUSH_CONST:
stack[ptr++] = rc.m_param;
break;
}
}
OUTANALOG(m_Q, stack[ptr-1]);
}
NETLIB_DEVICE_IMPL(dummy_input)
NETLIB_DEVICE_IMPL(frontier)
NETLIB_DEVICE_IMPL(function)
NETLIB_DEVICE_IMPL(logic_input)
NETLIB_DEVICE_IMPL(analog_input)
NETLIB_DEVICE_IMPL(clock)
NETLIB_DEVICE_IMPL(extclock)
NETLIB_DEVICE_IMPL(res_sw)
NETLIB_DEVICE_IMPL(mainclock)
NETLIB_DEVICE_IMPL(gnd)
NETLIB_DEVICE_IMPL(netlistparams)
} //namespace devices
} // namespace netlist

View File

@ -10,641 +10,66 @@
#define NLD_SYSTEM_H_
#include "nl_setup.h"
#include "nl_base.h"
#include "nl_factory.h"
#include "analog/nld_twoterm.h"
// -----------------------------------------------------------------------------
// Macros
// -----------------------------------------------------------------------------
#define TTL_INPUT(name, v) \
NET_REGISTER_DEV(TTL_INPUT, name) \
#define TTL_INPUT(name, v) \
NET_REGISTER_DEV(TTL_INPUT, name) \
PARAM(name.IN, v)
#define LOGIC_INPUT(name, v, family) \
NET_REGISTER_DEV(LOGIC_INPUT, name) \
PARAM(name.IN, v) \
#define LOGIC_INPUT(name, v, family) \
NET_REGISTER_DEV(LOGIC_INPUT, name) \
PARAM(name.IN, v) \
PARAM(name.FAMILY, family)
#define ANALOG_INPUT(name, v) \
NET_REGISTER_DEV(ANALOG_INPUT, name) \
#define ANALOG_INPUT(name, v) \
NET_REGISTER_DEV(ANALOG_INPUT, name) \
PARAM(name.IN, v)
#define MAINCLOCK(name, freq) \
NET_REGISTER_DEV(MAINCLOCK, name) \
#define MAINCLOCK(name, freq) \
NET_REGISTER_DEV(MAINCLOCK, name) \
PARAM(name.FREQ, freq)
#define CLOCK(name, freq) \
NET_REGISTER_DEV(CLOCK, name) \
#define CLOCK(name, freq) \
NET_REGISTER_DEV(CLOCK, name) \
PARAM(name.FREQ, freq)
#define EXTCLOCK(name, freq, pattern) \
NET_REGISTER_DEV(EXTCLOCK, name) \
PARAM(name.FREQ, freq) \
#define EXTCLOCK(name, freq, pattern) \
NET_REGISTER_DEV(EXTCLOCK, name) \
PARAM(name.FREQ, freq) \
PARAM(name.PATTERN, pattern)
#define GNDA() \
#define GNDA() \
NET_REGISTER_DEV(GNDA, GND)
#define DUMMY_INPUT(name) \
#define DUMMY_INPUT(name) \
NET_REGISTER_DEV(DUMMY_INPUT, name)
//FIXME: Usage discouraged, use OPTIMIZE_FRONTIER instead
#define FRONTIER_DEV(name, cIN, cG, cOUT) \
NET_REGISTER_DEV(FRONTIER_DEV, name) \
NET_C(cIN, name.I) \
NET_C(cG, name.G) \
#define FRONTIER_DEV(name, cIN, cG, cOUT) \
NET_REGISTER_DEV(FRONTIER_DEV, name) \
NET_C(cIN, name.I) \
NET_C(cG, name.G) \
NET_C(cOUT, name.Q)
#define OPTIMIZE_FRONTIER(attach, r_in, r_out) \
#define OPTIMIZE_FRONTIER(attach, r_in, r_out) \
setup.register_frontier(# attach, r_in, r_out);
#define RES_SWITCH(name, cIN, cP1, cP2) \
NET_REGISTER_DEV(RES_SWITCH, name) \
NET_C(cIN, name.I) \
NET_C(cP1, name.1) \
#define RES_SWITCH(name, cIN, cP1, cP2) \
NET_REGISTER_DEV(RES_SWITCH, name) \
NET_C(cIN, name.I) \
NET_C(cP1, name.1) \
NET_C(cP2, name.2)
/* Default device to hold netlist parameters */
#define PARAMETERS(name) \
#define PARAMETERS(name) \
NET_REGISTER_DEV(PARAMETERS, name)
#define AFUNC(name, p_N, p_F) \
NET_REGISTER_DEV(AFUNC, name) \
PARAM(name.N, p_N) \
NET_REGISTER_DEV(AFUNC, name) \
PARAM(name.N, p_N) \
PARAM(name.FUNC, p_F)
namespace netlist
{
namespace devices
{
// -----------------------------------------------------------------------------
// netlistparams
// -----------------------------------------------------------------------------
NETLIB_OBJECT(netlistparams)
{
NETLIB_CONSTRUCTOR(netlistparams)
, m_use_deactivate(*this, "USE_DEACTIVATE", 0)
{
}
NETLIB_UPDATEI() { }
//NETLIB_RESETI() { }
//NETLIB_UPDATE_PARAMI() { }
public:
param_logic_t m_use_deactivate;
};
// -----------------------------------------------------------------------------
// mainclock
// -----------------------------------------------------------------------------
NETLIB_OBJECT(mainclock)
{
NETLIB_CONSTRUCTOR(mainclock)
, m_freq(*this, "FREQ", 7159000.0 * 5)
{
enregister("Q", m_Q);
m_inc = netlist_time::from_hz(m_freq.Value()*2);
}
NETLIB_RESETI()
{
m_Q.net().set_time(netlist_time::zero);
}
NETLIB_UPDATE_PARAMI()
{
m_inc = netlist_time::from_hz(m_freq.Value()*2);
}
NETLIB_UPDATEI()
{
logic_net_t &net = m_Q.net().as_logic();
// this is only called during setup ...
net.toggle_new_Q();
net.set_time(netlist().time() + m_inc);
}
public:
logic_output_t m_Q;
param_double_t m_freq;
netlist_time m_inc;
ATTR_HOT inline static void mc_update(logic_net_t &net);
};
// -----------------------------------------------------------------------------
// clock
// -----------------------------------------------------------------------------
NETLIB_OBJECT(clock)
{
NETLIB_CONSTRUCTOR(clock)
, m_freq(*this, "FREQ", 7159000.0 * 5.0)
{
enregister("Q", m_Q);
enregister("FB", m_feedback);
m_inc = netlist_time::from_hz(m_freq.Value()*2);
connect_late(m_feedback, m_Q);
}
NETLIB_UPDATEI();
//NETLIB_RESETI();
NETLIB_UPDATE_PARAMI();
protected:
logic_input_t m_feedback;
logic_output_t m_Q;
param_double_t m_freq;
netlist_time m_inc;
};
// -----------------------------------------------------------------------------
// extclock
// -----------------------------------------------------------------------------
NETLIB_OBJECT(extclock)
{
NETLIB_CONSTRUCTOR(extclock)
, m_freq(*this, "FREQ", 7159000.0 * 5.0)
, m_pattern(*this, "PATTERN", "1,1")
, m_offset(*this, "OFFSET", 0.0)
{
enregister("Q", m_Q);
enregister("FB", m_feedback);
m_inc[0] = netlist_time::from_hz(m_freq.Value()*2);
connect_late(m_feedback, m_Q);
{
netlist_time base = netlist_time::from_hz(m_freq.Value()*2);
plib::pstring_vector_t pat(m_pattern.Value(),",");
m_off = netlist_time::from_double(m_offset.Value());
int pati[256];
m_size = pat.size();
int total = 0;
for (int i=0; i<m_size; i++)
{
pati[i] = pat[i].as_long();
total += pati[i];
}
netlist_time ttotal = netlist_time::zero;
for (int i=0; i<m_size - 1; i++)
{
m_inc[i] = base * pati[i];
ttotal += m_inc[i];
}
m_inc[m_size - 1] = base * total - ttotal;
}
save(NLNAME(m_cnt));
save(NLNAME(m_off));
}
NETLIB_UPDATEI();
NETLIB_RESETI();
//NETLIB_UPDATE_PARAMI();
protected:
param_double_t m_freq;
param_str_t m_pattern;
param_double_t m_offset;
logic_input_t m_feedback;
logic_output_t m_Q;
UINT32 m_cnt;
UINT32 m_size;
netlist_time m_inc[32];
netlist_time m_off;
};
// -----------------------------------------------------------------------------
// Special support devices ...
// -----------------------------------------------------------------------------
NETLIB_OBJECT(logic_input)
{
NETLIB_CONSTRUCTOR(logic_input)
, m_IN(*this, "IN", 0)
/* make sure we get the family first */
, m_FAMILY(*this, "FAMILY", "FAMILY(TYPE=TTL)")
{
set_logic_family(netlist().setup().family_from_model(m_FAMILY.Value()));
enregister("Q", m_Q);
}
NETLIB_UPDATE_AFTER_PARAM_CHANGE()
NETLIB_UPDATEI();
NETLIB_RESETI();
NETLIB_UPDATE_PARAMI();
protected:
logic_output_t m_Q;
param_logic_t m_IN;
param_model_t m_FAMILY;
};
NETLIB_OBJECT(analog_input)
{
NETLIB_CONSTRUCTOR(analog_input)
, m_IN(*this, "IN", 0.0)
{
enregister("Q", m_Q);
}
NETLIB_UPDATE_AFTER_PARAM_CHANGE()
NETLIB_UPDATEI();
NETLIB_RESETI();
NETLIB_UPDATE_PARAMI();
protected:
analog_output_t m_Q;
param_double_t m_IN;
};
// -----------------------------------------------------------------------------
// nld_gnd
// -----------------------------------------------------------------------------
NETLIB_OBJECT(gnd)
{
NETLIB_CONSTRUCTOR(gnd)
{
enregister("Q", m_Q);
}
NETLIB_UPDATEI()
{
OUTANALOG(m_Q, 0.0);
}
NETLIB_RESETI() { }
protected:
analog_output_t m_Q;
};
// -----------------------------------------------------------------------------
// nld_dummy_input
// -----------------------------------------------------------------------------
NETLIB_OBJECT_DERIVED(dummy_input, base_dummy)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(dummy_input, base_dummy)
{
enregister("I", m_I);
}
protected:
NETLIB_RESETI() { }
NETLIB_UPDATEI() { }
private:
analog_input_t m_I;
};
// -----------------------------------------------------------------------------
// nld_frontier
// -----------------------------------------------------------------------------
NETLIB_OBJECT_DERIVED(frontier, base_dummy)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(frontier, base_dummy)
, m_RIN(netlist(), "m_RIN")
, m_ROUT(netlist(), "m_ROUT")
, m_p_RIN(*this, "RIN", 1.0e6)
, m_p_ROUT(*this, "ROUT", 50.0)
{
enregister("_I", m_I);
enregister("I",m_RIN.m_P);
enregister("G",m_RIN.m_N);
connect_late(m_I, m_RIN.m_P);
enregister("_Q", m_Q);
enregister("_OP",m_ROUT.m_P);
enregister("Q",m_ROUT.m_N);
connect_late(m_Q, m_ROUT.m_P);
}
NETLIB_RESETI()
{
m_RIN.set(1.0 / m_p_RIN.Value(),0,0);
m_ROUT.set(1.0 / m_p_ROUT.Value(),0,0);
}
NETLIB_UPDATEI()
{
OUTANALOG(m_Q, INPANALOG(m_I));
}
private:
NETLIB_NAME(twoterm) m_RIN;
NETLIB_NAME(twoterm) m_ROUT;
analog_input_t m_I;
analog_output_t m_Q;
param_double_t m_p_RIN;
param_double_t m_p_ROUT;
};
/* -----------------------------------------------------------------------------
* nld_function
*
* FIXME: Currently a proof of concept to get congo bongo working
* ----------------------------------------------------------------------------- */
NETLIB_OBJECT(function)
{
NETLIB_CONSTRUCTOR(function)
, m_N(*this, "N", 2)
, m_func(*this, "FUNC", "")
{
enregister("Q", m_Q);
for (int i=0; i < m_N; i++)
enregister(plib::pfmt("A{1}")(i), m_I[i]);
plib::pstring_vector_t cmds(m_func.Value(), " ");
m_precompiled.clear();
for (std::size_t i=0; i < cmds.size(); i++)
{
pstring cmd = cmds[i];
rpn_inst rc;
if (cmd == "+")
rc.m_cmd = ADD;
else if (cmd == "-")
rc.m_cmd = SUB;
else if (cmd == "*")
rc.m_cmd = MULT;
else if (cmd == "/")
rc.m_cmd = DIV;
else if (cmd.startsWith("A"))
{
rc.m_cmd = PUSH_INPUT;
rc.m_param = cmd.substr(1).as_long();
}
else
{
bool err = false;
rc.m_cmd = PUSH_CONST;
rc.m_param = cmd.as_double(&err);
if (err)
netlist().log().fatal("nld_function: unknown/misformatted token <{1}> in <{2}>", cmd, m_func.Value());
}
m_precompiled.push_back(rc);
}
}
protected:
NETLIB_RESETI();
NETLIB_UPDATEI();
private:
enum rpn_cmd
{
ADD,
MULT,
SUB,
DIV,
PUSH_CONST,
PUSH_INPUT
};
struct rpn_inst
{
rpn_inst() : m_cmd(ADD), m_param(0.0) { }
rpn_cmd m_cmd;
nl_double m_param;
};
param_int_t m_N;
param_str_t m_func;
analog_output_t m_Q;
analog_input_t m_I[10];
plib::pvector_t<rpn_inst> m_precompiled;
};
// -----------------------------------------------------------------------------
// nld_res_sw
// -----------------------------------------------------------------------------
NETLIB_OBJECT(res_sw)
{
public:
NETLIB_CONSTRUCTOR(res_sw)
, m_R(*this, "R")
, m_RON(*this, "RON", 1.0)
, m_ROFF(*this, "ROFF", 1.0E20)
, m_last_state(0)
{
enregister("I", m_I);
register_subalias("1", m_R.m_P);
register_subalias("2", m_R.m_N);
save(NLNAME(m_last_state));
}
NETLIB_SUB(R) m_R;
logic_input_t m_I;
param_double_t m_RON;
param_double_t m_ROFF;
NETLIB_RESETI()
{
m_last_state = 0;
m_R.set_R(m_ROFF.Value());
}
//NETLIB_UPDATE_PARAMI();
NETLIB_UPDATEI();
private:
UINT8 m_last_state;
};
// -----------------------------------------------------------------------------
// nld_base_proxy
// -----------------------------------------------------------------------------
NETLIB_OBJECT(base_proxy)
{
public:
nld_base_proxy(netlist_t &anetlist, const pstring &name, logic_t *inout_proxied, core_terminal_t *proxy_inout)
: device_t(anetlist, name)
{
m_logic_family = inout_proxied->logic_family();
m_term_proxied = inout_proxied;
m_proxy_term = proxy_inout;
}
virtual ~nld_base_proxy() {}
logic_t &term_proxied() const { return *m_term_proxied; }
core_terminal_t &proxy_term() const { return *m_proxy_term; }
protected:
virtual const logic_family_desc_t &logic_family() const
{
return *m_logic_family;
}
private:
const logic_family_desc_t *m_logic_family;
logic_t *m_term_proxied;
core_terminal_t *m_proxy_term;
};
// -----------------------------------------------------------------------------
// nld_a_to_d_proxy
// -----------------------------------------------------------------------------
NETLIB_OBJECT_DERIVED(a_to_d_proxy, base_proxy)
{
public:
nld_a_to_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *in_proxied)
: nld_base_proxy(anetlist, name, in_proxied, &m_I)
{
enregister("I", m_I);
enregister("Q", m_Q);
}
virtual ~nld_a_to_d_proxy() {}
analog_input_t m_I;
logic_output_t m_Q;
protected:
NETLIB_RESETI() { }
NETLIB_UPDATEI()
{
if (m_I.Q_Analog() > logic_family().m_high_thresh_V)
OUTLOGIC(m_Q, 1, NLTIME_FROM_NS(1));
else if (m_I.Q_Analog() < logic_family().m_low_thresh_V)
OUTLOGIC(m_Q, 0, NLTIME_FROM_NS(1));
else
{
// do nothing
}
}
private:
};
// -----------------------------------------------------------------------------
// nld_base_d_to_a_proxy
// -----------------------------------------------------------------------------
NETLIB_OBJECT_DERIVED(base_d_to_a_proxy, base_proxy)
{
public:
virtual ~nld_base_d_to_a_proxy() {}
virtual logic_input_t &in() { return m_I; }
protected:
nld_base_d_to_a_proxy(netlist_t &anetlist, const pstring &name, logic_output_t *out_proxied, core_terminal_t &proxy_out)
: nld_base_proxy(anetlist, name, out_proxied, &proxy_out)
{
enregister("I", m_I);
}
logic_input_t m_I;
private:
};
NETLIB_OBJECT_DERIVED(d_to_a_proxy, base_d_to_a_proxy)
{
public:
nld_d_to_a_proxy(netlist_t &anetlist, const pstring &name, logic_output_t *out_proxied)
: nld_base_d_to_a_proxy(anetlist, name, out_proxied, m_RV.m_P)
, m_RV(*this, "RV")
, m_last_state(-1)
, m_is_timestep(false)
{
//register_sub(m_RV);
enregister("1", m_RV.m_P);
enregister("2", m_RV.m_N);
enregister("_Q", m_Q);
register_subalias("Q", m_RV.m_P);
connect_late(m_RV.m_N, m_Q);
save(NLNAME(m_last_state));
}
virtual ~nld_d_to_a_proxy() {}
protected:
NETLIB_RESETI();
NETLIB_UPDATEI();
private:
analog_output_t m_Q;
NETLIB_SUB(twoterm) m_RV;
int m_last_state;
bool m_is_timestep;
};
class factory_lib_entry_t : public base_factory_t
{
P_PREVENT_COPYING(factory_lib_entry_t)
public:
ATTR_COLD factory_lib_entry_t(setup_t &setup, const pstring &name, const pstring &classname,
const pstring &def_param)
: base_factory_t(name, classname, def_param), m_setup(setup) { }
class wrapper : public device_t
{
public:
wrapper(const pstring &devname, netlist_t &anetlist, const pstring &name)
: device_t(anetlist, name), m_devname(devname)
{
anetlist.setup().namespace_push(name);
anetlist.setup().include(m_devname);
anetlist.setup().namespace_pop();
}
protected:
NETLIB_RESETI() { }
NETLIB_UPDATEI() { }
pstring m_devname;
};
plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) override
{
return plib::owned_ptr<device_t>::Create<wrapper>(this->name(), anetlist, name);
}
private:
setup_t &m_setup;
};
} //namespace devices
} // namespace netlist
#endif /* NLD_SYSTEM_H_ */

View File

@ -0,0 +1,41 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
* nld_cmos.h
*
*/
#ifndef NLID_CMOS_H_
#define NLID_CMOS_H_
#include "nl_base.h"
#include "analog/nld_twoterm.h"
namespace netlist
{
namespace devices
{
NETLIB_OBJECT(vdd_vss)
{
NETLIB_CONSTRUCTOR(vdd_vss)
{
enregister("VDD", m_vdd);
enregister("VSS", m_vss);
}
NETLIB_UPDATEI() {};
NETLIB_RESETI() {};
public:
ATTR_HOT inline nl_double vdd() { return INPANALOG(m_vdd); }
ATTR_HOT inline nl_double vss() { return INPANALOG(m_vss); }
analog_input_t m_vdd;
analog_input_t m_vss;
};
} //namespace devices
} // namespace netlist
#endif /* NLID_CMOS_H_ */

View File

@ -0,0 +1,591 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
* nlid_system.h
*
* netlist devices defined in the core
*
* This file contains internal headers
*/
#ifndef NLID_SYSTEM_H_
#define NLID_SYSTEM_H_
#include "nl_setup.h"
#include "nl_base.h"
#include "nl_factory.h"
#include "analog/nld_twoterm.h"
namespace netlist
{
namespace devices
{
// -----------------------------------------------------------------------------
// netlistparams
// -----------------------------------------------------------------------------
NETLIB_OBJECT(netlistparams)
{
NETLIB_CONSTRUCTOR(netlistparams)
, m_use_deactivate(*this, "USE_DEACTIVATE", 0)
{
}
NETLIB_UPDATEI() { }
//NETLIB_RESETI() { }
//NETLIB_UPDATE_PARAMI() { }
public:
param_logic_t m_use_deactivate;
};
// -----------------------------------------------------------------------------
// mainclock
// -----------------------------------------------------------------------------
NETLIB_OBJECT(mainclock)
{
NETLIB_CONSTRUCTOR(mainclock)
, m_freq(*this, "FREQ", 7159000.0 * 5)
{
enregister("Q", m_Q);
m_inc = netlist_time::from_hz(m_freq.Value()*2);
}
NETLIB_RESETI()
{
m_Q.net().set_time(netlist_time::zero);
}
NETLIB_UPDATE_PARAMI()
{
m_inc = netlist_time::from_hz(m_freq.Value()*2);
}
NETLIB_UPDATEI()
{
logic_net_t &net = m_Q.net().as_logic();
// this is only called during setup ...
net.toggle_new_Q();
net.set_time(netlist().time() + m_inc);
}
public:
logic_output_t m_Q;
param_double_t m_freq;
netlist_time m_inc;
ATTR_HOT inline static void mc_update(logic_net_t &net);
};
// -----------------------------------------------------------------------------
// clock
// -----------------------------------------------------------------------------
NETLIB_OBJECT(clock)
{
NETLIB_CONSTRUCTOR(clock)
, m_freq(*this, "FREQ", 7159000.0 * 5.0)
{
enregister("Q", m_Q);
enregister("FB", m_feedback);
m_inc = netlist_time::from_hz(m_freq.Value()*2);
connect_late(m_feedback, m_Q);
}
NETLIB_UPDATEI();
//NETLIB_RESETI();
NETLIB_UPDATE_PARAMI();
protected:
logic_input_t m_feedback;
logic_output_t m_Q;
param_double_t m_freq;
netlist_time m_inc;
};
// -----------------------------------------------------------------------------
// extclock
// -----------------------------------------------------------------------------
NETLIB_OBJECT(extclock)
{
NETLIB_CONSTRUCTOR(extclock)
, m_freq(*this, "FREQ", 7159000.0 * 5.0)
, m_pattern(*this, "PATTERN", "1,1")
, m_offset(*this, "OFFSET", 0.0)
{
enregister("Q", m_Q);
enregister("FB", m_feedback);
m_inc[0] = netlist_time::from_hz(m_freq.Value()*2);
connect_late(m_feedback, m_Q);
{
netlist_time base = netlist_time::from_hz(m_freq.Value()*2);
plib::pstring_vector_t pat(m_pattern.Value(),",");
m_off = netlist_time::from_double(m_offset.Value());
int pati[256];
m_size = pat.size();
int total = 0;
for (int i=0; i<m_size; i++)
{
pati[i] = pat[i].as_long();
total += pati[i];
}
netlist_time ttotal = netlist_time::zero;
for (int i=0; i<m_size - 1; i++)
{
m_inc[i] = base * pati[i];
ttotal += m_inc[i];
}
m_inc[m_size - 1] = base * total - ttotal;
}
save(NLNAME(m_cnt));
save(NLNAME(m_off));
}
NETLIB_UPDATEI();
NETLIB_RESETI();
//NETLIB_UPDATE_PARAMI();
protected:
param_double_t m_freq;
param_str_t m_pattern;
param_double_t m_offset;
logic_input_t m_feedback;
logic_output_t m_Q;
UINT32 m_cnt;
UINT32 m_size;
netlist_time m_inc[32];
netlist_time m_off;
};
// -----------------------------------------------------------------------------
// Special support devices ...
// -----------------------------------------------------------------------------
NETLIB_OBJECT(logic_input)
{
NETLIB_CONSTRUCTOR(logic_input)
, m_IN(*this, "IN", 0)
/* make sure we get the family first */
, m_FAMILY(*this, "FAMILY", "FAMILY(TYPE=TTL)")
{
set_logic_family(netlist().setup().family_from_model(m_FAMILY.Value()));
enregister("Q", m_Q);
}
NETLIB_UPDATE_AFTER_PARAM_CHANGE()
NETLIB_UPDATEI();
NETLIB_RESETI();
NETLIB_UPDATE_PARAMI();
protected:
logic_output_t m_Q;
param_logic_t m_IN;
param_model_t m_FAMILY;
};
NETLIB_OBJECT(analog_input)
{
NETLIB_CONSTRUCTOR(analog_input)
, m_IN(*this, "IN", 0.0)
{
enregister("Q", m_Q);
}
NETLIB_UPDATE_AFTER_PARAM_CHANGE()
NETLIB_UPDATEI();
NETLIB_RESETI();
NETLIB_UPDATE_PARAMI();
protected:
analog_output_t m_Q;
param_double_t m_IN;
};
// -----------------------------------------------------------------------------
// nld_gnd
// -----------------------------------------------------------------------------
NETLIB_OBJECT(gnd)
{
NETLIB_CONSTRUCTOR(gnd)
{
enregister("Q", m_Q);
}
NETLIB_UPDATEI()
{
OUTANALOG(m_Q, 0.0);
}
NETLIB_RESETI() { }
protected:
analog_output_t m_Q;
};
// -----------------------------------------------------------------------------
// nld_dummy_input
// -----------------------------------------------------------------------------
NETLIB_OBJECT_DERIVED(dummy_input, base_dummy)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(dummy_input, base_dummy)
{
enregister("I", m_I);
}
protected:
NETLIB_RESETI() { }
NETLIB_UPDATEI() { }
private:
analog_input_t m_I;
};
// -----------------------------------------------------------------------------
// nld_frontier
// -----------------------------------------------------------------------------
NETLIB_OBJECT_DERIVED(frontier, base_dummy)
{
public:
NETLIB_CONSTRUCTOR_DERIVED(frontier, base_dummy)
, m_RIN(netlist(), "m_RIN")
, m_ROUT(netlist(), "m_ROUT")
, m_p_RIN(*this, "RIN", 1.0e6)
, m_p_ROUT(*this, "ROUT", 50.0)
{
enregister("_I", m_I);
enregister("I",m_RIN.m_P);
enregister("G",m_RIN.m_N);
connect_late(m_I, m_RIN.m_P);
enregister("_Q", m_Q);
enregister("_OP",m_ROUT.m_P);
enregister("Q",m_ROUT.m_N);
connect_late(m_Q, m_ROUT.m_P);
}
NETLIB_RESETI()
{
m_RIN.set(1.0 / m_p_RIN.Value(),0,0);
m_ROUT.set(1.0 / m_p_ROUT.Value(),0,0);
}
NETLIB_UPDATEI()
{
OUTANALOG(m_Q, INPANALOG(m_I));
}
private:
NETLIB_NAME(twoterm) m_RIN;
NETLIB_NAME(twoterm) m_ROUT;
analog_input_t m_I;
analog_output_t m_Q;
param_double_t m_p_RIN;
param_double_t m_p_ROUT;
};
/* -----------------------------------------------------------------------------
* nld_function
*
* FIXME: Currently a proof of concept to get congo bongo working
* ----------------------------------------------------------------------------- */
NETLIB_OBJECT(function)
{
NETLIB_CONSTRUCTOR(function)
, m_N(*this, "N", 2)
, m_func(*this, "FUNC", "")
{
enregister("Q", m_Q);
for (int i=0; i < m_N; i++)
enregister(plib::pfmt("A{1}")(i), m_I[i]);
plib::pstring_vector_t cmds(m_func.Value(), " ");
m_precompiled.clear();
for (std::size_t i=0; i < cmds.size(); i++)
{
pstring cmd = cmds[i];
rpn_inst rc;
if (cmd == "+")
rc.m_cmd = ADD;
else if (cmd == "-")
rc.m_cmd = SUB;
else if (cmd == "*")
rc.m_cmd = MULT;
else if (cmd == "/")
rc.m_cmd = DIV;
else if (cmd.startsWith("A"))
{
rc.m_cmd = PUSH_INPUT;
rc.m_param = cmd.substr(1).as_long();
}
else
{
bool err = false;
rc.m_cmd = PUSH_CONST;
rc.m_param = cmd.as_double(&err);
if (err)
netlist().log().fatal("nld_function: unknown/misformatted token <{1}> in <{2}>", cmd, m_func.Value());
}
m_precompiled.push_back(rc);
}
}
protected:
NETLIB_RESETI();
NETLIB_UPDATEI();
private:
enum rpn_cmd
{
ADD,
MULT,
SUB,
DIV,
PUSH_CONST,
PUSH_INPUT
};
struct rpn_inst
{
rpn_inst() : m_cmd(ADD), m_param(0.0) { }
rpn_cmd m_cmd;
nl_double m_param;
};
param_int_t m_N;
param_str_t m_func;
analog_output_t m_Q;
analog_input_t m_I[10];
plib::pvector_t<rpn_inst> m_precompiled;
};
// -----------------------------------------------------------------------------
// nld_res_sw
// -----------------------------------------------------------------------------
NETLIB_OBJECT(res_sw)
{
public:
NETLIB_CONSTRUCTOR(res_sw)
, m_R(*this, "R")
, m_RON(*this, "RON", 1.0)
, m_ROFF(*this, "ROFF", 1.0E20)
, m_last_state(0)
{
enregister("I", m_I);
register_subalias("1", m_R.m_P);
register_subalias("2", m_R.m_N);
save(NLNAME(m_last_state));
}
NETLIB_SUB(R) m_R;
logic_input_t m_I;
param_double_t m_RON;
param_double_t m_ROFF;
NETLIB_RESETI()
{
m_last_state = 0;
m_R.set_R(m_ROFF.Value());
}
//NETLIB_UPDATE_PARAMI();
NETLIB_UPDATEI();
private:
UINT8 m_last_state;
};
// -----------------------------------------------------------------------------
// nld_base_proxy
// -----------------------------------------------------------------------------
NETLIB_OBJECT(base_proxy)
{
public:
nld_base_proxy(netlist_t &anetlist, const pstring &name, logic_t *inout_proxied, core_terminal_t *proxy_inout)
: device_t(anetlist, name)
{
m_logic_family = inout_proxied->logic_family();
m_term_proxied = inout_proxied;
m_proxy_term = proxy_inout;
}
virtual ~nld_base_proxy() {}
logic_t &term_proxied() const { return *m_term_proxied; }
core_terminal_t &proxy_term() const { return *m_proxy_term; }
protected:
virtual const logic_family_desc_t &logic_family() const
{
return *m_logic_family;
}
private:
const logic_family_desc_t *m_logic_family;
logic_t *m_term_proxied;
core_terminal_t *m_proxy_term;
};
// -----------------------------------------------------------------------------
// nld_a_to_d_proxy
// -----------------------------------------------------------------------------
NETLIB_OBJECT_DERIVED(a_to_d_proxy, base_proxy)
{
public:
nld_a_to_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *in_proxied)
: nld_base_proxy(anetlist, name, in_proxied, &m_I)
{
enregister("I", m_I);
enregister("Q", m_Q);
}
virtual ~nld_a_to_d_proxy() {}
analog_input_t m_I;
logic_output_t m_Q;
protected:
NETLIB_RESETI() { }
NETLIB_UPDATEI()
{
if (m_I.Q_Analog() > logic_family().m_high_thresh_V)
OUTLOGIC(m_Q, 1, NLTIME_FROM_NS(1));
else if (m_I.Q_Analog() < logic_family().m_low_thresh_V)
OUTLOGIC(m_Q, 0, NLTIME_FROM_NS(1));
else
{
// do nothing
}
}
private:
};
// -----------------------------------------------------------------------------
// nld_base_d_to_a_proxy
// -----------------------------------------------------------------------------
NETLIB_OBJECT_DERIVED(base_d_to_a_proxy, base_proxy)
{
public:
virtual ~nld_base_d_to_a_proxy() {}
virtual logic_input_t &in() { return m_I; }
protected:
nld_base_d_to_a_proxy(netlist_t &anetlist, const pstring &name, logic_output_t *out_proxied, core_terminal_t &proxy_out)
: nld_base_proxy(anetlist, name, out_proxied, &proxy_out)
{
enregister("I", m_I);
}
logic_input_t m_I;
private:
};
NETLIB_OBJECT_DERIVED(d_to_a_proxy, base_d_to_a_proxy)
{
public:
nld_d_to_a_proxy(netlist_t &anetlist, const pstring &name, logic_output_t *out_proxied)
: nld_base_d_to_a_proxy(anetlist, name, out_proxied, m_RV.m_P)
, m_RV(*this, "RV")
, m_last_state(-1)
, m_is_timestep(false)
{
//register_sub(m_RV);
enregister("1", m_RV.m_P);
enregister("2", m_RV.m_N);
enregister("_Q", m_Q);
register_subalias("Q", m_RV.m_P);
connect_late(m_RV.m_N, m_Q);
save(NLNAME(m_last_state));
}
virtual ~nld_d_to_a_proxy() {}
protected:
NETLIB_RESETI();
NETLIB_UPDATEI();
private:
analog_output_t m_Q;
NETLIB_SUB(twoterm) m_RV;
int m_last_state;
bool m_is_timestep;
};
class factory_lib_entry_t : public base_factory_t
{
P_PREVENT_COPYING(factory_lib_entry_t)
public:
ATTR_COLD factory_lib_entry_t(setup_t &setup, const pstring &name, const pstring &classname,
const pstring &def_param)
: base_factory_t(name, classname, def_param), m_setup(setup) { }
class wrapper : public device_t
{
public:
wrapper(const pstring &devname, netlist_t &anetlist, const pstring &name)
: device_t(anetlist, name), m_devname(devname)
{
anetlist.setup().namespace_push(name);
anetlist.setup().include(m_devname);
anetlist.setup().namespace_pop();
}
protected:
NETLIB_RESETI() { }
NETLIB_UPDATEI() { }
pstring m_devname;
};
plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) override
{
return plib::owned_ptr<device_t>::Create<wrapper>(this->name(), anetlist, name);
}
private:
setup_t &m_setup;
};
} //namespace devices
} // namespace netlist
#endif /* NLD_SYSTEM_H_ */

View File

@ -10,7 +10,7 @@
#include "plib/palloc.h"
#include "nl_base.h"
#include "devices/nld_system.h"
#include "devices/nlid_system.h"
#include "nl_util.h"
const netlist::netlist_time netlist::netlist_time::zero = netlist::netlist_time(0);

View File

@ -16,7 +16,7 @@
#include "nl_util.h"
#include "nl_factory.h"
#include "devices/net_lib.h"
#include "devices/nld_system.h"
#include "devices/nlid_system.h"
#include "analog/nld_twoterm.h"
#include "solver/nld_solver.h"