diff --git a/scripts/src/netlist.lua b/scripts/src/netlist.lua index c038f14a28e..3d3558a2754 100644 --- a/scripts/src/netlist.lua +++ b/scripts/src/netlist.lua @@ -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", diff --git a/src/devices/machine/netlist.cpp b/src/devices/machine/netlist.cpp index 7160b696b52..b924e052e50 100644 --- a/src/devices/machine/netlist.cpp +++ b/src/devices/machine/netlist.cpp @@ -103,7 +103,7 @@ void netlist_mame_analog_output_t::custom_netlist_additions(netlist::setup_t &se plib::owned_ptr dev = plib::owned_ptr::Create(setup.netlist(), setup.build_fqn(dname)); static_cast(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); } diff --git a/src/devices/machine/netlist.h b/src/devices/machine/netlist.h index 606cd4af283..ad2cfdd47d1 100644 --- a/src/devices/machine/netlist.h +++ b/src/devices/machine/netlist.h @@ -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(_name)); + setup.register_source(plib::make_unique_base(_name)); #define NETDEV_ANALOG_CALLBACK_MEMBER(_name) \ void _name(const double data, const attotime &time) diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile index c1729cc0c39..0a3efaa70f8 100644 --- a/src/lib/netlist/build/makefile +++ b/src/lib/netlist/build/makefile @@ -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 $@... diff --git a/src/lib/netlist/devices/nld_74279.cpp b/src/lib/netlist/devices/nld_74279.cpp index 7fb75f946fb..7bcbadff855 100644 --- a/src/lib/netlist/devices/nld_74279.cpp +++ b/src/lib/netlist/devices/nld_74279.cpp @@ -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) { diff --git a/src/lib/netlist/devices/nld_7493.cpp b/src/lib/netlist/devices/nld_7493.cpp index 8a12333e596..31faa5191dc 100644 --- a/src/lib/netlist/devices/nld_7493.cpp +++ b/src/lib/netlist/devices/nld_7493.cpp @@ -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); diff --git a/src/lib/netlist/devices/nld_9312.cpp b/src/lib/netlist/devices/nld_9312.cpp index 0191a905ebc..33b6d8e7a87 100644 --- a/src/lib/netlist/devices/nld_9312.cpp +++ b/src/lib/netlist/devices/nld_9312.cpp @@ -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) diff --git a/src/lib/netlist/devices/nld_9316.cpp b/src/lib/netlist/devices/nld_9316.cpp index 8c6b70c5810..3033ace81bc 100644 --- a/src/lib/netlist/devices/nld_9316.cpp +++ b/src/lib/netlist/devices/nld_9316.cpp @@ -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) diff --git a/src/lib/netlist/devices/nld_truthtable.cpp b/src/lib/netlist/devices/nld_truthtable.cpp index 9ed524e58b1..29895ae8b4c 100644 --- a/src/lib/netlist/devices/nld_truthtable.cpp +++ b/src/lib/netlist/devices/nld_truthtable.cpp @@ -7,13 +7,14 @@ #include "nld_truthtable.h" #include "plib/plists.h" +#include "nl_setup.h" namespace netlist { namespace devices { - template + template 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 Create(netlist_t &anetlist, const pstring &name) override { - typedef nld_truthtable_t tt_type; + typedef nld_truthtable_t tt_type; return plib::owned_ptr::Create(anetlist, name, m_family, &m_ttbl, m_desc); } private: - typename nld_truthtable_t::truthtable_t m_ttbl; + typename nld_truthtable_t::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; \ - return plib::owned_ptr::Create(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; \ + 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 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 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(ret)); } } //namespace devices diff --git a/src/lib/netlist/devices/nld_truthtable.h b/src/lib/netlist/devices/nld_truthtable.h index d30ff03704c..157aea166fc 100644 --- a/src/lib/netlist/devices/nld_truthtable.h +++ b/src/lib/netlist/devices/nld_truthtable.h @@ -13,39 +13,22 @@ #include #include -#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 \ +#define NETLIB_TRUTHTABLE(cname, nIN, nOUT) \ + class NETLIB_NAME(cname) : public nld_truthtable_t \ { \ public: \ template \ - NETLIB_NAME(cname)(C &owner, const pstring &name) \ - : nld_truthtable_t(owner, name, nullptr, &m_ttbl, m_desc) { } \ + NETLIB_NAME(cname)(C &owner, const pstring &name) \ + : nld_truthtable_t(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 + template 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; im_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(); @@ -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 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 diff --git a/src/lib/netlist/macro/nlm_cd4xxx.cpp b/src/lib/netlist/macro/nlm_cd4xxx.cpp index f7eda575bab..d622881abb4 100644 --- a/src/lib/netlist/macro/nlm_cd4xxx.cpp +++ b/src/lib/netlist/macro/nlm_cd4xxx.cpp @@ -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") diff --git a/src/lib/netlist/macro/nlm_other.cpp b/src/lib/netlist/macro/nlm_other.cpp index 9a5e54af737..6fd73a29fe8 100644 --- a/src/lib/netlist/macro/nlm_other.cpp +++ b/src/lib/netlist/macro/nlm_other.cpp @@ -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") diff --git a/src/lib/netlist/macro/nlm_ttl74xx.cpp b/src/lib/netlist/macro/nlm_ttl74xx.cpp index 25bf7573c03..41065012690 100644 --- a/src/lib/netlist/macro/nlm_ttl74xx.cpp +++ b/src/lib/netlist/macro/nlm_ttl74xx.cpp @@ -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") diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp index e40ec1dc5d3..e20c240a374 100644 --- a/src/lib/netlist/nl_base.cpp +++ b/src/lib/netlist/nl_base.cpp @@ -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 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(libpath); - /* make sure the solver and parameters are started first! */ - - for (auto & e : setup().m_device_factory) - { - if ( setup().factory().is_class(e.second) - || setup().factory().is_class(e.second) - || setup().factory().is_class(e.second) - || setup().factory().is_class(e.second)) - { - auto dev = plib::owned_ptr(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("mainclock"); - m_solver = get_single_device("solver"); - m_gnd = get_single_device("gnd"); - m_params = get_single_device("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(e.second) - && !setup().factory().is_class(e.second) - && !setup().factory().is_class(e.second) - && !setup().factory().is_class(e.second)) - { - auto dev = plib::owned_ptr(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 index; + for (size_t i=0; im_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 { diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h index 1587cefb99b..1451e18038d 100644 --- a/src/lib/netlist/nl_base.h +++ b/src/lib/netlist/nl_base.h @@ -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 ¶m) - : 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 dev); + net_t *find_net(const pstring &name); template @@ -1165,22 +1160,21 @@ namespace netlist /* sole use is to manage lifetime of family objects */ std::vector>> 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; diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h index 19d8e3561ad..153057dbc22 100644 --- a/src/lib/netlist/nl_config.h +++ b/src/lib/netlist/nl_config.h @@ -11,6 +11,7 @@ #include #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; +using nperfcount_t = plib::counter; #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; +using nperfcount_t = plib::chrono::counter; #endif - +} //============================================================ // General //============================================================ diff --git a/src/lib/netlist/nl_factory.h b/src/lib/netlist/nl_factory.h index b85e85bf6b8..f97dad9bf5a 100644 --- a/src/lib/netlist/nl_factory.h +++ b/src/lib/netlist/nl_factory.h @@ -65,7 +65,7 @@ namespace netlist } }; - class factory_list_t : public std::vector> + class factory_list_t : public std::vector> { 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::Create>(name, classname, def_param)); + register_device(std::unique_ptr(new factory_t(name, classname, def_param))); } - void register_device(plib::owned_ptr factory) + void register_device(std::unique_ptr 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 (*)(const pstring &name, const pstring &classname, + using factory_creator_ptr_t = std::unique_ptr (*)(const pstring &name, const pstring &classname, const pstring &def_param); template - plib::owned_ptr factory_creator_t(const pstring &name, const pstring &classname, + std::unique_ptr factory_creator_t(const pstring &name, const pstring &classname, const pstring &def_param) { - return plib::owned_ptr::Create>(name, classname, def_param); + return std::unique_ptr(new factory_t(name, classname, def_param)); } } diff --git a/src/lib/netlist/nl_lists.h b/src/lib/netlist/nl_lists.h index 475e0e285c2..9e6cc335b5b 100644 --- a/src/lib/netlist/nl_lists.h +++ b/src/lib/netlist/nl_lists.h @@ -10,10 +10,11 @@ #ifndef NLLISTS_H_ #define NLLISTS_H_ +#include + #include "nl_config.h" #include "plib/plists.h" - -#include +#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 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; }; } diff --git a/src/lib/netlist/nl_parser.cpp b/src/lib/netlist/nl_parser.cpp index 14aabdf4a0e..bc27913e6b0 100644 --- a/src/lib/netlist/nl_parser.cpp +++ b/src/lib/netlist/nl_parser.cpp @@ -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 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]; diff --git a/src/lib/netlist/nl_parser.h b/src/lib/netlist/nl_parser.h index 7338fb01abd..5c915e69997 100644 --- a/src/lib/netlist/nl_parser.h +++ b/src/lib/netlist/nl_parser.h @@ -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; diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp index 5b7099a9e14..0582f8a9070 100644 --- a/src/lib/netlist/nl_setup.cpp +++ b/src/lib/netlist/nl_setup.cpp @@ -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 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(e.second) + || factory().is_class(e.second) + || factory().is_class(e.second) + || factory().is_class(e.second)) + { + auto dev = plib::owned_ptr(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("mainclock"); + netlist().m_solver = netlist().get_single_device("solver"); + netlist().m_gnd = netlist().get_single_device("gnd"); + netlist().m_params = netlist().get_single_device("parameter"); + + /* create devices */ + + for (auto & e : m_device_factory) + { + if ( !factory().is_class(e.second) + && !factory().is_class(e.second) + && !factory().is_class(e.second) + && !factory().is_class(e.second)) + { + auto dev = plib::owned_ptr(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 &setup_t::log() +{ + return netlist().log(); +} +const plib::plog_base &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; diff --git a/src/lib/netlist/nl_setup.h b/src/lib/netlist/nl_setup.h index 39ef1c514ff..2fee7210aa9 100644 --- a/src/lib/netlist/nl_setup.h +++ b/src/lib/netlist/nl_setup.h @@ -11,7 +11,13 @@ #include #include #include +#include +#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(# name, &NETLIST_NAME(name))); +#define LOCAL_SOURCE(name) \ + setup.register_source(plib::make_unique_base(# 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 ¶m) + : 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>; + + 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>; - - source_t() - {} - - virtual ~source_t() { } - - virtual bool parse(setup_t &setup, const pstring &name) = 0; - private: - }; - using link_t = std::pair; setup_t(netlist_t &netlist); @@ -118,7 +185,6 @@ namespace netlist void register_term(core_terminal_t &obj); - void register_dev(plib::owned_ptr 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 - void register_source(std::shared_ptr src) + void register_source(std::unique_ptr &&src) { - m_sources.push_back(std::static_pointer_cast(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 &log() { return netlist().log(); } - const plib::plog_base &log() const { return netlist().log(); } + plib::plog_base &log(); + const plib::plog_base &log() const; std::vector> 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) { diff --git a/src/lib/netlist/nl_time.h b/src/lib/netlist/nl_time.h index 0a4caac1ac6..974ba4c669c 100644 --- a/src/lib/netlist/nl_time.h +++ b/src/lib/netlist/nl_time.h @@ -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::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::max(), resolution); } private: internal_type m_time; }; diff --git a/src/lib/netlist/plib/pchrono.cpp b/src/lib/netlist/plib/pchrono.cpp new file mode 100644 index 00000000000..3beb3b2f161 --- /dev/null +++ b/src/lib/netlist/plib/pchrono.cpp @@ -0,0 +1,55 @@ +// license:GPL-2.0+ +// copyright-holders:Couriersud + +#include + +#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 + +} +} diff --git a/src/lib/netlist/plib/pchrono.h b/src/lib/netlist/plib/pchrono.h new file mode 100644 index 00000000000..805842007f2 --- /dev/null +++ b/src/lib/netlist/plib/pchrono.h @@ -0,0 +1,213 @@ +// license:GPL-2.0+ +// copyright-holders:Couriersud +/* + * pchrono.h + * + */ + +#ifndef PCHRONO_H_ +#define PCHRONO_H_ + +#include +#include +#include + +#include "pconfig.h" + +namespace plib { +namespace chrono { + template + 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; + using steady_ticks = sys_ticks; + using system_ticks = sys_ticks; + + #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 + 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 + { + 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 + struct timer + { + 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_ */ diff --git a/src/lib/netlist/plib/pconfig.h b/src/lib/netlist/plib/pconfig.h index 48a7e740a8f..5c1582cdec8 100644 --- a/src/lib/netlist/plib/pconfig.h +++ b/src/lib/netlist/plib/pconfig.h @@ -12,9 +12,22 @@ #include #include -#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. diff --git a/src/lib/netlist/plib/poptions.cpp b/src/lib/netlist/plib/poptions.cpp new file mode 100644 index 00000000000..8b2db8cf19e --- /dev/null +++ b/src/lib/netlist/plib/poptions.cpp @@ -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 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(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 diff --git a/src/lib/netlist/plib/poptions.h b/src/lib/netlist/plib/poptions.h index 3ab1adb78c6..6ddac682d66 100644 --- a/src/lib/netlist/plib/poptions.h +++ b/src/lib/netlist/plib/poptions.h @@ -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; im_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