Netlist: code maintenance and improvements. [Couriersud]

- Added support for line markers to the preprocessor and parser.
- Added support for include processing to the preprocessor.
- Moved sources base type to plib to be used for preprocessor includes.
  This enables to include e.g. from rom memory regions.
- Renamed some defines
This commit is contained in:
couriersud 2019-10-18 17:57:55 +02:00
parent ad27643c07
commit b09fa00cca
27 changed files with 508 additions and 210 deletions

View File

@ -286,13 +286,13 @@ public:
: netlist::nl_exception(plib::pfmt(fmt)(std::forward<Args>(args)...)) { }
};
class netlist_source_memregion_t : public netlist::source_t
class netlist_source_memregion_t : public netlist::source_netlist_t
{
public:
netlist_source_memregion_t(device_t &dev, pstring name)
: netlist::source_t(), m_dev(dev), m_name(name)
: netlist::source_netlist_t(), m_dev(dev), m_name(name)
{
}
@ -302,7 +302,7 @@ private:
pstring m_name;
};
class netlist_data_memregions_t : public netlist::source_t
class netlist_data_memregions_t : public netlist::source_data_t
{
public:
netlist_data_memregions_t(const device_t &dev);
@ -333,7 +333,7 @@ plib::unique_ptr<std::istream> netlist_source_memregion_t::stream(const pstring
}
netlist_data_memregions_t::netlist_data_memregions_t(const device_t &dev)
: netlist::source_t(netlist::source_t::DATA), m_dev(dev)
: netlist::source_data_t(), m_dev(dev)
{
}

View File

@ -66,7 +66,7 @@ namespace devices
LIB_ENTRY(2102A_dip)
LIB_ENTRY(2716)
LIB_ENTRY(2716_dip)
#if !(USE_TRUTHTABLE_7448)
#if !(NL_USE_TRUTHTABLE_7448)
LIB_ENTRY(7448)
LIB_ENTRY(7448_dip)
#endif
@ -92,7 +92,7 @@ namespace devices
LIB_ENTRY(7493_dip)
LIB_ENTRY(7497)
LIB_ENTRY(7497_dip)
#if (!USE_TRUTHTABLE_74107)
#if (!NL_USE_TRUTHTABLE_74107)
LIB_ENTRY(74107)
LIB_ENTRY(74107_dip)
#endif

View File

@ -145,7 +145,7 @@ namespace netlist
m_clk.activate_hl();
}
#if (!USE_TRUTHTABLE_74107)
#if (!NL_USE_TRUTHTABLE_74107)
NETLIB_DEVICE_IMPL(74107, "TTL_74107", "+CLK,+J,+K,+CLRQ,@VCC,@GND")
NETLIB_DEVICE_IMPL(74107_dip, "TTL_74107_DIP", "")
#endif

View File

@ -75,7 +75,7 @@
NET_CONNECT(name, K, cK) \
NET_CONNECT(name, CLRQ, cCLRQ)
#if (!USE_TRUTHTABLE_74107)
#if (!NL_USE_TRUTHTABLE_74107)
#define TTL_74107(name, cCLK, cJ, cK, cCLRQ) \
TTL_74107A(name, cCLK, cJ, cK, cCLRQ)

View File

@ -15,7 +15,7 @@ namespace netlist
{
namespace devices
{
#if !(USE_TRUTHTABLE_7448)
#if !(NL_USE_TRUTHTABLE_7448)
NETLIB_OBJECT(7448)
{
NETLIB_CONSTRUCTOR(7448)
@ -79,7 +79,7 @@ namespace netlist
#endif
#if !(USE_TRUTHTABLE_7448)
#if !(NL_USE_TRUTHTABLE_7448)
#define BITS7(b6,b5,b4,b3,b2,b1,b0) ((b6)<<6) | ((b5)<<5) | ((b4)<<4) | ((b3)<<3) | ((b2)<<2) | ((b1)<<1) | ((b0)<<0)

View File

@ -27,7 +27,7 @@
#include "netlist/nl_setup.h"
#ifndef NL_AUTO_DEVICES
#if !(USE_TRUTHTABLE_7448)
#if !(NL_USE_TRUTHTABLE_7448)
#define TTL_7448(name, cA0, cA1, cA2, cA3, cLTQ, cBIQ, cRBIQ) \
NET_REGISTER_DEV(TTL_7448, name) \
NET_CONNECT(name, VCC, VCC) \

View File

@ -604,7 +604,7 @@ static NETLIST_START(TTL_7486_DIP)
)
NETLIST_END()
#if (USE_TRUTHTABLE_74107)
#if (NL_USE_TRUTHTABLE_74107)
#ifndef __PLIB_PREPROCESSOR__
#define TTL_74107_TT(name) \
NET_REGISTER_DEV(TTL_74107, name)
@ -846,7 +846,7 @@ static NETLIST_START(DM9312_DIP)
)
NETLIST_END()
#if (USE_TRUTHTABLE_7448)
#if (NL_USE_TRUTHTABLE_7448)
/*
* DM7448: BCD to 7-Segment decoders/drivers
@ -1115,7 +1115,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
#if (USE_TRUTHTABLE_7448)
#if (NL_USE_TRUTHTABLE_7448)
TRUTHTABLE_START(TTL_7448, 7, 7, "+A,+B,+C,+D,+LTQ,+BIQ,+RBIQ,@VCC,@GND")
TT_HEAD(" LTQ,BIQ,RBIQ, A , B , C , D | a, b, c, d, e, f, g")
@ -1207,7 +1207,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
#if (USE_TRUTHTABLE_74107)
#if (NL_USE_TRUTHTABLE_74107)
/*
* +-----+-----+-----+---++---+-----+
* | CLRQ| CLK | J | K || Q | QQ |
@ -1379,11 +1379,11 @@ NETLIST_START(TTL74XX_lib)
LOCAL_LIB_ENTRY(TTL_7430_DIP)
LOCAL_LIB_ENTRY(TTL_7432_DIP)
LOCAL_LIB_ENTRY(TTL_7437_DIP)
#if (USE_TRUTHTABLE_7448)
#if (NL_USE_TRUTHTABLE_7448)
LOCAL_LIB_ENTRY(TTL_7448_DIP)
#endif
LOCAL_LIB_ENTRY(TTL_7486_DIP)
#if (USE_TRUTHTABLE_74107)
#if (NL_USE_TRUTHTABLE_74107)
LOCAL_LIB_ENTRY(TTL_74107_DIP)
#endif
LOCAL_LIB_ENTRY(TTL_74155_DIP)

View File

@ -209,7 +209,7 @@
NET_REGISTER_DEV(TTL_7437_DIP, name)
#if (USE_TRUTHTABLE_7448)
#if (NL_USE_TRUTHTABLE_7448)
#define TTL_7448(name, cA0, cA1, cA2, cA3, cLTQ, cBIQ, cRBIQ) \
NET_REGISTER_DEV(TTL_7448, name) \
NET_CONNECT(name, VCC, VCC) \
@ -240,7 +240,7 @@
#define TTL_7486_DIP(name) \
NET_REGISTER_DEV(TTL_7486_DIP, name)
#if (USE_TRUTHTABLE_74107)
#if (NL_USE_TRUTHTABLE_74107)
#define TTL_74107(name, cCLK, cJ, cK, cCLRQ) \
NET_REGISTER_DEV(TTL_74107, name) \
NET_CONNECT(name, GND, GND) \

View File

@ -254,23 +254,46 @@ namespace netlist
void netlist_state_t::compile_defines(std::vector<std::pair<pstring, pstring>> &defs)
{
//#define ENTRY(x) { #x, PSTRINGIFY(x) }
#define ENTRY(x) std::pair<pstring, pstring>(#x, PSTRINGIFY(x))
defs.emplace_back(ENTRY(PHAS_RDTSCP));
defs.emplace_back(ENTRY(PUSE_ACCURATE_STATS));
defs.emplace_back(ENTRY(PHAS_INT128));
defs.emplace_back(ENTRY(USE_ALIGNED_OPTIMIZATIONS));
defs.emplace_back(ENTRY(NVCCBUILD));
defs.emplace_back(ENTRY(USE_MEMPOOL));
defs.emplace_back(ENTRY(USE_QUEUE_STATS));
defs.emplace_back(ENTRY(USE_COPY_INSTEAD_OF_REFERENCE));
defs.emplace_back(ENTRY(USE_TRUTHTABLE_7448));
defs.emplace_back(ENTRY(NL_DEBUG));
defs.emplace_back(ENTRY(HAS_OPENMP));
defs.emplace_back(ENTRY(USE_OPENMP));
#define ENTRY(x) if (pstring(#x) != PSTRINGIFY(x)) defs.emplace_back(std::pair<pstring, pstring>(#x, PSTRINGIFY(x)));
ENTRY(PHAS_RDTSCP)
ENTRY(PUSE_ACCURATE_STATS)
ENTRY(PHAS_INT128)
ENTRY(PUSE_ALIGNED_OPTIMIZATIONS)
ENTRY(PHAS_OPENMP)
ENTRY(PUSE_OPENMP)
ENTRY(PPMF_TYPE)
ENTRY(PHAS_PMF_INTERNAL)
ENTRY(NL_USE_MEMPOOL)
ENTRY(NL_USE_QUEUE_STATS)
ENTRY(NL_USE_COPY_INSTEAD_OF_REFERENCE)
ENTRY(NL_USE_TRUTHTABLE_7448)
ENTRY(NL_AUTO_DEVICES)
ENTRY(NL_DEBUG)
ENTRY(NVCCBUILD)
defs.emplace_back(ENTRY(PPMF_TYPE));
defs.emplace_back(ENTRY(PHAS_PMF_INTERNAL));
ENTRY(__cplusplus)
ENTRY(__VERSION__)
ENTRY(__GNUC__)
ENTRY(__GNUC_MINOR__)
ENTRY(__GNUC_PATCHLEVEL__)
ENTRY(__clang__)
ENTRY(__clang_major__)
ENTRY(__clang_minor__)
ENTRY(__clang_patchlevel__)
ENTRY(__clang_version__)
ENTRY(OPENMP )
ENTRY(_OPENMP )
ENTRY(__x86_64__ )
ENTRY(__i386__)
ENTRY(_WIN32)
ENTRY(_MSC_VER)
ENTRY(__APPLE__)
ENTRY(__unix__)
ENTRY(__linux__)
#undef ENTRY
}
@ -417,7 +440,7 @@ namespace netlist
log().verbose("Total time {1:15}", total_time);
// FIXME: clang complains about unreachable code without
const auto clang_workaround_unreachable_code = USE_QUEUE_STATS;
const auto clang_workaround_unreachable_code = NL_USE_QUEUE_STATS;
if (clang_workaround_unreachable_code)
{
/* Only one serialization should be counted in total time */
@ -717,7 +740,7 @@ namespace netlist
: device_object_t(dev, dev.name() + "." + aname)
, plib::linkedlist_t<core_terminal_t>::element_t()
, m_delegate(delegate)
#if USE_COPY_INSTEAD_OF_REFERENCE
#if NL_USE_COPY_INSTEAD_OF_REFERENCE
, m_Q(*this, "m_Q", 0)
#endif
, m_net(nullptr)

View File

@ -589,7 +589,7 @@ namespace netlist
void reset() noexcept { set_state(is_type(OUTPUT) ? STATE_OUT : STATE_INP_ACTIVE); }
nldelegate m_delegate;
#if USE_COPY_INSTEAD_OF_REFERENCE
#if NL_USE_COPY_INSTEAD_OF_REFERENCE
void set_copied_input(netlist_sig_t val) noexcept
{
m_Q = val;
@ -667,7 +667,7 @@ namespace netlist
void move_connections(net_t &dest_net);
std::vector<core_terminal_t *> &core_terms() { return m_core_terms; }
#if USE_COPY_INSTEAD_OF_REFERENCE
#if NL_USE_COPY_INSTEAD_OF_REFERENCE
void update_inputs() noexcept
{
for (auto & term : m_core_terms)
@ -1553,7 +1553,7 @@ namespace netlist
void process_queue(netlist_time delta) NL_NOEXCEPT;
void abort_current_queue_slice() NL_NOEXCEPT
{
if (!USE_QUEUE_STATS || !m_use_stats)
if (!NL_USE_QUEUE_STATS || !m_use_stats)
m_queue.retime<false>(detail::queue_t::entry_t(m_time, nullptr));
else
m_queue.retime<true>(detail::queue_t::entry_t(m_time, nullptr));
@ -1564,7 +1564,7 @@ namespace netlist
template <typename E>
void qpush(E && e) noexcept
{
if (!USE_QUEUE_STATS || !m_use_stats)
if (!NL_USE_QUEUE_STATS || !m_use_stats)
m_queue.push<false>(std::forward<E>(e)); // NOLINT(performance-move-const-arg)
else
m_queue.push<true>(std::forward<E>(e)); // NOLINT(performance-move-const-arg)
@ -1573,7 +1573,7 @@ namespace netlist
template <class R>
void qremove(const R &elem) noexcept
{
if (!USE_QUEUE_STATS || !m_use_stats)
if (!NL_USE_QUEUE_STATS || !m_use_stats)
m_queue.remove<false>(elem);
else
m_queue.remove<true>(elem);
@ -1860,7 +1860,7 @@ namespace netlist
nl_assert(terminal_state() != STATE_INP_PASSIVE);
//if (net().Q() != m_Q)
// printf("term: %s, %d %d TS %d\n", this->name().c_str(), net().Q(), m_Q, terminal_state());
#if USE_COPY_INSTEAD_OF_REFERENCE
#if NL_USE_COPY_INSTEAD_OF_REFERENCE
return m_Q;
#else
return net().Q();

View File

@ -28,8 +28,8 @@
* Your mileage may vary.
*
*/
#ifndef USE_MEMPOOL
#define USE_MEMPOOL (1)
#ifndef NL_USE_MEMPOOL
#define NL_USE_MEMPOOL (1)
#endif
/*! Enable queue statistics.
@ -39,8 +39,8 @@
* only needed during development.
*
*/
#ifndef USE_QUEUE_STATS
#define USE_QUEUE_STATS (0)
#ifndef NL_USE_QUEUE_STATS
#define NL_USE_QUEUE_STATS (0)
#endif
/*! Store input values in logic_terminal_t.
@ -53,8 +53,8 @@
* the default approach. It is up to 10% slower.
*
*/
#ifndef USE_COPY_INSTEAD_OF_REFERENCE
#define USE_COPY_INSTEAD_OF_REFERENCE (0)
#ifndef NL_USE_COPY_INSTEAD_OF_REFERENCE
#define NL_USE_COPY_INSTEAD_OF_REFERENCE (0)
#endif
/*
@ -63,7 +63,9 @@
* setting param USE_DEACTIVATE for the device.
*/
#define USE_TRUTHTABLE_7448 (0)
#ifndef NL_USE_TRUTHTABLE_7448
#define NL_USE_TRUTHTABLE_7448 (0)
#endif
/*
* FIXME: The truthtable implementation of 74107 (JK-Flipflop)
@ -72,7 +74,9 @@
* It will completely nuke performance for pong.
*/
#define USE_TRUTHTABLE_74107 (0)
#ifndef NL_USE_TRUTHTABLE_74107
#define NL_USE_TRUTHTABLE_74107 (0)
#endif
//============================================================
// DEBUGGING

View File

@ -87,12 +87,21 @@ namespace netlist
void nlparse_t::include(const pstring &netlist_name)
{
for (auto &source : m_sources)
#if 0
for (auto &base : m_sources)
{
if (source->parse(*this, netlist_name))
auto source(dynamic_cast<source_netlist_t *>(base.get()));
if (source && source->parse(*this, netlist_name))
return;
}
log().fatal(MF_NOT_FOUND_IN_SOURCE_COLLECTION(netlist_name));
#endif
if (m_sources.for_all<source_netlist_t>(netlist_name, [this, &netlist_name] (auto &src)
{
return src->parse(*this, netlist_name);
}))
return;
log().fatal(MF_NOT_FOUND_IN_SOURCE_COLLECTION(netlist_name));
}
@ -206,9 +215,9 @@ namespace netlist
return false;
}
bool nlparse_t::parse_stream(plib::unique_ptr<std::istream> &&istrm, const pstring &name)
bool nlparse_t::parse_stream(plib::psource_t::stream_ptr &&istrm, const pstring &name)
{
plib::ppreprocessor y(&m_defines);
plib::ppreprocessor y(m_includes, &m_defines);
plib::ppreprocessor &x(y.process(std::move(istrm)));
return parser_t(std::move(x), *this).parse(name);
//return parser_t(std::move(plib::ppreprocessor(&m_defines).process(std::move(istrm))), *this).parse(name);
@ -239,12 +248,6 @@ setup_t::setup_t(netlist_state_t &nlstate)
setup_t::~setup_t() noexcept
{
// FIXME: can't see a need any longer
m_links.clear();
m_params.clear();
m_terminals.clear();
m_param_values.clear();
m_sources.clear();
}
pstring setup_t::termtype_as_str(detail::core_terminal_t &in) const
@ -1019,19 +1022,13 @@ const logic_family_desc_t *setup_t::family_from_model(const pstring &model)
// Sources
// ----------------------------------------------------------------------------------------
plib::unique_ptr<std::istream> setup_t::get_data_stream(const pstring &name)
plib::psource_t::stream_ptr setup_t::get_data_stream(const pstring &name)
{
for (auto &source : m_sources)
{
if (source->type() == source_t::DATA)
{
auto strm = source->stream(name);
if (strm)
return strm;
}
}
auto strm = m_sources.get_stream<source_data_t>(name);
if (strm)
return strm;
log().warning(MW_DATA_1_NOT_FOUND(name));
return plib::unique_ptr<std::istream>(nullptr);
return plib::psource_t::stream_ptr(nullptr);
}
@ -1185,21 +1182,16 @@ void setup_t::prepare_to_run()
// base sources
// ----------------------------------------------------------------------------------------
bool source_t::parse(nlparse_t &setup, const pstring &name)
bool source_netlist_t::parse(nlparse_t &setup, const pstring &name)
{
if (m_type != SOURCE)
return false;
auto strm(stream(name));
if (strm)
return setup.parse_stream(std::move(strm), name);
else
{
auto strm(stream(name));
if (strm)
return setup.parse_stream(std::move(strm), name);
else
return false;
}
return false;
}
plib::unique_ptr<std::istream> source_string_t::stream(const pstring &name)
source_string_t::stream_ptr source_string_t::stream(const pstring &name)
{
plib::unused_var(name);
auto ret(plib::make_unique<std::istringstream>(m_str));
@ -1207,7 +1199,7 @@ plib::unique_ptr<std::istream> source_string_t::stream(const pstring &name)
return std::move(ret);
}
plib::unique_ptr<std::istream> source_mem_t::stream(const pstring &name)
source_mem_t::stream_ptr source_mem_t::stream(const pstring &name)
{
plib::unused_var(name);
auto ret(plib::make_unique<std::istringstream>(m_str, std::ios_base::binary));
@ -1215,14 +1207,14 @@ plib::unique_ptr<std::istream> source_mem_t::stream(const pstring &name)
return std::move(ret);
}
plib::unique_ptr<std::istream> source_file_t::stream(const pstring &name)
source_file_t::stream_ptr source_file_t::stream(const pstring &name)
{
plib::unused_var(name);
auto ret(plib::make_unique<std::ifstream>(plib::filesystem::u8path(m_filename)));
if (ret->is_open())
return std::move(ret);
else
return plib::unique_ptr<std::istream>(nullptr);
return stream_ptr(nullptr);
}
bool source_proc_t::parse(nlparse_t &setup, const pstring &name)
@ -1236,10 +1228,10 @@ bool source_proc_t::parse(nlparse_t &setup, const pstring &name)
return false;
}
plib::unique_ptr<std::istream> source_proc_t::stream(const pstring &name)
source_proc_t::stream_ptr source_proc_t::stream(const pstring &name)
{
plib::unused_var(name);
plib::unique_ptr<std::istream> p(nullptr);
stream_ptr p(nullptr);
return p;
}

View File

@ -79,7 +79,7 @@ void NETLIST_NAME(name)(netlist::nlparse_t &setup) \
#define SUBMODEL(model, name) \
setup.namespace_push(# name); \
setup.include(# model); \
setup.include(# model); \
/*NETLIST_NAME(model)(setup);*/ \
setup.namespace_pop();
@ -167,42 +167,38 @@ namespace netlist
};
// ----------------------------------------------------------------------------------------
// A Generic netlist sources implementation
// Specific netlist psource_t implementations
// ----------------------------------------------------------------------------------------
class source_t
class source_netlist_t : public plib::psource_t
{
public:
friend class setup_t;
enum type_t
{
SOURCE,
DATA
};
using list_t = std::vector<plib::unique_ptr<source_t>>;
source_t(const type_t type = SOURCE)
: m_type(type)
source_netlist_t()
: plib::psource_t()
{}
COPYASSIGNMOVE(source_t, delete)
virtual ~source_t() noexcept = default;
COPYASSIGNMOVE(source_netlist_t, delete)
virtual ~source_netlist_t() noexcept = default;
virtual bool parse(nlparse_t &setup, const pstring &name);
type_t type() const { return m_type; }
protected:
virtual plib::unique_ptr<std::istream> stream(const pstring &name) = 0;
private:
const type_t m_type;
};
class source_data_t : public plib::psource_t
{
public:
friend class setup_t;
source_data_t()
: plib::psource_t()
{}
COPYASSIGNMOVE(source_data_t, delete)
virtual ~source_data_t() noexcept = default;
};
// ----------------------------------------------------------------------------------------
// Collection of models
@ -253,9 +249,9 @@ namespace netlist
void register_frontier(const pstring &attach, const double r_IN, const double r_OUT);
/* register a source */
void register_source(plib::unique_ptr<source_t> &&src)
void register_source(plib::unique_ptr<plib::psource_t> &&src)
{
m_sources.push_back(std::move(src));
m_sources.add_source(std::move(src));
}
void tt_factory_create(tt_desc &desc, const pstring &sourcefile);
@ -279,7 +275,12 @@ namespace netlist
bool device_exists(const pstring &name) const;
/* FIXME: used by source_t - need a different approach at some time */
bool parse_stream(plib::unique_ptr<std::istream> &&istrm, const pstring &name);
bool parse_stream(plib::psource_t::stream_ptr &&istrm, const pstring &name);
void add_include(plib::unique_ptr<plib::psource_t> &&inc)
{
m_includes.add_source(std::move(inc));
}
void add_define(const pstring &def, const pstring &val)
{
@ -314,7 +315,7 @@ namespace netlist
std::vector<link_t> m_links;
std::unordered_map<pstring, pstring> m_param_values;
source_t::list_t m_sources;
plib::psource_collection_t<> m_sources;
factory::list_t m_factory;
@ -324,6 +325,7 @@ namespace netlist
private:
plib::ppreprocessor::defines_map_type m_defines;
plib::psource_collection_t<> m_includes;
setup_t &m_setup;
log_type &m_log;
@ -364,7 +366,7 @@ namespace netlist
void register_dynamic_log_devices();
void resolve_inputs();
plib::unique_ptr<std::istream> get_data_stream(const pstring &name);
plib::psource_t::stream_ptr get_data_stream(const pstring &name);
factory::list_t &factory() { return m_factory; }
const factory::list_t &factory() const { return m_factory; }
@ -432,58 +434,58 @@ namespace netlist
// base sources
// ----------------------------------------------------------------------------------------
class source_string_t : public source_t
class source_string_t : public source_netlist_t
{
public:
source_string_t(const pstring &source)
: source_t(), m_str(source)
: source_netlist_t(), m_str(source)
{
}
protected:
plib::unique_ptr<std::istream> stream(const pstring &name) override;
stream_ptr stream(const pstring &name) override;
private:
pstring m_str;
};
class source_file_t : public source_t
class source_file_t : public source_netlist_t
{
public:
source_file_t(const pstring &filename)
: source_t(), m_filename(filename)
: source_netlist_t(), m_filename(filename)
{
}
protected:
plib::unique_ptr<std::istream> stream(const pstring &name) override;
stream_ptr stream(const pstring &name) override;
private:
pstring m_filename;
};
class source_mem_t : public source_t
class source_mem_t : public source_netlist_t
{
public:
source_mem_t(const char *mem)
: source_t(), m_str(mem)
: source_netlist_t(), m_str(mem)
{
}
protected:
plib::unique_ptr<std::istream> stream(const pstring &name) override;
stream_ptr stream(const pstring &name) override;
private:
pstring m_str;
};
class source_proc_t : public source_t
class source_proc_t : public source_netlist_t
{
public:
source_proc_t(const pstring &name, void (*setup_func)(nlparse_t &))
: source_t(),
: source_netlist_t(),
m_setup_func(setup_func),
m_setup_func_name(name)
{
@ -492,7 +494,7 @@ namespace netlist
bool parse(nlparse_t &setup, const pstring &name) override;
protected:
plib::unique_ptr<std::istream> stream(const pstring &name) override;
stream_ptr stream(const pstring &name) override;
private:
void (*m_setup_func)(nlparse_t &);

View File

@ -78,7 +78,7 @@ namespace netlist
*
*/
#if (USE_MEMPOOL)
#if (NL_USE_MEMPOOL)
using nlmempool = plib::mempool;
#else
using nlmempool = plib::aligned_arena;

View File

@ -276,7 +276,7 @@ namespace plib {
static inline void *allocate( size_t alignment, size_t size )
{
#if (USE_ALIGNED_ALLOCATION)
#if (PUSE_ALIGNED_ALLOCATION)
#if defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)
return _aligned_malloc(size, alignment);
#elif defined(__APPLE__)
@ -296,7 +296,7 @@ namespace plib {
static inline void deallocate( void *ptr )
{
#if (USE_ALIGNED_ALLOCATION)
#if (PUSE_ALIGNED_ALLOCATION)
// NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
free(ptr);
#else
@ -352,7 +352,7 @@ namespace plib {
//auto t = reinterpret_cast<std::uintptr_t>(p);
//if (t & (ALIGN-1))
// printf("alignment error!");
#if (USE_ALIGNED_HINTS)
#if (PUSE_ALIGNED_HINTS)
return reinterpret_cast<T *>(__builtin_assume_aligned(p, ALIGN));
#else
return p;
@ -364,7 +364,7 @@ namespace plib {
{
static_assert(ALIGN >= alignof(T), "Alignment must be greater or equal to alignof(T)");
static_assert(is_pow2(ALIGN), "Alignment must be a power of 2");
#if (USE_ALIGNED_HINTS)
#if (PUSE_ALIGNED_HINTS)
return reinterpret_cast<const T *>(__builtin_assume_aligned(p, ALIGN));
#else
return p;

View File

@ -38,20 +38,20 @@
* netlists like kidniki.
*/
#ifndef USE_OPENMP
#define USE_OPENMP (0)
#ifndef PUSE_OPENMP
#define PUSE_OPENMP (0)
#endif
/*
* Set this to one if you want to use aligned storage optimizations.
*/
#ifndef USE_ALIGNED_OPTIMIZATIONS
#define USE_ALIGNED_OPTIMIZATIONS (0)
#ifndef PUSE_ALIGNED_OPTIMIZATIONS
#define PUSE_ALIGNED_OPTIMIZATIONS (0)
#endif
#define USE_ALIGNED_ALLOCATION (USE_ALIGNED_OPTIMIZATIONS)
#define USE_ALIGNED_HINTS (USE_ALIGNED_OPTIMIZATIONS)
#define PUSE_ALIGNED_ALLOCATION (PUSE_ALIGNED_OPTIMIZATIONS)
#define PUSE_ALIGNED_HINTS (PUSE_ALIGNED_OPTIMIZATIONS)
/*
* Standard alignment macros
*/
@ -114,11 +114,19 @@ typedef __int128_t INT128;
//============================================================
#if defined(OPENMP)
#define HAS_OPENMP ( OPENMP >= 200805 )
#elif defined(_OPENMP)
#define HAS_OPENMP ( _OPENMP >= 200805 )
#if ( OPENMP >= 200805 )
#define PHAS_OPENMP (1)
#else
#define HAS_OPENMP (0)
#define PHAS_OPENMP (0)
#endif
#elif defined(_OPENMP)
#if ( _OPENMP >= 200805 )
#define PHAS_OPENMP (1)
#else
#define PHAS_OPENMP (0)
#endif
#else
#define PHAS_OPENMP (0)
#endif
@ -126,8 +134,8 @@ typedef __int128_t INT128;
// WARNINGS
//============================================================
#if (USE_OPENMP)
#if (!(HAS_OPENMP))
#if (PUSE_OPENMP)
#if (!(PHAS_OPENMP))
#error To use openmp compile and link with "-fopenmp"
#endif
#endif

View File

@ -112,10 +112,10 @@ pfmt::rtype pfmt::setfmt(std::stringstream &strm, char32_t cfmt_spec)
else if (pdot != pstring::npos)
{
strm << std::setprecision(pstonum<int>(fmt.substr(pdot + 1)));
r.width = pstonum<pstring::size_type>(left(fmt,pdot));
r.width = pstonum<int>(left(fmt,pdot));
}
else if (fmt != "")
r.width = pstonum<pstring::size_type>(fmt);
r.width = pstonum<int>(fmt);
switch (r.pend)
{

View File

@ -227,7 +227,7 @@ protected:
pstring::size_type p;
pstring::size_type sl;
char32_t pend;
pstring::size_type width;
int width;
};
rtype setfmt(std::stringstream &strm, char32_t cfmt_spec);
@ -248,10 +248,14 @@ protected:
strm << std::forward<T>(val);
const pstring ps(strm.str());
pstring pad("");
if (ret.width > ps.length())
pad = pstring(ret.width - ps.length(), ' ');
std::size_t aw(std::abs(ret.width));
if (aw > ps.length())
pad = pstring(aw - ps.length(), ' ');
m_str = m_str.substr(0, ret.p) + pad + ps + m_str.substr(ret.p + ret.sl);
if (ret.width > 0)
m_str = m_str.substr(0, ret.p) + pad + ps + m_str.substr(ret.p + ret.sl);
else
m_str = m_str.substr(0, ret.p) + ps + pad + m_str.substr(ret.p + ret.sl);
}
} while (ret.ret == 1);

View File

@ -14,7 +14,7 @@
#include <cstdint>
#if HAS_OPENMP
#if PHAS_OPENMP
#include "omp.h"
#endif
@ -26,7 +26,7 @@ void for_static(std::size_t numops, const I start, const I end, const T &what)
{
if (numops>1000)
{
#if HAS_OPENMP && USE_OPENMP
#if PHAS_OPENMP && PUSE_OPENMP
#pragma omp parallel for schedule(static)
#endif
for (I i = start; i < end; i++)
@ -40,7 +40,7 @@ void for_static(std::size_t numops, const I start, const I end, const T &what)
template <typename I, class T>
void for_static(const I start, const I end, const T &what)
{
#if HAS_OPENMP && USE_OPENMP
#if PHAS_OPENMP && PUSE_OPENMP
#pragma omp parallel for schedule(static)
#endif
for (I i = start; i < end; i++)
@ -57,7 +57,7 @@ void for_static_np(const I start, const I end, const T &what)
inline void set_num_threads(const std::size_t threads)
{
#if HAS_OPENMP && USE_OPENMP
#if PHAS_OPENMP && PUSE_OPENMP
omp_set_num_threads(threads);
#else
plib::unused_var(threads);
@ -66,7 +66,7 @@ inline void set_num_threads(const std::size_t threads)
inline std::size_t get_max_threads()
{
#if HAS_OPENMP && USE_OPENMP
#if PHAS_OPENMP && PUSE_OPENMP
return omp_get_max_threads();
#else
return 1;

View File

@ -149,6 +149,23 @@ ptokenizer::token_t ptokenizer::get_token()
if (ret.is_type(ENDOFFILE))
return ret;
if (m_support_line_markers && ret.is_type(LINEMARKER))
{
// FIXME: do something with information gathered
ret = get_token_internal();
if (!ret.is_type(NUMBER))
error(pfmt("Expected line number after line marker but got <{1}>")(ret.str()) );
ret = get_token_internal();
if (!ret.is_type(STRING))
error(pfmt("Expected file name after line marker but got <{1}>")(ret.str()) );
ret = get_token_internal();
while (ret.is_type(NUMBER))
{
// FIXME: process flags; actually only 1 (file enter) and 2 (after file exit)
ret = get_token_internal();
}
}
if (ret.is(m_tok_comment_start))
{
do {
@ -184,7 +201,9 @@ ptokenizer::token_t ptokenizer::get_token_internal()
return token_t(ENDOFFILE);
}
}
if (m_number_chars_start.find(c) != pstring::npos)
if (m_support_line_markers && c == '#')
return token_t(LINEMARKER);
else if (m_number_chars_start.find(c) != pstring::npos)
{
/* read number while we receive number or identifier chars
* treat it as an identifier when there are identifier chars in it
@ -259,11 +278,11 @@ ptokenizer::token_t ptokenizer::get_token_internal()
// A simple preprocessor
// ----------------------------------------------------------------------------------------
ppreprocessor::ppreprocessor(defines_map_type *defines)
ppreprocessor::ppreprocessor(psource_collection_t<> &sources, defines_map_type *defines)
: std::istream(new readbuffer(this))
, m_sources(sources)
, m_if_flag(0)
, m_if_level(0)
, m_lineno(0)
, m_pos(0)
, m_state(PROCESS)
, m_comment(false)
@ -289,7 +308,20 @@ ppreprocessor::ppreprocessor(defines_map_type *defines)
void ppreprocessor::error(const pstring &err)
{
throw pexception("PREPRO ERROR: " + err);
pstring s("");
pstring trail (" from ");
pstring trail_first("In file included from ");
pstring e = plib::pfmt("PREPRO ERROR: {1}:{2}:0: error: {3}\n")
(m_stack.top().m_name, m_stack.top().m_lineno, err);
m_stack.pop();
while (m_stack.size() > 0)
{
if (m_stack.size() == 1)
trail = trail_first;
s = trail + plib::pfmt("{1}:{2}:0\n")(m_stack.top().m_name, m_stack.top().m_lineno) + s;
m_stack.pop();
}
throw pexception("\n" + s + e);
}
#define CHECKTOK2(p_op, p_prio) \
@ -504,7 +536,38 @@ pstring ppreprocessor::process_line(pstring line)
}
else if (lti[0] == "#include")
{
// ignore
if (m_if_flag == 0)
{
pstring arg("");
for (std::size_t i=1; i<lti.size(); i++)
arg += (lti[i] + " ");
arg = plib::trim(arg);
if (startsWith(arg, "\"") && endsWith(arg, "\""))
{
arg = arg.substr(1, arg.length() - 2);
/* first try local context */
auto l(plib::util::buildpath({m_stack.top().m_local_path, arg}));
auto lstrm(m_sources.get_stream<>(l));
if (lstrm)
{
m_stack.emplace(input_context(std::move(lstrm), plib::util::path(l), l));
}
else
{
auto strm(m_sources.get_stream<>(arg));
if (strm)
{
m_stack.emplace(input_context(std::move(strm), plib::util::path(arg), arg));
}
else
error("include not found:" + arg);
}
}
else
error("include misspelled:" + arg);
}
}
else if (lti[0] == "#pragma")
{
@ -519,7 +582,7 @@ pstring ppreprocessor::process_line(pstring line)
if (m_if_flag == 0)
{
if (lti.size() < 2)
error("PREPRO: define needs at least one argument: " + line);
error("define needs at least one argument: " + line);
else if (lti.size() == 2)
m_defines.insert({lti[1], define_t(lti[1], "")});
else
@ -535,7 +598,7 @@ pstring ppreprocessor::process_line(pstring line)
else
{
if (m_if_flag == 0)
error(pfmt("unknown directive on line {1}: {2}")(m_lineno)(replace_macros(line)));
error(pfmt("unknown directive on line {1}: {2}")(m_stack.top().m_lineno)(replace_macros(line)));
}
}
else
@ -547,6 +610,28 @@ pstring ppreprocessor::process_line(pstring line)
return ret;
}
void ppreprocessor::process_stack()
{
while (m_stack.size() > 0)
{
pstring line;
pstring linemarker = pfmt("# {1} \"{2}\" 1\n")(m_stack.top().m_lineno, m_stack.top().m_name);
m_outbuf += decltype(m_outbuf)(linemarker.c_str());
while (m_stack.top().m_reader.readline(line))
{
m_stack.top().m_lineno++;
line = process_line(line);
m_outbuf += decltype(m_outbuf)(line.c_str()) + static_cast<char>(10);
}
m_stack.pop();
if (m_stack.size() > 0)
{
linemarker = pfmt("# {1} \"{2}\" 2\n")(m_stack.top().m_lineno, m_stack.top().m_name);
m_outbuf += decltype(m_outbuf)(linemarker.c_str());
}
}
}
} // namespace plib

View File

@ -12,9 +12,11 @@
#include "pstream.h"
#include "pstring.h"
#include "putil.h" // psource_t
//#include <cstdint>
#include <unordered_map>
#include <stack>
namespace plib {
class ptokenizer
@ -28,6 +30,7 @@ public:
, m_px(m_cur_line.begin())
, m_unget(0)
, m_string('"')
, m_support_line_markers(true) // FIXME
{
}
@ -42,6 +45,7 @@ public:
TOKEN,
STRING,
COMMENT,
LINEMARKER,
UNKNOWN,
ENDOFFILE
};
@ -156,6 +160,7 @@ private:
token_id_t m_tok_comment_start;
token_id_t m_tok_comment_end;
token_id_t m_tok_line_comment;
bool m_support_line_markers;
};
@ -174,7 +179,24 @@ public:
using defines_map_type = std::unordered_map<pstring, define_t>;
explicit ppreprocessor(defines_map_type *defines = nullptr);
explicit ppreprocessor(psource_collection_t<> &sources, defines_map_type *defines = nullptr);
COPYASSIGN(ppreprocessor, delete)
ppreprocessor &operator=(ppreprocessor &&src) = delete;
ppreprocessor(ppreprocessor &&s) noexcept
: std::istream(new readbuffer(this))
, m_defines(std::move(s.m_defines))
, m_sources(s.m_sources)
, m_expr_sep(std::move(s.m_expr_sep))
, m_if_flag(s.m_if_flag)
, m_if_level(s.m_if_level)
, m_outbuf(std::move(s.m_outbuf))
, m_pos(s.m_pos)
, m_state(s.m_state)
, m_comment(s.m_comment)
{
}
~ppreprocessor() override
{
@ -184,34 +206,11 @@ public:
template <typename T>
ppreprocessor & process(T &&istrm)
{
putf8_reader reader(std::forward<T>(istrm));
pstring line;
while (reader.readline(line))
{
m_lineno++;
line = process_line(line);
m_outbuf += decltype(m_outbuf)(line.c_str()) + static_cast<char>(10);
}
m_stack.emplace(input_context(std::forward<T>(istrm),"","<stream>"));
process_stack();
return *this;
}
COPYASSIGN(ppreprocessor, delete)
ppreprocessor &operator=(ppreprocessor &&src) = delete;
ppreprocessor(ppreprocessor &&s) noexcept
: std::istream(new readbuffer(this))
, m_defines(std::move(s.m_defines))
, m_expr_sep(std::move(s.m_expr_sep))
, m_if_flag(s.m_if_flag)
, m_if_level(s.m_if_level)
, m_lineno(s.m_lineno)
, m_outbuf(std::move(s.m_outbuf))
, m_pos(s.m_pos)
, m_state(s.m_state)
, m_comment(s.m_comment)
{
}
protected:
class readbuffer : public std::streambuf
@ -242,6 +241,7 @@ protected:
? std::char_traits<char>::eof()
: std::char_traits<char>::to_int_type(*this->gptr());
}
private:
ppreprocessor *m_strm;
std::array<char_type, 1024> m_buf;
@ -261,20 +261,41 @@ private:
LINE_CONTINUATION
};
void process_stack();
pstring process_line(pstring line);
pstring process_comments(pstring line);
defines_map_type m_defines;
psource_collection_t<> &m_sources;
std::vector<pstring> m_expr_sep;
std::uint_least64_t m_if_flag; // 31 if levels
int m_if_level;
int m_lineno;
struct input_context
{
template <typename T>
input_context(T &&istrm, const pstring &local_path, const pstring &name)
: m_reader(std::forward<T>(istrm))
, m_lineno(0)
, m_local_path(local_path)
, m_name(name)
{}
putf8_reader m_reader;
int m_lineno;
pstring m_local_path;
pstring m_name;
};
std::stack<input_context> m_stack;
pstring_t<pu8_traits> m_outbuf;
std::istream::pos_type m_pos;
state_e m_state;
pstring m_line;
bool m_comment;
};
} // namespace plib

View File

@ -87,6 +87,28 @@ namespace plib
return last_found;
}
template<typename T>
typename T::size_type find_last_of(const T &str, const T &no)
{
typename T::size_type last_found = T::npos;
typename T::size_type pos = 0;
for (auto it = str.begin(); it != str.end(); ++it, ++pos)
{
bool f = false;
for (typename T::value_type const jt : no)
{
if (*it == jt)
{
f = true;
break;
}
}
if (f)
last_found = pos;
}
return last_found;
}
template<typename T>
T ltrim(const T &str, const T &ws = T(" \t\n\r"))
{

View File

@ -13,6 +13,32 @@ namespace plib
{
namespace util
{
#ifdef _WIN32
static constexpr const char PATH_SEP = '\\';
#else
static constexpr const char PATH_SEP = '/';
#endif
pstring basename(pstring filename)
{
auto p=find_last_of(filename, pstring(1, PATH_SEP));
if (p == pstring::npos)
return filename;
else
return filename.substr(p+1);
}
pstring path(pstring filename)
{
auto p=find_last_of(filename, pstring(1, PATH_SEP));
if (p == pstring::npos)
return "";
else if (p == 0) // root case
return filename.substr(0, 1);
else
return filename.substr(0, p);
}
pstring buildpath(std::initializer_list<pstring> list )
{
pstring ret = "";
@ -21,11 +47,7 @@ namespace plib
if (ret == "")
ret = elem;
else
#ifdef _WIN32
ret = ret + '\\' + elem;
#else
ret += ('/' + elem);
#endif
ret += (PATH_SEP + elem);
}
return ret;
}

View File

@ -10,6 +10,8 @@
#include "pexception.h"
#include "pstring.h"
#include "palloc.h"
#include <algorithm>
#include <initializer_list>
#include <iostream>
@ -24,8 +26,118 @@
namespace plib
{
// ----------------------------------------------------------------------------------------
// A Generic netlist sources implementation
// ----------------------------------------------------------------------------------------
class psource_t
{
public:
using stream_ptr = plib::unique_ptr<std::istream>;
psource_t()
{}
COPYASSIGNMOVE(psource_t, delete)
virtual ~psource_t() noexcept = default;
virtual stream_ptr stream(const pstring &name) = 0;
private:
};
/**! Generic string source
*
* Will return the given string when name matches.
* Is used in preprocessor code to eliminate inclusion of certain files.
*
* @tparam TS base stream class. Default is psource_t
*/
template <typename TS = psource_t>
class psource_str_t : public TS
{
public:
psource_str_t(pstring name, pstring str)
: m_name(name), m_str(str)
{}
COPYASSIGNMOVE(psource_str_t, delete)
virtual ~psource_str_t() noexcept = default;
typename TS::stream_ptr stream(const pstring &name) override
{
if (name == m_name)
return plib::make_unique<std::stringstream>(m_str);
else
return typename TS::stream_ptr(nullptr);
}
private:
pstring m_name;
pstring m_str;
};
/**! Generic sources collection
*
* @tparam TS base stream class. Default is psource_t
*/
template <typename TS = psource_t>
class psource_collection_t
{
public:
using source_type = plib::unique_ptr<TS>;
using list_t = std::vector<source_type>;
psource_collection_t()
{}
COPYASSIGNMOVE(psource_collection_t, delete)
virtual ~psource_collection_t() noexcept = default;
void add_source(source_type &&src)
{
m_collection.push_back(std::move(src));
}
template <typename S = TS>
typename S::stream_ptr get_stream(pstring name)
{
for (auto &s : m_collection)
{
auto source(dynamic_cast<S *>(s.get()));
if (source)
{
auto strm = source->stream(name);
if (strm)
return strm;
}
}
return typename S::stream_ptr(nullptr);
}
template <typename S, typename F>
bool for_all(pstring name, F lambda)
{
for (auto &s : m_collection)
{
auto source(dynamic_cast<S *>(s.get()));
if (source)
{
if (lambda(source))
return true;
}
}
return false;
}
private:
list_t m_collection;
};
namespace util
{
pstring basename(pstring filename);
pstring path(pstring filename);
pstring buildpath(std::initializer_list<pstring> list );
pstring environment(const pstring &var, const pstring &default_val);
} // namespace util

View File

@ -31,6 +31,7 @@ public:
opt_grp1(*this, "General options", "The following options apply to all commands."),
opt_cmd (*this, "c", "cmd", 0, std::vector<pstring>({"run","validate","convert","listdevices","static","header","docheader"}), "run|validate|convert|listdevices|static|header|docheader"),
opt_file(*this, "f", "file", "-", "file to process (default is stdin)"),
opt_includes(*this, "I", "include", "Add the directory to the list of directories to be searched for header files. This option may be specified repeatedly."),
opt_defines(*this, "D", "define", "predefine value as macro, e.g. -Dname=value. If '=value' is omitted predefine it as 1. This option may be specified repeatedly."),
opt_rfolders(*this, "r", "rom", "where to look for data files"),
opt_verb(*this, "v", "verbose", "be verbose - this produces lots of output"),
@ -76,6 +77,7 @@ public:
plib::option_group opt_grp1;
plib::option_str_limit<unsigned> opt_cmd;
plib::option_str opt_file;
plib::option_vec opt_includes;
plib::option_vec opt_defines;
plib::option_vec opt_rfolders;
plib::option_bool opt_verb;
@ -140,21 +142,21 @@ NETLIST_END()
CORE IMPLEMENTATION
***************************************************************************/
class netlist_data_folder_t : public netlist::source_t
class netlist_data_folder_t : public netlist::source_data_t
{
public:
netlist_data_folder_t(const pstring &folder)
: netlist::source_t(netlist::source_t::DATA)
: netlist::source_data_t()
, m_folder(folder)
{
}
plib::unique_ptr<std::istream> stream(const pstring &file) override
stream_ptr stream(const pstring &file) override
{
pstring name = m_folder + "/" + file;
auto strm(plib::make_unique<std::ifstream>(plib::filesystem::u8path(name)));
if (strm->fail())
return plib::unique_ptr<std::istream>(nullptr);
return stream_ptr(nullptr);
else
{
strm->imbue(std::locale::classic());
@ -198,7 +200,8 @@ public:
void read_netlist(const pstring &filename, const pstring &name,
const std::vector<pstring> &logs,
const std::vector<pstring> &defines,
const std::vector<pstring> &roms)
const std::vector<pstring> &roms,
const std::vector<pstring> &includes)
{
// read the netlist ...
@ -208,6 +211,11 @@ public:
for (auto & r : roms)
setup().register_source(plib::make_unique<netlist_data_folder_t>(r));
using a = plib::psource_str_t<plib::psource_t>;
setup().add_include(plib::make_unique<a>("netlist/devices/net_lib.h",""));
for (auto & i : includes)
setup().add_include(plib::make_unique<netlist_data_folder_t>(i));
setup().register_source(plib::make_unique<netlist::source_file_t>(filename));
setup().include(name);
create_dynamic_logs(logs);
@ -377,7 +385,7 @@ void tool_app_t::run()
nt.read_netlist(opt_file(), opt_name(),
opt_logs(),
m_options, opt_rfolders());
m_options, opt_rfolders(), opt_includes());
nt.reset();
@ -473,7 +481,7 @@ void tool_app_t::validate()
nt.read_netlist(opt_file(), opt_name(),
opt_logs(),
m_options, opt_rfolders());
m_options, opt_rfolders(), opt_includes());
}
catch (netlist::nl_exception &e)
{
@ -507,7 +515,7 @@ void tool_app_t::static_compile()
nt.read_netlist(opt_file(), opt_name(),
opt_logs(),
m_options, opt_rfolders());
m_options, opt_rfolders(), opt_includes());
// need to reset ...
@ -824,8 +832,6 @@ int tool_app_t::execute()
if (opt_help())
{
pout(plib::pfmt("{:10.3}\n").f(20.0));
//pout(plib::pfmt("{10.3}\n").f(20));
pout(usage());
return 0;
}

View File

@ -1,7 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
#include "audio/nl_cheekyms.h"
#include "netlist/devices/net_lib.h"

View File

@ -1,10 +1,8 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb, Couriersud
#include "audio/nl_zac1b11142.h"
#include "netlist/devices/net_lib.h"
#ifndef __PLIB_PREPROCESSOR__
#endif