Netlist changes

- Replaced shared_ptr by unique_ptr. 
- Better seperation of setup_t and netlist_t. 
- Fixed bugs in rdtsc code. Refactored timer code. 
- Simplify conditional activation/deactivation. 
- Introduced HINT(device, hint) to clarify that hints are inheritent 
  and not specific to devices. 
- Added improved profiling support to netlist. Statistics output now
  proposes devices for which whole device activation/deactivation be
  disabled. No significant improvement for pong, but breakout
  experiences a 10% improvement. 
- Moved options code from include to cpp file.
- Minor modifications to 7493 and 9316
- Introduced perftime_t and perfcount_t for gathering statistics. These
  templates do not create any code if statistics are not kept.
- Make help2man ./nltool produce usuable output. 
- More truthtable refactoring. Removed half-finished code for internal
  state support. As implemented, this would have had no support for
  timing delays. 
[Couriersud]
This commit is contained in:
couriersud 2016-06-23 02:04:40 +02:00
parent 224dbf1cc9
commit c6e6911aed
35 changed files with 1195 additions and 633 deletions

View File

@ -38,11 +38,14 @@ project "netlist"
MAME_DIR .. "src/lib/netlist/plib/pconfig.h",
MAME_DIR .. "src/lib/netlist/plib/palloc.cpp",
MAME_DIR .. "src/lib/netlist/plib/palloc.h",
MAME_DIR .. "src/lib/netlist/plib/pchrono.cpp",
MAME_DIR .. "src/lib/netlist/plib/pchrono.h",
MAME_DIR .. "src/lib/netlist/plib/pfmtlog.cpp",
MAME_DIR .. "src/lib/netlist/plib/pfmtlog.h",
MAME_DIR .. "src/lib/netlist/plib/plists.h",
MAME_DIR .. "src/lib/netlist/plib/pdynlib.cpp",
MAME_DIR .. "src/lib/netlist/plib/pdynlib.h",
MAME_DIR .. "src/lib/netlist/plib/poptions.cpp",
MAME_DIR .. "src/lib/netlist/plib/poptions.h",
MAME_DIR .. "src/lib/netlist/plib/pparser.cpp",
MAME_DIR .. "src/lib/netlist/plib/pparser.h",

View File

@ -103,7 +103,7 @@ void netlist_mame_analog_output_t::custom_netlist_additions(netlist::setup_t &se
plib::owned_ptr<netlist::device_t> dev = plib::owned_ptr<netlist::device_t>::Create<NETLIB_NAME(analog_callback)>(setup.netlist(), setup.build_fqn(dname));
static_cast<NETLIB_NAME(analog_callback) *>(dev.get())->register_callback(m_delegate);
setup.register_dev(std::move(dev));
setup.netlist().register_dev(std::move(dev));
setup.register_link(dname + ".IN", m_in);
}

View File

@ -66,11 +66,11 @@
// Extensions to interface netlist with MAME code ....
// ----------------------------------------------------------------------------------------
class netlist_source_memregion_t : public netlist::setup_t::source_t
class netlist_source_memregion_t : public netlist::source_t
{
public:
netlist_source_memregion_t(pstring name)
: netlist::setup_t::source_t(), m_name(name)
: netlist::source_t(), m_name(name)
{
}
@ -80,7 +80,7 @@ private:
};
#define MEMREGION_SOURCE(_name) \
setup.register_source(std::make_shared<netlist_source_memregion_t>(_name));
setup.register_source(plib::make_unique_base<netlist::source_t, netlist_source_memregion_t>(_name));
#define NETDEV_ANALOG_CALLBACK_MEMBER(_name) \
void _name(const double data, const attotime &time)

View File

@ -23,7 +23,7 @@ CDEFS = -DPSTANDALONE=1 -DPTR64=1
CFLAGS = $(LTO) -g -O3 -std=c++11 -march=native -I.. -Wall -Wpedantic -Wsign-compare -Wextra -Wno-unused-parameter
LDFLAGS = $(LTO) -g -O3 -std=c++11 -lpthread -ldl
CC = @g++-5
CC = g++-5
LD = @g++-5
MD = @mkdir
RM = @rm
@ -49,8 +49,10 @@ OBJS = $(POBJS) $(NLOBJS)
POBJS := \
$(POBJ)/pstring.o \
$(POBJ)/palloc.o \
$(POBJ)/pchrono.o \
$(POBJ)/pdynlib.o \
$(POBJ)/pfmtlog.o \
$(POBJ)/poptions.o \
$(POBJ)/pparser.o \
$(POBJ)/pstate.o \
$(POBJ)/pstream.o \
@ -101,6 +103,13 @@ NLOBJS := \
$(NLOBJ)/solver/nld_solver.o \
$(NLOBJ)/tools/nl_convert.o \
ALL_OBJS = $(OBJS) $(NLOBJ)/prg/nltool.o $(NLOBJ)/prg/nlwav.o
SOURCES = $(patsubst $(OBJ)%, $(SRC)%, $(ALL_OBJS:.o=.cpp))
#-------------------------------------------------
# all
#-------------------------------------------------
all: maketree $(TARGETS)
#-------------------------------------------------
@ -108,7 +117,7 @@ all: maketree $(TARGETS)
#-------------------------------------------------
clean:
$(RM) -rf $(OBJS) $(TARGETS)
$(RM) -rf $(OBJS) $(TARGETS) .depend
#-------------------------------------------------
# nltool
@ -131,6 +140,20 @@ $(sort $(OBJDIRS)):
maketree: $(sort $(OBJDIRS))
#-------------------------------------------------
# depends
#-------------------------------------------------
depend: .depend
.depend: $(SOURCES)
@echo creating .depend
@rm -f ./.depend
@for i in $(SOURCES); do \
$(CC) $(CFLAGS) -MM $$i -MT `echo $$i | sed -e 's/$(SRC)/$(OBJ)/' -e 's/.cpp/.o/' ` >>./.depend; \
done
-include .depend
#-------------------------------------------------
# generic rules
@ -138,15 +161,15 @@ maketree: $(sort $(OBJDIRS))
$(OBJ)/%.o: $(SRC)/%.cpp
@echo Compiling $<...
$(CC) $(CDEFS) $(CFLAGS) -c $< -o $@
@$(CC) $(CDEFS) $(CFLAGS) -c $< -o $@
$(OBJ)/%.pp: $(SRC)/%.cpp | $(OSPREBUILD)
@echo Compiling $<...
$(CC) $(CDEFS) $(CFLAGS) -E $< -o $@
@$(CC) $(CDEFS) $(CFLAGS) -E $< -o $@
$(OBJ)/%.s: $(SRC)/%.cpp | $(OSPREBUILD)
@echo Compiling $<...
$(CC) $(CDEFS) $(CFLAGS) -S $< -o $@
@$(CC) $(CDEFS) $(CFLAGS) -S $< -o $@
$(OBJ)/%.a:
@echo Archiving $@...

View File

@ -13,8 +13,8 @@ namespace netlist
namespace devices
{
NETLIB_TRUTHTABLE(74279A, 3, 1, 0);
NETLIB_TRUTHTABLE(74279B, 4, 1, 0);
NETLIB_TRUTHTABLE(74279A, 3, 1);
NETLIB_TRUTHTABLE(74279B, 4, 1);
NETLIB_OBJECT(74279_dip)
{

View File

@ -101,8 +101,8 @@ namespace netlist
NETLIB_UPDATE(7493ff)
{
const netlist_time out_delay = NLTIME_FROM_NS(18);
if (m_reset != 0)
constexpr netlist_time out_delay = NLTIME_FROM_NS(18);
if (m_reset)
{
m_state ^= 1;
OUTLOGIC(m_Q, m_state, out_delay);

View File

@ -32,7 +32,7 @@ namespace netlist
/* The truthtable implementation is a lot faster than
* the carefully crafted code :-(
*/
NETLIB_TRUTHTABLE(9312, 12, 2, 0);
NETLIB_TRUTHTABLE(9312, 12, 2);
#else
NETLIB_OBJECT(9312)

View File

@ -44,15 +44,15 @@ namespace netlist
{
NETLIB_CONSTRUCTOR(9316_sub)
, m_CLK(*this, "CLK")
, m_cnt(*this, "m_cnt", 0)
, m_loadq(*this, "m_loadq", 0)
, m_ent(*this, "m_ent", 0)
, m_QA(*this, "QA")
, m_QB(*this, "QB")
, m_QC(*this, "QC")
, m_QD(*this, "QD")
, m_RC(*this, "RC")
, m_ABCD(nullptr)
, m_cnt(*this, "m_cnt", 0)
, m_loadq(*this, "m_loadq", 0)
, m_ent(*this, "m_ent", 0)
{
}
@ -60,11 +60,20 @@ namespace netlist
NETLIB_UPDATEI();
public:
inline void update_outputs_all(const uint_fast8_t cnt, const netlist_time out_delay);
inline void update_outputs(const uint_fast8_t cnt);
void update_outputs_all(const uint_fast8_t cnt, const netlist_time out_delay)
{
OUTLOGIC(m_QA, (cnt >> 0) & 1, out_delay);
OUTLOGIC(m_QB, (cnt >> 1) & 1, out_delay);
OUTLOGIC(m_QC, (cnt >> 2) & 1, out_delay);
OUTLOGIC(m_QD, (cnt >> 3) & 1, out_delay);
}
logic_input_t m_CLK;
state_var_u8 m_cnt;
state_var_u8 m_loadq;
state_var_u8 m_ent;
logic_output_t m_QA;
logic_output_t m_QB;
logic_output_t m_QC;
@ -72,11 +81,6 @@ namespace netlist
logic_output_t m_RC;
NETLIB_NAME(9316_subABCD) *m_ABCD;
state_var_u8 m_cnt;
state_var_u8 m_loadq;
state_var_u8 m_ent;
};
NETLIB_OBJECT(9316)
@ -173,7 +177,7 @@ namespace netlist
break;
default:
m_cnt++;
update_outputs(m_cnt);
update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
break;
}
}
@ -209,58 +213,6 @@ namespace netlist
}
}
inline NETLIB_FUNC_VOID(9316_sub, update_outputs_all, (const uint_fast8_t cnt, const netlist_time out_delay))
{
OUTLOGIC(m_QA, (cnt >> 0) & 1, out_delay);
OUTLOGIC(m_QB, (cnt >> 1) & 1, out_delay);
OUTLOGIC(m_QC, (cnt >> 2) & 1, out_delay);
OUTLOGIC(m_QD, (cnt >> 3) & 1, out_delay);
}
inline NETLIB_FUNC_VOID(9316_sub, update_outputs, (const uint_fast8_t cnt))
{
/* static */ const netlist_time out_delay = NLTIME_FROM_NS(20);
#if 0
// for (int i=0; i<4; i++)
// OUTLOGIC(m_Q[i], (cnt >> i) & 1, delay[i]);
OUTLOGIC(m_QA, (cnt >> 0) & 1, out_delay);
OUTLOGIC(m_QB, (cnt >> 1) & 1, out_delay);
OUTLOGIC(m_QC, (cnt >> 2) & 1, out_delay);
OUTLOGIC(m_QD, (cnt >> 3) & 1, out_delay);
#else
if ((cnt & 1) == 1)
OUTLOGIC(m_QA, 1, out_delay);
else
{
OUTLOGIC(m_QA, 0, out_delay);
switch (cnt)
{
case 0x00:
OUTLOGIC(m_QB, 0, out_delay);
OUTLOGIC(m_QC, 0, out_delay);
OUTLOGIC(m_QD, 0, out_delay);
break;
case 0x02:
case 0x06:
case 0x0A:
case 0x0E:
OUTLOGIC(m_QB, 1, out_delay);
break;
case 0x04:
case 0x0C:
OUTLOGIC(m_QB, 0, out_delay);
OUTLOGIC(m_QC, 1, out_delay);
break;
case 0x08:
OUTLOGIC(m_QB, 0, out_delay);
OUTLOGIC(m_QC, 0, out_delay);
OUTLOGIC(m_QD, 1, out_delay);
break;
}
}
#endif
}
NETLIB_DEVICE_IMPL(9316)
NETLIB_DEVICE_IMPL(9316_dip)

View File

@ -7,13 +7,14 @@
#include "nld_truthtable.h"
#include "plib/plists.h"
#include "nl_setup.h"
namespace netlist
{
namespace devices
{
template<unsigned m_NI, unsigned m_NO, int has_state>
template<unsigned m_NI, unsigned m_NO>
class netlist_factory_truthtable_t : public netlist_base_factory_truthtable_t
{
P_PREVENT_COPYING(netlist_factory_truthtable_t)
@ -25,11 +26,11 @@ namespace netlist
plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) override
{
typedef nld_truthtable_t<m_NI, m_NO, has_state> tt_type;
typedef nld_truthtable_t<m_NI, m_NO> tt_type;
return plib::owned_ptr<device_t>::Create<tt_type>(anetlist, name, m_family, &m_ttbl, m_desc);
}
private:
typename nld_truthtable_t<m_NI, m_NO, has_state>::truthtable_t m_ttbl;
typename nld_truthtable_t<m_NI, m_NO>::truthtable_t m_ttbl;
};
static const uint_least64_t all_set = ~((uint_least64_t) 0);
@ -259,20 +260,17 @@ void truthtable_desc_t::setup(const plib::pstring_vector_t &truthtable, uint_lea
}
#define ENTRYX(n, m, h) case (n * 1000 + m * 10 + h): \
{ using xtype = netlist_factory_truthtable_t<n, m, h>; \
return plib::owned_ptr<netlist_base_factory_truthtable_t>::Create<xtype>(name,classname,def_param); } break
#define ENTRYY(n, m) ENTRYX(n, m, 0); ENTRYX(n, m, 1)
#define ENTRYY(n, m) case (n * 100 + m): \
{ using xtype = netlist_factory_truthtable_t<n, m>; \
ret = new xtype(desc.name, desc.classname, desc.def_param); } break
#define ENTRY(n) ENTRYY(n, 1); ENTRYY(n, 2); ENTRYY(n, 3); ENTRYY(n, 4); ENTRYY(n, 5); ENTRYY(n, 6)
plib::owned_ptr<netlist_base_factory_truthtable_t> nl_tt_factory_create(const unsigned ni, const unsigned no,
const unsigned has_state,
const pstring &name, const pstring &classname,
const pstring &def_param)
void tt_factory_create(setup_t &setup, tt_desc &desc)
{
switch (ni * 1000 + no * 10 + has_state)
netlist_base_factory_truthtable_t *ret;
switch (desc.ni * 100 + desc.no)
{
ENTRY(1);
ENTRY(2);
@ -285,10 +283,13 @@ plib::owned_ptr<netlist_base_factory_truthtable_t> nl_tt_factory_create(const un
ENTRY(9);
ENTRY(10);
default:
pstring msg = plib::pfmt("unable to create truthtable<{1},{2},{3}>")(ni)(no)(has_state);
pstring msg = plib::pfmt("unable to create truthtable<{1},{2}>")(desc.ni)(desc.no);
nl_assert_always(false, msg);
}
//return nullptr;
ret->m_desc = desc.desc;
if (desc.family != "")
ret->m_family = setup.family_from_model(desc.family);
setup.factory().register_device(std::unique_ptr<netlist_base_factory_truthtable_t>(ret));
}
} //namespace devices

View File

@ -13,39 +13,22 @@
#include <new>
#include <cstdint>
#include "nl_base.h"
#include "nl_setup.h"
#include "nl_factory.h"
#include "plib/plists.h"
#define NETLIB_TRUTHTABLE(cname, nIN, nOUT, state) \
class NETLIB_NAME(cname) : public nld_truthtable_t<nIN, nOUT, state> \
#define NETLIB_TRUTHTABLE(cname, nIN, nOUT) \
class NETLIB_NAME(cname) : public nld_truthtable_t<nIN, nOUT> \
{ \
public: \
template <class C> \
NETLIB_NAME(cname)(C &owner, const pstring &name) \
: nld_truthtable_t<nIN, nOUT, state>(owner, name, nullptr, &m_ttbl, m_desc) { } \
NETLIB_NAME(cname)(C &owner, const pstring &name) \
: nld_truthtable_t<nIN, nOUT>(owner, name, nullptr, &m_ttbl, m_desc) { } \
private: \
static truthtable_t m_ttbl; \
static const char *m_desc[]; \
}
#define TRUTHTABLE_START(cname, in, out, has_state, def_params) \
{ \
auto ttd = netlist::devices::nl_tt_factory_create(in, out, has_state, \
# cname, # cname, "+" def_params);
#define TT_HEAD(x) \
ttd->m_desc.push_back(x);
#define TT_LINE(x) \
ttd->m_desc.push_back(x);
#define TT_FAMILY(x) \
ttd->m_family = setup.family_from_model(x);
#define TRUTHTABLE_END() \
setup.factory().register_device(std::move(ttd)); \
}
namespace netlist
{
@ -121,11 +104,11 @@ namespace netlist
struct truthtable_desc_t
{
truthtable_desc_t(int NO, int NI, int has_state, bool *initialized,
truthtable_desc_t(int NO, int NI, bool *initialized,
packed_int outs, uint_least8_t *timing, netlist_time *timing_nt)
: m_NO(NO), m_NI(NI), /*m_has_state(has_state),*/ m_initialized(initialized),
: m_NO(NO), m_NI(NI), m_initialized(initialized),
m_outs(outs), m_timing(timing), m_timing_nt(timing_nt),
m_num_bits(m_NI + has_state * (m_NI + m_NO)),
m_num_bits(m_NI),
m_size(1 << (m_num_bits))
{
}
@ -154,15 +137,15 @@ namespace netlist
};
template<unsigned m_NI, unsigned m_NO, int m_has_state>
template<unsigned m_NI, unsigned m_NO>
NETLIB_OBJECT(truthtable_t)
{
private:
family_setter_t m_fam;
public:
static const int m_num_bits = m_NI + m_has_state * (m_NI + m_NO);
static const int m_size = (1 << (m_num_bits));
static constexpr int m_num_bits = m_NI;
static constexpr int m_size = (1 << (m_num_bits));
struct truthtable_t
{
@ -180,10 +163,8 @@ namespace netlist
truthtable_t *ttp, const char *desc[])
: device_t(owner, name)
, m_fam(*this, fam)
, m_last_state(*this, "m_last_state", 0)
, m_ign(*this, "m_ign", 0)
, m_active(*this, "m_active", 1)
, m_use_deactivate(*this, "USE_DEACTIVATE", true)
, m_ttp(ttp)
{
while (*desc != nullptr && **desc != 0 )
@ -199,10 +180,8 @@ namespace netlist
truthtable_t *ttp, const plib::pstring_vector_t &desc)
: device_t(owner, name)
, m_fam(*this, fam)
, m_last_state(*this, "m_last_state", 0)
, m_ign(*this, "m_ign", 0)
, m_active(*this, "m_active", 1)
, m_use_deactivate(*this, "USE_DEACTIVATE", true)
, m_ttp(ttp)
{
m_desc = desc;
@ -211,6 +190,8 @@ namespace netlist
void startxx()
{
set_hint_deactivate(true);
pstring header = m_desc[0];
plib::pstring_vector_t io(header,"|");
@ -249,8 +230,9 @@ namespace netlist
m_ign = 0;
truthtable_desc_t desc(m_NO, m_NI, m_has_state,
&m_ttp->m_initialized, packed_int(m_ttp->m_outs), m_ttp->m_timing, m_ttp->m_timing_nt);
truthtable_desc_t desc(m_NO, m_NI, &m_ttp->m_initialized,
packed_int(m_ttp->m_outs),
m_ttp->m_timing, m_ttp->m_timing_nt);
desc.setup(m_desc, disabled_ignore * 0);
#if 0
@ -272,7 +254,6 @@ namespace netlist
for (std::size_t i=0; i<m_NO;i++)
if (this->m_Q[i].net().num_cons()>0)
m_active++;
m_last_state = 0;
}
NETLIB_UPDATEI()
@ -283,7 +264,7 @@ namespace netlist
public:
void inc_active() override
{
if (m_NI > 1 && m_has_state == 0 && m_use_deactivate)
if (m_NI > 1)
if (++m_active == 1)
{
process<false>();
@ -298,7 +279,7 @@ namespace netlist
* can decide for each individual gate whether it is benefitial to
* ignore deactivation.
*/
if (m_NI > 1 && m_has_state == 0 && m_use_deactivate)
if (m_NI > 1)
if (--m_active == 0)
{
for (std::size_t i = 0; i< m_NI; i++)
@ -322,7 +303,7 @@ namespace netlist
netlist_time mt = netlist_time::zero();
uint_least64_t state = 0;
if (m_NI > 1 && !m_has_state)
if (m_NI > 1)
{
auto ign = m_ign;
if (!doOUT)
@ -354,9 +335,6 @@ namespace netlist
}
auto nstate = state;
if (m_has_state)
nstate |= (m_last_state << m_NI);
const auto outstate = m_ttp->m_outs[nstate];
const auto out = outstate & ((1 << m_NO) - 1);
@ -373,10 +351,7 @@ namespace netlist
for (std::size_t i = 0; i < m_NO; i++)
m_Q[i].net().set_Q_time((out >> i) & 1, mt + m_ttp->m_timing_nt[m_ttp->m_timing[timebase + i]]);
if (m_has_state)
m_last_state = (state << m_NO) | out;
if (m_NI > 1 && !m_has_state)
if (m_NI > 1)
{
auto ign(m_ign);
for (std::size_t i = 0; ign != 0; ign >>= 1, i++)
@ -386,11 +361,9 @@ namespace netlist
}
/* FIXME: check width */
state_var_u32 m_last_state;
state_var_u32 m_ign;
state_var_s32 m_active;
param_logic_t m_use_deactivate;
truthtable_t *m_ttp;
state_var_u32 m_ign;
state_var_s32 m_active;
truthtable_t * m_ttp;
plib::pstring_vector_t m_desc;
};
@ -411,10 +384,7 @@ namespace netlist
const logic_family_desc_t *m_family;
};
plib::owned_ptr<netlist_base_factory_truthtable_t> nl_tt_factory_create(const unsigned ni, const unsigned no,
const unsigned has_state,
const pstring &name, const pstring &classname,
const pstring &def_param);
void tt_factory_create(setup_t &setup, tt_desc &desc);
} //namespace devices
} // namespace netlist

View File

@ -155,7 +155,7 @@ NETLIST_END()
NETLIST_START(CD4XXX_lib)
TRUTHTABLE_START(CD4001_NOR, 2, 1, 0, "")
TRUTHTABLE_START(CD4001_NOR, 2, 1, "")
TT_HEAD("A , B | Q ")
TT_LINE("0,0|1|85")
TT_LINE("X,1|0|120")

View File

@ -45,7 +45,7 @@ NETLIST_START(MC14584B_DIP)
NETLIST_END()
NETLIST_START(otheric_lib)
TRUTHTABLE_START(MC14584B_GATE, 1, 1, 0, "")
TRUTHTABLE_START(MC14584B_GATE, 1, 1, "")
TT_HEAD(" A | Q ")
TT_LINE(" 0 | 1 |100")
TT_LINE(" 1 | 0 |100")

View File

@ -542,7 +542,7 @@ NETLIST_END()
NETLIST_START(TTL74XX_lib)
TRUTHTABLE_START(TTL_7400_GATE, 2, 1, 0, "")
TRUTHTABLE_START(TTL_7400_GATE, 2, 1, "")
TT_HEAD("A,B|Q ")
TT_LINE("0,X|1|22")
TT_LINE("X,0|1|22")
@ -550,7 +550,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7400_NAND, 2, 1, 0, "A,B")
TRUTHTABLE_START(TTL_7400_NAND, 2, 1, "A,B")
TT_HEAD("A,B|Q ")
TT_LINE("0,X|1|22")
TT_LINE("X,0|1|22")
@ -558,7 +558,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7402_GATE, 2, 1, 0, "")
TRUTHTABLE_START(TTL_7402_GATE, 2, 1, "")
TT_HEAD("A,B|Q ")
TT_LINE("0,0|1|22")
TT_LINE("X,1|0|15")
@ -566,7 +566,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7402_NOR, 2, 1, 0, "A,B")
TRUTHTABLE_START(TTL_7402_NOR, 2, 1, "A,B")
TT_HEAD("A,B|Q ")
TT_LINE("0,0|1|22")
TT_LINE("X,1|0|15")
@ -574,21 +574,21 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7404_GATE, 1, 1, 0, "")
TRUTHTABLE_START(TTL_7404_GATE, 1, 1, "")
TT_HEAD(" A | Q ")
TT_LINE(" 0 | 1 |22")
TT_LINE(" 1 | 0 |15")
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7404_INVERT, 1, 1, 0, "A")
TRUTHTABLE_START(TTL_7404_INVERT, 1, 1, "A")
TT_HEAD(" A | Q ")
TT_LINE(" 0 | 1 |22")
TT_LINE(" 1 | 0 |15")
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7408_GATE, 2, 1, 0, "")
TRUTHTABLE_START(TTL_7408_GATE, 2, 1, "")
TT_HEAD("A,B|Q ")
TT_LINE("0,X|0|15")
TT_LINE("X,0|0|15")
@ -596,7 +596,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7408_AND, 2, 1, 0, "A,B")
TRUTHTABLE_START(TTL_7408_AND, 2, 1, "A,B")
TT_HEAD("A,B|Q ")
TT_LINE("0,X|0|15")
TT_LINE("X,0|0|15")
@ -604,7 +604,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7410_NAND, 3, 1, 0, "A,B,C")
TRUTHTABLE_START(TTL_7410_NAND, 3, 1, "A,B,C")
TT_HEAD("A,B,C|Q ")
TT_LINE("0,X,X|1|22")
TT_LINE("X,0,X|1|22")
@ -613,7 +613,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7410_GATE, 3, 1, 0, "")
TRUTHTABLE_START(TTL_7410_GATE, 3, 1, "")
TT_HEAD("A,B,C|Q ")
TT_LINE("0,X,X|1|22")
TT_LINE("X,0,X|1|22")
@ -622,7 +622,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7411_AND, 3, 1, 0, "A,B,C")
TRUTHTABLE_START(TTL_7411_AND, 3, 1, "A,B,C")
TT_HEAD("A,B,C|Q ")
TT_LINE("0,X,X|0|15")
TT_LINE("X,0,X|0|15")
@ -631,7 +631,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7411_GATE, 3, 1, 0, "")
TRUTHTABLE_START(TTL_7411_GATE, 3, 1, "")
TT_HEAD("A,B,C|Q ")
TT_LINE("0,X,X|0|15")
TT_LINE("X,0,X|0|15")
@ -640,7 +640,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7416_GATE, 1, 1, 0, "")
TRUTHTABLE_START(TTL_7416_GATE, 1, 1, "")
TT_HEAD(" A | Q ")
TT_LINE(" 0 | 1 |15")
TT_LINE(" 1 | 0 |23")
@ -648,7 +648,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XXOC")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7420_GATE, 4, 1, 0, "")
TRUTHTABLE_START(TTL_7420_GATE, 4, 1, "")
TT_HEAD("A,B,C,D|Q ")
TT_LINE("0,X,X,X|1|22")
TT_LINE("X,0,X,X|1|22")
@ -658,7 +658,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7420_NAND, 4, 1, 0, "A,B,C,D")
TRUTHTABLE_START(TTL_7420_NAND, 4, 1, "A,B,C,D")
TT_HEAD("A,B,C,D|Q ")
TT_LINE("0,X,X,X|1|22")
TT_LINE("X,0,X,X|1|22")
@ -668,7 +668,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7425_GATE, 4, 1, 0, "")
TRUTHTABLE_START(TTL_7425_GATE, 4, 1, "")
TT_HEAD("A,B,C,D|Q ")
TT_LINE("1,X,X,X|0|15")
TT_LINE("X,1,X,X|0|15")
@ -678,7 +678,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7425_NOR, 4, 1, 0, "A,B,C,D")
TRUTHTABLE_START(TTL_7425_NOR, 4, 1, "A,B,C,D")
TT_HEAD("A,B,C,D|Q ")
TT_LINE("1,X,X,X|0|15")
TT_LINE("X,1,X,X|0|15")
@ -688,7 +688,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7427_GATE, 3, 1, 0, "")
TRUTHTABLE_START(TTL_7427_GATE, 3, 1, "")
TT_HEAD("A,B,C|Q ")
TT_LINE("1,X,X|0|15")
TT_LINE("X,1,X|0|15")
@ -697,7 +697,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7427_NOR, 3, 1, 0, "A,B,C")
TRUTHTABLE_START(TTL_7427_NOR, 3, 1, "A,B,C")
TT_HEAD("A,B,C|Q ")
TT_LINE("1,X,X|0|15")
TT_LINE("X,1,X|0|15")
@ -706,7 +706,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7430_GATE, 8, 1, 0, "")
TRUTHTABLE_START(TTL_7430_GATE, 8, 1, "")
TT_HEAD("A,B,C,D,E,F,G,H|Q ")
TT_LINE("0,X,X,X,X,X,X,X|1|22")
TT_LINE("X,0,X,X,X,X,X,X|1|22")
@ -720,7 +720,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7430_NAND, 8, 1, 0, "A,B,C,D,E,F,G,H")
TRUTHTABLE_START(TTL_7430_NAND, 8, 1, "A,B,C,D,E,F,G,H")
TT_HEAD("A,B,C,D,E,F,G,H|Q ")
TT_LINE("0,X,X,X,X,X,X,X|1|22")
TT_LINE("X,0,X,X,X,X,X,X|1|22")
@ -734,7 +734,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7432_GATE, 2, 1, 0, "")
TRUTHTABLE_START(TTL_7432_GATE, 2, 1, "")
TT_HEAD("A,B|Q ")
TT_LINE("1,X|1|22")
TT_LINE("X,1|1|22")
@ -742,7 +742,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7432_OR, 2, 1, 0, "A,B")
TRUTHTABLE_START(TTL_7432_OR, 2, 1, "A,B")
TT_HEAD("A,B|Q ")
TT_LINE("1,X|1|22")
TT_LINE("X,1|1|22")
@ -754,7 +754,7 @@ NETLIST_START(TTL74XX_lib)
* Netlist currently does not model over currents (should it ever?)
*/
TRUTHTABLE_START(TTL_7437_GATE, 2, 1, 0, "")
TRUTHTABLE_START(TTL_7437_GATE, 2, 1, "")
TT_HEAD("A,B|Q ")
TT_LINE("0,X|1|22")
TT_LINE("X,0|1|22")
@ -762,7 +762,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7437_NAND, 2, 1, 0, "A,B")
TRUTHTABLE_START(TTL_7437_NAND, 2, 1, "A,B")
TT_HEAD("A,B|Q ")
TT_LINE("0,X|1|22")
TT_LINE("X,0|1|22")
@ -770,7 +770,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7486_GATE, 2, 1, 0, "")
TRUTHTABLE_START(TTL_7486_GATE, 2, 1, "")
TT_HEAD("A,B|Q ")
TT_LINE("0,0|0|15")
TT_LINE("0,1|1|22")
@ -779,7 +779,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
TRUTHTABLE_START(TTL_7486_XOR, 2, 1, 0, "A,B")
TRUTHTABLE_START(TTL_7486_XOR, 2, 1, "A,B")
TT_HEAD("A,B|Q ")
TT_LINE("0,0|0|15")
TT_LINE("0,1|1|22")

View File

@ -189,7 +189,6 @@ netlist_t::netlist_t(const pstring &aname)
: m_state()
, m_time(netlist_time::zero())
, m_queue(*this)
, m_use_deactivate(0)
, m_mainclock(nullptr)
, m_solver(nullptr)
, m_gnd(nullptr)
@ -218,6 +217,14 @@ nl_double netlist_t::gmin() const
return solver()->gmin();
}
void netlist_t::register_dev(plib::owned_ptr<device_t> dev)
{
for (auto & d : m_devices)
if (d->name() == dev->name())
log().fatal("Error adding {1} to device list. Duplicate name \n", d->name());
m_devices.push_back(std::move(dev));
}
void netlist_t::start()
{
/* load the library ... */
@ -226,42 +233,6 @@ void netlist_t::start()
m_lib = plib::palloc<plib::dynlib>(libpath);
/* make sure the solver and parameters are started first! */
for (auto & e : setup().m_device_factory)
{
if ( setup().factory().is_class<devices::NETLIB_NAME(mainclock)>(e.second)
|| setup().factory().is_class<devices::NETLIB_NAME(solver)>(e.second)
|| setup().factory().is_class<devices::NETLIB_NAME(gnd)>(e.second)
|| setup().factory().is_class<devices::NETLIB_NAME(netlistparams)>(e.second))
{
auto dev = plib::owned_ptr<device_t>(e.second->Create(*this, e.first));
setup().register_dev(std::move(dev));
}
}
log().debug("Searching for mainclock and solver ...\n");
m_mainclock = get_single_device<devices::NETLIB_NAME(mainclock)>("mainclock");
m_solver = get_single_device<devices::NETLIB_NAME(solver)>("solver");
m_gnd = get_single_device<devices::NETLIB_NAME(gnd)>("gnd");
m_params = get_single_device<devices::NETLIB_NAME(netlistparams)>("parameter");
m_use_deactivate = (m_params->m_use_deactivate.Value() ? true : false);
/* create devices */
for (auto & e : setup().m_device_factory)
{
if ( !setup().factory().is_class<devices::NETLIB_NAME(mainclock)>(e.second)
&& !setup().factory().is_class<devices::NETLIB_NAME(solver)>(e.second)
&& !setup().factory().is_class<devices::NETLIB_NAME(gnd)>(e.second)
&& !setup().factory().is_class<devices::NETLIB_NAME(netlistparams)>(e.second))
{
auto dev = plib::owned_ptr<device_t>(e.second->Create(*this, e.first));
setup().register_dev(std::move(dev));
}
}
}
@ -334,6 +305,8 @@ void netlist_t::process_queue(const netlist_time &delta)
m_queue.push(stop, nullptr);
m_stat_mainloop.start();
if (m_mainclock == nullptr)
{
queue_t::entry_t e(m_queue.pop());
@ -341,7 +314,7 @@ void netlist_t::process_queue(const netlist_time &delta)
while (e.m_object != nullptr)
{
e.m_object->update_devs();
add_to_stat(m_perf_out_processed, 1);
m_perf_out_processed.inc();
e = m_queue.pop();
m_time = e.m_exec_time;
}
@ -367,27 +340,67 @@ void netlist_t::process_queue(const netlist_time &delta)
if (e.m_object == nullptr)
break;
e.m_object->update_devs();
add_to_stat(m_perf_out_processed, 1);
m_perf_out_processed.inc();
}
mc_net.set_time(mc_time);
}
m_stat_mainloop.stop();
}
void netlist_t::print_stats() const
{
#if (NL_KEEP_STATISTICS)
if (nperftime_t::enabled)
{
for (auto & entry : m_devices)
std::vector<size_t> index;
for (size_t i=0; i<m_devices.size(); i++)
index.push_back(i);
std::sort(index.begin(), index.end(),
[&](size_t i1, size_t i2) { return m_devices[i1]->m_stat_total_time.total() < m_devices[i2]->m_stat_total_time.total(); });
nperftime_t::type total_time(0);
uint_least64_t total_count(0);
for (auto & j : index)
{
log().verbose("Device {1:20} : {2:12} {3:12} {4:15}", entry->name(),
entry->stat_call_count, entry->stat_update_count,
(long int) entry->stat_total_time / (entry->stat_update_count + 1));
auto entry = m_devices[j].get();
log().verbose("Device {1:20} : {2:12} {3:12} {4:15} {5:12}", entry->name(),
entry->m_stat_call_count(), entry->m_stat_total_time.count(),
entry->m_stat_total_time.total(), entry->m_stat_inc_active());
total_time += entry->m_stat_total_time.total();
total_count += entry->m_stat_total_time.count();
}
log().verbose("Queue Pushes {1:15}", queue().m_prof_call);
log().verbose("Queue Moves {1:15}", queue().m_prof_sortmove);
nperftime_t overhead;
nperftime_t test;
overhead.start();
for (int j=0; j<100000;j++)
{
test.start();
test.stop();
}
overhead.stop();
uint_least64_t total_overhead = (uint_least64_t) overhead()*(uint_least64_t)total_count/(uint_least64_t)200000;
log().verbose("Queue Pushes {1:15}", queue().m_prof_call());
log().verbose("Queue Moves {1:15}", queue().m_prof_sortmove());
log().verbose("Total loop {1:15}", m_stat_mainloop());
/* Only one serialization should be counted in total time */
/* But two are contained in m_stat_mainloop */
log().verbose("Total devices {1:15}", total_time);
log().verbose("");
log().verbose("Take the next lines with a grain of salt. They depend on the measurement implementation.");
log().verbose("Total overhead {1:15}", total_overhead);
log().verbose("Overhead per pop {1:11}", (m_stat_mainloop()-2*total_overhead - (total_time - total_overhead ))/queue().m_prof_call());
log().verbose("");
for (auto &entry : m_devices)
{
if (entry->m_stat_inc_active() > 3 * entry->m_stat_total_time.count())
log().verbose("HINT({}, NO_DEACTIVATE)", entry->name());
}
}
#endif
}
// ----------------------------------------------------------------------------------------
@ -419,10 +432,9 @@ core_device_t::core_device_t(netlist_t &owner, const pstring &name)
: object_t(name)
, logic_family_t()
, netlist_ref(owner)
#if (NL_KEEP_STATISTICS)
, stat_total_time(0)
, stat_update_count(0)
, stat_call_count(0)
, m_hint_deactivate(false)
#if (NL_PMF_TYPE > NL_PMF_TYPE_VIRTUAL)
, m_static_update()
#endif
{
if (logic_family() == nullptr)
@ -433,10 +445,9 @@ core_device_t::core_device_t(core_device_t &owner, const pstring &name)
: object_t(owner.name() + "." + name)
, logic_family_t()
, netlist_ref(owner.netlist())
#if (NL_KEEP_STATISTICS)
, stat_total_time(0)
, stat_update_count(0)
, stat_call_count(0)
, m_hint_deactivate(false)
#if (NL_PMF_TYPE > NL_PMF_TYPE_VIRTUAL)
, m_static_update()
#endif
{
set_logic_family(owner.logic_family());
@ -586,14 +597,10 @@ void net_t::inc_active(core_terminal_t &term)
{
m_active++;
m_list_active.push_front(&term);
nl_assert(m_active <= num_cons());
nl_assert(m_active <= (int) num_cons());
if (m_active == 1)
{
if (netlist().use_deactivate())
{
railterminal().device().do_inc_active();
//m_cur_Q = m_new_Q;
}
railterminal().device().do_inc_active();
if (m_in_queue == 0)
{
if (m_time > netlist().time())
@ -607,8 +614,6 @@ void net_t::inc_active(core_terminal_t &term)
m_in_queue = 2;
}
}
//else if (netlist().use_deactivate())
// m_cur_Q = m_new_Q;
}
}
@ -617,7 +622,7 @@ void net_t::dec_active(core_terminal_t &term)
--m_active;
nl_assert(m_active >= 0);
m_list_active.remove(&term);
if (m_active == 0 && netlist().use_deactivate())
if (m_active == 0)
railterminal().device().do_dec_active();
}
@ -656,7 +661,7 @@ void net_t::update_devs()
for (auto & p : m_list_active)
{
inc_stat(p.device().stat_call_count);
p.device().m_stat_call_count.inc();
if ((p.state() & mask) != 0)
p.device().update_dev();
}
@ -945,10 +950,6 @@ nl_double param_model_t::model_value(const pstring &entity)
}
} // namespace
namespace netlist
{
namespace devices
{

View File

@ -892,10 +892,9 @@ namespace netlist
void update_dev()
{
begin_timing(stat_total_time);
inc_stat(stat_update_count);
m_stat_total_time.start();
do_update();
end_timing(stat_total_time);
m_stat_total_time.stop();
}
void do_update() NOEXCEPT
@ -912,9 +911,21 @@ namespace netlist
void set_delegate_pointer();
void stop_dev();
void do_inc_active() { inc_active(); }
void do_dec_active() { dec_active(); }
void do_inc_active()
{
if (m_hint_deactivate)
{
m_stat_inc_active.inc();
inc_active();
}
}
void do_dec_active()
{
if (m_hint_deactivate)
dec_active();
}
void do_reset() { reset(); }
void set_hint_deactivate(bool v) { m_hint_deactivate = v; }
netlist_sig_t INPLOGIC_PASSIVE(logic_input_t &inp);
netlist_sig_t INPLOGIC(const logic_input_t &inp) const
@ -928,12 +939,10 @@ namespace netlist
nl_double TERMANALOG(const terminal_t &term) const { return term.net().Q_Analog(); }
void OUTANALOG(analog_output_t &out, const nl_double val) { out.set_Q(val); }
#if (NL_KEEP_STATISTICS)
/* stats */
plib::ticks_t stat_total_time;
int_fast32_t stat_update_count;
int_fast32_t stat_call_count;
#endif
nperftime_t m_stat_total_time;
nperfcount_t m_stat_call_count;
nperfcount_t m_stat_inc_active;
protected:
@ -953,34 +962,18 @@ namespace netlist
virtual bool needs_update_after_param_change() const { return false; }
private:
#if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF)
bool m_hint_deactivate;
#if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF)
typedef void (core_device_t::*net_update_delegate)();
#elif ((NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV) || (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL))
#elif ((NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV) || (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL))
using net_update_delegate = MEMBER_ABI void (*)(core_device_t *);
#endif
#endif
#if (NL_PMF_TYPE > NL_PMF_TYPE_VIRTUAL)
net_update_delegate m_static_update;
#endif
};
// -----------------------------------------------------------------------------
// param_ref_t
// -----------------------------------------------------------------------------
struct param_ref_t
{
param_ref_t(const pstring name, core_device_t &device, param_t &param)
: m_name(name)
, m_device(device)
, m_param(param)
{ }
pstring m_name;
core_device_t &m_device;
param_t &m_param;
};
// -----------------------------------------------------------------------------
// device_t
// -----------------------------------------------------------------------------
@ -1071,8 +1064,9 @@ namespace netlist
// -----------------------------------------------------------------------------
class netlist_t : public plib::plog_dispatch_intf //, public device_owner_t
class netlist_t : public plib::plog_dispatch_intf
{
friend class setup_t;
P_PREVENT_COPYING(netlist_t)
public:
@ -1097,13 +1091,14 @@ namespace netlist
void process_queue(const netlist_time &delta);
void abort_current_queue_slice() { m_queue.retime(m_time, nullptr); }
bool use_deactivate() const { return m_use_deactivate; }
void rebuild_lists(); /* must be called after post_load ! */
void set_setup(setup_t *asetup) { m_setup = asetup; }
setup_t &setup() { return *m_setup; }
void register_dev(plib::owned_ptr<device_t> dev);
net_t *find_net(const pstring &name);
template<class device_class>
@ -1165,22 +1160,21 @@ namespace netlist
/* sole use is to manage lifetime of family objects */
std::vector<std::pair<pstring, std::unique_ptr<logic_family_desc_t>>> m_family_cache;
protected:
protected:
#if (NL_KEEP_STATISTICS)
// performance
int m_perf_out_processed;
int m_perf_inp_processed;
int m_perf_inp_active;
#endif
nperfcount_t m_perf_out_processed;
nperfcount_t m_perf_inp_processed;
nperfcount_t m_perf_inp_active;
private:
plib::state_manager_t m_state;
/* mostly rw */
netlist_time m_time;
queue_t m_queue;
/* mostly rw */
bool m_use_deactivate;
nperftime_t m_stat_mainloop;
/* mostly ro */
devices::NETLIB_NAME(mainclock) * m_mainclock;
devices::NETLIB_NAME(solver) * m_solver;

View File

@ -11,6 +11,7 @@
#include <cstdint>
#include "plib/pconfig.h"
#include "plib/pchrono.h"
//============================================================
// SETUP
@ -111,18 +112,16 @@
// Performance tracking
//============================================================
namespace netlist
{
#if NL_KEEP_STATISTICS
#define add_to_stat(v,x) do { v += (x); } while (0)
#define inc_stat(v) add_to_stat(v, 1)
#define begin_timing(v) do { v -= plib::profile_ticks(); } while (0)
#define end_timing(v) do { v += plib::profile_ticks(); } while (0)
using nperftime_t = plib::timer<plib::exact_ticks, true>;
using nperfcount_t = plib::counter<true>;
#else
#define add_to_stat(v,x) do { } while (0)
#define inc_stat(v) add_to_stat(v, 1)
#define begin_timing(v) do { } while (0)
#define end_timing(v) do { } while (0)
using nperftime_t = plib::chrono::timer<plib::chrono::exact_ticks, false>;
using nperfcount_t = plib::chrono::counter<false>;
#endif
}
//============================================================
// General
//============================================================

View File

@ -65,7 +65,7 @@ namespace netlist
}
};
class factory_list_t : public std::vector<plib::owned_ptr<base_factory_t>>
class factory_list_t : public std::vector<std::unique_ptr<base_factory_t>>
{
public:
factory_list_t(setup_t &m_setup);
@ -75,10 +75,10 @@ namespace netlist
void register_device(const pstring &name, const pstring &classname,
const pstring &def_param)
{
register_device(plib::owned_ptr<base_factory_t>::Create<factory_t<device_class>>(name, classname, def_param));
register_device(std::unique_ptr<base_factory_t>(new factory_t<device_class>(name, classname, def_param)));
}
void register_device(plib::owned_ptr<base_factory_t> factory)
void register_device(std::unique_ptr<base_factory_t> factory)
{
for (auto & e : *this)
if (e->name() == factory->name())
@ -104,14 +104,14 @@ namespace netlist
// factory_creator_ptr_t
// -----------------------------------------------------------------------------
using factory_creator_ptr_t = plib::owned_ptr<base_factory_t> (*)(const pstring &name, const pstring &classname,
using factory_creator_ptr_t = std::unique_ptr<base_factory_t> (*)(const pstring &name, const pstring &classname,
const pstring &def_param);
template <typename T>
plib::owned_ptr<base_factory_t> factory_creator_t(const pstring &name, const pstring &classname,
std::unique_ptr<base_factory_t> factory_creator_t(const pstring &name, const pstring &classname,
const pstring &def_param)
{
return plib::owned_ptr<base_factory_t>::Create<factory_t<T>>(name, classname, def_param);
return std::unique_ptr<base_factory_t>(new factory_t<T>(name, classname, def_param));
}
}

View File

@ -10,10 +10,11 @@
#ifndef NLLISTS_H_
#define NLLISTS_H_
#include <atomic>
#include "nl_config.h"
#include "plib/plists.h"
#include <atomic>
#include "plib/pchrono.h"
// ----------------------------------------------------------------------------------------
@ -36,10 +37,6 @@ namespace netlist
timed_queue(unsigned list_size)
: m_list(list_size)
#if (NL_KEEP_STATISTICS)
, m_prof_sortmove(0)
, m_prof_call(0)
#endif
{
#if HAS_OPENMP && USE_OPENMP
m_lock = 0;
@ -60,11 +57,11 @@ namespace netlist
for (; t > (i - 1)->m_exec_time; --i)
{
*(i) = *(i-1);
inc_stat(m_prof_sortmove);
m_prof_sortmove.inc();
}
*i = { t, o };
++m_end;
inc_stat(m_prof_call);
m_prof_call.inc();
#if HAS_OPENMP && USE_OPENMP
m_lock = 0;
#endif
@ -132,12 +129,9 @@ namespace netlist
std::vector<entry_t> m_list;
public:
#if (NL_KEEP_STATISTICS)
// profiling
std::size_t m_prof_sortmove;
std::size_t m_prof_call;
#endif
nperfcount_t m_prof_sortmove;
nperfcount_t m_prof_call;
};
}

View File

@ -45,6 +45,7 @@ bool parser_t::parse(const pstring nlname)
m_tok_NET_C = register_token("NET_C");
m_tok_FRONTIER = register_token("OPTIMIZE_FRONTIER");
m_tok_PARAM = register_token("PARAM");
m_tok_HINT = register_token("HINT");
m_tok_NET_MODEL = register_token("NET_MODEL");
m_tok_INCLUDE = register_token("INCLUDE");
m_tok_LOCAL_SOURCE = register_token("LOCAL_SOURCE");
@ -120,6 +121,8 @@ void parser_t::parse_netlist(ATTR_UNUSED const pstring &nlname)
frontier();
else if (token.is(m_tok_PARAM))
netdev_param();
else if (token.is(m_tok_HINT))
netdev_hint();
else if (token.is(m_tok_NET_MODEL))
net_model();
else if (token.is(m_tok_SUBMODEL))
@ -153,13 +156,16 @@ void parser_t::net_truthtable_start()
require_token(m_tok_comma);
unsigned no = get_number_long();
require_token(m_tok_comma);
unsigned hs = get_number_long();
require_token(m_tok_comma);
pstring def_param = get_string();
require_token(m_tok_param_right);
plib::owned_ptr<netlist::devices::netlist_base_factory_truthtable_t> ttd = netlist::devices::nl_tt_factory_create(ni, no, hs,
name, name, "+" + def_param);
netlist::tt_desc desc;
desc.classname = name;
desc.name = name;
desc.ni = ni;
desc.no = no;
desc.def_param = "+" + def_param;
desc.family = "";
while (true)
{
@ -168,19 +174,19 @@ void parser_t::net_truthtable_start()
if (token.is(m_tok_TT_HEAD))
{
require_token(m_tok_param_left);
ttd->m_desc.push_back(get_string());
desc.desc.push_back(get_string());
require_token(m_tok_param_right);
}
else if (token.is(m_tok_TT_LINE))
{
require_token(m_tok_param_left);
ttd->m_desc.push_back(get_string());
desc.desc.push_back(get_string());
require_token(m_tok_param_right);
}
else if (token.is(m_tok_TT_FAMILY))
{
require_token(m_tok_param_left);
ttd->m_family = m_setup.family_from_model(get_string());
desc.family = get_string();
require_token(m_tok_param_right);
}
else
@ -188,7 +194,7 @@ void parser_t::net_truthtable_start()
require_token(token, m_tok_TRUTHTABLE_END);
require_token(m_tok_param_left);
require_token(m_tok_param_right);
m_setup.factory().register_device(std::move(ttd));
netlist::devices::tt_factory_create(m_setup, desc);
return;
}
}
@ -339,6 +345,15 @@ void parser_t::netdev_param()
require_token(m_tok_param_right);
}
void parser_t::netdev_hint()
{
pstring dev(get_identifier());
require_token(m_tok_comma);
pstring hint(get_identifier());
m_setup.register_param(dev + ".HINT_" + hint, 1);
require_token(m_tok_param_right);
}
void parser_t::device(const pstring &dev_type)
{
if (m_setup.is_library_item(dev_type))
@ -431,7 +446,7 @@ nl_double parser_t::eval_param(const token_t tok)
val = tok.str();
ret = val.as_double(&e);
if (e)
error("Error with parameter ...\n");
error(plib::pfmt("Error with parameter {1}...\n")(val));
}
return ret * facs[f];

View File

@ -27,6 +27,7 @@ namespace netlist
void net_alias();
void dippins();
void netdev_param();
void netdev_hint();
void net_c();
void frontier();
void device(const pstring &dev_type);
@ -54,6 +55,7 @@ namespace netlist
token_id_t m_tok_DIPPINS;
token_id_t m_tok_FRONTIER;
token_id_t m_tok_PARAM;
token_id_t m_tok_HINT;
token_id_t m_tok_NET_MODEL;
token_id_t m_tok_NETLIST_START;
token_id_t m_tok_NETLIST_END;

View File

@ -16,6 +16,7 @@
#include "nl_parser.h"
#include "nl_factory.h"
#include "devices/net_lib.h"
#include "devices/nld_truthtable.h"
#include "devices/nlid_system.h"
#include "analog/nld_twoterm.h"
#include "solver/nld_solver.h"
@ -99,15 +100,6 @@ void setup_t::namespace_pop()
m_namespace_stack.pop();
}
void setup_t::register_dev(plib::owned_ptr<device_t> dev)
{
for (auto & d : netlist().m_devices)
if (d->name() == dev->name())
log().fatal("Error adding {1} to device list. Duplicate name \n", d->name());
netlist().m_devices.push_back(std::move(dev));
}
void setup_t::register_lib_entry(const pstring &name)
{
if (plib::container::contains(m_lib, name))
@ -453,7 +445,7 @@ devices::nld_base_proxy *setup_t::get_d_a_proxy(core_terminal_t &out)
proxy = new_proxy.get();
register_dev(std::move(new_proxy));
netlist().register_dev(std::move(new_proxy));
}
return proxy;
}
@ -471,7 +463,7 @@ void setup_t::connect_input_output(core_terminal_t &in, core_terminal_t &out)
proxy->m_Q.net().register_con(in);
out.net().register_con(proxy->m_I);
register_dev(std::move(proxy));
netlist().register_dev(std::move(proxy));
}
else if (out.is_logic() && in.is_analog())
@ -514,7 +506,7 @@ void setup_t::connect_terminal_input(terminal_t &term, core_terminal_t &inp)
else
proxy->m_Q.net().register_con(inp);
register_dev(std::move(proxy));
netlist().register_dev(std::move(proxy));
}
else
{
@ -781,13 +773,77 @@ void setup_t::start_devices()
auto nc = factory().factory_by_name("LOG")->Create(netlist(), name);
register_link(name + ".I", ll);
log().debug(" dynamic link {1}: <{2}>\n",ll, name);
register_dev(std::move(nc));
netlist().register_dev(std::move(nc));
}
}
/* make sure the solver and parameters are started first! */
for (auto & e : m_device_factory)
{
if ( factory().is_class<devices::NETLIB_NAME(mainclock)>(e.second)
|| factory().is_class<devices::NETLIB_NAME(solver)>(e.second)
|| factory().is_class<devices::NETLIB_NAME(gnd)>(e.second)
|| factory().is_class<devices::NETLIB_NAME(netlistparams)>(e.second))
{
auto dev = plib::owned_ptr<device_t>(e.second->Create(netlist(), e.first));
netlist().register_dev(std::move(dev));
}
}
log().debug("Searching for mainclock and solver ...\n");
netlist().m_mainclock = netlist().get_single_device<devices::NETLIB_NAME(mainclock)>("mainclock");
netlist().m_solver = netlist().get_single_device<devices::NETLIB_NAME(solver)>("solver");
netlist().m_gnd = netlist().get_single_device<devices::NETLIB_NAME(gnd)>("gnd");
netlist().m_params = netlist().get_single_device<devices::NETLIB_NAME(netlistparams)>("parameter");
/* create devices */
for (auto & e : m_device_factory)
{
if ( !factory().is_class<devices::NETLIB_NAME(mainclock)>(e.second)
&& !factory().is_class<devices::NETLIB_NAME(solver)>(e.second)
&& !factory().is_class<devices::NETLIB_NAME(gnd)>(e.second)
&& !factory().is_class<devices::NETLIB_NAME(netlistparams)>(e.second))
{
auto dev = plib::owned_ptr<device_t>(e.second->Create(netlist(), e.first));
netlist().register_dev(std::move(dev));
}
}
bool use_deactivate = (netlist().m_params->m_use_deactivate.Value() ? true : false);
for (auto &d : netlist().m_devices)
{
if (use_deactivate)
{
auto p = m_param_values.find(d->name() + ".HINT_NO_DEACTIVATE");
if (p != m_param_values.end())
{
//FIXME: Error checking
auto v = p->second.as_long();
d->set_hint_deactivate(!v);
}
}
else
d->set_hint_deactivate(false);
}
netlist().start();
}
plib::plog_base<NL_DEBUG> &setup_t::log()
{
return netlist().log();
}
const plib::plog_base<NL_DEBUG> &setup_t::log() const
{
return netlist().log();
}
// ----------------------------------------------------------------------------------------
// Model / family
// ----------------------------------------------------------------------------------------
@ -926,13 +982,19 @@ nl_double setup_t::model_value(model_map_t &map, const pstring &entity)
return tmp.as_double() * factor;
}
void setup_t::tt_factory_create(tt_desc &desc)
{
devices::tt_factory_create(*this, desc);
}
// ----------------------------------------------------------------------------------------
// Sources
// ----------------------------------------------------------------------------------------
void setup_t::include(const pstring &netlist_name)
{
for (auto source : m_sources)
for (auto &source : m_sources)
{
if (source->parse(*this, netlist_name))
return;

View File

@ -11,7 +11,13 @@
#include <memory>
#include <stack>
#include <unordered_map>
#include <vector>
#include "plib/pstring.h"
#include "plib/palloc.h"
#include "plib/pfmtlog.h"
#include "plib/putil.h"
#include "nl_config.h"
#include "nl_base.h"
#include "nl_factory.h"
@ -34,51 +40,130 @@
#define NET_REGISTER_DEV(type, name) \
setup.register_dev(# type, # name);
#define NET_CONNECT(name, input, output) \
#define NET_CONNECT(name, input, output) \
setup.register_link(# name "." # input, # output);
#define NET_C(term1, ...) \
#define NET_C(term1, ...) \
setup.register_link_arr( # term1 ", " # __VA_ARGS__);
#define PARAM(name, val) \
#define PARAM(name, val) \
setup.register_param(# name, val);
#define NETDEV_PARAMI(name, param, val) \
#define HINT(name, val) \
setup.register_param(# name ".HINT_" # val, 1);
#define NETDEV_PARAMI(name, param, val) \
setup.register_param(# name "." # param, val);
#define NETLIST_NAME(name) netlist ## _ ## name
#define NETLIST_EXTERNAL(name) \
#define NETLIST_EXTERNAL(name) \
void NETLIST_NAME(name)(netlist::setup_t &setup);
#define NETLIST_START(name) \
void NETLIST_NAME(name)(netlist::setup_t &setup) \
#define NETLIST_START(name) \
void NETLIST_NAME(name)(netlist::setup_t &setup) \
{
#define NETLIST_END() }
#define LOCAL_SOURCE(name) \
setup.register_source(std::make_shared<netlist::source_proc_t>(# name, &NETLIST_NAME(name)));
#define LOCAL_SOURCE(name) \
setup.register_source(plib::make_unique_base<netlist::source_t, netlist::source_proc_t>(# name, &NETLIST_NAME(name)));
#define LOCAL_LIB_ENTRY(name) \
LOCAL_SOURCE(name) \
#define LOCAL_LIB_ENTRY(name) \
LOCAL_SOURCE(name) \
setup.register_lib_entry(# name);
#define INCLUDE(name) \
#define INCLUDE(name) \
setup.include(# name);
#define SUBMODEL(model, name) \
setup.namespace_push(# name); \
NETLIST_NAME(model)(setup); \
#define SUBMODEL(model, name) \
setup.namespace_push(# name); \
NETLIST_NAME(model)(setup); \
setup.namespace_pop();
// ----------------------------------------------------------------------------------------
// netlist_setup_t
// ----------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// truthtable defines
// -----------------------------------------------------------------------------
#define TRUTHTABLE_START(cname, in, out, def_params) \
{ \
netlist::tt_desc desc; \
desc.name = #cname ; \
desc.classname = #cname ; \
desc.ni = in; \
desc.no = out; \
desc.def_param = pstring("+") + def_params; \
desc.family = "";
#define TT_HEAD(x) \
desc.desc.push_back(x);
#define TT_LINE(x) \
desc.desc.push_back(x);
#define TT_FAMILY(x) \
desc.family = x;
#define TRUTHTABLE_END() \
netlist::devices::tt_factory_create(setup, desc); \
}
namespace netlist
{
// Forward definition so we keep nl_factory.h out of the public
class factory_list_t;
// -----------------------------------------------------------------------------
// truthtable desc
// -----------------------------------------------------------------------------
struct tt_desc
{
pstring name;
pstring classname;
unsigned ni;
unsigned no;
pstring def_param;
plib::pstring_vector_t desc;
pstring family;
};
// -----------------------------------------------------------------------------
// param_ref_t
// -----------------------------------------------------------------------------
struct param_ref_t
{
param_ref_t(const pstring name, core_device_t &device, param_t &param)
: m_name(name)
, m_device(device)
, m_param(param)
{ }
pstring m_name;
core_device_t &m_device;
param_t &m_param;
};
// ----------------------------------------------------------------------------------------
// A Generic netlist sources implementation
// ----------------------------------------------------------------------------------------
class source_t
{
public:
using list_t = std::vector<std::unique_ptr<source_t>>;
source_t()
{}
virtual ~source_t() { }
virtual bool parse(setup_t &setup, const pstring &name) = 0;
private:
};
// ----------------------------------------------------------------------------------------
// setup_t
// ----------------------------------------------------------------------------------------
class setup_t
@ -86,24 +171,6 @@ namespace netlist
P_PREVENT_COPYING(setup_t)
public:
// ----------------------------------------------------------------------------------------
// A Generic netlist sources implementation
// ----------------------------------------------------------------------------------------
class source_t
{
public:
using list_t = std::vector<std::shared_ptr<source_t>>;
source_t()
{}
virtual ~source_t() { }
virtual bool parse(setup_t &setup, const pstring &name) = 0;
private:
};
using link_t = std::pair<pstring, pstring>;
setup_t(netlist_t &netlist);
@ -118,7 +185,6 @@ namespace netlist
void register_term(core_terminal_t &obj);
void register_dev(plib::owned_ptr<device_t> dev);
void register_dev(const pstring &classname, const pstring &name);
void register_lib_entry(const pstring &name);
@ -160,10 +226,9 @@ namespace netlist
/* register a source */
template <class C>
void register_source(std::shared_ptr<C> src)
void register_source(std::unique_ptr<source_t> &&src)
{
m_sources.push_back(std::static_pointer_cast<source_t>(src));
m_sources.push_back(std::move(src));
}
factory_list_t &factory() { return m_factory; }
@ -179,11 +244,15 @@ namespace netlist
void model_parse(const pstring &model, model_map_t &map);
plib::plog_base<NL_DEBUG> &log() { return netlist().log(); }
const plib::plog_base<NL_DEBUG> &log() const { return netlist().log(); }
plib::plog_base<NL_DEBUG> &log();
const plib::plog_base<NL_DEBUG> &log() const;
std::vector<std::pair<pstring, base_factory_t *>> m_device_factory;
/* FIXME: truth table trampoline */
void tt_factory_create(tt_desc &desc);
protected:
private:
@ -232,12 +301,12 @@ namespace netlist
// ----------------------------------------------------------------------------------------
class source_string_t : public setup_t::source_t
class source_string_t : public source_t
{
public:
source_string_t(const pstring &source)
: setup_t::source_t(), m_str(source)
: source_t(), m_str(source)
{
}
@ -247,12 +316,12 @@ namespace netlist
pstring m_str;
};
class source_file_t : public setup_t::source_t
class source_file_t : public source_t
{
public:
source_file_t(const pstring &filename)
: setup_t::source_t(), m_filename(filename)
: source_t(), m_filename(filename)
{
}
@ -262,11 +331,11 @@ namespace netlist
pstring m_filename;
};
class source_mem_t : public setup_t::source_t
class source_mem_t : public source_t
{
public:
source_mem_t(const char *mem)
: setup_t::source_t(), m_str(mem)
: source_t(), m_str(mem)
{
}
@ -276,11 +345,11 @@ namespace netlist
pstring m_str;
};
class source_proc_t : public setup_t::source_t
class source_proc_t : public source_t
{
public:
source_proc_t(pstring name, void (*setup_func)(setup_t &))
: setup_t::source_t(),
: source_t(),
m_setup_func(setup_func),
m_setup_func_name(name)
{

View File

@ -42,7 +42,7 @@ namespace netlist
constexpr explicit ptime(const double t) = delete;
//: m_time((internal_type) ( t * (double) resolution)) { }
constexpr explicit ptime(const internal_type nom, const internal_type den)
constexpr explicit ptime(const internal_type nom, const internal_type den) NOEXCEPT
: m_time(nom * (resolution / den)) { }
ptime &operator=(const ptime rhs) { m_time = rhs.m_time; return *this; }
@ -100,7 +100,7 @@ namespace netlist
friend bool operator!=(const ptime &lhs, const ptime &rhs)
{
return lhs.m_time != rhs.m_time;
return !(lhs == rhs);
}
constexpr internal_type as_raw() const { return m_time; }
@ -109,16 +109,16 @@ namespace netlist
// for save states ....
internal_type *get_internaltype_ptr() { return &m_time; }
static inline constexpr ptime from_nsec(const internal_type ns) { return ptime(ns, UINT64_C(1000000000)); }
static inline constexpr ptime from_usec(const internal_type us) { return ptime(us, UINT64_C(1000000)); }
static inline constexpr ptime from_msec(const internal_type ms) { return ptime(ms, UINT64_C(1000)); }
static inline constexpr ptime from_hz(const internal_type hz) { return ptime(1 , hz); }
static inline constexpr ptime from_raw(const internal_type raw) { return ptime(raw, resolution); }
static inline constexpr ptime from_double(const double t) { return ptime((internal_type) ( t * (double) resolution), resolution); }
static constexpr ptime from_nsec(const internal_type ns) { return ptime(ns, UINT64_C(1000000000)); }
static constexpr ptime from_usec(const internal_type us) { return ptime(us, UINT64_C(1000000)); }
static constexpr ptime from_msec(const internal_type ms) { return ptime(ms, UINT64_C(1000)); }
static constexpr ptime from_hz(const internal_type hz) { return ptime(1 , hz); }
static constexpr ptime from_raw(const internal_type raw) { return ptime(raw, resolution); }
static constexpr ptime from_double(const double t) { return ptime((internal_type) ( t * (double) resolution), resolution); }
static inline constexpr ptime zero() { return ptime(0, resolution); }
static inline constexpr ptime quantum() { return ptime(1, resolution); }
static inline constexpr ptime never() { return ptime(plib::numeric_limits<internal_type>::max(), resolution); }
static constexpr ptime zero() { return ptime(0, resolution); }
static constexpr ptime quantum() { return ptime(1, resolution); }
static constexpr ptime never() { return ptime(plib::numeric_limits<internal_type>::max(), resolution); }
private:
internal_type m_time;
};

View File

@ -0,0 +1,55 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
#include <chrono>
#include "pchrono.h"
namespace plib {
namespace chrono {
#if defined(__x86_64__) && !defined(_clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
fast_ticks::type fast_ticks::per_second()
{
static type persec = 0;
if (persec == 0)
{
type x = 0;
system_ticks::type t = system_ticks::start();
system_ticks::type e;
x = -start();
do {
e = system_ticks::stop();
} while (e - t < system_ticks::per_second() / 100 );
x += stop();
persec = (type)(double)((double) x * (double) system_ticks::per_second() / double (e - t));
}
return persec;
}
#if PUSE_ACCURATE_STATS && PHAS_RDTSCP
exact_ticks::type exact_ticks::per_second()
{
static type persec = 0;
if (persec == 0)
{
type x = 0;
system_ticks::type t = system_ticks::start();
system_ticks::type e;
x = -start();
do {
e = system_ticks::stop();
} while (e - t < system_ticks::per_second() / 100 );
x += stop();
persec = (type)(double)((double) x * (double) system_ticks::per_second() / double (e - t));
}
return persec;
}
#endif
#endif
}
}

View File

@ -0,0 +1,213 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
* pchrono.h
*
*/
#ifndef PCHRONO_H_
#define PCHRONO_H_
#include <cstdint>
#include <thread>
#include <chrono>
#include "pconfig.h"
namespace plib {
namespace chrono {
template <typename T>
struct sys_ticks
{
typedef typename T::rep type;
static inline type start() { return T::now().time_since_epoch().count(); }
static inline type stop() { return T::now().time_since_epoch().count(); }
static inline constexpr type per_second() { return T::period::den / T::period::num; }
};
using hires_ticks = sys_ticks<std::chrono::high_resolution_clock>;
using steady_ticks = sys_ticks<std::chrono::steady_clock>;
using system_ticks = sys_ticks<std::chrono::system_clock>;
#if defined(__x86_64__) && !defined(_clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
#if PHAS_RDTSCP
struct fast_ticks
{
typedef int64_t type;
static inline type start()
{
int64_t v;
__asm__ __volatile__ (
"rdtscp;"
"shl $32, %%rdx;"
"or %%rdx, %%rax;"
: "=a"(v) /* outputs */
: /* inputs */
: "%rcx", "%rdx" /* clobbers */
);
return v;
}
static inline type stop()
{
return start();
}
static type per_second();
};
#else
struct fast_ticks
{
typedef int64_t type;
static inline type start()
{
int64_t v;
__asm__ __volatile__ (
"rdtsc;"
"shl $32, %%rdx;"
"or %%rdx, %%rax;"
: "=a"(v) /* outputs */
: /* inputs */
: "%rdx" /* clobbers */
);
return v;
}
static inline type stop()
{
return start();
}
static type per_second();
};
#endif
/* Based on "How to Benchmark Code Execution Times on Intel® IA-32 and IA-64
* Instruction Set Architectures", Intel, 2010
*
*/
#if PUSE_ACCURATE_STATS && PHAS_RDTSCP
/*
* kills performance completely, but is accurate
* cpuid serializes, but clobbers ebx and ecx
*
*/
struct exact_ticks
{
typedef int64_t type;
static inline type start()
{
int64_t v;
__asm__ __volatile__ (
"cpuid;"
//"xor %%eax, %%eax\n\t"
"rdtsc;"
"shl $32, %%rdx;"
"or %%rdx, %%rax;"
: "=a"(v) /* outputs */
: "a"(0x0) /* inputs */
: "%ebx", "%ecx", "%rdx" /* clobbers*/
);
return v;
}
static inline type stop()
{
int64_t v;
__asm__ __volatile__ (
"rdtscp;"
"shl $32, %%rdx;"
"or %%rax, %%rdx;"
"mov %%rdx, %%r10;"
"xor %%eax, %%eax\n\t"
"cpuid;"
"mov %%r10, %%rax;"
: "=a" (v)
:
: "%ebx", "%ecx", "%rdx", "%r10"
);
return v;
}
static type per_second();
};
#else
using exact_ticks = fast_ticks;
#endif
#else
using fast_ticks = hires_ticks;
using exact_ticks = fast_ticks;
#endif
template<bool enabled_>
struct counter
{
counter() : m_count(0) { }
typedef uint_least64_t type;
type operator()() const { return m_count; }
void inc() { ++m_count; }
void reset() { m_count = 0; }
constexpr static bool enabled = enabled_;
private:
type m_count;
};
template<>
struct counter<false>
{
typedef uint_least64_t type;
constexpr type operator()() const { return 0; }
void inc() const { }
void reset() const { }
constexpr static bool enabled = false;
};
template< typename T, bool enabled_ = true>
struct timer
{
typedef typename T::type type;
typedef uint_least64_t ctype;
timer() : m_time(0), m_count(0) { }
type operator()() const { return m_time; }
void start() { m_time -= T::start(); }
void stop() { m_time += T::stop(); ++m_count; }
void reset() { m_time = 0; m_count = 0; }
type average() const { return (m_count == 0) ? 0 : m_time / m_count; }
type total() const { return m_time; }
ctype count() const { return m_count; }
double as_seconds() const { return (double) total() / (double) T::per_second(); }
constexpr static bool enabled = enabled_;
private:
type m_time;
ctype m_count;
};
template<typename T>
struct timer<T, false>
{
typedef typename T::type type;
typedef uint_least64_t ctype;
constexpr type operator()() const { return 0; }
void start() const { }
void stop() const { }
void reset() const { }
constexpr type average() const { return 0; }
constexpr type total() const { return 0; }
constexpr ctype count() const { return 0; }
constexpr double as_seconds() const { return 0.0; }
constexpr static bool enabled = false;
};
} // namespace chrono
} // namespace plib
#endif /* PCHRONO_H_ */

View File

@ -12,9 +12,22 @@
#include <thread>
#include <chrono>
#ifndef PSTANDALONE
#define PSTANDALONE (0)
#endif
/*
* Define this for more accurate measurements if you processor supports
* RDTSCP.
*/
#define PHAS_RDTSCP (1)
/*
* Define this to use accurate timing measurements. Only works
* if PHAS_RDTSCP == 1
*/
#define PUSE_ACCURATE_STATS (1)
/*
* Set this to one if you want to use 128 bit int for ptime.
* This is for tests only.
*/
#define PHAS_INT128 (0)
@ -75,30 +88,6 @@ typedef __int128_t INT128;
namespace plib {
using ticks_t = int64_t;
static inline ticks_t ticks()
{
return std::chrono::high_resolution_clock::now().time_since_epoch().count();
}
static inline ticks_t ticks_per_second()
{
return std::chrono::high_resolution_clock::period::den / std::chrono::high_resolution_clock::period::num;
}
#if defined(__x86_64__) && !defined(_clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
static inline ticks_t profile_ticks()
{
unsigned hi, lo;
__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
}
#else
static inline ticks_t profile_ticks() { return ticks(); }
#endif
/*
* The following class was derived from the MAME delegate.h code.
* It derives a pointer to a member function.

View File

@ -0,0 +1,226 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
* poptions.cpp
*
*/
#include "poptions.h"
namespace plib {
/***************************************************************************
Options
***************************************************************************/
option::option()
: m_short(""), m_long(""), m_help(""), m_has_argument(false)
{}
option::option(options &parent, pstring ashort, pstring along, pstring help, bool has_argument)
: m_short(ashort), m_long(along), m_help(help), m_has_argument(has_argument)
{
parent.register_option(this);
}
option::~option()
{
}
int option_str::parse(pstring argument)
{
m_val = argument;
return 0;
}
int option_str_limit::parse(pstring argument)
{
if (plib::container::contains(m_limit, argument))
{
m_val = argument;
return 0;
}
else
return 1;
}
int option_bool::parse(ATTR_UNUSED pstring argument)
{
m_val = true;
return 0;
}
int option_double::parse(pstring argument)
{
bool err = false;
m_val = argument.as_double(&err);
return (err ? 1 : 0);
}
options::options()
{
}
options::options(option *o[])
{
int i=0;
while (o[i] != nullptr)
{
m_opts.push_back(o[i]);
i++;
}
}
options::~options()
{
m_opts.clear();
}
void options::register_option(option *opt)
{
m_opts.push_back(opt);
}
int options::parse(int argc, char *argv[])
{
m_app = argv[0];
for (int i=1; i<argc; )
{
pstring arg(argv[i]);
option *opt = nullptr;
pstring opt_arg;
bool has_equal_arg = false;
if (arg.startsWith("--"))
{
auto v = pstring_vector_t(arg.substr(2),"=");
opt = getopt_long(v[0]);
has_equal_arg = (v.size() > 1);
if (has_equal_arg) opt_arg = v[1];
}
else if (arg.startsWith("-"))
{
opt = getopt_short(arg.substr(1));
}
else
return i;
if (opt == nullptr)
return i;
if (opt->has_argument())
{
if (has_equal_arg)
{
if (opt->parse(opt_arg) != 0)
return i;
}
else
{
i++; // FIXME: are there more arguments?
if (opt->parse(argv[i]) != 0)
return i - 1;
}
}
else
{
if (has_equal_arg)
return i;
opt->parse("");
}
i++;
}
return argc;
}
pstring options::split_paragraphs(pstring text, unsigned width, unsigned ident,
unsigned firstline_ident)
{
auto paragraphs = pstring_vector_t(text,"\n");
pstring ret("");
for (auto &p : paragraphs)
{
pstring line = pstring("").rpad(" ", firstline_ident);
for (auto &s : pstring_vector_t(p, " "))
{
if (line.len() + s.len() > width)
{
ret += line + "\n";
line = pstring("").rpad(" ", ident);
}
line += s + " ";
}
ret += line + "\n";
}
return ret;
}
pstring options::help(pstring description, pstring usage,
unsigned width, unsigned ident)
{
pstring ret;
ret = split_paragraphs(description, width, 0, 0) + "\n";
ret += "Usage:\t" + usage + "\n\nOptions:\n";
for (auto & opt : m_opts )
{
pstring line = "";
if (opt->short_opt() != "")
line += " -" + opt->short_opt();
if (opt->long_opt() != "")
{
if (line != "")
line += ", ";
else
line = " ";
line += "--" + opt->long_opt();
if (opt->has_argument())
{
line += "=";
option_str_limit *ol = dynamic_cast<option_str_limit *>(opt);
if (ol)
{
for (auto &v : ol->limit())
{
line += v + "|";
}
line = line.left(line.len() - 1);
}
else
line += "Value";
}
}
line = line.rpad(" ", 20) + " ";
if (line.len() > 21)
{
ret += line + "\n";
ret += split_paragraphs(opt->help(), 72, 21, 21);
}
else
ret += split_paragraphs(line + opt->help(), 72, 21, 0);
}
return ret;
}
option *options::getopt_short(pstring arg)
{
for (auto & opt : m_opts)
{
if (opt->short_opt() == arg)
return opt;
}
return nullptr;
}
option *options::getopt_long(pstring arg)
{
for (auto & opt : m_opts)
{
if (opt->long_opt() == arg)
return opt;
}
return nullptr;
}
} // namespace plib

View File

@ -27,35 +27,34 @@ class options;
class option
{
public:
option()
: m_short(""), m_long(""), m_help(""), m_has_argument(false)
{}
option();
option(options &parent, pstring ashort, pstring along, pstring help, bool has_argument);
option(pstring ashort, pstring along, pstring help, bool has_argument, options *parent = nullptr);
virtual ~option()
{
}
virtual ~option();
/* no_argument options will be called with "" argument */
virtual int parse(ATTR_UNUSED pstring argument) { return 0; }
virtual int parse(ATTR_UNUSED pstring argument) = 0;
pstring short_opt() { return m_short; }
pstring long_opt() { return m_long; }
pstring help() { return m_help; }
bool has_argument() { return m_has_argument ; }
private:
pstring m_short;
pstring m_long;
pstring m_help;
bool m_has_argument;
private:
};
class option_str : public option
{
public:
option_str(pstring ashort, pstring along, pstring defval, pstring help, options *parent = nullptr)
: option(ashort, along, help, true, parent), m_val(defval)
option_str(options &parent, pstring ashort, pstring along, pstring defval, pstring help)
: option(parent, ashort, along, help, true), m_val(defval)
{}
virtual int parse(pstring argument) override { m_val = argument; return 0; }
virtual int parse(pstring argument) override;
pstring operator ()() { return m_val; }
private:
@ -65,22 +64,15 @@ private:
class option_str_limit : public option
{
public:
option_str_limit(pstring ashort, pstring along, pstring defval, pstring limit, pstring help, options *parent = nullptr)
: option(ashort, along, help, true, parent), m_val(defval), m_limit(limit, ":")
option_str_limit(options &parent, pstring ashort, pstring along, pstring defval, pstring limit, pstring help)
: option(parent, ashort, along, help, true), m_val(defval), m_limit(limit, ":")
{}
virtual int parse(pstring argument) override
{
if (plib::container::contains(m_limit, argument))
{
m_val = argument;
return 0;
}
else
return 1;
}
virtual int parse(pstring argument) override;
pstring operator ()() { return m_val; }
const plib::pstring_vector_t &limit() { return m_limit; }
private:
pstring m_val;
plib::pstring_vector_t m_limit;
@ -89,11 +81,11 @@ private:
class option_bool : public option
{
public:
option_bool(pstring ashort, pstring along, pstring help, options *parent = nullptr)
: option(ashort, along, help, false, parent), m_val(false)
option_bool(options &parent, pstring ashort, pstring along, pstring help)
: option(parent, ashort, along, help, false), m_val(false)
{}
virtual int parse(ATTR_UNUSED pstring argument) override { m_val = true; return 0; }
virtual int parse(ATTR_UNUSED pstring argument) override;
bool operator ()() { return m_val; }
private:
@ -103,16 +95,11 @@ private:
class option_double : public option
{
public:
option_double(pstring ashort, pstring along, double defval, pstring help, options *parent = nullptr)
: option(ashort, along, help, true, parent), m_val(defval)
option_double(options &parent, pstring ashort, pstring along, double defval, pstring help)
: option(parent, ashort, along, help, true), m_val(defval)
{}
virtual int parse(pstring argument) override
{
bool err = false;
m_val = argument.as_double(&err);
return (err ? 1 : 0);
}
virtual int parse(pstring argument) override;
double operator ()() { return m_val; }
private:
@ -123,117 +110,30 @@ class options
{
public:
options() {}
options();
options(option *o[]);
options(option *o[])
{
int i=0;
while (o[i] != nullptr)
{
m_opts.push_back(o[i]);
i++;
}
}
~options();
~options()
{
m_opts.clear();
}
void register_option(option *opt);
int parse(int argc, char *argv[]);
void register_option(option *opt)
{
m_opts.push_back(opt);
}
pstring help(pstring description, pstring usage,
unsigned width = 72, unsigned ident = 20);
int parse(int argc, char *argv[])
{
m_app = argv[0];
for (int i=1; i<argc; )
{
pstring arg(argv[i]);
option *opt = nullptr;
if (arg.startsWith("--"))
{
opt = getopt_long(arg.substr(2));
}
else if (arg.startsWith("-"))
{
opt = getopt_short(arg.substr(1));
}
else
return i;
if (opt == nullptr)
return i;
if (opt->m_has_argument)
{
i++; // FIXME: are there more arguments?
if (opt->parse(argv[i]) != 0)
return i - 1;
}
else
opt->parse("");
i++;
}
return argc;
}
pstring help()
{
pstring ret;
for (auto & opt : m_opts )
{
pstring line = "";
if (opt->m_short != "")
line += " -" + opt->m_short;
if (opt->m_long != "")
{
if (line != "")
line += ", ";
else
line = " ";
line += "--" + opt->m_long;
}
line = line.rpad(" ", 20).cat(opt->m_help);
ret = ret + line + "\n";
}
return ret;
}
pstring app() { return m_app; }
private:
static pstring split_paragraphs(pstring text, unsigned width, unsigned ident,
unsigned firstline_ident);
option *getopt_short(pstring arg)
{
for (auto & opt : m_opts)
{
if (opt->m_short == arg)
return opt;
}
return nullptr;
}
option *getopt_long(pstring arg)
{
for (auto & opt : m_opts)
{
if (opt->m_long == arg)
return opt;
}
return nullptr;
}
option *getopt_short(pstring arg);
option *getopt_long(pstring arg);
std::vector<option *> m_opts;
pstring m_app;
};
option::option(pstring ashort, pstring along, pstring help, bool has_argument, options *parent)
: m_short(ashort), m_long(along), m_help(help), m_has_argument(has_argument)
{
if (parent != nullptr)
parent->register_option(this);
}
}

View File

@ -258,7 +258,7 @@ const pstring_t<F> pstring_t<F>::rpad(const pstring_t &ws, const unsigned cnt) c
pstring_t ret(*this);
while (ret.len() < cnt)
ret += ws;
return pstring_t(ret).substr(0, cnt);
return ret;
}

View File

@ -26,16 +26,17 @@ class tool_options_t : public plib::options
public:
tool_options_t() :
plib::options(),
opt_ttr ("t", "time_to_run", 1.0, "time to run the emulation (seconds)", this),
opt_name("n", "name", "", "netlist in file to run; default is first one", this),
opt_logs("l", "logs", "", "colon separated list of terminals to log", this),
opt_file("f", "file", "-", "file to process (default is stdin)", this),
opt_type("y", "type", "spice", "spice:eagle", "type of file to be converted: spice,eagle", this),
opt_cmd ("c", "cmd", "run", "run|convert|listdevices|static", this),
opt_inp( "i", "input", "", "input file to process (default is none)", this),
opt_verb("v", "verbose", "be verbose - this produces lots of output", this),
opt_quiet("q", "quiet", "be quiet - no warnings", this),
opt_help("h", "help", "display help", this)
opt_ttr (*this, "t", "time_to_run", 1.0, "time to run the emulation (seconds)"),
opt_name(*this, "n", "name", "", "netlist in file to run; default is first one"),
opt_logs(*this, "l", "logs", "", "colon separated list of terminals to log"),
opt_file(*this, "f", "file", "-", "file to process (default is stdin)"),
opt_type(*this, "y", "type", "spice", "spice:eagle", "type of file to be converted: spice,eagle"),
opt_cmd (*this, "c", "cmd", "run", "run:convert:listdevices:static", "run|convert|listdevices|static"),
opt_inp(*this, "i", "input", "", "input file to process (default is none)"),
opt_verb(*this, "v", "verbose", "be verbose - this produces lots of output"),
opt_quiet(*this, "q", "quiet", "be quiet - no warnings"),
opt_version(*this, "", "version", "display version and exit"),
opt_help(*this, "h", "help", "display help and exit")
{}
plib::option_double opt_ttr;
@ -43,10 +44,11 @@ public:
plib::option_str opt_logs;
plib::option_str opt_file;
plib::option_str_limit opt_type;
plib::option_str opt_cmd;
plib::option_str_limit opt_cmd;
plib::option_str opt_inp;
plib::option_bool opt_verb;
plib::option_bool opt_quiet;
plib::option_bool opt_version;
plib::option_bool opt_help;
};
@ -92,7 +94,8 @@ public:
{
// read the netlist ...
m_setup->register_source(std::make_shared<netlist::source_file_t>(filename));
m_setup->register_source(plib::make_unique_base<netlist::source_t,
netlist::source_file_t>(filename));
m_setup->include(name);
log_setup();
@ -133,14 +136,9 @@ private:
void usage(tool_options_t &opts)
{
perr("{}",
"Usage:\n"
" nltool --help\n"
" nltool [options]\n"
"\n"
"Where:\n"
);
perr("{}\n", opts.help().cstr());
pout("{}\n", opts.help(
"nltool serves as the Swiss Army knife to run, test and convert netlists.",
"nltool [options]").cstr());
}
struct input_t
@ -207,7 +205,10 @@ std::vector<input_t> *read_input(netlist::netlist_t *netlist, pstring fname)
static void run(tool_options_t &opts)
{
netlist_tool_t nt("netlist");
plib::ticks_t t = plib::ticks();
plib::chrono::timer<plib::chrono::system_ticks> t;
//plib::perftime_t<plib::exact_ticks> t;
t.start();
nt.m_opts = &opts;
nt.init();
@ -222,10 +223,13 @@ static void run(tool_options_t &opts)
std::vector<input_t> *inps = read_input(&nt, opts.opt_inp());
double ttr = opts.opt_ttr();
t.stop();
pout("startup time ==> {1:5.3f}\n", (double) (plib::ticks() - t) / (double) plib::ticks_per_second() );
pout("startup time ==> {1:5.3f}\n", t.as_seconds() );
pout("runnning ...\n");
t = plib::ticks();
t.reset();
t.start();
unsigned pos = 0;
netlist::netlist_time nlt = netlist::netlist_time::zero();
@ -241,7 +245,9 @@ static void run(tool_options_t &opts)
nt.stop();
plib::pfree(inps);
double emutime = (double) (plib::ticks() - t) / (double) plib::ticks_per_second();
t.stop();
double emutime = t.as_seconds();
pout("{1:f} seconds emulation took {2:f} real time ==> {3:5.2f}%\n", ttr, emutime, ttr/emutime*100.0);
}
@ -273,7 +279,8 @@ static void listdevices()
nt.init();
netlist::factory_list_t &list = nt.setup().factory();
nt.setup().register_source(std::make_shared<netlist::source_proc_t>("dummy", &netlist_dummy));
nt.setup().register_source(plib::make_unique_base<netlist::source_t,
netlist::source_proc_t>("dummy", &netlist_dummy));
nt.setup().include("dummy");
nt.setup().start_devices();
@ -351,7 +358,7 @@ int main(int argc, char *argv[])
tool_options_t opts;
int ret;
perr("{}", "WARNING: This is Work In Progress! - It may fail anytime\n");
//perr("{}", "WARNING: This is Work In Progress! - It may fail anytime\n");
//perr("Update dispatching using method {}\n", pmf_verbose[NL_PMF_TYPE]);
if ((ret = opts.parse(argc, argv)) != argc)
{
@ -363,7 +370,19 @@ int main(int argc, char *argv[])
if (opts.opt_help())
{
usage(opts);
return 1;
return 0;
}
if (opts.opt_version())
{
pout(
"nltool (netlist) 0.1\n"
"Copyright (C) 2016 Couriersud\n"
"License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>.\n"
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n\n"
"Written by Couriersud.\n");
return 0;
}
pstring cmd = opts.opt_cmd();

View File

@ -13,21 +13,29 @@ class nlwav_options_t : public plib::options
public:
nlwav_options_t() :
plib::options(),
opt_inp( "i", "input", "", "input file", this),
opt_out( "o", "output", "", "output file", this),
opt_amp( "a", "amp", 10000.0, "amplification after mean correction", this),
opt_verb("v", "verbose", "be verbose - this produces lots of output", this),
opt_quiet("q", "quiet", "be quiet - no warnings", this),
opt_help("h", "help", "display help", this)
opt_inp(*this, "i", "input", "", "input file"),
opt_out(*this, "o", "output", "", "output file"),
opt_amp(*this, "a", "amp", 10000.0, "amplification after mean correction"),
opt_verb(*this, "v", "verbose", "be verbose - this produces lots of output"),
opt_quiet(*this,"q", "quiet", "be quiet - no warnings"),
opt_version(*this, "", "version", "display version and exit"),
opt_help(*this, "h", "help", "display help and exit")
{}
plib::option_str opt_inp;
plib::option_str opt_out;
plib::option_double opt_amp;
plib::option_bool opt_verb;
plib::option_bool opt_quiet;
plib::option_bool opt_version;
plib::option_bool opt_help;
};
plib::pstdout pout_strm;
plib::pstderr perr_strm;
plib::pstream_fmt_writer_t pout(pout_strm);
plib::pstream_fmt_writer_t perr(perr_strm);
/* http://de.wikipedia.org/wiki/RIFF_WAVE */
class wav_t
{
@ -196,26 +204,20 @@ void convert(nlwav_options_t &opts)
//printf("%f %f\n", t, v);
#endif
}
printf("Mean (low freq filter): %f\n", mean);
printf("Mean (static): %f\n", means / (double) n);
printf("Amp + %f\n", 32000.0 / (maxsam- mean));
printf("Amp - %f\n", -32000.0 / (minsam- mean));
pout("Mean (low freq filter): {}\n", mean);
pout("Mean (static): {}\n", means / (double) n);
pout("Amp + {}\n", 32000.0 / (maxsam- mean));
pout("Amp - {}\n", -32000.0 / (minsam- mean));
wo.close();
fo.close();
fin.close();
}
void usage(nlwav_options_t &opts)
void usage(plib::pstream_fmt_writer_t &fw, nlwav_options_t &opts)
{
fprintf(stderr,
"Usage:\n"
" nltool -help\n"
" nltool [options]\n"
"\n"
"Where:\n"
);
fprintf(stderr, "%s\n", opts.help().cstr());
fw("{}\n", opts.help("Convert netlist log files into wav files.\n",
"nltool [options]").cstr());
}
@ -226,15 +228,27 @@ int main(int argc, char *argv[])
if ((ret = opts.parse(argc, argv)) != argc)
{
fprintf(stderr, "Error parsing %s\n", argv[ret]);
usage(opts);
perr("Error parsing {}\n", argv[ret]);
usage(perr, opts);
return 1;
}
if (opts.opt_help())
{
usage(opts);
return 1;
usage(pout, opts);
return 0;
}
if (opts.opt_version())
{
pout(
"nlwav (netlist) 0.1\n"
"Copyright (C) 2016 Couriersud\n"
"License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>.\n"
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n\n"
"Written by Couriersud.\n");
return 0;
}
convert(opts);

View File

@ -18,7 +18,7 @@
void nl_convert_base_t::add_pin_alias(const pstring &devname, const pstring &name, const pstring &alias)
{
pstring pname = devname + "." + name;
m_pins.insert({pname, plib::make_unique<pin_alias_t>(pname, devname + "." + alias)});
m_pins.emplace(pname, plib::make_unique<pin_alias_t>(pname, devname + "." + alias));
}
void nl_convert_base_t::add_ext_alias(const pstring &alias)
@ -26,7 +26,7 @@ void nl_convert_base_t::add_ext_alias(const pstring &alias)
m_ext_alias.push_back(alias);
}
void nl_convert_base_t::add_device(std::shared_ptr<dev_t> dev)
void nl_convert_base_t::add_device(std::unique_ptr<dev_t> dev)
{
for (auto & d : m_devs)
if (d->name() == dev->name())
@ -34,20 +34,20 @@ void nl_convert_base_t::add_device(std::shared_ptr<dev_t> dev)
out("ERROR: Duplicate device {1} ignored.", dev->name());
return;
}
m_devs.push_back(dev);
m_devs.push_back(std::move(dev));
}
void nl_convert_base_t::add_device(const pstring &atype, const pstring &aname, const pstring &amodel)
{
add_device(std::make_shared<dev_t>(atype, aname, amodel));
add_device(plib::make_unique<dev_t>(atype, aname, amodel));
}
void nl_convert_base_t::add_device(const pstring &atype, const pstring &aname, double aval)
{
add_device(std::make_shared<dev_t>(atype, aname, aval));
add_device(plib::make_unique<dev_t>(atype, aname, aval));
}
void nl_convert_base_t::add_device(const pstring &atype, const pstring &aname)
{
add_device(std::make_shared<dev_t>(atype, aname));
add_device(plib::make_unique<dev_t>(atype, aname));
}
void nl_convert_base_t::add_term(pstring netname, pstring termname)
@ -58,9 +58,9 @@ void nl_convert_base_t::add_term(pstring netname, pstring termname)
net = m_nets[netname].get();
else
{
auto nets = std::make_shared<net_t>(netname);
auto nets = plib::make_unique<net_t>(netname);
net = nets.get();
m_nets.insert({netname, nets});
m_nets.emplace(netname, std::move(nets));
}
/* if there is a pin alias, translate ... */
@ -84,10 +84,11 @@ void nl_convert_base_t::dump_nl()
net->set_no_export();
}
std::vector<int> sorted;
for (unsigned i=0; i < m_devs.size(); i++)
std::vector<size_t> sorted;
for (size_t i=0; i < m_devs.size(); i++)
sorted.push_back(i);
std::sort(sorted.begin(), sorted.end(), plib::indexed_compare<std::vector<std::shared_ptr<dev_t>>>(m_devs));
std::sort(sorted.begin(), sorted.end(),
[&](size_t i1, size_t i2) { return m_devs[i1]->name() < m_devs[i2]->name(); });
for (std::size_t i=0; i<m_devs.size(); i++)
{

View File

@ -126,14 +126,14 @@ private:
private:
void add_device(std::shared_ptr<dev_t> dev);
void add_device(std::unique_ptr<dev_t> dev);
plib::postringstream m_buf;
std::vector<std::shared_ptr<dev_t>> m_devs;
std::unordered_map<pstring, std::shared_ptr<net_t> > m_nets;
std::vector<std::unique_ptr<dev_t>> m_devs;
std::unordered_map<pstring, std::unique_ptr<net_t> > m_nets;
std::vector<pstring> m_ext_alias;
std::unordered_map<pstring, std::shared_ptr<pin_alias_t>> m_pins;
std::unordered_map<pstring, std::unique_ptr<pin_alias_t>> m_pins;
static unit_t m_units[];

View File

@ -275,6 +275,7 @@ CIRCUIT_LAYOUT( breakout )
CHIP("H5", 9312)
CHIP("H6", 9310)
CHIP("H7", 7408) //sometimes looks like N7 on schematic
//PARAM(H7.USE_DEACTIVATE, 0)
CHIP("H8", 7474)
CHIP("H9", 7474)
@ -1700,6 +1701,36 @@ CIRCUIT_LAYOUT( breakout )
NET_C(GND, D9.1, D9.2, D9.13, D9.3, D9.4, D9.5)
HINT(A3.1.sub, NO_DEACTIVATE)
HINT(B6.s3, NO_DEACTIVATE)
HINT(C4.s3, NO_DEACTIVATE)
HINT(C4.s4, NO_DEACTIVATE)
HINT(C5.s3, NO_DEACTIVATE)
HINT(C5.s4, NO_DEACTIVATE)
HINT(D3.2.sub, NO_DEACTIVATE)
HINT(E2.s2, NO_DEACTIVATE)
HINT(E3.s2, NO_DEACTIVATE)
HINT(E5.s4, NO_DEACTIVATE)
HINT(E8.2.sub, NO_DEACTIVATE)
HINT(E9.s6, NO_DEACTIVATE)
HINT(F5.2.sub, NO_DEACTIVATE)
HINT(H2.s1, NO_DEACTIVATE)
HINT(H3.s1, NO_DEACTIVATE)
HINT(H6.sub, NO_DEACTIVATE)
HINT(J3.s4, NO_DEACTIVATE)
HINT(J5, NO_DEACTIVATE)
HINT(J6.sub, NO_DEACTIVATE)
HINT(J8.1, NO_DEACTIVATE)
HINT(J8.3, NO_DEACTIVATE)
HINT(K4.s4, NO_DEACTIVATE)
HINT(M3.s2, NO_DEACTIVATE)
HINT(M3.s4, NO_DEACTIVATE)
HINT(M4.s2, NO_DEACTIVATE)
HINT(M6.sub, NO_DEACTIVATE)
HINT(M8.s1, NO_DEACTIVATE)
HINT(N6.sub, NO_DEACTIVATE)
HINT(N7.s3, NO_DEACTIVATE)
CIRCUIT_LAYOUT_END
/*

View File

@ -27,7 +27,6 @@ NETLIST_START(pong_fast)
TTL_INPUT(high, 1)
TTL_INPUT(low, 0)
#if 1
#if (FAST_CLOCK)
/* abstracting this, performance increases by 60%
* No surprise, the clock is extremely expensive */
@ -38,12 +37,6 @@ NETLIST_START(pong_fast)
TTL_74107(ic_f6a, xclk, high, high, high)
ALIAS(clk, ic_f6a.Q)
#endif
#else
// benchmarking ...
NETDEV_TTL_CONST(clk, 0)
MAINCLOCK(xclk)
PARAM(xclk.FREQ, 7159000.0*2)
#endif
/* 3V Logic - Just a resistor - the value is not given in schematics */
@ -577,5 +570,41 @@ NETLIST_START(pong_fast)
NET_C(RV2.2, RV3.2)
ALIAS(videomix, RV3.2)
#if 1
HINT(clk, NO_DEACTIVATE)
HINT(ic_e1d, NO_DEACTIVATE)
HINT(ic_e1c, NO_DEACTIVATE)
HINT(ic_f1.A, NO_DEACTIVATE)
HINT(ic_f1.D, NO_DEACTIVATE)
HINT(ic_g1d, NO_DEACTIVATE)
HINT(ic_h1a, NO_DEACTIVATE)
HINT(ic_h1d, NO_DEACTIVATE)
HINT(ic_h3b.sub, NO_DEACTIVATE)
HINT(ic_g6b.sub, NO_DEACTIVATE)
HINT(ic_c2a.sub, NO_DEACTIVATE)
HINT(hit_sound, NO_DEACTIVATE)
HINT(topbothitsound, NO_DEACTIVATE)
HINT(ic_c9b, NO_DEACTIVATE)
HINT(ic_b8.D, NO_DEACTIVATE)
HINT(ic_b7a, NO_DEACTIVATE)
HINT(ic_a7b, NO_DEACTIVATE)
HINT(ic_c9a, NO_DEACTIVATE)
HINT(ic_a8.D, NO_DEACTIVATE)
HINT(ic_b7d, NO_DEACTIVATE)
HINT(ic_a7a, NO_DEACTIVATE)
HINT(ic_g1a, NO_DEACTIVATE)
HINT(ic_c8a.sub, NO_DEACTIVATE)
HINT(ic_c8b.sub, NO_DEACTIVATE)
HINT(ic_d8b, NO_DEACTIVATE)
HINT(ic_d6a.sub, NO_DEACTIVATE)
HINT(ic_d6b.sub, NO_DEACTIVATE)
HINT(ic_c6a.sub, NO_DEACTIVATE)
HINT(ic_c6b.sub, NO_DEACTIVATE)
HINT(ic_e5b, NO_DEACTIVATE)
HINT(ic_e4c, NO_DEACTIVATE)
HINT(ic_d4b, NO_DEACTIVATE)
HINT(ic_g1b, NO_DEACTIVATE)
#endif
NETLIST_END()