mirror of
https://github.com/holub/mame
synced 2025-04-21 07:52:35 +03:00
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:
parent
224dbf1cc9
commit
c6e6911aed
@ -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",
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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 $@...
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
{
|
||||
|
||||
|
@ -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<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;
|
||||
|
@ -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
|
||||
//============================================================
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 ¶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<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)
|
||||
{
|
||||
|
@ -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;
|
||||
};
|
||||
|
55
src/lib/netlist/plib/pchrono.cpp
Normal file
55
src/lib/netlist/plib/pchrono.cpp
Normal 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
|
||||
|
||||
}
|
||||
}
|
213
src/lib/netlist/plib/pchrono.h
Normal file
213
src/lib/netlist/plib/pchrono.h
Normal 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_ */
|
@ -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.
|
||||
|
226
src/lib/netlist/plib/poptions.cpp
Normal file
226
src/lib/netlist/plib/poptions.cpp
Normal 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
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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++)
|
||||
{
|
||||
|
@ -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[];
|
||||
|
||||
|
@ -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
|
||||
|
||||
/*
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user