summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/formats/apd_dsk.cpp145
-rw-r--r--src/lib/formats/apd_dsk.h31
-rw-r--r--src/lib/formats/tzx_cas.cpp77
-rw-r--r--src/lib/formats/tzx_cas.h2
-rw-r--r--src/lib/formats/zx81_p.cpp22
-rw-r--r--src/lib/formats/zx81_p.h1
-rw-r--r--src/lib/netlist/analog/nld_bjt.cpp255
-rw-r--r--src/lib/netlist/analog/nld_bjt.h248
-rw-r--r--src/lib/netlist/analog/nld_fourterm.h203
-rw-r--r--src/lib/netlist/analog/nld_opamps.cpp64
-rw-r--r--src/lib/netlist/analog/nld_opamps.h70
-rw-r--r--src/lib/netlist/analog/nld_switches.cpp5
-rw-r--r--src/lib/netlist/analog/nld_switches.h4
-rw-r--r--src/lib/netlist/analog/nld_twoterm.h424
-rw-r--r--src/lib/netlist/analog/nlid_fourterm.cpp (renamed from src/lib/netlist/analog/nld_fourterm.cpp)15
-rw-r--r--src/lib/netlist/analog/nlid_fourterm.h211
-rw-r--r--src/lib/netlist/analog/nlid_twoterm.cpp (renamed from src/lib/netlist/analog/nld_twoterm.cpp)70
-rw-r--r--src/lib/netlist/analog/nlid_twoterm.h448
-rw-r--r--src/lib/netlist/build/doxygen.conf514
-rw-r--r--src/lib/netlist/build/makefile9
-rw-r--r--src/lib/netlist/devices/net_lib.cpp55
-rw-r--r--src/lib/netlist/devices/net_lib.h29
-rw-r--r--src/lib/netlist/devices/nld_2102A.cpp1
-rw-r--r--src/lib/netlist/devices/nld_2716.cpp1
-rw-r--r--src/lib/netlist/devices/nld_4020.cpp2
-rw-r--r--src/lib/netlist/devices/nld_4066.cpp4
-rw-r--r--src/lib/netlist/devices/nld_4316.cpp4
-rw-r--r--src/lib/netlist/devices/nld_74107.cpp1
-rw-r--r--src/lib/netlist/devices/nld_74123.cpp6
-rw-r--r--src/lib/netlist/devices/nld_74153.cpp1
-rw-r--r--src/lib/netlist/devices/nld_74161.cpp1
-rw-r--r--src/lib/netlist/devices/nld_74165.cpp1
-rw-r--r--src/lib/netlist/devices/nld_74166.cpp3
-rw-r--r--src/lib/netlist/devices/nld_74174.cpp1
-rw-r--r--src/lib/netlist/devices/nld_74175.cpp1
-rw-r--r--src/lib/netlist/devices/nld_74192.cpp1
-rw-r--r--src/lib/netlist/devices/nld_74193.cpp5
-rw-r--r--src/lib/netlist/devices/nld_74194.cpp1
-rw-r--r--src/lib/netlist/devices/nld_74194.h22
-rw-r--r--src/lib/netlist/devices/nld_74279.cpp7
-rw-r--r--src/lib/netlist/devices/nld_74365.cpp1
-rw-r--r--src/lib/netlist/devices/nld_7448.cpp6
-rw-r--r--src/lib/netlist/devices/nld_7448.h6
-rw-r--r--src/lib/netlist/devices/nld_7450.cpp1
-rw-r--r--src/lib/netlist/devices/nld_7473.cpp1
-rw-r--r--src/lib/netlist/devices/nld_7474.cpp1
-rw-r--r--src/lib/netlist/devices/nld_7475.cpp1
-rw-r--r--src/lib/netlist/devices/nld_7483.cpp1
-rw-r--r--src/lib/netlist/devices/nld_7485.cpp1
-rw-r--r--src/lib/netlist/devices/nld_7490.cpp1
-rw-r--r--src/lib/netlist/devices/nld_7493.cpp8
-rw-r--r--src/lib/netlist/devices/nld_74ls629.cpp2
-rw-r--r--src/lib/netlist/devices/nld_82S115.cpp1
-rw-r--r--src/lib/netlist/devices/nld_82S115.h26
-rw-r--r--src/lib/netlist/devices/nld_82S123.cpp1
-rw-r--r--src/lib/netlist/devices/nld_82S126.cpp1
-rw-r--r--src/lib/netlist/devices/nld_82S16.cpp1
-rw-r--r--src/lib/netlist/devices/nld_9310.cpp30
-rw-r--r--src/lib/netlist/devices/nld_9312.cpp4
-rw-r--r--src/lib/netlist/devices/nld_9312.h26
-rw-r--r--src/lib/netlist/devices/nld_9316.cpp31
-rw-r--r--src/lib/netlist/devices/nld_9322.cpp1
-rw-r--r--src/lib/netlist/devices/nld_am2847.cpp1
-rw-r--r--src/lib/netlist/devices/nld_dm9334.cpp1
-rw-r--r--src/lib/netlist/devices/nld_legacy.cpp2
-rw-r--r--src/lib/netlist/devices/nld_log.cpp12
-rw-r--r--src/lib/netlist/devices/nld_mm5837.cpp8
-rw-r--r--src/lib/netlist/devices/nld_ne555.cpp4
-rw-r--r--src/lib/netlist/devices/nld_r2r_dac.cpp5
-rw-r--r--src/lib/netlist/devices/nld_system.cpp79
-rw-r--r--src/lib/netlist/devices/nld_system.h4
-rw-r--r--src/lib/netlist/devices/nld_tristate.cpp1
-rw-r--r--src/lib/netlist/devices/nlid_cmos.h1
-rw-r--r--src/lib/netlist/devices/nlid_proxy.cpp15
-rw-r--r--src/lib/netlist/devices/nlid_proxy.h8
-rw-r--r--src/lib/netlist/devices/nlid_system.h45
-rw-r--r--src/lib/netlist/devices/nlid_truthtable.cpp (renamed from src/lib/netlist/devices/nld_truthtable.cpp)55
-rw-r--r--src/lib/netlist/devices/nlid_truthtable.h (renamed from src/lib/netlist/devices/nld_truthtable.h)40
-rw-r--r--src/lib/netlist/documentation/mainpage.dox.h1
-rw-r--r--src/lib/netlist/macro/nlm_cd4xxx.cpp1
-rw-r--r--src/lib/netlist/macro/nlm_cd4xxx.h3
-rw-r--r--src/lib/netlist/macro/nlm_opamp.cpp4
-rw-r--r--src/lib/netlist/macro/nlm_opamp.h4
-rw-r--r--src/lib/netlist/macro/nlm_other.cpp1
-rw-r--r--src/lib/netlist/macro/nlm_other.h3
-rw-r--r--src/lib/netlist/macro/nlm_ttl74xx.cpp7
-rw-r--r--src/lib/netlist/macro/nlm_ttl74xx.h4
-rw-r--r--src/lib/netlist/netlist_types.h54
-rw-r--r--src/lib/netlist/nl_base.cpp239
-rw-r--r--src/lib/netlist/nl_base.h326
-rw-r--r--src/lib/netlist/nl_config.h88
-rw-r--r--src/lib/netlist/nl_dice_compat.h3
-rw-r--r--src/lib/netlist/nl_errstr.h92
-rw-r--r--src/lib/netlist/nl_factory.cpp25
-rw-r--r--src/lib/netlist/nl_factory.h78
-rw-r--r--src/lib/netlist/nl_lists.h75
-rw-r--r--src/lib/netlist/nl_parser.cpp51
-rw-r--r--src/lib/netlist/nl_parser.h11
-rw-r--r--src/lib/netlist/nl_setup.cpp272
-rw-r--r--src/lib/netlist/nl_setup.h68
-rw-r--r--src/lib/netlist/nl_time.h70
-rw-r--r--src/lib/netlist/plib/palloc.cpp2
-rw-r--r--src/lib/netlist/plib/palloc.h5
-rw-r--r--src/lib/netlist/plib/pchrono.h1
-rw-r--r--src/lib/netlist/plib/pconfig.h88
-rw-r--r--src/lib/netlist/plib/pdynlib.h4
-rw-r--r--src/lib/netlist/plib/pexception.cpp4
-rw-r--r--src/lib/netlist/plib/pexception.h1
-rw-r--r--src/lib/netlist/plib/pfmtlog.cpp19
-rw-r--r--src/lib/netlist/plib/pfmtlog.h57
-rw-r--r--src/lib/netlist/plib/pfunction.cpp212
-rw-r--r--src/lib/netlist/plib/pfunction.h87
-rw-r--r--src/lib/netlist/plib/plists.h4
-rw-r--r--src/lib/netlist/plib/poptions.cpp29
-rw-r--r--src/lib/netlist/plib/poptions.h38
-rw-r--r--src/lib/netlist/plib/pparser.cpp18
-rw-r--r--src/lib/netlist/plib/pparser.h31
-rw-r--r--src/lib/netlist/plib/ppmf.h198
-rw-r--r--src/lib/netlist/plib/pstate.h7
-rw-r--r--src/lib/netlist/plib/pstream.cpp58
-rw-r--r--src/lib/netlist/plib/pstream.h123
-rw-r--r--src/lib/netlist/plib/pstring.cpp80
-rw-r--r--src/lib/netlist/plib/pstring.h106
-rw-r--r--src/lib/netlist/plib/ptypes.h32
-rw-r--r--src/lib/netlist/plib/putil.cpp32
-rwxr-xr-x[-rw-r--r--]src/lib/netlist/plib/putil.h18
-rw-r--r--src/lib/netlist/prg/nltool.cpp117
-rw-r--r--src/lib/netlist/prg/nlwav.cpp170
-rw-r--r--src/lib/netlist/solver/mat_cr.h114
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.cpp63
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.h74
-rw-r--r--src/lib/netlist/solver/nld_ms_direct.h177
-rw-r--r--src/lib/netlist/solver/nld_ms_direct_lu.h9
-rw-r--r--src/lib/netlist/solver/nld_ms_gcr.h332
-rw-r--r--src/lib/netlist/solver/nld_ms_gmres.h97
-rw-r--r--src/lib/netlist/solver/nld_ms_sm.h64
-rw-r--r--src/lib/netlist/solver/nld_ms_sor.h42
-rw-r--r--src/lib/netlist/solver/nld_ms_sor_mat.h18
-rw-r--r--src/lib/netlist/solver/nld_ms_w.h63
-rw-r--r--src/lib/netlist/solver/nld_solver.cpp228
-rw-r--r--src/lib/netlist/solver/nld_solver.h19
-rwxr-xr-x[-rw-r--r--]src/lib/netlist/solver/vector_base.h41
-rw-r--r--src/lib/netlist/tools/nl_convert.cpp48
-rw-r--r--src/lib/netlist/tools/nl_convert.h14
-rw-r--r--src/lib/util/chd.cpp14
-rw-r--r--src/lib/util/hashing.h54
-rw-r--r--src/lib/util/path_to_regex.cpp4
-rw-r--r--src/lib/util/path_to_regex.hpp4
-rw-r--r--src/lib/util/server_ws.hpp4
-rw-r--r--src/lib/util/sha1.hpp232
-rw-r--r--src/lib/util/unicode.cpp10
151 files changed, 4620 insertions, 3524 deletions
diff --git a/src/lib/formats/apd_dsk.cpp b/src/lib/formats/apd_dsk.cpp
new file mode 100644
index 00000000000..3c972c25e49
--- /dev/null
+++ b/src/lib/formats/apd_dsk.cpp
@@ -0,0 +1,145 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/*********************************************************************
+
+ formats/apd_dsk.c
+
+ Archimedes Protected Disk Image format
+
+*********************************************************************/
+
+#include <zlib.h>
+#include "formats/apd_dsk.h"
+
+static const uint8_t APD_HEADER[8] = { 'A', 'P', 'D', 'X', '0', '0', '0', '1' };
+static const uint8_t GZ_HEADER[2] = { 0x1f, 0x8b };
+
+apd_format::apd_format()
+{
+}
+
+const char *apd_format::name() const
+{
+ return "apd";
+}
+
+const char *apd_format::description() const
+{
+ return "Archimedes Protected Disk Image";
+}
+
+const char *apd_format::extensions() const
+{
+ return "apd";
+}
+
+int apd_format::identify(io_generic *io, uint32_t form_factor)
+{
+ uint64_t size = io_generic_size(io);
+ std::vector<uint8_t> img(size);
+ io_generic_read(io, &img[0], 0, size);
+
+ int err;
+ std::vector<uint8_t> gz_ptr(8);
+ z_stream d_stream;
+
+ if (!memcmp(&img[0], GZ_HEADER, sizeof(GZ_HEADER))) {
+ d_stream.zalloc = nullptr;
+ d_stream.zfree = nullptr;
+ d_stream.opaque = nullptr;
+ d_stream.next_in = &img[0];
+ d_stream.avail_in = size;
+ d_stream.next_out = &gz_ptr[0];
+ d_stream.avail_out = 8;
+
+ err = inflateInit2(&d_stream, MAX_WBITS | 16);
+ if (err != Z_OK) return 0;
+
+ err = inflate(&d_stream, Z_SYNC_FLUSH);
+ if (err != Z_OK) return 0;
+
+ err = inflateEnd(&d_stream);
+ if (err != Z_OK) return 0;
+
+ img = gz_ptr;
+ }
+
+ if (!memcmp(&img[0], APD_HEADER, sizeof(APD_HEADER))) {
+ return 100;
+ }
+
+ return 0;
+}
+
+bool apd_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
+{
+ uint64_t size = io_generic_size(io);
+ std::vector<uint8_t> img(size);
+ io_generic_read(io, &img[0], 0, size);
+
+ int err;
+ std::vector<uint8_t> gz_ptr;
+ z_stream d_stream;
+ int inflate_size = (img[size - 1] << 24) | (img[size - 2] << 16) | (img[size - 3] << 8) | img[size - 4];
+ uint8_t *in_ptr = &img[0];
+
+ if (!memcmp(&img[0], GZ_HEADER, sizeof(GZ_HEADER))) {
+ gz_ptr.resize(inflate_size);
+
+ d_stream.zalloc = nullptr;
+ d_stream.zfree = nullptr;
+ d_stream.opaque = nullptr;
+ d_stream.next_in = in_ptr;
+ d_stream.avail_in = size;
+ d_stream.next_out = &gz_ptr[0];
+ d_stream.avail_out = inflate_size;
+
+ err = inflateInit2(&d_stream, MAX_WBITS | 16);
+ if (err != Z_OK) {
+ LOG_FORMATS("inflateInit2 error: %d\n", err);
+ return false;
+ }
+ err = inflate(&d_stream, Z_FINISH);
+ if (err != Z_STREAM_END && err != Z_OK) {
+ LOG_FORMATS("inflate error: %d\n", err);
+ return false;
+ }
+ err = inflateEnd(&d_stream);
+ if (err != Z_OK) {
+ LOG_FORMATS("inflateEnd error: %d\n", err);
+ return false;
+ }
+ size = inflate_size;
+ img = gz_ptr;
+ }
+
+ int data = 0x7d0;
+ for (int track = 0; track < 166; track++) {
+ uint32_t sdlen = little_endianize_int32(*(uint32_t *)(&img[(track * 12) + 8 + 0x0]));
+ uint32_t ddlen = little_endianize_int32(*(uint32_t *)(&img[(track * 12) + 8 + 0x4]));
+ uint32_t qdlen = little_endianize_int32(*(uint32_t *)(&img[(track * 12) + 8 + 0x8]));
+
+ if (sdlen > 0) {
+ generate_track_from_bitstream(track / 2, track % 2, &img[data], sdlen, image);
+ data += (sdlen + 7) >> 3;
+ }
+ if (ddlen > 0) {
+ generate_track_from_bitstream(track / 2, track % 2, &img[data], ddlen, image);
+ data += (ddlen + 7) >> 3;
+ }
+ if (qdlen > 0) {
+ generate_track_from_bitstream(track / 2, track % 2, &img[data], qdlen, image);
+ data += (qdlen + 7) >> 3;
+ }
+ }
+ image->set_variant(floppy_image::DSDD);
+
+ return true;
+}
+
+bool apd_format::supports_save() const
+{
+ return false;
+}
+
+const floppy_format_type FLOPPY_APD_FORMAT = &floppy_image_format_creator<apd_format>;
diff --git a/src/lib/formats/apd_dsk.h b/src/lib/formats/apd_dsk.h
new file mode 100644
index 00000000000..3bf40055a7b
--- /dev/null
+++ b/src/lib/formats/apd_dsk.h
@@ -0,0 +1,31 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/*********************************************************************
+
+ formats/apd_dsk.h
+
+ Archimedes Protected Disk Image format
+
+*********************************************************************/
+
+#ifndef APD_DSK_H_
+#define APD_DSK_H_
+
+#include "flopimg.h"
+
+class apd_format : public floppy_image_format_t {
+public:
+ apd_format();
+
+ virtual const char *name() const override;
+ virtual const char *description() const override;
+ virtual const char *extensions() const override;
+
+ virtual int identify(io_generic *io, uint32_t form_factor) override;
+ virtual bool load(io_generic *io, uint32_t form_factor, floppy_image *image) override;
+ virtual bool supports_save() const override;
+};
+
+extern const floppy_format_type FLOPPY_APD_FORMAT;
+
+#endif
diff --git a/src/lib/formats/tzx_cas.cpp b/src/lib/formats/tzx_cas.cpp
index 748f0227c65..7f03be7977a 100644
--- a/src/lib/formats/tzx_cas.cpp
+++ b/src/lib/formats/tzx_cas.cpp
@@ -8,7 +8,6 @@ TODO:
Add support for the remaining block types:
case 0x15: Direct Recording
case 0x18: CSW Recording
- case 0x19: Generalized Data Block
case 0x21: Group Start
case 0x22: Group End
case 0x23: Jump To Block
@@ -31,7 +30,7 @@ Notes:
TZX format specification lists
8064 pulses for a header block and 3220 for a data block
-but the documentaiton on worldofspectrum lists
+but the documentation on worldofspectrum lists
8063 pulses for a header block and 3223 for a data block
see http://www.worldofspectrum.org/faq/reference/48kreference.htm#TapeDataStructure
@@ -315,7 +314,6 @@ static int tzx_handle_direct(int16_t **buffer, const uint8_t *bytes, int pause,
tzx_output_wave(buffer, samples);
size += samples;
-
}
}
@@ -342,8 +340,6 @@ static inline int tzx_handle_symbol(int16_t **buffer, const uint8_t *symtable, u
uint8_t starttype = cursymb[0];
-// printf("start polarity %01x (max number of symbols is %d)\n", starttype, maxp);
-
switch (starttype)
{
case 0x00:
@@ -371,7 +367,6 @@ static inline int tzx_handle_symbol(int16_t **buffer, const uint8_t *symtable, u
for (int i = 0; i < maxp; i++)
{
uint16_t pulse_length = cursymb[1 + (i*2)] | (cursymb[2 + (i*2)] << 8);
- // printf("pulse_length %04x\n", pulse_length);
// shorter lists can be terminated with a pulse_length of 0
if (pulse_length != 0)
@@ -380,7 +375,6 @@ static inline int tzx_handle_symbol(int16_t **buffer, const uint8_t *symtable, u
tzx_output_wave(buffer, samples);
size += samples;
toggle_wave_data();
-
}
else
{
@@ -390,8 +384,6 @@ static inline int tzx_handle_symbol(int16_t **buffer, const uint8_t *symtable, u
}
}
- //toggle_wave_data();
-
return size;
}
@@ -405,7 +397,6 @@ static inline int stream_get_bit(const uint8_t *bytes, uint8_t &stream_bit, uint
if (byte & 0x80) retbit = 1;
-
stream_bit++;
if (stream_bit == 8)
@@ -433,34 +424,26 @@ static int tzx_handle_generalized(int16_t **buffer, const uint8_t *bytes, int pa
{
uint8_t symbol = table2[i + 0];
uint16_t repetitions = table2[i + 1] + (table2[i + 2] << 8);
- //printf("symbol %02x repititions %04x\n", symbol, repetitions); // does 1 mean repeat once, or that it only occurs once?
+ //printf("symbol %02x repetitions %04x\n", symbol, repetitions); // does 1 mean repeat once, or that it only occurs once?
for (int j = 0; j < repetitions; j++)
{
size += tzx_handle_symbol(buffer, symtable, symbol, npp);
- // toggle_wave_data();
}
-
-
}
// advance to after this data
bytes += ((2 * npp + 1)*asp) + totp * 3;
}
- else
- {
- printf("no pilot block\n");
- }
if (totd > 0)
{
- printf("data block table %04x (has %0d symbols, max symbol length is %d)\n", totd, asd, npd);
+ // printf("data block table %04x (has %0d symbols, max symbol length is %d)\n", totd, asd, npd);
const uint8_t *symtable = bytes;
const uint8_t *table2 = bytes + (2 * npd + 1)*asd;
int NB = ceil(compute_log2(asd)); // number of bits needed to represent each symbol
- printf("NB is %d\n", NB);
uint8_t stream_bit = 0;
uint32_t stream_byte = 0;
@@ -475,16 +458,8 @@ static int tzx_handle_generalized(int16_t **buffer, const uint8_t *bytes, int pa
}
size += tzx_handle_symbol(buffer, symtable, symbol, npd);
-
- //toggle_wave_data();
}
}
- else
- {
- printf("no data block\n");
- }
-
-
/* pause */
if (pause > 0)
@@ -505,9 +480,7 @@ static int tzx_handle_generalized(int16_t **buffer, const uint8_t *bytes, int pa
static void ascii_block_common_log( const char *block_type_string, uint8_t block_type )
{
- LOG_FORMATS("%s (type %02x) encountered.\n", block_type_string, block_type);
- LOG_FORMATS("This block contains info on the .tzx file you are loading.\n");
- LOG_FORMATS("Please include the following info in your bug reports, if the image has issue in M.E.S.S.\n");
+ LOG_FORMATS("%s (type %02x) encountered:\n", block_type_string, block_type);
}
static const char *const archive_ident[] =
@@ -744,20 +717,18 @@ static int tzx_cas_do_work( int16_t **buffer )
{
// having this missing is fatal
// used crudely by batmanc in spectrum_cass list (which is just a redundant encoding of batmane ?)
- printf("Unsupported block type (0x19 - Generalized Data Block) encountered.\n");
-
data_size = cur_block[1] + (cur_block[2] << 8) + (cur_block[3] << 16) + (cur_block[4] << 24);
pause_time= cur_block[5] + (cur_block[6] << 8);
uint32_t totp = cur_block[7] + (cur_block[8] << 8) + (cur_block[9] << 16) + (cur_block[10] << 24);
int npp = cur_block[11];
int asp = cur_block[12];
- if (asp == 0) asp = 256;
+ if (asp == 0 && totp > 0) asp = 256;
uint32_t totd = cur_block[13] + (cur_block[14] << 8) + (cur_block[15] << 16) + (cur_block[16] << 24);
int npd = cur_block[17];
int asd = cur_block[18];
- if (asd == 0) asd = 256;
+ if (asd == 0 && totd > 0) asd = 256;
size += tzx_handle_generalized(buffer, &cur_block[19], pause_time, data_size, totp, npp, asp, totd, npd, asd);
@@ -840,7 +811,7 @@ static int tap_cas_to_wav_size( const uint8_t *casdata, int caslen )
{
int data_size = p[0] + (p[1] << 8);
int pilot_length = (p[2] == 0x00) ? 8064 : 3220; /* TZX specification */
-// int pilot_length = (p[2] == 0x00) ? 8063 : 3223; /* worldofspectrum */
+// int pilot_length = (p[2] == 0x00) ? 8063 : 3223; /* worldofspectrum */
LOG_FORMATS("tap_cas_to_wav_size: Handling TAP block containing 0x%X bytes", data_size);
p += 2;
size += tzx_cas_handle_block(nullptr, p, 1000, data_size, 2168, pilot_length, 667, 735, 855, 1710, 8);
@@ -859,7 +830,7 @@ static int tap_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes )
{
int data_size = bytes[0] + (bytes[1] << 8);
int pilot_length = (bytes[2] == 0x00) ? 8064 : 3220; /* TZX specification */
-// int pilot_length = (bytes[2] == 0x00) ? 8063 : 3223; /* worldofspectrum */
+// int pilot_length = (bytes[2] == 0x00) ? 8063 : 3223; /* worldofspectrum */
LOG_FORMATS("tap_cas_fill_wave: Handling TAP block containing 0x%X bytes\n", data_size);
bytes += 2;
size += tzx_cas_handle_block(&p, bytes, 1000, data_size, 2168, pilot_length, 667, 735, 855, 1710, 8);
@@ -871,34 +842,34 @@ static int tap_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes )
static const struct CassetteLegacyWaveFiller tzx_legacy_fill_wave =
{
tzx_cas_fill_wave, /* fill_wave */
- -1, /* chunk_size */
- 0, /* chunk_samples */
- tzx_cas_to_wav_size, /* chunk_sample_calc */
+ -1, /* chunk_size */
+ 0, /* chunk_samples */
+ tzx_cas_to_wav_size, /* chunk_sample_calc */
TZX_WAV_FREQUENCY, /* sample_frequency */
- 0, /* header_samples */
- 0 /* trailer_samples */
+ 0, /* header_samples */
+ 0 /* trailer_samples */
};
static const struct CassetteLegacyWaveFiller tap_legacy_fill_wave =
{
tap_cas_fill_wave, /* fill_wave */
- -1, /* chunk_size */
- 0, /* chunk_samples */
- tap_cas_to_wav_size, /* chunk_sample_calc */
+ -1, /* chunk_size */
+ 0, /* chunk_samples */
+ tap_cas_to_wav_size, /* chunk_sample_calc */
TZX_WAV_FREQUENCY, /* sample_frequency */
- 0, /* header_samples */
- 0 /* trailer_samples */
+ 0, /* header_samples */
+ 0 /* trailer_samples */
};
static const struct CassetteLegacyWaveFiller cdt_legacy_fill_wave =
{
cdt_cas_fill_wave, /* fill_wave */
- -1, /* chunk_size */
- 0, /* chunk_samples */
- tzx_cas_to_wav_size, /* chunk_sample_calc */
+ -1, /* chunk_size */
+ 0, /* chunk_samples */
+ tzx_cas_to_wav_size, /* chunk_sample_calc */
TZX_WAV_FREQUENCY, /* sample_frequency */
- 0, /* header_samples */
- 0 /* trailer_samples */
+ 0, /* header_samples */
+ 0 /* trailer_samples */
};
static cassette_image::error tzx_cassette_identify( cassette_image *cassette, struct CassetteOptions *opts )
@@ -931,7 +902,7 @@ static cassette_image::error cdt_cassette_load( cassette_image *cassette )
return cassette_legacy_construct(cassette, &cdt_legacy_fill_wave);
}
-static const struct CassetteFormat tzx_cassette_format =
+const struct CassetteFormat tzx_cassette_format =
{
"tzx",
tzx_cassette_identify,
diff --git a/src/lib/formats/tzx_cas.h b/src/lib/formats/tzx_cas.h
index 8610fb0cdd4..2db31245310 100644
--- a/src/lib/formats/tzx_cas.h
+++ b/src/lib/formats/tzx_cas.h
@@ -12,6 +12,8 @@
#include "cassimg.h"
+extern const struct CassetteFormat tzx_cassette_format;
+
CASSETTE_FORMATLIST_EXTERN(tzx_cassette_formats);
CASSETTE_FORMATLIST_EXTERN(cdt_cassette_formats);
diff --git a/src/lib/formats/zx81_p.cpp b/src/lib/formats/zx81_p.cpp
index 7f359ccaca3..9fa5814385f 100644
--- a/src/lib/formats/zx81_p.cpp
+++ b/src/lib/formats/zx81_p.cpp
@@ -34,6 +34,7 @@ medium transfer rate is approx. 307 bps (38 bytes/sec) for files that contain
#include <assert.h>
#include "zx81_p.h"
+#include "tzx_cas.h"
#define WAVEENTRY_LOW -32768
@@ -197,13 +198,13 @@ static int zx81_cassette_fill_wave(int16_t *buffer, int length, uint8_t *bytes)
static const struct CassetteLegacyWaveFiller zx81_legacy_fill_wave =
{
- zx81_cassette_fill_wave, /* fill_wave */
- -1, /* chunk_size */
- 0, /* chunk_samples */
+ zx81_cassette_fill_wave, /* fill_wave */
+ -1, /* chunk_size */
+ 0, /* chunk_samples */
zx81_cassette_calculate_size_in_samples, /* chunk_sample_calc */
- ZX81_WAV_FREQUENCY, /* sample_frequency */
- 0, /* header_samples */
- 0 /* trailer_samples */
+ ZX81_WAV_FREQUENCY, /* sample_frequency */
+ 0, /* header_samples */
+ 0 /* trailer_samples */
};
static cassette_image::error zx81_p_identify(cassette_image *cassette, struct CassetteOptions *opts)
@@ -233,6 +234,11 @@ CASSETTE_FORMATLIST_START(zx81_p_format)
CASSETTE_FORMAT(zx81_p_image_format)
CASSETTE_FORMATLIST_END
+CASSETTE_FORMATLIST_START(zx81_cassette_formats)
+ CASSETTE_FORMAT(zx81_p_image_format)
+ CASSETTE_FORMAT(tzx_cassette_format)
+CASSETTE_FORMATLIST_END
+
/* ZX-80 functions */
static int zx80_cassette_calculate_size_in_samples(const uint8_t *bytes, int length)
@@ -265,11 +271,11 @@ static int zx80_cassette_fill_wave(int16_t *buffer, int length, uint8_t *bytes)
static const struct CassetteLegacyWaveFiller zx80_legacy_fill_wave =
{
- zx80_cassette_fill_wave, /* fill_wave */
+ zx80_cassette_fill_wave, /* fill_wave */
-1, /* chunk_size */
0, /* chunk_samples */
zx80_cassette_calculate_size_in_samples, /* chunk_sample_calc */
- ZX81_WAV_FREQUENCY, /* sample_frequency */
+ ZX81_WAV_FREQUENCY, /* sample_frequency */
0, /* header_samples */
0 /* trailer_samples */
};
diff --git a/src/lib/formats/zx81_p.h b/src/lib/formats/zx81_p.h
index 16a1b22724d..36da808c989 100644
--- a/src/lib/formats/zx81_p.h
+++ b/src/lib/formats/zx81_p.h
@@ -14,6 +14,7 @@
#include "cassimg.h"
CASSETTE_FORMATLIST_EXTERN(zx81_p_format);
+CASSETTE_FORMATLIST_EXTERN(zx81_cassette_formats);
CASSETTE_FORMATLIST_EXTERN(zx80_o_format);
#endif /* ZX81_P_H */
diff --git a/src/lib/netlist/analog/nld_bjt.cpp b/src/lib/netlist/analog/nld_bjt.cpp
index 0acd0887e74..e40fbfa366d 100644
--- a/src/lib/netlist/analog/nld_bjt.cpp
+++ b/src/lib/netlist/analog/nld_bjt.cpp
@@ -6,13 +6,16 @@
*/
#include "solver/nld_solver.h"
-#include "analog/nld_bjt.h"
+#include "analog/nlid_twoterm.h"
#include "nl_setup.h"
+#include <cmath>
+
namespace netlist
{
namespace analog
{
+
class diode
{
public:
@@ -40,6 +43,240 @@ private:
nl_double m_VT_inv;
};
+// -----------------------------------------------------------------------------
+// nld_Q - Base classes
+// -----------------------------------------------------------------------------
+
+ /*! Class representing the bjt model paramers.
+ *
+ * This is the model representation of the bjt model. Typically, SPICE uses
+ * the following parameters. A "Y" in the first column indicates that the
+ * parameter is actually used in netlist.
+ *
+ * | NL? | name | parameter | units | default | example | area |
+ * |:---:|------|-----------------------------------------------------------------------|-------|---------:|----------------:|:----:|
+ * | Y | IS | transport saturation current | A | 1E-016 | 1E-015 | * |
+ * | Y | BF | ideal maximum forward beta | - | 100 | 100 | |
+ * | Y | NF | forward current emission coefficient | - | 1 | 1 | |
+ * | | VAF | forward Early voltage | V | infinite | 200 | |
+ * | | IKF | corner for forward beta high current roll-off | A | infinite | 0.01 | * |
+ * | | ISE | B-E leakage saturation current | A | 0 | 0.0000000000001 | * |
+ * | | NE | B-E leakage emission coefficient | - | 1.5 | 2 | |
+ * | Y | BR | ideal maximum reverse beta | - | 1 | 0.1 | |
+ * | Y | NR | reverse current emission coefficient | - | 1 | 1 | |
+ * | | VAR | reverse Early voltage | V | infinite | 200 | |
+ * | | IKR | corner for reverse beta high current roll-off | A | infinite | 0.01 | * |
+ * | | ISC | leakage saturation current | A | 0 | 8 | |
+ * | | NC | leakage emission coefficient | - | 2 | 1.5 | |
+ * | | RB | zero bias base resistance | | 0 | 100 | * |
+ * | | IRB | current where base resistance falls halfway to its min value | A | infinte | 0.1 | * |
+ * | | RBM | minimum base resistance at high currents | | RB | 10 | * |
+ * | | RE | emitter resistance | | 0 | 1 | * |
+ * | | RC | collector resistance | | 0 | 10 | * |
+ * | | CJE | B-E zero-bias depletion capacitance | F | 0 | 2pF | * |
+ * | | VJE | B-E built-in potential | V | 0.75 | 0.6 | |
+ * | | MJE | B-E junction exponential factor | - | 0.33 | 0.33 | |
+ * | | TF | ideal forward transit time | sec | 0 | 0.1ns | |
+ * | | XTF | coefficient for bias dependence of TF | - | 0 | | |
+ * | | VTF | voltage describing VBC dependence of TF | V | infinite | | |
+ * | | ITF | high-current parameter for effect on TF | A | 0 | | * |
+ * | | PTF | excess phase at freq=1.0/(TF*2PI) Hz | deg | 0 | | |
+ * | | CJC | B-C zero-bias depletion capacitance | F | 0 | 2pF | * |
+ * | | VJC | B-C built-in potential | V | 0.75 | 0.5 | |
+ * | | MJC | B-C junction exponential factor | - | 0.33 | 0.5 | |
+ * | | XCJC | fraction of B-C depletion capacitance connected to internal base node | - | 1 | | |
+ * | | TR | ideal reverse transit time | sec | 0 | 10ns | |
+ * | | CJS | zero-bias collector-substrate capacitance | F | 0 | 2pF | * |
+ * | | VJS | substrate junction built-in potential | V | 0.75 | | |
+ * | | MJS | substrate junction exponential factor | - | 0 | 0.5 | |
+ * | | XTB | forward and reverse beta temperature exponent | - | 0 | | |
+ * | | EG | energy gap for temperature effect on IS | eV | 1.11 | | |
+ * | | XTI | temperature exponent for effect on IS | - | 3 | | |
+ * | | KF | flicker-noise coefficient | - | 0 | | |
+ * | | AF | flicker-noise exponent | - | 1 | | |
+ * | | FC | coefficient for forward-bias depletion capacitance formula | - | 0.5 | | |
+ * | | TNOM | Parameter measurement temperature | C | 27 | 50 | | */
+
+ class bjt_model_t : public param_model_t
+ {
+ public:
+ bjt_model_t(device_t &device, const pstring name, const pstring val)
+ : param_model_t(device, name, val)
+ , m_IS(*this, "IS")
+ , m_BF(*this, "BF")
+ , m_NF(*this, "NF")
+ , m_BR(*this, "BR")
+ , m_NR(*this, "NR")
+ {}
+
+ value_t m_IS; //!< transport saturation current
+ value_t m_BF; //!< ideal maximum forward beta
+ value_t m_NF; //!< forward current emission coefficient
+ value_t m_BR; //!< ideal maximum reverse beta
+ value_t m_NR; //!< reverse current emission coefficient
+ };
+
+ // Have a common start for transistors
+
+NETLIB_OBJECT(Q)
+{
+public:
+ enum q_type {
+ BJT_NPN,
+ BJT_PNP
+ };
+
+ NETLIB_CONSTRUCTOR(Q)
+ , m_model(*this, "MODEL", "")
+ , m_qtype(BJT_NPN)
+ {
+ }
+
+ NETLIB_IS_DYNAMIC(true)
+
+ //NETLIB_RESETI();
+ NETLIB_UPDATEI();
+
+ inline q_type qtype() const { return m_qtype; }
+ inline bool is_qtype(q_type atype) const { return m_qtype == atype; }
+ inline void set_qtype(q_type atype) { m_qtype = atype; }
+protected:
+
+ bjt_model_t m_model;
+private:
+ q_type m_qtype;
+};
+
+NETLIB_OBJECT_DERIVED(QBJT, Q)
+{
+public:
+ NETLIB_CONSTRUCTOR_DERIVED(QBJT, Q)
+ { }
+
+protected:
+
+private:
+};
+
+
+
+
+// -----------------------------------------------------------------------------
+// nld_QBJT_switch
+// -----------------------------------------------------------------------------
+
+
+/*
+ * + - C
+ * B ----VVV----+ |
+ * | |
+ * Rb Rc
+ * Rb Rc
+ * Rb Rc
+ * | |
+ * +----+----+
+ * |
+ * E
+ */
+
+NETLIB_OBJECT_DERIVED(QBJT_switch, QBJT)
+{
+ NETLIB_CONSTRUCTOR_DERIVED(QBJT_switch, QBJT)
+ , m_RB(*this, "m_RB", true)
+ , m_RC(*this, "m_RC", true)
+ , m_BC_dummy(*this, "m_BC", true)
+ , m_gB(NETLIST_GMIN_DEFAULT)
+ , m_gC(NETLIST_GMIN_DEFAULT)
+ , m_V(0.0)
+ , m_state_on(*this, "m_state_on", 0)
+ {
+ register_subalias("B", m_RB.m_P);
+ register_subalias("E", m_RB.m_N);
+ register_subalias("C", m_RC.m_P);
+ //register_term("_E1", m_RC.m_N);
+
+ //register_term("_B1", m_BC_dummy.m_P);
+ //register_term("_C1", m_BC_dummy.m_N);
+
+ connect(m_RB.m_N, m_RC.m_N);
+
+ connect(m_RB.m_P, m_BC_dummy.m_P);
+ connect(m_RC.m_P, m_BC_dummy.m_N);
+ }
+
+ NETLIB_RESETI();
+ NETLIB_UPDATEI();
+ NETLIB_UPDATE_PARAMI();
+ NETLIB_UPDATE_TERMINALSI();
+
+ nld_twoterm m_RB;
+ nld_twoterm m_RC;
+
+ // FIXME: this is needed so we have all terminals belong to one net list
+
+ nld_twoterm m_BC_dummy;
+
+protected:
+
+
+ nl_double m_gB; // base conductance / switch on
+ nl_double m_gC; // collector conductance / switch on
+ nl_double m_V; // internal voltage source
+ state_var<unsigned> m_state_on;
+
+private:
+};
+
+// -----------------------------------------------------------------------------
+// nld_QBJT_EB
+// -----------------------------------------------------------------------------
+
+
+NETLIB_OBJECT_DERIVED(QBJT_EB, QBJT)
+{
+public:
+ NETLIB_CONSTRUCTOR_DERIVED(QBJT_EB, QBJT)
+ , m_gD_BC(*this, "m_D_BC")
+ , m_gD_BE(*this, "m_D_BE")
+ , m_D_CB(*this, "m_D_CB", true)
+ , m_D_EB(*this, "m_D_EB", true)
+ , m_D_EC(*this, "m_D_EC", true)
+ , m_alpha_f(0)
+ , m_alpha_r(0)
+ {
+ register_subalias("E", m_D_EB.m_P); // Cathode
+ register_subalias("B", m_D_EB.m_N); // Anode
+
+ register_subalias("C", m_D_CB.m_P); // Cathode
+ //register_term("_B1", m_D_CB.m_N); // Anode
+
+ //register_term("_E1", m_D_EC.m_P);
+ //register_term("_C1", m_D_EC.m_N);
+
+ connect(m_D_EB.m_P, m_D_EC.m_P);
+ connect(m_D_EB.m_N, m_D_CB.m_N);
+ connect(m_D_CB.m_P, m_D_EC.m_N);
+ }
+
+protected:
+
+ NETLIB_RESETI();
+ NETLIB_UPDATEI();
+ NETLIB_UPDATE_PARAMI();
+ NETLIB_UPDATE_TERMINALSI();
+
+ generic_diode m_gD_BC;
+ generic_diode m_gD_BE;
+
+private:
+ nld_twoterm m_D_CB; // gcc, gce - gcc, gec - gcc, gcc - gce | Ic
+ nld_twoterm m_D_EB; // gee, gec - gee, gce - gee, gee - gec | Ie
+ nld_twoterm m_D_EC; // 0, -gec, -gcc, 0 | 0
+
+ nl_double m_alpha_f;
+ nl_double m_alpha_r;
+
+};
// ----------------------------------------------------------------------------------------
@@ -122,8 +359,6 @@ NETLIB_UPDATE_TERMINALS(QBJT_switch)
m_RB.set(gb, v, 0.0);
m_RC.set(gc, 0.0, 0.0);
- //m_RB.update_dev();
- //m_RC.update_dev();
m_state_on = new_state;
}
}
@@ -166,11 +401,11 @@ NETLIB_UPDATE_TERMINALS(QBJT_EB)
const nl_double Ic = (sIc - gce * m_gD_BE.Vd() + gcc * m_gD_BC.Vd()) * polarity;
m_D_EB.set_mat( gee, gec - gee, -Ie,
- gce - gee, gee - gec, Ie);
+ gce - gee, gee - gec, Ie);
m_D_CB.set_mat( gcc, gce - gcc, -Ic,
- gec - gcc, gcc - gce, Ic);
+ gec - gcc, gcc - gce, Ic);
m_D_EC.set_mat( 0, -gec, 0,
- -gce, 0, 0);
+ -gce, 0, 0);
}
@@ -192,5 +427,11 @@ NETLIB_UPDATE_PARAM(QBJT_EB)
m_gD_BC.set_param(IS / m_alpha_r, NR, netlist().gmin());
}
- } //namespace devices
+ } //namespace analog
+
+ namespace devices {
+ NETLIB_DEVICE_IMPL_NS(analog, QBJT_EB)
+ NETLIB_DEVICE_IMPL_NS(analog, QBJT_switch)
+ }
+
} // namespace netlist
diff --git a/src/lib/netlist/analog/nld_bjt.h b/src/lib/netlist/analog/nld_bjt.h
index a4e163b13bc..5e40bd1ef36 100644
--- a/src/lib/netlist/analog/nld_bjt.h
+++ b/src/lib/netlist/analog/nld_bjt.h
@@ -8,8 +8,7 @@
#ifndef NLD_BJT_H_
#define NLD_BJT_H_
-#include "nl_base.h"
-#include "nld_twoterm.h"
+#include "nl_setup.h"
// -----------------------------------------------------------------------------
// Macros
@@ -23,249 +22,4 @@
NET_REGISTER_DEV(QBJT_EB, name) \
NETDEV_PARAMI(name, MODEL, model)
-
-namespace netlist
-{
- namespace analog
- {
-// -----------------------------------------------------------------------------
-// nld_Q - Base classes
-// -----------------------------------------------------------------------------
-
- /* FIXME: Make table pretty */
-
- /*! Class representing the bjt model paramers.
- * This is the model representation of the bjt model. Typically, SPICE uses
- * the following parameters. A "Y" in the first column indicates that the
- * parameter is actually used in netlist.
- *
- * |NL? |name |parameter |units|default| example|area  |
- * |:--:|:-----|:--------------------------------|:----|------:|-------:|:----:|
- * | Y |IS |transport saturation current|A |1E-016|1E-015|* |
- * | Y |BF |ideal maximum forward beta|- |100|100| |
- * | Y |NF |forward current emission coefficient|- |1|1| |
- * | |VAF |forward Early voltage|V |infinite |200| |
- * | |IKF |corner for forward beta high current roll-off|A |infinite |0.01|* |
- * | |ISE |B-E leakage saturation current|A |0|0.0000000000001|* |
- * | |NE |B-E leakage emission coefficient|- |1.5|2| |
- * | Y |BR |ideal maximum reverse beta |- |1|0.1| |
- * | Y |NR |reverse current emission coefficient|- |1|1| |
- * | |VAR |reverse Early voltage|V |infinite |200| |
- * | |IKR |corner for reverse beta high current roll-off|A |infinite |0.01|* |
- * | |ISC |leakage saturation current|A |0|8| |
- * | |NC |leakage emission coefficient|- |2|1.5| |
- * | |RB |zero bias base resistance| |0|100|* |
- * | |IRB |current where base resistance falls halfway to its min value|A |infinte |0.1|* |
- * | |RBM |minimum base resistance at high currents| |RB |10|* |
- * | |RE |emitter resistance| |0|1|* |
- * | |RC |collector resistance | |0|10|* |
- * | |CJE |B-E zero-bias depletion capacitance|F |0|2pF |* |
- * | |VJE |B-E built-in potential|V |0.75|0.6| |
- * | |MJE |B-E junction exponential factor |- |0.33|0.33| |
- * | |TF |ideal forward transit time |sec |0|0.1ns | |
- * | |XTF|coefficient for bias dependence of TF |- |0| | |
- * | |VTF |voltage describing VBC  dependence of TF |V |infinite | | |
- * | |ITF |high-current parameter  for effect on TF |A |0| |* |
- * | |PTF |excess phase at freq=1.0/(TF*2PI) Hz |deg |0| | |
- * | |CJC |B-C zero-bias depletion capacitance |F |0|2pF |* |
- * | |VJC |B-C built-in potential |V |0.75|0.5| |
- * | |MJC |B-C junction exponential factor |- |0.33|0.5| |
- * | |XCJC |fraction of B-C depletion capacitance connected to internal base node |- |1| | |
- * | |TR |ideal reverse transit time |sec |0|10ns | |
- * | |CJS |zero-bias collector-substrate capacitance |F |0|2pF |* |
- * | |VJS |substrate junction built-in potential |V |0.75| | |
- * | |MJS |substrate junction exponential factor |- |0|0.5| |
- * | |XTB |forward and reverse beta temperature exponent |- |0| | |
- * | |EG|energy gap for temperature effect on IS |eV |1.11| | |
- * | |XTI|temperature exponent for effect on IS |- |3| | |
- * | |KF |flicker-noise coefficient |- |0| | |
- * | |AF |flicker-noise exponent |- |1| | |
- * | |FC |coefficient for forward-bias depletion capacitance formula |- |0.5| | |
- * | |TNOM |Parameter measurement temperature |C |27|50| |
- */
-
- class bjt_model_t : public param_model_t
- {
- public:
- bjt_model_t(device_t &device, const pstring name, const pstring val)
- : param_model_t(device, name, val)
- , m_IS(*this, "IS")
- , m_BF(*this, "BF")
- , m_NF(*this, "NF")
- , m_BR(*this, "BR")
- , m_NR(*this, "NR")
- {}
-
- value_t m_IS; //!< transport saturation current
- value_t m_BF; //!< ideal maximum forward beta
- value_t m_NF; //!< forward current emission coefficient
- value_t m_BR; //!< ideal maximum reverse beta 
- value_t m_NR; //!< reverse current emission coefficient
- };
-
- // Have a common start for transistors
-
-NETLIB_OBJECT(Q)
-{
-public:
- enum q_type {
- BJT_NPN,
- BJT_PNP
- };
-
- NETLIB_CONSTRUCTOR(Q)
- , m_model(*this, "MODEL", "")
- , m_qtype(BJT_NPN)
- {
- }
-
- NETLIB_IS_DYNAMIC()
-
- //NETLIB_RESETI();
- NETLIB_UPDATEI();
-
- inline q_type qtype() const { return m_qtype; }
- inline bool is_qtype(q_type atype) const { return m_qtype == atype; }
- inline void set_qtype(q_type atype) { m_qtype = atype; }
-protected:
-
- bjt_model_t m_model;
-private:
- q_type m_qtype;
-};
-
-NETLIB_OBJECT_DERIVED(QBJT, Q)
-{
-public:
- NETLIB_CONSTRUCTOR_DERIVED(QBJT, Q)
- { }
-
-protected:
-
-private:
-};
-
-
-
-
-// -----------------------------------------------------------------------------
-// nld_QBJT_switch
-// -----------------------------------------------------------------------------
-
-
-/*
- * + - C
- * B ----VVV----+ |
- * | |
- * Rb Rc
- * Rb Rc
- * Rb Rc
- * | |
- * +----+----+
- * |
- * E
- */
-
-NETLIB_OBJECT_DERIVED(QBJT_switch, QBJT)
-{
- NETLIB_CONSTRUCTOR_DERIVED(QBJT_switch, QBJT)
- , m_RB(*this, "m_RB", true)
- , m_RC(*this, "m_RC", true)
- , m_BC_dummy(*this, "m_BC", true)
- , m_gB(NETLIST_GMIN_DEFAULT)
- , m_gC(NETLIST_GMIN_DEFAULT)
- , m_V(0.0)
- , m_state_on(*this, "m_state_on", 0)
- {
- register_subalias("B", m_RB.m_P);
- register_subalias("E", m_RB.m_N);
- register_subalias("C", m_RC.m_P);
- //register_term("_E1", m_RC.m_N);
-
- //register_term("_B1", m_BC_dummy.m_P);
- //register_term("_C1", m_BC_dummy.m_N);
-
- connect(m_RB.m_N, m_RC.m_N);
-
- connect(m_RB.m_P, m_BC_dummy.m_P);
- connect(m_RC.m_P, m_BC_dummy.m_N);
- }
-
- NETLIB_RESETI();
- NETLIB_UPDATEI();
- NETLIB_UPDATE_PARAMI();
- NETLIB_UPDATE_TERMINALSI();
-
- nld_twoterm m_RB;
- nld_twoterm m_RC;
-
- // FIXME: this is needed so we have all terminals belong to one net list
-
- nld_twoterm m_BC_dummy;
-
-protected:
-
-
- nl_double m_gB; // base conductance / switch on
- nl_double m_gC; // collector conductance / switch on
- nl_double m_V; // internal voltage source
- state_var<unsigned> m_state_on;
-
-private:
-};
-
-// -----------------------------------------------------------------------------
-// nld_QBJT_EB
-// -----------------------------------------------------------------------------
-
-
-NETLIB_OBJECT_DERIVED(QBJT_EB, QBJT)
-{
-public:
- NETLIB_CONSTRUCTOR_DERIVED(QBJT_EB, QBJT)
- , m_gD_BC(*this, "m_D_BC")
- , m_gD_BE(*this, "m_D_BE")
- , m_D_CB(*this, "m_D_CB", true)
- , m_D_EB(*this, "m_D_EB", true)
- , m_D_EC(*this, "m_D_EC", true)
- , m_alpha_f(0)
- , m_alpha_r(0)
- {
- register_subalias("E", m_D_EB.m_P); // Cathode
- register_subalias("B", m_D_EB.m_N); // Anode
-
- register_subalias("C", m_D_CB.m_P); // Cathode
- //register_term("_B1", m_D_CB.m_N); // Anode
-
- //register_term("_E1", m_D_EC.m_P);
- //register_term("_C1", m_D_EC.m_N);
-
- connect(m_D_EB.m_P, m_D_EC.m_P);
- connect(m_D_EB.m_N, m_D_CB.m_N);
- connect(m_D_CB.m_P, m_D_EC.m_N);
- }
-
-protected:
-
- NETLIB_RESETI();
- NETLIB_UPDATEI();
- NETLIB_UPDATE_PARAMI();
- NETLIB_UPDATE_TERMINALSI();
-
- generic_diode m_gD_BC;
- generic_diode m_gD_BE;
-
-private:
- nld_twoterm m_D_CB; // gcc, gce - gcc, gec - gcc, gcc - gce | Ic
- nld_twoterm m_D_EB; // gee, gec - gee, gce - gee, gee - gec | Ie
- nld_twoterm m_D_EC; // 0, -gec, -gcc, 0 | 0
-
- nl_double m_alpha_f;
- nl_double m_alpha_r;
-
-};
-
- } //namespace devices
-} // namespace netlist
-
#endif /* NLD_BJT_H_ */
diff --git a/src/lib/netlist/analog/nld_fourterm.h b/src/lib/netlist/analog/nld_fourterm.h
index 0e4bcc03429..bd420b8cfa9 100644
--- a/src/lib/netlist/analog/nld_fourterm.h
+++ b/src/lib/netlist/analog/nld_fourterm.h
@@ -9,8 +9,7 @@
#define NLD_FOURTERM_H_
-#include "nl_base.h"
-#include "nld_twoterm.h"
+#include "nl_setup.h"
// ----------------------------------------------------------------------------------------
// Macros
@@ -28,204 +27,4 @@
#define LVCCS(name) \
NET_REGISTER_DEV(LVCCS, name)
-namespace netlist
-{
- namespace analog
- {
-// ----------------------------------------------------------------------------------------
-// nld_VCCS
-// ----------------------------------------------------------------------------------------
-
-/*
- * Voltage controlled current source
- *
- * IP ---+ +------> OP
- * | |
- * RI I
- * RI => G => I IOut = (V(IP)-V(IN)) * G
- * RI I
- * | |
- * IN ---+ +------< ON
- *
- * G=1 ==> 1V ==> 1A
- *
- * RI = 1 / NETLIST_GMIN
- *
- */
-
-NETLIB_OBJECT(VCCS)
-{
-public:
- NETLIB_CONSTRUCTOR(VCCS)
- , m_G(*this, "G", 1.0)
- , m_RI(*this, "RI", 1e9)
- , m_OP(*this, "OP")
- , m_ON(*this, "ON")
- , m_IP(*this, "IP")
- , m_IN(*this, "IN")
- , m_OP1(*this, "_OP1")
- , m_ON1(*this, "_ON1")
- , m_gfac(1.0)
- {
- m_IP.m_otherterm = &m_IN; // <= this should be NULL and terminal be filtered out prior to solving...
- m_IN.m_otherterm = &m_IP; // <= this should be NULL and terminal be filtered out prior to solving...
-
- m_OP.m_otherterm = &m_IP;
- m_OP1.m_otherterm = &m_IN;
-
- m_ON.m_otherterm = &m_IP;
- m_ON1.m_otherterm = &m_IN;
-
- connect(m_OP, m_OP1);
- connect(m_ON, m_ON1);
- m_gfac = NL_FCONST(1.0);
- }
-
- param_double_t m_G;
- param_double_t m_RI;
-
-protected:
- NETLIB_RESETI();
- NETLIB_UPDATEI();
- NETLIB_UPDATE_PARAMI()
- {
- NETLIB_NAME(VCCS)::reset();
- }
-
- terminal_t m_OP;
- terminal_t m_ON;
-
- terminal_t m_IP;
- terminal_t m_IN;
-
- terminal_t m_OP1;
- terminal_t m_ON1;
-
- nl_double m_gfac;
-};
-
-/* Limited Current source*/
-
-NETLIB_OBJECT_DERIVED(LVCCS, VCCS)
-{
-public:
- NETLIB_CONSTRUCTOR_DERIVED(LVCCS, VCCS)
- , m_cur_limit(*this, "CURLIM", 1000.0)
- , m_vi(0.0)
- {
- }
-
- NETLIB_IS_DYNAMIC()
-
- param_double_t m_cur_limit; /* current limit */
-
-protected:
- NETLIB_UPDATEI();
- NETLIB_RESETI();
- NETLIB_UPDATE_PARAMI();
- NETLIB_UPDATE_TERMINALSI();
-
- nl_double m_vi;
-};
-
-// ----------------------------------------------------------------------------------------
-// nld_CCCS
-// ----------------------------------------------------------------------------------------
-
-/*
- * Current controlled current source
- *
- * IP ---+ +------> OP
- * | |
- * RI I
- * RI => G => I IOut = (V(IP)-V(IN)) / RI * G
- * RI I
- * | |
- * IN ---+ +------< ON
- *
- * G=1 ==> 1A ==> 1A
- *
- * RI = 1
- *
- * This needs high levels of accuracy to work with 1 Ohm RI.
- *
- */
-
-NETLIB_OBJECT_DERIVED(CCCS, VCCS)
-{
-public:
- NETLIB_CONSTRUCTOR_DERIVED(CCCS, VCCS)
- , m_gfac(1.0)
- {
- m_gfac = NL_FCONST(1.0) / m_RI();
- }
-
-protected:
- NETLIB_UPDATEI();
- NETLIB_RESETI();
- NETLIB_UPDATE_PARAMI();
-
- nl_double m_gfac;
-};
-
-
-// ----------------------------------------------------------------------------------------
-// nld_VCVS
-// ----------------------------------------------------------------------------------------
-
-/*
- * Voltage controlled voltage source
- *
- * Parameters:
- * G Default: 1
- * RO Default: 1 (would be typically 50 for an op-amp
- *
- * IP ---+ +--+---- OP
- * | | |
- * RI I RO
- * RI => G => I RO V(OP) - V(ON) = (V(IP)-V(IN)) * G
- * RI I RO
- * | | |
- * IN ---+ +--+---- ON
- *
- * G=1 ==> 1V ==> 1V
- *
- * RI = 1 / NETLIST_GMIN
- *
- * Internal GI = G / RO
- *
- */
-
-
-NETLIB_OBJECT_DERIVED(VCVS, VCCS)
-{
-public:
- NETLIB_CONSTRUCTOR_DERIVED(VCVS, VCCS)
- , m_RO(*this, "RO", 1.0)
- , m_OP2(*this, "_OP2")
- , m_ON2(*this, "_ON2")
- {
- m_OP2.m_otherterm = &m_ON2;
- m_ON2.m_otherterm = &m_OP2;
-
- connect(m_OP2, m_OP1);
- connect(m_ON2, m_ON1);
- }
-
- param_double_t m_RO;
-
-protected:
- //NETLIB_UPDATEI();
- NETLIB_RESETI();
- //NETLIB_UPDATE_PARAMI();
-
- terminal_t m_OP2;
- terminal_t m_ON2;
-
-};
-
- } //namespace devices
-} // namespace netlist
-
-
#endif /* NLD_FOURTERM_H_ */
diff --git a/src/lib/netlist/analog/nld_opamps.cpp b/src/lib/netlist/analog/nld_opamps.cpp
index e777ffb791c..64f6b1b6df9 100644
--- a/src/lib/netlist/analog/nld_opamps.cpp
+++ b/src/lib/netlist/analog/nld_opamps.cpp
@@ -6,9 +6,14 @@
*/
#include "nld_opamps.h"
-#include "devices/net_lib.h"
+#include "nl_base.h"
+#include "nl_errstr.h"
+#include "nlid_twoterm.h"
+#include "nlid_fourterm.h"
+#include <cmath>
+
namespace netlist
{
namespace analog
@@ -42,6 +47,61 @@ namespace netlist
*
* */
+ /*! Class representing the opamp model parameters.
+ * The opamp model was designed based on designs from
+ * http://www.ecircuitcenter.com/Circuits/opmodel1/opmodel1.htm.
+ * Currently 2 different types are supported: Type 1 and Type 3. Type 1
+ * is less complex and should run faster than Type 3.
+ *
+ * This is an extension to the traditional SPICE approach which
+ * assumes that you will be using an manufacturer model. These models may
+ * have copyrights incompatible with the netlist license. Thus they may not
+ * be suitable for certain implementations of netlist.
+ *
+ * For the typical use cases in low frequency (< 100 KHz) applications at
+ * which netlist is targeted, this model is certainly suitable. All parameters
+ * can be determined from a typical opamp datasheet.
+ *
+ * |Type|name |parameter |units|default| example|
+ * |:--:|:-----|:----------------------------------------------|:----|------:|-------:|
+ * | 3 |TYPE |Model Type, 1 and 3 are supported | | | |
+ * |1,3 |FPF |frequency of first pole |Hz | |100 |
+ * | 3 |SLEW |unity gain slew rate |V/s | | 1|
+ * |1,3 |RI |input resistance |Ohm | |1M |
+ * |1,3 |RO |output resistance |Ohm | |50 |
+ * |1,3 |UGF |unity gain frequency (transition frequency) |Hz | |1000 |
+ * | 3 |VLL |low output swing minus low supply rail |V | |1.5 |
+ * | 3 |VLH |high supply rail minus high output swing |V | |1.5 |
+ * | 3 |DAB |Differential Amp Bias - total quiescent current|A | |0.001 |
+ */
+
+ class opamp_model_t : public param_model_t
+ {
+ public:
+ opamp_model_t(device_t &device, const pstring name, const pstring val)
+ : param_model_t(device, name, val)
+ , m_TYPE(*this, "TYPE")
+ , m_FPF(*this, "FPF")
+ , m_SLEW(*this, "SLEW")
+ , m_RI(*this, "RI")
+ , m_RO(*this, "RO")
+ , m_UGF(*this, "UGF")
+ , m_VLL(*this, "VLL")
+ , m_VLH(*this, "VLH")
+ , m_DAB(*this, "DAB")
+ {}
+
+ value_t m_TYPE; //!< Model Type, 1 and 3 are supported
+ value_t m_FPF; //!< frequency of first pole
+ value_t m_SLEW; //!< unity gain slew rate
+ value_t m_RI; //!< input resistance
+ value_t m_RO; //!< output resistance
+ value_t m_UGF; //!< unity gain frequency (transition frequency)
+ value_t m_VLL; //!< low output swing minus low supply rail
+ value_t m_VLH; //!< high supply rail minus high output swing
+ value_t m_DAB; //!< Differential Amp Bias - total quiescent current
+ };
+
NETLIB_OBJECT(opamp)
{
@@ -99,7 +159,7 @@ namespace netlist
connect("EBUF.IP", "RP1.1");
}
else
- netlist().log().fatal("Unknown opamp type: {1}", m_type);
+ log().fatal(MF_1_UNKNOWN_OPAMP_TYPE, m_type);
}
diff --git a/src/lib/netlist/analog/nld_opamps.h b/src/lib/netlist/analog/nld_opamps.h
index b407bb2215e..31b883be688 100644
--- a/src/lib/netlist/analog/nld_opamps.h
+++ b/src/lib/netlist/analog/nld_opamps.h
@@ -10,10 +10,7 @@
#ifndef NLD_OPAMPS_H_
#define NLD_OPAMPS_H_
-#include "nl_base.h"
#include "nl_setup.h"
-#include "nld_twoterm.h"
-#include "nld_fourterm.h"
// ----------------------------------------------------------------------------------------
// Macros
@@ -23,72 +20,5 @@
NET_REGISTER_DEV(OPAMP, name) \
NETDEV_PARAMI(name, MODEL, model)
-// ----------------------------------------------------------------------------------------
-// Devices ...
-// ----------------------------------------------------------------------------------------
-
-namespace netlist
-{
- namespace analog
- {
-
- /*! Class representing the opamp model parameters.
- * The opamp model was designed based on designs from
- * http://www.ecircuitcenter.com/Circuits/opmodel1/opmodel1.htm.
- * Currently 2 different types are supported: Type 1 and Type 3. Type 1
- * is less complex and should run faster than Type 3.
- *
- * This is an extension to the traditional SPICE approach which
- * assumes that you will be using an manufacturer model. These models may
- * have copyrights incompatible with the netlist license. Thus they may not
- * be suitable for certain implementations of netlist.
- *
- * For the typical use cases in low frequency (< 100 KHz) applications at
- * which netlist is targeted, this model is certainly suitable. All parameters
- * can be determined from a typical opamp datasheet.
- *
- * |Type|name |parameter |units|default| example|
- * |:--:|:-----|:----------------------------------------------|:----|------:|-------:|
- * | 3 |TYPE  |Model Type, 1 and 3 are supported |  | | |
- * |1,3 |FPF  |frequency of first pole |Hz  | |100 |
- * | 3 |SLEW  |unity gain slew rate |V/s  | | 1|
- * |1,3 |RI  |input resistance |Ohm  | |1M |
- * |1,3 |RO  |output resistance |Ohm  | |50 |
- * |1,3 |UGF  |unity gain frequency (transition frequency) |Hz  | |1000 |
- * | 3 |VLL  |low output swing minus low supply rail |V  | |1.5 |
- * | 3 |VLH  |high supply rail minus high output swing |V  | |1.5 |
- * | 3 |DAB  |Differential Amp Bias - total quiescent current|A  | |0.001 |
- */
-
- class opamp_model_t : public param_model_t
- {
- public:
- opamp_model_t(device_t &device, const pstring name, const pstring val)
- : param_model_t(device, name, val)
- , m_TYPE(*this, "TYPE")
- , m_FPF(*this, "FPF")
- , m_SLEW(*this, "SLEW")
- , m_RI(*this, "RI")
- , m_RO(*this, "RO")
- , m_UGF(*this, "UGF")
- , m_VLL(*this, "VLL")
- , m_VLH(*this, "VLH")
- , m_DAB(*this, "DAB")
- {}
-
- value_t m_TYPE; //!< Model Type, 1 and 3 are supported
- value_t m_FPF; //!< frequency of first pole
- value_t m_SLEW; //!< unity gain slew rate
- value_t m_RI; //!< input resistance
- value_t m_RO; //!< output resistance
- value_t m_UGF; //!< unity gain frequency (transition frequency)
- value_t m_VLL; //!< low output swing minus low supply rail
- value_t m_VLH; //!< high supply rail minus high output swing
- value_t m_DAB; //!< Differential Amp Bias - total quiescent current
- };
-
-
- } //namespace analog
-} // namespace netlist
#endif /* NLD_OPAMPS_H_ */
diff --git a/src/lib/netlist/analog/nld_switches.cpp b/src/lib/netlist/analog/nld_switches.cpp
index 92afa752e86..bf92a8cf4f8 100644
--- a/src/lib/netlist/analog/nld_switches.cpp
+++ b/src/lib/netlist/analog/nld_switches.cpp
@@ -5,8 +5,9 @@
*
*/
-#include "nld_switches.h"
-#include "nl_setup.h"
+#include "nlid_twoterm.h"
+#include "nl_base.h"
+#include "nl_factory.h"
#define R_OFF (1.0 / netlist().gmin())
#define R_ON 0.01
diff --git a/src/lib/netlist/analog/nld_switches.h b/src/lib/netlist/analog/nld_switches.h
index d91cf775377..06af3fad0ca 100644
--- a/src/lib/netlist/analog/nld_switches.h
+++ b/src/lib/netlist/analog/nld_switches.h
@@ -10,8 +10,7 @@
#ifndef NLD_SWITCHES_H_
#define NLD_SWITCHES_H_
-#include "nl_base.h"
-#include "nld_twoterm.h"
+#include "nl_setup.h"
// ----------------------------------------------------------------------------------------
// Macros
@@ -23,5 +22,4 @@
#define SWITCH2(name) \
NET_REGISTER_DEV(SWITCH2, name)
-
#endif /* NLD_SWITCHES_H_ */
diff --git a/src/lib/netlist/analog/nld_twoterm.h b/src/lib/netlist/analog/nld_twoterm.h
index 06325679dff..3ffbafd3b51 100644
--- a/src/lib/netlist/analog/nld_twoterm.h
+++ b/src/lib/netlist/analog/nld_twoterm.h
@@ -1,39 +1,10 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
-/*
- * nld_twoterm.h
- *
- * Devices with two terminals ...
- *
- *
- * (k)
- * +-----T-----+
- * | | |
- * | +--+--+ |
- * | | | |
- * | R | |
- * | R | |
- * | R I |
- * | | I | Device n
- * | V+ I |
- * | V | |
- * | V- | |
- * | | | |
- * | +--+--+ |
- * | | |
- * +-----T-----+
- * (l)
- *
- * This is a resistance in series to a voltage source and paralleled by a
- * current source. This is suitable to model voltage sources, current sources,
- * resistors, capacitors, inductances and diodes.
- *
- */
#ifndef NLD_TWOTERM_H_
#define NLD_TWOTERM_H_
-#include "nl_base.h"
+#include "nl_setup.h"
// -----------------------------------------------------------------------------
// Macros
@@ -95,397 +66,4 @@
#define IND_P(ind) (static_cast<double>(ind) * 1e-12)
#endif
-// -----------------------------------------------------------------------------
-// Implementation
-// -----------------------------------------------------------------------------
-
-namespace netlist
-{
- namespace analog
- {
-// -----------------------------------------------------------------------------
-// nld_twoterm
-// -----------------------------------------------------------------------------
-
-NETLIB_OBJECT(twoterm)
-{
- NETLIB_CONSTRUCTOR_EX(twoterm, bool terminals_owned = false)
- , m_P(bselect(terminals_owned, owner, *this), (terminals_owned ? name + "." : "") + "1")
- , m_N(bselect(terminals_owned, owner, *this), (terminals_owned ? name + "." : "") + "2")
- {
- m_P.m_otherterm = &m_N;
- m_N.m_otherterm = &m_P;
- }
-
- terminal_t m_P;
- terminal_t m_N;
-
- //NETLIB_UPDATE_TERMINALSI() { }
- //NETLIB_RESETI() { }
- NETLIB_UPDATEI();
-
-public:
- /* inline */ void set(const nl_double G, const nl_double V, const nl_double I)
- {
- /* GO, GT, I */
- m_P.set( G, G, ( V) * G - I);
- m_N.set( G, G, ( -V) * G + I);
- }
-
- /* inline */ nl_double deltaV() const
- {
- return m_P.net().Q_Analog() - m_N.net().Q_Analog();
- }
-
- void set_mat(const nl_double a11, const nl_double a12, const nl_double r1,
- const nl_double a21, const nl_double a22, const nl_double r2)
- {
- /* GO, GT, I */
- m_P.set(-a12, a11, r1);
- m_N.set(-a21, a22, r2);
- }
-
-private:
- template <class C>
- static core_device_t &bselect(bool b, C &d1, core_device_t &d2)
- {
- core_device_t *h = dynamic_cast<core_device_t *>(&d1);
- return b ? *h : d2;
- }
-};
-
-
-// -----------------------------------------------------------------------------
-// nld_R
-// -----------------------------------------------------------------------------
-
-NETLIB_OBJECT_DERIVED(R_base, twoterm)
-{
- NETLIB_CONSTRUCTOR_DERIVED(R_base, twoterm)
- {
- }
-
-public:
- inline void set_R(const nl_double R)
- {
- const nl_double G = NL_FCONST(1.0) / R;
- set_mat( G, -G, 0.0,
- -G, G, 0.0);
- }
-
-protected:
- NETLIB_RESETI();
- NETLIB_UPDATEI();
-
-};
-
-NETLIB_OBJECT_DERIVED(R, R_base)
-{
- NETLIB_CONSTRUCTOR_DERIVED(R, R_base)
- , m_R(*this, "R", 1e9)
- {
- }
-
- param_double_t m_R;
-
-protected:
-
- NETLIB_RESETI();
- //NETLIB_UPDATEI() { }
- NETLIB_UPDATE_PARAMI();
-
-private:
- /* protect set_R ... it's a recipe to desaster when used to bypass the parameter */
- using NETLIB_NAME(R_base)::set_R;
-};
-
-// -----------------------------------------------------------------------------
-// nld_POT
-// -----------------------------------------------------------------------------
-
-NETLIB_OBJECT(POT)
-{
- NETLIB_CONSTRUCTOR(POT)
- , m_R1(*this, "_R1")
- , m_R2(*this, "_R2")
- , m_R(*this, "R", 10000)
- , m_Dial(*this, "DIAL", 0.5)
- , m_DialIsLog(*this, "DIALLOG", 0)
- {
- register_subalias("1", m_R1.m_P);
- register_subalias("2", m_R1.m_N);
- register_subalias("3", m_R2.m_N);
-
- connect(m_R2.m_P, m_R1.m_N);
-
- }
-
- //NETLIB_UPDATEI();
- NETLIB_RESETI();
- NETLIB_UPDATE_PARAMI();
-
-private:
- NETLIB_SUB(R_base) m_R1;
- NETLIB_SUB(R_base) m_R2;
-
- param_double_t m_R;
- param_double_t m_Dial;
- param_logic_t m_DialIsLog;
-};
-
-NETLIB_OBJECT(POT2)
-{
- NETLIB_CONSTRUCTOR(POT2)
- , m_R1(*this, "_R1")
- , m_R(*this, "R", 10000)
- , m_Dial(*this, "DIAL", 0.5)
- , m_DialIsLog(*this, "DIALLOG", 0)
- , m_Reverse(*this, "REVERSE", 0)
- {
- register_subalias("1", m_R1.m_P);
- register_subalias("2", m_R1.m_N);
-
- }
-
- //NETLIB_UPDATEI();
- NETLIB_RESETI();
- NETLIB_UPDATE_PARAMI();
-
-private:
- NETLIB_SUB(R_base) m_R1;
-
- param_double_t m_R;
- param_double_t m_Dial;
- param_logic_t m_DialIsLog;
- param_logic_t m_Reverse;
-};
-
-
-// -----------------------------------------------------------------------------
-// nld_C
-// -----------------------------------------------------------------------------
-
-NETLIB_OBJECT_DERIVED(C, twoterm)
-{
-public:
- NETLIB_CONSTRUCTOR_DERIVED(C, twoterm)
- , m_C(*this, "C", 1e-6)
- , m_GParallel(0.0)
- {
- //register_term("1", m_P);
- //register_term("2", m_N);
- }
-
- NETLIB_IS_TIMESTEP()
- NETLIB_TIMESTEPI();
-
- param_double_t m_C;
-
-protected:
- NETLIB_RESETI();
- NETLIB_UPDATEI();
- NETLIB_UPDATE_PARAMI();
-
-private:
- nl_double m_GParallel;
-
-};
-
-// -----------------------------------------------------------------------------
-// nld_L
-// -----------------------------------------------------------------------------
-
-NETLIB_OBJECT_DERIVED(L, twoterm)
-{
-public:
- NETLIB_CONSTRUCTOR_DERIVED(L, twoterm)
- , m_L(*this, "L", 1e-6)
- , m_GParallel(0.0)
- , m_G(0.0)
- , m_I(0.0)
- {
- //register_term("1", m_P);
- //register_term("2", m_N);
- }
-
- NETLIB_IS_TIMESTEP()
- NETLIB_TIMESTEPI();
-
- param_double_t m_L;
-
-protected:
- NETLIB_RESETI();
- NETLIB_UPDATEI();
- NETLIB_UPDATE_PARAMI();
-
-private:
- nl_double m_GParallel;
- nl_double m_G;
- nl_double m_I;
-};
-
-// -----------------------------------------------------------------------------
-// A generic diode model to be used in other devices (Diode, BJT ...)
-// -----------------------------------------------------------------------------
-
-class generic_diode
-{
-public:
- generic_diode(device_t &dev, pstring name);
-
- void update_diode(const nl_double nVd);
-
- void set_param(const nl_double Is, const nl_double n, nl_double gmin);
-
- inline nl_double I() const { return m_Id; }
- inline nl_double G() const { return m_G; }
- inline nl_double Ieq() const { return (m_Id - m_Vd * m_G); }
- inline nl_double Vd() const { return m_Vd; }
-
- /* owning object must save those ... */
-
-private:
- state_var<nl_double> m_Vd;
- state_var<nl_double> m_Id;
- state_var<nl_double> m_G;
-
- nl_double m_Vt;
- nl_double m_Is;
- nl_double m_n;
- nl_double m_gmin;
-
- nl_double m_VtInv;
- nl_double m_Vcrit;
-};
-
-/*! Class representing the diode model paramers.
- * This is the model representation of the diode model. Typically, SPICE uses
- * the following parameters. A "Y" in the first column indicates that the
- * parameter is actually used in netlist.
- *
- * |NL? |name |parameter |units|default| example|area  |
- * |:--:|:-----|:--------------------------------|:----|------:|-------:|:----:|
- * | Y |IS |saturation current |A |1.0e-14| 1.0e-14| *  |
- * | |RS |ohmic resistanc |Ohm | 0| 10| *  |
- * | Y |N |emission coefficient |- | 1| 1| |
- * | |TT |transit-time |sec | 0| 0.1ns| |
- * | |CJO |zero-bias junction capacitance |F | 0| 2pF| *  |
- * | |VJ |junction potential |V | 1| 0.6| |
- * | |M |grading coefficient |- | 0.5| 0.5| |
- * | |EG |band-gap energy |eV | 1.11| 1.11 Si| |
- * | |XTI |saturation-current temp.exp |- | 3|3.0 pn. 2.0 Schottky| |
- * | |KF |flicker noise coefficient |- | 0| | |
- * | |AF |flicker noise exponent |- | 1| | |
- * | |FC |coefficient for forward-bias depletion capacitance formula|-|0.5|| |
- * | |BV |reverse breakdown voltage |V |infinite| 40| |
- * | |IBV |current at breakdown voltage |V | 0.001| | |
- * | |TNOM |parameter measurement temperature|deg C| 27| 50| |
- *
- */
-
-class diode_model_t : public param_model_t
-{
-public:
- diode_model_t(device_t &device, const pstring name, const pstring val)
- : param_model_t(device, name, val)
- , m_IS(*this, "IS")
- , m_N(*this, "N")
- {}
-
- value_t m_IS; //!< saturation current.
- value_t m_N; //!< emission coefficient.
-};
-
-
-// -----------------------------------------------------------------------------
-// nld_D
-// -----------------------------------------------------------------------------
-
-NETLIB_OBJECT_DERIVED(D, twoterm)
-{
-public:
- NETLIB_CONSTRUCTOR_DERIVED(D, twoterm)
- , m_model(*this, "MODEL", "")
- , m_D(*this, "m_D")
- {
- register_subalias("A", m_P);
- register_subalias("K", m_N);
- }
-
- template <class CLASS>
- NETLIB_NAME(D)(CLASS &owner, const pstring name, const pstring model)
- : NETLIB_NAME(twoterm)(owner, name)
- , m_model(*this, "MODEL", model)
- , m_D(*this, "m_D")
- {
- register_subalias("A", m_P);
- register_subalias("K", m_N);
- }
-
-
- NETLIB_IS_DYNAMIC()
-
- NETLIB_UPDATE_TERMINALSI();
-
- diode_model_t m_model;
-
-protected:
- NETLIB_RESETI();
- NETLIB_UPDATEI();
- NETLIB_UPDATE_PARAMI();
-
- generic_diode m_D;
-};
-
-
-// -----------------------------------------------------------------------------
-// nld_VS - Voltage source
-//
-// netlist voltage source must have inner resistance
-// -----------------------------------------------------------------------------
-
-NETLIB_OBJECT_DERIVED(VS, twoterm)
-{
-public:
- NETLIB_CONSTRUCTOR_DERIVED(VS, twoterm)
- , m_R(*this, "R", 0.1)
- , m_V(*this, "V", 0.0)
- {
- register_subalias("P", m_P);
- register_subalias("N", m_N);
- }
-
-protected:
- NETLIB_UPDATEI();
- NETLIB_RESETI();
-
- param_double_t m_R;
- param_double_t m_V;
-};
-
-// -----------------------------------------------------------------------------
-// nld_CS - Current source
-// -----------------------------------------------------------------------------
-
-NETLIB_OBJECT_DERIVED(CS, twoterm)
-{
-public:
- NETLIB_CONSTRUCTOR_DERIVED(CS, twoterm)
- , m_I(*this, "I", 1.0)
- {
- register_subalias("P", m_P);
- register_subalias("N", m_N);
- }
-
- NETLIB_UPDATEI();
- NETLIB_RESETI();
-protected:
-
- param_double_t m_I;
-};
-
-
- } //namespace devices
-} // namespace netlist
-
#endif /* NLD_TWOTERM_H_ */
diff --git a/src/lib/netlist/analog/nld_fourterm.cpp b/src/lib/netlist/analog/nlid_fourterm.cpp
index 3707b2a74c4..493b22fe231 100644
--- a/src/lib/netlist/analog/nld_fourterm.cpp
+++ b/src/lib/netlist/analog/nlid_fourterm.cpp
@@ -6,13 +6,17 @@
*/
#include "solver/nld_solver.h"
-#include "nld_fourterm.h"
+#include "nlid_fourterm.h"
#include "nl_setup.h"
+#include <cmath>
+
namespace netlist
{
namespace analog
{
+
+
// ----------------------------------------------------------------------------------------
// nld_VCCS
// ----------------------------------------------------------------------------------------
@@ -119,5 +123,12 @@ NETLIB_RESET(VCVS)
m_ON2.set(NL_FCONST(1.0) / m_RO());
}
- } //namespace devices
+ } //namespace analog
+
+ namespace devices {
+ NETLIB_DEVICE_IMPL_NS(analog, VCVS)
+ NETLIB_DEVICE_IMPL_NS(analog, VCCS)
+ NETLIB_DEVICE_IMPL_NS(analog, CCCS)
+ NETLIB_DEVICE_IMPL_NS(analog, LVCCS)
+ }
} // namespace netlist
diff --git a/src/lib/netlist/analog/nlid_fourterm.h b/src/lib/netlist/analog/nlid_fourterm.h
new file mode 100644
index 00000000000..cfc8f30d751
--- /dev/null
+++ b/src/lib/netlist/analog/nlid_fourterm.h
@@ -0,0 +1,211 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * nlid_fourterm.h
+ *
+ */
+
+#ifndef NLID_FOURTERM_H_
+#define NLID_FOURTERM_H_
+
+#include "nl_base.h"
+
+namespace netlist {
+ namespace analog {
+
+ // ----------------------------------------------------------------------------------------
+ // nld_VCCS
+ // ----------------------------------------------------------------------------------------
+
+ /*
+ * Voltage controlled current source
+ *
+ * IP ---+ +------> OP
+ * | |
+ * RI I
+ * RI => G => I IOut = (V(IP)-V(IN)) * G
+ * RI I
+ * | |
+ * IN ---+ +------< ON
+ *
+ * G=1 ==> 1V ==> 1A
+ *
+ * RI = 1 / NETLIST_GMIN
+ *
+ */
+
+ NETLIB_OBJECT(VCCS)
+ {
+ public:
+ NETLIB_CONSTRUCTOR(VCCS)
+ , m_G(*this, "G", 1.0)
+ , m_RI(*this, "RI", 1e9)
+ , m_OP(*this, "OP")
+ , m_ON(*this, "ON")
+ , m_IP(*this, "IP")
+ , m_IN(*this, "IN")
+ , m_OP1(*this, "_OP1")
+ , m_ON1(*this, "_ON1")
+ , m_gfac(1.0)
+ {
+ m_IP.m_otherterm = &m_IN; // <= this should be NULL and terminal be filtered out prior to solving...
+ m_IN.m_otherterm = &m_IP; // <= this should be NULL and terminal be filtered out prior to solving...
+
+ m_OP.m_otherterm = &m_IP;
+ m_OP1.m_otherterm = &m_IN;
+
+ m_ON.m_otherterm = &m_IP;
+ m_ON1.m_otherterm = &m_IN;
+
+ connect(m_OP, m_OP1);
+ connect(m_ON, m_ON1);
+ m_gfac = NL_FCONST(1.0);
+ }
+
+ param_double_t m_G;
+ param_double_t m_RI;
+
+ protected:
+ NETLIB_RESETI();
+ NETLIB_UPDATEI();
+ NETLIB_UPDATE_PARAMI()
+ {
+ NETLIB_NAME(VCCS)::reset();
+ }
+
+ terminal_t m_OP;
+ terminal_t m_ON;
+
+ terminal_t m_IP;
+ terminal_t m_IN;
+
+ terminal_t m_OP1;
+ terminal_t m_ON1;
+
+ nl_double m_gfac;
+ };
+
+ /* Limited Current source*/
+
+ NETLIB_OBJECT_DERIVED(LVCCS, VCCS)
+ {
+ public:
+ NETLIB_CONSTRUCTOR_DERIVED(LVCCS, VCCS)
+ , m_cur_limit(*this, "CURLIM", 1000.0)
+ , m_vi(0.0)
+ {
+ }
+
+ NETLIB_IS_DYNAMIC(true)
+
+ param_double_t m_cur_limit; /* current limit */
+
+ protected:
+ NETLIB_UPDATEI();
+ NETLIB_RESETI();
+ NETLIB_UPDATE_PARAMI();
+ NETLIB_UPDATE_TERMINALSI();
+
+ nl_double m_vi;
+ };
+
+ // ----------------------------------------------------------------------------------------
+ // nld_CCCS
+ // ----------------------------------------------------------------------------------------
+
+ /*
+ * Current controlled current source
+ *
+ * IP ---+ +------> OP
+ * | |
+ * RI I
+ * RI => G => I IOut = (V(IP)-V(IN)) / RI * G
+ * RI I
+ * | |
+ * IN ---+ +------< ON
+ *
+ * G=1 ==> 1A ==> 1A
+ *
+ * RI = 1
+ *
+ * This needs high levels of accuracy to work with 1 Ohm RI.
+ *
+ */
+
+ NETLIB_OBJECT_DERIVED(CCCS, VCCS)
+ {
+ public:
+ NETLIB_CONSTRUCTOR_DERIVED(CCCS, VCCS)
+ , m_gfac(1.0)
+ {
+ m_gfac = NL_FCONST(1.0) / m_RI();
+ }
+
+ protected:
+ NETLIB_UPDATEI();
+ NETLIB_RESETI();
+ NETLIB_UPDATE_PARAMI();
+
+ nl_double m_gfac;
+ };
+
+
+ // ----------------------------------------------------------------------------------------
+ // nld_VCVS
+ // ----------------------------------------------------------------------------------------
+
+ /*
+ * Voltage controlled voltage source
+ *
+ * Parameters:
+ * G Default: 1
+ * RO Default: 1 (would be typically 50 for an op-amp
+ *
+ * IP ---+ +--+---- OP
+ * | | |
+ * RI I RO
+ * RI => G => I RO V(OP) - V(ON) = (V(IP)-V(IN)) * G
+ * RI I RO
+ * | | |
+ * IN ---+ +--+---- ON
+ *
+ * G=1 ==> 1V ==> 1V
+ *
+ * RI = 1 / NETLIST_GMIN
+ *
+ * Internal GI = G / RO
+ *
+ */
+
+
+ NETLIB_OBJECT_DERIVED(VCVS, VCCS)
+ {
+ public:
+ NETLIB_CONSTRUCTOR_DERIVED(VCVS, VCCS)
+ , m_RO(*this, "RO", 1.0)
+ , m_OP2(*this, "_OP2")
+ , m_ON2(*this, "_ON2")
+ {
+ m_OP2.m_otherterm = &m_ON2;
+ m_ON2.m_otherterm = &m_OP2;
+
+ connect(m_OP2, m_OP1);
+ connect(m_ON2, m_ON1);
+ }
+
+ param_double_t m_RO;
+
+ protected:
+ //NETLIB_UPDATEI();
+ NETLIB_RESETI();
+ //NETLIB_UPDATE_PARAMI();
+
+ terminal_t m_OP2;
+ terminal_t m_ON2;
+
+ };
+
+ }
+}
+
+#endif /* NLD_FOURTERM_H_ */
diff --git a/src/lib/netlist/analog/nld_twoterm.cpp b/src/lib/netlist/analog/nlid_twoterm.cpp
index a87e0c03f88..a9a4edb604a 100644
--- a/src/lib/netlist/analog/nld_twoterm.cpp
+++ b/src/lib/netlist/analog/nlid_twoterm.cpp
@@ -5,10 +5,12 @@
*
*/
-#include <solver/nld_solver.h>
-#include <algorithm>
+#include "solver/nld_solver.h"
-#include "nld_twoterm.h"
+#include "nlid_twoterm.h"
+#include "nl_factory.h"
+
+#include <cmath>
namespace netlist
{
@@ -23,7 +25,9 @@ generic_diode::generic_diode(device_t &dev, pstring name)
, m_Id(dev, name + ".m_Id", 0.0)
, m_G(dev, name + ".m_G", 1e-15)
, m_Vt(0.0)
+ , m_Vmin(0.0)
, m_Is(0.0)
+ , m_logIs(0.0)
, m_n(0.0)
, m_gmin(1e-15)
, m_VtInv(0.0)
@@ -36,10 +40,12 @@ void generic_diode::set_param(const nl_double Is, const nl_double n, nl_double g
{
static const double csqrt2 = std::sqrt(2.0);
m_Is = Is;
+ m_logIs = std::log(Is);
m_n = n;
m_gmin = gmin;
m_Vt = 0.0258 * m_n;
+ m_Vmin = -5.0 * m_Vt;
m_Vcrit = m_Vt * std::log(m_Vt / m_Is / csqrt2);
m_VtInv = 1.0 / m_Vt;
@@ -47,8 +53,7 @@ void generic_diode::set_param(const nl_double Is, const nl_double n, nl_double g
void generic_diode::update_diode(const nl_double nVd)
{
-#if 1
- if (nVd < NL_FCONST(-5.0) * m_Vt)
+ if (nVd < m_Vmin)
{
m_Vd = nVd;
m_G = m_gmin;
@@ -58,29 +63,20 @@ void generic_diode::update_diode(const nl_double nVd)
{
m_Vd = nVd;
//m_Vd = m_Vd + 10.0 * m_Vt * std::tanh((nVd - m_Vd) / 10.0 / m_Vt);
- const nl_double eVDVt = std::exp(m_Vd * m_VtInv);
- m_Id = m_Is * (eVDVt - NL_FCONST(1.0));
- m_G = m_Is * m_VtInv * eVDVt + m_gmin;
+ //const double IseVDVt = m_Is * std::exp(m_Vd * m_VtInv);
+ const double IseVDVt = std::exp(m_logIs + m_Vd * m_VtInv);
+ m_Id = IseVDVt - m_Is;
+ m_G = IseVDVt * m_VtInv + m_gmin;
}
else
{
-#if 1
- const nl_double a = std::max((nVd - m_Vd) * m_VtInv, NL_FCONST(-0.99));
+ const double a = std::max((nVd - m_Vd) * m_VtInv, NL_FCONST(-0.99));
m_Vd = m_Vd + std::log1p(a) * m_Vt;
-#else
- m_Vd = m_Vd + 10.0 * m_Vt * std::tanh((nVd - m_Vd) / 10.0 / m_Vt);
-#endif
- const nl_double eVDVt = std::exp(m_Vd * m_VtInv);
- m_Id = m_Is * (eVDVt - NL_FCONST(1.0));
-
- m_G = m_Is * m_VtInv * eVDVt + m_gmin;
+ //const double IseVDVt = m_Is * std::exp(m_Vd * m_VtInv);
+ const double IseVDVt = std::exp(m_logIs + m_Vd * m_VtInv);
+ m_Id = IseVDVt - m_Is;
+ m_G = IseVDVt * m_VtInv + m_gmin;
}
-#else
- m_Vd = m_Vd + 20.0 * m_Vt * std::tanh((nVd - m_Vd) / 20.0 / m_Vt);
- const nl_double eVDVt = std::exp(m_Vd * m_VtInv);
- m_Id = m_Is * (eVDVt - NL_FCONST(1.0));
- m_G = m_Is * m_VtInv * eVDVt + m_gmin;
-#endif
}
// ----------------------------------------------------------------------------------------
@@ -300,6 +296,13 @@ NETLIB_UPDATE(VS)
NETLIB_NAME(twoterm)::update();
}
+NETLIB_TIMESTEP(VS)
+{
+ this->set(1.0 / m_R(),
+ m_compiled.evaluate(std::vector<double>({netlist().time().as_double()})),
+ 0.0);
+}
+
// ----------------------------------------------------------------------------------------
// nld_CS
// ----------------------------------------------------------------------------------------
@@ -319,5 +322,24 @@ NETLIB_UPDATE(CS)
NETLIB_NAME(twoterm)::update();
}
- } //namespace devices
+NETLIB_TIMESTEP(CS)
+{
+ const double I = m_compiled.evaluate(std::vector<double>({netlist().time().as_double()}));
+ set_mat(0.0, 0.0, -I,
+ 0.0, 0.0, I);
+}
+
+ } //namespace analog
+
+ namespace devices {
+ NETLIB_DEVICE_IMPL_NS(analog, R)
+ NETLIB_DEVICE_IMPL_NS(analog, POT)
+ NETLIB_DEVICE_IMPL_NS(analog, POT2)
+ NETLIB_DEVICE_IMPL_NS(analog, C)
+ NETLIB_DEVICE_IMPL_NS(analog, L)
+ NETLIB_DEVICE_IMPL_NS(analog, D)
+ NETLIB_DEVICE_IMPL_NS(analog, VS)
+ NETLIB_DEVICE_IMPL_NS(analog, CS)
+ }
+
} // namespace netlist
diff --git a/src/lib/netlist/analog/nlid_twoterm.h b/src/lib/netlist/analog/nlid_twoterm.h
new file mode 100644
index 00000000000..6166c707d2d
--- /dev/null
+++ b/src/lib/netlist/analog/nlid_twoterm.h
@@ -0,0 +1,448 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * nld_twoterm.h
+ *
+ * Devices with two terminals ...
+ *
+ *
+ * (k)
+ * +-----T-----+
+ * | | |
+ * | +--+--+ |
+ * | | | |
+ * | R | |
+ * | R | |
+ * | R I |
+ * | | I | Device n
+ * | V+ I |
+ * | V | |
+ * | V- | |
+ * | | | |
+ * | +--+--+ |
+ * | | |
+ * +-----T-----+
+ * (l)
+ *
+ * This is a resistance in series to a voltage source and paralleled by a
+ * current source. This is suitable to model voltage sources, current sources,
+ * resistors, capacitors, inductances and diodes.
+ *
+ */
+
+#ifndef NLID_TWOTERM_H_
+#define NLID_TWOTERM_H_
+
+#include "nl_base.h"
+#include "plib/pfunction.h"
+
+// -----------------------------------------------------------------------------
+// Implementation
+// -----------------------------------------------------------------------------
+
+namespace netlist
+{
+ namespace analog
+ {
+// -----------------------------------------------------------------------------
+// nld_twoterm
+// -----------------------------------------------------------------------------
+
+NETLIB_OBJECT(twoterm)
+{
+ NETLIB_CONSTRUCTOR_EX(twoterm, bool terminals_owned = false)
+ , m_P(bselect(terminals_owned, owner, *this), (terminals_owned ? name + "." : "") + "1")
+ , m_N(bselect(terminals_owned, owner, *this), (terminals_owned ? name + "." : "") + "2")
+ {
+ m_P.m_otherterm = &m_N;
+ m_N.m_otherterm = &m_P;
+ }
+
+ terminal_t m_P;
+ terminal_t m_N;
+
+ //NETLIB_UPDATE_TERMINALSI() { }
+ //NETLIB_RESETI() { }
+ NETLIB_UPDATEI();
+
+public:
+ /* inline */ void set(const nl_double G, const nl_double V, const nl_double I)
+ {
+ /* GO, GT, I */
+ m_P.set( G, G, ( V) * G - I);
+ m_N.set( G, G, ( -V) * G + I);
+ }
+
+ /* inline */ nl_double deltaV() const
+ {
+ return m_P.net().Q_Analog() - m_N.net().Q_Analog();
+ }
+
+ void set_mat(const nl_double a11, const nl_double a12, const nl_double r1,
+ const nl_double a21, const nl_double a22, const nl_double r2)
+ {
+ /* GO, GT, I */
+ m_P.set(-a12, a11, r1);
+ m_N.set(-a21, a22, r2);
+ }
+
+private:
+ template <class C>
+ static core_device_t &bselect(bool b, C &d1, core_device_t &d2)
+ {
+ core_device_t *h = dynamic_cast<core_device_t *>(&d1);
+ return b ? *h : d2;
+ }
+};
+
+
+// -----------------------------------------------------------------------------
+// nld_R
+// -----------------------------------------------------------------------------
+
+NETLIB_OBJECT_DERIVED(R_base, twoterm)
+{
+ NETLIB_CONSTRUCTOR_DERIVED(R_base, twoterm)
+ {
+ }
+
+public:
+ inline void set_R(const nl_double R)
+ {
+ const nl_double G = NL_FCONST(1.0) / R;
+ set_mat( G, -G, 0.0,
+ -G, G, 0.0);
+ }
+
+protected:
+ NETLIB_RESETI();
+ NETLIB_UPDATEI();
+
+};
+
+NETLIB_OBJECT_DERIVED(R, R_base)
+{
+ NETLIB_CONSTRUCTOR_DERIVED(R, R_base)
+ , m_R(*this, "R", 1e9)
+ {
+ }
+
+ param_double_t m_R;
+
+protected:
+
+ NETLIB_RESETI();
+ //NETLIB_UPDATEI() { }
+ NETLIB_UPDATE_PARAMI();
+
+private:
+ /* protect set_R ... it's a recipe to desaster when used to bypass the parameter */
+ using NETLIB_NAME(R_base)::set_R;
+};
+
+// -----------------------------------------------------------------------------
+// nld_POT
+// -----------------------------------------------------------------------------
+
+NETLIB_OBJECT(POT)
+{
+ NETLIB_CONSTRUCTOR(POT)
+ , m_R1(*this, "_R1")
+ , m_R2(*this, "_R2")
+ , m_R(*this, "R", 10000)
+ , m_Dial(*this, "DIAL", 0.5)
+ , m_DialIsLog(*this, "DIALLOG", 0)
+ {
+ register_subalias("1", m_R1.m_P);
+ register_subalias("2", m_R1.m_N);
+ register_subalias("3", m_R2.m_N);
+
+ connect(m_R2.m_P, m_R1.m_N);
+
+ }
+
+ //NETLIB_UPDATEI();
+ NETLIB_RESETI();
+ NETLIB_UPDATE_PARAMI();
+
+private:
+ NETLIB_SUB(R_base) m_R1;
+ NETLIB_SUB(R_base) m_R2;
+
+ param_double_t m_R;
+ param_double_t m_Dial;
+ param_logic_t m_DialIsLog;
+};
+
+NETLIB_OBJECT(POT2)
+{
+ NETLIB_CONSTRUCTOR(POT2)
+ , m_R1(*this, "_R1")
+ , m_R(*this, "R", 10000)
+ , m_Dial(*this, "DIAL", 0.5)
+ , m_DialIsLog(*this, "DIALLOG", 0)
+ , m_Reverse(*this, "REVERSE", 0)
+ {
+ register_subalias("1", m_R1.m_P);
+ register_subalias("2", m_R1.m_N);
+
+ }
+
+ //NETLIB_UPDATEI();
+ NETLIB_RESETI();
+ NETLIB_UPDATE_PARAMI();
+
+private:
+ NETLIB_SUB(R_base) m_R1;
+
+ param_double_t m_R;
+ param_double_t m_Dial;
+ param_logic_t m_DialIsLog;
+ param_logic_t m_Reverse;
+};
+
+
+// -----------------------------------------------------------------------------
+// nld_C
+// -----------------------------------------------------------------------------
+
+NETLIB_OBJECT_DERIVED(C, twoterm)
+{
+public:
+ NETLIB_CONSTRUCTOR_DERIVED(C, twoterm)
+ , m_C(*this, "C", 1e-6)
+ , m_GParallel(0.0)
+ {
+ //register_term("1", m_P);
+ //register_term("2", m_N);
+ }
+
+ NETLIB_IS_TIMESTEP(true)
+ NETLIB_TIMESTEPI();
+
+ param_double_t m_C;
+
+protected:
+ NETLIB_RESETI();
+ NETLIB_UPDATEI();
+ NETLIB_UPDATE_PARAMI();
+
+private:
+ nl_double m_GParallel;
+
+};
+
+// -----------------------------------------------------------------------------
+// nld_L
+// -----------------------------------------------------------------------------
+
+NETLIB_OBJECT_DERIVED(L, twoterm)
+{
+public:
+ NETLIB_CONSTRUCTOR_DERIVED(L, twoterm)
+ , m_L(*this, "L", 1e-6)
+ , m_GParallel(0.0)
+ , m_G(0.0)
+ , m_I(0.0)
+ {
+ //register_term("1", m_P);
+ //register_term("2", m_N);
+ }
+
+ NETLIB_IS_TIMESTEP(true)
+ NETLIB_TIMESTEPI();
+
+ param_double_t m_L;
+
+protected:
+ NETLIB_RESETI();
+ NETLIB_UPDATEI();
+ NETLIB_UPDATE_PARAMI();
+
+private:
+ nl_double m_GParallel;
+ nl_double m_G;
+ nl_double m_I;
+};
+
+// -----------------------------------------------------------------------------
+// A generic diode model to be used in other devices (Diode, BJT ...)
+// -----------------------------------------------------------------------------
+
+class generic_diode
+{
+public:
+ generic_diode(device_t &dev, pstring name);
+
+ void update_diode(const double nVd);
+
+ void set_param(const double Is, const double n, double gmin);
+
+ double I() const { return m_Id; }
+ double G() const { return m_G; }
+ double Ieq() const { return (m_Id - m_Vd * m_G); }
+ double Vd() const { return m_Vd; }
+
+ /* owning object must save those ... */
+
+private:
+ state_var<double> m_Vd;
+ state_var<double> m_Id;
+ state_var<double> m_G;
+
+ double m_Vt;
+ double m_Vmin;
+ double m_Is;
+ double m_logIs;
+ double m_n;
+ double m_gmin;
+
+ double m_VtInv;
+ double m_Vcrit;
+};
+
+/*! Class representing the diode model paramers.
+ * This is the model representation of the diode model. Typically, SPICE uses
+ * the following parameters. A "Y" in the first column indicates that the
+ * parameter is actually used in netlist.
+ *
+ * |NL? |name |parameter |units|default| example|area |
+ * |:--:|:-----|:--------------------------------|:----|------:|-------:|:----:|
+ * | Y |IS |saturation current |A |1.0e-14| 1.0e-14| * |
+ * | |RS |ohmic resistanc |Ohm | 0| 10| * |
+ * | Y |N |emission coefficient |- | 1| 1| |
+ * | |TT |transit-time |sec | 0| 0.1ns| |
+ * | |CJO |zero-bias junction capacitance |F | 0| 2pF| * |
+ * | |VJ |junction potential |V | 1| 0.6| |
+ * | |M |grading coefficient |- | 0.5| 0.5| |
+ * | |EG |band-gap energy |eV | 1.11| 1.11 Si| |
+ * | |XTI |saturation-current temp.exp |- | 3|3.0 pn. 2.0 Schottky| |
+ * | |KF |flicker noise coefficient |- | 0| | |
+ * | |AF |flicker noise exponent |- | 1| | |
+ * | |FC |coefficient for forward-bias depletion capacitance formula|-|0.5|| |
+ * | |BV |reverse breakdown voltage |V |infinite| 40| |
+ * | |IBV |current at breakdown voltage |V | 0.001| | |
+ * | |TNOM |parameter measurement temperature|deg C| 27| 50| |
+ *
+ */
+
+class diode_model_t : public param_model_t
+{
+public:
+ diode_model_t(device_t &device, const pstring name, const pstring val)
+ : param_model_t(device, name, val)
+ , m_IS(*this, "IS")
+ , m_N(*this, "N")
+ {}
+
+ value_t m_IS; //!< saturation current.
+ value_t m_N; //!< emission coefficient.
+};
+
+
+// -----------------------------------------------------------------------------
+// nld_D
+// -----------------------------------------------------------------------------
+
+NETLIB_OBJECT_DERIVED(D, twoterm)
+{
+public:
+ NETLIB_CONSTRUCTOR_DERIVED(D, twoterm)
+ , m_model(*this, "MODEL", "")
+ , m_D(*this, "m_D")
+ {
+ register_subalias("A", m_P);
+ register_subalias("K", m_N);
+ }
+
+ template <class CLASS>
+ NETLIB_NAME(D)(CLASS &owner, const pstring name, const pstring model)
+ : NETLIB_NAME(twoterm)(owner, name)
+ , m_model(*this, "MODEL", model)
+ , m_D(*this, "m_D")
+ {
+ register_subalias("A", m_P);
+ register_subalias("K", m_N);
+ }
+
+ NETLIB_IS_DYNAMIC(true)
+ NETLIB_UPDATE_TERMINALSI();
+
+ diode_model_t m_model;
+
+protected:
+ NETLIB_RESETI();
+ NETLIB_UPDATEI();
+ NETLIB_UPDATE_PARAMI();
+
+ generic_diode m_D;
+};
+
+
+// -----------------------------------------------------------------------------
+// nld_VS - Voltage source
+//
+// netlist voltage source must have inner resistance
+// -----------------------------------------------------------------------------
+
+NETLIB_OBJECT_DERIVED(VS, twoterm)
+{
+public:
+ NETLIB_CONSTRUCTOR_DERIVED(VS, twoterm)
+ , m_R(*this, "R", 0.1)
+ , m_V(*this, "V", 0.0)
+ , m_func(*this,"FUNC", "")
+ {
+ register_subalias("P", m_P);
+ register_subalias("N", m_N);
+ if (m_func() != "")
+ m_compiled.compile_postfix(std::vector<pstring>({{"T"}}), m_func());
+ }
+
+ NETLIB_IS_TIMESTEP(m_func() != "")
+ NETLIB_TIMESTEPI();
+
+protected:
+ NETLIB_UPDATEI();
+ NETLIB_RESETI();
+
+ param_double_t m_R;
+ param_double_t m_V;
+ param_str_t m_func;
+ plib::pfunction m_compiled;
+};
+
+// -----------------------------------------------------------------------------
+// nld_CS - Current source
+// -----------------------------------------------------------------------------
+
+NETLIB_OBJECT_DERIVED(CS, twoterm)
+{
+public:
+ NETLIB_CONSTRUCTOR_DERIVED(CS, twoterm)
+ , m_I(*this, "I", 1.0)
+ , m_func(*this,"FUNC", "")
+ {
+ register_subalias("P", m_P);
+ register_subalias("N", m_N);
+ if (m_func() != "")
+ m_compiled.compile_postfix(std::vector<pstring>({{"T"}}), m_func());
+ }
+
+ NETLIB_IS_TIMESTEP(m_func() != "")
+ NETLIB_TIMESTEPI();
+protected:
+
+ NETLIB_UPDATEI();
+ NETLIB_RESETI();
+
+ param_double_t m_I;
+ param_str_t m_func;
+ plib::pfunction m_compiled;
+};
+
+
+ } //namespace devices
+} // namespace netlist
+
+#endif /* NLD_TWOTERM_H_ */
diff --git a/src/lib/netlist/build/doxygen.conf b/src/lib/netlist/build/doxygen.conf
index adf69b30e54..9de9b691114 100644
--- a/src/lib/netlist/build/doxygen.conf
+++ b/src/lib/netlist/build/doxygen.conf
@@ -24,7 +24,7 @@
# for the list of possible encodings.
# The default value is: UTF-8.
-DOXYFILE_ENCODING = UTF-8
+DOXYFILE_ENCODING = UTF-8
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
# double-quotes, unless you are using Doxywizard) that should identify the
@@ -32,33 +32,33 @@ DOXYFILE_ENCODING = UTF-8
# title of most generated pages and in a few other places.
# The default value is: My Project.
-PROJECT_NAME = "My Project"
+PROJECT_NAME = Netlist documentaton
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER =
+PROJECT_NUMBER =
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.
-PROJECT_BRIEF =
+PROJECT_BRIEF =
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
# in the documentation. The maximum height of the logo should not exceed 55
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
# the logo to the output directory.
-PROJECT_LOGO =
+PROJECT_LOGO =
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.
-OUTPUT_DIRECTORY = doxy
+OUTPUT_DIRECTORY = doxy
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
@@ -68,7 +68,7 @@ OUTPUT_DIRECTORY = doxy
# performance problems for the file system.
# The default value is: NO.
-CREATE_SUBDIRS = NO
+CREATE_SUBDIRS = NO
# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
# characters to appear in the names of generated files. If set to NO, non-ASCII
@@ -76,7 +76,7 @@ CREATE_SUBDIRS = NO
# U+3044.
# The default value is: NO.
-ALLOW_UNICODE_NAMES = NO
+ALLOW_UNICODE_NAMES = NO
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
@@ -91,14 +91,14 @@ ALLOW_UNICODE_NAMES = NO
# Ukrainian and Vietnamese.
# The default value is: English.
-OUTPUT_LANGUAGE = English
+OUTPUT_LANGUAGE = English
# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
# descriptions after the members that are listed in the file and class
# documentation (similar to Javadoc). Set to NO to disable this.
# The default value is: YES.
-BRIEF_MEMBER_DESC = YES
+BRIEF_MEMBER_DESC = YES
# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
# description of a member or function before the detailed description
@@ -107,7 +107,7 @@ BRIEF_MEMBER_DESC = YES
# brief descriptions will be completely suppressed.
# The default value is: YES.
-REPEAT_BRIEF = YES
+REPEAT_BRIEF = YES
# This tag implements a quasi-intelligent brief description abbreviator that is
# used to form the text in various listings. Each string in this list, if found
@@ -118,14 +118,14 @@ REPEAT_BRIEF = YES
# the entity):The $name class, The $name widget, The $name file, is, provides,
# specifies, contains, represents, a, an and the.
-ABBREVIATE_BRIEF =
+ABBREVIATE_BRIEF =
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# doxygen will generate a detailed section even if there is only a brief
# description.
# The default value is: NO.
-ALWAYS_DETAILED_SEC = NO
+ALWAYS_DETAILED_SEC = NO
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
# inherited members of a class in the documentation of that class as if those
@@ -133,14 +133,14 @@ ALWAYS_DETAILED_SEC = NO
# operators of the base classes will not be shown.
# The default value is: NO.
-INLINE_INHERITED_MEMB = NO
+INLINE_INHERITED_MEMB = NO
# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
# before files name in the file list and in the header files. If set to NO the
# shortest path that makes the file name unique will be used
# The default value is: YES.
-FULL_PATH_NAMES = YES
+FULL_PATH_NAMES = YES
# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
# Stripping is only done if one of the specified strings matches the left-hand
@@ -152,7 +152,7 @@ FULL_PATH_NAMES = YES
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
-STRIP_FROM_PATH = ../..
+STRIP_FROM_PATH = ../..
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
@@ -161,14 +161,14 @@ STRIP_FROM_PATH = ../..
# specify the list of include paths that are normally passed to the compiler
# using the -I flag.
-STRIP_FROM_INC_PATH =
+STRIP_FROM_INC_PATH =
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
# less readable) file names. This can be useful is your file systems doesn't
# support long names like on DOS, Mac, or CD-ROM.
# The default value is: NO.
-SHORT_NAMES = NO
+SHORT_NAMES = NO
# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
# first line (until the first dot) of a Javadoc-style comment as the brief
@@ -177,7 +177,7 @@ SHORT_NAMES = NO
# description.)
# The default value is: NO.
-JAVADOC_AUTOBRIEF = YES
+JAVADOC_AUTOBRIEF = YES
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
# line (until the first dot) of a Qt-style comment as the brief description. If
@@ -185,7 +185,7 @@ JAVADOC_AUTOBRIEF = YES
# requiring an explicit \brief command for a brief description.)
# The default value is: NO.
-QT_AUTOBRIEF = YES
+QT_AUTOBRIEF = YES
# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
@@ -203,20 +203,20 @@ MULTILINE_CPP_IS_BRIEF = NO
# documentation from any documented member that it re-implements.
# The default value is: YES.
-INHERIT_DOCS = YES
+INHERIT_DOCS = YES
# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
# page for each member. If set to NO, the documentation of a member will be part
# of the file/class/namespace that contains it.
# The default value is: NO.
-SEPARATE_MEMBER_PAGES = NO
+SEPARATE_MEMBER_PAGES = NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
# uses this value to replace tabs by spaces in code fragments.
# Minimum value: 1, maximum value: 16, default value: 4.
-TAB_SIZE = 4
+TAB_SIZE = 4
# This tag can be used to specify a number of aliases that act as commands in
# the documentation. An alias has the form:
@@ -228,13 +228,13 @@ TAB_SIZE = 4
# "Side Effects:". You can put \n's in the value part of an alias to insert
# newlines.
-ALIASES =
+ALIASES =
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding "class=itcl::class"
# will allow you to use the command class in the itcl::class meaning.
-TCL_SUBST =
+TCL_SUBST =
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For
@@ -242,7 +242,7 @@ TCL_SUBST =
# members will be omitted, etc.
# The default value is: NO.
-OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_FOR_C = NO
# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
# Python sources only. Doxygen will then generate output that is more tailored
@@ -250,19 +250,19 @@ OPTIMIZE_OUTPUT_FOR_C = NO
# qualified scopes will look different, etc.
# The default value is: NO.
-OPTIMIZE_OUTPUT_JAVA = NO
+OPTIMIZE_OUTPUT_JAVA = NO
# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
# sources. Doxygen will then generate output that is tailored for Fortran.
# The default value is: NO.
-OPTIMIZE_FOR_FORTRAN = NO
+OPTIMIZE_FOR_FORTRAN = NO
# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
# sources. Doxygen will then generate output that is tailored for VHDL.
# The default value is: NO.
-OPTIMIZE_OUTPUT_VHDL = NO
+OPTIMIZE_OUTPUT_VHDL = NO
# Doxygen selects the parser to use depending on the extension of the files it
# parses. With this tag you can assign which parser to use for a given
@@ -281,7 +281,7 @@ OPTIMIZE_OUTPUT_VHDL = NO
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
# the files are not read by doxygen.
-EXTENSION_MAPPING =
+EXTENSION_MAPPING =
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
# according to the Markdown format, which allows for more readable
@@ -291,7 +291,7 @@ EXTENSION_MAPPING =
# case of backward compatibilities issues.
# The default value is: YES.
-MARKDOWN_SUPPORT = YES
+MARKDOWN_SUPPORT = YES
# When enabled doxygen tries to link words that correspond to documented
# classes, or namespaces to their corresponding documentation. Such a link can
@@ -299,7 +299,7 @@ MARKDOWN_SUPPORT = YES
# globally by setting AUTOLINK_SUPPORT to NO.
# The default value is: YES.
-AUTOLINK_SUPPORT = YES
+AUTOLINK_SUPPORT = YES
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
# to include (a tag file for) the STL sources as input, then you should set this
@@ -309,13 +309,13 @@ AUTOLINK_SUPPORT = YES
# diagrams that involve STL classes more complete and accurate.
# The default value is: NO.
-BUILTIN_STL_SUPPORT = NO
+BUILTIN_STL_SUPPORT = NO
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.
# The default value is: NO.
-CPP_CLI_SUPPORT = NO
+CPP_CLI_SUPPORT = NO
# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
@@ -323,7 +323,7 @@ CPP_CLI_SUPPORT = NO
# of private inheritance when no explicit protection keyword is present.
# The default value is: NO.
-SIP_SUPPORT = NO
+SIP_SUPPORT = NO
# For Microsoft's IDL there are propget and propput attributes to indicate
# getter and setter methods for a property. Setting this option to YES will make
@@ -333,7 +333,7 @@ SIP_SUPPORT = NO
# should set this option to NO.
# The default value is: YES.
-IDL_PROPERTY_SUPPORT = YES
+IDL_PROPERTY_SUPPORT = YES
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
# tag is set to YES then doxygen will reuse the documentation of the first
@@ -341,7 +341,7 @@ IDL_PROPERTY_SUPPORT = YES
# all members of a group must be documented explicitly.
# The default value is: NO.
-DISTRIBUTE_GROUP_DOC = NO
+DISTRIBUTE_GROUP_DOC = NO
# If one adds a struct or class to a group and this option is enabled, then also
# any nested class or struct is added to the same group. By default this option
@@ -357,7 +357,7 @@ GROUP_NESTED_COMPOUNDS = NO
# \nosubgrouping command.
# The default value is: YES.
-SUBGROUPING = YES
+SUBGROUPING = YES
# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
# are shown inside the group in which they are included (e.g. using \ingroup)
@@ -378,7 +378,7 @@ INLINE_GROUPED_CLASSES = NO
# Man pages) or section (for LaTeX and RTF).
# The default value is: NO.
-INLINE_SIMPLE_STRUCTS = NO
+INLINE_SIMPLE_STRUCTS = NO
# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
# enum is documented as struct, union, or enum with the name of the typedef. So
@@ -389,7 +389,7 @@ INLINE_SIMPLE_STRUCTS = NO
# types are typedef'ed and only the typedef is referenced, never the tag name.
# The default value is: NO.
-TYPEDEF_HIDES_STRUCT = NO
+TYPEDEF_HIDES_STRUCT = NO
# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
# cache is used to resolve symbols given their name and scope. Since this can be
@@ -402,7 +402,7 @@ TYPEDEF_HIDES_STRUCT = NO
# the optimal cache size from a speed point of view.
# Minimum value: 0, maximum value: 9, default value: 0.
-LOOKUP_CACHE_SIZE = 0
+LOOKUP_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
@@ -416,25 +416,25 @@ LOOKUP_CACHE_SIZE = 0
# normally produced when WARNINGS is set to YES.
# The default value is: NO.
-EXTRACT_ALL = NO
+EXTRACT_ALL = NO
# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
# be included in the documentation.
# The default value is: NO.
-EXTRACT_PRIVATE = NO
+EXTRACT_PRIVATE = NO
# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
# scope will be included in the documentation.
# The default value is: NO.
-EXTRACT_PACKAGE = NO
+EXTRACT_PACKAGE = NO
# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
# included in the documentation.
# The default value is: NO.
-EXTRACT_STATIC = NO
+EXTRACT_STATIC = NO
# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
# locally in source files will be included in the documentation. If set to NO,
@@ -442,7 +442,7 @@ EXTRACT_STATIC = NO
# for Java sources.
# The default value is: YES.
-EXTRACT_LOCAL_CLASSES = YES
+EXTRACT_LOCAL_CLASSES = YES
# This flag is only useful for Objective-C code. If set to YES, local methods,
# which are defined in the implementation section but not in the interface are
@@ -450,7 +450,7 @@ EXTRACT_LOCAL_CLASSES = YES
# included.
# The default value is: NO.
-EXTRACT_LOCAL_METHODS = NO
+EXTRACT_LOCAL_METHODS = NO
# If this flag is set to YES, the members of anonymous namespaces will be
# extracted and appear in the documentation as a namespace called
@@ -459,7 +459,7 @@ EXTRACT_LOCAL_METHODS = NO
# are hidden.
# The default value is: NO.
-EXTRACT_ANON_NSPACES = NO
+EXTRACT_ANON_NSPACES = NO
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
# undocumented members inside documented classes or files. If set to NO these
@@ -467,7 +467,7 @@ EXTRACT_ANON_NSPACES = NO
# section is generated. This option has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
-HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_MEMBERS = YES
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy. If set
@@ -475,28 +475,28 @@ HIDE_UNDOC_MEMBERS = NO
# has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
-HIDE_UNDOC_CLASSES = NO
+HIDE_UNDOC_CLASSES = YES
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
# (class|struct|union) declarations. If set to NO, these declarations will be
# included in the documentation.
# The default value is: NO.
-HIDE_FRIEND_COMPOUNDS = NO
+HIDE_FRIEND_COMPOUNDS = NO
# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
# documentation blocks found inside the body of a function. If set to NO, these
# blocks will be appended to the function's detailed documentation block.
# The default value is: NO.
-HIDE_IN_BODY_DOCS = NO
+HIDE_IN_BODY_DOCS = NO
# The INTERNAL_DOCS tag determines if documentation that is typed after a
# \internal command is included. If the tag is set to NO then the documentation
# will be excluded. Set it to YES to include the internal documentation.
# The default value is: NO.
-INTERNAL_DOCS = NO
+INTERNAL_DOCS = NO
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
# names in lower-case letters. If set to YES, upper-case letters are also
@@ -505,53 +505,53 @@ INTERNAL_DOCS = NO
# and Mac users are advised to set this option to NO.
# The default value is: system dependent.
-CASE_SENSE_NAMES = YES
+CASE_SENSE_NAMES = YES
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
# their full class and namespace scopes in the documentation. If set to YES, the
# scope will be hidden.
# The default value is: NO.
-HIDE_SCOPE_NAMES = NO
+HIDE_SCOPE_NAMES = NO
# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
# append additional text to a page's title, such as Class Reference. If set to
# YES the compound reference will be hidden.
# The default value is: NO.
-HIDE_COMPOUND_REFERENCE= NO
+HIDE_COMPOUND_REFERENCE = NO
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
# the files that are included by a file in the documentation of that file.
# The default value is: YES.
-SHOW_INCLUDE_FILES = YES
+SHOW_INCLUDE_FILES = YES
# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
# grouped member an include statement to the documentation, telling the reader
# which file to include in order to use the member.
# The default value is: NO.
-SHOW_GROUPED_MEMB_INC = NO
+SHOW_GROUPED_MEMB_INC = NO
# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
# files with double quotes in the documentation rather than with sharp brackets.
# The default value is: NO.
-FORCE_LOCAL_INCLUDES = NO
+FORCE_LOCAL_INCLUDES = NO
# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
# documentation for inline members.
# The default value is: YES.
-INLINE_INFO = YES
+INLINE_INFO = YES
# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
# (detailed) documentation of file and class members alphabetically by member
# name. If set to NO, the members will appear in declaration order.
# The default value is: YES.
-SORT_MEMBER_DOCS = YES
+SORT_MEMBER_DOCS = YES
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
# descriptions of file, namespace and class members alphabetically by member
@@ -559,7 +559,7 @@ SORT_MEMBER_DOCS = YES
# this will also influence the order of the classes in the class list.
# The default value is: NO.
-SORT_BRIEF_DOCS = NO
+SORT_BRIEF_DOCS = NO
# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
# (brief and detailed) documentation of class members so that constructors and
@@ -578,7 +578,7 @@ SORT_MEMBERS_CTORS_1ST = NO
# appear in their defined order.
# The default value is: NO.
-SORT_GROUP_NAMES = NO
+SORT_GROUP_NAMES = NO
# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
# fully-qualified names, including namespaces. If set to NO, the class list will
@@ -588,7 +588,7 @@ SORT_GROUP_NAMES = NO
# list.
# The default value is: NO.
-SORT_BY_SCOPE_NAME = NO
+SORT_BY_SCOPE_NAME = NO
# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
# type resolution of all parameters of a function it will reject a match between
@@ -598,38 +598,38 @@ SORT_BY_SCOPE_NAME = NO
# accept a match between prototype and implementation in such cases.
# The default value is: NO.
-STRICT_PROTO_MATCHING = NO
+STRICT_PROTO_MATCHING = NO
# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
# list. This list is created by putting \todo commands in the documentation.
# The default value is: YES.
-GENERATE_TODOLIST = YES
+GENERATE_TODOLIST = YES
# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
# list. This list is created by putting \test commands in the documentation.
# The default value is: YES.
-GENERATE_TESTLIST = YES
+GENERATE_TESTLIST = YES
# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
# list. This list is created by putting \bug commands in the documentation.
# The default value is: YES.
-GENERATE_BUGLIST = YES
+GENERATE_BUGLIST = YES
# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
# the deprecated list. This list is created by putting \deprecated commands in
# the documentation.
# The default value is: YES.
-GENERATE_DEPRECATEDLIST= YES
+GENERATE_DEPRECATEDLIST = YES
# The ENABLED_SECTIONS tag can be used to enable conditional documentation
# sections, marked by \if <section_label> ... \endif and \cond <section_label>
# ... \endcond blocks.
-ENABLED_SECTIONS =
+ENABLED_SECTIONS =
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
# initial value of a variable or macro / define can have for it to appear in the
@@ -640,28 +640,28 @@ ENABLED_SECTIONS =
# documentation regardless of this setting.
# Minimum value: 0, maximum value: 10000, default value: 30.
-MAX_INITIALIZER_LINES = 30
+MAX_INITIALIZER_LINES = 30
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
# the bottom of the documentation of classes and structs. If set to YES, the
# list will mention the files that were used to generate the documentation.
# The default value is: YES.
-SHOW_USED_FILES = YES
+SHOW_USED_FILES = YES
# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
# will remove the Files entry from the Quick Index and from the Folder Tree View
# (if specified).
# The default value is: YES.
-SHOW_FILES = YES
+SHOW_FILES = YES
# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
# page. This will remove the Namespaces entry from the Quick Index and from the
# Folder Tree View (if specified).
# The default value is: YES.
-SHOW_NAMESPACES = YES
+SHOW_NAMESPACES = YES
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
# doxygen should invoke to get the current version for each file (typically from
@@ -671,7 +671,7 @@ SHOW_NAMESPACES = YES
# by doxygen. Whatever the program writes to standard output is used as the file
# version. For an example see the documentation.
-FILE_VERSION_FILTER =
+FILE_VERSION_FILTER =
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
# by doxygen. The layout file controls the global structure of the generated
@@ -684,7 +684,7 @@ FILE_VERSION_FILTER =
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
# tag is left empty.
-LAYOUT_FILE =
+LAYOUT_FILE =
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
# the reference definitions. This must be a list of .bib files. The .bib
@@ -694,7 +694,7 @@ LAYOUT_FILE =
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
# search path. See also \cite for info how to create references.
-CITE_BIB_FILES =
+CITE_BIB_FILES =
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
@@ -705,7 +705,7 @@ CITE_BIB_FILES =
# messages are off.
# The default value is: NO.
-QUIET = NO
+QUIET = NO
# The WARNINGS tag can be used to turn on/off the warning messages that are
# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
@@ -714,14 +714,14 @@ QUIET = NO
# Tip: Turn warnings on while writing the documentation.
# The default value is: YES.
-WARNINGS = YES
+WARNINGS = YES
# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
# will automatically be disabled.
# The default value is: YES.
-WARN_IF_UNDOCUMENTED = YES
+WARN_IF_UNDOCUMENTED = YES
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
# potential errors in the documentation, such as not documenting some parameters
@@ -729,7 +729,7 @@ WARN_IF_UNDOCUMENTED = YES
# markup commands wrongly.
# The default value is: YES.
-WARN_IF_DOC_ERROR = YES
+WARN_IF_DOC_ERROR = YES
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
# are documented, but have no documentation for their parameters or return
@@ -737,13 +737,13 @@ WARN_IF_DOC_ERROR = YES
# parameter documentation, but not about the absence of documentation.
# The default value is: NO.
-WARN_NO_PARAMDOC = NO
+WARN_NO_PARAMDOC = NO
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
# a warning is encountered.
# The default value is: NO.
-WARN_AS_ERROR = NO
+WARN_AS_ERROR = NO
# The WARN_FORMAT tag determines the format of the warning messages that doxygen
# can produce. The string should contain the $file, $line, and $text tags, which
@@ -753,13 +753,13 @@ WARN_AS_ERROR = NO
# FILE_VERSION_FILTER)
# The default value is: $file:$line: $text.
-WARN_FORMAT = "$file:$line: $text"
+WARN_FORMAT = "$file:$line: $text"
# The WARN_LOGFILE tag can be used to specify a file to which warning and error
# messages should be written. If left blank the output is written to standard
# error (stderr).
-WARN_LOGFILE =
+WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
@@ -771,7 +771,7 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
-INPUT = ".." "../analog" "../documentation"
+INPUT = ".." "../analog" "../documentation"
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@@ -780,7 +780,7 @@ INPUT = ".." "../analog" "../documentation"
# possible encodings.
# The default value is: UTF-8.
-INPUT_ENCODING = UTF-8
+INPUT_ENCODING = UTF-8
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
@@ -796,13 +796,13 @@ INPUT_ENCODING = UTF-8
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl,
# *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js.
-FILE_PATTERNS = *.h *.cpp
+FILE_PATTERNS = *.h *.cpp
# The RECURSIVE tag can be used to specify whether or not subdirectories should
# be searched for input files as well.
# The default value is: NO.
-RECURSIVE = NO
+RECURSIVE = NO
# The EXCLUDE tag can be used to specify files and/or directories that should be
# excluded from the INPUT source files. This way you can easily exclude a
@@ -811,14 +811,14 @@ RECURSIVE = NO
# Note that relative paths are relative to the directory from which doxygen is
# run.
-EXCLUDE =
+EXCLUDE =
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
# from the input.
# The default value is: NO.
-EXCLUDE_SYMLINKS = NO
+EXCLUDE_SYMLINKS = NO
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
@@ -827,7 +827,7 @@ EXCLUDE_SYMLINKS = NO
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories for example use the pattern */test/*
-EXCLUDE_PATTERNS =
+EXCLUDE_PATTERNS =
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
@@ -838,33 +838,33 @@ EXCLUDE_PATTERNS =
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories use the pattern */test/*
-EXCLUDE_SYMBOLS =
+EXCLUDE_SYMBOLS =
# The EXAMPLE_PATH tag can be used to specify one or more files or directories
# that contain example code fragments that are included (see the \include
# command).
-EXAMPLE_PATH =
+EXAMPLE_PATH =
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
# *.h) to filter out the source-files in the directories. If left blank all
# files are included.
-EXAMPLE_PATTERNS =
+EXAMPLE_PATTERNS =
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
# searched for input files to be used with the \include or \dontinclude commands
# irrespective of the value of the RECURSIVE tag.
# The default value is: NO.
-EXAMPLE_RECURSIVE = NO
+EXAMPLE_RECURSIVE = NO
# The IMAGE_PATH tag can be used to specify one or more files or directories
# that contain images that are to be included in the documentation (see the
# \image command).
-IMAGE_PATH = "../documentation"
+IMAGE_PATH = "../documentation"
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
@@ -885,7 +885,7 @@ IMAGE_PATH = "../documentation"
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# properly processed by doxygen.
-INPUT_FILTER =
+INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis. Doxygen will compare the file name with each pattern and apply the
@@ -898,14 +898,14 @@ INPUT_FILTER =
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# properly processed by doxygen.
-FILTER_PATTERNS =
+FILTER_PATTERNS =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER) will also be used to filter the input files that are used for
# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
# The default value is: NO.
-FILTER_SOURCE_FILES = NO
+FILTER_SOURCE_FILES = NO
# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
@@ -913,14 +913,14 @@ FILTER_SOURCE_FILES = NO
# *.ext= (so without naming a filter).
# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
-FILTER_SOURCE_PATTERNS =
+FILTER_SOURCE_PATTERNS =
# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
# is part of the input, its contents will be placed on the main page
# (index.html). This can be useful if you have a project on for instance GitHub
# and want to reuse the introduction page also for the doxygen output.
-USE_MDFILE_AS_MAINPAGE =
+USE_MDFILE_AS_MAINPAGE =
#---------------------------------------------------------------------------
# Configuration options related to source browsing
@@ -933,20 +933,20 @@ USE_MDFILE_AS_MAINPAGE =
# also VERBATIM_HEADERS is set to NO.
# The default value is: NO.
-SOURCE_BROWSER = NO
+SOURCE_BROWSER = NO
# Setting the INLINE_SOURCES tag to YES will include the body of functions,
# classes and enums directly into the documentation.
# The default value is: NO.
-INLINE_SOURCES = NO
+INLINE_SOURCES = NO
# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
# special comment blocks from generated source code fragments. Normal C, C++ and
# Fortran comments will always remain visible.
# The default value is: YES.
-STRIP_CODE_COMMENTS = YES
+STRIP_CODE_COMMENTS = YES
# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
# function all documented functions referencing it will be listed.
@@ -958,7 +958,7 @@ REFERENCED_BY_RELATION = NO
# all documented entities called/used by that function will be listed.
# The default value is: NO.
-REFERENCES_RELATION = NO
+REFERENCES_RELATION = NO
# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
# to YES then the hyperlinks from functions in REFERENCES_RELATION and
@@ -976,7 +976,7 @@ REFERENCES_LINK_SOURCE = YES
# The default value is: YES.
# This tag requires that the tag SOURCE_BROWSER is set to YES.
-SOURCE_TOOLTIPS = YES
+SOURCE_TOOLTIPS = YES
# If the USE_HTAGS tag is set to YES then the references to source code will
# point to the HTML generated by the htags(1) tool instead of doxygen built-in
@@ -998,7 +998,7 @@ SOURCE_TOOLTIPS = YES
# The default value is: NO.
# This tag requires that the tag SOURCE_BROWSER is set to YES.
-USE_HTAGS = NO
+USE_HTAGS = NO
# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
# verbatim copy of the header file for each class for which an include is
@@ -1006,7 +1006,7 @@ USE_HTAGS = NO
# See also: Section \class.
# The default value is: YES.
-VERBATIM_HEADERS = YES
+VERBATIM_HEADERS = YES
# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
@@ -1025,7 +1025,7 @@ CLANG_ASSISTED_PARSING = NO
# specified with INPUT and INCLUDE_PATH.
# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
-CLANG_OPTIONS =
+CLANG_OPTIONS =
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
@@ -1036,14 +1036,14 @@ CLANG_OPTIONS =
# classes, structs, unions or interfaces.
# The default value is: YES.
-ALPHABETICAL_INDEX = YES
+ALPHABETICAL_INDEX = YES
# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
# which the alphabetical index list will be split.
# Minimum value: 1, maximum value: 20, default value: 5.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
-COLS_IN_ALPHA_INDEX = 5
+COLS_IN_ALPHA_INDEX = 5
# In case all classes in a project start with a common prefix, all classes will
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
@@ -1051,7 +1051,7 @@ COLS_IN_ALPHA_INDEX = 5
# while generating the index headers.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
-IGNORE_PREFIX =
+IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
@@ -1060,7 +1060,7 @@ IGNORE_PREFIX =
# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
# The default value is: YES.
-GENERATE_HTML = YES
+GENERATE_HTML = YES
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
@@ -1068,14 +1068,14 @@ GENERATE_HTML = YES
# The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_OUTPUT = html
+HTML_OUTPUT = html
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp).
# The default value is: .html.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_FILE_EXTENSION = .html
+HTML_FILE_EXTENSION = .html
# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
# each generated HTML page. If the tag is left blank doxygen will generate a
@@ -1095,7 +1095,7 @@ HTML_FILE_EXTENSION = .html
# of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_HEADER =
+HTML_HEADER =
# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
# generated HTML page. If the tag is left blank doxygen will generate a standard
@@ -1105,7 +1105,7 @@ HTML_HEADER =
# that doxygen normally uses.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_FOOTER =
+HTML_FOOTER =
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
# sheet that is used by each HTML page. It can be used to fine-tune the look of
@@ -1117,7 +1117,7 @@ HTML_FOOTER =
# obsolete.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_STYLESHEET =
+HTML_STYLESHEET =
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# cascading style sheets that are included after the standard style sheets
@@ -1130,7 +1130,7 @@ HTML_STYLESHEET =
# list). For an example see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_EXTRA_STYLESHEET = "../documentation/doc.css"
+HTML_EXTRA_STYLESHEET = "../documentation/doc.css"
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note
@@ -1140,7 +1140,7 @@ HTML_EXTRA_STYLESHEET = "../documentation/doc.css"
# files will be copied as-is; there are no commands or markers available.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_EXTRA_FILES =
+HTML_EXTRA_FILES =
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the style sheet and background images according to
@@ -1151,7 +1151,7 @@ HTML_EXTRA_FILES =
# Minimum value: 0, maximum value: 359, default value: 220.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_COLORSTYLE_HUE = 220
+HTML_COLORSTYLE_HUE = 220
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
# in the HTML output. For a value of 0 the output will use grayscales only. A
@@ -1159,7 +1159,7 @@ HTML_COLORSTYLE_HUE = 220
# Minimum value: 0, maximum value: 255, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_COLORSTYLE_SAT = 100
+HTML_COLORSTYLE_SAT = 100
# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
# luminance component of the colors in the HTML output. Values below 100
@@ -1170,7 +1170,7 @@ HTML_COLORSTYLE_SAT = 100
# Minimum value: 40, maximum value: 240, default value: 80.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_COLORSTYLE_GAMMA = 80
+HTML_COLORSTYLE_GAMMA = 80
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting this
@@ -1179,7 +1179,7 @@ HTML_COLORSTYLE_GAMMA = 80
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_TIMESTAMP = NO
+HTML_TIMESTAMP = NO
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
@@ -1187,7 +1187,7 @@ HTML_TIMESTAMP = NO
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_DYNAMIC_SECTIONS = NO
+HTML_DYNAMIC_SECTIONS = YES
# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
# shown in the various tree structured indices initially; the user can expand
@@ -1214,7 +1214,7 @@ HTML_INDEX_NUM_ENTRIES = 100
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
-GENERATE_DOCSET = NO
+GENERATE_DOCSET = NO
# This tag determines the name of the docset feed. A documentation feed provides
# an umbrella under which multiple documentation sets from a single provider
@@ -1222,7 +1222,7 @@ GENERATE_DOCSET = NO
# The default value is: Doxygen generated docs.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
-DOCSET_FEEDNAME = "Doxygen generated docs"
+DOCSET_FEEDNAME = "Doxygen generated docs"
# This tag specifies a string that should uniquely identify the documentation
# set bundle. This should be a reverse domain-name style string, e.g.
@@ -1230,7 +1230,7 @@ DOCSET_FEEDNAME = "Doxygen generated docs"
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
-DOCSET_BUNDLE_ID = org.doxygen.Project
+DOCSET_BUNDLE_ID = org.doxygen.Project
# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
# the documentation publisher. This should be a reverse domain-name style
@@ -1238,13 +1238,13 @@ DOCSET_BUNDLE_ID = org.doxygen.Project
# The default value is: org.doxygen.Publisher.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
-DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
# The default value is: Publisher.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
-DOCSET_PUBLISHER_NAME = Publisher
+DOCSET_PUBLISHER_NAME = Publisher
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
@@ -1262,14 +1262,14 @@ DOCSET_PUBLISHER_NAME = Publisher
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
-GENERATE_HTMLHELP = NO
+GENERATE_HTMLHELP = NO
# The CHM_FILE tag can be used to specify the file name of the resulting .chm
# file. You can add a path in front of the file if the result should not be
# written to the html output directory.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-CHM_FILE =
+CHM_FILE =
# The HHC_LOCATION tag can be used to specify the location (absolute path
# including file name) of the HTML help compiler (hhc.exe). If non-empty,
@@ -1277,20 +1277,20 @@ CHM_FILE =
# The file has to be specified with full path.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-HHC_LOCATION =
+HHC_LOCATION =
# The GENERATE_CHI flag controls if a separate .chi index file is generated
# (YES) or that it should be included in the master .chm file (NO).
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-GENERATE_CHI = NO
+GENERATE_CHI = NO
# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
# and project file content.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-CHM_INDEX_ENCODING =
+CHM_INDEX_ENCODING =
# The BINARY_TOC flag controls whether a binary table of contents is generated
# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
@@ -1298,14 +1298,14 @@ CHM_INDEX_ENCODING =
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-BINARY_TOC = NO
+BINARY_TOC = NO
# The TOC_EXPAND flag can be set to YES to add extra items for group members to
# the table of contents of the HTML help documentation and to the tree view.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-TOC_EXPAND = NO
+TOC_EXPAND = NO
# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
@@ -1314,14 +1314,14 @@ TOC_EXPAND = NO
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
-GENERATE_QHP = NO
+GENERATE_QHP = NO
# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
# the file name of the resulting .qch file. The path specified is relative to
# the HTML output folder.
# This tag requires that the tag GENERATE_QHP is set to YES.
-QCH_FILE =
+QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace
@@ -1329,7 +1329,7 @@ QCH_FILE =
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_QHP is set to YES.
-QHP_NAMESPACE = org.doxygen.Project
+QHP_NAMESPACE = org.doxygen.Project
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
# Help Project output. For more information please see Qt Help Project / Virtual
@@ -1338,7 +1338,7 @@ QHP_NAMESPACE = org.doxygen.Project
# The default value is: doc.
# This tag requires that the tag GENERATE_QHP is set to YES.
-QHP_VIRTUAL_FOLDER = doc
+QHP_VIRTUAL_FOLDER = doc
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
# filter to add. For more information please see Qt Help Project / Custom
@@ -1346,7 +1346,7 @@ QHP_VIRTUAL_FOLDER = doc
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
-QHP_CUST_FILTER_NAME =
+QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see Qt Help Project / Custom
@@ -1354,21 +1354,21 @@ QHP_CUST_FILTER_NAME =
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
-QHP_CUST_FILTER_ATTRS =
+QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's filter section matches. Qt Help Project / Filter Attributes (see:
# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
# This tag requires that the tag GENERATE_QHP is set to YES.
-QHP_SECT_FILTER_ATTRS =
+QHP_SECT_FILTER_ATTRS =
# The QHG_LOCATION tag can be used to specify the location of Qt's
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
# generated .qhp file.
# This tag requires that the tag GENERATE_QHP is set to YES.
-QHG_LOCATION =
+QHG_LOCATION =
# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
# generated, together with the HTML files, they form an Eclipse help plugin. To
@@ -1380,7 +1380,7 @@ QHG_LOCATION =
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
-GENERATE_ECLIPSEHELP = NO
+GENERATE_ECLIPSEHELP = NO
# A unique identifier for the Eclipse help plugin. When installing the plugin
# the directory name containing the HTML and XML files should also have this
@@ -1388,7 +1388,7 @@ GENERATE_ECLIPSEHELP = NO
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
-ECLIPSE_DOC_ID = org.doxygen.Project
+ECLIPSE_DOC_ID = org.doxygen.Project
# If you want full control over the layout of the generated HTML pages it might
# be necessary to disable the index and replace it with your own. The
@@ -1399,7 +1399,7 @@ ECLIPSE_DOC_ID = org.doxygen.Project
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
-DISABLE_INDEX = NO
+DISABLE_INDEX = NO
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information. If the tag
@@ -1416,7 +1416,7 @@ DISABLE_INDEX = NO
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
-GENERATE_TREEVIEW = NO
+GENERATE_TREEVIEW = NO
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation.
@@ -1426,21 +1426,21 @@ GENERATE_TREEVIEW = NO
# Minimum value: 0, maximum value: 20, default value: 4.
# This tag requires that the tag GENERATE_HTML is set to YES.
-ENUM_VALUES_PER_LINE = 4
+ENUM_VALUES_PER_LINE = 4
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
# to set the initial width (in pixels) of the frame in which the tree is shown.
# Minimum value: 0, maximum value: 1500, default value: 250.
# This tag requires that the tag GENERATE_HTML is set to YES.
-TREEVIEW_WIDTH = 250
+TREEVIEW_WIDTH = 250
# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
# external symbols imported via tag files in a separate window.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
-EXT_LINKS_IN_WINDOW = NO
+EXT_LINKS_IN_WINDOW = NO
# Use this tag to change the font size of LaTeX formulas included as images in
# the HTML documentation. When you change the font size after a successful
@@ -1449,7 +1449,7 @@ EXT_LINKS_IN_WINDOW = NO
# Minimum value: 8, maximum value: 50, default value: 10.
# This tag requires that the tag GENERATE_HTML is set to YES.
-FORMULA_FONTSIZE = 10
+FORMULA_FONTSIZE = 10
# Use the FORMULA_TRANPARENT tag to determine whether or not the images
# generated for formulas are transparent PNGs. Transparent PNGs are not
@@ -1460,7 +1460,7 @@ FORMULA_FONTSIZE = 10
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
-FORMULA_TRANSPARENT = YES
+FORMULA_TRANSPARENT = YES
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
# http://www.mathjax.org) which uses client side Javascript for the rendering
@@ -1471,7 +1471,7 @@ FORMULA_TRANSPARENT = YES
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
-USE_MATHJAX = YES
+USE_MATHJAX = YES
# When MathJax is enabled you can set the default output format to be used for
# the MathJax output. See the MathJax site (see:
@@ -1481,7 +1481,7 @@ USE_MATHJAX = YES
# The default value is: HTML-CSS.
# This tag requires that the tag USE_MATHJAX is set to YES.
-MATHJAX_FORMAT = HTML-CSS
+MATHJAX_FORMAT = HTML-CSS
# When MathJax is enabled you need to specify the location relative to the HTML
# output directory using the MATHJAX_RELPATH option. The destination directory
@@ -1494,14 +1494,14 @@ MATHJAX_FORMAT = HTML-CSS
# The default value is: http://cdn.mathjax.org/mathjax/latest.
# This tag requires that the tag USE_MATHJAX is set to YES.
-MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
# extension names that should be enabled during MathJax rendering. For example
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
# This tag requires that the tag USE_MATHJAX is set to YES.
-MATHJAX_EXTENSIONS =
+MATHJAX_EXTENSIONS =
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
# of code that will be used on startup of the MathJax code. See the MathJax site
@@ -1509,7 +1509,7 @@ MATHJAX_EXTENSIONS =
# example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES.
-MATHJAX_CODEFILE =
+MATHJAX_CODEFILE =
# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
# the HTML output. The underlying search engine uses javascript and DHTML and
@@ -1530,7 +1530,7 @@ MATHJAX_CODEFILE =
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
-SEARCHENGINE = YES
+SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a web server instead of a web client using Javascript. There
@@ -1542,7 +1542,7 @@ SEARCHENGINE = YES
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
-SERVER_BASED_SEARCH = NO
+SERVER_BASED_SEARCH = NO
# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
# script for searching. Instead the search results are written to an XML file
@@ -1558,7 +1558,7 @@ SERVER_BASED_SEARCH = NO
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
-EXTERNAL_SEARCH = NO
+EXTERNAL_SEARCH = NO
# The SEARCHENGINE_URL should point to a search engine hosted by a web server
# which will return the search results when EXTERNAL_SEARCH is enabled.
@@ -1569,7 +1569,7 @@ EXTERNAL_SEARCH = NO
# Searching" for details.
# This tag requires that the tag SEARCHENGINE is set to YES.
-SEARCHENGINE_URL =
+SEARCHENGINE_URL =
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
# search data is written to a file for indexing by an external tool. With the
@@ -1577,7 +1577,7 @@ SEARCHENGINE_URL =
# The default file is: searchdata.xml.
# This tag requires that the tag SEARCHENGINE is set to YES.
-SEARCHDATA_FILE = searchdata.xml
+SEARCHDATA_FILE = searchdata.xml
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
@@ -1585,7 +1585,7 @@ SEARCHDATA_FILE = searchdata.xml
# projects and redirect the results back to the right project.
# This tag requires that the tag SEARCHENGINE is set to YES.
-EXTERNAL_SEARCH_ID =
+EXTERNAL_SEARCH_ID =
# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
# projects other than the one defined by this configuration file, but that are
@@ -1595,7 +1595,7 @@ EXTERNAL_SEARCH_ID =
# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
# This tag requires that the tag SEARCHENGINE is set to YES.
-EXTRA_SEARCH_MAPPINGS =
+EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
@@ -1604,7 +1604,7 @@ EXTRA_SEARCH_MAPPINGS =
# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
# The default value is: YES.
-GENERATE_LATEX = YES
+GENERATE_LATEX = YES
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
@@ -1612,7 +1612,7 @@ GENERATE_LATEX = YES
# The default directory is: latex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_OUTPUT = latex
+LATEX_OUTPUT = latex
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked.
@@ -1623,14 +1623,14 @@ LATEX_OUTPUT = latex
# The default file is: latex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_CMD_NAME = latex
+LATEX_CMD_NAME = latex
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
# index for LaTeX.
# The default file is: makeindex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-MAKEINDEX_CMD_NAME = makeindex
+MAKEINDEX_CMD_NAME = makeindex
# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
# documents. This may be useful for small projects and may help to save some
@@ -1638,7 +1638,7 @@ MAKEINDEX_CMD_NAME = makeindex
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-COMPACT_LATEX = NO
+COMPACT_LATEX = NO
# The PAPER_TYPE tag can be used to set the paper type that is used by the
# printer.
@@ -1647,7 +1647,7 @@ COMPACT_LATEX = NO
# The default value is: a4.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-PAPER_TYPE = a4
+PAPER_TYPE = a4
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
# that should be included in the LaTeX output. The package can be specified just
@@ -1659,7 +1659,7 @@ PAPER_TYPE = a4
# If left blank no extra packages will be included.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-EXTRA_PACKAGES =
+EXTRA_PACKAGES =
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
# generated LaTeX document. The header should contain everything until the first
@@ -1675,7 +1675,7 @@ EXTRA_PACKAGES =
# to HTML_HEADER.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_HEADER =
+LATEX_HEADER =
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
# generated LaTeX document. The footer should contain everything after the last
@@ -1686,7 +1686,7 @@ LATEX_HEADER =
# Note: Only use a user-defined footer if you know what you are doing!
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_FOOTER =
+LATEX_FOOTER =
# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# LaTeX style sheets that are included after the standard style sheets created
@@ -1697,7 +1697,7 @@ LATEX_FOOTER =
# list).
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_EXTRA_STYLESHEET =
+LATEX_EXTRA_STYLESHEET =
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the LATEX_OUTPUT output
@@ -1705,7 +1705,7 @@ LATEX_EXTRA_STYLESHEET =
# markers available.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_EXTRA_FILES =
+LATEX_EXTRA_FILES =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
@@ -1714,7 +1714,7 @@ LATEX_EXTRA_FILES =
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-PDF_HYPERLINKS = YES
+PDF_HYPERLINKS = YES
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
# the PDF file directly from the LaTeX files. Set this option to YES, to get a
@@ -1722,7 +1722,7 @@ PDF_HYPERLINKS = YES
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-USE_PDFLATEX = YES
+USE_PDFLATEX = YES
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
# command to the generated LaTeX files. This will instruct LaTeX to keep running
@@ -1731,14 +1731,14 @@ USE_PDFLATEX = YES
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_BATCHMODE = NO
+LATEX_BATCHMODE = NO
# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
# index chapters (such as File Index, Compound Index, etc.) in the output.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_HIDE_INDICES = NO
+LATEX_HIDE_INDICES = NO
# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
# code with syntax highlighting in the LaTeX output.
@@ -1748,7 +1748,7 @@ LATEX_HIDE_INDICES = NO
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_SOURCE_CODE = NO
+LATEX_SOURCE_CODE = NO
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
# bibliography, e.g. plainnat, or ieeetr. See
@@ -1756,7 +1756,7 @@ LATEX_SOURCE_CODE = NO
# The default value is: plain.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_BIB_STYLE = plain
+LATEX_BIB_STYLE = plain
# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
# page will contain the date and time when the page was generated. Setting this
@@ -1764,7 +1764,7 @@ LATEX_BIB_STYLE = plain
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_TIMESTAMP = NO
+LATEX_TIMESTAMP = NO
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
@@ -1775,7 +1775,7 @@ LATEX_TIMESTAMP = NO
# readers/editors.
# The default value is: NO.
-GENERATE_RTF = NO
+GENERATE_RTF = NO
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
@@ -1783,7 +1783,7 @@ GENERATE_RTF = NO
# The default directory is: rtf.
# This tag requires that the tag GENERATE_RTF is set to YES.
-RTF_OUTPUT = rtf
+RTF_OUTPUT = rtf
# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
# documents. This may be useful for small projects and may help to save some
@@ -1791,7 +1791,7 @@ RTF_OUTPUT = rtf
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
-COMPACT_RTF = NO
+COMPACT_RTF = NO
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
# contain hyperlink fields. The RTF file will contain links (just like the HTML
@@ -1803,7 +1803,7 @@ COMPACT_RTF = NO
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
-RTF_HYPERLINKS = NO
+RTF_HYPERLINKS = NO
# Load stylesheet definitions from file. Syntax is similar to doxygen's config
# file, i.e. a series of assignments. You only have to provide replacements,
@@ -1813,14 +1813,14 @@ RTF_HYPERLINKS = NO
# default style sheet that doxygen normally uses.
# This tag requires that the tag GENERATE_RTF is set to YES.
-RTF_STYLESHEET_FILE =
+RTF_STYLESHEET_FILE =
# Set optional variables used in the generation of an RTF document. Syntax is
# similar to doxygen's config file. A template extensions file can be generated
# using doxygen -e rtf extensionFile.
# This tag requires that the tag GENERATE_RTF is set to YES.
-RTF_EXTENSIONS_FILE =
+RTF_EXTENSIONS_FILE =
# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
# with syntax highlighting in the RTF output.
@@ -1830,7 +1830,7 @@ RTF_EXTENSIONS_FILE =
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
-RTF_SOURCE_CODE = NO
+RTF_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# Configuration options related to the man page output
@@ -1840,7 +1840,7 @@ RTF_SOURCE_CODE = NO
# classes and files.
# The default value is: NO.
-GENERATE_MAN = NO
+GENERATE_MAN = NO
# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
@@ -1849,7 +1849,7 @@ GENERATE_MAN = NO
# The default directory is: man.
# This tag requires that the tag GENERATE_MAN is set to YES.
-MAN_OUTPUT = man
+MAN_OUTPUT = man
# The MAN_EXTENSION tag determines the extension that is added to the generated
# man pages. In case the manual section does not start with a number, the number
@@ -1858,14 +1858,14 @@ MAN_OUTPUT = man
# The default value is: .3.
# This tag requires that the tag GENERATE_MAN is set to YES.
-MAN_EXTENSION = .3
+MAN_EXTENSION = .3
# The MAN_SUBDIR tag determines the name of the directory created within
# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
# MAN_EXTENSION with the initial . removed.
# This tag requires that the tag GENERATE_MAN is set to YES.
-MAN_SUBDIR =
+MAN_SUBDIR =
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
# will generate one additional man file for each entity documented in the real
@@ -1874,7 +1874,7 @@ MAN_SUBDIR =
# The default value is: NO.
# This tag requires that the tag GENERATE_MAN is set to YES.
-MAN_LINKS = NO
+MAN_LINKS = NO
#---------------------------------------------------------------------------
# Configuration options related to the XML output
@@ -1884,7 +1884,7 @@ MAN_LINKS = NO
# captures the structure of the code including all documentation.
# The default value is: NO.
-GENERATE_XML = NO
+GENERATE_XML = NO
# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
@@ -1892,7 +1892,7 @@ GENERATE_XML = NO
# The default directory is: xml.
# This tag requires that the tag GENERATE_XML is set to YES.
-XML_OUTPUT = xml
+XML_OUTPUT = xml
# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
# listings (including syntax highlighting and cross-referencing information) to
@@ -1901,7 +1901,7 @@ XML_OUTPUT = xml
# The default value is: YES.
# This tag requires that the tag GENERATE_XML is set to YES.
-XML_PROGRAMLISTING = YES
+XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
@@ -1911,7 +1911,7 @@ XML_PROGRAMLISTING = YES
# that can be used to generate PDF.
# The default value is: NO.
-GENERATE_DOCBOOK = NO
+GENERATE_DOCBOOK = NO
# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
@@ -1919,7 +1919,7 @@ GENERATE_DOCBOOK = NO
# The default directory is: docbook.
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
-DOCBOOK_OUTPUT = docbook
+DOCBOOK_OUTPUT = docbook
# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
# program listings (including syntax highlighting and cross-referencing
@@ -1940,7 +1940,7 @@ DOCBOOK_PROGRAMLISTING = NO
# still experimental and incomplete at the moment.
# The default value is: NO.
-GENERATE_AUTOGEN_DEF = NO
+GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Configuration options related to the Perl module output
@@ -1952,7 +1952,7 @@ GENERATE_AUTOGEN_DEF = NO
# Note that this feature is still experimental and incomplete at the moment.
# The default value is: NO.
-GENERATE_PERLMOD = NO
+GENERATE_PERLMOD = NO
# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
@@ -1960,7 +1960,7 @@ GENERATE_PERLMOD = NO
# The default value is: NO.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
-PERLMOD_LATEX = NO
+PERLMOD_LATEX = NO
# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
# formatted so it can be parsed by a human reader. This is useful if you want to
@@ -1970,7 +1970,7 @@ PERLMOD_LATEX = NO
# The default value is: YES.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
-PERLMOD_PRETTY = YES
+PERLMOD_PRETTY = YES
# The names of the make variables in the generated doxyrules.make file are
# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
@@ -1978,7 +1978,7 @@ PERLMOD_PRETTY = YES
# overwrite each other's variables.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
-PERLMOD_MAKEVAR_PREFIX =
+PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
@@ -1988,7 +1988,7 @@ PERLMOD_MAKEVAR_PREFIX =
# C-preprocessor directives found in the sources and include files.
# The default value is: YES.
-ENABLE_PREPROCESSING = YES
+ENABLE_PREPROCESSING = YES
# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
# in the source code. If set to NO, only conditional compilation will be
@@ -1997,7 +1997,7 @@ ENABLE_PREPROCESSING = YES
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-MACRO_EXPANSION = NO
+MACRO_EXPANSION = NO
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
# the macro expansion is limited to the macros specified with the PREDEFINED and
@@ -2005,21 +2005,21 @@ MACRO_EXPANSION = NO
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-EXPAND_ONLY_PREDEF = NO
+EXPAND_ONLY_PREDEF = NO
# If the SEARCH_INCLUDES tag is set to YES, the include files in the
# INCLUDE_PATH will be searched if a #include is found.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-SEARCH_INCLUDES = YES
+SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by the
# preprocessor.
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
-INCLUDE_PATH =
+INCLUDE_PATH =
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
@@ -2027,7 +2027,7 @@ INCLUDE_PATH =
# used.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-INCLUDE_FILE_PATTERNS =
+INCLUDE_FILE_PATTERNS =
# The PREDEFINED tag can be used to specify one or more macro names that are
# defined before the preprocessor is started (similar to the -D option of e.g.
@@ -2037,7 +2037,7 @@ INCLUDE_FILE_PATTERNS =
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-PREDEFINED =
+PREDEFINED =
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The
@@ -2046,7 +2046,7 @@ PREDEFINED =
# definition found in the source code.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-EXPAND_AS_DEFINED =
+EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
# remove all references to function-like macros that are alone on a line, have
@@ -2056,7 +2056,7 @@ EXPAND_AS_DEFINED =
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-SKIP_FUNCTION_MACROS = YES
+SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration options related to external references
@@ -2075,40 +2075,40 @@ SKIP_FUNCTION_MACROS = YES
# the path). If a tag file is not located in the directory in which doxygen is
# run, you must also specify the path to the tagfile here.
-TAGFILES =
+TAGFILES =
# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
# tag file that is based on the input files it reads. See section "Linking to
# external documentation" for more information about the usage of tag files.
-GENERATE_TAGFILE =
+GENERATE_TAGFILE =
# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
# the class index. If set to NO, only the inherited external classes will be
# listed.
# The default value is: NO.
-ALLEXTERNALS = NO
+ALLEXTERNALS = NO
# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
# in the modules index. If set to NO, only the current project's groups will be
# listed.
# The default value is: YES.
-EXTERNAL_GROUPS = YES
+EXTERNAL_GROUPS = YES
# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
# the related pages index. If set to NO, only the current project's pages will
# be listed.
# The default value is: YES.
-EXTERNAL_PAGES = YES
+EXTERNAL_PAGES = YES
# The PERL_PATH should be the absolute path and name of the perl script
# interpreter (i.e. the result of 'which perl').
# The default file (with absolute path) is: /usr/bin/perl.
-PERL_PATH = /usr/bin/perl
+PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
@@ -2121,7 +2121,7 @@ PERL_PATH = /usr/bin/perl
# powerful graphs.
# The default value is: YES.
-CLASS_DIAGRAMS = YES
+CLASS_DIAGRAMS = NO
# You can define message sequence charts within doxygen comments using the \msc
# command. Doxygen will then run the mscgen tool (see:
@@ -2130,20 +2130,20 @@ CLASS_DIAGRAMS = YES
# the mscgen tool resides. If left empty the tool is assumed to be found in the
# default search path.
-MSCGEN_PATH =
+MSCGEN_PATH =
# You can include diagrams made with dia in doxygen documentation. Doxygen will
# then run dia to produce the diagram and insert it in the documentation. The
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
# If left empty dia is assumed to be found in the default search path.
-DIA_PATH =
+DIA_PATH =
# If set to YES the inheritance and collaboration graphs will hide inheritance
# and usage relations if the target is undocumented or is not a class.
# The default value is: YES.
-HIDE_UNDOC_RELATIONS = YES
+HIDE_UNDOC_RELATIONS = YES
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz (see:
@@ -2152,7 +2152,7 @@ HIDE_UNDOC_RELATIONS = YES
# set to NO
# The default value is: YES.
-HAVE_DOT = YES
+HAVE_DOT = YES
# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
# to run in parallel. When set to 0 doxygen will base this on the number of
@@ -2162,7 +2162,7 @@ HAVE_DOT = YES
# Minimum value: 0, maximum value: 32, default value: 0.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_NUM_THREADS = 0
+DOT_NUM_THREADS = 0
# When you want a differently looking font in the dot files that doxygen
# generates you can specify the font name using DOT_FONTNAME. You need to make
@@ -2172,21 +2172,21 @@ DOT_NUM_THREADS = 0
# The default value is: Helvetica.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_FONTNAME = Helvetica
+DOT_FONTNAME = Helvetica
# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
# dot graphs.
# Minimum value: 4, maximum value: 24, default value: 10.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_FONTSIZE = 10
+DOT_FONTSIZE = 10
# By default doxygen will tell dot to use the default font as specified with
# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
# the path where dot can find it using this tag.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_FONTPATH =
+DOT_FONTPATH =
# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
# each documented class showing the direct and indirect inheritance relations.
@@ -2194,7 +2194,7 @@ DOT_FONTPATH =
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
-CLASS_GRAPH = YES
+CLASS_GRAPH = YES
# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
# graph for each documented class showing the direct and indirect implementation
@@ -2203,14 +2203,14 @@ CLASS_GRAPH = YES
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
-COLLABORATION_GRAPH = YES
+COLLABORATION_GRAPH = YES
# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
# groups, showing the direct groups dependencies.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
-GROUP_GRAPHS = YES
+GROUP_GRAPHS = YES
# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling
@@ -2218,7 +2218,7 @@ GROUP_GRAPHS = YES
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
-UML_LOOK = NO
+UML_LOOK = NO
# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
# class node. If there are many fields or methods and many nodes the graph may
@@ -2231,7 +2231,7 @@ UML_LOOK = NO
# Minimum value: 0, maximum value: 100, default value: 10.
# This tag requires that the tag HAVE_DOT is set to YES.
-UML_LIMIT_NUM_FIELDS = 10
+UML_LIMIT_NUM_FIELDS = 10
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
# collaboration graphs will show the relations between templates and their
@@ -2239,7 +2239,7 @@ UML_LIMIT_NUM_FIELDS = 10
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
-TEMPLATE_RELATIONS = NO
+TEMPLATE_RELATIONS = NO
# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
# YES then doxygen will generate a graph for each documented file showing the
@@ -2248,7 +2248,7 @@ TEMPLATE_RELATIONS = NO
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
-INCLUDE_GRAPH = YES
+INCLUDE_GRAPH = YES
# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
# set to YES then doxygen will generate a graph for each documented file showing
@@ -2257,7 +2257,7 @@ INCLUDE_GRAPH = YES
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
-INCLUDED_BY_GRAPH = YES
+INCLUDED_BY_GRAPH = YES
# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
# dependency graph for every global function or class method.
@@ -2269,7 +2269,7 @@ INCLUDED_BY_GRAPH = YES
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
-CALL_GRAPH = NO
+CALL_GRAPH = NO
# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
# dependency graph for every global function or class method.
@@ -2281,14 +2281,14 @@ CALL_GRAPH = NO
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
-CALLER_GRAPH = NO
+CALLER_GRAPH = NO
# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
# hierarchy of all classes instead of a textual one.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
-GRAPHICAL_HIERARCHY = YES
+GRAPHICAL_HIERARCHY = YES
# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
# dependencies a directory has on other directories in a graphical way. The
@@ -2297,7 +2297,7 @@ GRAPHICAL_HIERARCHY = YES
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
-DIRECTORY_GRAPH = YES
+DIRECTORY_GRAPH = YES
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot. For an explanation of the image formats see the section
@@ -2314,7 +2314,7 @@ DIRECTORY_GRAPH = YES
# The default value is: png.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_IMAGE_FORMAT = png
+DOT_IMAGE_FORMAT = png
# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
# enable generation of interactive SVG images that allow zooming and panning.
@@ -2326,32 +2326,32 @@ DOT_IMAGE_FORMAT = png
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
-INTERACTIVE_SVG = NO
+INTERACTIVE_SVG = NO
# The DOT_PATH tag can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_PATH =
+DOT_PATH =
# The DOTFILE_DIRS tag can be used to specify one or more directories that
# contain dot files that are included in the documentation (see the \dotfile
# command).
# This tag requires that the tag HAVE_DOT is set to YES.
-DOTFILE_DIRS =
+DOTFILE_DIRS =
# The MSCFILE_DIRS tag can be used to specify one or more directories that
# contain msc files that are included in the documentation (see the \mscfile
# command).
-MSCFILE_DIRS =
+MSCFILE_DIRS =
# The DIAFILE_DIRS tag can be used to specify one or more directories that
# contain dia files that are included in the documentation (see the \diafile
# command).
-DIAFILE_DIRS =
+DIAFILE_DIRS =
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
# path where java can find the plantuml.jar file. If left blank, it is assumed
@@ -2359,12 +2359,12 @@ DIAFILE_DIRS =
# generate a warning when it encounters a \startuml command in this case and
# will not generate output for the diagram.
-PLANTUML_JAR_PATH =
+PLANTUML_JAR_PATH =
# When using plantuml, the specified paths are searched for files specified by
# the !include statement in a plantuml block.
-PLANTUML_INCLUDE_PATH =
+PLANTUML_INCLUDE_PATH =
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
# that will be shown in the graph. If the number of nodes in a graph becomes
@@ -2376,7 +2376,7 @@ PLANTUML_INCLUDE_PATH =
# Minimum value: 0, maximum value: 10000, default value: 50.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_GRAPH_MAX_NODES = 50
+DOT_GRAPH_MAX_NODES = 50
# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
# generated by dot. A depth value of 3 means that only nodes reachable from the
@@ -2388,7 +2388,7 @@ DOT_GRAPH_MAX_NODES = 50
# Minimum value: 0, maximum value: 1000, default value: 0.
# This tag requires that the tag HAVE_DOT is set to YES.
-MAX_DOT_GRAPH_DEPTH = 0
+MAX_DOT_GRAPH_DEPTH = 0
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
# background. This is disabled by default, because dot on Windows does not seem
@@ -2400,7 +2400,7 @@ MAX_DOT_GRAPH_DEPTH = 0
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_TRANSPARENT = NO
+DOT_TRANSPARENT = NO
# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
@@ -2409,7 +2409,7 @@ DOT_TRANSPARENT = NO
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_MULTI_TARGETS = NO
+DOT_MULTI_TARGETS = NO
# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
# explaining the meaning of the various boxes and arrows in the dot generated
@@ -2417,11 +2417,11 @@ DOT_MULTI_TARGETS = NO
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
-GENERATE_LEGEND = YES
+GENERATE_LEGEND = YES
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
# files that are used to generate the various graphs.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_CLEANUP = YES
+DOT_CLEANUP = YES
diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile
index 7ee5a204629..fa983cb1d6c 100644
--- a/src/lib/netlist/build/makefile
+++ b/src/lib/netlist/build/makefile
@@ -50,6 +50,7 @@ POBJS := \
$(POBJ)/pchrono.o \
$(POBJ)/pdynlib.o \
$(POBJ)/pexception.o \
+ $(POBJ)/pfunction.o \
$(POBJ)/pfmtlog.o \
$(POBJ)/poptions.o \
$(POBJ)/pparser.o \
@@ -63,9 +64,9 @@ NLOBJS := \
$(NLOBJ)/nl_setup.o \
$(NLOBJ)/nl_factory.o \
$(NLOBJ)/analog/nld_bjt.o \
- $(NLOBJ)/analog/nld_fourterm.o \
+ $(NLOBJ)/analog/nlid_fourterm.o \
$(NLOBJ)/analog/nld_switches.o \
- $(NLOBJ)/analog/nld_twoterm.o \
+ $(NLOBJ)/analog/nlid_twoterm.o \
$(NLOBJ)/analog/nld_opamps.o \
$(NLOBJ)/devices/nld_2102A.o \
$(NLOBJ)/devices/nld_2716.o \
@@ -114,7 +115,7 @@ NLOBJS := \
$(NLOBJ)/devices/nld_log.o \
$(NLOBJ)/devices/nlid_proxy.o \
$(NLOBJ)/devices/nld_system.o \
- $(NLOBJ)/devices/nld_truthtable.o \
+ $(NLOBJ)/devices/nlid_truthtable.o \
$(NLOBJ)/macro/nlm_base.o \
$(NLOBJ)/macro/nlm_cd4xxx.o \
$(NLOBJ)/macro/nlm_opamp.o \
@@ -169,7 +170,7 @@ maketree: $(sort $(OBJDIRS))
.PHONY: clang mingw doc
clang:
- $(MAKE) CC=clang++ LD=clang++ CEXTRAFLAGS="-march=native -Weverything -Werror -Wno-padded -Wno-weak-vtables -Wno-missing-variable-declarations -Wconversion -Wno-c++98-compat -Wno-float-equal -Wno-global-constructors -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-weak-template-vtables -Wno-exit-time-destructors"
+ $(MAKE) CC=clang++-5.0 LD=clang++-5.0 CEXTRAFLAGS="-march=native -Weverything -Werror -Wno-padded -Wno-weak-vtables -Wno-missing-variable-declarations -Wconversion -Wno-c++98-compat -Wno-float-equal -Wno-global-constructors -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-weak-template-vtables -Wno-exit-time-destructors"
#
# Mostly done: -Wno-weak-vtables -Wno-cast-align
diff --git a/src/lib/netlist/devices/net_lib.cpp b/src/lib/netlist/devices/net_lib.cpp
index 502f044ec76..bc1d7051b39 100644
--- a/src/lib/netlist/devices/net_lib.cpp
+++ b/src/lib/netlist/devices/net_lib.cpp
@@ -9,60 +9,62 @@
****************************************************************************/
#include "net_lib.h"
-#include "nld_system.h"
#include "nl_factory.h"
#include "solver/nld_solver.h"
+
#define xstr(s) # s
+
+#if 0
#define ENTRY1(nic, name, defparam) factory.register_device<nic>( # name, xstr(nic), defparam );
#define ENTRY(nic, name, defparam) ENTRY1(NETLIB_NAME(nic), name, defparam)
+#endif
#define NETLIB_DEVICE_DECL(chip) extern factory::constructor_ptr_t decl_ ## chip;
-#define ENTRYX1(nic, name, defparam, decl) factory.register_device( decl (# name, xstr(nic), defparam) );
+//#define ENTRYX1(nic, name, defparam, decl) factory.register_device( decl (# name, xstr(nic), defparam) );
+#define ENTRYX1(nic, name, defparam, decl) factory.register_device( decl (pstring(# name), pstring(xstr(nic)), pstring(defparam)) );
#define ENTRYX(nic, name, defparam) { NETLIB_DEVICE_DECL(nic) ENTRYX1(NETLIB_NAME(nic), name, defparam, decl_ ## nic) }
namespace netlist
{
- using namespace netlist::analog;
-
namespace devices
{
-static void initialize_factory(factory::list_t &factory)
+ void initialize_factory(factory::list_t &factory)
{
- ENTRY(R, RES, "R")
- ENTRY(POT, POT, "R")
- ENTRY(POT2, POT2, "R")
- ENTRY(C, CAP, "C")
- ENTRY(L, IND, "L")
- ENTRY(D, DIODE, "MODEL")
- ENTRY(VCVS, VCVS, "")
- ENTRY(VCCS, VCCS, "")
- ENTRY(CCCS, CCCS, "")
- ENTRY(LVCCS, LVCCS, "")
- ENTRY(VS, VS, "V")
- ENTRY(CS, CS, "I")
- ENTRYX(opamp, OPAMP, "MODEL")
+ ENTRYX(R, RES, "R")
+ ENTRYX(POT, POT, "R")
+ ENTRYX(POT2, POT2, "R")
+ ENTRYX(C, CAP, "C")
+ ENTRYX(L, IND, "L")
+ ENTRYX(D, DIODE, "MODEL")
+ ENTRYX(VS, VS, "V")
+ ENTRYX(CS, CS, "I")
+ ENTRYX(VCVS, VCVS, "")
+ ENTRYX(VCCS, VCCS, "")
+ ENTRYX(CCCS, CCCS, "")
+ ENTRYX(LVCCS, LVCCS, "")
+ ENTRYX(opamp, OPAMP, "MODEL")
ENTRYX(dummy_input, DUMMY_INPUT, "")
ENTRYX(frontier, FRONTIER_DEV, "+I,+G,+Q") // not intended to be used directly
ENTRYX(function, AFUNC, "N,FUNC") // only for macro devices - NO FEEDBACK loops
- ENTRY(QBJT_EB, QBJT_EB, "MODEL")
- ENTRY(QBJT_switch, QBJT_SW, "MODEL")
+ ENTRYX(QBJT_EB, QBJT_EB, "MODEL")
+ ENTRYX(QBJT_switch, QBJT_SW, "MODEL")
ENTRYX(logic_input, TTL_INPUT, "IN")
ENTRYX(logic_input, LOGIC_INPUT, "IN,FAMILY")
ENTRYX(analog_input, ANALOG_INPUT, "IN")
ENTRYX(log, LOG, "+I")
ENTRYX(logD, LOGD, "+I,+I2")
ENTRYX(clock, CLOCK, "FREQ")
- ENTRYX(extclock, EXTCLOCK, "FREQ")
+ ENTRYX(extclock, EXTCLOCK, "FREQ,PATTERN")
ENTRYX(mainclock, MAINCLOCK, "FREQ")
ENTRYX(gnd, GND, "")
ENTRYX(netlistparams, PARAMETER, "")
- ENTRY(solver, SOLVER, "FREQ")
+ ENTRYX(solver, SOLVER, "FREQ")
ENTRYX(res_sw, RES_SWITCH, "+IN,+P1,+P2")
ENTRYX(switch1, SWITCH, "")
ENTRYX(switch2, SWITCH2, "")
- ENTRYX(nicRSFF, NETDEV_RSFF, "+S,+R")
+ ENTRYX(nicRSFF, NETDEV_RSFF, "")
ENTRYX(nicDelay, NETDEV_DELAY, "")
ENTRYX(2716, EPROM_2716, "+GQ,+EPQ,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,+A8,+A9,+A10")
ENTRYX(2102A, RAM_2102A, "+CEQ,+A0,+A1,+A2,+A3,+A4,+A5,+A6,+A7,+A8,+A9,+RWQ,+DI")
@@ -158,10 +160,3 @@ static void initialize_factory(factory::list_t &factory)
} //namespace devices
} // namespace netlist
-namespace netlist
-{
- void initialize_factory(factory::list_t &factory)
- {
- devices::initialize_factory(factory);
- }
-}
diff --git a/src/lib/netlist/devices/net_lib.h b/src/lib/netlist/devices/net_lib.h
index 9bbd9db744a..9ac05f9bccb 100644
--- a/src/lib/netlist/devices/net_lib.h
+++ b/src/lib/netlist/devices/net_lib.h
@@ -11,7 +11,28 @@
#ifndef NET_LIB_H
#define NET_LIB_H
-#include "nl_base.h"
+#include "nl_setup.h"
+
+//#define NL_AUTO_DEVICES 1
+
+#ifdef NL_AUTO_DEVICES
+#include "nld_devinc.h"
+
+#include "solver/nld_solver.h"
+
+#include "macro/nlm_cd4xxx.h"
+#include "macro/nlm_ttl74xx.h"
+#include "macro/nlm_opamp.h"
+#include "macro/nlm_other.h"
+
+#include "nld_7448.h"
+
+#else
+
+#define SOLVER(name, freq) \
+ NET_REGISTER_DEV(SOLVER, name) \
+ PARAM(name.FREQ, freq)
+
#include "nld_system.h"
#include "nld_2102A.h"
@@ -72,12 +93,8 @@
#include "analog/nld_switches.h"
#include "analog/nld_twoterm.h"
#include "analog/nld_opamps.h"
-#include "solver/nld_solver.h"
#include "nld_legacy.h"
-
-namespace netlist {
- void initialize_factory(factory::list_t &factory);
-}
+#endif
#endif
diff --git a/src/lib/netlist/devices/nld_2102A.cpp b/src/lib/netlist/devices/nld_2102A.cpp
index 8dbd5be8fec..803f5b523c9 100644
--- a/src/lib/netlist/devices/nld_2102A.cpp
+++ b/src/lib/netlist/devices/nld_2102A.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_2102A.h"
+#include "nl_base.h"
#define ADDR2BYTE(a) ((a) >> 3)
#define ADDR2BIT(a) ((a) & 0x7)
diff --git a/src/lib/netlist/devices/nld_2716.cpp b/src/lib/netlist/devices/nld_2716.cpp
index 7ba974b92da..aa491c47d3c 100644
--- a/src/lib/netlist/devices/nld_2716.cpp
+++ b/src/lib/netlist/devices/nld_2716.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_2716.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_4020.cpp b/src/lib/netlist/devices/nld_4020.cpp
index a147cf3f58f..14459fb3b62 100644
--- a/src/lib/netlist/devices/nld_4020.cpp
+++ b/src/lib/netlist/devices/nld_4020.cpp
@@ -5,7 +5,7 @@
*
*/
-#include <devices/nlid_cmos.h>
+#include "devices/nlid_cmos.h"
#include "nld_4020.h"
namespace netlist
diff --git a/src/lib/netlist/devices/nld_4066.cpp b/src/lib/netlist/devices/nld_4066.cpp
index f33688b73b7..11dca7b11dd 100644
--- a/src/lib/netlist/devices/nld_4066.cpp
+++ b/src/lib/netlist/devices/nld_4066.cpp
@@ -5,8 +5,8 @@
*
*/
-#include <devices/nlid_cmos.h>
-#include "analog/nld_twoterm.h"
+#include "devices/nlid_cmos.h"
+#include "analog/nlid_twoterm.h"
#include "nld_4066.h"
namespace netlist
diff --git a/src/lib/netlist/devices/nld_4316.cpp b/src/lib/netlist/devices/nld_4316.cpp
index 8b9cb0d46ad..5c86f885545 100644
--- a/src/lib/netlist/devices/nld_4316.cpp
+++ b/src/lib/netlist/devices/nld_4316.cpp
@@ -5,8 +5,8 @@
*
*/
-#include <devices/nlid_cmos.h>
-#include "analog/nld_twoterm.h"
+#include "devices/nlid_cmos.h"
+#include "analog/nlid_twoterm.h"
#include "nld_4316.h"
namespace netlist { namespace devices {
diff --git a/src/lib/netlist/devices/nld_74107.cpp b/src/lib/netlist/devices/nld_74107.cpp
index a9006d55a75..3a3c43ac0fa 100644
--- a/src/lib/netlist/devices/nld_74107.cpp
+++ b/src/lib/netlist/devices/nld_74107.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_74107.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_74123.cpp b/src/lib/netlist/devices/nld_74123.cpp
index bcbfdcb106a..514ea4e9390 100644
--- a/src/lib/netlist/devices/nld_74123.cpp
+++ b/src/lib/netlist/devices/nld_74123.cpp
@@ -5,10 +5,10 @@
*
*/
-#include "nld_74123.h"
-
#include "nlid_system.h"
-#include "analog/nld_twoterm.h"
+#include "analog/nlid_twoterm.h"
+
+#include <cmath>
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_74153.cpp b/src/lib/netlist/devices/nld_74153.cpp
index fb97411e350..efa6322e514 100644
--- a/src/lib/netlist/devices/nld_74153.cpp
+++ b/src/lib/netlist/devices/nld_74153.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_74153.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_74161.cpp b/src/lib/netlist/devices/nld_74161.cpp
index d6e31f36417..4579fa41b7a 100644
--- a/src/lib/netlist/devices/nld_74161.cpp
+++ b/src/lib/netlist/devices/nld_74161.cpp
@@ -8,6 +8,7 @@
#define MAXCNT 15
#include "nld_74161.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_74165.cpp b/src/lib/netlist/devices/nld_74165.cpp
index bb263409bf9..c967f95d44c 100644
--- a/src/lib/netlist/devices/nld_74165.cpp
+++ b/src/lib/netlist/devices/nld_74165.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_74165.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_74166.cpp b/src/lib/netlist/devices/nld_74166.cpp
index 5cb7114ee0f..d56159183b0 100644
--- a/src/lib/netlist/devices/nld_74166.cpp
+++ b/src/lib/netlist/devices/nld_74166.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_74166.h"
+#include "nl_base.h"
namespace netlist
{
@@ -82,7 +83,7 @@ namespace netlist
netlist_time delay = NLTIME_FROM_NS(26);
if (m_CLRQ())
{
- bool clear_unset = !m_last_CLRQ();
+ bool clear_unset = !m_last_CLRQ;
if (clear_unset)
{
delay = NLTIME_FROM_NS(35);
diff --git a/src/lib/netlist/devices/nld_74174.cpp b/src/lib/netlist/devices/nld_74174.cpp
index 64698423435..d131b18af23 100644
--- a/src/lib/netlist/devices/nld_74174.cpp
+++ b/src/lib/netlist/devices/nld_74174.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_74174.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_74175.cpp b/src/lib/netlist/devices/nld_74175.cpp
index 4d8e3608ee8..3055a73f2c9 100644
--- a/src/lib/netlist/devices/nld_74175.cpp
+++ b/src/lib/netlist/devices/nld_74175.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_74175.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_74192.cpp b/src/lib/netlist/devices/nld_74192.cpp
index 80e1853b7f7..77029cfdf50 100644
--- a/src/lib/netlist/devices/nld_74192.cpp
+++ b/src/lib/netlist/devices/nld_74192.cpp
@@ -8,6 +8,7 @@
#define MAXCNT 9
#include "nld_74192.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_74193.cpp b/src/lib/netlist/devices/nld_74193.cpp
index 3d32596dbee..f5370719778 100644
--- a/src/lib/netlist/devices/nld_74193.cpp
+++ b/src/lib/netlist/devices/nld_74193.cpp
@@ -8,6 +8,7 @@
#define MAXCNT 15
#include "nld_74193.h"
+#include "nl_base.h"
namespace netlist
{
@@ -136,8 +137,8 @@ namespace netlist
for (std::size_t i=0; i<4; i++)
m_Q[i].push((m_cnt >> i) & 1, delay[i]);
- m_BORROWQ.push(tBorrow, NLTIME_FROM_NS(20)); //FIXME
- m_CARRYQ.push(tCarry, NLTIME_FROM_NS(20)); //FIXME
+ m_BORROWQ.push(tBorrow, NLTIME_FROM_NS(20)); //FIXME timing
+ m_CARRYQ.push(tCarry, NLTIME_FROM_NS(20)); //FIXME timing
}
NETLIB_DEVICE_IMPL(74193)
diff --git a/src/lib/netlist/devices/nld_74194.cpp b/src/lib/netlist/devices/nld_74194.cpp
index e951e351e93..4fe5092f4d5 100644
--- a/src/lib/netlist/devices/nld_74194.cpp
+++ b/src/lib/netlist/devices/nld_74194.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_74194.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_74194.h b/src/lib/netlist/devices/nld_74194.h
index 944d9537754..8d07b685e55 100644
--- a/src/lib/netlist/devices/nld_74194.h
+++ b/src/lib/netlist/devices/nld_74194.h
@@ -28,17 +28,17 @@
#include "nl_setup.h"
-#define TTL_74194(name, cCLK, cS0, cS1, cSRIN, cA, cB, cC, cD, cSLIN, cCLRQ) \
- NET_REGISTER_DEV(TTL_74194, name) \
- NET_CONNECT(name, CLK, cCLK) \
- NET_CONNECT(name, S0, cS0) \
- NET_CONNECT(name, S1, cS1) \
- NET_CONNECT(name, SRIN, cSRIN) \
- NET_CONNECT(name, A, cA) \
- NET_CONNECT(name, B, cB) \
- NET_CONNECT(name, C, cC) \
- NET_CONNECT(name, D, cD) \
- NET_CONNECT(name, SLIN, cSLIN) \
+#define TTL_74194(name, cCLK, cS0, cS1, cSRIN, cA, cB, cC, cD, cSLIN, cCLRQ) \
+ NET_REGISTER_DEV(TTL_74194, name) \
+ NET_CONNECT(name, CLK, cCLK) \
+ NET_CONNECT(name, S0, cS0) \
+ NET_CONNECT(name, S1, cS1) \
+ NET_CONNECT(name, SRIN, cSRIN) \
+ NET_CONNECT(name, A, cA) \
+ NET_CONNECT(name, B, cB) \
+ NET_CONNECT(name, C, cC) \
+ NET_CONNECT(name, D, cD) \
+ NET_CONNECT(name, SLIN, cSLIN) \
NET_CONNECT(name, CLRQ, cCLRQ)
#define TTL_74194_DIP(name) \
diff --git a/src/lib/netlist/devices/nld_74279.cpp b/src/lib/netlist/devices/nld_74279.cpp
index 48c2e7e095b..ff8f12e07ea 100644
--- a/src/lib/netlist/devices/nld_74279.cpp
+++ b/src/lib/netlist/devices/nld_74279.cpp
@@ -5,8 +5,9 @@
*
*/
+#include "nlid_truthtable.h"
#include "nld_74279.h"
-#include "nld_truthtable.h"
+#include "nl_base.h"
namespace netlist
{
@@ -56,7 +57,7 @@ namespace netlist
nld_74279A::truthtable_t nld_74279A::m_ttbl;
nld_74279B::truthtable_t nld_74279B::m_ttbl;
- const char *nld_74279A::m_desc[] = {
+ const pstring nld_74279A::m_desc[] = {
"S,R,_Q|Q",
"0,X,X|1|22",
"1,0,X|0|27",
@@ -66,7 +67,7 @@ namespace netlist
};
- const char *nld_74279B::m_desc[] = {
+ const pstring nld_74279B::m_desc[] = {
"S1,S2,R,_Q|Q",
"0,X,X,X|1|22",
"X,0,X,X|1|22",
diff --git a/src/lib/netlist/devices/nld_74365.cpp b/src/lib/netlist/devices/nld_74365.cpp
index 34eafb0856e..f008b721344 100644
--- a/src/lib/netlist/devices/nld_74365.cpp
+++ b/src/lib/netlist/devices/nld_74365.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_74365.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_7448.cpp b/src/lib/netlist/devices/nld_7448.cpp
index 8b4d11c374b..a4b358c3da5 100644
--- a/src/lib/netlist/devices/nld_7448.cpp
+++ b/src/lib/netlist/devices/nld_7448.cpp
@@ -5,8 +5,8 @@
*
*/
+#include "nlid_truthtable.h"
#include "nld_7448.h"
-#include "nld_truthtable.h"
namespace netlist
{
@@ -14,7 +14,7 @@ namespace netlist
{
#if (USE_TRUTHTABLE_7448 && USE_TRUTHTABLE)
- NETLIB_TRUTHTABLE(7448, 7, 7, 0);
+ NETLIB_TRUTHTABLE(7448, 7, 7);
#else
@@ -80,7 +80,7 @@ namespace netlist
#if (USE_TRUTHTABLE_7448 && USE_TRUTHTABLE)
nld_7448::truthtable_t nld_7448::m_ttbl;
- const char *nld_7448::m_desc[] = {
+ const pstring nld_7448::m_desc[] = {
" LTQ,BIQ,RBIQ, A , B , C , D | a, b, c, d, e, f, g",
" 1, 1, 1, 0, 0, 0, 0 | 1, 1, 1, 1, 1, 1, 0|100,100,100,100,100,100,100",
diff --git a/src/lib/netlist/devices/nld_7448.h b/src/lib/netlist/devices/nld_7448.h
index 199b46343a8..24cdcb8f6f1 100644
--- a/src/lib/netlist/devices/nld_7448.h
+++ b/src/lib/netlist/devices/nld_7448.h
@@ -24,7 +24,7 @@
#ifndef NLD_7448_H_
#define NLD_7448_H_
-#include "nl_base.h"
+#include "nl_setup.h"
/*
* FIXME: Using truthtable is a lot slower than the explicit device
@@ -34,6 +34,8 @@
#define USE_TRUTHTABLE_7448 (0)
+#ifndef NL_AUTO_DEVICES
+
#define TTL_7448(name, cA0, cA1, cA2, cA3, cLTQ, cBIQ, cRBIQ) \
NET_REGISTER_DEV(TTL_7448, name) \
NET_CONNECT(name, A, cA0) \
@@ -47,4 +49,6 @@
#define TTL_7448_DIP(name) \
NET_REGISTER_DEV(TTL_7448_DIP, name)
+#endif
+
#endif /* NLD_7448_H_ */
diff --git a/src/lib/netlist/devices/nld_7450.cpp b/src/lib/netlist/devices/nld_7450.cpp
index 007f899a5f9..2ad560b1d07 100644
--- a/src/lib/netlist/devices/nld_7450.cpp
+++ b/src/lib/netlist/devices/nld_7450.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_7450.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_7473.cpp b/src/lib/netlist/devices/nld_7473.cpp
index fc73b97c201..3c88b0f8167 100644
--- a/src/lib/netlist/devices/nld_7473.cpp
+++ b/src/lib/netlist/devices/nld_7473.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_7473.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_7474.cpp b/src/lib/netlist/devices/nld_7474.cpp
index f11ccbd2164..627d3a9b48a 100644
--- a/src/lib/netlist/devices/nld_7474.cpp
+++ b/src/lib/netlist/devices/nld_7474.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_7474.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_7475.cpp b/src/lib/netlist/devices/nld_7475.cpp
index 3c26c1ce439..7bf3f14d7f2 100644
--- a/src/lib/netlist/devices/nld_7475.cpp
+++ b/src/lib/netlist/devices/nld_7475.cpp
@@ -7,6 +7,7 @@
*/
#include "nld_7475.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_7483.cpp b/src/lib/netlist/devices/nld_7483.cpp
index a11f36c1540..518026e7fe5 100644
--- a/src/lib/netlist/devices/nld_7483.cpp
+++ b/src/lib/netlist/devices/nld_7483.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_7483.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_7485.cpp b/src/lib/netlist/devices/nld_7485.cpp
index b4237a6426d..4526b9001ea 100644
--- a/src/lib/netlist/devices/nld_7485.cpp
+++ b/src/lib/netlist/devices/nld_7485.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_7485.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_7490.cpp b/src/lib/netlist/devices/nld_7490.cpp
index e395c64120e..a85ccbcfbcb 100644
--- a/src/lib/netlist/devices/nld_7490.cpp
+++ b/src/lib/netlist/devices/nld_7490.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_7490.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_7493.cpp b/src/lib/netlist/devices/nld_7493.cpp
index 557d7fa42b6..df6ab4ad668 100644
--- a/src/lib/netlist/devices/nld_7493.cpp
+++ b/src/lib/netlist/devices/nld_7493.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_7493.h"
-#include "nl_setup.h"
+#include "nl_base.h"
namespace netlist
{
@@ -29,8 +29,8 @@ namespace netlist
logic_input_t m_I;
logic_output_t m_Q;
- state_var_u8 m_reset;
- state_var_u8 m_state;
+ state_var<netlist_sig_t> m_reset;
+ state_var<netlist_sig_t> m_state;
};
NETLIB_OBJECT(7493)
@@ -99,7 +99,7 @@ namespace netlist
NETLIB_UPDATE(7493ff)
{
- constexpr netlist_time out_delay = NLTIME_FROM_NS(18);
+ static constexpr netlist_time out_delay = NLTIME_FROM_NS(18);
if (m_reset)
{
m_state ^= 1;
diff --git a/src/lib/netlist/devices/nld_74ls629.cpp b/src/lib/netlist/devices/nld_74ls629.cpp
index 07eee6f5a57..26a5aaf2220 100644
--- a/src/lib/netlist/devices/nld_74ls629.cpp
+++ b/src/lib/netlist/devices/nld_74ls629.cpp
@@ -40,7 +40,7 @@
#include "nld_74ls629.h"
-#include "analog/nld_twoterm.h"
+#include "analog/nlid_twoterm.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_82S115.cpp b/src/lib/netlist/devices/nld_82S115.cpp
index c01d013aec5..855e22c0f87 100644
--- a/src/lib/netlist/devices/nld_82S115.cpp
+++ b/src/lib/netlist/devices/nld_82S115.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_82S115.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_82S115.h b/src/lib/netlist/devices/nld_82S115.h
index 0c900e4dad7..1ceb22dc1b1 100644
--- a/src/lib/netlist/devices/nld_82S115.h
+++ b/src/lib/netlist/devices/nld_82S115.h
@@ -30,19 +30,19 @@
#include "nl_setup.h"
-#define PROM_82S115(name, cCE1Q, cCE2, cA0, cA1, cA2, cA3, cA4, cA5, cA6, cA7, cA8, cSTROBE) \
- NET_REGISTER_DEV(PROM_82S115, name) \
- NET_CONNECT(name, CE1Q, cCE1Q) \
- NET_CONNECT(name, CE2, cCE2) \
- NET_CONNECT(name, A0, cA0) \
- NET_CONNECT(name, A1, cA1) \
- NET_CONNECT(name, A2, cA2) \
- NET_CONNECT(name, A3, cA3) \
- NET_CONNECT(name, A4, cA4) \
- NET_CONNECT(name, A5, cA5) \
- NET_CONNECT(name, A6, cA6) \
- NET_CONNECT(name, A7, cA7) \
- NET_CONNECT(name, A8, cA8) \
+#define PROM_82S115(name, cCE1Q, cCE2, cA0, cA1, cA2, cA3, cA4, cA5, cA6, cA7, cA8, cSTROBE) \
+ NET_REGISTER_DEV(PROM_82S115, name) \
+ NET_CONNECT(name, CE1Q, cCE1Q) \
+ NET_CONNECT(name, CE2, cCE2) \
+ NET_CONNECT(name, A0, cA0) \
+ NET_CONNECT(name, A1, cA1) \
+ NET_CONNECT(name, A2, cA2) \
+ NET_CONNECT(name, A3, cA3) \
+ NET_CONNECT(name, A4, cA4) \
+ NET_CONNECT(name, A5, cA5) \
+ NET_CONNECT(name, A6, cA6) \
+ NET_CONNECT(name, A7, cA7) \
+ NET_CONNECT(name, A8, cA8) \
NET_CONNECT(name, STROBE, cSTROBE)
#define PROM_82S115_DIP(name) \
diff --git a/src/lib/netlist/devices/nld_82S123.cpp b/src/lib/netlist/devices/nld_82S123.cpp
index f9e97174d4a..2152bd738eb 100644
--- a/src/lib/netlist/devices/nld_82S123.cpp
+++ b/src/lib/netlist/devices/nld_82S123.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_82S123.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_82S126.cpp b/src/lib/netlist/devices/nld_82S126.cpp
index d3a86ce84ee..221b7425c8d 100644
--- a/src/lib/netlist/devices/nld_82S126.cpp
+++ b/src/lib/netlist/devices/nld_82S126.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_82S126.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_82S16.cpp b/src/lib/netlist/devices/nld_82S16.cpp
index fccdc8b1044..a2a199a61d5 100644
--- a/src/lib/netlist/devices/nld_82S16.cpp
+++ b/src/lib/netlist/devices/nld_82S16.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_82S16.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_9310.cpp b/src/lib/netlist/devices/nld_9310.cpp
index 4ddb62af519..dd448c4282b 100644
--- a/src/lib/netlist/devices/nld_9310.cpp
+++ b/src/lib/netlist/devices/nld_9310.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_9310.h"
+#include "nl_base.h"
#define MAXCNT 9
@@ -158,21 +159,22 @@ namespace netlist
{
if (m_loadq)
{
- switch (m_cnt())
+ if (m_cnt < MAXCNT - 1)
{
- case MAXCNT - 1:
- m_cnt = MAXCNT;
- m_RC.push(m_ent, NLTIME_FROM_NS(20));
- m_QA.push(1, NLTIME_FROM_NS(20));
- break;
- case MAXCNT:
- m_RC.push(0, NLTIME_FROM_NS(20));
- m_cnt = 0;
- update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
- break;
- default:
- m_cnt++;
- update_outputs(m_cnt);
+ m_cnt++;
+ update_outputs(m_cnt);
+ }
+ else if (m_cnt == MAXCNT - 1)
+ {
+ m_cnt = MAXCNT;
+ m_RC.push(m_ent, NLTIME_FROM_NS(20));
+ m_QA.push(1, NLTIME_FROM_NS(20));
+ }
+ else // MAXCNT
+ {
+ m_RC.push(0, NLTIME_FROM_NS(20));
+ m_cnt = 0;
+ update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
}
}
else
diff --git a/src/lib/netlist/devices/nld_9312.cpp b/src/lib/netlist/devices/nld_9312.cpp
index 2ad298f368a..b3fe0545f81 100644
--- a/src/lib/netlist/devices/nld_9312.cpp
+++ b/src/lib/netlist/devices/nld_9312.cpp
@@ -20,8 +20,8 @@
* | 1 | 1 | 1 | 0 || D7|D7Q|
* +---+---+---+---++---+---+
*/
+#include "nlid_truthtable.h"
#include "nld_9312.h"
-#include "nld_truthtable.h"
namespace netlist
{
@@ -130,7 +130,7 @@ namespace netlist
* do this right now.
*/
- const char *nld_9312::m_desc[] = {
+ const pstring nld_9312::m_desc[] = {
" C, B, A, G,D0,D1,D2,D3,D4,D5,D6,D7| Y,YQ",
" X, X, X, 1, X, X, X, X, X, X, X, X| 0, 1|33,19",
" 0, 0, 0, 0, 0, X, X, X, X, X, X, X| 0, 1|33,28",
diff --git a/src/lib/netlist/devices/nld_9312.h b/src/lib/netlist/devices/nld_9312.h
index 98cc0d115c8..c85d86d2773 100644
--- a/src/lib/netlist/devices/nld_9312.h
+++ b/src/lib/netlist/devices/nld_9312.h
@@ -39,19 +39,19 @@
#include "nl_setup.h"
-#define TTL_9312(name, cA, cB, cC, cD0, cD1, cD2, cD3, cD4, cD5, cD6, cD7, cSTROBE) \
- NET_REGISTER_DEV(TTL_9312, name) \
- NET_CONNECT(name, A, cA) \
- NET_CONNECT(name, B, cB) \
- NET_CONNECT(name, C, cC) \
- NET_CONNECT(name, D0, cD0) \
- NET_CONNECT(name, D1, cD1) \
- NET_CONNECT(name, D2, cD2) \
- NET_CONNECT(name, D3, cD3) \
- NET_CONNECT(name, D4, cD4) \
- NET_CONNECT(name, D5, cD5) \
- NET_CONNECT(name, D6, cD6) \
- NET_CONNECT(name, D7, cD7) \
+#define TTL_9312(name, cA, cB, cC, cD0, cD1, cD2, cD3, cD4, cD5, cD6, cD7, cSTROBE) \
+ NET_REGISTER_DEV(TTL_9312, name) \
+ NET_CONNECT(name, A, cA) \
+ NET_CONNECT(name, B, cB) \
+ NET_CONNECT(name, C, cC) \
+ NET_CONNECT(name, D0, cD0) \
+ NET_CONNECT(name, D1, cD1) \
+ NET_CONNECT(name, D2, cD2) \
+ NET_CONNECT(name, D3, cD3) \
+ NET_CONNECT(name, D4, cD4) \
+ NET_CONNECT(name, D5, cD5) \
+ NET_CONNECT(name, D6, cD6) \
+ NET_CONNECT(name, D7, cD7) \
NET_CONNECT(name, G, cSTROBE)
#define TTL_9312_DIP(name) \
diff --git a/src/lib/netlist/devices/nld_9316.cpp b/src/lib/netlist/devices/nld_9316.cpp
index ea7ca9fc45c..e9004417b6d 100644
--- a/src/lib/netlist/devices/nld_9316.cpp
+++ b/src/lib/netlist/devices/nld_9316.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_9316.h"
+#include "nl_base.h"
#define MAXCNT 15
@@ -161,22 +162,22 @@ namespace netlist
{
if (m_loadq)
{
- switch (m_cnt())
+ if (m_cnt < MAXCNT - 1)
{
- case MAXCNT - 1:
- m_cnt = MAXCNT;
- m_RC.push(m_ent, NLTIME_FROM_NS(27));
- m_QA.push(1, NLTIME_FROM_NS(20));
- break;
- case MAXCNT:
- m_RC.push(0, NLTIME_FROM_NS(27));
- m_cnt = 0;
- update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
- break;
- default:
- m_cnt++;
- update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
- break;
+ m_cnt++;
+ update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
+ }
+ else if (m_cnt == MAXCNT - 1)
+ {
+ m_cnt = MAXCNT;
+ m_RC.push(m_ent, NLTIME_FROM_NS(27));
+ m_QA.push(1, NLTIME_FROM_NS(20));
+ }
+ else // MAXCNT
+ {
+ m_RC.push(0, NLTIME_FROM_NS(27));
+ m_cnt = 0;
+ update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
}
}
else
diff --git a/src/lib/netlist/devices/nld_9322.cpp b/src/lib/netlist/devices/nld_9322.cpp
index 881ec9e5355..1f402d4111b 100644
--- a/src/lib/netlist/devices/nld_9322.cpp
+++ b/src/lib/netlist/devices/nld_9322.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_9322.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_am2847.cpp b/src/lib/netlist/devices/nld_am2847.cpp
index b4891db5398..be5f75c3774 100644
--- a/src/lib/netlist/devices/nld_am2847.cpp
+++ b/src/lib/netlist/devices/nld_am2847.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_am2847.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_dm9334.cpp b/src/lib/netlist/devices/nld_dm9334.cpp
index 091f08f00a8..b8607374620 100644
--- a/src/lib/netlist/devices/nld_dm9334.cpp
+++ b/src/lib/netlist/devices/nld_dm9334.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_dm9334.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_legacy.cpp b/src/lib/netlist/devices/nld_legacy.cpp
index 3a063094b72..29cff9576ab 100644
--- a/src/lib/netlist/devices/nld_legacy.cpp
+++ b/src/lib/netlist/devices/nld_legacy.cpp
@@ -6,7 +6,7 @@
*/
#include "nld_legacy.h"
-#include "nl_setup.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_log.cpp b/src/lib/netlist/devices/nld_log.cpp
index 17661de803d..d69bc6aa81e 100644
--- a/src/lib/netlist/devices/nld_log.cpp
+++ b/src/lib/netlist/devices/nld_log.cpp
@@ -5,7 +5,6 @@
*
*/
-#include <memory>
#include "nl_base.h"
#include "plib/pstream.h"
#include "plib/pfmtlog.h"
@@ -20,21 +19,22 @@ namespace netlist
{
NETLIB_CONSTRUCTOR(log)
, m_I(*this, "I")
+ , m_strm(plib::pfmt("{1}.log")(this->name()))
+ , m_writer(m_strm)
{
- pstring filename = plib::pfmt("{1}.log")(this->name());
- m_strm = plib::make_unique<plib::pofilestream>(filename);
}
NETLIB_UPDATEI()
{
/* use pstring::sprintf, it is a LOT faster */
- m_strm->writeline(plib::pfmt("{1} {2}").e(netlist().time().as_double(),".9").e(static_cast<double>(m_I())));
+ m_writer.writeline(plib::pfmt("{1} {2}").e(netlist().time().as_double(),".9").e(static_cast<double>(m_I())));
}
NETLIB_RESETI() { }
protected:
analog_input_t m_I;
- std::unique_ptr<plib::pofilestream> m_strm;
+ plib::pofilestream m_strm;
+ plib::putf8_writer m_writer;
};
NETLIB_OBJECT_DERIVED(logD, log)
@@ -46,7 +46,7 @@ namespace netlist
NETLIB_UPDATEI()
{
- m_strm->writeline(plib::pfmt("{1} {2}").e(netlist().time().as_double(),".9").e(static_cast<double>(m_I() - m_I2())));
+ m_writer.writeline(plib::pfmt("{1} {2}").e(netlist().time().as_double(),".9").e(static_cast<double>(m_I() - m_I2())));
}
NETLIB_RESETI() { }
diff --git a/src/lib/netlist/devices/nld_mm5837.cpp b/src/lib/netlist/devices/nld_mm5837.cpp
index 7650538997b..d9297166d94 100644
--- a/src/lib/netlist/devices/nld_mm5837.cpp
+++ b/src/lib/netlist/devices/nld_mm5837.cpp
@@ -6,8 +6,8 @@
*/
#include "nld_mm5837.h"
-#include <solver/nld_matrix_solver.h>
-#include "analog/nld_twoterm.h"
+#include "solver/nld_matrix_solver.h"
+#include "analog/nlid_twoterm.h"
#define R_LOW (1000.0)
#define R_HIGH (1000.0)
@@ -72,7 +72,7 @@ namespace netlist
m_RV.set(NL_FCONST(1.0) / R_LOW, 0.0, 0.0);
m_inc = netlist_time::from_double(1.0 / m_FREQ());
if (m_FREQ() < 24000 || m_FREQ() > 56000)
- netlist().log().warning("MM5837: Frequency outside of specs.", m_FREQ());
+ log().warning(MW_1_FREQUENCY_OUTSIDE_OF_SPECS_1, m_FREQ());
m_shift = 0x1ffff;
m_is_timestep = m_RV.m_P.net().solver()->is_timestep();
@@ -82,7 +82,7 @@ namespace netlist
{
m_inc = netlist_time::from_double(1.0 / m_FREQ());
if (m_FREQ() < 24000 || m_FREQ() > 56000)
- netlist().log().warning("MM5837: Frequency outside of specs.", m_FREQ());
+ log().warning(MW_1_FREQUENCY_OUTSIDE_OF_SPECS_1, m_FREQ());
}
NETLIB_UPDATE(MM5837_dip)
diff --git a/src/lib/netlist/devices/nld_ne555.cpp b/src/lib/netlist/devices/nld_ne555.cpp
index 3cfd120be30..f9bb5e261c2 100644
--- a/src/lib/netlist/devices/nld_ne555.cpp
+++ b/src/lib/netlist/devices/nld_ne555.cpp
@@ -6,8 +6,8 @@
*/
#include "nld_ne555.h"
-#include "analog/nld_twoterm.h"
-#include <solver/nld_solver.h>
+#include "analog/nlid_twoterm.h"
+#include "solver/nld_solver.h"
#define R_OFF (1E20)
#define R_ON (25) // Datasheet states a maximum discharge of 200mA, R = 5V / 0.2
diff --git a/src/lib/netlist/devices/nld_r2r_dac.cpp b/src/lib/netlist/devices/nld_r2r_dac.cpp
index 8a6d811f2d4..f4006eef31d 100644
--- a/src/lib/netlist/devices/nld_r2r_dac.cpp
+++ b/src/lib/netlist/devices/nld_r2r_dac.cpp
@@ -5,8 +5,9 @@
*
*/
-#include "nld_r2r_dac.h"
-#include "analog/nld_twoterm.h"
+#include "nl_base.h"
+#include "nl_factory.h"
+#include "analog/nlid_twoterm.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nld_system.cpp b/src/lib/netlist/devices/nld_system.cpp
index f555e41720a..e3585271696 100644
--- a/src/lib/netlist/devices/nld_system.cpp
+++ b/src/lib/netlist/devices/nld_system.cpp
@@ -5,8 +5,8 @@
*
*/
-#include <solver/nld_solver.h>
-#include <solver/nld_matrix_solver.h>
+#include "solver/nld_solver.h"
+#include "solver/nld_matrix_solver.h"
#include "nlid_system.h"
namespace netlist
@@ -132,82 +132,13 @@ namespace netlist
NETLIB_UPDATE(function)
{
- //nl_double val = INPANALOG(m_I[0]) * INPANALOG(m_I[1]) * 0.2;
- //OUTANALOG(m_Q, val);
- nl_double stack[20];
- unsigned ptr = 0;
- std::size_t e = m_precompiled.size();
- for (std::size_t i = 0; i<e; i++)
+ for (std::size_t i=0; i < static_cast<unsigned>(m_N()); i++)
{
- rpn_inst &rc = m_precompiled[i];
- switch (rc.m_cmd)
- {
- case ADD:
- ptr--;
- stack[ptr-1] = stack[ptr] + stack[ptr-1];
- break;
- case MULT:
- ptr--;
- stack[ptr-1] = stack[ptr] * stack[ptr-1];
- break;
- case SUB:
- ptr--;
- stack[ptr-1] = stack[ptr-1] - stack[ptr];
- break;
- case DIV:
- ptr--;
- stack[ptr-1] = stack[ptr-1] / stack[ptr];
- break;
- case POW:
- ptr--;
- stack[ptr-1] = std::pow(stack[ptr-1], stack[ptr]);
- break;
- case PUSH_INPUT:
- stack[ptr++] = (*m_I[static_cast<unsigned>(rc.m_param)])();
- break;
- case PUSH_CONST:
- stack[ptr++] = rc.m_param;
- break;
- }
+ m_vals[i] = (*m_I[i])();
}
- m_Q.push(stack[ptr-1]);
+ m_Q.push(m_precompiled.evaluate(m_vals));
}
- void NETLIB_NAME(function)::compile()
- {
- plib::pstring_vector_t cmds(m_func(), " ");
- m_precompiled.clear();
-
- for (std::size_t i=0; i < cmds.size(); i++)
- {
- pstring cmd = cmds[i];
- rpn_inst rc;
- if (cmd == "+")
- rc.m_cmd = ADD;
- else if (cmd == "-")
- rc.m_cmd = SUB;
- else if (cmd == "*")
- rc.m_cmd = MULT;
- else if (cmd == "/")
- rc.m_cmd = DIV;
- else if (cmd == "pow")
- rc.m_cmd = POW;
- else if (cmd.startsWith("A"))
- {
- rc.m_cmd = PUSH_INPUT;
- rc.m_param = cmd.substr(1).as_long();
- }
- else
- {
- bool err = false;
- rc.m_cmd = PUSH_CONST;
- rc.m_param = cmd.as_double(&err);
- if (err)
- netlist().log().fatal("nld_function: unknown/misformatted token <{1}> in <{2}>", cmd, m_func());
- }
- m_precompiled.push_back(rc);
- }
- }
NETLIB_DEVICE_IMPL(dummy_input)
NETLIB_DEVICE_IMPL(frontier)
diff --git a/src/lib/netlist/devices/nld_system.h b/src/lib/netlist/devices/nld_system.h
index 738ceb2a171..46781fe2884 100644
--- a/src/lib/netlist/devices/nld_system.h
+++ b/src/lib/netlist/devices/nld_system.h
@@ -54,9 +54,6 @@
NET_C(cG, name.G) \
NET_C(cOUT, name.Q)
-#define OPTIMIZE_FRONTIER(attach, r_in, r_out) \
- setup.register_frontier(# attach, r_in, r_out);
-
#define RES_SWITCH(name, cIN, cP1, cP2) \
NET_REGISTER_DEV(RES_SWITCH, name) \
NET_C(cIN, name.I) \
@@ -72,4 +69,5 @@
PARAM(name.N, p_N) \
PARAM(name.FUNC, p_F)
+
#endif /* NLD_SYSTEM_H_ */
diff --git a/src/lib/netlist/devices/nld_tristate.cpp b/src/lib/netlist/devices/nld_tristate.cpp
index db21468685e..b724a09bf9c 100644
--- a/src/lib/netlist/devices/nld_tristate.cpp
+++ b/src/lib/netlist/devices/nld_tristate.cpp
@@ -6,6 +6,7 @@
*/
#include "nld_tristate.h"
+#include "nl_base.h"
namespace netlist
{
diff --git a/src/lib/netlist/devices/nlid_cmos.h b/src/lib/netlist/devices/nlid_cmos.h
index 4770eac2164..2d836ef656d 100644
--- a/src/lib/netlist/devices/nlid_cmos.h
+++ b/src/lib/netlist/devices/nlid_cmos.h
@@ -8,6 +8,7 @@
#ifndef NLID_CMOS_H_
#define NLID_CMOS_H_
+#include "nl_setup.h"
#include "nl_base.h"
namespace netlist
diff --git a/src/lib/netlist/devices/nlid_proxy.cpp b/src/lib/netlist/devices/nlid_proxy.cpp
index 0b08327070c..4b18ca0bbb2 100644
--- a/src/lib/netlist/devices/nlid_proxy.cpp
+++ b/src/lib/netlist/devices/nlid_proxy.cpp
@@ -5,7 +5,6 @@
*
*/
-//#include <memory>
#include "nlid_proxy.h"
#include "solver/nld_solver.h"
//#include "plib/pstream.h"
@@ -100,7 +99,7 @@ namespace netlist
, m_last_state(*this, "m_last_var", -1)
, m_is_timestep(false)
{
- const char *power_syms[3][2] ={ {"VCC", "VEE"}, {"VCC", "GND"}, {"VDD", "VSS"}};
+ const pstring power_syms[3][2] ={ {"VCC", "VEE"}, {"VCC", "GND"}, {"VDD", "VSS"}};
//register_sub(m_RV);
//register_term("1", m_RV.m_P);
//register_term("2", m_RV.m_N);
@@ -112,8 +111,10 @@ namespace netlist
for (int i = 0; i < 3; i++)
{
pstring devname = out_proxied->device().name();
- auto tp = netlist().setup().find_terminal(devname + "." + power_syms[i][0], detail::device_object_t::type_t::INPUT, false);
- auto tn = netlist().setup().find_terminal(devname + "." + power_syms[i][1], detail::device_object_t::type_t::INPUT, false);
+ auto tp = netlist().setup().find_terminal(devname + "." + power_syms[i][0],
+ detail::terminal_type::INPUT, false);
+ auto tn = netlist().setup().find_terminal(devname + "." + power_syms[i][1],
+ detail::terminal_type::INPUT, false);
if (tp != nullptr && tn != nullptr)
{
/* alternative logic */
@@ -121,12 +122,12 @@ namespace netlist
}
}
if (!f)
- netlist().log().warning("D/A Proxy: Found no valid combination of power terminals on device {1}", out_proxied->device().name());
+ log().warning(MW_1_NO_POWER_TERMINALS_ON_DEVICE_1, out_proxied->device().name());
else
- netlist().log().warning("D/A Proxy: Found power terminals on device {1}", out_proxied->device().name());
+ log().verbose("D/A Proxy: Found power terminals on device {1}", out_proxied->device().name());
#if (0)
printf("%s %s\n", out_proxied->name().c_str(), out_proxied->device().name().c_str());
- auto x = netlist().setup().find_terminal(out_proxied->name(), detail::device_object_t::type_t::OUTPUT, false);
+ auto x = netlist().setup().find_terminal(out_proxied->name(), detail::device_object_t::terminal_type::OUTPUT, false);
if (x) printf("==> %s\n", x->name().c_str());
#endif
}
diff --git a/src/lib/netlist/devices/nlid_proxy.h b/src/lib/netlist/devices/nlid_proxy.h
index 77a8d52026c..178faae20fd 100644
--- a/src/lib/netlist/devices/nlid_proxy.h
+++ b/src/lib/netlist/devices/nlid_proxy.h
@@ -11,12 +11,8 @@
#ifndef NLID_PROXY_H_
#define NLID_PROXY_H_
-#include <vector>
-
#include "nl_setup.h"
-#include "nl_base.h"
-#include "nl_factory.h"
-#include "analog/nld_twoterm.h"
+#include "analog/nlid_twoterm.h"
namespace netlist
{
@@ -127,7 +123,7 @@ namespace netlist
analog::NETLIB_SUB(twoterm) m_RV;
state_var<int> m_last_state;
bool m_is_timestep;
- };
+};
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/devices/nlid_system.h b/src/lib/netlist/devices/nlid_system.h
index 8d2cd8162f8..e9baa4c159d 100644
--- a/src/lib/netlist/devices/nlid_system.h
+++ b/src/lib/netlist/devices/nlid_system.h
@@ -11,12 +11,10 @@
#ifndef NLID_SYSTEM_H_
#define NLID_SYSTEM_H_
-#include <vector>
-
-#include "nl_setup.h"
#include "nl_base.h"
-#include "nl_factory.h"
-#include "analog/nld_twoterm.h"
+#include "nl_setup.h"
+#include "analog/nlid_twoterm.h"
+#include "plib/putil.h"
namespace netlist
{
@@ -126,7 +124,7 @@ namespace netlist
connect(m_feedback, m_Q);
{
netlist_time base = netlist_time::from_double(1.0 / (m_freq()*2.0));
- plib::pstring_vector_t pat(m_pattern(),",");
+ std::vector<pstring> pat(plib::psplit(m_pattern(),","));
m_off = netlist_time::from_double(m_offset());
unsigned long pati[256];
@@ -175,7 +173,7 @@ namespace netlist
/* make sure we get the family first */
, m_FAMILY(*this, "FAMILY", "FAMILY(TYPE=TTL)")
{
- set_logic_family(netlist().family_from_model(m_FAMILY()));
+ set_logic_family(setup().family_from_model(m_FAMILY()));
}
NETLIB_UPDATE_AFTER_PARAM_CHANGE()
@@ -309,9 +307,15 @@ namespace netlist
, m_func(*this, "FUNC", "")
, m_Q(*this, "Q")
{
+ std::vector<pstring> inps;
for (int i=0; i < m_N(); i++)
- m_I.push_back(plib::make_unique<analog_input_t>(*this, plib::pfmt("A{1}")(i)));
- compile();
+ {
+ pstring n = plib::pfmt("A{1}")(i);
+ m_I.push_back(plib::make_unique<analog_input_t>(*this, n));
+ inps.push_back(n);
+ m_vals.push_back(0.0);
+ }
+ m_precompiled.compile(inps, m_func());
}
protected:
@@ -321,32 +325,13 @@ namespace netlist
private:
- enum rpn_cmd
- {
- ADD,
- MULT,
- SUB,
- DIV,
- POW,
- PUSH_CONST,
- PUSH_INPUT
- };
-
- struct rpn_inst
- {
- rpn_inst() : m_cmd(ADD), m_param(0.0) { }
- rpn_cmd m_cmd;
- nl_double m_param;
- };
-
- void compile();
-
param_int_t m_N;
param_str_t m_func;
analog_output_t m_Q;
std::vector<std::unique_ptr<analog_input_t>> m_I;
- std::vector<rpn_inst> m_precompiled;
+ std::vector<double> m_vals;
+ plib::pfunction m_precompiled;
};
// -----------------------------------------------------------------------------
diff --git a/src/lib/netlist/devices/nld_truthtable.cpp b/src/lib/netlist/devices/nlid_truthtable.cpp
index 9030f6b8801..824061fdc30 100644
--- a/src/lib/netlist/devices/nld_truthtable.cpp
+++ b/src/lib/netlist/devices/nlid_truthtable.cpp
@@ -5,9 +5,10 @@
*
*/
-#include "nld_truthtable.h"
+#include "nlid_truthtable.h"
#include "plib/plists.h"
#include "nl_setup.h"
+#include "plib/palloc.h"
namespace netlist
{
@@ -16,11 +17,10 @@ namespace netlist
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)
public:
netlist_factory_truthtable_t(const pstring &name, const pstring &classname,
- const pstring &def_param)
- : netlist_base_factory_truthtable_t(name, classname, def_param)
+ const pstring &def_param, const pstring &sourcefile)
+ : netlist_base_factory_truthtable_t(name, classname, def_param, sourcefile)
{ }
plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) override
@@ -120,7 +120,7 @@ uint_least64_t truthtable_desc_t::get_ignored_extended(uint_least64_t state)
// desc
// ----------------------------------------------------------------------------------------
-void truthtable_desc_t::help(unsigned cur, plib::pstring_vector_t list,
+void truthtable_desc_t::help(unsigned cur, std::vector<pstring> list,
uint_least64_t state, uint_least64_t val, std::vector<uint_least8_t> &timing_index)
{
pstring elem = list[cur].trim();
@@ -165,7 +165,7 @@ void truthtable_desc_t::help(unsigned cur, plib::pstring_vector_t list,
}
}
-void truthtable_desc_t::setup(const plib::pstring_vector_t &truthtable, uint_least64_t disabled_ignore)
+void truthtable_desc_t::setup(const std::vector<pstring> &truthtable, uint_least64_t disabled_ignore)
{
unsigned line = 0;
@@ -185,14 +185,14 @@ void truthtable_desc_t::setup(const plib::pstring_vector_t &truthtable, uint_lea
while (!ttline.equals(""))
{
- plib::pstring_vector_t io(ttline,"|");
+ std::vector<pstring> io(plib::psplit(ttline,"|"));
// checks
nl_assert_always(io.size() == 3, "io.count mismatch");
- plib::pstring_vector_t inout(io[0], ",");
+ std::vector<pstring> inout(plib::psplit(io[0], ","));
nl_assert_always(inout.size() == m_num_bits, "number of bits not matching");
- plib::pstring_vector_t out(io[1], ",");
+ std::vector<pstring> out(plib::psplit(io[1], ","));
nl_assert_always(out.size() == m_NO, "output count not matching");
- plib::pstring_vector_t times(io[2], ",");
+ std::vector<pstring> times(plib::psplit(io[2], ","));
nl_assert_always(times.size() == m_NO, "timing count not matching");
uint_least64_t val = 0;
@@ -260,8 +260,8 @@ void truthtable_desc_t::setup(const plib::pstring_vector_t &truthtable, uint_lea
}
netlist_base_factory_truthtable_t::netlist_base_factory_truthtable_t(const pstring &name, const pstring &classname,
- const pstring &def_param)
-: factory::element_t(name, classname, def_param), m_family(family_TTL())
+ const pstring &def_param, const pstring &sourcefile)
+: factory::element_t(name, classname, def_param, sourcefile), m_family(family_TTL())
{
}
@@ -270,35 +270,36 @@ netlist_base_factory_truthtable_t::~netlist_base_factory_truthtable_t()
}
-#define ENTRYY(n, m) case (n * 100 + m): \
+#define ENTRYY(n, m, s) case (n * 100 + m): \
{ using xtype = netlist_factory_truthtable_t<n, m>; \
- ret = new xtype(desc.name, desc.classname, desc.def_param); } break
+ ret = plib::palloc<xtype>(desc.name, desc.classname, desc.def_param, s); } break
-#define ENTRY(n) ENTRYY(n, 1); ENTRYY(n, 2); ENTRYY(n, 3); ENTRYY(n, 4); ENTRYY(n, 5); ENTRYY(n, 6)
+#define ENTRY(n, s) ENTRYY(n, 1, s); ENTRYY(n, 2, s); ENTRYY(n, 3, s); \
+ ENTRYY(n, 4, s); ENTRYY(n, 5, s); ENTRYY(n, 6, s)
-void tt_factory_create(setup_t &setup, tt_desc &desc)
+void tt_factory_create(setup_t &setup, tt_desc &desc, const pstring &sourcefile)
{
netlist_base_factory_truthtable_t *ret;
switch (desc.ni * 100 + desc.no)
{
- ENTRY(1);
- ENTRY(2);
- ENTRY(3);
- ENTRY(4);
- ENTRY(5);
- ENTRY(6);
- ENTRY(7);
- ENTRY(8);
- ENTRY(9);
- ENTRY(10);
+ ENTRY(1, sourcefile);
+ ENTRY(2, sourcefile);
+ ENTRY(3, sourcefile);
+ ENTRY(4, sourcefile);
+ ENTRY(5, sourcefile);
+ ENTRY(6, sourcefile);
+ ENTRY(7, sourcefile);
+ ENTRY(8, sourcefile);
+ ENTRY(9, sourcefile);
+ ENTRY(10, sourcefile);
default:
pstring msg = plib::pfmt("unable to create truthtable<{1},{2}>")(desc.ni)(desc.no);
nl_assert_always(false, msg);
}
ret->m_desc = desc.desc;
if (desc.family != "")
- ret->m_family = setup.netlist().family_from_model(desc.family);
+ ret->m_family = setup.family_from_model(desc.family);
setup.factory().register_device(std::unique_ptr<netlist_base_factory_truthtable_t>(ret));
}
diff --git a/src/lib/netlist/devices/nld_truthtable.h b/src/lib/netlist/devices/nlid_truthtable.h
index 990afc45dd7..68c3d680e40 100644
--- a/src/lib/netlist/devices/nld_truthtable.h
+++ b/src/lib/netlist/devices/nlid_truthtable.h
@@ -7,15 +7,12 @@
* Author: andre
*/
-#ifndef NLD_TRUTHTABLE_H_
-#define NLD_TRUTHTABLE_H_
-
-#include <new>
-#include <cstdint>
+#ifndef NLID_TRUTHTABLE_H_
+#define NLID_TRUTHTABLE_H_
#include "nl_setup.h"
-#include "nl_factory.h"
-#include "plib/plists.h"
+#include "nl_base.h"
+#include "plib/putil.h"
#define NETLIB_TRUTHTABLE(cname, nIN, nOUT) \
class NETLIB_NAME(cname) : public nld_truthtable_t<nIN, nOUT> \
@@ -26,7 +23,7 @@
: nld_truthtable_t<nIN, nOUT>(owner, name, family_TTL(), &m_ttbl, m_desc) { } \
private: \
static truthtable_t m_ttbl; \
- static const char *m_desc[]; \
+ static const pstring m_desc[]; \
}
@@ -112,10 +109,10 @@ namespace netlist
{
}
- void setup(const plib::pstring_vector_t &desc, uint_least64_t disabled_ignore);
+ void setup(const std::vector<pstring> &desc, uint_least64_t disabled_ignore);
private:
- void help(unsigned cur, plib::pstring_vector_t list,
+ void help(unsigned cur, std::vector<pstring> list,
uint_least64_t state, uint_least64_t val, std::vector<uint_least8_t> &timing_index);
static unsigned count_bits(uint_least64_t v);
static uint_least64_t set_bits(uint_least64_t v, uint_least64_t b);
@@ -159,14 +156,14 @@ namespace netlist
template <class C>
nld_truthtable_t(C &owner, const pstring &name, const logic_family_desc_t *fam,
- truthtable_t *ttp, const char *desc[])
+ truthtable_t *ttp, const pstring *desc)
: device_t(owner, name)
, m_fam(*this, fam)
, m_ign(*this, "m_ign", 0)
, m_active(*this, "m_active", 1)
, m_ttp(ttp)
{
- while (*desc != nullptr && **desc != 0 )
+ while (*desc != "" )
{
m_desc.push_back(*desc);
desc++;
@@ -176,7 +173,7 @@ namespace netlist
template <class C>
nld_truthtable_t(C &owner, const pstring &name, const logic_family_desc_t *fam,
- truthtable_t *ttp, const plib::pstring_vector_t &desc)
+ truthtable_t *ttp, const std::vector<pstring> &desc)
: device_t(owner, name)
, m_fam(*this, fam)
, m_ign(*this, "m_ign", 0)
@@ -193,12 +190,12 @@ namespace netlist
pstring header = m_desc[0];
- plib::pstring_vector_t io(header,"|");
+ std::vector<pstring> io(plib::psplit(header,"|"));
// checks
nl_assert_always(io.size() == 2, "too many '|'");
- plib::pstring_vector_t inout(io[0], ",");
+ std::vector<pstring> inout(plib::psplit(io[0], ","));
nl_assert_always(inout.size() == m_num_bits, "bitcount wrong");
- plib::pstring_vector_t out(io[1], ",");
+ std::vector<pstring> out(plib::psplit(io[1], ","));
nl_assert_always(out.size() == m_NO, "output count wrong");
for (std::size_t i=0; i < m_NI; i++)
@@ -363,27 +360,26 @@ namespace netlist
state_var_u32 m_ign;
state_var_s32 m_active;
truthtable_t * m_ttp;
- plib::pstring_vector_t m_desc;
+ std::vector<pstring> m_desc;
};
class netlist_base_factory_truthtable_t : public factory::element_t
{
- P_PREVENT_COPYING(netlist_base_factory_truthtable_t)
public:
netlist_base_factory_truthtable_t(const pstring &name, const pstring &classname,
- const pstring &def_param);
+ const pstring &def_param, const pstring &sourcefile);
virtual ~netlist_base_factory_truthtable_t();
- plib::pstring_vector_t m_desc;
+ std::vector<pstring> m_desc;
const logic_family_desc_t *m_family;
};
- void tt_factory_create(setup_t &setup, tt_desc &desc);
+ void tt_factory_create(setup_t &setup, tt_desc &desc, const pstring &sourcefile);
} //namespace devices
} // namespace netlist
-#endif /* NLD_TRUTHTABLE_H_ */
+#endif /* NLID_TRUTHTABLE_H_ */
diff --git a/src/lib/netlist/documentation/mainpage.dox.h b/src/lib/netlist/documentation/mainpage.dox.h
index 75df1a18065..744abe642e6 100644
--- a/src/lib/netlist/documentation/mainpage.dox.h
+++ b/src/lib/netlist/documentation/mainpage.dox.h
@@ -161,5 +161,4 @@ equation solver.
The formal representation of the circuit will stay the same, thus scales.
-
*/
diff --git a/src/lib/netlist/macro/nlm_cd4xxx.cpp b/src/lib/netlist/macro/nlm_cd4xxx.cpp
index 469ff13b954..ed805cb52dc 100644
--- a/src/lib/netlist/macro/nlm_cd4xxx.cpp
+++ b/src/lib/netlist/macro/nlm_cd4xxx.cpp
@@ -2,7 +2,6 @@
// copyright-holders:Couriersud
#include "nlm_cd4xxx.h"
-#include "devices/nld_truthtable.h"
#include "devices/nld_system.h"
#include "devices/nld_4020.h"
#include "devices/nld_4066.h"
diff --git a/src/lib/netlist/macro/nlm_cd4xxx.h b/src/lib/netlist/macro/nlm_cd4xxx.h
index de10ff7a64d..446c2d6e435 100644
--- a/src/lib/netlist/macro/nlm_cd4xxx.h
+++ b/src/lib/netlist/macro/nlm_cd4xxx.h
@@ -22,6 +22,8 @@
* Netlist Macros
* ---------------------------------------------------------------------------*/
+#ifndef NL_AUTO_DEVICES
+
#define CD4001_NOR(name) \
NET_REGISTER_DEV(CD4001_NOR, name)
@@ -44,6 +46,7 @@
#define CD4316_DIP(name) \
NET_REGISTER_DEV(CD4016_DIP, name)
+#endif
/* ----------------------------------------------------------------------------
* External declarations
* ---------------------------------------------------------------------------*/
diff --git a/src/lib/netlist/macro/nlm_opamp.cpp b/src/lib/netlist/macro/nlm_opamp.cpp
index 146f95b72b4..f363c88a100 100644
--- a/src/lib/netlist/macro/nlm_opamp.cpp
+++ b/src/lib/netlist/macro/nlm_opamp.cpp
@@ -1,9 +1,7 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
#include "nlm_opamp.h"
-
-#include "analog/nld_opamps.h"
-#include "devices/nld_system.h"
+#include "devices/net_lib.h"
/*
* Generic layout with 4 opamps, VCC on pin 4 and GND on pin 11
diff --git a/src/lib/netlist/macro/nlm_opamp.h b/src/lib/netlist/macro/nlm_opamp.h
index 6e3c1f615e7..ec717fdb2dc 100644
--- a/src/lib/netlist/macro/nlm_opamp.h
+++ b/src/lib/netlist/macro/nlm_opamp.h
@@ -11,6 +11,8 @@
* Netlist Macros
* ---------------------------------------------------------------------------*/
+#ifndef NL_AUTO_DEVICES
+
#define MB3614_DIP(name) \
NET_REGISTER_DEV(MB3614_DIP, name)
@@ -23,6 +25,8 @@
#define LM3900(name) \
NET_REGISTER_DEV(LM3900, name)
+#endif
+
/* ----------------------------------------------------------------------------
* External declarations
* ---------------------------------------------------------------------------*/
diff --git a/src/lib/netlist/macro/nlm_other.cpp b/src/lib/netlist/macro/nlm_other.cpp
index 84a3af4dc04..49f4404427a 100644
--- a/src/lib/netlist/macro/nlm_other.cpp
+++ b/src/lib/netlist/macro/nlm_other.cpp
@@ -2,7 +2,6 @@
// copyright-holders:Couriersud
#include "nlm_other.h"
-#include "devices/nld_truthtable.h"
#include "devices/nld_system.h"
/*
diff --git a/src/lib/netlist/macro/nlm_other.h b/src/lib/netlist/macro/nlm_other.h
index bb73d0105d2..f0e8ca05af0 100644
--- a/src/lib/netlist/macro/nlm_other.h
+++ b/src/lib/netlist/macro/nlm_other.h
@@ -11,12 +11,15 @@
* Netlist Macros
* ---------------------------------------------------------------------------*/
+#ifndef NL_AUTO_DEVICES
+
#define MC14584B_GATE(name) \
NET_REGISTER_DEV(MC14584B_GATE, name)
#define MC14584B_DIP(name) \
NET_REGISTER_DEV(MC14584B_DIP, name)
+#endif
/* ----------------------------------------------------------------------------
* External declarations
diff --git a/src/lib/netlist/macro/nlm_ttl74xx.cpp b/src/lib/netlist/macro/nlm_ttl74xx.cpp
index c66314366d2..c8fe9912911 100644
--- a/src/lib/netlist/macro/nlm_ttl74xx.cpp
+++ b/src/lib/netlist/macro/nlm_ttl74xx.cpp
@@ -2,7 +2,6 @@
// copyright-holders:Couriersud
#include "nlm_ttl74xx.h"
-#include "devices/nld_truthtable.h"
#include "devices/nld_system.h"
@@ -377,7 +376,7 @@ static NETLIST_START(TTL_7427_DIP)
s2.C, /* C2 |5 10| B3 */ s3.B,
s2.Q, /* Y2 |6 9| A3 */ s3.A,
GND.I, /* GND |7 8| Y3 */ s3.Q
- /* +--------------+ */
+ /* +--------------+ */
)
NETLIST_END()
@@ -413,11 +412,11 @@ static NETLIST_START(TTL_7430_DIP)
s1.A, /* A |1 ++ 14| VCC */ VCC.I,
s1.B, /* B |2 13| NC */ NC.I,
s1.C, /* C |3 12| H */ s1.H,
- s1.D, /* D |4 7420 11| G */ s1.G,
+ s1.D, /* D |4 7430 11| G */ s1.G,
s1.E, /* E |5 10| NC */ NC.I,
s1.F, /* F |6 9| NC */ NC.I,
GND.I, /* GND |7 8| Y */ s1.Q
- /* +--------------+ */
+ /* +--------------+ */
)
NETLIST_END()
diff --git a/src/lib/netlist/macro/nlm_ttl74xx.h b/src/lib/netlist/macro/nlm_ttl74xx.h
index 44b3db63bd3..526fbf395da 100644
--- a/src/lib/netlist/macro/nlm_ttl74xx.h
+++ b/src/lib/netlist/macro/nlm_ttl74xx.h
@@ -11,6 +11,8 @@
* Netlist Macros
* ---------------------------------------------------------------------------*/
+#ifndef NL_AUTO_DEVICES
+
#define TTL_7400_GATE(name) \
NET_REGISTER_DEV(TTL_7400_GATE, name)
@@ -200,6 +202,8 @@
#define TTL_74260_DIP(name) \
NET_REGISTER_DEV(TTL_74260_DIP, name)
+#endif
+
/* ----------------------------------------------------------------------------
* External declarations
* ---------------------------------------------------------------------------*/
diff --git a/src/lib/netlist/netlist_types.h b/src/lib/netlist/netlist_types.h
new file mode 100644
index 00000000000..c7c4aef4750
--- /dev/null
+++ b/src/lib/netlist/netlist_types.h
@@ -0,0 +1,54 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*!
+ *
+ * \file netlist_types.h
+ *
+ */
+
+#ifndef NETLIST_TYPES_H_
+#define NETLIST_TYPES_H_
+
+#include <cstdint>
+#include <unordered_map>
+
+#include "nl_config.h"
+#include "plib/pchrono.h"
+#include "plib/pstring.h"
+
+namespace netlist
+{
+ //============================================================
+ // Performance tracking
+ //============================================================
+
+#if NL_KEEP_STATISTICS
+ using nperftime_t = plib::chrono::timer<plib::chrono::exact_ticks, true>;
+ using nperfcount_t = plib::chrono::counter<true>;
+#else
+ using nperftime_t = plib::chrono::timer<plib::chrono::exact_ticks, false>;
+ using nperfcount_t = plib::chrono::counter<false>;
+#endif
+
+ //============================================================
+ // Types needed by various includes
+ //============================================================
+
+ namespace detail {
+
+ /*! Enum specifying the type of object */
+ enum terminal_type {
+ TERMINAL = 0, /*!< object is an analog terminal */
+ INPUT = 1, /*!< object is an input */
+ OUTPUT = 2, /*!< object is an output */
+ };
+
+ /*! Type of the model map used.
+ * This is used to hold all #Models in an unordered map
+ */
+ using model_map_t = std::unordered_map<pstring, pstring>;
+
+ }
+}
+
+#endif /* NETLIST_TYPES_H_ */
diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp
index 80acf9847a3..4374ef2212d 100644
--- a/src/lib/netlist/nl_base.cpp
+++ b/src/lib/netlist/nl_base.cpp
@@ -6,6 +6,7 @@
*/
#include <cstring>
+#include <cmath>
#include "solver/nld_matrix_solver.h"
#include "solver/nld_solver.h"
@@ -25,7 +26,7 @@ namespace netlist
namespace detail
{
#if (USE_MEMPOOL)
-static plib::mempool pool(65536, 8);
+static plib::mempool pool(6553600, 64);
void * object_t::operator new (size_t size)
{
@@ -135,24 +136,6 @@ const logic_family_desc_t *family_CD4XXX()
return &obj;
}
-class logic_family_std_proxy_t : public logic_family_desc_t
-{
-public:
- logic_family_std_proxy_t() { }
- virtual plib::owned_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_t &anetlist,
- const pstring &name, logic_output_t *proxied) const override;
- virtual plib::owned_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *proxied) const override;
-};
-
-plib::owned_ptr<devices::nld_base_d_to_a_proxy> logic_family_std_proxy_t::create_d_a_proxy(netlist_t &anetlist,
- const pstring &name, logic_output_t *proxied) const
-{
- return plib::owned_ptr<devices::nld_base_d_to_a_proxy>::Create<devices::nld_d_to_a_proxy>(anetlist, name, proxied);
-}
-plib::owned_ptr<devices::nld_base_a_to_d_proxy> logic_family_std_proxy_t::create_a_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *proxied) const
-{
- return plib::owned_ptr<devices::nld_base_a_to_d_proxy>::Create<devices::nld_a_to_d_proxy>(anetlist, name, proxied);
-}
// ----------------------------------------------------------------------------------------
// queue_t
@@ -199,10 +182,10 @@ void detail::queue_t::on_post_load()
netlist().log().debug("current time {1} qsize {2}\n", netlist().time().as_double(), m_qsize);
for (std::size_t i = 0; i < m_qsize; i++ )
{
- detail::net_t *n = netlist().find_net(m_names[i].m_buf);
+ detail::net_t *n = netlist().find_net(pstring(m_names[i].m_buf, pstring::UTF8));
//log().debug("Got {1} ==> {2}\n", qtemp[i].m_name, n));
//log().debug("schedule time {1} ({2})\n", n->time().as_double(), netlist_time::from_raw(m_times[i]).as_double()));
- this->push(n, netlist_time::from_raw(m_times[i]));
+ this->push(queue_t::entry_t(netlist_time::from_raw(m_times[i]),n));
}
}
@@ -234,24 +217,22 @@ detail::device_object_t::device_object_t(core_device_t &dev, const pstring &anam
{
}
-detail::device_object_t::type_t detail::device_object_t::type() const
+detail::terminal_type detail::core_terminal_t::type() const
{
if (dynamic_cast<const terminal_t *>(this) != nullptr)
- return type_t::TERMINAL;
- else if (dynamic_cast<const param_t *>(this) != nullptr)
- return param_t::PARAM;
+ return terminal_type::TERMINAL;
else if (dynamic_cast<const logic_input_t *>(this) != nullptr)
- return param_t::INPUT;
+ return terminal_type::INPUT;
else if (dynamic_cast<const logic_output_t *>(this) != nullptr)
- return param_t::OUTPUT;
+ return terminal_type::OUTPUT;
else if (dynamic_cast<const analog_input_t *>(this) != nullptr)
- return param_t::INPUT;
+ return terminal_type::INPUT;
else if (dynamic_cast<const analog_output_t *>(this) != nullptr)
- return param_t::OUTPUT;
+ return terminal_type::OUTPUT;
else
{
netlist().log().fatal(MF_1_UNKNOWN_TYPE_FOR_OBJECT, name());
- return type_t::TERMINAL; // please compiler
+ return terminal_type::TERMINAL; // please compiler
}
}
@@ -272,19 +253,16 @@ netlist_t::netlist_t(const pstring &aname)
{
state().save_item(this, static_cast<plib::state_manager_t::callback_t &>(m_queue), "m_queue");
state().save_item(this, m_time, "m_time");
- m_setup = new setup_t(*this);
+ m_setup = plib::make_unique<setup_t>(*this);
/* FIXME: doesn't really belong here */
NETLIST_NAME(base)(*m_setup);
}
netlist_t::~netlist_t()
{
- if (m_setup != nullptr)
- delete m_setup;
m_nets.clear();
m_devices.clear();
- pfree(m_lib);
pstring::resetmem();
}
@@ -303,48 +281,18 @@ void netlist_t::register_dev(plib::owned_ptr<core_device_t> dev)
void netlist_t::remove_dev(core_device_t *dev)
{
- m_devices.erase(
- std::remove_if(
- m_devices.begin(),
+ m_devices.erase(
+ std::remove_if(
+ m_devices.begin(),
m_devices.end(),
- [&] (plib::owned_ptr<core_device_t> const& p)
- {
- return p.get() == dev;
- }),
+ [&] (plib::owned_ptr<core_device_t> const& p)
+ {
+ return p.get() == dev;
+ }),
m_devices.end()
- );
+ );
}
-const logic_family_desc_t *netlist_t::family_from_model(const pstring &model)
-{
- model_map_t map;
- setup().model_parse(model, map);
-
- if (setup().model_value_str(map, "TYPE") == "TTL")
- return family_TTL();
- if (setup().model_value_str(map, "TYPE") == "CD4XXX")
- return family_CD4XXX();
-
- for (auto & e : m_family_cache)
- if (e.first == model)
- return e.second.get();
-
- auto ret = plib::make_unique_base<logic_family_desc_t, logic_family_std_proxy_t>();
-
- ret->m_fixed_V = setup().model_value(map, "FV");
- ret->m_low_thresh_PCNT = setup().model_value(map, "IVL");
- ret->m_high_thresh_PCNT = setup().model_value(map, "IVH");
- ret->m_low_VO = setup().model_value(map, "OVL");
- ret->m_high_VO = setup().model_value(map, "OVH");
- ret->m_R_low = setup().model_value(map, "ORL");
- ret->m_R_high = setup().model_value(map, "ORH");
-
- auto retp = ret.get();
-
- m_family_cache.emplace_back(model, std::move(ret));
-
- return retp;
-}
void netlist_t::start()
@@ -372,6 +320,7 @@ void netlist_t::start()
/* create devices */
+ log().debug("Creating devices ...\n");
for (auto & e : setup().m_device_factory)
{
if ( !setup().factory().is_class<devices::NETLIB_NAME(solver)>(e.second)
@@ -394,9 +343,12 @@ void netlist_t::start()
auto p = setup().m_param_values.find(d->name() + ".HINT_NO_DEACTIVATE");
if (p != setup().m_param_values.end())
{
- //FIXME: Error checking
- auto v = p->second.as_long();
- d->set_hint_deactivate(!v);
+ //FIXME: turn this into a proper function
+ bool error;
+ auto v = p->second.as_double(&error);
+ if (error || std::abs(v - std::floor(v)) > 1e-6 )
+ log().fatal(MF_1_HND_VAL_NOT_SUPPORTED, p->second);
+ d->set_hint_deactivate(v == 0.0);
}
}
else
@@ -404,11 +356,30 @@ void netlist_t::start()
}
pstring libpath = plib::util::environment("NL_BOOSTLIB", plib::util::buildpath({".", "nlboost.so"}));
- m_lib = plib::palloc<plib::dynlib>(libpath);
+ m_lib = plib::make_unique<plib::dynlib>(libpath);
/* resolve inputs */
setup().resolve_inputs();
+ /* Make sure devices are fully created - now done in register_dev */
+
+ log().debug("Setting delegate pointers ...\n");
+ for (auto &dev : m_devices)
+ dev->set_delegate_pointer();
+
+ log().verbose("looking for two terms connected to rail nets ...");
+ for (auto & t : get_device_list<analog::NETLIB_NAME(twoterm)>())
+ {
+ if (t->m_N.net().isRailNet() && t->m_P.net().isRailNet())
+ {
+ log().warning(MW_3_REMOVE_DEVICE_1_CONNECTED_ONLY_TO_RAILS_2_3,
+ t->name(), t->m_N.net().name(), t->m_P.net().name());
+ t->m_N.net().remove_terminal(t->m_N);
+ t->m_P.net().remove_terminal(t->m_P);
+ remove_dev(t);
+ }
+ }
+
log().verbose("initialize solver ...\n");
if (m_solver == nullptr)
@@ -420,12 +391,6 @@ void netlist_t::start()
else
m_solver->post_start();
- /* finally, set the pointers */
-
- log().debug("Setting delegate pointers ...\n");
- for (auto &dev : m_devices)
- dev->set_delegate_pointer();
-
}
void netlist_t::stop()
@@ -433,7 +398,8 @@ void netlist_t::stop()
log().debug("Printing statistics ...\n");
print_stats();
log().debug("Stopping solver device ...\n");
- m_solver->stop();
+ if (m_solver != nullptr)
+ m_solver->stop();
}
detail::net_t *netlist_t::find_net(const pstring &name)
@@ -474,16 +440,16 @@ void netlist_t::reset()
dev->update_param();
// Step all devices once !
+ /*
+ * INFO: The order here affects power up of e.g. breakout. However, such
+ * variations are explicitly stated in the breakout manual.
+ */
#if 0
for (std::size_t i = 0; i < m_devices.size(); i++)
{
m_devices[i]->update_dev();
}
#else
- /* FIXME: this makes breakout attract mode working again.
- * It is however not acceptable that this depends on the startup order.
- * Best would be, if reset would call update_dev for devices which need it.
- */
std::size_t i = m_devices.size();
while (i>0)
m_devices[--i]->update_dev();
@@ -495,7 +461,7 @@ void netlist_t::process_queue(const netlist_time &delta)
{
netlist_time stop(m_time + delta);
- m_queue.push(nullptr, stop);
+ m_queue.push(detail::queue_t::entry_t(stop, nullptr));
m_stat_mainloop.start();
@@ -522,17 +488,20 @@ void netlist_t::process_queue(const netlist_time &delta)
while (m_queue.top().m_exec_time > mc_time)
{
m_time = mc_time;
- mc_time += inc;
mc_net.toggle_new_Q();
mc_net.update_devs();
+ mc_time += inc;
}
const detail::queue_t::entry_t e(m_queue.pop());
m_time = e.m_exec_time;
- if (e.m_object == nullptr)
+ if (e.m_object != nullptr)
+ {
+ e.m_object->update_devs();
+ m_perf_out_processed.inc();
+ }
+ else
break;
- e.m_object->update_devs();
- m_perf_out_processed.inc();
}
mc_net.set_time(mc_time);
}
@@ -599,6 +568,21 @@ void netlist_t::print_stats() const
}
}
+core_device_t *netlist_t::pget_single_device(const pstring classname, bool (*cc)(core_device_t *))
+{
+ core_device_t *ret = nullptr;
+ for (auto &d : m_devices)
+ {
+ if (cc(d.get()))
+ {
+ if (ret != nullptr)
+ this->log().fatal(MF_1_MORE_THAN_ONE_1_DEVICE_FOUND, classname);
+ else
+ ret = d.get();
+ }
+ }
+ return ret;
+}
// ----------------------------------------------------------------------------------------
@@ -610,7 +594,7 @@ core_device_t::core_device_t(netlist_t &owner, const pstring &name)
, logic_family_t()
, netlist_ref(owner)
, m_hint_deactivate(false)
-#if (NL_PMF_TYPE > NL_PMF_TYPE_VIRTUAL)
+#if (!NL_USE_PMF_VIRTUAL)
, m_static_update()
#endif
{
@@ -623,7 +607,7 @@ core_device_t::core_device_t(core_device_t &owner, const pstring &name)
, logic_family_t()
, netlist_ref(owner.netlist())
, m_hint_deactivate(false)
-#if (NL_PMF_TYPE > NL_PMF_TYPE_VIRTUAL)
+#if (!NL_USE_PMF_VIRTUAL)
, m_static_update()
#endif
{
@@ -639,17 +623,16 @@ core_device_t::~core_device_t()
void core_device_t::set_delegate_pointer()
{
-#if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF)
- void (core_device_t::* pFunc)() = &core_device_t::update;
- m_static_update = pFunc;
-#elif (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV)
- void (core_device_t::* pFunc)() = &core_device_t::update;
- m_static_update = reinterpret_cast<net_update_delegate>((this->*pFunc));
-#elif (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL)
- m_static_update = plib::mfp::get_mfp<net_update_delegate>(&core_device_t::update, this);
+#if (!NL_USE_PMF_VIRTUAL)
+ m_static_update.set_base(&core_device_t::update, this);
#endif
}
+plib::plog_base<NL_DEBUG> &core_device_t::log()
+{
+ return netlist().log();
+}
+
// ----------------------------------------------------------------------------------------
// device_t
// ----------------------------------------------------------------------------------------
@@ -697,7 +680,7 @@ void device_t::connect(const pstring &t1, const pstring &t2)
void device_t::connect_post_start(detail::core_terminal_t &t1, detail::core_terminal_t &t2)
{
if (!setup().connect(t1, t2))
- netlist().log().fatal(MF_2_ERROR_CONNECTING_1_TO_2, t1.name(), t2.name());
+ log().fatal(MF_2_ERROR_CONNECTING_1_TO_2, t1.name(), t2.name());
}
@@ -705,9 +688,9 @@ void device_t::connect_post_start(detail::core_terminal_t &t1, detail::core_term
// family_setter_t
// -----------------------------------------------------------------------------
-detail::family_setter_t::family_setter_t(core_device_t &dev, const char *desc)
+detail::family_setter_t::family_setter_t(core_device_t &dev, const pstring desc)
{
- dev.set_logic_family(dev.netlist().family_from_model(desc));
+ dev.set_logic_family(dev.netlist().setup().family_from_model(desc));
}
detail::family_setter_t::family_setter_t(core_device_t &dev, const logic_family_desc_t *desc)
@@ -719,13 +702,6 @@ detail::family_setter_t::family_setter_t(core_device_t &dev, const logic_family_
// net_t
// ----------------------------------------------------------------------------------------
-// FIXME: move somewhere central
-
-struct do_nothing_deleter{
- template<typename T> void operator()(T*){}
-};
-
-
detail::net_t::net_t(netlist_t &nl, const pstring &aname, core_terminal_t *mr)
: object_t(aname)
, netlist_ref(nl)
@@ -734,10 +710,9 @@ detail::net_t::net_t(netlist_t &nl, const pstring &aname, core_terminal_t *mr)
, m_time(*this, "m_time", netlist_time::zero())
, m_active(*this, "m_active", 0)
, m_in_queue(*this, "m_in_queue", 2)
- , m_railterminal(nullptr)
, m_cur_Analog(*this, "m_cur_Analog", 0.0)
+ , m_railterminal(mr)
{
- m_railterminal = mr;
}
detail::net_t::~net_t()
@@ -758,7 +733,7 @@ void detail::net_t::inc_active(core_terminal_t &term) NL_NOEXCEPT
if (m_time > netlist().time())
{
m_in_queue = 1; /* pending */
- netlist().queue().push(this, m_time);
+ netlist().queue().push(queue_t::entry_t(m_time, this));
}
else
{
@@ -968,16 +943,20 @@ terminal_t::~terminal_t()
void terminal_t::schedule_solve()
{
- // FIXME: Remove this after we found a way to remove *ALL* twoterms connected to railnets only.
- if (net().solver() != nullptr)
- net().solver()->update_forced();
+ // Nets may belong to railnets which do not have a solver attached
+ // FIXME: Enforce that all terminals get connected?
+ if (this->has_net())
+ if (net().solver() != nullptr)
+ net().solver()->update_forced();
}
void terminal_t::schedule_after(const netlist_time &after)
{
- // FIXME: Remove this after we found a way to remove *ALL* twoterms connected to railnets only.
- if (net().solver() != nullptr)
- net().solver()->update_after(after);
+ // Nets may belong to railnets which do not have a solver attached
+ // FIXME: Enforce that all terminals get connected?
+ if (this->has_net())
+ if (net().solver() != nullptr)
+ net().solver()->update_after(after);
}
// ----------------------------------------------------------------------------------------
@@ -1037,7 +1016,7 @@ analog_output_t::analog_output_t(core_device_t &dev, const pstring &aname)
netlist().m_nets.push_back(plib::owned_ptr<analog_net_t>(&m_my_net, false));
this->set_net(&m_my_net);
- net().m_cur_Analog = NL_FCONST(0.0);
+ //net().m_cur_Analog = NL_FCONST(0.0);
netlist().setup().register_term(*this);
}
@@ -1047,7 +1026,7 @@ analog_output_t::~analog_output_t()
void analog_output_t::initial(const nl_double val)
{
- net().m_cur_Analog = val;
+ net().set_Q_Analog(val);
}
// -----------------------------------------------------------------------------
@@ -1133,11 +1112,11 @@ param_double_t::param_double_t(device_t &device, const pstring name, const doubl
m_param = device.setup().get_initial_param_val(this->name(),val);
netlist().save(*this, m_param, "m_param");
}
-
+#if 0
param_double_t::~param_double_t()
{
}
-
+#endif
param_int_t::param_int_t(device_t &device, const pstring name, const int val)
: param_t(device, name)
{
@@ -1145,9 +1124,11 @@ param_int_t::param_int_t(device_t &device, const pstring name, const int val)
netlist().save(*this, m_param, "m_param");
}
+#if 0
param_int_t::~param_int_t()
{
}
+#endif
param_logic_t::param_logic_t(device_t &device, const pstring name, const bool val)
: param_t(device, name)
@@ -1156,9 +1137,11 @@ param_logic_t::param_logic_t(device_t &device, const pstring name, const bool va
netlist().save(*this, m_param, "m_param");
}
+#if 0
param_logic_t::~param_logic_t()
{
}
+#endif
param_ptr_t::param_ptr_t(device_t &device, const pstring name, uint8_t * val)
: param_t(device, name)
@@ -1167,13 +1150,15 @@ param_ptr_t::param_ptr_t(device_t &device, const pstring name, uint8_t * val)
//netlist().save(*this, m_param, "m_param");
}
+#if 0
param_ptr_t::~param_ptr_t()
{
}
+#endif
void param_model_t::changed()
{
- netlist().log().fatal("Models can not be changed at runtime");
+ netlist().log().fatal(MF_1_MODEL_1_CAN_NOT_BE_CHANGED_AT_RUNTIME, name());
m_map.clear();
}
@@ -1200,8 +1185,6 @@ std::unique_ptr<plib::pistream> param_data_t::stream()
return device().netlist().setup().get_data_stream(Value());
}
-
-
namespace devices
{
// ----------------------------------------------------------------------------------------
diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h
index 171a81292ae..e56a10b9e20 100644
--- a/src/lib/netlist/nl_base.h
+++ b/src/lib/netlist/nl_base.h
@@ -9,27 +9,27 @@
#ifndef NLBASE_H_
#define NLBASE_H_
-#include <vector>
-#include <unordered_map>
-#include <memory>
-//#include <cmath>
-#include <cstdint>
-
#include "nl_lists.h"
#include "nl_time.h"
-#include "plib/palloc.h"
+#include "plib/palloc.h" // owned_ptr
#include "plib/pdynlib.h"
#include "plib/pstate.h"
#include "plib/pfmtlog.h"
#include "plib/pstream.h"
-#include "plib/pexception.h"
+#include "plib/ppmf.h"
+
+#include <unordered_map>
+
+#ifdef NL_PROHIBIT_BASEH_INCLUDE
+#error "nl_base.h included. Please correct."
+#endif
// ----------------------------------------------------------------------------------------
// Type definitions
// ----------------------------------------------------------------------------------------
/*! netlist_sig_t is the type used for logic signals. */
-using netlist_sig_t = std::uint_least32_t;
+using netlist_sig_t = std::uint32_t;
//============================================================
// MACROS / New Syntax
@@ -85,18 +85,26 @@ class NETLIB_NAME(name) : public device_t
: device_t(owner, name)
/*! Add this to a device definition to mark the device as dynamic.
- * If this is added to device definition the device is treated as an analog
- * dynamic device, i.e. #NETLIB_UPDATE_TERMINALSI is called on a each step
- * of the Newton-Raphson step of solving the linear equations.
+ * If NETLIB_IS_DYNAMIC(true) is added to the device definition the device
+ * is treated as an analog dynamic device, i.e. #NETLIB_UPDATE_TERMINALSI
+ * is called on a each step of the Newton-Raphson step
+ * of solving the linear equations.
+ *
+ * You may also use e.g. NETLIB_IS_DYNAMIC(m_func() != "") to only make the
+ * device a dynamic device if parameter m_func is set.
*/
-#define NETLIB_IS_DYNAMIC() \
- public: virtual bool is_dynamic() const override { return true; }
+#define NETLIB_IS_DYNAMIC(expr) \
+ public: virtual bool is_dynamic() const override { return expr; }
/*! Add this to a device definition to mark the device as a time-stepping device.
- *
+ *
* You have to implement NETLIB_TIMESTEP in this case as well. Currently, only
* the capacitor and inductor devices uses this.
*
+ * You may also use e.g. NETLIB_IS_TIMESTEP(m_func() != "") to only make the
+ * device a dynamic device if parameter m_func is set. This is used by the
+ * Voltage Source element.
+ *
* Example:
*
* NETLIB_TIMESTEP_IS_TIMESTEP()
@@ -109,8 +117,8 @@ class NETLIB_NAME(name) : public device_t
* }
*
*/
-#define NETLIB_IS_TIMESTEP() \
- public: virtual bool is_timestep() const override { return true; }
+#define NETLIB_IS_TIMESTEP(expr) \
+ public: virtual bool is_timestep() const override { return expr; }
/*! Used to implement the time stepping code.
*
@@ -220,11 +228,6 @@ namespace netlist
class core_device_t;
class device_t;
- /*! Type of the model map used.
- * This is used to hold all #Models in an unordered map
- */
- using model_map_t = std::unordered_map<pstring, pstring>;
-
/*! Logic families descriptors are used to create proxy devices.
* The logic family describes the analog capabilities of logic devices,
* inputs and outputs.
@@ -248,7 +251,7 @@ namespace netlist
double R_low() const { return m_R_low; }
double R_high() const { return m_R_high; }
- double m_fixed_V; //!< For variable voltage families, specify 0. For TTL this would be 5. */
+ double m_fixed_V; //!< For variable voltage families, specify 0. For TTL this would be 5. */
double m_low_thresh_PCNT; //!< low input threshhold offset. If the input voltage is below this value times supply voltage, a "0" input is signalled
double m_high_thresh_PCNT; //!< high input threshhold offset. If the input voltage is above the value times supply voltage, a "0" input is signalled
double m_low_VO; //!< low output voltage offset. This voltage is output if the ouput is "0"
@@ -273,12 +276,12 @@ namespace netlist
public:
logic_family_t() : m_logic_family(nullptr) {}
- ~logic_family_t() { }
const logic_family_desc_t *logic_family() const { return m_logic_family; }
void set_logic_family(const logic_family_desc_t *fam) { m_logic_family = fam; }
protected:
+ ~logic_family_t() { } // prohibit polymorphic destruction
const logic_family_desc_t *m_logic_family;
};
@@ -313,19 +316,15 @@ namespace netlist
//! Move Constructor.
state_var(state_var &&rhs) NL_NOEXCEPT = default;
//! Assignment operator to assign value of a state var.
- state_var &operator=(state_var rhs) { std::swap(rhs.m_value, this->m_value); return *this; }
+ state_var &operator=(const state_var &rhs) { m_value = rhs; return *this; }
//! Assignment operator to assign value of type T.
- state_var &operator=(const T rhs) { m_value = rhs; return *this; }
+ state_var &operator=(const T &rhs) { m_value = rhs; return *this; }
//! Return value of state variable.
operator T & () { return m_value; }
- //! Return value of state variable.
- T & operator()() { return m_value; }
//! Return const value of state variable.
- operator const T & () const { return m_value; }
- //! Return const value of state variable.
- const T & operator()() const { return m_value; }
+ constexpr operator const T & () const { return m_value; }
T * ptr() { return &m_value; }
- const T * ptr() const { return &m_value; }
+ constexpr T * ptr() const { return &m_value; }
private:
T m_value;
};
@@ -338,13 +337,20 @@ namespace netlist
struct state_var<T[N]>
{
public:
- state_var(device_t &dev, const pstring name, const T & value);
+ //! Constructor.
+ template <typename O>
+ state_var(O &owner, //!< owner must have a netlist() method.
+ const pstring name, //!< identifier/name for this state variable
+ const T &value //!< Initial value after construction
+ );
+ //! Copy Constructor.
state_var(const state_var &rhs) NL_NOEXCEPT = default;
+ //! Move Constructor.
state_var(state_var &&rhs) NL_NOEXCEPT = default;
- state_var &operator=(const state_var rhs) { m_value = rhs.m_value; return *this; }
- state_var &operator=(const T rhs) { m_value = rhs; return *this; }
+ state_var &operator=(const state_var &rhs) { m_value = rhs.m_value; return *this; }
+ state_var &operator=(const T &rhs) { m_value = rhs; return *this; }
T & operator[](const std::size_t i) { return m_value[i]; }
- const T & operator[](const std::size_t i) const { return m_value[i]; }
+ constexpr T & operator[](const std::size_t i) const { return m_value[i]; }
private:
T m_value[N];
};
@@ -376,7 +382,6 @@ namespace netlist
*/
class detail::object_t
{
- P_PREVENT_COPYING(object_t)
public:
/*! Constructor.
@@ -384,7 +389,6 @@ namespace netlist
* Every class derived from the object_t class must have a name.
*/
object_t(const pstring &aname /*!< string containing name of the object */);
- virtual ~object_t();
/*! return name of the object
*
@@ -396,6 +400,8 @@ namespace netlist
void operator delete (void *ptr, void *) { }
void * operator new (size_t size);
void operator delete (void * mem);
+ protected:
+ ~object_t(); // only childs should be destructible
private:
pstring m_name;
@@ -404,11 +410,13 @@ namespace netlist
struct detail::netlist_ref
{
netlist_ref(netlist_t &nl) : m_netlist(nl) { }
- ~netlist_ref() {}
netlist_t & netlist() { return m_netlist; }
const netlist_t & netlist() const { return m_netlist; }
+ protected:
+ ~netlist_ref() {} // prohibit polymorphic destruction
+
private:
netlist_t & m_netlist;
@@ -425,16 +433,7 @@ namespace netlist
*/
class detail::device_object_t : public detail::object_t
{
- P_PREVENT_COPYING(device_object_t)
public:
- /*! Enum specifying the type of object */
- enum type_t {
- TERMINAL = 0, /*!< object is an analog terminal */
- INPUT = 1, /*!< object is an input */
- OUTPUT = 2, /*!< object is an output */
- PARAM = 3, /*!< object is a parameter */
- };
-
/*! Constructor.
*
* \param dev device owning the object.
@@ -446,16 +445,6 @@ namespace netlist
*/
core_device_t &device() const { return m_device; }
- /*! The object type.
- * \returns type of the object
- */
- type_t type() const;
- /*! Checks if object is of specified type.
- * \param atype type to check object against.
- * \returns true if object is of specified type else false.
- */
- bool is_type(const type_t atype) const { return (type() == atype); }
-
/*! The netlist owning the owner of this object.
* \returns reference to netlist object.
*/
@@ -478,7 +467,6 @@ namespace netlist
*/
class detail::core_terminal_t : public device_object_t, public plib::linkedlist_t<core_terminal_t>::element_t
{
- P_PREVENT_COPYING(core_terminal_t)
public:
using list_t = std::vector<core_terminal_t *>;
@@ -495,6 +483,16 @@ namespace netlist
core_terminal_t(core_device_t &dev, const pstring &aname, const state_e state);
virtual ~core_terminal_t();
+ /*! The object type.
+ * \returns type of the object
+ */
+ terminal_type type() const;
+ /*! Checks if object is of specified type.
+ * \param atype type to check object against.
+ * \returns true if object is of specified type else false.
+ */
+ bool is_type(const terminal_type atype) const { return (type() == atype); }
+
void set_net(net_t *anet);
void clear_net();
bool has_net() const { return (m_net != nullptr); }
@@ -540,7 +538,6 @@ namespace netlist
class terminal_t : public analog_t
{
- P_PREVENT_COPYING(terminal_t)
public:
terminal_t(core_device_t &dev, const pstring &aname);
@@ -550,16 +547,12 @@ namespace netlist
void set(const nl_double G)
{
- set_ptr(m_Idr1, 0);
- set_ptr(m_go1, G);
- set_ptr(m_gt1, G);
+ set(G,G, 0.0);
}
void set(const nl_double GO, const nl_double GT)
{
- set_ptr(m_Idr1, 0);
- set_ptr(m_go1, GO);
- set_ptr(m_gt1, GT);
+ set(GO, GT, 0.0);
}
void set(const nl_double GO, const nl_double GT, const nl_double I)
@@ -690,7 +683,6 @@ namespace netlist
public detail::object_t,
public detail::netlist_ref
{
- P_PREVENT_COPYING(net_t)
public:
net_t(netlist_t &nl, const pstring &aname, core_terminal_t *mr = nullptr);
@@ -698,12 +690,6 @@ namespace netlist
void reset();
- void add_terminal(core_terminal_t &terminal);
- void remove_terminal(core_terminal_t &terminal);
-
- bool is_logic() const NL_NOEXCEPT;
- bool is_analog() const NL_NOEXCEPT;
-
void toggle_new_Q() { m_new_Q ^= 1; }
void force_queue_execution() { m_new_Q = (m_cur_Q ^ 1); }
@@ -724,6 +710,14 @@ namespace netlist
void inc_active(core_terminal_t &term) NL_NOEXCEPT;
void dec_active(core_terminal_t &term) NL_NOEXCEPT;
+ /* setup stuff */
+
+ void add_terminal(core_terminal_t &terminal);
+ void remove_terminal(core_terminal_t &terminal);
+
+ bool is_logic() const NL_NOEXCEPT;
+ bool is_analog() const NL_NOEXCEPT;
+
void rebuild_list(); /* rebuild m_list after a load */
void move_connections(net_t &dest_net);
@@ -737,26 +731,25 @@ namespace netlist
state_var_s32 m_active;
state_var_u8 m_in_queue; /* 0: not in queue, 1: in queue, 2: last was taken */
+ state_var<nl_double> m_cur_Analog;
+
private:
plib::linkedlist_t<core_terminal_t> m_list_active;
core_terminal_t * m_railterminal;
public:
- // FIXME: Have to fix the public at some time
- state_var<nl_double> m_cur_Analog;
};
class logic_net_t : public detail::net_t
{
- P_PREVENT_COPYING(logic_net_t)
public:
logic_net_t(netlist_t &nl, const pstring &aname, detail::core_terminal_t *mr = nullptr);
virtual ~logic_net_t();
netlist_sig_t Q() const { return m_cur_Q; }
- netlist_sig_t new_Q() const { return m_new_Q; }
+ netlist_sig_t new_Q() const { return m_new_Q; }
void initial(const netlist_sig_t val) { m_cur_Q = m_new_Q = val; }
void set_Q(const netlist_sig_t newQ, const netlist_time delay) NL_NOEXCEPT
@@ -781,7 +774,7 @@ namespace netlist
/* internal state support
* FIXME: get rid of this and implement export/import in MAME
*/
- netlist_sig_t &Q_state_ptr() { return m_cur_Q; }
+ netlist_sig_t *Q_state_ptr() { return m_cur_Q.ptr(); }
protected:
private:
@@ -790,7 +783,6 @@ namespace netlist
class analog_net_t : public detail::net_t
{
- P_PREVENT_COPYING(analog_net_t)
public:
using list_t = std::vector<analog_net_t *>;
@@ -800,7 +792,8 @@ namespace netlist
virtual ~analog_net_t();
nl_double Q_Analog() const { return m_cur_Analog; }
- nl_double &Q_Analog_state_ptr() { return m_cur_Analog; }
+ void set_Q_Analog(const nl_double &v) { m_cur_Analog = v; }
+ nl_double *Q_Analog_state_ptr() { return m_cur_Analog.ptr(); }
//FIXME: needed by current solver code
devices::matrix_solver_t *solver() const { return m_solver; }
@@ -816,7 +809,6 @@ namespace netlist
class logic_output_t : public logic_t
{
- P_PREVENT_COPYING(logic_output_t)
public:
logic_output_t(core_device_t &dev, const pstring &aname);
@@ -835,7 +827,6 @@ namespace netlist
class analog_output_t : public analog_t
{
- P_PREVENT_COPYING(analog_output_t)
public:
analog_output_t(core_device_t &dev, const pstring &aname);
virtual ~analog_output_t();
@@ -854,7 +845,6 @@ namespace netlist
class param_t : public detail::device_object_t
{
- P_PREVENT_COPYING(param_t)
public:
enum param_type_t {
@@ -866,11 +856,12 @@ namespace netlist
};
param_t(device_t &device, const pstring &name);
- virtual ~param_t();
param_type_t param_type() const;
protected:
+ virtual ~param_t(); /* not intended to be destroyed */
+
void update_param();
template<typename C>
@@ -889,7 +880,6 @@ namespace netlist
{
public:
param_ptr_t(device_t &device, const pstring name, std::uint8_t* val);
- virtual ~param_ptr_t();
std::uint8_t * operator()() const { return m_param; }
void setTo(std::uint8_t *param) { set(m_param, param); }
private:
@@ -900,7 +890,6 @@ namespace netlist
{
public:
param_logic_t(device_t &device, const pstring name, const bool val);
- virtual ~param_logic_t();
bool operator()() const { return m_param; }
void setTo(const bool &param) { set(m_param, param); }
private:
@@ -911,7 +900,6 @@ namespace netlist
{
public:
param_int_t(device_t &device, const pstring name, const int val);
- virtual ~param_int_t();
int operator()() const { return m_param; }
void setTo(const int &param) { set(m_param, param); }
private:
@@ -922,7 +910,6 @@ namespace netlist
{
public:
param_double_t(device_t &device, const pstring name, const double val);
- virtual ~param_double_t();
double operator()() const { return m_param; }
void setTo(const double &param) { set(m_param, param); }
private:
@@ -934,6 +921,7 @@ namespace netlist
public:
param_str_t(device_t &device, const pstring name, const pstring val);
virtual ~param_str_t();
+
const pstring operator()() const { return Value(); }
void setTo(const pstring &param)
{
@@ -981,8 +969,8 @@ namespace netlist
private:
/* hide this */
void setTo(const pstring &param) = delete;
- model_map_t m_map;
- };
+ detail::model_map_t m_map;
+};
class param_data_t : public param_str_t
@@ -996,6 +984,28 @@ namespace netlist
};
// -----------------------------------------------------------------------------
+ // rom parameter
+ // -----------------------------------------------------------------------------
+
+ template <typename ST, std::size_t AW, std::size_t DW>
+ class param_rom_t final: public param_data_t
+ {
+ public:
+
+ param_rom_t(device_t &device, const pstring name);
+
+ const ST & operator[] (std::size_t n) { return m_data[n]; }
+ protected:
+ virtual void changed() override
+ {
+ stream()->read(&m_data[0],1<<AW);
+ }
+
+ private:
+ ST m_data[1 << AW];
+ };
+
+ // -----------------------------------------------------------------------------
// core_device_t
// -----------------------------------------------------------------------------
@@ -1004,7 +1014,6 @@ namespace netlist
public logic_family_t,
public detail::netlist_ref
{
- P_PREVENT_COPYING(core_device_t)
public:
core_device_t(netlist_t &owner, const pstring &name);
core_device_t(core_device_t &owner, const pstring &name);
@@ -1052,15 +1061,15 @@ namespace netlist
void do_update() NL_NOEXCEPT
{
- #if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF)
- (this->*m_static_update)();
- #elif ((NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV) || (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL))
- m_static_update(this);
+ #if (NL_USE_PMF_VIRTUAL)
+ update();
#else
- update();
+ m_static_update.call(this);
#endif
}
+ plib::plog_base<NL_DEBUG> &log();
+
public:
virtual void timestep(ATTR_UNUSED const nl_double st) { }
virtual void update_terminals() { }
@@ -1072,14 +1081,9 @@ namespace netlist
private:
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))
- using net_update_delegate = MEMBER_ABI void (*)(core_device_t *);
- #endif
- #if (NL_PMF_TYPE > NL_PMF_TYPE_VIRTUAL)
- net_update_delegate m_static_update;
+ #if (!NL_USE_PMF_VIRTUAL)
+ plib::pmfp_base<void> m_static_update;
#endif
};
@@ -1089,7 +1093,6 @@ namespace netlist
class device_t : public core_device_t
{
- P_PREVENT_COPYING(device_t)
public:
template <class C>
@@ -1103,7 +1106,7 @@ namespace netlist
template<class C, typename... Args>
void register_sub(const pstring &name, std::unique_ptr<C> &dev, const Args&... args)
{
- dev.reset(new C(*this, name, args...));
+ dev.reset(plib::palloc<C>(*this, name, args...));
}
void register_subalias(const pstring &name, detail::core_terminal_t &term);
@@ -1127,7 +1130,7 @@ namespace netlist
struct detail::family_setter_t
{
family_setter_t() { }
- family_setter_t(core_device_t &dev, const char *desc);
+ family_setter_t(core_device_t &dev, const pstring desc);
family_setter_t(core_device_t &dev, const logic_family_desc_t *desc);
};
@@ -1171,9 +1174,8 @@ namespace netlist
// -----------------------------------------------------------------------------
- class netlist_t : public plib::plog_dispatch_intf
+ class netlist_t : public plib::plog_dispatch_intf, private plib::nocopyassignmove
{
- P_PREVENT_COPYING(netlist_t)
public:
explicit netlist_t(const pstring &aname);
@@ -1207,7 +1209,6 @@ namespace netlist
void remove_dev(core_device_t *dev);
detail::net_t *find_net(const pstring &name);
- const logic_family_desc_t *family_from_model(const pstring &model);
template<class device_class>
std::vector<device_class *> get_device_list()
@@ -1222,22 +1223,16 @@ namespace netlist
return tmp;
}
- template<class device_class>
- device_class *get_single_device(const char *classname)
+ template<class C>
+ static bool check_class(core_device_t *p)
{
- device_class *ret = nullptr;
- for (auto &d : m_devices)
- {
- device_class *dev = dynamic_cast<device_class *>(d.get());
- if (dev != nullptr)
- {
- if (ret != nullptr)
- this->log().fatal("more than one {1} device found", classname);
- else
- ret = dev;
- }
- }
- return ret;
+ return dynamic_cast<C *>(p) != nullptr;
+ }
+
+ template<class C>
+ C *get_single_device(const pstring classname)
+ {
+ return dynamic_cast<C *>(pget_single_device(classname, check_class<C>));
}
/* logging and name */
@@ -1252,24 +1247,34 @@ namespace netlist
template<typename O, typename C> void save(O &owner, C &state, const pstring &stname)
{
- this->state().save_item(static_cast<void *>(&owner), state, owner.name() + pstring(".") + stname);
+ this->state().save_item(static_cast<void *>(&owner), state, from_utf8(owner.name()) + pstring(".") + stname);
}
template<typename O, typename C> void save(O &owner, C *state, const pstring &stname, const std::size_t count)
{
- this->state().save_state_ptr(static_cast<void *>(&owner), owner.name() + pstring(".") + stname, plib::state_manager_t::datatype_f<C>::f(), count, state);
+ this->state().save_state_ptr(static_cast<void *>(&owner), from_utf8(owner.name()) + pstring(".") + stname, plib::state_manager_t::datatype_f<C>::f(), count, state);
}
void rebuild_lists(); /* must be called after post_load ! */
plib::dynlib &lib() { return *m_lib; }
+ // FIXME: find something better
/* sole use is to manage lifetime of net objects */
std::vector<plib::owned_ptr<detail::net_t>> m_nets;
+ /* 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:
void print_stats() const;
private:
+
+ /* helper for save above */
+ static pstring from_utf8(const char *c) { return pstring(c, pstring::UTF8); }
+ static pstring from_utf8(const pstring &c) { return c; }
+
+ core_device_t *pget_single_device(const pstring classname, bool (*cc)(core_device_t *));
+
/* mostly rw */
netlist_time m_time;
detail::queue_t m_queue;
@@ -1281,21 +1286,17 @@ namespace netlist
devices::NETLIB_NAME(netlistparams) *m_params;
pstring m_name;
- setup_t * m_setup;
+ std::unique_ptr<setup_t> m_setup;
plib::plog_base<NL_DEBUG> m_log;
- plib::dynlib * m_lib; // external lib needs to be loaded as long as netlist exists
+ std::unique_ptr<plib::dynlib> m_lib; // external lib needs to be loaded as long as netlist exists
plib::state_manager_t m_state;
// performance
nperftime_t m_stat_mainloop;
nperfcount_t m_perf_out_processed;
- nperfcount_t m_perf_inp_processed;
- nperfcount_t m_perf_inp_active;
std::vector<plib::owned_ptr<core_device_t>> m_devices;
- /* sole use is to manage lifetime of family objects */
- std::vector<std::pair<pstring, std::unique_ptr<logic_family_desc_t>>> m_family_cache;
};
// -----------------------------------------------------------------------------
@@ -1313,43 +1314,24 @@ namespace netlist
object_array_t(core_device_t &dev, init names)
{
for (std::size_t i = 0; i<N; i++)
- this->emplace(i, dev, names.p[i]);
+ this->emplace(i, dev, pstring(names.p[i], pstring::UTF8));
}
};
// -----------------------------------------------------------------------------
- // rom parameter
+ // inline implementations
// -----------------------------------------------------------------------------
template <typename ST, std::size_t AW, std::size_t DW>
- class param_rom_t final: public param_data_t
+ inline param_rom_t<ST, AW, DW>::param_rom_t(device_t &device, const pstring name)
+ : param_data_t(device, name)
{
- public:
-
- param_rom_t(device_t &device, const pstring name)
- : param_data_t(device, name)
- {
- auto f = stream();
- if (f != nullptr)
- f->read(&m_data[0],1<<AW);
- else
- device.netlist().log().warning("Rom {1} not found", Value());
- }
-
- const ST & operator[] (std::size_t n) { return m_data[n]; }
-
- protected:
- virtual void changed() override
- {
- stream()->read(&m_data[0],1<<AW);
- }
- private:
- ST m_data[1 << AW];
- };
-
- // -----------------------------------------------------------------------------
- // inline implementations
- // -----------------------------------------------------------------------------
+ auto f = stream();
+ if (f != nullptr)
+ f->read(&m_data[0],1<<AW);
+ else
+ device.netlist().log().warning("Rom {1} not found", Value());
+ }
inline bool detail::core_terminal_t::is_logic() const NL_NOEXCEPT
{
@@ -1414,7 +1396,7 @@ namespace netlist
m_time = netlist().time() + delay;
m_in_queue = (m_active > 0); /* queued ? */
if (m_in_queue)
- netlist().queue().push(this, m_time);
+ netlist().queue().push(queue_t::entry_t(m_time, this));
}
}
@@ -1426,7 +1408,7 @@ namespace netlist
m_time = netlist().time() + delay;
m_in_queue = (m_active > 0); /* queued ? */
if (m_in_queue)
- netlist().queue().push(this, m_time);
+ netlist().queue().push(queue_t::entry_t(m_time, this));
}
inline const analog_net_t & analog_t::net() const NL_NOEXCEPT
@@ -1443,7 +1425,7 @@ namespace netlist
inline logic_net_t & logic_t::net() NL_NOEXCEPT
{
- return *static_cast<logic_net_t *>(&core_terminal_t::net());
+ return static_cast<logic_net_t &>(core_terminal_t::net());
}
inline const logic_net_t & logic_t::net() const NL_NOEXCEPT
@@ -1465,7 +1447,7 @@ namespace netlist
{
if (newQ != m_my_net.Q_Analog())
{
- m_my_net.m_cur_Analog = newQ;
+ m_my_net.set_Q_Analog(newQ);
m_my_net.toggle_new_Q();
m_my_net.push_to_queue(NLTIME_FROM_NS(1));
}
@@ -1480,9 +1462,10 @@ namespace netlist
}
template <typename T, std::size_t N>
- state_var<T[N]>::state_var(device_t &dev, const pstring name, const T & value)
+ template <typename O>
+ state_var<T[N]>::state_var(O &owner, const pstring name, const T & value)
{
- dev.netlist().save(dev, m_value, name);
+ owner.netlist().save(owner, m_value, name);
for (std::size_t i=0; i<N; i++)
m_value[i] = value;
}
@@ -1499,5 +1482,14 @@ namespace netlist
}
+namespace plib
+{
+ template<typename X>
+ struct ptype_traits<netlist::state_var<X>> : ptype_traits<X>
+ {
+ };
+}
+
+
#endif /* NLBASE_H_ */
diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h
index 88f240394be..ded567717f9 100644
--- a/src/lib/netlist/nl_config.h
+++ b/src/lib/netlist/nl_config.h
@@ -9,68 +9,12 @@
#ifndef NLCONFIG_H_
#define NLCONFIG_H_
-#include <cstdint>
-
#include "plib/pconfig.h"
-#include "plib/pchrono.h"
//============================================================
// SETUP
//============================================================
-/*
- * The following options determine how object::update is called.
- * NL_PMF_TYPE_VIRTUAL
- * Use stock virtual call
- *
- * NL_PMF_TYPE_GNUC_PMF
- * Use standard pointer to member function syntax
- *
- * NL_PMF_TYPE_GNUC_PMF_CONV
- * Use gnu extension and convert the pmf to a function pointer.
- * This is not standard compliant and needs
- * -Wno-pmf-conversions to compile.
- *
- * NL_PMF_TYPE_INTERNAL
- * Use the same approach as MAME for deriving the function pointer.
- * This is compiler-dependant as well
- *
- * Benchmarks for ./nltool -c run -f src/mame/drivers/nl_pong.c -t 10 -n pong_fast
- *
- * NL_PMF_TYPE_INTERNAL: 215%
- * NL_PMF_TYPE_GNUC_PMF: 163%
- * NL_PMF_TYPE_GNUC_PMF_CONV: 215%
- * NL_PMF_TYPE_VIRTUAL: 213%
- *
- * The whole exercise was done to avoid virtual calls. In prior versions of
- * netlist, the INTERNAL and GNUC_PMF_CONV approach provided significant improvement.
- * Since than, was removed from functions declared as virtual.
- * This may explain that the recent benchmarks show no difference at all.
- *
- * Disappointing is the GNUC_PMF performance.
- */
-
-// This will be autodetected
-// #define NL_PMF_TYPE 0
-
-#define NL_PMF_TYPE_VIRTUAL 0
-#define NL_PMF_TYPE_GNUC_PMF 1
-#define NL_PMF_TYPE_GNUC_PMF_CONV 2
-#define NL_PMF_TYPE_INTERNAL 3
-
-#ifndef NL_PMF_TYPE
- #if PHAS_PMF_INTERNAL
- #define NL_PMF_TYPE NL_PMF_TYPE_INTERNAL
- #else
- #define NL_PMF_TYPE NL_PMF_TYPE_VIRTUAL
- #endif
-#endif
-
-#if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV)
-#pragma GCC diagnostic ignored "-Wpmf-conversions"
-#endif
-
-
//============================================================
// GENERAL
@@ -86,8 +30,12 @@
*
*/
#define USE_MEMPOOL (0)
+
#define USE_TRUTHTABLE (1)
+// How many times do we try to resolve links (connections)
+#define NL_MAX_LINK_RESOLVE_LOOPS (100)
+
//============================================================
// Solver defines
//============================================================
@@ -120,20 +68,6 @@
#endif
//============================================================
-// Performance tracking
-//============================================================
-
-namespace netlist
-{
-#if NL_KEEP_STATISTICS
-using nperftime_t = plib::chrono::timer<plib::chrono::exact_ticks, true>;
-using nperfcount_t = plib::chrono::counter<true>;
-#else
-using nperftime_t = plib::chrono::timer<plib::chrono::exact_ticks, false>;
-using nperfcount_t = plib::chrono::counter<false>;
-#endif
-}
-//============================================================
// General
//============================================================
@@ -156,6 +90,20 @@ using nperfcount_t = plib::chrono::counter<false>;
#define NL_FCONST(x) x
using nl_double = double;
+/* The following option determines how object::update is called.
+ * If set to 1, a virtual call is used. If it is left undefined, the best
+ * approach will be automatically selected.
+ */
+
+//#define NL_USE_PMF_VIRTUAL 1
+
+#ifndef NL_USE_PMF_VIRTUAL
+ #if PPMF_TYPE == PPMF_TYPE_PMF
+ #define NL_USE_PMF_VIRTUAL 1
+ #else
+ #define NL_USE_PMF_VIRTUAL 0
+ #endif
+#endif
//============================================================
// WARNINGS
diff --git a/src/lib/netlist/nl_dice_compat.h b/src/lib/netlist/nl_dice_compat.h
index 209f18d82af..b0ebdb2e371 100644
--- a/src/lib/netlist/nl_dice_compat.h
+++ b/src/lib/netlist/nl_dice_compat.h
@@ -27,8 +27,11 @@ sed -e 's/#define \(.*\)"\(.*\)"[ \t]*,[ \t]*\(.*\)/NET_ALIAS(\1,\2.\3)/' src/ma
#ifndef NL_CONVERT_CPP
#include "devices/net_lib.h"
#include "analog/nld_twoterm.h"
+
+#include <cmath>
#endif
+
/* --------------------------------------------------------------------
* Compatibility macros for DICE netlists ...
* -------------------------------------------------------------------- */
diff --git a/src/lib/netlist/nl_errstr.h b/src/lib/netlist/nl_errstr.h
index 563e33dd93f..ec52187558f 100644
--- a/src/lib/netlist/nl_errstr.h
+++ b/src/lib/netlist/nl_errstr.h
@@ -11,18 +11,92 @@
// nl_base.cpp
-#define MF_1_DUPLICATE_NAME_DEVICE_LIST "Error adding {1} to device list. Duplicate name."
-#define MF_1_UNKNOWN_TYPE_FOR_OBJECT "Unknown type for object {1} "
-#define MF_2_NET_1_DUPLICATE_TERMINAL_2 "net {1}: duplicate terminal {2}"
-#define MF_2_REMOVE_TERMINAL_1_FROM_NET_2 "Can not remove terminal {1} from net {2}."
-#define MF_1_UNKNOWN_PARAM_TYPE "Can not determine param_type for {1}"
-#define MF_2_ERROR_CONNECTING_1_TO_2 "Error connecting {1} to {2}"
-#define MF_0_NO_SOLVER "No solver found for this netlist although analog elements are present\n"
+#define MF_1_DUPLICATE_NAME_DEVICE_LIST "Error adding {1} to device list. Duplicate name."
+#define MF_1_UNKNOWN_TYPE_FOR_OBJECT "Unknown type for object {1} "
+#define MF_2_NET_1_DUPLICATE_TERMINAL_2 "net {1}: duplicate terminal {2}"
+#define MF_2_REMOVE_TERMINAL_1_FROM_NET_2 "Can not remove terminal {1} from net {2}."
+#define MF_1_UNKNOWN_PARAM_TYPE "Can not determine param_type for {1}"
+#define MF_2_ERROR_CONNECTING_1_TO_2 "Error connecting {1} to {2}"
+#define MF_0_NO_SOLVER "No solver found for this netlist although analog elements are present"
+#define MF_1_HND_VAL_NOT_SUPPORTED "HINT_NO_DEACTIVATE value not supported: <{1}>"
// nl_factory.cpp
-#define MF_1_FACTORY_ALREADY_CONTAINS_1 "factory already contains {1}"
+#define MF_1_FACTORY_ALREADY_CONTAINS_1 "factory already contains {1}"
#define MF_1_CLASS_1_NOT_FOUND "Class <{1}> not found!"
+// nld_opamps.cpp
-#endif /* NLBASE_H_ */
+#define MF_1_UNKNOWN_OPAMP_TYPE "Unknown opamp type: {1}"
+
+// nld_matrix_solver.cpp
+
+#define MF_1_UNHANDLED_ELEMENT_1_FOUND "setup_base:unhandled element <{1}> found"
+#define MF_1_FOUND_TERM_WITH_MISSING_OTHERNET "found term with missing othernet {1}"
+
+#define MW_1_NEWTON_LOOPS_EXCEEDED_ON_NET_1 "NEWTON_LOOPS exceeded on net {1}... reschedule"
+
+// nld_solver.cpp
+
+#define MF_1_UNKNOWN_SOLVER_TYPE "Unknown solver type: {1}"
+#define MF_1_NETGROUP_SIZE_EXCEEDED_1 "Encountered netgroup with > {1} nets"
+
+#define MW_1_NO_SPECIFIC_SOLVER "No specific solver found for netlist of size {1}"
+
+// nl_base.cpp
+
+#define MF_1_MODEL_1_CAN_NOT_BE_CHANGED_AT_RUNTIME "Model {1} can not be changed at runtime"
+#define MF_1_MORE_THAN_ONE_1_DEVICE_FOUND "more than one {1} device found"
+
+// nl_parser.cpp
+
+#define MF_0_UNEXPECTED_NETLIST_END "Unexpected NETLIST_END"
+#define MF_0_UNEXPECTED_NETLIST_START "Unexpected NETLIST_START"
+
+// nl_setup.cpp
+
+//#define MF_1_CLASS_1_NOT_FOUND "Class {1} not found!"
+#define MF_1_UNABLE_TO_PARSE_MODEL_1 "Unable to parse model: {1}"
+#define MF_1_MODEL_ALREADY_EXISTS_1 "Model already exists: {1}"
+#define MF_1_ADDING_ALIAS_1_TO_ALIAS_LIST "Error adding alias {1} to alias list"
+#define MF_1_DIP_PINS_MUST_BE_AN_EQUAL_NUMBER_OF_PINS_1 "You must pass an equal number of pins to DIPPINS {1}"
+#define MF_1_UNKNOWN_OBJECT_TYPE_1 "Unknown object type {1}"
+#define MF_2_INVALID_NUMBER_CONVERSION_1_2 "Invalid number conversion {1} : {2}"
+#define MF_1_ADDING_PARAMETER_1_TO_PARAMETER_LIST "Error adding parameter {1} to parameter list"
+#define MF_2_ADDING_1_2_TO_TERMINAL_LIST "Error adding {1} {2} to terminal list"
+#define MF_2_NET_C_NEEDS_AT_LEAST_2_TERMINAL "You must pass at least 2 terminals to NET_C"
+#define MF_1_FOUND_NO_OCCURRENCE_OF_1 "Found no occurrence of {1}"
+#define MF_2_TERMINAL_1_2_NOT_FOUND "Alias {1} was resolved to be terminal {2}. Terminal {2} was not found."
+#define MF_2_OBJECT_1_2_WRONG_TYPE "object {1}({2}) found but wrong type"
+#define MF_2_PARAMETER_1_2_NOT_FOUND "parameter {1}({2}) not found!"
+#define MF_2_CONNECTING_1_TO_2 "Error connecting {1} to {2}"
+#define MF_2_MERGE_RAIL_NETS_1_AND_2 "Trying to merge two rail nets: {1} and {2}"
+#define MF_1_OBJECT_INPUT_TYPE_1 "Unable to determine input type of {1}"
+#define MF_1_OBJECT_OUTPUT_TYPE_1 "Unable to determine output type of {1}"
+#define MF_1_INPUT_1_ALREADY_CONNECTED "Input {1} already connected"
+#define MF_0_LINK_TRIES_EXCEEDED "Error connecting -- bailing out"
+#define MF_1_MODEL_NOT_FOUND "Model {1} not found"
+#define MF_1_MODEL_ERROR_1 "Model error {1}"
+#define MF_1_MODEL_ERROR_ON_PAIR_1 "Model error on pair {1}"
+#define MF_2_MODEL_PARAMETERS_NOT_UPPERCASE_1_2 "model parameters should be uppercase:{1} {2}"
+#define MF_2_ENTITY_1_NOT_FOUND_IN_MODEL_2 "Entity {1} not found in model {2}"
+#define MF_1_UNKNOWN_NUMBER_FACTOR_IN_1 "Unknown number factor in: {1}"
+#define MF_1_NOT_FOUND_IN_SOURCE_COLLECTION "unable to find {1} in source collection"
+
+#define MW_3_OVERWRITING_PARAM_1_OLD_2_NEW_3 "Overwriting {1} old <{2}> new <{3}>"
+#define MW_1_CONNECTING_1_TO_ITSELF "Connecting {1} to itself. This may be right, though"
+#define MW_1_DUMMY_1_WITHOUT_CONNECTIONS "Found dummy terminal {1} without connections"
+#define MW_1_TERMINAL_1_WITHOUT_CONNECTIONS "Found terminal {1} without connections"
+#define MW_3_REMOVE_DEVICE_1_CONNECTED_ONLY_TO_RAILS_2_3 "Found device {1} connected only to railterminals {2}/{3}. Will be removed"
+#define MW_1_DATA_1_NOT_FOUND "unable to find data named {1} in source collection"
+
+// nld_mm5837.cpp
+
+#define MW_1_FREQUENCY_OUTSIDE_OF_SPECS_1 "MM5837: Frequency outside of specs: {1}"
+
+// nlid_proxy.cpp
+
+#define MW_1_NO_POWER_TERMINALS_ON_DEVICE_1 "D/A Proxy: Found no valid combination of power terminals on device {1}"
+
+
+#endif /* NL_ERRSTR_H_ */
diff --git a/src/lib/netlist/nl_factory.cpp b/src/lib/netlist/nl_factory.cpp
index 50dc2ef9c8d..2ab15375d62 100644
--- a/src/lib/netlist/nl_factory.cpp
+++ b/src/lib/netlist/nl_factory.cpp
@@ -9,6 +9,7 @@
****************************************************************************/
#include "nl_factory.h"
+#include "nl_base.h"
#include "nl_setup.h"
#include "plib/putil.h"
#include "nl_errstr.h"
@@ -16,9 +17,31 @@
namespace netlist { namespace factory
{
+class NETLIB_NAME(wrapper) : public device_t
+{
+public:
+ NETLIB_NAME(wrapper)(netlist_t &anetlist, const pstring &name)
+ : device_t(anetlist, name)
+ {
+ }
+protected:
+ NETLIB_RESETI();
+ NETLIB_UPDATEI();
+};
+
+
+
+element_t::element_t(const pstring &name, const pstring &classname,
+ const pstring &def_param, const pstring &sourcefile)
+ : m_name(name), m_classname(classname), m_def_param(def_param),
+ m_sourcefile(sourcefile)
+{
+}
+
element_t::element_t(const pstring &name, const pstring &classname,
const pstring &def_param)
- : m_name(name), m_classname(classname), m_def_param(def_param)
+ : m_name(name), m_classname(classname), m_def_param(def_param),
+ m_sourcefile("<unknown>")
{
}
diff --git a/src/lib/netlist/nl_factory.h b/src/lib/netlist/nl_factory.h
index 9e2185e0729..92f126ea4d5 100644
--- a/src/lib/netlist/nl_factory.h
+++ b/src/lib/netlist/nl_factory.h
@@ -9,29 +9,42 @@
#ifndef NLFACTORY_H_
#define NLFACTORY_H_
-#include <type_traits>
-
-#include "nl_config.h"
#include "plib/palloc.h"
-#include "plib/plists.h"
-#include "plib/putil.h"
-#include "nl_base.h"
-
-#define NETLIB_DEVICE_IMPL(chip) factory::constructor_ptr_t decl_ ## chip = factory::constructor_t< NETLIB_NAME(chip) >;
-#define NETLIB_DEVICE_IMPL_NS(ns, chip) factory::constructor_ptr_t decl_ ## chip = factory::constructor_t< ns :: NETLIB_NAME(chip) >;
-
-namespace netlist { namespace factory
-{
+#include "plib/ptypes.h"
+
+#define NETLIB_DEVICE_IMPL(chip) \
+ static std::unique_ptr<factory::element_t> NETLIB_NAME(chip ## _c)( \
+ const pstring &name, const pstring &classname, const pstring &def_param) \
+ { \
+ return std::unique_ptr<factory::element_t>(plib::palloc<factory::device_element_t<NETLIB_NAME(chip)>>(name, classname, def_param, pstring(__FILE__))); \
+ } \
+ factory::constructor_ptr_t decl_ ## chip = NETLIB_NAME(chip ## _c);
+
+#define NETLIB_DEVICE_IMPL_NS(ns, chip) \
+ static std::unique_ptr<factory::element_t> NETLIB_NAME(chip ## _c)( \
+ const pstring &name, const pstring &classname, const pstring &def_param) \
+ { \
+ return std::unique_ptr<factory::element_t>(plib::palloc<factory::device_element_t<ns :: NETLIB_NAME(chip)>>(name, classname, def_param, pstring(__FILE__))); \
+ } \
+ factory::constructor_ptr_t decl_ ## chip = NETLIB_NAME(chip ## _c);
+
+namespace netlist {
+ class netlist_t;
+ class device_t;
+ class setup_t;
+
+namespace factory {
// -----------------------------------------------------------------------------
// net_dev class factory
// -----------------------------------------------------------------------------
- class element_t
+ class element_t : plib::nocopyassignmove
{
- P_PREVENT_COPYING(element_t)
public:
element_t(const pstring &name, const pstring &classname,
const pstring &def_param);
+ element_t(const pstring &name, const pstring &classname,
+ const pstring &def_param, const pstring &sourcefile);
virtual ~element_t();
virtual plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) = 0;
@@ -40,21 +53,25 @@ namespace netlist { namespace factory
const pstring &name() const { return m_name; }
const pstring &classname() const { return m_classname; }
const pstring &param_desc() const { return m_def_param; }
+ const pstring &sourcefile() const { return m_sourcefile; }
protected:
pstring m_name; /* device name */
pstring m_classname; /* device class name */
pstring m_def_param; /* default parameter */
+ pstring m_sourcefile; /* source file */
};
template <class C>
class device_element_t : public element_t
{
- P_PREVENT_COPYING(device_element_t)
public:
device_element_t(const pstring &name, const pstring &classname,
const pstring &def_param)
: element_t(name, classname, def_param) { }
+ device_element_t(const pstring &name, const pstring &classname,
+ const pstring &def_param, const pstring &sourcefile)
+ : element_t(name, classname, def_param, sourcefile) { }
plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) override
{
@@ -72,7 +89,7 @@ namespace netlist { namespace factory
void register_device(const pstring &name, const pstring &classname,
const pstring &def_param)
{
- register_device(std::unique_ptr<element_t>(new device_element_t<device_class>(name, classname, def_param)));
+ register_device(std::unique_ptr<element_t>(plib::palloc<device_element_t<device_class>>(name, classname, def_param)));
}
void register_device(std::unique_ptr<element_t> factory);
@@ -87,7 +104,7 @@ namespace netlist { namespace factory
private:
setup_t &m_setup;
-};
+ };
// -----------------------------------------------------------------------------
// factory_creator_ptr_t
@@ -100,42 +117,33 @@ namespace netlist { namespace factory
std::unique_ptr<element_t> constructor_t(const pstring &name, const pstring &classname,
const pstring &def_param)
{
- return std::unique_ptr<element_t>(new device_element_t<T>(name, classname, def_param));
+ return std::unique_ptr<element_t>(plib::palloc<device_element_t<T>>(name, classname, def_param));
}
// -----------------------------------------------------------------------------
// factory_lib_entry_t: factory class to wrap macro based chips/elements
// -----------------------------------------------------------------------------
- class NETLIB_NAME(wrapper) : public device_t
- {
- public:
- NETLIB_NAME(wrapper)(netlist_t &anetlist, const pstring &name)
- : device_t(anetlist, name)
- {
- }
- protected:
- NETLIB_RESETI();
- NETLIB_UPDATEI();
- };
-
class library_element_t : public element_t
{
- P_PREVENT_COPYING(library_element_t)
public:
library_element_t(setup_t &setup, const pstring &name, const pstring &classname,
- const pstring &def_param)
- : element_t(name, classname, def_param), m_setup(setup) { }
+ const pstring &def_param, const pstring &source)
+ : element_t(name, classname, def_param, source) { }
plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) override;
void macro_actions(netlist_t &anetlist, const pstring &name) override;
private:
- setup_t &m_setup;
};
-} }
+ }
+
+ namespace devices {
+ void initialize_factory(factory::list_t &factory);
+ }
+}
#endif /* NLFACTORY_H_ */
diff --git a/src/lib/netlist/nl_lists.h b/src/lib/netlist/nl_lists.h
index 2b378dadf71..4c6935bd7d4 100644
--- a/src/lib/netlist/nl_lists.h
+++ b/src/lib/netlist/nl_lists.h
@@ -11,10 +11,14 @@
#define NLLISTS_H_
#include <atomic>
+#include <thread>
+#include <mutex>
#include "nl_config.h"
+#include "netlist_types.h"
#include "plib/plists.h"
#include "plib/pchrono.h"
+#include "plib/ptypes.h"
// ----------------------------------------------------------------------------------------
// timed queue
@@ -23,41 +27,45 @@
namespace netlist
{
-
//FIXME: move to an appropriate place
template<bool enabled_ = true>
- class pspin_lock
+ class pspin_mutex
{
public:
- pspin_lock() { }
- void acquire() noexcept{ while (m_lock.test_and_set(std::memory_order_acquire)) { } }
- void release() noexcept { m_lock.clear(std::memory_order_release); }
+ pspin_mutex() noexcept { }
+ void lock() noexcept{ while (m_lock.test_and_set(std::memory_order_acquire)) { } }
+ void unlock() noexcept { m_lock.clear(std::memory_order_release); }
private:
std::atomic_flag m_lock = ATOMIC_FLAG_INIT;
};
template<>
- class pspin_lock<false>
+ class pspin_mutex<false>
{
public:
- void acquire() const noexcept { }
- void release() const noexcept { }
+ void lock() const noexcept { }
+ void unlock() const noexcept { }
};
- #if HAS_OPENMP && USE_OPENMP
- using tqlock = pspin_lock<true>;
- #else
- using tqlock = pspin_lock<false>;
- #endif
-
template <class Element, class Time>
- class timed_queue
+ class timed_queue : plib::nocopyassignmove
{
- P_PREVENT_COPYING(timed_queue)
public:
struct entry_t
{
+ entry_t() { }
+ entry_t(const Time &t, const Element &o) : m_exec_time(t), m_object(o) { }
+ entry_t(const entry_t &e) : m_exec_time(e.m_exec_time), m_object(e.m_object) { }
+ entry_t(entry_t &&e) : m_exec_time(e.m_exec_time), m_object(e.m_object) { }
+
+ entry_t& operator=(entry_t && other)
+ {
+ m_exec_time = other.m_exec_time;
+ m_object = other.m_object;
+ return *this;
+ }
+
Time m_exec_time;
Element m_object;
};
@@ -65,37 +73,35 @@ namespace netlist
timed_queue(unsigned list_size)
: m_list(list_size)
{
- m_lock.acquire();
clear();
- m_lock.release();
}
std::size_t capacity() const { return m_list.size(); }
bool empty() const { return (m_end == &m_list[1]); }
- void push(Element o, const Time t) noexcept
+ void push(entry_t &&e) noexcept
{
/* Lock */
- m_lock.acquire();
+ tqlock lck(m_lock);
entry_t * i = m_end;
- for (; t > (i - 1)->m_exec_time; --i)
+ while (e.m_exec_time > (i - 1)->m_exec_time)
{
- *(i) = *(i-1);
+ *(i) = std::move(*(i-1));
+ --i;
m_prof_sortmove.inc();
}
- *i = { t, o };
+ *i = std::move(e);
++m_end;
m_prof_call.inc();
- m_lock.release();
}
- entry_t pop() noexcept { return *(--m_end); }
- const entry_t &top() const noexcept { return *(m_end-1); }
+ entry_t pop() noexcept { return std::move(*(--m_end)); }
+ const entry_t &top() const noexcept { return std::move(*(m_end-1)); }
void remove(const Element &elem) noexcept
{
/* Lock */
- m_lock.acquire();
+ tqlock lck(m_lock);
for (entry_t * i = m_end - 1; i > &m_list[0]; i--)
{
if (i->m_object == elem)
@@ -103,24 +109,23 @@ namespace netlist
m_end--;
while (i < m_end)
{
- *i = *(i+1);
+ *i = std::move(*(i+1));
++i;
}
- m_lock.release();
return;
}
}
- m_lock.release();
}
void retime(const Element &elem, const Time t) noexcept
{
remove(elem);
- push(elem, t);
+ push(entry_t(t, elem));
}
void clear()
{
+ tqlock lck(m_lock);
m_end = &m_list[0];
/* put an empty element with maximum time into the queue.
* the insert algo above will run into this element and doesn't
@@ -137,8 +142,14 @@ namespace netlist
const entry_t & operator[](const std::size_t index) const { return m_list[ 1 + index]; }
private:
+ #if HAS_OPENMP && USE_OPENMP
+ using tqmutex = pspin_mutex<true>;
+ #else
+ using tqmutex = pspin_mutex<false>;
+ #endif
+ using tqlock = std::lock_guard<tqmutex>;
- tqlock m_lock;
+ tqmutex m_lock;
entry_t * m_end;
std::vector<entry_t> m_list;
diff --git a/src/lib/netlist/nl_parser.cpp b/src/lib/netlist/nl_parser.cpp
index 6dee211ce56..db7ced8fae0 100644
--- a/src/lib/netlist/nl_parser.cpp
+++ b/src/lib/netlist/nl_parser.cpp
@@ -7,7 +7,7 @@
#include "nl_parser.h"
#include "nl_factory.h"
-#include "devices/nld_truthtable.h"
+#include "nl_errstr.h"
namespace netlist
{
@@ -28,13 +28,7 @@ bool parser_t::parse(const pstring nlname)
{
set_identifier_chars("abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-");
set_number_chars(".0123456789", "0123456789eE-."); //FIXME: processing of numbers
- char ws[5];
- ws[0] = ' ';
- ws[1] = 9;
- ws[2] = 10;
- ws[3] = 13;
- ws[4] = 0;
- set_whitespace(ws);
+ set_whitespace(pstring("").cat(' ').cat(9).cat(10).cat(13));
set_comment("/*", "*/", "//");
m_tok_param_left = register_token("(");
m_tok_param_right = register_token(")");
@@ -64,18 +58,16 @@ bool parser_t::parse(const pstring nlname)
while (true)
{
token_t token = get_token();
-
if (token.is_type(ENDOFFILE))
{
return false;
- //error("EOF while searching for <{1}>", nlname);
}
if (token.is(m_tok_NETLIST_END))
{
require_token(m_tok_param_left);
if (!in_nl)
- error("Unexpected NETLIST_END");
+ error (MF_0_UNEXPECTED_NETLIST_END);
else
{
in_nl = false;
@@ -85,7 +77,7 @@ bool parser_t::parse(const pstring nlname)
else if (token.is(m_tok_NETLIST_START))
{
if (in_nl)
- error("Unexpected NETLIST_START");
+ error (MF_0_UNEXPECTED_NETLIST_START);
require_token(m_tok_param_left);
token_t name = get_token();
require_token(m_tok_param_right);
@@ -99,7 +91,7 @@ bool parser_t::parse(const pstring nlname)
}
}
-void parser_t::parse_netlist(ATTR_UNUSED const pstring &nlname)
+void parser_t::parse_netlist(const pstring &nlname)
{
while (true)
{
@@ -132,10 +124,10 @@ void parser_t::parse_netlist(ATTR_UNUSED const pstring &nlname)
else if (token.is(m_tok_LOCAL_SOURCE))
net_local_source();
else if (token.is(m_tok_TRUTHTABLE_START))
- net_truthtable_start();
+ net_truthtable_start(nlname);
else if (token.is(m_tok_LOCAL_LIB_ENTRY))
{
- m_setup.register_lib_entry(get_identifier());
+ m_setup.register_lib_entry(get_identifier(), "parser: " + nlname);
require_token(m_tok_param_right);
}
else if (token.is(m_tok_NETLIST_END))
@@ -148,7 +140,7 @@ void parser_t::parse_netlist(ATTR_UNUSED const pstring &nlname)
}
}
-void parser_t::net_truthtable_start()
+void parser_t::net_truthtable_start(const pstring &nlname)
{
pstring name = get_identifier();
require_token(m_tok_comma);
@@ -194,7 +186,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);
- netlist::devices::tt_factory_create(m_setup, desc);
+ m_setup.tt_factory_create(desc, nlname);
return;
}
}
@@ -300,7 +292,7 @@ void parser_t::net_c()
void parser_t::dippins()
{
- plib::pstring_vector_t pins;
+ std::vector<pstring> pins;
pins.push_back(get_identifier());
require_token(m_tok_comma);
@@ -357,7 +349,7 @@ void parser_t::netdev_hint()
void parser_t::device(const pstring &dev_type)
{
factory::element_t *f = m_setup.factory().factory_by_name(dev_type);
- auto paramlist = plib::pstring_vector_t(f->param_desc(), ",");
+ auto paramlist = plib::psplit(f->param_desc(), ",");
pstring devname = get_identifier();
@@ -404,7 +396,7 @@ void parser_t::device(const pstring &dev_type)
nl_double parser_t::eval_param(const token_t tok)
{
- static const char *macs[6] = {"", "RES_K", "RES_M", "CAP_U", "CAP_N", "CAP_P"};
+ static pstring macs[6] = {"", "RES_K", "RES_M", "CAP_U", "CAP_N", "CAP_P"};
static nl_double facs[6] = {1, 1e3, 1e6, 1e-6, 1e-9, 1e-12};
int i;
int f=0;
@@ -415,7 +407,6 @@ nl_double parser_t::eval_param(const token_t tok)
for (i=1; i<6;i++)
if (tok.str().equals(macs[i]))
f = i;
-#if 1
if (f>0)
{
require_token(m_tok_param_left);
@@ -431,22 +422,6 @@ nl_double parser_t::eval_param(const token_t tok)
}
return ret * facs[f];
-#else
- if (f>0)
- {
- require_token(m_tok_param_left);
- val = get_identifier();
- }
- else
- val = tok.str();
-
- ret = val.as_double(&e);
-
- if (e)
- fatal("Error with parameter ...\n");
- if (f>0)
- require_token(m_tok_param_right);
- return ret * facs[f];
-#endif
}
+
}
diff --git a/src/lib/netlist/nl_parser.h b/src/lib/netlist/nl_parser.h
index 5c915e69997..4654bcb3f87 100644
--- a/src/lib/netlist/nl_parser.h
+++ b/src/lib/netlist/nl_parser.h
@@ -15,10 +15,9 @@ namespace netlist
{
class parser_t : public plib::ptokenizer
{
- P_PREVENT_COPYING(parser_t)
public:
- parser_t(plib::pistream &strm, setup_t &setup)
- : plib::ptokenizer(strm), m_setup(setup), m_buf(nullptr) {}
+ parser_t(plib::putf8_reader &strm, setup_t &setup)
+ : plib::ptokenizer(strm), m_setup(setup) {}
bool parse(const pstring nlname = "");
@@ -37,7 +36,7 @@ namespace netlist
void net_submodel();
void net_include();
void net_local_source();
- void net_truthtable_start();
+ void net_truthtable_start(const pstring &nlname);
/* for debugging messages */
netlist_t &netlist() { return m_setup.netlist(); }
@@ -70,9 +69,7 @@ namespace netlist
token_id_t m_tok_TT_FAMILY;
setup_t &m_setup;
-
- const char *m_buf;
- };
+};
}
diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp
index 84aa7c8d384..0572ec1e693 100644
--- a/src/lib/netlist/nl_setup.cpp
+++ b/src/lib/netlist/nl_setup.cpp
@@ -5,22 +5,17 @@
*
*/
-#include <cstdio>
-
-#include "solver/nld_solver.h"
-
#include "plib/palloc.h"
#include "plib/putil.h"
#include "nl_base.h"
#include "nl_setup.h"
#include "nl_parser.h"
#include "nl_factory.h"
-#include "devices/net_lib.h"
-#include "devices/nld_truthtable.h"
#include "devices/nlid_system.h"
#include "devices/nlid_proxy.h"
#include "analog/nld_twoterm.h"
#include "solver/nld_solver.h"
+#include "devices/nlid_truthtable.h"
// ----------------------------------------------------------------------------------------
// setup_t
@@ -34,7 +29,7 @@ setup_t::setup_t(netlist_t &netlist)
, m_proxy_cnt(0)
, m_frontier_cnt(0)
{
- initialize_factory(m_factory);
+ devices::initialize_factory(m_factory);
}
setup_t::~setup_t()
@@ -73,16 +68,16 @@ void setup_t::namespace_pop()
m_namespace_stack.pop();
}
-void setup_t::register_lib_entry(const pstring &name)
+void setup_t::register_lib_entry(const pstring &name, const pstring &sourcefile)
{
- factory().register_device(plib::make_unique_base<factory::element_t, factory::library_element_t>(*this, name, name, ""));
+ factory().register_device(plib::make_unique_base<factory::element_t, factory::library_element_t>(*this, name, name, "", sourcefile));
}
void setup_t::register_dev(const pstring &classname, const pstring &name)
{
auto f = factory().factory_by_name(classname);
if (f == nullptr)
- log().fatal("Class {1} not found!\n", classname);
+ log().fatal(MF_1_CLASS_1_NOT_FOUND, classname);
/* make sure we parse macro library entries */
f->macro_actions(netlist(), name);
m_device_factory.push_back(std::pair<pstring, factory::element_t *>(build_fqn(name), f));
@@ -103,17 +98,17 @@ void setup_t::register_model(const pstring &model_in)
{
auto pos = model_in.find(" ");
if (pos == model_in.end())
- log().fatal("Unable to parse model: {1}", model_in);
+ log().fatal(MF_1_UNABLE_TO_PARSE_MODEL_1, model_in);
pstring model = model_in.left(pos).trim().ucase();
pstring def = model_in.substr(pos + 1).trim();
if (!m_models.insert({model, def}).second)
- log().fatal("Model already exists: {1}", model_in);
+ log().fatal(MF_1_MODEL_ALREADY_EXISTS_1, model_in);
}
void setup_t::register_alias_nofqn(const pstring &alias, const pstring &out)
{
if (!m_alias.insert({alias, out}).second)
- log().fatal("Error adding alias {1} to alias list\n", alias);
+ log().fatal(MF_1_ADDING_ALIAS_1_TO_ALIAS_LIST, alias);
}
void setup_t::register_alias(const pstring &alias, const pstring &out)
@@ -125,9 +120,10 @@ void setup_t::register_alias(const pstring &alias, const pstring &out)
void setup_t::register_dippins_arr(const pstring &terms)
{
- plib::pstring_vector_t list(terms,", ");
+ std::vector<pstring> list(plib::psplit(terms,", "));
if (list.size() == 0 || (list.size() % 2) == 1)
- log().fatal("You must pass an equal number of pins to DIPPINS {1}" , build_fqn(""));
+ log().fatal(MF_1_DIP_PINS_MUST_BE_AN_EQUAL_NUMBER_OF_PINS_1,
+ build_fqn(""));
std::size_t n = list.size();
for (std::size_t i = 0; i < n / 2; i++)
{
@@ -136,22 +132,19 @@ void setup_t::register_dippins_arr(const pstring &terms)
}
}
-pstring setup_t::objtype_as_str(detail::device_object_t &in) const
+pstring setup_t::termtype_as_str(detail::core_terminal_t &in) const
{
switch (in.type())
{
- case terminal_t::TERMINAL:
- return "TERMINAL";
- case terminal_t::INPUT:
- return "INPUT";
- case terminal_t::OUTPUT:
- return "OUTPUT";
- case terminal_t::PARAM:
- return "PARAM";
+ case detail::terminal_type::TERMINAL:
+ return pstring("TERMINAL");
+ case detail::terminal_type::INPUT:
+ return pstring("INPUT");
+ case detail::terminal_type::OUTPUT:
+ return pstring("OUTPUT");
}
- // FIXME: noreturn
- log().fatal("Unknown object type {1}\n", static_cast<unsigned>(in.type()));
- return "Error";
+ log().fatal(MF_1_UNKNOWN_OBJECT_TYPE_1, static_cast<unsigned>(in.type()));
+ return pstring("Error");
}
pstring setup_t::get_initial_param_val(const pstring name, const pstring def)
@@ -170,7 +163,7 @@ double setup_t::get_initial_param_val(const pstring name, const double def)
{
double vald = 0;
if (sscanf(i->second.c_str(), "%lf", &vald) != 1)
- log().fatal("Invalid number conversion {1} : {2}\n", name, i->second);
+ log().fatal(MF_2_INVALID_NUMBER_CONVERSION_1_2, name, i->second);
return vald;
}
else
@@ -184,7 +177,7 @@ int setup_t::get_initial_param_val(const pstring name, const int def)
{
double vald = 0;
if (sscanf(i->second.c_str(), "%lf", &vald) != 1)
- log().fatal("Invalid number conversion {1} : {2}\n", name, i->second);
+ log().fatal(MF_2_INVALID_NUMBER_CONVERSION_1_2, name, i->second);
return static_cast<int>(vald);
}
else
@@ -194,21 +187,22 @@ int setup_t::get_initial_param_val(const pstring name, const int def)
void setup_t::register_param(pstring name, param_t &param)
{
if (!m_params.insert({param.name(), param_ref_t(param.name(), param.device(), param)}).second)
- log().fatal("Error adding parameter {1} to parameter list\n", name);
+ log().fatal(MF_1_ADDING_PARAMETER_1_TO_PARAMETER_LIST, name);
}
void setup_t::register_term(detail::core_terminal_t &term)
{
if (!m_terminals.insert({term.name(), &term}).second)
- log().fatal("Error adding {1} {2} to terminal list\n", objtype_as_str(term), term.name());
- log().debug("{1} {2}\n", objtype_as_str(term), term.name());
+ log().fatal(MF_2_ADDING_1_2_TO_TERMINAL_LIST, termtype_as_str(term),
+ term.name());
+ log().debug("{1} {2}\n", termtype_as_str(term), term.name());
}
void setup_t::register_link_arr(const pstring &terms)
{
- plib::pstring_vector_t list(terms,", ");
+ std::vector<pstring> list(plib::psplit(terms,", "));
if (list.size() < 2)
- log().fatal("You must pass at least 2 terminals to NET_C");
+ log().fatal(MF_2_NET_C_NEEDS_AT_LEAST_2_TERMINAL);
for (std::size_t i = 1; i < list.size(); i++)
{
register_link(list[0], list[i]);
@@ -245,7 +239,7 @@ void setup_t::remove_connections(const pstring pin)
link++;
}
if (!found)
- log().fatal("remove_connections: found no occurrence of {1}\n", pin);
+ log().fatal(MF_1_FOUND_NO_OCCURRENCE_OF_1, pin);
}
@@ -274,7 +268,7 @@ void setup_t::register_frontier(const pstring attach, const double r_IN, const d
}
}
if (!found)
- log().fatal("Frontier setup: found no occurrence of {1}\n", attach);
+ log().fatal(MF_1_FOUND_NO_OCCURRENCE_OF_1, attach);
register_link(attach, frontier_name + ".Q");
}
@@ -292,11 +286,13 @@ void setup_t::register_param(const pstring &param, const pstring &value)
if (idx == m_param_values.end())
{
if (!m_param_values.insert({fqn, value}).second)
- log().fatal("Unexpected error adding parameter {1} to parameter list\n", param);
+ log().fatal(MF_1_ADDING_PARAMETER_1_TO_PARAMETER_LIST,
+ param);
}
else
{
- log().warning("Overwriting {1} old <{2}> new <{3}>\n", fqn, idx->second, value);
+ log().warning(MW_3_OVERWRITING_PARAM_1_OLD_2_NEW_3, fqn, idx->second,
+ value);
m_param_values[fqn] = value;
}
}
@@ -331,32 +327,32 @@ detail::core_terminal_t *setup_t::find_terminal(const pstring &terminal_in, bool
detail::core_terminal_t *term = (ret == m_terminals.end() ? nullptr : ret->second);
if (term == nullptr && required)
- log().fatal("terminal {1}({2}) not found!\n", terminal_in, tname);
+ log().fatal(MF_2_TERMINAL_1_2_NOT_FOUND, terminal_in, tname);
if (term != nullptr)
log().debug("Found input {1}\n", tname);
return term;
}
detail::core_terminal_t *setup_t::find_terminal(const pstring &terminal_in,
- detail::device_object_t::type_t atype, bool required)
+ detail::terminal_type atype, bool required)
{
const pstring &tname = resolve_alias(terminal_in);
auto ret = m_terminals.find(tname);
/* look for default */
- if (ret == m_terminals.end() && atype == detail::device_object_t::OUTPUT)
+ if (ret == m_terminals.end() && atype == detail::terminal_type::OUTPUT)
{
/* look for ".Q" std output */
ret = m_terminals.find(tname + ".Q");
}
if (ret == m_terminals.end() && required)
- log().fatal("terminal {1}({2}) not found!\n", terminal_in, tname);
+ log().fatal(MF_2_TERMINAL_1_2_NOT_FOUND, terminal_in, tname);
detail::core_terminal_t *term = (ret == m_terminals.end() ? nullptr : ret->second);
if (term != nullptr && term->type() != atype)
{
if (required)
- log().fatal("object {1}({2}) found but wrong type\n", terminal_in, tname);
+ log().fatal(MF_2_OBJECT_1_2_WRONG_TYPE, terminal_in, tname);
else
term = nullptr;
}
@@ -373,18 +369,17 @@ param_t *setup_t::find_param(const pstring &param_in, bool required) const
const pstring &outname = resolve_alias(param_in_fqn);
auto ret = m_params.find(outname);
if (ret == m_params.end() && required)
- log().fatal("parameter {1}({2}) not found!\n", param_in_fqn, outname);
+ log().fatal(MF_2_PARAMETER_1_2_NOT_FOUND, param_in_fqn, outname);
if (ret != m_params.end())
log().debug("Found parameter {1}\n", outname);
return (ret == m_params.end() ? nullptr : &ret->second.m_param);
}
-// FIXME avoid dynamic cast here
devices::nld_base_proxy *setup_t::get_d_a_proxy(detail::core_terminal_t &out)
{
nl_assert(out.is_logic());
- logic_output_t &out_cast = dynamic_cast<logic_output_t &>(out);
+ logic_output_t &out_cast = static_cast<logic_output_t &>(out);
devices::nld_base_proxy *proxy = out_cast.get_proxy();
if (proxy == nullptr)
@@ -403,7 +398,8 @@ devices::nld_base_proxy *setup_t::get_d_a_proxy(detail::core_terminal_t &out)
{
p->clear_net(); // de-link from all nets ...
if (!connect(new_proxy->proxy_term(), *p))
- log().fatal("Error connecting {1} to {2}\n", new_proxy->proxy_term().name(), (*p).name());
+ log().fatal(MF_2_CONNECTING_1_TO_2,
+ new_proxy->proxy_term().name(), (*p).name());
}
out.net().m_core_terms.clear(); // clear the list
@@ -437,7 +433,6 @@ devices::nld_base_proxy *setup_t::get_a_d_proxy(detail::core_terminal_t &inp)
auto ret = new_proxy.get();
-#if 1
/* connect all existing terminals to new net */
if (inp.has_net())
@@ -446,18 +441,12 @@ devices::nld_base_proxy *setup_t::get_a_d_proxy(detail::core_terminal_t &inp)
{
p->clear_net(); // de-link from all nets ...
if (!connect(ret->proxy_term(), *p))
- log().fatal("Error connecting {1} to {2}\n", ret->proxy_term().name(), (*p).name());
+ log().fatal(MF_2_CONNECTING_1_TO_2,
+ ret->proxy_term().name(), (*p).name());
}
inp.net().m_core_terms.clear(); // clear the list
}
ret->out().net().add_terminal(inp);
-#else
- if (inp.has_net())
- //fatalerror("logic inputs can only belong to one net!\n");
- merge_nets(ret->out().net(), inp.net());
- else
- ret->out().net().add_terminal(inp);
-#endif
netlist().register_dev(std::move(new_proxy));
return ret;
}
@@ -465,19 +454,20 @@ devices::nld_base_proxy *setup_t::get_a_d_proxy(detail::core_terminal_t &inp)
void setup_t::merge_nets(detail::net_t &thisnet, detail::net_t &othernet)
{
- netlist().log().debug("merging nets ...\n");
+ log().debug("merging nets ...\n");
if (&othernet == &thisnet)
{
- netlist().log().warning("Connecting {1} to itself. This may be right, though\n", thisnet.name());
+ log().warning(MW_1_CONNECTING_1_TO_ITSELF, thisnet.name());
return; // Nothing to do
}
if (thisnet.isRailNet() && othernet.isRailNet())
- netlist().log().fatal("Trying to merge two rail nets: {1} and {2}\n", thisnet.name(), othernet.name());
+ log().fatal(MF_2_MERGE_RAIL_NETS_1_AND_2,
+ thisnet.name(), othernet.name());
if (othernet.isRailNet())
{
- netlist().log().debug("othernet is railnet\n");
+ log().debug("othernet is railnet\n");
merge_nets(othernet, thisnet);
}
else
@@ -521,7 +511,8 @@ void setup_t::connect_terminal_input(terminal_t &term, detail::core_terminal_t &
}
else if (inp.is_logic())
{
- netlist().log().verbose("connect terminal {1} (in, {2}) to {3}\n", inp.name(), pstring(inp.is_analog() ? "analog" : inp.is_logic() ? "logic" : "?"), term.name());
+ log().verbose("connect terminal {1} (in, {2}) to {3}\n", inp.name(),
+ inp.is_analog() ? pstring("analog") : inp.is_logic() ? pstring("logic") : pstring("?"), term.name());
auto proxy = get_a_d_proxy(inp);
//out.net().register_con(proxy->proxy_term());
@@ -530,7 +521,7 @@ void setup_t::connect_terminal_input(terminal_t &term, detail::core_terminal_t &
}
else
{
- log().fatal("Netlist: Severe Error");
+ log().fatal(MF_1_OBJECT_INPUT_TYPE_1, inp.name());
}
}
@@ -554,7 +545,7 @@ void setup_t::connect_terminal_output(terminal_t &in, detail::core_terminal_t &o
}
else
{
- log().fatal("Netlist: Severe Error");
+ log().fatal(MF_1_OBJECT_OUTPUT_TYPE_1, out.name());
}
}
@@ -609,7 +600,7 @@ bool setup_t::connect_input_input(detail::core_terminal_t &t1, detail::core_term
{
for (auto & t : t1.net().m_core_terms)
{
- if (t->is_type(detail::core_terminal_t::TERMINAL))
+ if (t->is_type(detail::terminal_type::TERMINAL))
ret = connect(t2, *t);
if (ret)
break;
@@ -624,7 +615,7 @@ bool setup_t::connect_input_input(detail::core_terminal_t &t1, detail::core_term
{
for (auto & t : t2.net().m_core_terms)
{
- if (t->is_type(detail::core_terminal_t::TERMINAL))
+ if (t->is_type(detail::terminal_type::TERMINAL))
ret = connect(t1, *t);
if (ret)
break;
@@ -643,39 +634,39 @@ bool setup_t::connect(detail::core_terminal_t &t1_in, detail::core_terminal_t &t
detail::core_terminal_t &t2 = resolve_proxy(t2_in);
bool ret = true;
- if (t1.is_type(detail::core_terminal_t::OUTPUT) && t2.is_type(detail::core_terminal_t::INPUT))
+ if (t1.is_type(detail::terminal_type::OUTPUT) && t2.is_type(detail::terminal_type::INPUT))
{
if (t2.has_net() && t2.net().isRailNet())
- log().fatal("Input {1} already connected\n", t2.name());
+ log().fatal(MF_1_INPUT_1_ALREADY_CONNECTED, t2.name());
connect_input_output(t2, t1);
}
- else if (t1.is_type(detail::core_terminal_t::INPUT) && t2.is_type(detail::core_terminal_t::OUTPUT))
+ else if (t1.is_type(detail::terminal_type::INPUT) && t2.is_type(detail::terminal_type::OUTPUT))
{
if (t1.has_net() && t1.net().isRailNet())
- log().fatal("Input {1} already connected\n", t1.name());
+ log().fatal(MF_1_INPUT_1_ALREADY_CONNECTED, t1.name());
connect_input_output(t1, t2);
}
- else if (t1.is_type(detail::core_terminal_t::OUTPUT) && t2.is_type(detail::core_terminal_t::TERMINAL))
+ else if (t1.is_type(detail::terminal_type::OUTPUT) && t2.is_type(detail::terminal_type::TERMINAL))
{
connect_terminal_output(dynamic_cast<terminal_t &>(t2), t1);
}
- else if (t1.is_type(detail::core_terminal_t::TERMINAL) && t2.is_type(detail::core_terminal_t::OUTPUT))
+ else if (t1.is_type(detail::terminal_type::TERMINAL) && t2.is_type(detail::terminal_type::OUTPUT))
{
connect_terminal_output(dynamic_cast<terminal_t &>(t1), t2);
}
- else if (t1.is_type(detail::core_terminal_t::INPUT) && t2.is_type(detail::core_terminal_t::TERMINAL))
+ else if (t1.is_type(detail::terminal_type::INPUT) && t2.is_type(detail::terminal_type::TERMINAL))
{
connect_terminal_input(dynamic_cast<terminal_t &>(t2), t1);
}
- else if (t1.is_type(detail::core_terminal_t::TERMINAL) && t2.is_type(detail::core_terminal_t::INPUT))
+ else if (t1.is_type(detail::terminal_type::TERMINAL) && t2.is_type(detail::terminal_type::INPUT))
{
connect_terminal_input(dynamic_cast<terminal_t &>(t1), t2);
}
- else if (t1.is_type(detail::core_terminal_t::TERMINAL) && t2.is_type(detail::core_terminal_t::TERMINAL))
+ else if (t1.is_type(detail::terminal_type::TERMINAL) && t2.is_type(detail::terminal_type::TERMINAL))
{
connect_terminals(dynamic_cast<terminal_t &>(t1), dynamic_cast<terminal_t &>(t2));
}
- else if (t1.is_type(detail::core_terminal_t::INPUT) && t2.is_type(detail::core_terminal_t::INPUT))
+ else if (t1.is_type(detail::terminal_type::INPUT) && t2.is_type(detail::terminal_type::INPUT))
{
ret = connect_input_input(t1, t2);
}
@@ -693,8 +684,8 @@ void setup_t::resolve_inputs()
* We therefore first park connecting inputs and retry
* after all other terminals were connected.
*/
- int tries = 100;
- while (m_links.size() > 0 && tries > 0) // FIXME: convert into constant
+ int tries = NL_MAX_LINK_RESOLVE_LOOPS;
+ while (m_links.size() > 0 && tries > 0)
{
for (auto li = m_links.begin(); li != m_links.end(); )
@@ -714,9 +705,9 @@ void setup_t::resolve_inputs()
if (tries == 0)
{
for (auto & link : m_links)
- log().warning("Error connecting {1} to {2}\n", link.first, link.second);
+ log().warning(MF_2_CONNECTING_1_TO_2, link.first, link.second);
- log().fatal("Error connecting -- bailing out\n");
+ log().fatal(MF_0_LINK_TRIES_EXCEEDED);
}
log().verbose("deleting empty nets ...");
@@ -743,38 +734,26 @@ void setup_t::resolve_inputs()
{
detail::core_terminal_t *term = i.second;
if (!term->has_net() && dynamic_cast< devices::NETLIB_NAME(dummy_input) *>(&term->device()) != nullptr)
- log().warning("Found dummy terminal {1} without connections", term->name());
+ log().warning(MW_1_DUMMY_1_WITHOUT_CONNECTIONS, term->name());
else if (!term->has_net())
errstr += plib::pfmt("Found terminal {1} without a net\n")(term->name());
else if (term->net().num_cons() == 0)
- log().warning("Found terminal {1} without connections", term->name());
+ log().warning(MW_1_TERMINAL_1_WITHOUT_CONNECTIONS, term->name());
}
+ //FIXME: error string handling
if (errstr != "")
log().fatal("{1}", errstr);
-
- log().verbose("looking for two terms connected to rail nets ...");
- for (auto & t : netlist().get_device_list<analog::NETLIB_NAME(twoterm)>())
- {
- if (t->m_N.net().isRailNet() && t->m_P.net().isRailNet())
- {
- log().warning("Found device {1} connected only to railterminals {2}/{3}. Will be removed",
- t->name(), t->m_N.net().name(), t->m_P.net().name());
- t->m_N.net().remove_terminal(t->m_N);
- t->m_P.net().remove_terminal(t->m_P);
- netlist().remove_dev(t);
- }
- }
}
void setup_t::start_devices()
{
- pstring env = plib::util::environment("NL_LOGS");
+ pstring env = plib::util::environment("NL_LOGS", "");
if (env != "")
{
log().debug("Creating dynamic logs ...");
- plib::pstring_vector_t loglist(env, ":");
+ std::vector<pstring> loglist(plib::psplit(env, ":"));
for (pstring ll : loglist)
{
pstring name = "log_" + ll;
@@ -800,7 +779,7 @@ const plib::plog_base<NL_DEBUG> &setup_t::log() const
// Model
// ----------------------------------------------------------------------------------------
-static pstring model_string(model_map_t &map)
+static pstring model_string(detail::model_map_t &map)
{
pstring ret = map["COREMODEL"] + "(";
for (auto & i : map)
@@ -809,7 +788,7 @@ static pstring model_string(model_map_t &map)
return ret + ")";
}
-void setup_t::model_parse(const pstring &model_in, model_map_t &map)
+void setup_t::model_parse(const pstring &model_in, detail::model_map_t &map)
{
pstring model = model_in;
pstring::iterator pos(nullptr);
@@ -823,7 +802,7 @@ void setup_t::model_parse(const pstring &model_in, model_map_t &map)
key = model.ucase();
auto i = m_models.find(key);
if (i == m_models.end())
- log().fatal("Model {1} not found\n", model);
+ log().fatal(MF_1_MODEL_NOT_FOUND, model);
model = i->second;
}
pstring xmodel = model.left(pos);
@@ -836,40 +815,41 @@ void setup_t::model_parse(const pstring &model_in, model_map_t &map)
if (i != m_models.end())
model_parse(xmodel, map);
else
- log().fatal("Model doesn't exist: <{1}>\n", model_in);
+ log().fatal(MF_1_MODEL_NOT_FOUND, model_in);
}
pstring remainder=model.substr(pos+1).trim();
if (!remainder.endsWith(")"))
- log().fatal("Model error {1}\n", model);
+ log().fatal(MF_1_MODEL_ERROR_1, model);
// FIMXE: Not optimal
remainder = remainder.left(remainder.begin() + (remainder.len() - 1));
- plib::pstring_vector_t pairs(remainder," ", true);
+ std::vector<pstring> pairs(plib::psplit(remainder," ", true));
for (pstring &pe : pairs)
{
auto pose = pe.find("=");
if (pose == pe.end())
- log().fatal("Model error on pair {1}\n", model);
+ log().fatal(MF_1_MODEL_ERROR_ON_PAIR_1, model);
map[pe.left(pose).ucase()] = pe.substr(pose+1);
}
}
-const pstring setup_t::model_value_str(model_map_t &map, const pstring &entity)
+const pstring setup_t::model_value_str(detail::model_map_t &map, const pstring &entity)
{
pstring ret;
if (entity != entity.ucase())
- log().fatal("model parameters should be uppercase:{1} {2}\n", entity, model_string(map));
+ log().fatal(MF_2_MODEL_PARAMETERS_NOT_UPPERCASE_1_2, entity,
+ model_string(map));
if (map.find(entity) == map.end())
- log().fatal("Entity {1} not found in model {2}\n", entity, model_string(map));
+ log().fatal(MF_2_ENTITY_1_NOT_FOUND_IN_MODEL_2, entity, model_string(map));
else
ret = map[entity];
return ret;
}
-nl_double setup_t::model_value(model_map_t &map, const pstring &entity)
+nl_double setup_t::model_value(detail::model_map_t &map, const pstring &entity)
{
pstring tmp = model_value_str(map, entity);
@@ -887,16 +867,67 @@ nl_double setup_t::model_value(model_map_t &map, const pstring &entity)
case 'a': factor = 1e-18; break;
default:
if (*p < '0' || *p > '9')
- nl_exception(plib::pfmt("Unknown number factor in: {1}")(entity));
+ log().fatal(MF_1_UNKNOWN_NUMBER_FACTOR_IN_1, entity);
}
if (factor != NL_FCONST(1.0))
tmp = tmp.left(tmp.begin() + (tmp.len() - 1));
return tmp.as_double() * factor;
}
-void setup_t::tt_factory_create(tt_desc &desc)
+class logic_family_std_proxy_t : public logic_family_desc_t
+{
+public:
+ logic_family_std_proxy_t() { }
+ virtual plib::owned_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_t &anetlist,
+ const pstring &name, logic_output_t *proxied) const override;
+ virtual plib::owned_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *proxied) const override;
+};
+
+plib::owned_ptr<devices::nld_base_d_to_a_proxy> logic_family_std_proxy_t::create_d_a_proxy(netlist_t &anetlist,
+ const pstring &name, logic_output_t *proxied) const
+{
+ return plib::owned_ptr<devices::nld_base_d_to_a_proxy>::Create<devices::nld_d_to_a_proxy>(anetlist, name, proxied);
+}
+plib::owned_ptr<devices::nld_base_a_to_d_proxy> logic_family_std_proxy_t::create_a_d_proxy(netlist_t &anetlist, const pstring &name, logic_input_t *proxied) const
+{
+ return plib::owned_ptr<devices::nld_base_a_to_d_proxy>::Create<devices::nld_a_to_d_proxy>(anetlist, name, proxied);
+}
+
+
+const logic_family_desc_t *setup_t::family_from_model(const pstring &model)
{
- devices::tt_factory_create(*this, desc);
+ detail::model_map_t map;
+ model_parse(model, map);
+
+ if (model_value_str(map, "TYPE") == "TTL")
+ return family_TTL();
+ if (model_value_str(map, "TYPE") == "CD4XXX")
+ return family_CD4XXX();
+
+ for (auto & e : netlist().m_family_cache)
+ if (e.first == model)
+ return e.second.get();
+
+ auto ret = plib::make_unique_base<logic_family_desc_t, logic_family_std_proxy_t>();
+
+ ret->m_fixed_V = model_value(map, "FV");
+ ret->m_low_thresh_PCNT = model_value(map, "IVL");
+ ret->m_high_thresh_PCNT = model_value(map, "IVH");
+ ret->m_low_VO = model_value(map, "OVL");
+ ret->m_high_VO = model_value(map, "OVH");
+ ret->m_R_low = model_value(map, "ORL");
+ ret->m_R_high = model_value(map, "ORH");
+
+ auto retp = ret.get();
+
+ netlist().m_family_cache.emplace_back(model, std::move(ret));
+
+ return retp;
+}
+
+void setup_t::tt_factory_create(tt_desc &desc, const pstring &sourcefile)
+{
+ devices::tt_factory_create(*this, desc, sourcefile);
}
@@ -911,7 +942,7 @@ void setup_t::include(const pstring &netlist_name)
if (source->parse(netlist_name))
return;
}
- log().fatal("unable to find {1} in source collection", netlist_name);
+ log().fatal(MF_1_NOT_FOUND_IN_SOURCE_COLLECTION, netlist_name);
}
std::unique_ptr<plib::pistream> setup_t::get_data_stream(const pstring name)
@@ -925,18 +956,21 @@ std::unique_ptr<plib::pistream> setup_t::get_data_stream(const pstring name)
return strm;
}
}
- //log().fatal("unable to find data named {1} in source collection", name);
- log().warning("unable to find data named {1} in source collection", name);
+ log().warning(MW_1_DATA_1_NOT_FOUND, name);
return std::unique_ptr<plib::pistream>(nullptr);
}
-bool setup_t::parse_stream(plib::pistream &istrm, const pstring &name)
+bool setup_t::parse_stream(plib::putf8_reader &istrm, const pstring &name)
{
plib::pomemstream ostrm;
+ plib::putf8_writer owrt(ostrm);
- plib::pimemstream istrm2(plib::ppreprocessor(&m_defines).process(istrm, ostrm));
- return parser_t(istrm2, *this).parse(name);
+ plib::ppreprocessor(&m_defines).process(istrm, owrt);
+
+ plib::pimemstream istrm2(ostrm);
+ plib::putf8_reader reader2(istrm2);
+ return parser_t(reader2, *this).parse(name);
}
void setup_t::register_define(pstring defstr)
@@ -957,7 +991,11 @@ bool source_t::parse(const pstring &name)
if (m_type != SOURCE)
return false;
else
- return m_setup.parse_stream(*stream(name), name);
+ {
+ auto rstream = stream(name);
+ plib::putf8_reader reader(*rstream);
+ return m_setup.parse_stream(reader, name);
+ }
}
std::unique_ptr<plib::pistream> source_string_t::stream(const pstring &name)
diff --git a/src/lib/netlist/nl_setup.h b/src/lib/netlist/nl_setup.h
index 798ba8f4140..e9fc0861328 100644
--- a/src/lib/netlist/nl_setup.h
+++ b/src/lib/netlist/nl_setup.h
@@ -8,19 +8,18 @@
#ifndef NLSETUP_H_
#define NLSETUP_H_
-#include <memory>
-#include <stack>
-#include <unordered_map>
-#include <vector>
-
#include "plib/pstring.h"
-#include "plib/pfmtlog.h"
-#include "plib/pstream.h"
#include "plib/putil.h"
+#include "plib/pstream.h"
#include "plib/pparser.h"
-#include "nl_config.h"
-#include "nl_base.h"
+
#include "nl_factory.h"
+#include "nl_config.h"
+#include "netlist_types.h"
+
+#include <stack>
+#include <vector>
+#include <memory>
//============================================================
// MACROS / inline netlist definitions
@@ -71,7 +70,7 @@ void NETLIST_NAME(name)(netlist::setup_t &setup) \
#define LOCAL_LIB_ENTRY(name) \
LOCAL_SOURCE(name) \
- setup.register_lib_entry(# name);
+ setup.register_lib_entry(# name, __FILE__);
#define INCLUDE(name) \
setup.include(# name);
@@ -81,6 +80,9 @@ void NETLIST_NAME(name)(netlist::setup_t &setup) \
NETLIST_NAME(model)(setup); \
setup.namespace_pop();
+#define OPTIMIZE_FRONTIER(attach, r_in, r_out) \
+ setup.register_frontier(# attach, r_in, r_out);
+
// -----------------------------------------------------------------------------
// truthtable defines
// -----------------------------------------------------------------------------
@@ -105,12 +107,29 @@ void NETLIST_NAME(name)(netlist::setup_t &setup) \
desc.family = x;
#define TRUTHTABLE_END() \
- netlist::devices::tt_factory_create(setup, desc); \
+ setup.tt_factory_create(desc, __FILE__); \
}
namespace netlist
{
+
+ namespace detail {
+ class core_terminal_t;
+ class net_t;
+ }
+
+ namespace devices {
+ class nld_base_proxy;
+ }
+
+ class core_device_t;
+ class param_t;
+ class setup_t;
+ class netlist_t;
+ class logic_family_desc_t;
+ class terminal_t;
+
// -----------------------------------------------------------------------------
// truthtable desc
// -----------------------------------------------------------------------------
@@ -122,7 +141,7 @@ namespace netlist
unsigned long ni;
unsigned long no;
pstring def_param;
- plib::pstring_vector_t desc;
+ std::vector<pstring> desc;
pstring family;
};
@@ -178,9 +197,8 @@ namespace netlist
// ----------------------------------------------------------------------------------------
- class setup_t
+ class setup_t : plib::nocopyassignmove
{
- P_PREVENT_COPYING(setup_t)
public:
using link_t = std::pair<pstring, pstring>;
@@ -202,7 +220,7 @@ namespace netlist
void register_dev(const pstring &classname, const pstring &name);
- void register_lib_entry(const pstring &name);
+ void register_lib_entry(const pstring &name, const pstring &sourcefile);
void register_model(const pstring &model_in);
void register_alias(const pstring &alias, const pstring &out);
@@ -241,7 +259,7 @@ namespace netlist
std::unique_ptr<plib::pistream> get_data_stream(const pstring name);
- bool parse_stream(plib::pistream &istrm, const pstring &name);
+ bool parse_stream(plib::putf8_reader &istrm, const pstring &name);
/* register a source */
@@ -258,14 +276,14 @@ namespace netlist
/* model / family related */
- const pstring model_value_str(model_map_t &map, const pstring &entity);
- nl_double model_value(model_map_t &map, const pstring &entity);
+ const pstring model_value_str(detail::model_map_t &map, const pstring &entity);
+ double model_value(detail::model_map_t &map, const pstring &entity);
- void model_parse(const pstring &model, model_map_t &map);
+ void model_parse(const pstring &model, detail::model_map_t &map);
- /* FIXME: truth table trampoline */
+ const logic_family_desc_t *family_from_model(const pstring &model);
- void tt_factory_create(tt_desc &desc);
+ void tt_factory_create(tt_desc &desc, const pstring &sourcefile);
/* helper - also used by nltool */
const pstring resolve_alias(const pstring &name) const;
@@ -280,7 +298,7 @@ namespace netlist
std::unordered_map<pstring, detail::core_terminal_t *> m_terminals;
/* needed by proxy */
- detail::core_terminal_t *find_terminal(const pstring &outname_in, detail::device_object_t::type_t atype, bool required = true);
+ detail::core_terminal_t *find_terminal(const pstring &outname_in, const detail::terminal_type atype, bool required = true);
private:
@@ -295,7 +313,7 @@ namespace netlist
bool connect_input_input(detail::core_terminal_t &t1, detail::core_terminal_t &t2);
// helpers
- pstring objtype_as_str(detail::device_object_t &in) const;
+ pstring termtype_as_str(detail::core_terminal_t &in) const;
devices::nld_base_proxy *get_d_a_proxy(detail::core_terminal_t &out);
devices::nld_base_proxy *get_a_d_proxy(detail::core_terminal_t &inp);
@@ -312,7 +330,7 @@ namespace netlist
unsigned m_proxy_cnt;
unsigned m_frontier_cnt;
- };
+};
// ----------------------------------------------------------------------------------------
// base sources
@@ -353,7 +371,7 @@ namespace netlist
{
public:
source_mem_t(setup_t &setup, const char *mem)
- : source_t(setup), m_str(mem)
+ : source_t(setup), m_str(mem, pstring::UTF8)
{
}
diff --git a/src/lib/netlist/nl_time.h b/src/lib/netlist/nl_time.h
index 4edc9524a43..7706555f995 100644
--- a/src/lib/netlist/nl_time.h
+++ b/src/lib/netlist/nl_time.h
@@ -10,6 +10,7 @@
#include <cstdint>
#include "nl_config.h"
+#include "plib/ptypes.h"
#include "plib/pstate.h"
//============================================================
@@ -45,82 +46,83 @@ namespace netlist
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; }
+ ptime &operator=(const ptime rhs) noexcept { m_time = rhs.m_time; return *this; }
- ptime &operator+=(const ptime &rhs) { m_time += rhs.m_time; return *this; }
- ptime &operator-=(const ptime &rhs) { m_time -= rhs.m_time; return *this; }
+ ptime &operator+=(const ptime &rhs) noexcept { m_time += rhs.m_time; return *this; }
+ ptime &operator-=(const ptime &rhs) noexcept { m_time -= rhs.m_time; return *this; }
- friend ptime operator-(ptime lhs, const ptime &rhs)
+ friend constexpr ptime operator-(const ptime &lhs, const ptime &rhs) noexcept
{
- lhs -= rhs;
- return lhs;
+ return ptime(lhs.m_time - rhs.m_time);
}
- friend ptime operator+(ptime lhs, const ptime &rhs)
+ friend constexpr ptime operator+(const ptime &lhs, const ptime &rhs) noexcept
{
- lhs += rhs;
- return lhs;
+ return ptime(lhs.m_time + rhs.m_time);
}
- friend ptime operator*(ptime lhs, const mult_type factor)
+ friend constexpr ptime operator*(const ptime &lhs, const mult_type factor) noexcept
{
- lhs.m_time *= static_cast<internal_type>(factor);
- return lhs;
+ return ptime(lhs.m_time * static_cast<internal_type>(factor));
}
- friend mult_type operator/(const ptime &lhs, const ptime &rhs)
+ friend constexpr mult_type operator/(const ptime &lhs, const ptime &rhs) noexcept
{
return static_cast<mult_type>(lhs.m_time / rhs.m_time);
}
- friend bool operator<(const ptime &lhs, const ptime &rhs)
+ friend constexpr bool operator<(const ptime &lhs, const ptime &rhs) noexcept
{
return (lhs.m_time < rhs.m_time);
}
- friend bool operator>(const ptime &lhs, const ptime &rhs)
+ friend constexpr bool operator>(const ptime &lhs, const ptime &rhs) noexcept
{
return (rhs < lhs);
}
- friend bool operator<=(const ptime &lhs, const ptime &rhs)
+ friend constexpr bool operator<=(const ptime &lhs, const ptime &rhs) noexcept
{
return !(lhs > rhs);
}
- friend bool operator>=(const ptime &lhs, const ptime &rhs)
+ friend constexpr bool operator>=(const ptime &lhs, const ptime &rhs) noexcept
{
return !(lhs < rhs);
}
- friend bool operator==(const ptime &lhs, const ptime &rhs)
+ friend constexpr bool operator==(const ptime &lhs, const ptime &rhs) noexcept
{
return lhs.m_time == rhs.m_time;
}
- friend bool operator!=(const ptime &lhs, const ptime &rhs)
+ friend constexpr bool operator!=(const ptime &lhs, const ptime &rhs) noexcept
{
return !(lhs == rhs);
}
- constexpr internal_type as_raw() const { return m_time; }
- constexpr double as_double() const { return static_cast<double>(m_time)
- / static_cast<double>(resolution); }
+ constexpr internal_type as_raw() const noexcept { return m_time; }
+ constexpr double as_double() const noexcept
+ {
+ return static_cast<double>(m_time)
+ / static_cast<double>(resolution);
+ }
// for save states ....
- internal_type *get_internaltype_ptr() { return &m_time; }
-
- 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(static_cast<internal_type>( t * static_cast<double>(resolution)), 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); }
+ internal_type *get_internaltype_ptr() noexcept { return &m_time; }
+
+ static constexpr ptime from_nsec(const internal_type ns) noexcept { return ptime(ns, UINT64_C(1000000000)); }
+ static constexpr ptime from_usec(const internal_type us) noexcept { return ptime(us, UINT64_C(1000000)); }
+ static constexpr ptime from_msec(const internal_type ms) noexcept { return ptime(ms, UINT64_C(1000)); }
+ static constexpr ptime from_hz(const internal_type hz) noexcept { return ptime(1 , hz); }
+ static constexpr ptime from_raw(const internal_type raw) noexcept { return ptime(raw); }
+ static constexpr ptime from_double(const double t) noexcept { return ptime(static_cast<internal_type>( t * static_cast<double>(resolution)), resolution); }
+
+ static constexpr ptime zero() noexcept { return ptime(0, resolution); }
+ static constexpr ptime quantum() noexcept { return ptime(1, resolution); }
+ static constexpr ptime never() noexcept { return ptime(plib::numeric_limits<internal_type>::max(), resolution); }
private:
+ constexpr explicit ptime(const internal_type time) : m_time(time) {}
internal_type m_time;
};
diff --git a/src/lib/netlist/plib/palloc.cpp b/src/lib/netlist/plib/palloc.cpp
index 2f1131601da..ceee5a75904 100644
--- a/src/lib/netlist/plib/palloc.cpp
+++ b/src/lib/netlist/plib/palloc.cpp
@@ -5,8 +5,6 @@
*
*/
-#include <cstdio>
-
#include "pconfig.h"
#include "palloc.h"
#include "pfmtlog.h"
diff --git a/src/lib/netlist/plib/palloc.h b/src/lib/netlist/plib/palloc.h
index 2d223180b3d..2e4c2809048 100644
--- a/src/lib/netlist/plib/palloc.h
+++ b/src/lib/netlist/plib/palloc.h
@@ -10,9 +10,6 @@
#include <vector>
#include <memory>
-#include <utility>
-
-#include "pconfig.h"
#include "pstring.h"
namespace plib {
@@ -31,7 +28,7 @@ template<typename T>
void pfree(T *ptr) { delete ptr; }
template<typename T>
-inline T* palloc_array(std::size_t num)
+inline T* palloc_array(const std::size_t num)
{
return new T[num]();
}
diff --git a/src/lib/netlist/plib/pchrono.h b/src/lib/netlist/plib/pchrono.h
index e37cd995ab5..5d64f9c4add 100644
--- a/src/lib/netlist/plib/pchrono.h
+++ b/src/lib/netlist/plib/pchrono.h
@@ -9,7 +9,6 @@
#define PCHRONO_H_
#include <cstdint>
-#include <thread>
#include <chrono>
#include "pconfig.h"
diff --git a/src/lib/netlist/plib/pconfig.h b/src/lib/netlist/plib/pconfig.h
index f2164bbde7f..e3870206cbd 100644
--- a/src/lib/netlist/plib/pconfig.h
+++ b/src/lib/netlist/plib/pconfig.h
@@ -8,10 +8,6 @@
#ifndef PCONFIG_H_
#define PCONFIG_H_
-#include <cstdint>
-#include <thread>
-#include <chrono>
-
/*
* Define this for more accurate measurements if you processor supports
* RDTSCP.
@@ -41,6 +37,9 @@ typedef __int128_t INT128;
#endif
#if defined(__GNUC__)
+#ifdef RESTRICT
+#undef RESTRICT
+#endif
#define RESTRICT __restrict__
#define ATTR_UNUSED __attribute__((__unused__))
#else
@@ -52,16 +51,17 @@ typedef __int128_t INT128;
// Standard defines
//============================================================
-// prevent implicit copying
-#define P_PREVENT_COPYING(name) \
- private: \
- name(const name &); \
- name &operator=(const name &);
-
//============================================================
-// cut down delegate implementation
+// Pointer to Member Function
//============================================================
+// This will be autodetected
+// #define PPMF_TYPE 0
+
+#define PPMF_TYPE_PMF 0
+#define PPMF_TYPE_GNUC_PMF_CONV 1
+#define PPMF_TYPE_INTERNAL 2
+
#if defined(__GNUC__)
/* does not work in versions over 4.7.x of 32bit MINGW */
#if defined(__MINGW32__) && !defined(__x86_64) && defined(__i386__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)))
@@ -86,66 +86,12 @@ typedef __int128_t INT128;
#define MEMBER_ABI
#endif
-namespace plib {
-/*
- * The following class was derived from the MAME delegate.h code.
- * It derives a pointer to a member function.
- */
-
-#if (PHAS_PMF_INTERNAL)
- class mfp
- {
- public:
- // construct from any member function pointer
- class generic_class;
- using generic_function = void (*)();
-
- template<typename MemberFunctionType>
- mfp(MemberFunctionType mftp)
- : m_function(0), m_this_delta(0)
- {
- *reinterpret_cast<MemberFunctionType *>(this) = mftp;
- }
-
- // binding helper
- template<typename FunctionType, typename ObjectType>
- FunctionType update_after_bind(ObjectType *object)
- {
- return reinterpret_cast<FunctionType>(
- convert_to_generic(reinterpret_cast<generic_class *>(object)));
- }
- template<typename FunctionType, typename MemberFunctionType, typename ObjectType>
- static FunctionType get_mfp(MemberFunctionType mftp, ObjectType *object)
- {
- mfp mfpo(mftp);
- return mfpo.update_after_bind<FunctionType>(object);
- }
-
- private:
- // extract the generic function and adjust the object pointer
- generic_function convert_to_generic(generic_class * object) const
- {
- // apply the "this" delta to the object first
- generic_class * o_p_delta = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta);
-
- // if the low bit of the vtable index is clear, then it is just a raw function pointer
- if (!(m_function & 1))
- return reinterpret_cast<generic_function>(m_function);
-
- // otherwise, it is the byte index into the vtable where the actual function lives
- std::uint8_t *vtable_base = *reinterpret_cast<std::uint8_t **>(o_p_delta);
- return *reinterpret_cast<generic_function *>(vtable_base + m_function - 1);
- }
-
- // actual state
- uintptr_t m_function; // first item can be one of two things:
- // if even, it's a pointer to the function
- // if odd, it's the byte offset into the vtable
- int m_this_delta; // delta to apply to the 'this' pointer
- };
-
+#ifndef PPMF_TYPE
+ #if PHAS_PMF_INTERNAL
+ #define PPMF_TYPE PPMF_TYPE_INTERNAL
+ #else
+ #define PPMF_TYPE PPMF_TYPE_PMF
+ #endif
#endif
-}
-
#endif /* PCONFIG_H_ */
diff --git a/src/lib/netlist/plib/pdynlib.h b/src/lib/netlist/plib/pdynlib.h
index e91b86e3a82..3a0c12a5f2d 100644
--- a/src/lib/netlist/plib/pdynlib.h
+++ b/src/lib/netlist/plib/pdynlib.h
@@ -7,10 +7,6 @@
#ifndef PDYNLIB_H_
#define PDYNLIB_H_
-#include <cstdarg>
-#include <cstddef>
-
-#include "pconfig.h"
#include "pstring.h"
namespace plib {
diff --git a/src/lib/netlist/plib/pexception.cpp b/src/lib/netlist/plib/pexception.cpp
index 2eedd6f9d16..282acfe30d5 100644
--- a/src/lib/netlist/plib/pexception.cpp
+++ b/src/lib/netlist/plib/pexception.cpp
@@ -11,9 +11,9 @@
#include "pfmtlog.h"
#if (defined(__x86_64__) || defined(__i386__)) && defined(__linux__)
-#define HAS_FEENABLE_EXCEPT (1)
+#define HAS_FEENABLE_EXCEPT (1)
#else
-#define HAS_FEENABLE_EXCEPT (0)
+#define HAS_FEENABLE_EXCEPT (0)
#endif
namespace plib {
diff --git a/src/lib/netlist/plib/pexception.h b/src/lib/netlist/plib/pexception.h
index a4d3b3c498f..9ef3077a75d 100644
--- a/src/lib/netlist/plib/pexception.h
+++ b/src/lib/netlist/plib/pexception.h
@@ -10,7 +10,6 @@
#include <exception>
-#include "pconfig.h"
#include "pstring.h"
namespace plib {
diff --git a/src/lib/netlist/plib/pfmtlog.cpp b/src/lib/netlist/plib/pfmtlog.cpp
index 48b0f1544c1..9451e11866d 100644
--- a/src/lib/netlist/plib/pfmtlog.cpp
+++ b/src/lib/netlist/plib/pfmtlog.cpp
@@ -6,11 +6,8 @@
*/
#include <cstring>
-//FIXME:: pstring should be locale free
-#include <cctype>
#include <cstdlib>
-#include <cstdio>
-
+#include <cstdarg>
#include <algorithm>
#include "pfmtlog.h"
@@ -22,7 +19,7 @@ plog_dispatch_intf::~plog_dispatch_intf()
{
}
-pfmt::pfmt(const pstring &fmt)
+pfmt::pfmt(const pstring fmt)
: m_str(m_str_buf), m_allocated(0), m_arg(0)
{
std::size_t l = fmt.blen() + 1;
@@ -34,18 +31,6 @@ pfmt::pfmt(const pstring &fmt)
memcpy(m_str, fmt.c_str(), l);
}
-pfmt::pfmt(const char *fmt)
-: m_str(m_str_buf), m_allocated(0), m_arg(0)
-{
- std::size_t l = strlen(fmt) + 1;
- if (l>sizeof(m_str_buf))
- {
- m_allocated = 2 * l;
- m_str = palloc_array<char>(2 * l);
- }
- memcpy(m_str, fmt, l);
-}
-
pfmt::~pfmt()
{
if (m_allocated > 0)
diff --git a/src/lib/netlist/plib/pfmtlog.h b/src/lib/netlist/plib/pfmtlog.h
index c5369109b81..681607bddc0 100644
--- a/src/lib/netlist/plib/pfmtlog.h
+++ b/src/lib/netlist/plib/pfmtlog.h
@@ -9,12 +9,19 @@
#include <limits>
-#include "pconfig.h"
#include "pstring.h"
#include "ptypes.h"
namespace plib {
+P_ENUM(plog_level,
+ DEBUG,
+ INFO,
+ VERBOSE,
+ WARNING,
+ ERROR,
+ FATAL)
+
template <typename T>
struct ptype_traits_base
{
@@ -157,13 +164,12 @@ protected:
class pfmt : public pformat_base<pfmt>
{
public:
- explicit pfmt(const pstring &fmt);
- explicit pfmt(const char *fmt);
+ explicit pfmt(const pstring fmt);
virtual ~pfmt();
- operator pstring() const { return m_str; }
+ operator pstring() const { return pstring(m_str, pstring::UTF8); }
- const char *cstr() { return m_str; }
+ const char *c_str() { return m_str; }
protected:
@@ -177,54 +183,53 @@ private:
unsigned m_arg;
};
-P_ENUM(plog_level,
- DEBUG,
- INFO,
- VERBOSE,
- WARNING,
- ERROR,
- FATAL)
-
class plog_dispatch_intf;
template <bool build_enabled = true>
-class pfmt_writer_t
+class pfmt_writer_t : plib::nocopyassignmove
{
public:
- pfmt_writer_t() : m_enabled(true) { }
+ explicit pfmt_writer_t() : m_enabled(true) { }
virtual ~pfmt_writer_t() { }
- void operator ()(const char *fmt) const
+ /* runtime enable */
+ template<bool enabled, typename... Args>
+ void log(const pstring fmt, Args&&... args) const
+ {
+ if (build_enabled && enabled && m_enabled) (*this)(fmt, std::forward<Args>(args)...);
+ }
+
+ void operator ()(const pstring fmt) const
{
if (build_enabled && m_enabled) vdowrite(fmt);
}
template<typename T1>
- void operator ()(const char *fmt, const T1 &v1) const
+ void operator ()(const pstring fmt, const T1 &v1) const
{
if (build_enabled && m_enabled) vdowrite(pfmt(fmt)(v1));
}
template<typename T1, typename T2>
- void operator ()(const char *fmt, const T1 &v1, const T2 &v2) const
+ void operator ()(const pstring fmt, const T1 &v1, const T2 &v2) const
{
if (build_enabled && m_enabled) vdowrite(pfmt(fmt)(v1)(v2));
}
template<typename T1, typename T2, typename T3>
- void operator ()(const char *fmt, const T1 &v1, const T2 &v2, const T3 &v3) const
+ void operator ()(const pstring fmt, const T1 &v1, const T2 &v2, const T3 &v3) const
{
if (build_enabled && m_enabled) vdowrite(pfmt(fmt)(v1)(v2)(v3));
}
template<typename T1, typename T2, typename T3, typename T4>
- void operator ()(const char *fmt, const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) const
+ void operator ()(const pstring fmt, const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) const
{
if (build_enabled && m_enabled) vdowrite(pfmt(fmt)(v1)(v2)(v3)(v4));
}
template<typename T1, typename T2, typename T3, typename T4, typename T5>
- void operator ()(const char *fmt, const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5) const
+ void operator ()(const pstring fmt, const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5) const
{
if (build_enabled && m_enabled) vdowrite(pfmt(fmt)(v1)(v2)(v3)(v4)(v5));
}
@@ -237,18 +242,18 @@ public:
bool is_enabled() const { return m_enabled; }
protected:
- virtual void vdowrite(const pstring &ls) const {}
+ virtual void vdowrite(const pstring &ls) const = 0;
private:
bool m_enabled;
};
-template <plog_level::e L, bool build_enabled = true>
+template <plog_level::E L, bool build_enabled = true>
class plog_channel : public pfmt_writer_t<build_enabled>
{
public:
- explicit plog_channel(plog_dispatch_intf *b) : pfmt_writer_t<build_enabled>(), m_base(b) { }
+ explicit plog_channel(plog_dispatch_intf *b) : pfmt_writer_t<build_enabled>(), m_base(b) { }
virtual ~plog_channel() { }
protected:
@@ -260,7 +265,7 @@ private:
class plog_dispatch_intf
{
- template<plog_level::e, bool> friend class plog_channel;
+ template<plog_level::E, bool> friend class plog_channel;
public:
virtual ~plog_dispatch_intf();
@@ -292,7 +297,7 @@ public:
};
-template <plog_level::e L, bool build_enabled>
+template <plog_level::E L, bool build_enabled>
void plog_channel<L, build_enabled>::vdowrite(const pstring &ls) const
{
m_base->vlog(L, ls);
diff --git a/src/lib/netlist/plib/pfunction.cpp b/src/lib/netlist/plib/pfunction.cpp
new file mode 100644
index 00000000000..b457c940021
--- /dev/null
+++ b/src/lib/netlist/plib/pfunction.cpp
@@ -0,0 +1,212 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * palloc.c
+ *
+ */
+
+#include <cmath>
+#include <stack>
+#include "pfunction.h"
+#include "pfmtlog.h"
+#include "putil.h"
+#include "pexception.h"
+
+namespace plib {
+
+void pfunction::compile(const std::vector<pstring> &inputs, const pstring expr)
+{
+ if (expr.startsWith("rpn:"))
+ compile_postfix(inputs, expr.substr(4));
+ else
+ compile_infix(inputs, expr);
+}
+
+void pfunction::compile_postfix(const std::vector<pstring> &inputs, const pstring expr)
+{
+ std::vector<pstring> cmds(plib::psplit(expr, " "));
+ compile_postfix(inputs, cmds, expr);
+}
+
+void pfunction::compile_postfix(const std::vector<pstring> &inputs,
+ const std::vector<pstring> &cmds, const pstring expr)
+{
+ m_precompiled.clear();
+ int stk = 0;
+
+ for (const pstring &cmd : cmds)
+ {
+ rpn_inst rc;
+ if (cmd == "+")
+ { rc.m_cmd = ADD; stk -= 1; }
+ else if (cmd == "-")
+ { rc.m_cmd = SUB; stk -= 1; }
+ else if (cmd == "*")
+ { rc.m_cmd = MULT; stk -= 1; }
+ else if (cmd == "/")
+ { rc.m_cmd = DIV; stk -= 1; }
+ else if (cmd == "pow")
+ { rc.m_cmd = POW; stk -= 1; }
+ else if (cmd == "sin")
+ { rc.m_cmd = SIN; stk -= 0; }
+ else if (cmd == "cos")
+ { rc.m_cmd = COS; stk -= 0; }
+ else
+ {
+ for (unsigned i = 0; i < inputs.size(); i++)
+ {
+ if (inputs[i] == cmd)
+ {
+ rc.m_cmd = PUSH_INPUT;
+ rc.m_param = i;
+ stk += 1;
+ break;
+ }
+ }
+ if (rc.m_cmd != PUSH_INPUT)
+ {
+ bool err = false;
+ rc.m_cmd = PUSH_CONST;
+ rc.m_param = cmd.as_double(&err);
+ if (err)
+ throw plib::pexception(plib::pfmt("nld_function: unknown/misformatted token <{1}> in <{2}>")(cmd)(expr));
+ stk += 1;
+ }
+ }
+ if (stk < 1)
+ throw plib::pexception(plib::pfmt("nld_function: stack underflow on token <{1}> in <{2}>")(cmd)(expr));
+ m_precompiled.push_back(rc);
+ }
+ if (stk != 1)
+ throw plib::pexception(plib::pfmt("nld_function: stack count different to one on <{2}>")(expr));
+}
+
+static int get_prio(pstring v)
+{
+ if (v == "(" || v == ")")
+ return 1;
+ else if (v.left(v.begin()+1) >= "a" && v.left(v.begin()+1) <= "z")
+ return 0;
+ else if (v == "*" || v == "/")
+ return 20;
+ else if (v == "+" || v == "-")
+ return 10;
+ else if (v == "^")
+ return 30;
+ else
+ return -1;
+}
+
+static pstring pop_check(std::stack<pstring> &stk, const pstring &expr)
+{
+ if (stk.size() == 0)
+ throw plib::pexception(plib::pfmt("nld_function: stack underflow during infix parsing of: <{1}>")(expr));
+ pstring res = stk.top();
+ stk.pop();
+ return res;
+}
+
+void pfunction::compile_infix(const std::vector<pstring> &inputs, const pstring expr)
+{
+ // Shunting-yard infix parsing
+ std::vector<pstring> sep = {"(", ")", ",", "*", "/", "+", "-", "^"};
+ std::vector<pstring> sexpr(plib::psplit(expr.replace(" ",""), sep));
+ std::stack<pstring> opstk;
+ std::vector<pstring> postfix;
+
+ //printf("dbg: %s\n", expr.c_str());
+ for (unsigned i = 0; i < sexpr.size(); i++)
+ {
+ pstring &s = sexpr[i];
+ if (s=="(")
+ opstk.push(s);
+ else if (s==")")
+ {
+ pstring x = pop_check(opstk, expr);
+ while (x != "(")
+ {
+ postfix.push_back(x);
+ x = pop_check(opstk, expr);
+ }
+ if (opstk.size() > 0 && get_prio(opstk.top()) == 0)
+ postfix.push_back(pop_check(opstk, expr));
+ }
+ else if (s==",")
+ {
+ pstring x = pop_check(opstk, expr);
+ while (x != "(")
+ {
+ postfix.push_back(x);
+ x = pop_check(opstk, expr);
+ }
+ opstk.push(x);
+ }
+ else {
+ int p = get_prio(s);
+ if (p>0)
+ {
+ if (opstk.size() == 0)
+ opstk.push(s);
+ else
+ {
+ if (get_prio(opstk.top()) >= get_prio(s))
+ postfix.push_back(pop_check(opstk, expr));
+ opstk.push(s);
+ }
+ }
+ else if (p == 0) // Function or variable
+ {
+ if (sexpr[i+1] == "(")
+ opstk.push(s);
+ else
+ postfix.push_back(s);
+ }
+ else
+ postfix.push_back(s);
+ }
+ }
+ while (opstk.size() > 0)
+ {
+ postfix.push_back(opstk.top());
+ opstk.pop();
+ }
+ compile_postfix(inputs, postfix, expr);
+}
+
+
+#define ST1 stack[ptr]
+#define ST2 stack[ptr-1]
+
+#define OP(OP, ADJ, EXPR) \
+case OP: \
+ ptr-=ADJ; \
+ stack[ptr-1] = EXPR; \
+ break;
+
+double pfunction::evaluate(const std::vector<double> &values)
+{
+ double stack[20];
+ unsigned ptr = 0;
+ for (auto &rc : m_precompiled)
+ {
+ switch (rc.m_cmd)
+ {
+ OP(ADD, 1, ST2 + ST1)
+ OP(MULT, 1, ST2 * ST1)
+ OP(SUB, 1, ST2 - ST1)
+ OP(DIV, 1, ST2 / ST1)
+ OP(POW, 1, std::pow(ST2, ST1))
+ OP(SIN, 0, std::sin(ST2));
+ OP(COS, 0, std::cos(ST2));
+ case PUSH_INPUT:
+ stack[ptr++] = values[static_cast<unsigned>(rc.m_param)];
+ break;
+ case PUSH_CONST:
+ stack[ptr++] = rc.m_param;
+ break;
+ }
+ }
+ return stack[ptr-1];
+}
+
+}
diff --git a/src/lib/netlist/plib/pfunction.h b/src/lib/netlist/plib/pfunction.h
new file mode 100644
index 00000000000..da61fe84e17
--- /dev/null
+++ b/src/lib/netlist/plib/pfunction.h
@@ -0,0 +1,87 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * pfunction.h
+ *
+ */
+
+#ifndef PFUNCTION_H_
+#define PFUNCTION_H_
+
+#include <vector>
+
+#include "pstring.h"
+
+namespace plib {
+
+ //============================================================
+ // function evaluation
+ //============================================================
+
+ /*! Class providing support for evaluating expressions
+ *
+ */
+ class pfunction
+ {
+ enum rpn_cmd
+ {
+ ADD,
+ MULT,
+ SUB,
+ DIV,
+ POW,
+ SIN,
+ COS,
+ PUSH_CONST,
+ PUSH_INPUT
+ };
+ struct rpn_inst
+ {
+ rpn_inst() : m_cmd(ADD), m_param(0.0) { }
+ rpn_cmd m_cmd;
+ double m_param;
+ };
+ public:
+ pfunction()
+ {
+ }
+
+ /*! Compile an expression
+ *
+ * @param inputs Vector of input variables, e.g. {"A","B"}
+ * @param expr infix or postfix expression. default is infix, postrix
+ * to be prefixed with rpn, e.g. "rpn:A B + 1.3 /"
+ */
+ void compile(const std::vector<pstring> &inputs, const pstring expr);
+
+ /*! Compile a rpn expression
+ *
+ * @param inputs Vector of input variables, e.g. {"A","B"}
+ * @param expr Reverse polish notation expression, e.g. "A B + 1.3 /"
+ */
+ void compile_postfix(const std::vector<pstring> &inputs, const pstring expr);
+ /*! Compile an infix expression
+ *
+ * @param inputs Vector of input variables, e.g. {"A","B"}
+ * @param expr Infix expression, e.g. "(A+B)/1.3"
+ */
+ void compile_infix(const std::vector<pstring> &inputs, const pstring expr);
+ /*! Evaluate the expression
+ *
+ * @param values for input variables, e.g. {1.1, 2.2}
+ * @return value of expression
+ */
+ double evaluate(const std::vector<double> &values);
+
+ private:
+
+ void compile_postfix(const std::vector<pstring> &inputs,
+ const std::vector<pstring> &cmds, const pstring expr);
+
+ std::vector<rpn_inst> m_precompiled; //!< precompiled expression
+ };
+
+
+}
+
+#endif /* PEXCEPTION_H_ */
diff --git a/src/lib/netlist/plib/plists.h b/src/lib/netlist/plib/plists.h
index 37f4e2a1391..c6ba2821790 100644
--- a/src/lib/netlist/plib/plists.h
+++ b/src/lib/netlist/plib/plists.h
@@ -10,10 +10,7 @@
#ifndef PLISTS_H_
#define PLISTS_H_
-#include <algorithm>
#include <vector>
-#include <type_traits>
-#include <cmath>
#include "pstring.h"
@@ -56,6 +53,7 @@ public:
template<typename... Args>
void emplace(const std::size_t index, Args&&... args)
{
+ // allocate on buffer
new (&m_buf[index]) C(std::forward<Args>(args)...);
}
diff --git a/src/lib/netlist/plib/poptions.cpp b/src/lib/netlist/plib/poptions.cpp
index a14d4ae93e7..775ee6d8810 100644
--- a/src/lib/netlist/plib/poptions.cpp
+++ b/src/lib/netlist/plib/poptions.cpp
@@ -39,13 +39,13 @@ namespace plib {
{
}
- int option_str::parse(pstring argument)
+ int option_str::parse(const pstring &argument)
{
m_val = argument;
return 0;
}
- int option_str_limit::parse(pstring argument)
+ int option_str_limit::parse(const pstring &argument)
{
if (plib::container::contains(m_limit, argument))
{
@@ -56,20 +56,27 @@ namespace plib {
return 1;
}
- int option_bool::parse(ATTR_UNUSED pstring argument)
+ int option_bool::parse(const pstring &argument)
{
m_val = true;
return 0;
}
- int option_double::parse(pstring argument)
+ int option_double::parse(const pstring &argument)
{
bool err = false;
m_val = argument.as_double(&err);
return (err ? 1 : 0);
}
- int option_vec::parse(pstring argument)
+ int option_long::parse(const pstring &argument)
+ {
+ bool err = false;
+ m_val = argument.as_long(&err);
+ return (err ? 1 : 0);
+ }
+
+ int option_vec::parse(const pstring &argument)
{
bool err = false;
m_val.push_back(argument);
@@ -102,18 +109,18 @@ namespace plib {
int options::parse(int argc, char *argv[])
{
- m_app = argv[0];
+ m_app = pstring(argv[0], pstring::UTF8);
for (int i=1; i<argc; )
{
- pstring arg(argv[i]);
+ pstring arg(argv[i], pstring::UTF8);
option *opt = nullptr;
pstring opt_arg;
bool has_equal_arg = false;
if (arg.startsWith("--"))
{
- auto v = pstring_vector_t(arg.substr(2),"=");
+ auto v = psplit(arg.substr(2),"=");
opt = getopt_long(v[0]);
has_equal_arg = (v.size() > 1);
if (has_equal_arg)
@@ -148,7 +155,7 @@ namespace plib {
else
{
i++; // FIXME: are there more arguments?
- if (opt->parse(argv[i]) != 0)
+ if (opt->parse(pstring(argv[i], pstring::UTF8)) != 0)
return i - 1;
}
}
@@ -166,13 +173,13 @@ namespace plib {
pstring options::split_paragraphs(pstring text, unsigned width, unsigned indent,
unsigned firstline_indent)
{
- auto paragraphs = pstring_vector_t(text,"\n");
+ auto paragraphs = psplit(text,"\n");
pstring ret("");
for (auto &p : paragraphs)
{
pstring line = pstring("").rpad(" ", firstline_indent);
- for (auto &s : pstring_vector_t(p, " "))
+ for (auto &s : psplit(p, " "))
{
if (line.len() + s.len() > width)
{
diff --git a/src/lib/netlist/plib/poptions.h b/src/lib/netlist/plib/poptions.h
index aa5ce07cbc8..f859b2f5b3d 100644
--- a/src/lib/netlist/plib/poptions.h
+++ b/src/lib/netlist/plib/poptions.h
@@ -10,8 +10,6 @@
#ifndef POPTIONS_H_
#define POPTIONS_H_
-#include <cstddef>
-
#include "pstring.h"
#include "plists.h"
#include "putil.h"
@@ -67,7 +65,7 @@ public:
/* no_argument options will be called with "" argument */
- virtual int parse(ATTR_UNUSED pstring argument) = 0;
+ virtual int parse(const pstring &argument) = 0;
pstring short_opt() { return m_short; }
pstring long_opt() { return m_long; }
@@ -85,7 +83,7 @@ public:
: option(parent, ashort, along, help, true), m_val(defval)
{}
- virtual int parse(pstring argument) override;
+ virtual int parse(const pstring &argument) override;
pstring operator ()() { return m_val; }
private:
@@ -96,17 +94,19 @@ class option_str_limit : public option
{
public:
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, ":")
- {}
+ : option(parent, ashort, along, help, true), m_val(defval)
+ {
+ m_limit = plib::psplit(limit, ":");
+ }
- virtual int parse(pstring argument) override;
+ virtual int parse(const pstring &argument) override;
pstring operator ()() { return m_val; }
- const plib::pstring_vector_t &limit() { return m_limit; }
+ const std::vector<pstring> &limit() { return m_limit; }
private:
pstring m_val;
- plib::pstring_vector_t m_limit;
+ std::vector<pstring> m_limit;
};
class option_bool : public option
@@ -116,7 +116,7 @@ public:
: option(parent, ashort, along, help, false), m_val(false)
{}
- virtual int parse(ATTR_UNUSED pstring argument) override;
+ virtual int parse(const pstring &argument) override;
bool operator ()() { return m_val; }
private:
@@ -130,13 +130,27 @@ public:
: option(parent, ashort, along, help, true), m_val(defval)
{}
- virtual int parse(pstring argument) override;
+ virtual int parse(const pstring &argument) override;
double operator ()() { return m_val; }
private:
double m_val;
};
+class option_long : public option
+{
+public:
+ option_long(options &parent, pstring ashort, pstring along, long defval, pstring help)
+ : option(parent, ashort, along, help, true), m_val(defval)
+ {}
+
+ virtual int parse(const pstring &argument) override;
+
+ long operator ()() { return m_val; }
+private:
+ long m_val;
+};
+
class option_vec : public option
{
public:
@@ -144,7 +158,7 @@ public:
: option(parent, ashort, along, help, true)
{}
- virtual int parse(pstring argument) override;
+ virtual int parse(const pstring &argument) override;
std::vector<pstring> operator ()() { return m_val; }
private:
diff --git a/src/lib/netlist/plib/pparser.cpp b/src/lib/netlist/plib/pparser.cpp
index 35629aacdee..6604c07dcb7 100644
--- a/src/lib/netlist/plib/pparser.cpp
+++ b/src/lib/netlist/plib/pparser.cpp
@@ -8,14 +8,15 @@
#include <cstdarg>
#include "pparser.h"
-#include "plib/palloc.h"
+#include "palloc.h"
+#include "putil.h"
namespace plib {
// ----------------------------------------------------------------------------------------
// A simple tokenizer
// ----------------------------------------------------------------------------------------
-ptokenizer::ptokenizer(pistream &strm)
+ptokenizer::ptokenizer(plib::putf8_reader &strm)
: m_strm(strm), m_lineno(0), m_cur_line(""), m_px(m_cur_line.begin()), m_unget(0), m_string('"')
{
}
@@ -302,7 +303,7 @@ void ppreprocessor::error(const pstring &err)
-double ppreprocessor::expr(const pstring_vector_t &sexpr, std::size_t &start, int prio)
+double ppreprocessor::expr(const std::vector<pstring> &sexpr, std::size_t &start, int prio)
{
double val;
pstring tok=sexpr[start];
@@ -383,7 +384,7 @@ ppreprocessor::define_t *ppreprocessor::get_define(const pstring &name)
pstring ppreprocessor::replace_macros(const pstring &line)
{
- pstring_vector_t elems(line, m_expr_sep);
+ std::vector<pstring> elems(psplit(line, m_expr_sep));
pstringbuffer ret = "";
for (auto & elem : elems)
{
@@ -396,7 +397,7 @@ pstring ppreprocessor::replace_macros(const pstring &line)
return ret;
}
-static pstring catremainder(const pstring_vector_t &elems, std::size_t start, pstring sep)
+static pstring catremainder(const std::vector<pstring> &elems, std::size_t start, pstring sep)
{
pstringbuffer ret = "";
for (auto & elem : elems)
@@ -415,13 +416,13 @@ pstring ppreprocessor::process_line(const pstring &line)
// FIXME ... revise and extend macro handling
if (lt.startsWith("#"))
{
- pstring_vector_t lti(lt, " ", true);
+ std::vector<pstring> lti(psplit(lt, " ", true));
if (lti[0].equals("#if"))
{
m_level++;
std::size_t start = 0;
lt = replace_macros(lt);
- pstring_vector_t t(lt.substr(3).replace(" ",""), m_expr_sep);
+ std::vector<pstring> t(psplit(lt.substr(3).replace(" ",""), m_expr_sep));
int val = static_cast<int>(expr(t, start, 0));
if (val == 0)
m_ifflag |= (1 << m_level);
@@ -483,7 +484,7 @@ pstring ppreprocessor::process_line(const pstring &line)
}
-postream & ppreprocessor::process_i(pistream &istrm, postream &ostrm)
+void ppreprocessor::process(putf8_reader &istrm, putf8_writer &ostrm)
{
pstring line;
while (istrm.readline(line))
@@ -491,7 +492,6 @@ postream & ppreprocessor::process_i(pistream &istrm, postream &ostrm)
line = process_line(line);
ostrm.writeline(line);
}
- return ostrm;
}
}
diff --git a/src/lib/netlist/plib/pparser.h b/src/lib/netlist/plib/pparser.h
index db88299d85c..321dad2f608 100644
--- a/src/lib/netlist/plib/pparser.h
+++ b/src/lib/netlist/plib/pparser.h
@@ -11,18 +11,16 @@
#include <unordered_map>
#include <cstdint>
-#include "pconfig.h"
#include "pstring.h"
#include "plists.h"
-#include "putil.h"
+//#include "putil.h"
#include "pstream.h"
namespace plib {
-class ptokenizer
+class ptokenizer : nocopyassignmove
{
- P_PREVENT_COPYING(ptokenizer)
public:
- explicit ptokenizer(pistream &strm);
+ explicit ptokenizer(plib::putf8_reader &strm);
virtual ~ptokenizer();
@@ -126,7 +124,7 @@ private:
bool eof() { return m_strm.eof(); }
- pistream &m_strm;
+ putf8_reader &m_strm;
int m_lineno;
pstring m_cur_line;
@@ -148,9 +146,8 @@ private:
};
-class ppreprocessor
+class ppreprocessor : plib::nocopyassignmove
{
- P_PREVENT_COPYING(ppreprocessor)
public:
struct define_t
@@ -165,22 +162,12 @@ public:
ppreprocessor(std::vector<define_t> *defines = nullptr);
virtual ~ppreprocessor() {}
- template<class ISTR, class OSTR>
- OSTR &process(ISTR &istrm, OSTR &ostrm)
- {
- return dynamic_cast<OSTR &>(process_i(istrm, ostrm));
- }
+ void process(putf8_reader &istrm, putf8_writer &ostrm);
protected:
-
- postream &process_i(pistream &istrm, postream &ostrm);
-
- double expr(const plib::pstring_vector_t &sexpr, std::size_t &start, int prio);
-
+ double expr(const std::vector<pstring> &sexpr, std::size_t &start, int prio);
define_t *get_define(const pstring &name);
-
pstring replace_macros(const pstring &line);
-
virtual void error(const pstring &err);
private:
@@ -188,9 +175,9 @@ private:
pstring process_line(const pstring &line);
std::unordered_map<pstring, define_t> m_defines;
- plib::pstring_vector_t m_expr_sep;
+ std::vector<pstring> m_expr_sep;
- std::uint_least32_t m_ifflag; // 31 if levels
+ std::uint_least64_t m_ifflag; // 31 if levels
int m_level;
int m_lineno;
};
diff --git a/src/lib/netlist/plib/ppmf.h b/src/lib/netlist/plib/ppmf.h
new file mode 100644
index 00000000000..03a2a65baa4
--- /dev/null
+++ b/src/lib/netlist/plib/ppmf.h
@@ -0,0 +1,198 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * ppmf.h
+ *
+ */
+
+#ifndef PPMF_H_
+#define PPMF_H_
+
+#include "pconfig.h"
+#include <utility>
+#include <cstdint>
+
+
+/*
+ *
+ * NL_PMF_TYPE_GNUC_PMF
+ * Use standard pointer to member function syntax C++11
+ *
+ * NL_PMF_TYPE_GNUC_PMF_CONV
+ * Use gnu extension and convert the pmf to a function pointer.
+ * This is not standard compliant and needs
+ * -Wno-pmf-conversions to compile.
+ *
+ * NL_PMF_TYPE_INTERNAL
+ * Use the same approach as MAME for deriving the function pointer.
+ * This is compiler-dependent as well
+ *
+ * Benchmarks for ./nltool -c run -f src/mame/machine/nl_pong.cpp -t 10 -n pong_fast
+ *
+ * NL_PMF_TYPE_INTERNAL: 215% 215%
+ * NL_PMF_TYPE_GNUC_PMF: 163% 196%
+ * NL_PMF_TYPE_GNUC_PMF_CONV: 215% 215%
+ * NL_PMF_TYPE_VIRTUAL: 213% 209%
+ *
+ * The whole exercise was done to avoid virtual calls. In prior versions of
+ * netlist, the INTERNAL and GNUC_PMF_CONV approach provided significant improvement.
+ * Since than, "hot" was removed from functions declared as virtual.
+ * This may explain that the recent benchmarks show no difference at all.
+ *
+ */
+
+#if (PPMF_TYPE == PPMF_TYPE_GNUC_PMF_CONV)
+#pragma GCC diagnostic ignored "-Wpmf-conversions"
+#endif
+
+namespace plib {
+/*
+ * The following class was derived from the MAME delegate.h code.
+ * It derives a pointer to a member function.
+ */
+
+#if (PHAS_PMF_INTERNAL)
+ class mfp
+ {
+ public:
+ // construct from any member function pointer
+ class generic_class;
+ using generic_function = void (*)();
+
+ template<typename MemberFunctionType>
+ mfp(MemberFunctionType mftp)
+ : m_function(0), m_this_delta(0)
+ {
+ *reinterpret_cast<MemberFunctionType *>(this) = mftp;
+ }
+
+ template<typename FunctionType, typename MemberFunctionType, typename ObjectType>
+ static FunctionType get_mfp(MemberFunctionType mftp, ObjectType *object)
+ {
+ mfp mfpo(mftp);
+ //return mfpo.update_after_bind<FunctionType>(object);
+ return reinterpret_cast<FunctionType>(
+ mfpo.convert_to_generic(reinterpret_cast<generic_class *>(object)));
+ }
+
+ private:
+ // extract the generic function and adjust the object pointer
+ generic_function convert_to_generic(generic_class * object) const
+ {
+ // apply the "this" delta to the object first
+ generic_class * o_p_delta = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta);
+
+ // if the low bit of the vtable index is clear, then it is just a raw function pointer
+ if (!(m_function & 1))
+ return reinterpret_cast<generic_function>(m_function);
+
+ // otherwise, it is the byte index into the vtable where the actual function lives
+ std::uint8_t *vtable_base = *reinterpret_cast<std::uint8_t **>(o_p_delta);
+ return *reinterpret_cast<generic_function *>(vtable_base + m_function - 1);
+ }
+
+ // actual state
+ uintptr_t m_function; // first item can be one of two things:
+ // if even, it's a pointer to the function
+ // if odd, it's the byte offset into the vtable
+ int m_this_delta; // delta to apply to the 'this' pointer
+ };
+#endif
+
+#if (PPMF_TYPE == PPMF_TYPE_PMF)
+ template<typename R, typename... Targs>
+ class pmfp_base
+ {
+ public:
+ class generic_class;
+#if defined (__INTEL_COMPILER) && defined (_M_X64) // needed for "Intel(R) C++ Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 14.0.2.176 Build 20140130" at least
+ using generic_function = int [((sizeof(void *) + 4 * sizeof(int)) + (sizeof(int) - 1)) / sizeof(int)];
+#elif defined(_MSC_VER)// all other cases - for MSVC maximum size is one pointer, plus 3 ints; all other implementations seem to be smaller
+ using generic_function = int [((sizeof(void *) + 3 * sizeof(int)) + (sizeof(int) - 1)) / sizeof(int)];
+#else
+ using generic_function = R (generic_class::*)(Targs...);
+#endif
+ pmfp_base() {}
+
+ template<typename MemberFunctionType, typename O>
+ void set_base(MemberFunctionType mftp, O *object)
+ {
+ using function_ptr = R (O::*)(Targs...);
+ function_ptr t = mftp;
+ *reinterpret_cast<function_ptr *>(&m_func) = t;
+ }
+ template<typename O>
+ inline R call(O *obj, Targs... args)
+ {
+ using function_ptr = R (O::*)(Targs...);
+ function_ptr t = *reinterpret_cast<function_ptr *>(&m_func);
+ return (obj->*t)(std::forward<Targs>(args)...);
+ }
+ private:
+ generic_function m_func;
+ };
+
+#elif ((PPMF_TYPE == PPMF_TYPE_GNUC_PMF_CONV) || (PPMF_TYPE == PPMF_TYPE_INTERNAL))
+ template<typename R, typename... Targs>
+ class pmfp_base
+ {
+ public:
+ using generic_function = void (*)();
+
+ pmfp_base() : m_func(nullptr) {}
+
+ template<typename MemberFunctionType, typename O>
+ void set_base(MemberFunctionType mftp, O *object)
+ {
+ #if (PPMF_TYPE == PPMF_TYPE_INTERNAL)
+ using function_ptr = MEMBER_ABI R (*)(O *obj, Targs... args);
+ m_func = reinterpret_cast<generic_function>(plib::mfp::get_mfp<function_ptr>(mftp, object));
+ #elif (PPMF_TYPE == PPMF_TYPE_GNUC_PMF_CONV)
+ R (O::* pFunc)(Targs...) = mftp;
+ m_func = reinterpret_cast<generic_function>((object->*pFunc));
+ #endif
+ }
+ template<typename O>
+ inline R call(O *obj, Targs... args) const
+ {
+ using function_ptr = MEMBER_ABI R (*)(O *obj, Targs... args);
+ return (reinterpret_cast<function_ptr>(m_func))(obj, std::forward<Targs>(args)...);
+ }
+ bool is_set() { return m_func != nullptr; }
+ private:
+ generic_function m_func;
+ };
+#endif
+
+ template<typename R, typename... Targs>
+ class pmfp : public pmfp_base<R, Targs...>
+ {
+ public:
+ class generic_class;
+ pmfp() : pmfp_base<R, Targs...>(), m_obj(nullptr) {}
+
+ template<typename MemberFunctionType, typename O>
+ pmfp(MemberFunctionType mftp, O *object)
+ {
+ this->set(mftp, object);
+ }
+
+ template<typename MemberFunctionType, typename O>
+ void set(MemberFunctionType mftp, O *object)
+ {
+ this->set_base(mftp, object);
+ m_obj = reinterpret_cast<generic_class *>(object);
+ }
+
+ inline R operator()(Targs... args)
+ {
+ return this->call(m_obj, std::forward<Targs>(args)...);
+ }
+ private:
+ generic_class *m_obj;
+ };
+
+
+}
+
+#endif /* PPMF_H_ */
diff --git a/src/lib/netlist/plib/pstate.h b/src/lib/netlist/plib/pstate.h
index 7c25bf4d722..4256fa45152 100644
--- a/src/lib/netlist/plib/pstate.h
+++ b/src/lib/netlist/plib/pstate.h
@@ -8,13 +8,12 @@
#ifndef PSTATE_H_
#define PSTATE_H_
-#include <memory>
-#include <type_traits>
-
-#include "plists.h"
#include "pstring.h"
#include "ptypes.h"
+#include <vector>
+#include <memory>
+
// ----------------------------------------------------------------------------------------
// state saving ...
// ----------------------------------------------------------------------------------------
diff --git a/src/lib/netlist/plib/pstream.cpp b/src/lib/netlist/plib/pstream.cpp
index b05d86d7bc5..efbf2aa2374 100644
--- a/src/lib/netlist/plib/pstream.cpp
+++ b/src/lib/netlist/plib/pstream.cpp
@@ -27,28 +27,6 @@ pistream::~pistream()
{
}
-bool pistream::readline(pstring &line)
-{
- char c = 0;
- m_linebuf.clear();
- if (!this->readbyte(c))
- {
- line = "";
- return false;
- }
- while (true)
- {
- if (c == 10)
- break;
- else if (c != 13) /* ignore CR */
- m_linebuf += c;
- if (!this->readbyte(c))
- break;
- }
- line = m_linebuf;
- return true;
-}
-
// -----------------------------------------------------------------------------
// postream: output stream
// -----------------------------------------------------------------------------
@@ -367,9 +345,43 @@ pstream::pos_type pomemstream::vtell()
return m_pos;
}
-pstream_fmt_writer_t::~pstream_fmt_writer_t()
+bool putf8_reader::readline(pstring &line)
{
+ pstring::code_t c = 0;
+ m_linebuf.clear();
+ if (!this->readcode(c))
+ {
+ line = "";
+ return false;
+ }
+ while (true)
+ {
+ if (c == 10)
+ break;
+ else if (c != 13) /* ignore CR */
+ m_linebuf += pstring(c);
+ if (!this->readcode(c))
+ break;
+ }
+ line = m_linebuf;
+ return true;
}
+putf8_fmt_writer::putf8_fmt_writer(postream &strm)
+: pfmt_writer_t()
+, putf8_writer(strm)
+{
+}
+
+putf8_fmt_writer::~putf8_fmt_writer()
+{
+}
+
+void putf8_fmt_writer::vdowrite(const pstring &ls) const
+{
+ write(ls);
+}
+
+
}
diff --git a/src/lib/netlist/plib/pstream.h b/src/lib/netlist/plib/pstream.h
index 6d02c4d1551..83c514da2e1 100644
--- a/src/lib/netlist/plib/pstream.h
+++ b/src/lib/netlist/plib/pstream.h
@@ -7,9 +7,6 @@
#ifndef PSTREAM_H_
#define PSTREAM_H_
-#include <cstdarg>
-#include <cstddef>
-
#include "pconfig.h"
#include "pstring.h"
#include "pfmtlog.h"
@@ -20,9 +17,8 @@ namespace plib {
// pstream: things common to all streams
// -----------------------------------------------------------------------------
-class pstream
+class pstream : nocopyassignmove
{
- P_PREVENT_COPYING(pstream)
public:
using pos_type = std::size_t;
@@ -73,7 +69,6 @@ private:
class pistream : public pstream
{
- P_PREVENT_COPYING(pistream)
public:
explicit pistream(const unsigned flags) : pstream(flags) {}
@@ -81,15 +76,6 @@ public:
bool eof() const { return ((flags() & FLAG_EOF) != 0); }
- /* this digests linux & dos/windows text files */
-
- bool readline(pstring &line);
-
- bool readbyte(char &b)
- {
- return (read(&b, 1) == 1);
- }
-
pos_type read(void *buf, const unsigned n)
{
return vread(buf, n);
@@ -99,8 +85,6 @@ protected:
/* read up to n bytes from stream */
virtual pos_type vread(void *buf, const pos_type n) = 0;
-private:
- pstringbuffer m_linebuf;
};
// -----------------------------------------------------------------------------
@@ -109,30 +93,11 @@ private:
class postream : public pstream
{
- P_PREVENT_COPYING(postream)
public:
explicit postream(unsigned flags) : pstream(flags) {}
virtual ~postream();
- /* this digests linux & dos/windows text files */
-
- void writeline(const pstring &line)
- {
- write(line);
- write(10);
- }
-
- void write(const pstring &text)
- {
- write(text.c_str(), text.blen());
- }
-
- void write(const char c)
- {
- write(&c, 1);
- }
-
void write(const void *buf, const pos_type n)
{
vwrite(buf, n);
@@ -153,7 +118,6 @@ private:
class pomemstream : public postream
{
- P_PREVENT_COPYING(pomemstream)
public:
pomemstream();
@@ -177,8 +141,6 @@ private:
class postringstream : public postream
{
- P_PREVENT_COPYING(postringstream )
-
public:
postringstream() : postream(0) { }
@@ -205,7 +167,6 @@ private:
class pofilestream : public postream
{
- P_PREVENT_COPYING(pofilestream)
public:
explicit pofilestream(const pstring &fname);
@@ -233,7 +194,6 @@ private:
class pstderr : public pofilestream
{
- P_PREVENT_COPYING(pstderr)
public:
pstderr();
virtual ~pstderr();
@@ -245,7 +205,6 @@ public:
class pstdout : public pofilestream
{
- P_PREVENT_COPYING(pstdout)
public:
pstdout();
virtual ~pstdout();
@@ -257,7 +216,6 @@ public:
class pifilestream : public pistream
{
- P_PREVENT_COPYING(pifilestream)
public:
explicit pifilestream(const pstring &fname);
@@ -286,7 +244,6 @@ private:
class pstdin : public pifilestream
{
- P_PREVENT_COPYING(pstdin)
public:
pstdin();
@@ -299,13 +256,13 @@ public:
class pimemstream : public pistream
{
- P_PREVENT_COPYING(pimemstream)
public:
pimemstream(const void *mem, const pos_type len);
explicit pimemstream(const pomemstream &ostrm);
virtual ~pimemstream();
+ pos_type size() const { return m_len; }
protected:
/* read up to n bytes from stream */
virtual pos_type vread(void *buf, const pos_type n) override;
@@ -324,7 +281,6 @@ private:
class pistringstream : public pimemstream
{
- P_PREVENT_COPYING(pistringstream)
public:
pistringstream(const pstring &str) : pimemstream(str.c_str(), str.len()), m_str(str) { }
virtual ~pistringstream();
@@ -335,27 +291,86 @@ private:
};
// -----------------------------------------------------------------------------
-// pstream_fmt_writer_t: writer on top of ostream
+// putf8reader_t: reader on top of istream
// -----------------------------------------------------------------------------
-class pstream_fmt_writer_t : public plib::pfmt_writer_t<>
+/* this digests linux & dos/windows text files */
+
+class putf8_reader : plib::nocopyassignmove
{
- P_PREVENT_COPYING(pstream_fmt_writer_t)
public:
+ explicit putf8_reader(pistream &strm) : m_strm(strm) {}
+ virtual ~putf8_reader() {}
- explicit pstream_fmt_writer_t(postream &strm) : m_strm(strm) {}
- virtual ~pstream_fmt_writer_t();
+ bool eof() const { return m_strm.eof(); }
+ bool readline(pstring &line);
-protected:
- virtual void vdowrite(const pstring &ls) const override
+ bool readbyte1(char &b)
+ {
+ return (m_strm.read(&b, 1) == 1);
+ }
+
+ bool readcode(pstring::code_t &c)
+ {
+ char b[4];
+ if (m_strm.read(&b[0], 1) != 1)
+ return false;
+ const unsigned l = pstring::traits::codelen(b);
+ for (unsigned i = 1; i < l; i++)
+ if (m_strm.read(&b[i], 1) != 1)
+ return false;
+ c = pstring::traits::code(b);
+ return true;
+ }
+
+private:
+ pistream &m_strm;
+ pstringbuffer m_linebuf;
+};
+
+// -----------------------------------------------------------------------------
+// putf8writer_t: writer on top of ostream
+// -----------------------------------------------------------------------------
+
+class putf8_writer : plib::nocopyassignmove
+{
+public:
+ explicit putf8_writer(postream &strm) : m_strm(strm) {}
+ virtual ~putf8_writer() {}
+
+ void writeline(const pstring &line) const
{
- m_strm.write(ls);
+ write(line);
+ write(10);
+ }
+
+ void write(const pstring &text) const
+ {
+ m_strm.write(text.c_str(), text.blen());
+ }
+
+ void write(const pstring::code_t c) const
+ {
+ write(pstring(c));
}
private:
postream &m_strm;
};
+class putf8_fmt_writer : public pfmt_writer_t<>, public putf8_writer
+{
+public:
+
+ explicit putf8_fmt_writer(postream &strm);
+ virtual ~putf8_fmt_writer();
+
+protected:
+ virtual void vdowrite(const pstring &ls) const override;
+
+private:
+};
+
}
#endif /* PSTREAM_H_ */
diff --git a/src/lib/netlist/plib/pstring.cpp b/src/lib/netlist/plib/pstring.cpp
index 2506357c9a5..baeace1edb9 100644
--- a/src/lib/netlist/plib/pstring.cpp
+++ b/src/lib/netlist/plib/pstring.cpp
@@ -6,17 +6,16 @@
*/
#include <cstring>
-//FIXME:: pstring should be locale free
-#include <cctype>
-#include <cstdlib>
-#include <cstdio>
#include <algorithm>
#include <stack>
+#include <cstdlib>
#include "pstring.h"
#include "palloc.h"
#include "plists.h"
+template <typename F> pstr_t pstring_t<F>::m_zero(0);
+
template<typename F>
pstring_t<F>::~pstring_t()
{
@@ -97,14 +96,15 @@ const pstring_t<F> pstring_t<F>::substr(const iterator start, const iterator end
return ret;
}
-
template<typename F>
const pstring_t<F> pstring_t<F>::ucase() const
{
- pstring_t ret = *this;
- ret.pcopy(c_str(), blen());
- for (std::size_t i=0; i<ret.len(); i++)
- ret.m_ptr->str()[i] = static_cast<char>(toupper(static_cast<int>(ret.m_ptr->str()[i])));
+ pstring_t ret = "";
+ for (auto c : *this)
+ if (c >= 'a' && c <= 'z')
+ ret += (c - 'a' + 'A');
+ else
+ ret += c;
return ret;
}
@@ -151,7 +151,7 @@ typename pstring_t<F>::iterator pstring_t<F>::find_last_not_of(const pstring_t &
}
template<typename F>
-typename pstring_t<F>::iterator pstring_t<F>::find(const pstring_t &search, iterator start) const
+typename pstring_t<F>::iterator pstring_t<F>::find(const pstring_t search, iterator start) const
{
for (; start != end(); ++start)
{
@@ -169,6 +169,15 @@ typename pstring_t<F>::iterator pstring_t<F>::find(const pstring_t &search, iter
}
template<typename F>
+typename pstring_t<F>::iterator pstring_t<F>::find(const code_t search, iterator start) const
+{
+ mem_t buf[traits::MAXCODELEN+1] = { 0 };
+ traits::encode(search, buf);
+ return find(pstring_t(&buf[0], UTF8), start);
+}
+
+
+template<typename F>
pstring_t<F> pstring_t<F>::replace(const pstring_t &search, const pstring_t &replace) const
{
pstring_t ret("");
@@ -188,13 +197,13 @@ pstring_t<F> pstring_t<F>::replace(const pstring_t &search, const pstring_t &rep
}
template<typename F>
-const pstring_t<F> pstring_t<F>::ltrim(const pstring_t &ws) const
+const pstring_t<F> pstring_t<F>::ltrim(const pstring_t ws) const
{
return substr(find_first_not_of(ws), end());
}
template<typename F>
-const pstring_t<F> pstring_t<F>::rtrim(const pstring_t &ws) const
+const pstring_t<F> pstring_t<F>::rtrim(const pstring_t ws) const
{
auto f = find_last_not_of(ws);
if (f==end())
@@ -230,7 +239,7 @@ double pstring_t<F>::as_double(bool *error) const
if (error != nullptr)
*error = false;
- ret = strtod(c_str(), &e);
+ ret = std::strtod(c_str(), &e);
if (*e != 0)
if (error != nullptr)
*error = true;
@@ -246,9 +255,9 @@ long pstring_t<F>::as_long(bool *error) const
if (error != nullptr)
*error = false;
if (startsWith("0x"))
- ret = strtol(substr(2).c_str(), &e, 16);
+ ret = std::strtol(substr(2).c_str(), &e, 16);
else
- ret = strtol(c_str(), &e, 10);
+ ret = std::strtol(c_str(), &e, 10);
if (*e != 0)
if (error != nullptr)
*error = true;
@@ -256,24 +265,6 @@ long pstring_t<F>::as_long(bool *error) const
}
template<typename F>
-typename pstring_t<F>::iterator pstring_t<F>::find(const mem_t *search, iterator start) const
-{
- for (; start != end(); ++start)
- {
- iterator itc(start);
- iterator cmp(search);
- while (itc != end() && *cmp != 0 && *itc == *cmp)
- {
- ++itc;
- ++cmp;
- }
- if (*cmp == 0)
- return start;
- }
- return end();
-}
-
-template<typename F>
bool pstring_t<F>::startsWith(const pstring_t &arg) const
{
if (arg.blen() > blen())
@@ -291,17 +282,6 @@ bool pstring_t<F>::endsWith(const pstring_t &arg) const
return (memcmp(c_str()+this->blen()-arg.blen(), arg.c_str(), arg.blen()) == 0);
}
-
-template<typename F>
-bool pstring_t<F>::startsWith(const mem_t *arg) const
-{
- std::size_t alen = strlen(arg);
- if (alen > blen())
- return false;
- else
- return (memcmp(arg, c_str(), alen) == 0);
-}
-
template<typename F>
int pstring_t<F>::pcmp(const mem_t *right) const
{
@@ -435,8 +415,8 @@ static inline std::size_t countleadbits(std::size_t x)
template<typename F>
void pstring_t<F>::sfree(pstr_t *s)
{
- s->m_ref_count--;
- if (s->m_ref_count == 0 && s != &m_zero)
+ bool b = s->dec_and_check();
+ if ( b && s != &m_zero)
{
if (stk != nullptr)
{
@@ -445,7 +425,6 @@ void pstring_t<F>::sfree(pstr_t *s)
}
else
plib::pfree_array(reinterpret_cast<char *>(s));
- //_mm_free(((char *)s));
}
}
@@ -492,16 +471,15 @@ void pstring_t<F>::resetmem()
template<typename F>
void pstring_t<F>::sfree(pstr_t *s)
{
- s->m_ref_count--;
- if (s->m_ref_count == 0 && s != &m_zero)
+ bool b = s->dec_and_check();
+ if ( b && s != &m_zero)
{
plib::pfree_array(((char *)s));
- //_mm_free(((char *)s));
}
}
template<typename F>
-pstr_t *pstring_t<F>::salloc(int n)
+pstr_t *pstring_t<F>::salloc(std::size_t n)
{
int size = sizeof(pstr_t) + n + 1;
pstr_t *p = (pstr_t *) plib::palloc_array<char>(size);
diff --git a/src/lib/netlist/plib/pstring.h b/src/lib/netlist/plib/pstring.h
index 16bf61b08ee..80a8fc4e78e 100644
--- a/src/lib/netlist/plib/pstring.h
+++ b/src/lib/netlist/plib/pstring.h
@@ -7,11 +7,8 @@
#ifndef PSTRING_H_
#define PSTRING_H_
-#include <cstdarg>
-#include <cstddef>
#include <iterator>
-
-#include "pconfig.h"
+#include <exception>
// ----------------------------------------------------------------------------------------
// pstring: immutable strings ...
@@ -22,27 +19,24 @@
struct pstr_t
{
- //str_t() : m_ref_count(1), m_len(0) { m_str[0] = 0; }
- pstr_t(const std::size_t alen)
- {
- init(alen);
- }
+ pstr_t(const std::size_t alen) { init(alen); }
void init(const std::size_t alen)
{
- m_ref_count = 1;
- m_len = alen;
- m_str[0] = 0;
+ m_ref_count = 1;
+ m_len = alen;
+ m_str[0] = 0;
}
char *str() { return &m_str[0]; }
unsigned char *ustr() { return reinterpret_cast<unsigned char *>(&m_str[0]); }
std::size_t len() const { return m_len; }
- int m_ref_count;
+ void inc() { m_ref_count++; }
+ bool dec_and_check() { --m_ref_count; return m_ref_count == 0; }
private:
+ int m_ref_count;
std::size_t m_len;
char m_str[1];
};
-
template <typename F>
struct pstring_t
{
@@ -53,20 +47,38 @@ public:
typedef typename F::code_t code_t;
typedef std::size_t size_type;
+ enum enc_t
+ {
+ UTF8
+ };
+
// simple construction/destruction
- pstring_t()
+ pstring_t() : m_ptr(&m_zero)
{
- init();
+ init(nullptr);
}
~pstring_t();
- // construction with copy
- pstring_t(const mem_t *string) { init(); if (string != nullptr && *string != 0) pcopy(string); }
- pstring_t(const pstring_t &string) { init(); pcopy(string); }
+ // FIXME: Do something with encoding
+ pstring_t(const mem_t *string, const enc_t enc) : m_ptr(&m_zero)
+ {
+ init(string);
+ }
+
+ template<typename C, std::size_t N>
+ pstring_t(C (&string)[N]) : m_ptr(&m_zero) {
+ static_assert(std::is_same<C, const mem_t>::value, "pstring constructor only accepts const mem_t");
+ static_assert(N>0,"pstring from array of length 0");
+ if (string[N-1] != 0)
+ throw std::exception();
+ init(string);
+ }
+
+ pstring_t(const pstring_t &string) : m_ptr(&m_zero) { init(string); }
pstring_t(pstring_t &&string) : m_ptr(string.m_ptr) { string.m_ptr = nullptr; }
+ explicit pstring_t(code_t code) : m_ptr(&m_zero) { pstring_t t; t+= code; init(t); }
// assignment operators
- pstring_t &operator=(const mem_t *string) { pcopy(string); return *this; }
pstring_t &operator=(const pstring_t &string) { pcopy(string); return *this; }
struct iterator final : public std::iterator<std::forward_iterator_tag, mem_t>
@@ -94,41 +106,24 @@ public:
// concatenation operators
pstring_t& operator+=(const pstring_t &string) { pcat(string); return *this; }
- pstring_t& operator+=(const mem_t *string) { pcat(string); return *this; }
friend pstring_t operator+(const pstring_t &lhs, const pstring_t &rhs) { return pstring_t(lhs) += rhs; }
- friend pstring_t operator+(const pstring_t &lhs, const mem_t *rhs) { return pstring_t(lhs) += rhs; }
- friend pstring_t operator+(const mem_t *lhs, const pstring_t &rhs) { return pstring_t(lhs) += rhs; }
// comparison operators
- bool operator==(const mem_t *string) const { return (pcmp(string) == 0); }
bool operator==(const pstring_t &string) const { return (pcmp(string) == 0); }
- bool operator!=(const mem_t *string) const { return (pcmp(string) != 0); }
bool operator!=(const pstring_t &string) const { return (pcmp(string) != 0); }
- bool operator<(const mem_t *string) const { return (pcmp(string) < 0); }
bool operator<(const pstring_t &string) const { return (pcmp(string) < 0); }
- bool operator<=(const mem_t *string) const { return (pcmp(string) <= 0); }
bool operator<=(const pstring_t &string) const { return (pcmp(string) <= 0); }
- bool operator>(const mem_t *string) const { return (pcmp(string) > 0); }
bool operator>(const pstring_t &string) const { return (pcmp(string) > 0); }
- bool operator>=(const mem_t *string) const { return (pcmp(string) >= 0); }
bool operator>=(const pstring_t &string) const { return (pcmp(string) >= 0); }
bool equals(const pstring_t &string) const { return (pcmp(string) == 0); }
-
- //int cmp(const pstring_t &string) const { return pcmp(string); }
- //int cmp(const mem_t *string) const { return pcmp(string); }
-
bool startsWith(const pstring_t &arg) const;
- bool startsWith(const mem_t *arg) const;
-
bool endsWith(const pstring_t &arg) const;
- bool endsWith(const mem_t *arg) const { return endsWith(pstring_t(arg)); }
pstring_t replace(const pstring_t &search, const pstring_t &replace) const;
-
const pstring_t cat(const pstring_t &s) const { return *this + s; }
- const pstring_t cat(const mem_t *s) const { return *this + s; }
+ const pstring_t cat(const code_t c) const { return *this + c; }
size_type blen() const { return m_ptr->len(); }
@@ -145,11 +140,9 @@ public:
pstring_t& operator+=(const code_t c) { mem_t buf[traits::MAXCODELEN+1] = { 0 }; traits::encode(c, buf); pcat(buf); return *this; }
friend pstring_t operator+(const pstring_t &lhs, const code_t rhs) { return pstring_t(lhs) += rhs; }
- iterator find(const pstring_t &search, iterator start) const;
- iterator find(const pstring_t &search) const { return find(search, begin()); }
- iterator find(const mem_t *search, iterator start) const;
- iterator find(const mem_t *search) const { return find(search, begin()); }
- iterator find(const code_t search, iterator start) const { mem_t buf[traits::MAXCODELEN+1] = { 0 }; traits::encode(search, buf); return find(buf, start); }
+ iterator find(const pstring_t search, iterator start) const;
+ iterator find(const pstring_t search) const { return find(search, begin()); }
+ iterator find(const code_t search, iterator start) const;
iterator find(const code_t search) const { return find(search, begin()); }
const pstring_t substr(const iterator start, const iterator end) const ;
@@ -162,9 +155,9 @@ public:
iterator find_first_not_of(const pstring_t &no) const;
iterator find_last_not_of(const pstring_t &no) const;
- const pstring_t ltrim(const pstring_t &ws = " \t\n\r") const;
- const pstring_t rtrim(const pstring_t &ws = " \t\n\r") const;
- const pstring_t trim(const pstring_t &ws = " \t\n\r") const { return this->ltrim(ws).rtrim(ws); }
+ const pstring_t ltrim(const pstring_t ws = pstring_t(" \t\n\r")) const;
+ const pstring_t rtrim(const pstring_t ws = pstring_t(" \t\n\r")) const;
+ const pstring_t trim(const pstring_t ws = pstring_t(" \t\n\r")) const { return this->ltrim(ws).rtrim(ws); }
const pstring_t rpad(const pstring_t &ws, const size_type cnt) const;
@@ -178,10 +171,16 @@ protected:
pstr_t *m_ptr;
private:
- void init()
+ void init(const mem_t *string)
+ {
+ m_ptr->inc();
+ if (string != nullptr && *string != 0)
+ pcopy(string);
+ }
+ void init(const pstring_t &string)
{
- m_ptr = &m_zero;
- m_ptr->m_ref_count++;
+ m_ptr->inc();
+ pcopy(string);
}
int pcmp(const pstring_t &right) const;
@@ -191,14 +190,12 @@ private:
void pcopy(const mem_t *from, std::size_t size);
void pcopy(const mem_t *from);
-
void pcopy(const pstring_t &from)
{
sfree(m_ptr);
m_ptr = from.m_ptr;
- m_ptr->m_ref_count++;
+ m_ptr->inc();
}
-
void pcat(const mem_t *s);
void pcat(const pstring_t &s);
@@ -208,8 +205,6 @@ private:
static pstr_t m_zero;
};
-template <typename F> pstr_t pstring_t<F>::m_zero(0);
-
struct pu8_traits
{
static const unsigned MAXCODELEN = 1; /* in memory units */
@@ -358,7 +353,8 @@ public:
// C string conversion helpers
const char *c_str() const { return m_ptr; }
- operator pstring() const { return pstring(m_ptr); }
+ // FIXME: encoding should be parameter
+ operator pstring() const { return pstring(m_ptr, pstring::UTF8); }
// concatenation operators
pstringbuffer& operator+=(const char c) { char buf[2] = { c, 0 }; pcat(buf); return *this; }
diff --git a/src/lib/netlist/plib/ptypes.h b/src/lib/netlist/plib/ptypes.h
index 9c477f71944..182333875d0 100644
--- a/src/lib/netlist/plib/ptypes.h
+++ b/src/lib/netlist/plib/ptypes.h
@@ -9,6 +9,7 @@
#define PTYPES_H_
#include <type_traits>
+#include <limits>
#include "pconfig.h"
#include "pstring.h"
@@ -39,10 +40,25 @@ namespace plib
#endif
//============================================================
+ // prevent implicit copying
+ //============================================================
+
+ struct nocopyassignmove
+ {
+ protected:
+ nocopyassignmove() = default;
+ ~nocopyassignmove() = default;
+ private:
+ nocopyassignmove(const nocopyassignmove &) = delete;
+ nocopyassignmove(nocopyassignmove &&) = delete;
+ nocopyassignmove &operator=(const nocopyassignmove &) = delete;
+ };
+
+ //============================================================
// penum - strongly typed enumeration
//============================================================
- struct enum_base
+ struct penum_base
{
protected:
static int from_string_int(const char *str, const char *x);
@@ -52,22 +68,22 @@ namespace plib
}
#define P_ENUM(ename, ...) \
- struct ename : public plib::enum_base { \
- enum e { __VA_ARGS__ }; \
- ename (e v) : m_v(v) { } \
+ struct ename : public plib::penum_base { \
+ enum E { __VA_ARGS__ }; \
+ ename (E v) : m_v(v) { } \
bool set_from_string (const pstring &s) { \
static const char *strings = # __VA_ARGS__; \
int f = from_string_int(strings, s.c_str()); \
- if (f>=0) { m_v = static_cast<e>(f); return true; } else { return false; } \
+ if (f>=0) { m_v = static_cast<E>(f); return true; } else { return false; } \
} \
- operator e() const {return m_v;} \
+ operator E() const {return m_v;} \
bool operator==(const ename &rhs) const {return m_v == rhs.m_v;} \
- bool operator==(const e &rhs) const {return m_v == rhs;} \
+ bool operator==(const E &rhs) const {return m_v == rhs;} \
const pstring name() const { \
static const char *strings = # __VA_ARGS__; \
return nthstr(static_cast<int>(m_v), strings); \
} \
- private: e m_v; };
+ private: E m_v; };
#endif /* PTYPES_H_ */
diff --git a/src/lib/netlist/plib/putil.cpp b/src/lib/netlist/plib/putil.cpp
index 39e1b444f33..6a24e8c4012 100644
--- a/src/lib/netlist/plib/putil.cpp
+++ b/src/lib/netlist/plib/putil.cpp
@@ -36,13 +36,14 @@ namespace plib
if (getenv(var.c_str()) == nullptr)
return default_val;
else
- return pstring(getenv(var.c_str()));
+ return pstring(getenv(var.c_str()), pstring::UTF8);
}
}
- pstring_vector_t::pstring_vector_t(const pstring &str, const pstring &onstr, bool ignore_empty)
- : std::vector<pstring>()
+ std::vector<pstring> psplit(const pstring &str, const pstring &onstr, bool ignore_empty)
{
+ std::vector<pstring> ret;
+
pstring::iterator p = str.begin();
pstring::iterator pn = str.find(onstr, p);
@@ -50,7 +51,7 @@ namespace plib
{
pstring t = str.substr(p, pn);
if (!ignore_empty || t.len() != 0)
- this->push_back(t);
+ ret.push_back(t);
p = pn + onstr.len();
pn = str.find(onstr, p);
}
@@ -58,14 +59,15 @@ namespace plib
{
pstring t = str.substr(p, str.end());
if (!ignore_empty || t.len() != 0)
- this->push_back(t);
+ ret.push_back(t);
}
+ return ret;
}
- pstring_vector_t::pstring_vector_t(const pstring &str, const pstring_vector_t &onstrl)
- : std::vector<pstring>()
+ std::vector<pstring> psplit(const pstring &str, const std::vector<pstring> &onstrl)
{
pstring col = "";
+ std::vector<pstring> ret;
unsigned i = 0;
while (i<str.blen())
@@ -82,10 +84,10 @@ namespace plib
if (p != static_cast<std::size_t>(-1))
{
if (col != "")
- this->push_back(col);
+ ret.push_back(col);
col = "";
- this->push_back(onstrl[p]);
+ ret.push_back(onstrl[p]);
i += onstrl[p].blen();
}
else
@@ -96,11 +98,13 @@ namespace plib
}
}
if (col != "")
- this->push_back(col);
+ ret.push_back(col);
+
+ return ret;
}
- int enum_base::from_string_int(const char *str, const char *x)
+ int penum_base::from_string_int(const char *str, const char *x)
{
int cnt = 0;
const char *cur = str;
@@ -127,7 +131,7 @@ namespace plib
return cnt;
return -1;
}
- pstring enum_base::nthstr(int n, const char *str)
+ pstring penum_base::nthstr(int n, const char *str)
{
char buf[64];
char *bufp = buf;
@@ -139,7 +143,7 @@ namespace plib
if (*str == ',')
{
*bufp = 0;
- return pstring(buf);
+ return pstring(buf, pstring::UTF8);
}
else if (*str != ' ')
*bufp++ = *str;
@@ -152,6 +156,6 @@ namespace plib
str++;
}
*bufp = 0;
- return pstring(buf);
+ return pstring(buf, pstring::UTF8);
}
} // namespace plib
diff --git a/src/lib/netlist/plib/putil.h b/src/lib/netlist/plib/putil.h
index 9e79e958927..4bc8dcd695f 100644..100755
--- a/src/lib/netlist/plib/putil.h
+++ b/src/lib/netlist/plib/putil.h
@@ -8,17 +8,18 @@
#ifndef P_UTIL_H_
#define P_UTIL_H_
-#include <initializer_list>
+#include "pstring.h"
-#include "plib/pstring.h"
-#include "plib/plists.h"
+#include <initializer_list>
+#include <algorithm>
+#include <vector> // <<= needed by windows build
namespace plib
{
namespace util
{
const pstring buildpath(std::initializer_list<pstring> list );
- const pstring environment(const pstring &var, const pstring &default_val = "");
+ const pstring environment(const pstring &var, const pstring &default_val);
}
namespace container
@@ -66,13 +67,8 @@ namespace plib
// string list
// ----------------------------------------------------------------------------------------
- class pstring_vector_t : public std::vector<pstring>
- {
- public:
- pstring_vector_t() : std::vector<pstring>() { }
- pstring_vector_t(const pstring &str, const pstring &onstr, bool ignore_empty = false);
- pstring_vector_t(const pstring &str, const pstring_vector_t &onstrl);
- };
+ std::vector<pstring> psplit(const pstring &str, const pstring &onstr, bool ignore_empty = false);
+ std::vector<pstring> psplit(const pstring &str, const std::vector<pstring> &onstrl);
}
diff --git a/src/lib/netlist/prg/nltool.cpp b/src/lib/netlist/prg/nltool.cpp
index 91f9fc7c1ae..6eec3d0e6dc 100644
--- a/src/lib/netlist/prg/nltool.cpp
+++ b/src/lib/netlist/prg/nltool.cpp
@@ -8,21 +8,12 @@
****************************************************************************/
-#include <cstdio>
-#include <cstdlib>
-
#include "plib/poptions.h"
-#include "plib/pstring.h"
-#include "plib/plists.h"
-#include "plib/ptypes.h"
-#include "plib/pexception.h"
#include "nl_setup.h"
-#include "nl_factory.h"
#include "nl_parser.h"
#include "devices/net_lib.h"
#include "tools/nl_convert.h"
-
-#include <cfenv>
+#include "solver/nld_solver.h"
class tool_options_t : public plib::options
{
@@ -30,7 +21,7 @@ public:
tool_options_t() :
plib::options(),
opt_grp1(*this, "General options", "The following options apply to all commands."),
- opt_cmd (*this, "c", "cmd", "run", "run:convert:listdevices:static", "run|convert|listdevices|static"),
+ opt_cmd (*this, "c", "cmd", "run", "run:convert:listdevices:static:header", "run|convert|listdevices|static|header"),
opt_file(*this, "f", "file", "-", "file to process (default is stdin)"),
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 files"),
@@ -77,8 +68,8 @@ public:
static plib::pstdout pout_strm;
static plib::pstderr perr_strm;
-static plib::pstream_fmt_writer_t pout(pout_strm);
-static plib::pstream_fmt_writer_t perr(perr_strm);
+static plib::putf8_fmt_writer pout(pout_strm);
+static plib::putf8_fmt_writer perr(perr_strm);
static NETLIST_START(dummy)
/* Standard stuff */
@@ -211,7 +202,7 @@ struct input_t
if (e != 3)
throw netlist::nl_exception(plib::pfmt("error {1} scanning line {2}\n")(e)(line));
m_time = netlist::netlist_time::from_double(t);
- m_param = setup.find_param(buf, true);
+ m_param = setup.find_param(pstring(buf, pstring::UTF8), true);
}
void setparam()
@@ -244,8 +235,9 @@ static std::vector<input_t> read_input(const netlist::setup_t &setup, pstring fn
if (fname != "")
{
plib::pifilestream f(fname);
+ plib::putf8_reader r(f);
pstring l;
- while (f.readline(l))
+ while (r.readline(l))
{
if (l != "")
{
@@ -319,12 +311,95 @@ static void static_compile(tool_options_t &opts)
opts.opt_logs(),
opts.opt_defines(), opts.opt_rfolders());
- nt.solver()->create_solver_code(pout_strm);
+ plib::putf8_writer w(pout_strm);
+ std::map<pstring, pstring> mp;
+
+ nt.solver()->create_solver_code(mp);
+
+ for (auto &e : mp)
+ {
+ w.write(e.second);
+ }
nt.stop();
}
+static void mac_out(const pstring s, const bool cont = true)
+{
+ static const unsigned RIGHT = 72;
+ if (cont)
+ {
+ unsigned adj = 0;
+ for (auto x : s)
+ adj += (x == '\t' ? 3 : 0);
+ pout("{1}\\\n", s.rpad(" ", RIGHT-1-adj));
+ }
+ else
+ pout("{1}\n", s);
+}
+
+static void create_header(tool_options_t &opts)
+{
+ netlist_tool_t nt("netlist");
+
+ nt.init();
+
+ nt.log().verbose.set_enabled(false);
+ nt.log().warning.set_enabled(false);
+
+ nt.setup().register_source(plib::make_unique_base<netlist::source_t,
+ netlist::source_proc_t>(nt.setup(), "dummy", &netlist_dummy));
+ nt.setup().include("dummy");
+
+ pout("// license:GPL-2.0+\n");
+ pout("// copyright-holders:Couriersud\n");
+ pout("#ifndef NLD_DEVINC_H\n");
+ pout("#define NLD_DEVINC_H\n");
+ pout("\n");
+ pout("#include \"nl_setup.h\"\n");
+ pout("#ifndef __PLIB_PREPROCESSOR__\n");
+ pout("\n");
+ pout("/* ----------------------------------------------------------------------------\n");
+ pout(" * Netlist Macros\n");
+ pout(" * ---------------------------------------------------------------------------*/\n");
+ pout("\n");
+
+ pstring last_source("");
+
+ for (auto &e : nt.setup().factory())
+ {
+ if (last_source != e->sourcefile())
+ {
+ last_source = e->sourcefile();
+ pout("{1}\n", pstring("// ").rpad("-", 72));
+ pout("{1}\n", pstring("// Source: ").cat(e->sourcefile().replace("../","")));
+ pout("{1}\n", pstring("// ").rpad("-", 72));
+ }
+ auto v = plib::psplit(e->param_desc(), ",");
+ pstring vs;
+ for (auto s : v)
+ vs += ", p" + s.replace("+","").replace(".","_");
+ mac_out("#define " + e->name() + "(name" + vs + ")");
+ mac_out("\tNET_REGISTER_DEV(" + e->name() +", name)"); \
+
+ for (auto s : v)
+ {
+ pstring r(s.replace("+","").replace(".","_"));
+ if (s.startsWith("+"))
+ mac_out("\tNET_CONNECT(name, " + r + ", p" + r + ")");
+ else
+ mac_out("\tNETDEV_PARAMI(name, " + r + ", p" + r + ")");
+ }
+ mac_out("", false);
+ }
+ pout("#endif // __PLIB_PREPROCESSOR__\n");
+ pout("#endif\n");
+ nt.stop();
+
+}
+
+
/*-------------------------------------------------
listdevices - list all known devices
-------------------------------------------------*/
@@ -390,7 +465,7 @@ static void listdevices(tool_options_t &opts)
}
out += "," + f->param_desc();
- for (auto p : plib::pstring_vector_t(f->param_desc(),",") )
+ for (auto p : plib::psplit(f->param_desc(),",") )
{
if (p.startsWith("+"))
{
@@ -417,7 +492,7 @@ static void listdevices(tool_options_t &opts)
-------------------------------------------------*/
#if 0
-static const char *pmf_verbose[] =
+static const pstring pmf_verbose[] =
{
"NL_PMF_TYPE_VIRTUAL",
"NL_PMF_TYPE_GNUC_PMF",
@@ -455,7 +530,7 @@ int main(int argc, char *argv[])
{
pout(
"nltool (netlist) 0.1\n"
- "Copyright (C) 2016 Couriersud\n"
+ "Copyright (C) 2017 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"
@@ -472,6 +547,8 @@ int main(int argc, char *argv[])
run(opts);
else if (cmd == "static")
static_compile(opts);
+ else if (cmd == "header")
+ create_header(opts);
else if (cmd == "convert")
{
pstring contents;
@@ -508,7 +585,7 @@ int main(int argc, char *argv[])
result = c.result();
}
/* present result */
- pout_strm.write(result.c_str());
+ pout.write(result);
}
else
{
diff --git a/src/lib/netlist/prg/nlwav.cpp b/src/lib/netlist/prg/nlwav.cpp
index 44adf2b3508..52f59f366f6 100644
--- a/src/lib/netlist/prg/nlwav.cpp
+++ b/src/lib/netlist/prg/nlwav.cpp
@@ -1,13 +1,12 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
-#include <plib/poptions.h>
-#include <cstdio>
#include <cstring>
#include "plib/pstring.h"
#include "plib/plists.h"
#include "plib/pstream.h"
+#include "plib/poptions.h"
+#include "plib/ppmf.h"
#include "nl_setup.h"
-#include <memory>
class nlwav_options_t : public plib::options
{
@@ -17,6 +16,7 @@ public:
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_rate(*this, "r", "rate", 48000, "sample rate of output file"),
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"),
@@ -25,6 +25,7 @@ public:
plib::option_str opt_inp;
plib::option_str opt_out;
plib::option_double opt_amp;
+ plib::option_long opt_rate;
plib::option_bool opt_verb;
plib::option_bool opt_quiet;
plib::option_bool opt_version;
@@ -35,8 +36,8 @@ plib::pstdin pin_strm;
plib::pstdout pout_strm;
plib::pstderr perr_strm;
-plib::pstream_fmt_writer_t pout(pout_strm);
-plib::pstream_fmt_writer_t perr(perr_strm);
+plib::putf8_fmt_writer pout(pout_strm);
+plib::putf8_fmt_writer perr(perr_strm);
nlwav_options_t opts;
@@ -141,11 +142,114 @@ private:
};
-static void convert()
+class log_processor
{
- plib::postream *fo = (opts.opt_out() == "-" ? &pout_strm : new plib::pofilestream(opts.opt_out()));
- plib::pistream *fin = (opts.opt_inp() == "-" ? &pin_strm : new plib::pifilestream(opts.opt_inp()));
- wav_t *wo = new wav_t(*fo, 48000);
+public:
+ typedef plib::pmfp<void, double, double> callback_type;
+ log_processor(plib::pistream &is, callback_type cb) : m_is(is), m_cb(cb) { }
+
+ void process()
+ {
+ plib::putf8_reader reader(m_is);
+ pstring line;
+
+ while(reader.readline(line))
+ {
+ double t = 0.0; double v = 0.0;
+ sscanf(line.c_str(), "%lf %lf", &t, &v);
+ m_cb(t, v);
+ }
+ }
+
+private:
+ plib::pistream &m_is;
+ callback_type m_cb;
+};
+
+struct aggregator
+{
+ typedef plib::pmfp<void, double, double> callback_type;
+
+ aggregator(double quantum, callback_type cb)
+ : m_quantum(quantum)
+ , m_cb(cb)
+ , ct(0.0)
+ , lt(0.0)
+ , outsam(0.0)
+ , cursam(0.0)
+ { }
+ void process(double time, double val)
+ {
+ while (time >= ct)
+ {
+ outsam += (ct - lt) * cursam;
+ outsam = outsam / m_quantum;
+ m_cb(ct, outsam);
+ outsam = 0.0;
+ lt = ct;
+ ct += m_quantum;
+ }
+ outsam += (time-lt)*cursam;
+ lt = time;
+ cursam = val;
+ }
+
+private:
+ double m_quantum;
+ callback_type m_cb;
+ double ct;
+ double lt;
+ double outsam;
+ double cursam;
+};
+
+class wavwriter
+{
+public:
+ wavwriter(plib::postream &fo, unsigned sample_rate, double ampa)
+ : mean(0.0)
+ , means(0.0)
+ , maxsam(-1e9)
+ , minsam(1e9)
+ , n(0)
+ , m_fo(fo)
+ , amp(ampa)
+ , m_wo(m_fo, sample_rate)
+ { }
+
+ void process(double time, double outsam)
+ {
+ means += outsam;
+ maxsam = std::max(maxsam, outsam);
+ minsam = std::min(minsam, outsam);
+ n++;
+ //mean = means / (double) n;
+ mean += 5.0 / static_cast<double>(m_wo.sample_rate()) * (outsam - mean);
+
+ outsam = (outsam - mean) * amp;
+ outsam = std::max(-32000.0, outsam);
+ outsam = std::min(32000.0, outsam);
+ m_wo.write_sample(static_cast<int>(outsam));
+ }
+
+ double mean;
+ double means;
+ double maxsam;
+ double minsam;
+ std::size_t n;
+
+private:
+ plib::postream &m_fo;
+ double amp;
+ wav_t m_wo;
+};
+
+static void convert(long sample_rate)
+{
+ plib::postream *fo = (opts.opt_out() == "-" ? &pout_strm : plib::palloc<plib::pofilestream>(opts.opt_out()));
+ plib::pistream *fin = (opts.opt_inp() == "-" ? &pin_strm : plib::palloc<plib::pifilestream>(opts.opt_inp()));
+ plib::putf8_reader reader(*fin);
+ wav_t *wo = plib::palloc<wav_t>(*fo, static_cast<unsigned>(sample_rate));
double dt = 1.0 / static_cast<double>(wo->sample_rate());
double ct = dt;
@@ -162,7 +266,7 @@ static void convert()
//short sample = 0;
pstring line;
- while(fin->readline(line))
+ while(reader.readline(line))
{
#if 1
double t = 0.0; double v = 0.0;
@@ -212,11 +316,11 @@ static void convert()
//printf("%f %f\n", t, v);
#endif
}
- delete wo;
+ plib::pfree(wo);
if (opts.opt_inp() != "-")
- delete fin;
+ plib::pfree(fin);
if (opts.opt_out() != "-")
- delete fo;
+ plib::pfree(fo);
if (!opts.opt_quiet())
{
@@ -227,10 +331,39 @@ static void convert()
}
}
-static void usage(plib::pstream_fmt_writer_t &fw)
+static void convert1(long sample_rate)
+{
+ plib::postream *fo = (opts.opt_out() == "-" ? &pout_strm : plib::palloc<plib::pofilestream>(opts.opt_out()));
+ plib::pistream *fin = (opts.opt_inp() == "-" ? &pin_strm : plib::palloc<plib::pifilestream>(opts.opt_inp()));
+
+ double dt = 1.0 / static_cast<double>(sample_rate);
+
+ wavwriter *wo = plib::palloc<wavwriter>(*fo, static_cast<unsigned>(sample_rate), opts.opt_amp());
+ aggregator ag(dt, aggregator::callback_type(&wavwriter::process, wo));
+ log_processor lp(*fin, log_processor::callback_type(&aggregator::process, &ag));
+
+ lp.process();
+
+ if (!opts.opt_quiet())
+ {
+ perr("Mean (low freq filter): {}\n", wo->mean);
+ perr("Mean (static): {}\n", wo->means / static_cast<double>(wo->n));
+ perr("Amp + {}\n", 32000.0 / (wo->maxsam - wo->mean));
+ perr("Amp - {}\n", -32000.0 / (wo->minsam - wo->mean));
+ }
+
+ plib::pfree(wo);
+ if (opts.opt_inp() != "-")
+ plib::pfree(fin);
+ if (opts.opt_out() != "-")
+ plib::pfree(fo);
+
+}
+
+static void usage(plib::putf8_fmt_writer &fw)
{
fw("{}\n", opts.help("Convert netlist log files into wav files.\n",
- "nltool [options]").c_str());
+ "nltool [options]"));
}
@@ -255,7 +388,7 @@ int main(int argc, char *argv[])
{
pout(
"nlwav (netlist) 0.1\n"
- "Copyright (C) 2016 Couriersud\n"
+ "Copyright (C) 2017 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"
@@ -263,7 +396,10 @@ int main(int argc, char *argv[])
return 0;
}
- convert();
+ if ((1))
+ convert1(opts.opt_rate());
+ else
+ convert(opts.opt_rate());
return 0;
}
diff --git a/src/lib/netlist/solver/mat_cr.h b/src/lib/netlist/solver/mat_cr.h
index 340c662752f..c39af1b2f5f 100644
--- a/src/lib/netlist/solver/mat_cr.h
+++ b/src/lib/netlist/solver/mat_cr.h
@@ -12,38 +12,79 @@
#include <algorithm>
#include "plib/pconfig.h"
+#include "plib/palloc.h"
-template<int storage_N>
+template<std::size_t N, typename C = uint16_t, typename T = double>
struct mat_cr_t
{
- unsigned nz_num;
- unsigned ia[storage_N + 1];
- unsigned ja[storage_N * storage_N];
- unsigned diag[storage_N]; /* n */
+ typedef C index_type;
+ typedef T value_type;
- template<typename T>
- void mult_vec(const T * RESTRICT A, const T * RESTRICT x, T * RESTRICT res)
+ C diag[N]; // diagonal index pointer n
+ C ia[N+1]; // row index pointer n + 1
+ C ja[N*N]; // column index array nz_num, initially (n * n)
+ T A[N*N]; // Matrix elements nz_num, initially (n * n)
+
+ std::size_t size;
+ std::size_t nz_num;
+
+ mat_cr_t(const std::size_t n)
+ : size(n)
+ , nz_num(0)
+ {
+#if 0
+#if 0
+ ia = plib::palloc_array<C>(n + 1);
+ ja = plib::palloc_array<C>(n * n);
+ diag = plib::palloc_array<C>(n);
+#else
+ diag = plib::palloc_array<C>(n + (n + 1) + n * n);
+ ia = diag + n;
+ ja = ia + (n+1);
+ A = plib::palloc_array<T>(n * n);
+#endif
+#endif
+ }
+
+ ~mat_cr_t()
+ {
+#if 0
+ plib::pfree_array(diag);
+#if 0
+ plib::pfree_array(ia);
+ plib::pfree_array(ja);
+#endif
+ plib::pfree_array(A);
+#endif
+ }
+
+ void set_scalar(const T scalar)
+ {
+ for (std::size_t i=0, e=nz_num; i<e; i++)
+ A[i] = scalar;
+ }
+
+ void mult_vec(const T * RESTRICT x, T * RESTRICT res)
{
/*
* res = A * x
*/
- unsigned i = 0;
- unsigned k = 0;
- const unsigned oe = nz_num;
+ std::size_t i = 0;
+ std::size_t k = 0;
+ const std::size_t oe = nz_num;
while (k < oe)
{
T tmp = 0.0;
- const unsigned e = ia[i+1];
+ const std::size_t e = ia[i+1];
for (; k < e; k++)
tmp += A[k] * x[ja[k]];
res[i++] = tmp;
}
}
- template<typename T>
- void incomplete_LU_factorization(const T * RESTRICT A, T * RESTRICT LU)
+ void incomplete_LU_factorization(T * RESTRICT LU)
{
/*
* incomplete LU Factorization according to http://de.wikipedia.org/wiki/ILU-Zerlegung
@@ -52,28 +93,28 @@ struct mat_cr_t
*
*/
- const unsigned lnz = nz_num;
+ const std::size_t lnz = nz_num;
- for (unsigned k = 0; k < lnz; k++)
+ for (std::size_t k = 0; k < lnz; k++)
LU[k] = A[k];
- for (unsigned i = 1; ia[i] < lnz; i++) // row i
+ for (std::size_t i = 1; ia[i] < lnz; i++) // row i
{
- const unsigned iai1 = ia[i + 1];
- const unsigned pke = diag[i];
- for (unsigned pk = ia[i]; pk < pke; pk++) // all columns left of diag in row i
+ const std::size_t iai1 = ia[i + 1];
+ const std::size_t pke = diag[i];
+ for (std::size_t pk = ia[i]; pk < pke; pk++) // all columns left of diag in row i
{
// pk == (i, k)
- const unsigned k = ja[pk];
- const unsigned iak1 = ia[k + 1];
+ const std::size_t k = ja[pk];
+ const std::size_t iak1 = ia[k + 1];
const T LUpk = LU[pk] = LU[pk] / LU[diag[k]];
- unsigned pt = ia[k];
+ std::size_t pt = ia[k];
- for (unsigned pj = pk + 1; pj < iai1; pj++) // pj = (i, j)
+ for (std::size_t pj = pk + 1; pj < iai1; pj++) // pj = (i, j)
{
// we can assume that within a row ja increases continuously */
- const unsigned ej = ja[pj];
+ const std::size_t ej = ja[pj];
while (ja[pt] < ej && pt < iak1)
pt++;
if (pt < iak1 && ja[pt] == ej)
@@ -83,7 +124,6 @@ struct mat_cr_t
}
}
- template<typename T>
void solveLUx (const T * RESTRICT LU, T * RESTRICT r)
{
/*
@@ -96,7 +136,7 @@ struct mat_cr_t
*
* ==> LUx = r
*
- * ==> Ux = L?????r = w
+ * ==> Ux = L⁻¹ r = w
*
* ==> r = Lw
*
@@ -108,32 +148,28 @@ struct mat_cr_t
*
*/
- unsigned i;
-
- for (i = 1; ia[i] < nz_num; i++ )
+ for (std::size_t i = 1; ia[i] < nz_num; ++i )
{
T tmp = 0.0;
- const unsigned j1 = ia[i];
- const unsigned j2 = diag[i];
+ const std::size_t j1 = ia[i];
+ const std::size_t j2 = diag[i];
- for (unsigned j = j1; j < j2; j++ )
+ for (std::size_t j = j1; j < j2; ++j )
tmp += LU[j] * r[ja[j]];
r[i] -= tmp;
}
// i now is equal to n;
- for (; 0 < i; i-- )
+ for (std::size_t i = size; i-- > 0; )
{
- const unsigned im1 = i - 1;
T tmp = 0.0;
- const unsigned j1 = diag[im1] + 1;
- const unsigned j2 = ia[im1+1];
- for (unsigned j = j1; j < j2; j++ )
+ const std::size_t di = diag[i];
+ const std::size_t j2 = ia[i+1];
+ for (std::size_t j = di + 1; j < j2; j++ )
tmp += LU[j] * r[ja[j]];
- r[im1] = (r[im1] - tmp) / LU[diag[im1]];
+ r[i] = (r[i] - tmp) / LU[di];
}
}
-
};
#endif /* MAT_CR_H_ */
diff --git a/src/lib/netlist/solver/nld_matrix_solver.cpp b/src/lib/netlist/solver/nld_matrix_solver.cpp
index a27301a754d..f314aea2314 100644
--- a/src/lib/netlist/solver/nld_matrix_solver.cpp
+++ b/src/lib/netlist/solver/nld_matrix_solver.cpp
@@ -8,6 +8,8 @@
#include "nld_matrix_solver.h"
#include "plib/putil.h"
+#include <cmath> // <<= needed by windows build
+
namespace netlist
{
namespace devices
@@ -64,7 +66,7 @@ void terms_for_net_t::set_pointers()
for (unsigned i = 0; i < count(); i++)
{
m_terms[i]->set_ptrs(&m_gt[i], &m_go[i], &m_Idr[i]);
- m_connected_net_V[i] = m_terms[i]->m_otherterm->net().m_cur_Analog.ptr();
+ m_connected_net_V[i] = m_terms[i]->m_otherterm->net().Q_Analog_state_ptr();
}
}
@@ -91,15 +93,11 @@ matrix_solver_t::matrix_solver_t(netlist_t &anetlist, const pstring &name,
matrix_solver_t::~matrix_solver_t()
{
- for (unsigned k = 0; k < m_terms.size(); k++)
- {
- plib::pfree(m_terms[k]);
- }
-
}
void matrix_solver_t::setup_base(analog_net_t::list_t &nets)
{
+
log().debug("New solver setup\n");
m_nets.clear();
@@ -108,7 +106,7 @@ void matrix_solver_t::setup_base(analog_net_t::list_t &nets)
for (auto & net : nets)
{
m_nets.push_back(net);
- m_terms.push_back(plib::palloc<terms_for_net_t>());
+ m_terms.push_back(plib::make_unique<terms_for_net_t>());
m_rails_temp.push_back(plib::palloc<terms_for_net_t>());
}
@@ -125,7 +123,7 @@ void matrix_solver_t::setup_base(analog_net_t::list_t &nets)
log().debug("{1} {2} {3}\n", p->name(), net->name(), net->isRailNet());
switch (p->type())
{
- case terminal_t::TERMINAL:
+ case detail::terminal_type::TERMINAL:
if (p->device().is_timestep())
if (!plib::container::contains(m_step_devices, &p->device()))
m_step_devices.push_back(&p->device());
@@ -138,7 +136,7 @@ void matrix_solver_t::setup_base(analog_net_t::list_t &nets)
}
log().debug("Added terminal {1}\n", p->name());
break;
- case terminal_t::INPUT:
+ case detail::terminal_type::INPUT:
{
proxied_analog_output_t *net_proxy_output = nullptr;
for (auto & input : m_inps)
@@ -157,14 +155,14 @@ void matrix_solver_t::setup_base(analog_net_t::list_t &nets)
net_proxy_output->m_proxied_net = static_cast<analog_net_t *>(&p->net());
}
net_proxy_output->net().add_terminal(*p);
- // FIXME: repeated
+ // FIXME: repeated calling - kind of brute force
net_proxy_output->net().rebuild_list();
log().debug("Added input\n");
}
break;
- case terminal_t::OUTPUT:
- case terminal_t::PARAM:
- log().fatal("unhandled element found\n");
+ case detail::terminal_type::OUTPUT:
+ log().fatal(MF_1_UNHANDLED_ELEMENT_1_FOUND,
+ p->name());
break;
}
}
@@ -210,7 +208,7 @@ void matrix_solver_t::setup_matrix()
* literature but I have found no articles about Gauss Seidel.
*
* For Gaussian Elimination however increasing order is better suited.
- * FIXME: Even better would be to sort on elements right of the matrix diagonal.
+ * NOTE: Even better would be to sort on elements right of the matrix diagonal.
*
*/
@@ -240,7 +238,7 @@ void matrix_solver_t::setup_matrix()
/* create a list of non zero elements. */
for (unsigned k = 0; k < iN; k++)
{
- terms_for_net_t * t = m_terms[k];
+ terms_for_net_t * t = m_terms[k].get();
/* pretty brutal */
int *other = t->connected_net_idx();
@@ -262,7 +260,7 @@ void matrix_solver_t::setup_matrix()
*/
for (unsigned k = 0; k < iN; k++)
{
- terms_for_net_t * t = m_terms[k];
+ terms_for_net_t * t = m_terms[k].get();
/* pretty brutal */
int *other = t->connected_net_idx();
@@ -292,9 +290,9 @@ void matrix_solver_t::setup_matrix()
* This should reduce cache misses ...
*/
- bool **touched = new bool*[iN];
+ bool **touched = plib::palloc_array<bool *>(iN);
for (unsigned k=0; k<iN; k++)
- touched[k] = new bool[iN];
+ touched[k] = plib::palloc_array<bool>(iN);
for (unsigned k = 0; k < iN; k++)
{
@@ -352,8 +350,8 @@ void matrix_solver_t::setup_matrix()
}
for (unsigned k=0; k<iN; k++)
- delete [] touched[k];
- delete [] touched;
+ plib::pfree_array(touched[k]);
+ plib::pfree_array(touched);
}
void matrix_solver_t::update_inputs()
@@ -378,6 +376,7 @@ void matrix_solver_t::reset()
void matrix_solver_t::update() NL_NOEXCEPT
{
const netlist_time new_timestep = solve();
+ update_inputs();
if (m_params.m_dynamic_ts && has_timestep_devices() && new_timestep > netlist_time::zero())
{
@@ -389,6 +388,7 @@ void matrix_solver_t::update() NL_NOEXCEPT
void matrix_solver_t::update_forced()
{
ATTR_UNUSED const netlist_time new_timestep = solve();
+ update_inputs();
if (m_params.m_dynamic_ts && has_timestep_devices())
{
@@ -423,7 +423,7 @@ void matrix_solver_t::solve_base()
// reschedule ....
if (this_resched > 1 && !m_Q_sync.net().is_queued())
{
- log().warning("NEWTON_LOOPS exceeded on net {1}... reschedule", this->name());
+ log().warning(MW_1_NEWTON_LOOPS_EXCEEDED_ON_NET_1, this->name());
m_Q_sync.net().toggle_new_Q();
m_Q_sync.net().reschedule_in_queue(m_params.m_nr_recalc_delay);
}
@@ -449,7 +449,6 @@ const netlist_time matrix_solver_t::solve()
step(delta);
solve_base();
const netlist_time next_time_step = compute_next_timestep(delta.as_double());
- update_inputs();
return next_time_step;
}
@@ -479,7 +478,7 @@ void matrix_solver_t::add_term(std::size_t k, terminal_t *term)
else // if (ot<0)
{
m_rails_temp[k]->add(term, ot, true);
- log().fatal("found term with missing othernet {1}\n", term->name());
+ log().fatal(MF_1_FOUND_TERM_WITH_MISSING_OTHERNET, term->name());
}
}
}
@@ -490,14 +489,10 @@ netlist_time matrix_solver_t::compute_next_timestep(const double cur_ts)
if (m_params.m_dynamic_ts)
{
- /*
- * FIXME: We should extend the logic to use either all nets or
- * only output nets.
- */
for (std::size_t k = 0, iN=m_terms.size(); k < iN; k++)
{
analog_net_t *n = m_nets[k];
- terms_for_net_t *t = m_terms[k];
+ terms_for_net_t *t = m_terms[k].get();
const nl_double DD_n = (n->Q_Analog() - t->m_last_V);
const nl_double hn = cur_ts;
@@ -546,12 +541,12 @@ void matrix_solver_t::log_stats()
log().verbose(" {1:6.3} average newton raphson loops",
static_cast<double>(this->m_stat_newton_raphson) / static_cast<double>(this->m_stat_vsolver_calls));
log().verbose(" {1:10} invocations ({2:6.0} Hz) {3:10} gs fails ({4:6.2} %) {5:6.3} average",
- this->m_stat_calculations(),
- static_cast<double>(this->m_stat_calculations()) / this->netlist().time().as_double(),
- this->m_iterative_fail(),
- 100.0 * static_cast<double>(this->m_iterative_fail())
- / static_cast<double>(this->m_stat_calculations()),
- static_cast<double>(this->m_iterative_total()) / static_cast<double>(this->m_stat_calculations()));
+ this->m_stat_calculations,
+ static_cast<double>(this->m_stat_calculations) / this->netlist().time().as_double(),
+ this->m_iterative_fail,
+ 100.0 * static_cast<double>(this->m_iterative_fail)
+ / static_cast<double>(this->m_stat_calculations),
+ static_cast<double>(this->m_iterative_total) / static_cast<double>(this->m_stat_calculations));
}
}
diff --git a/src/lib/netlist/solver/nld_matrix_solver.h b/src/lib/netlist/solver/nld_matrix_solver.h
index 522b157eafb..82910e9c4d1 100644
--- a/src/lib/netlist/solver/nld_matrix_solver.h
+++ b/src/lib/netlist/solver/nld_matrix_solver.h
@@ -8,11 +8,9 @@
#ifndef NLD_MATRIX_SOLVER_H_
#define NLD_MATRIX_SOLVER_H_
-#include <type_traits>
-
-//#include "solver/nld_solver.h"
#include "nl_base.h"
-#include "plib/pstream.h"
+#include "nl_errstr.h"
+#include "plib/putil.h"
namespace netlist
{
@@ -36,10 +34,8 @@ namespace netlist
};
-class terms_for_net_t
+class terms_for_net_t : plib::nocopyassignmove
{
- P_PREVENT_COPYING(terms_for_net_t)
-
public:
terms_for_net_t();
@@ -47,14 +43,14 @@ public:
void add(terminal_t *term, int net_other, bool sorted);
- inline std::size_t count() { return m_terms.size(); }
+ inline std::size_t count() const { return m_terms.size(); }
inline terminal_t **terms() { return m_terms.data(); }
inline int *connected_net_idx() { return m_connected_net_idx.data(); }
inline nl_double *gt() { return m_gt.data(); }
inline nl_double *go() { return m_go.data(); }
inline nl_double *Idr() { return m_Idr.data(); }
- inline nl_double **connected_net_V() { return m_connected_net_V.data(); }
+ inline nl_double * const *connected_net_V() const { return m_connected_net_V.data(); }
void set_pointers();
@@ -110,11 +106,18 @@ public:
virtual ~matrix_solver_t();
- void setup(analog_net_t::list_t &nets) { vsetup(nets); }
+ void setup(analog_net_t::list_t &nets)
+ {
+ vsetup(nets);
+ }
void solve_base();
+ /* after every call to solve, update inputs must be called.
+ * this can be done as well as a batch to ease parallel processing.
+ */
const netlist_time solve();
+ void update_inputs();
inline bool has_dynamic_devices() const { return m_dynamic_devices.size() > 0; }
inline bool has_timestep_devices() const { return m_step_devices.size() > 0; }
@@ -133,13 +136,11 @@ public:
public:
int get_net_idx(detail::net_t *net);
- plib::plog_base<NL_DEBUG> &log() { return netlist().log(); }
-
virtual void log_stats();
- virtual void create_solver_code(plib::postream &strm)
+ virtual std::pair<pstring, pstring> create_solver_code()
{
- strm.writeline(plib::pfmt("/* {1} doesn't support static compile */"));
+ return std::pair<pstring, pstring>("", plib::pfmt("/* {1} doesn't support static compile */"));
}
protected:
@@ -163,7 +164,7 @@ protected:
template <typename T>
void build_LE_RHS();
- std::vector<terms_for_net_t *> m_terms;
+ std::vector<std::unique_ptr<terms_for_net_t>> m_terms;
std::vector<analog_net_t *> m_nets;
std::vector<std::unique_ptr<proxied_analog_output_t>> m_inps;
@@ -191,31 +192,30 @@ private:
void step(const netlist_time &delta);
- void update_inputs();
-
const eSortType m_sort;
};
template <typename T>
T matrix_solver_t::delta(const T * RESTRICT V)
{
- /* FIXME: Ideally we should also include currents (RHS) here. This would
+ /* NOTE: Ideally we should also include currents (RHS) here. This would
* need a reevaluation of the right hand side after voltages have been updated
* and thus belong into a different calculation. This applies to all solvers.
*/
- std::size_t iN = this->m_terms.size();
+ const std::size_t iN = this->m_terms.size();
T cerr = 0;
- for (unsigned i = 0; i < iN; i++)
- cerr = std::max(cerr, std::abs(V[i] - static_cast<T>(this->m_nets[i]->m_cur_Analog)));
+ for (std::size_t i = 0; i < iN; i++)
+ cerr = std::max(cerr, std::abs(V[i] - static_cast<T>(this->m_nets[i]->Q_Analog())));
return cerr;
}
template <typename T>
void matrix_solver_t::store(const T * RESTRICT V)
{
- for (std::size_t i = 0, iN=m_terms.size(); i < iN; i++)
- this->m_nets[i]->m_cur_Analog = V[i];
+ const std::size_t iN = this->m_terms.size();
+ for (std::size_t i = 0; i < iN; i++)
+ this->m_nets[i]->set_Q_Analog(V[i]);
}
template <typename T>
@@ -225,26 +225,28 @@ void matrix_solver_t::build_LE_A()
T &child = static_cast<T &>(*this);
- const unsigned iN = child.N();
- for (unsigned k = 0; k < iN; k++)
+ const std::size_t iN = child.N();
+ for (std::size_t k = 0; k < iN; k++)
{
- for (unsigned i=0; i < iN; i++)
+ terms_for_net_t *terms = m_terms[k].get();
+
+ for (std::size_t i=0; i < iN; i++)
child.A(k,i) = 0.0;
- const std::size_t terms_count = m_terms[k]->count();
- const std::size_t railstart = m_terms[k]->m_railstart;
- const nl_double * RESTRICT gt = m_terms[k]->gt();
+ const std::size_t terms_count = terms->count();
+ const std::size_t railstart = terms->m_railstart;
+ const nl_double * const RESTRICT gt = terms->gt();
{
nl_double akk = 0.0;
- for (unsigned i = 0; i < terms_count; i++)
+ for (std::size_t i = 0; i < terms_count; i++)
akk += gt[i];
child.A(k,k) = akk;
}
- const nl_double * RESTRICT go = m_terms[k]->go();
- const int * RESTRICT net_other = m_terms[k]->connected_net_idx();
+ const nl_double * const RESTRICT go = terms->go();
+ int * RESTRICT net_other = terms->connected_net_idx();
for (std::size_t i = 0; i < railstart; i++)
child.A(k,net_other[i]) -= go[i];
@@ -257,15 +259,15 @@ void matrix_solver_t::build_LE_RHS()
static_assert(std::is_base_of<matrix_solver_t, T>::value, "T must derive from matrix_solver_t");
T &child = static_cast<T &>(*this);
- const unsigned iN = child.N();
- for (unsigned k = 0; k < iN; k++)
+ const std::size_t iN = child.N();
+ for (std::size_t k = 0; k < iN; k++)
{
nl_double rhsk_a = 0.0;
nl_double rhsk_b = 0.0;
const std::size_t terms_count = m_terms[k]->count();
- const nl_double * RESTRICT go = m_terms[k]->go();
- const nl_double * RESTRICT Idr = m_terms[k]->Idr();
+ const nl_double * const RESTRICT go = m_terms[k]->go();
+ const nl_double * const RESTRICT Idr = m_terms[k]->Idr();
const nl_double * const * RESTRICT other_cur_analog = m_terms[k]->connected_net_V();
for (std::size_t i = 0; i < terms_count; i++)
diff --git a/src/lib/netlist/solver/nld_ms_direct.h b/src/lib/netlist/solver/nld_ms_direct.h
index 5b4a33ce66e..b929fb6ed22 100644
--- a/src/lib/netlist/solver/nld_ms_direct.h
+++ b/src/lib/netlist/solver/nld_ms_direct.h
@@ -19,7 +19,7 @@
* going forward in case we implement cuda solvers in the future.
*/
#define NL_USE_DYNAMIC_ALLOCATION (0)
-#define TEST_PARALLEL (0)
+#define TEST_PARALLEL (0 )
#if TEST_PARALLEL
#include <thread>
@@ -36,16 +36,17 @@ namespace netlist
#if TEST_PARALLEL
#define MAXTHR 10
-static const int num_thr = 1;
+static const int num_thr = 3;
struct thr_intf
{
+ virtual ~thr_intf() = default;
virtual void do_work(const int id, void *param) = 0;
};
struct ti_t
{
- volatile std::atomic<int> lo;
+ /*volatile */std::atomic<int> lo;
thr_intf *intf;
void *params;
// int block[29]; /* make it 256 bytes */
@@ -113,7 +114,7 @@ static void thr_dispose()
}
#endif
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
#if TEST_PARALLEL
class matrix_solver_direct_t: public matrix_solver_t, public thr_intf
#else
@@ -123,8 +124,8 @@ class matrix_solver_direct_t: public matrix_solver_t
friend class matrix_solver_t;
public:
- matrix_solver_direct_t(netlist_t &anetlist, const pstring &name, const solver_parameters_t *params, const unsigned size);
- matrix_solver_direct_t(netlist_t &anetlist, const pstring &name, const eSortType sort, const solver_parameters_t *params, const unsigned size);
+ matrix_solver_direct_t(netlist_t &anetlist, const pstring &name, const solver_parameters_t *params, const std::size_t size);
+ matrix_solver_direct_t(netlist_t &anetlist, const pstring &name, const eSortType sort, const solver_parameters_t *params, const std::size_t size);
virtual ~matrix_solver_direct_t();
@@ -135,7 +136,7 @@ protected:
virtual unsigned vsolve_non_dynamic(const bool newton_raphson) override;
unsigned solve_non_dynamic(const bool newton_raphson);
- inline unsigned N() const { if (m_N == 0) return m_dim; else return m_N; }
+ constexpr std::size_t N() const { return (m_N == 0) ? m_dim : m_N; }
void LE_solve();
@@ -156,13 +157,14 @@ protected:
inline nl_ext_double &RHS(const T1 &r) { return m_A[r * m_pitch + N()]; }
#else
template <typename T1, typename T2>
- inline nl_ext_double &A(const T1 &r, const T2 &c) { return m_A[r][c]; }
+ nl_ext_double &A(const T1 &r, const T2 &c) { return m_A[r][c]; }
template <typename T1>
- inline nl_ext_double &RHS(const T1 &r) { return m_A[r][N()]; }
+ nl_ext_double &RHS(const T1 &r) { return m_A[r][N()]; }
#endif
nl_double m_last_RHS[storage_N]; // right hand side - contains currents
private:
+ //static const std::size_t m_pitch = (((storage_N + 1) + 0) / 1) * 1;
static const std::size_t m_pitch = (((storage_N + 1) + 7) / 8) * 8;
//static const std::size_t m_pitch = (((storage_N + 1) + 15) / 16) * 16;
//static const std::size_t m_pitch = (((storage_N + 1) + 31) / 32) * 32;
@@ -173,7 +175,7 @@ private:
#endif
//nl_ext_double m_RHSx[storage_N];
- const unsigned m_dim;
+ const std::size_t m_dim;
};
@@ -181,44 +183,41 @@ private:
// matrix_solver_direct
// ----------------------------------------------------------------------------------------
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
matrix_solver_direct_t<m_N, storage_N>::~matrix_solver_direct_t()
{
#if (NL_USE_DYNAMIC_ALLOCATION)
- pfree_array(m_A);
+ plib::pfree_array(m_A);
#endif
#if TEST_PARALLEL
thr_dispose();
#endif
}
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
void matrix_solver_direct_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
{
- if (m_dim < nets.size())
- log().fatal("Dimension {1} less than {2}", m_dim, nets.size());
-
matrix_solver_t::setup_base(nets);
/* add RHS element */
- for (unsigned k = 0; k < N(); k++)
+ for (std::size_t k = 0; k < N(); k++)
{
- terms_for_net_t * t = m_terms[k];
+ terms_for_net_t * t = m_terms[k].get();
- if (!plib::container::contains(t->m_nzrd, N()))
- t->m_nzrd.push_back(N());
+ if (!plib::container::contains(t->m_nzrd, static_cast<unsigned>(N())))
+ t->m_nzrd.push_back(static_cast<unsigned>(N()));
}
netlist().save(*this, m_last_RHS, "m_last_RHS");
- for (unsigned k = 0; k < N(); k++)
+ for (std::size_t k = 0; k < N(); k++)
netlist().save(*this, RHS(k), plib::pfmt("RHS.{1}")(k));
}
#if TEST_PARALLEL
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
void matrix_solver_direct_t<m_N, storage_N>::do_work(const int id, void *param)
{
const int i = x_i[id];
@@ -242,58 +241,13 @@ void matrix_solver_direct_t<m_N, storage_N>::do_work(const int id, void *param)
}
#endif
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
void matrix_solver_direct_t<m_N, storage_N>::LE_solve()
{
- const unsigned kN = N();
-
- for (unsigned i = 0; i < kN; i++) {
- // FIXME: use a parameter to enable pivoting? m_pivot
- if (!TEST_PARALLEL && m_params.m_pivot)
- {
- /* Find the row with the largest first value */
- unsigned maxrow = i;
- for (unsigned j = i + 1; j < kN; j++)
- {
- //if (std::abs(m_A[j][i]) > std::abs(m_A[maxrow][i]))
- if (A(j,i) * A(j,i) > A(maxrow,i) * A(maxrow,i))
- maxrow = j;
- }
-
- if (maxrow != i)
- {
- /* Swap the maxrow and ith row */
- for (unsigned k = 0; k < kN + 1; k++) {
- std::swap(A(i,k), A(maxrow,k));
- }
- //std::swap(RHS(i), RHS(maxrow));
- }
- /* FIXME: Singular matrix? */
- const nl_double f = 1.0 / A(i,i);
-
- /* Eliminate column i from row j */
-
- for (unsigned j = i + 1; j < kN; j++)
- {
- const nl_double f1 = - A(j,i) * f;
- if (f1 != NL_FCONST(0.0))
- {
- const nl_double * RESTRICT pi = &A(i,i+1);
- nl_double * RESTRICT pj = &A(j,i+1);
-#if 1
- vec_add_mult_scalar(kN-i,pi,f1,pj);
-#else
- vec_add_mult_scalar(kN-i-1,pj,f1,pi);
- //for (unsigned k = i+1; k < kN; k++)
- // pj[k] = pj[k] + pi[k] * f1;
- //for (unsigned k = i+1; k < kN; k++)
- //A(j,k) += A(i,k) * f1;
- RHS(j) += RHS(i) * f1;
-#endif
- }
- }
- }
- else
+ const std::size_t kN = N();
+ if (!(!TEST_PARALLEL && m_params.m_pivot))
+ {
+ for (std::size_t i = 0; i < kN; i++)
{
#if TEST_PARALLEL
const unsigned eb = m_terms[i]->m_nzbd.size();
@@ -326,29 +280,76 @@ void matrix_solver_direct_t<m_N, storage_N>::LE_solve()
const auto &nzrd = m_terms[i]->m_nzrd;
const auto &nzbd = m_terms[i]->m_nzbd;
- for (auto & j : nzbd)
+ for (std::size_t j : nzbd)
{
const nl_double f1 = -f * A(j,i);
- for (auto & k : nzrd)
+ for (std::size_t k : nzrd)
A(j,k) += A(i,k) * f1;
//RHS(j) += RHS(i) * f1;
+ }
#endif
+ }
+ }
+ else
+ {
+ for (std::size_t i = 0; i < kN; i++)
+ {
+ /* Find the row with the largest first value */
+ std::size_t maxrow = i;
+ for (std::size_t j = i + 1; j < kN; j++)
+ {
+ //if (std::abs(m_A[j][i]) > std::abs(m_A[maxrow][i]))
+ if (A(j,i) * A(j,i) > A(maxrow,i) * A(maxrow,i))
+ maxrow = j;
+ }
+
+ if (maxrow != i)
+ {
+ /* Swap the maxrow and ith row */
+ for (std::size_t k = 0; k < kN + 1; k++) {
+ std::swap(A(i,k), A(maxrow,k));
+ }
+ //std::swap(RHS(i), RHS(maxrow));
+ }
+ /* FIXME: Singular matrix? */
+ const nl_double f = 1.0 / A(i,i);
+
+ /* Eliminate column i from row j */
+
+ for (std::size_t j = i + 1; j < kN; j++)
+ {
+ const nl_double f1 = - A(j,i) * f;
+ if (f1 != NL_FCONST(0.0))
+ {
+ const nl_double * RESTRICT pi = &A(i,i+1);
+ nl_double * RESTRICT pj = &A(j,i+1);
+#if 1
+ vec_add_mult_scalar_p(kN-i,pi,f1,pj);
+#else
+ vec_add_mult_scalar_p(kN-i-1,pj,f1,pi);
+ //for (unsigned k = i+1; k < kN; k++)
+ // pj[k] = pj[k] + pi[k] * f1;
+ //for (unsigned k = i+1; k < kN; k++)
+ //A(j,k) += A(i,k) * f1;
+ RHS(j) += RHS(i) * f1;
+#endif
+ }
}
}
}
}
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
template <typename T>
void matrix_solver_direct_t<m_N, storage_N>::LE_back_subst(
T * RESTRICT x)
{
- const unsigned kN = N();
+ const std::size_t kN = N();
/* back substitution */
if (m_params.m_pivot)
{
- for (unsigned j = kN; j-- > 0; )
+ for (std::size_t j = kN; j-- > 0; )
{
T tmp = 0;
for (std::size_t k = j+1; k < kN; k++)
@@ -358,14 +359,14 @@ void matrix_solver_direct_t<m_N, storage_N>::LE_back_subst(
}
else
{
- for (unsigned j = kN; j-- > 0; )
+ for (std::size_t j = kN; j-- > 0; )
{
T tmp = 0;
const auto *p = m_terms[j]->m_nzrd.data();
const auto e = m_terms[j]->m_nzrd.size() - 1; /* exclude RHS element */
- for (unsigned k = 0; k < e; k++)
+ for (std::size_t k = 0; k < e; k++)
{
const auto pk = p[k];
tmp += A(j,pk) * x[pk];
@@ -376,7 +377,7 @@ void matrix_solver_direct_t<m_N, storage_N>::LE_back_subst(
}
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
unsigned matrix_solver_direct_t<m_N, storage_N>::solve_non_dynamic(const bool newton_raphson)
{
nl_double new_V[storage_N]; // = { 0.0 };
@@ -399,27 +400,27 @@ unsigned matrix_solver_direct_t<m_N, storage_N>::solve_non_dynamic(const bool ne
}
}
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
inline unsigned matrix_solver_direct_t<m_N, storage_N>::vsolve_non_dynamic(const bool newton_raphson)
{
build_LE_A<matrix_solver_direct_t>();
build_LE_RHS<matrix_solver_direct_t>();
- for (unsigned i=0, iN=N(); i < iN; i++)
+ for (std::size_t i=0, iN=N(); i < iN; i++)
m_last_RHS[i] = RHS(i);
this->m_stat_calculations++;
return this->solve_non_dynamic(newton_raphson);
}
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
matrix_solver_direct_t<m_N, storage_N>::matrix_solver_direct_t(netlist_t &anetlist, const pstring &name,
- const solver_parameters_t *params, const unsigned size)
+ const solver_parameters_t *params, const std::size_t size)
: matrix_solver_t(anetlist, name, ASCENDING, params)
, m_dim(size)
{
#if (NL_USE_DYNAMIC_ALLOCATION)
- m_A = palloc_array(nl_ext_double, N() * m_pitch);
+ m_A = plib::palloc_array<nl_ext_double>(N() * m_pitch);
#endif
for (unsigned k = 0; k < N(); k++)
{
@@ -430,14 +431,14 @@ matrix_solver_direct_t<m_N, storage_N>::matrix_solver_direct_t(netlist_t &anetli
#endif
}
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
matrix_solver_direct_t<m_N, storage_N>::matrix_solver_direct_t(netlist_t &anetlist, const pstring &name,
- const eSortType sort, const solver_parameters_t *params, const unsigned size)
+ const eSortType sort, const solver_parameters_t *params, const std::size_t size)
: matrix_solver_t(anetlist, name, sort, params)
, m_dim(size)
{
#if (NL_USE_DYNAMIC_ALLOCATION)
- m_A = palloc_array(nl_ext_double, N() * m_pitch);
+ m_A = plib::palloc_array<nl_ext_double>(N() * m_pitch);
#endif
for (unsigned k = 0; k < N(); k++)
{
diff --git a/src/lib/netlist/solver/nld_ms_direct_lu.h b/src/lib/netlist/solver/nld_ms_direct_lu.h
index f71982f8eb4..c379cf8d055 100644
--- a/src/lib/netlist/solver/nld_ms_direct_lu.h
+++ b/src/lib/netlist/solver/nld_ms_direct_lu.h
@@ -4,7 +4,7 @@
* nld_ms_direct.h
*
*/
-
+#if 0
#ifndef NLD_MS_DIRECT_H_
#define NLD_MS_DIRECT_H_
@@ -345,10 +345,10 @@ void matrix_solver_direct_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
if(0)
for (unsigned k = 0; k < N(); k++)
{
- netlist().log("{1:3}: ", k);
+ log("{1:3}: ", k);
for (unsigned j = 0; j < m_terms[k]->m_nzrd.size(); j++)
- netlist().log(" {1:3}", m_terms[k]->m_nzrd[j]);
- netlist().log("\n");
+ log(" {1:3}", m_terms[k]->m_nzrd[j]);
+ log("\n");
}
/*
@@ -634,3 +634,4 @@ matrix_solver_direct_t<m_N, storage_N>::matrix_solver_direct_t(const eSolverType
} // namespace netlist
#endif /* NLD_MS_DIRECT_H_ */
+#endif
diff --git a/src/lib/netlist/solver/nld_ms_gcr.h b/src/lib/netlist/solver/nld_ms_gcr.h
index 80a68604a56..eda9b14aa74 100644
--- a/src/lib/netlist/solver/nld_ms_gcr.h
+++ b/src/lib/netlist/solver/nld_ms_gcr.h
@@ -5,8 +5,6 @@
*
* Gaussian elimination using compressed row format.
*
- * Fow w==1 we will do the classic Gauss-Seidel approach
- *
*/
#ifndef NLD_MS_GCR_H_
@@ -21,24 +19,20 @@
#include "solver/vector_base.h"
#include "plib/pstream.h"
-#define NL_USE_SSE 0
-#if NL_USE_SSE
-#include <mmintrin.h>
-#endif
-
namespace netlist
{
namespace devices
{
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
class matrix_solver_GCR_t: public matrix_solver_t
{
public:
matrix_solver_GCR_t(netlist_t &anetlist, const pstring &name,
- const solver_parameters_t *params, const unsigned size)
+ const solver_parameters_t *params, const std::size_t size)
: matrix_solver_t(anetlist, name, matrix_solver_t::ASCENDING, params)
, m_dim(size)
+ , mat(size)
, m_proc(nullptr)
{
}
@@ -47,55 +41,50 @@ public:
{
}
- inline unsigned N() const { if (m_N == 0) return m_dim; else return m_N; }
+ constexpr std::size_t N() const { return (m_N == 0) ? m_dim : m_N; }
virtual void vsetup(analog_net_t::list_t &nets) override;
virtual unsigned vsolve_non_dynamic(const bool newton_raphson) override;
- virtual void create_solver_code(plib::postream &strm) override;
+ virtual std::pair<pstring, pstring> create_solver_code() override;
private:
- void csc_private(plib::postream &strm);
+ //typedef typename mat_cr_t<storage_N>::type mattype;
+ typedef typename mat_cr_t<storage_N>::index_type mattype;
- using extsolver = void (*)(double * RESTRICT m_A, double * RESTRICT RHS);
+ void csc_private(plib::putf8_fmt_writer &strm);
- pstring static_compile_name()
- {
- plib::postringstream t;
- csc_private(t);
- std::hash<pstring> h;
+ using extsolver = void (*)(double * RESTRICT m_A, double * RESTRICT RHS, double * RESTRICT V);
- return plib::pfmt("nl_gcr_{1:x}_{2}")(h( t.str() ))(mat.nz_num);
- }
+ pstring static_compile_name();
- unsigned m_dim;
+ const std::size_t m_dim;
std::vector<unsigned> m_term_cr[storage_N];
mat_cr_t<storage_N> mat;
- nl_double m_A[storage_N * storage_N];
extsolver m_proc;
};
// ----------------------------------------------------------------------------------------
-// matrix_solver - GMRES
+// matrix_solver - GCR
// ----------------------------------------------------------------------------------------
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
void matrix_solver_GCR_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
{
setup_base(nets);
- unsigned nz = 0;
- const unsigned iN = this->N();
+ mattype nz = 0;
+ const std::size_t iN = this->N();
/* build the final matrix */
bool touched[storage_N][storage_N] = { { false } };
- for (unsigned k = 0; k < iN; k++)
+ for (std::size_t k = 0; k < iN; k++)
{
- for (auto & j : this->m_terms[k]->m_nz)
+ for (auto &j : this->m_terms[k]->m_nz)
touched[k][j] = true;
}
@@ -103,42 +92,31 @@ void matrix_solver_GCR_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
unsigned ops = 0;
- const bool static_compile = false;
- for (unsigned k = 0; k < iN; k++)
+ for (std::size_t k = 0; k < iN; k++)
{
ops++; // 1/A(k,k)
- if (static_compile) printf("const double fd%d = 1.0 / A(%d,%d); \n", k, k, k);
- for (unsigned row = k + 1; row < iN; row++)
+ for (std::size_t row = k + 1; row < iN; row++)
{
if (touched[row][k])
{
ops++;
fc++;
- if (static_compile) printf(" const double f%d = -fd%d * A(%d,%d); \n", fc, k, row, k);
- for (unsigned col = k + 1; col < iN; col++)
+ for (std::size_t col = k + 1; col < iN; col++)
if (touched[k][col])
{
- if (touched[row][col])
- {
- if (static_compile) printf(" A(%d,%d) += f%d * A(%d,%d); \n", row, col, fc, k, col);
- } else
- {
- if (static_compile) printf(" A(%d,%d) = f%d * A(%d,%d); \n", row, col, fc, k, col);
- }
touched[row][col] = true;
ops += 2;
}
- if (static_compile) printf(" RHS(%d) += f%d * RHS(%d); \n", row, fc, k);
}
}
}
- for (unsigned k=0; k<iN; k++)
+ for (mattype k=0; k<iN; k++)
{
mat.ia[k] = nz;
- for (unsigned j=0; j<iN; j++)
+ for (mattype j=0; j<iN; j++)
{
if (touched[k][j])
{
@@ -151,10 +129,10 @@ void matrix_solver_GCR_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
m_term_cr[k].clear();
/* build pointers into the compressed row format matrix for each terminal */
- for (unsigned j=0; j< this->m_terms[k]->m_railstart;j++)
+ for (std::size_t j=0; j< this->m_terms[k]->m_railstart;j++)
{
int other = this->m_terms[k]->connected_net_idx()[j];
- for (unsigned i = mat.ia[k]; i < nz; i++)
+ for (auto i = mat.ia[k]; i < nz; i++)
if (other == static_cast<int>(mat.ja[i]))
{
m_term_cr[k].push_back(i);
@@ -179,82 +157,173 @@ void matrix_solver_GCR_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
if (m_proc != nullptr)
this->log().verbose("External static solver {1} found ...", symname);
else
- this->log().verbose("External static solver {1} not found ...", symname);
+ this->log().warning("External static solver {1} not found ...", symname);
}
}
+#if 0
+template <std::size_t m_N, std::size_t storage_N>
+void matrix_solver_GCR_t<m_N, storage_N>::csc_private(plib::putf8_fmt_writer &strm)
+{
+ const std::size_t iN = N();
+ for (std::size_t i = 0; i < iN - 1; i++)
+ {
+ const auto &nzbd = this->m_terms[i]->m_nzbd;
+
+ if (nzbd.size() > 0)
+ {
+ std::size_t pi = mat.diag[i];
+
+ //const nl_double f = 1.0 / m_A[pi++];
+ strm("const double f{1} = 1.0 / m_A[{2}];\n", i, pi);
+ pi++;
+ const std::size_t piie = mat.ia[i+1];
+
+ //for (auto & j : nzbd)
+ for (std::size_t j : nzbd)
+ {
+ // proceed to column i
+ std::size_t pj = mat.ia[j];
+
+ while (mat.ja[pj] < i)
+ pj++;
+
+ //const nl_double f1 = - m_A[pj++] * f;
+ strm("\tconst double f{1}_{2} = -f{3} * m_A[{4}];\n", i, j, i, pj);
+ pj++;
-template <unsigned m_N, unsigned storage_N>
-void matrix_solver_GCR_t<m_N, storage_N>::csc_private(plib::postream &strm)
+ // subtract row i from j */
+ for (std::size_t pii = pi; pii<piie; )
+ {
+ while (mat.ja[pj] < mat.ja[pii])
+ pj++;
+ //m_A[pj++] += m_A[pii++] * f1;
+ strm("\tm_A[{1}] += m_A[{2}] * f{3}_{4};\n", pj, pii, i, j);
+ pj++; pii++;
+ }
+ //RHS[j] += f1 * RHS[i];
+ strm("\tRHS[{1}] += f{2}_{3} * RHS[{4}];\n", j, i, j, i);
+ }
+ }
+ }
+
+ //new_V[iN - 1] = RHS[iN - 1] / mat.A[mat.diag[iN - 1]];
+ strm("\tV[{1}] = RHS[{2}] / m_A[{3}];\n", iN - 1, iN - 1, mat.diag[iN - 1]);
+ for (std::size_t j = iN - 1; j-- > 0;)
+ {
+ strm("\tdouble tmp{1} = 0.0;\n", j);
+ const std::size_t e = mat.ia[j+1];
+ for (std::size_t pk = mat.diag[j] + 1; pk < e; pk++)
+ {
+ strm("\ttmp{1} += m_A[{2}] * V[{3}];\n", j, pk, mat.ja[pk]);
+ }
+ strm("\tV[{1}] = (RHS[{1}] - tmp{1}) / m_A[{4}];\n", j, j, j, mat.diag[j]);
+ }
+}
+#else
+template <std::size_t m_N, std::size_t storage_N>
+void matrix_solver_GCR_t<m_N, storage_N>::csc_private(plib::putf8_fmt_writer &strm)
{
- const unsigned iN = N();
- for (unsigned i = 0; i < iN - 1; i++)
+ const std::size_t iN = N();
+
+ for (std::size_t i = 0; i < mat.nz_num; i++)
+ strm("double m_A{1} = m_A[{2}];\n", i, i);
+
+ for (std::size_t i = 0; i < iN - 1; i++)
{
const auto &nzbd = this->m_terms[i]->m_nzbd;
if (nzbd.size() > 0)
{
- unsigned pi = mat.diag[i];
+ std::size_t pi = mat.diag[i];
//const nl_double f = 1.0 / m_A[pi++];
- strm.writeline(plib::pfmt("const double f{1} = 1.0 / m_A[{2}];")(i)(pi));
+ strm("const double f{1} = 1.0 / m_A{2};\n", i, pi);
pi++;
- const unsigned piie = mat.ia[i+1];
+ const std::size_t piie = mat.ia[i+1];
- for (auto & j : nzbd)
+ //for (auto & j : nzbd)
+ for (std::size_t j : nzbd)
{
// proceed to column i
- unsigned pj = mat.ia[j];
+ std::size_t pj = mat.ia[j];
while (mat.ja[pj] < i)
pj++;
//const nl_double f1 = - m_A[pj++] * f;
- strm.writeline(plib::pfmt("\tconst double f{1}_{2} = -f{3} * m_A[{4}];")(i)(j)(i)(pj));
+ strm("\tconst double f{1}_{2} = -f{3} * m_A{4};\n", i, j, i, pj);
pj++;
// subtract row i from j */
- for (unsigned pii = pi; pii<piie; )
+ for (std::size_t pii = pi; pii<piie; )
{
while (mat.ja[pj] < mat.ja[pii])
pj++;
//m_A[pj++] += m_A[pii++] * f1;
- strm.writeline(plib::pfmt("\tm_A[{1}] += m_A[{2}] * f{3}_{4};")(pj)(pii)(i)(j));
+ strm("\tm_A{1} += m_A{2} * f{3}_{4};\n", pj, pii, i, j);
pj++; pii++;
}
//RHS[j] += f1 * RHS[i];
- strm.writeline(plib::pfmt("\tRHS[{1}] += f{2}_{3} * RHS[{4}];")(j)(i)(j)(i));
+ strm("\tRHS[{1}] += f{2}_{3} * RHS[{4}];\n", j, i, j, i);
}
}
}
+
+ //new_V[iN - 1] = RHS[iN - 1] / mat.A[mat.diag[iN - 1]];
+ strm("\tV[{1}] = RHS[{2}] / m_A{3};\n", iN - 1, iN - 1, mat.diag[iN - 1]);
+ for (std::size_t j = iN - 1; j-- > 0;)
+ {
+ strm("\tdouble tmp{1} = 0.0;\n", j);
+ const std::size_t e = mat.ia[j+1];
+ for (std::size_t pk = mat.diag[j] + 1; pk < e; pk++)
+ {
+ strm("\ttmp{1} += m_A{2} * V[{3}];\n", j, pk, mat.ja[pk]);
+ }
+ strm("\tV[{1}] = (RHS[{1}] - tmp{1}) / m_A{4};\n", j, j, j, mat.diag[j]);
+ }
+}
+#endif
+
+template <std::size_t m_N, std::size_t storage_N>
+pstring matrix_solver_GCR_t<m_N, storage_N>::static_compile_name()
+{
+ plib::postringstream t;
+ plib::putf8_fmt_writer w(t);
+ csc_private(w);
+ std::hash<pstring> h;
+
+ return plib::pfmt("nl_gcr_{1:x}_{2}")(h( t.str() ))(mat.nz_num);
}
-template <unsigned m_N, unsigned storage_N>
-void matrix_solver_GCR_t<m_N, storage_N>::create_solver_code(plib::postream &strm)
+template <std::size_t m_N, std::size_t storage_N>
+std::pair<pstring, pstring> matrix_solver_GCR_t<m_N, storage_N>::create_solver_code()
{
- //const unsigned iN = N();
+ plib::postringstream t;
+ plib::putf8_fmt_writer strm(t);
+ pstring name = static_compile_name();
- strm.writeline(plib::pfmt("extern \"C\" void {1}(double * _restrict m_A, double * _restrict RHS)")(static_compile_name()));
- strm.writeline("{");
+ strm.writeline(plib::pfmt("extern \"C\" void {1}(double * __restrict m_A, double * __restrict RHS, double * __restrict V)\n")(name));
+ strm.writeline("{\n");
csc_private(strm);
- strm.writeline("}");
+ strm.writeline("}\n");
+ return std::pair<pstring, pstring>(name, t.str());
}
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
unsigned matrix_solver_GCR_t<m_N, storage_N>::vsolve_non_dynamic(const bool newton_raphson)
{
- const unsigned iN = this->N();
+ const std::size_t iN = this->N();
nl_double RHS[storage_N];
nl_double new_V[storage_N];
- for (unsigned i=0, e=mat.nz_num; i<e; i++)
- m_A[i] = 0.0;
+ mat.set_scalar(0.0);
- for (unsigned k = 0; k < iN; k++)
+ for (std::size_t k = 0; k < iN; k++)
{
- terms_for_net_t *t = this->m_terms[k];
+ terms_for_net_t *t = this->m_terms[k].get();
nl_double gtot_t = 0.0;
nl_double RHS_t = 0.0;
@@ -264,126 +333,109 @@ unsigned matrix_solver_GCR_t<m_N, storage_N>::vsolve_non_dynamic(const bool newt
const nl_double * const RESTRICT go = t->go();
const nl_double * const RESTRICT Idr = t->Idr();
const nl_double * const * RESTRICT other_cur_analog = t->connected_net_V();
+ const unsigned * const RESTRICT tcr = m_term_cr[k].data();
-#if (0 ||NL_USE_SSE)
- __m128d mg = _mm_set_pd(0.0, 0.0);
- __m128d mr = _mm_set_pd(0.0, 0.0);
- unsigned i = 0;
- for (; i < term_count - 1; i+=2)
- {
- mg = _mm_add_pd(mg, _mm_loadu_pd(&gt[i]));
- mr = _mm_add_pd(mr, _mm_loadu_pd(&Idr[i]));
- }
- gtot_t = _mm_cvtsd_f64(mg) + _mm_cvtsd_f64(_mm_unpackhi_pd(mg,mg));
- RHS_t = _mm_cvtsd_f64(mr) + _mm_cvtsd_f64(_mm_unpackhi_pd(mr,mr));
- for (; i < term_count; i++)
- {
- gtot_t += gt[i];
- RHS_t += Idr[i];
- }
-#else
- for (unsigned i = 0; i < term_count; i++)
+#if 0
+ for (std::size_t i = 0; i < term_count; i++)
{
gtot_t += gt[i];
RHS_t += Idr[i];
}
-#endif
+
for (std::size_t i = railstart; i < term_count; i++)
RHS_t += go[i] * *other_cur_analog[i];
RHS[k] = RHS_t;
// add diagonal element
- m_A[mat.diag[k]] = gtot_t;
+ mat.A[mat.diag[k]] = gtot_t;
- for (unsigned i = 0; i < railstart; i++)
+ for (std::size_t i = 0; i < railstart; i++)
+ mat.A[tcr[i]] -= go[i];
+ }
+#else
+ for (std::size_t i = 0; i < railstart; i++)
{
- const unsigned pi = m_term_cr[k][i];
- m_A[pi] -= go[i];
+ mat.A[tcr[i]] -= go[i];
+ gtot_t = gtot_t + gt[i];
+ RHS_t = RHS_t + Idr[i];
}
+
+ for (std::size_t i = railstart; i < term_count; i++)
+ {
+ RHS_t += (Idr[i] + go[i] * *other_cur_analog[i]);
+ gtot_t += gt[i];
+ }
+
+ RHS[k] = RHS_t;
+ mat.A[mat.diag[k]] += gtot_t;
}
- mat.ia[iN] = mat.nz_num;
+#endif
+ mat.ia[iN] = static_cast<mattype>(mat.nz_num);
/* now solve it */
if (m_proc != nullptr)
{
//static_solver(m_A, RHS);
- m_proc(m_A, RHS);
+ m_proc(mat.A, RHS, new_V);
}
else
{
- for (unsigned i = 0; i < iN - 1; i++)
+ for (std::size_t i = 0; i < iN - 1; i++)
{
const auto &nzbd = this->m_terms[i]->m_nzbd;
if (nzbd.size() > 0)
{
- unsigned pi = mat.diag[i];
- const nl_double f = 1.0 / m_A[pi++];
- const unsigned piie = mat.ia[i+1];
+ std::size_t pi = mat.diag[i];
+ const nl_double f = 1.0 / mat.A[pi++];
+ const std::size_t piie = mat.ia[i+1];
- for (auto & j : nzbd)
+ for (std::size_t j : nzbd) // for (std::size_t j = i + 1; j < iN; j++)
{
// proceed to column i
//__builtin_prefetch(&m_A[mat.diag[j+1]], 1);
- unsigned pj = mat.ia[j];
+ std::size_t pj = mat.ia[j];
while (mat.ja[pj] < i)
pj++;
- const nl_double f1 = - m_A[pj++] * f;
+ const nl_double f1 = - mat.A[pj++] * f;
// subtract row i from j */
- for (unsigned pii = pi; pii<piie; )
+ for (std::size_t pii = pi; pii<piie; )
{
while (mat.ja[pj] < mat.ja[pii])
pj++;
- m_A[pj++] += m_A[pii++] * f1;
+ mat.A[pj++] += mat.A[pii++] * f1;
}
RHS[j] += f1 * RHS[i];
}
}
}
- }
-
- /* backward substitution
- *
- */
+ /* backward substitution
+ *
+ */
- /* row n-1 */
- new_V[iN - 1] = RHS[iN - 1] / m_A[mat.diag[iN - 1]];
+ /* row n-1 */
+ new_V[iN - 1] = RHS[iN - 1] / mat.A[mat.diag[iN - 1]];
- for (unsigned j = iN - 1; j-- > 0;)
- {
- //__builtin_prefetch(&new_V[j-1], 1);
- //if (j>0)__builtin_prefetch(&m_A[mat.diag[j-1]], 0);
-#if (NL_USE_SSE)
- __m128d tmp = _mm_set_pd1(0.0);
- const unsigned e = mat.ia[j+1];
- unsigned pk = mat.diag[j] + 1;
- for (; pk < e - 1; pk+=2)
- {
- //tmp += m_A[pk] * new_V[mat.ja[pk]];
- tmp = _mm_add_pd(tmp, _mm_mul_pd(_mm_set_pd(m_A[pk], m_A[pk+1]),
- _mm_set_pd(new_V[mat.ja[pk]], new_V[mat.ja[pk+1]])));
- }
- double tmpx = _mm_cvtsd_f64(tmp) + _mm_cvtsd_f64(_mm_unpackhi_pd(tmp,tmp));
- for (; pk < e; pk++)
- {
- tmpx += m_A[pk] * new_V[mat.ja[pk]];
- }
- new_V[j] = (RHS[j] - tmpx) / m_A[mat.diag[j]];
-#else
- double tmp = 0;
- const unsigned e = mat.ia[j+1];
- for (unsigned pk = mat.diag[j] + 1; pk < e; pk++)
+ for (std::size_t j = iN - 1; j-- > 0;)
{
- tmp += m_A[pk] * new_V[mat.ja[pk]];
+ //__builtin_prefetch(&new_V[j-1], 1);
+ //if (j>0)__builtin_prefetch(&m_A[mat.diag[j-1]], 0);
+ double tmp = 0;
+ auto jdiag = mat.diag[j];
+ const std::size_t e = mat.ia[j+1];
+ for (std::size_t pk = jdiag + 1; pk < e; pk++)
+ {
+ tmp += mat.A[pk] * new_V[mat.ja[pk]];
+ }
+ new_V[j] = (RHS[j] - tmp) / mat.A[jdiag];
}
- new_V[j] = (RHS[j] - tmp) / m_A[mat.diag[j]];
-#endif
}
+
this->m_stat_calculations++;
if (newton_raphson)
diff --git a/src/lib/netlist/solver/nld_ms_gmres.h b/src/lib/netlist/solver/nld_ms_gmres.h
index 0c5a5e6228f..a97de6a2446 100644
--- a/src/lib/netlist/solver/nld_ms_gmres.h
+++ b/src/lib/netlist/solver/nld_ms_gmres.h
@@ -23,16 +23,17 @@ namespace netlist
{
namespace devices
{
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
class matrix_solver_GMRES_t: public matrix_solver_direct_t<m_N, storage_N>
{
public:
- matrix_solver_GMRES_t(netlist_t &anetlist, const pstring &name, const solver_parameters_t *params, const unsigned size)
+ matrix_solver_GMRES_t(netlist_t &anetlist, const pstring &name, const solver_parameters_t *params, const std::size_t size)
: matrix_solver_direct_t<m_N, storage_N>(anetlist, name, matrix_solver_t::ASCENDING, params, size)
, m_use_iLU_preconditioning(true)
, m_use_more_precise_stop_condition(false)
, m_accuracy_mult(1.0)
+ , mat(size)
{
}
@@ -45,7 +46,10 @@ public:
private:
- unsigned solve_ilu_gmres(nl_double * RESTRICT x, const nl_double * RESTRICT rhs, const unsigned restart_max, const unsigned mr, nl_double accuracy);
+ //typedef typename mat_cr_t<storage_N>::type mattype;
+ typedef typename mat_cr_t<storage_N>::index_type mattype;
+
+ unsigned solve_ilu_gmres(nl_double (& RESTRICT x)[storage_N], const nl_double * RESTRICT rhs, const unsigned restart_max, const std::size_t mr, nl_double accuracy);
std::vector<unsigned> m_term_cr[storage_N];
@@ -55,7 +59,6 @@ private:
mat_cr_t<storage_N> mat;
- nl_double m_A[storage_N * storage_N];
nl_double m_LU[storage_N * storage_N];
nl_double m_c[storage_N + 1]; /* mr + 1 */
@@ -71,22 +74,22 @@ private:
// matrix_solver - GMRES
// ----------------------------------------------------------------------------------------
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
void matrix_solver_GMRES_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
{
matrix_solver_direct_t<m_N, storage_N>::vsetup(nets);
- unsigned nz = 0;
- const unsigned iN = this->N();
+ mattype nz = 0;
+ const std::size_t iN = this->N();
- for (unsigned k=0; k<iN; k++)
+ for (std::size_t k=0; k<iN; k++)
{
- terms_for_net_t * RESTRICT row = this->m_terms[k];
+ terms_for_net_t * RESTRICT row = this->m_terms[k].get();
mat.ia[k] = nz;
- for (unsigned j=0; j<row->m_nz.size(); j++)
+ for (std::size_t j=0; j<row->m_nz.size(); j++)
{
- mat.ja[nz] = row->m_nz[j];
+ mat.ja[nz] = static_cast<mattype>(row->m_nz[j]);
if (row->m_nz[j] == k)
mat.diag[k] = nz;
nz++;
@@ -110,10 +113,10 @@ void matrix_solver_GMRES_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
mat.nz_num = nz;
}
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
unsigned matrix_solver_GMRES_t<m_N, storage_N>::vsolve_non_dynamic(const bool newton_raphson)
{
- const unsigned iN = this->N();
+ const std::size_t iN = this->N();
/* ideally, we could get an estimate for the spectral radius of
* Inv(D - L) * U
@@ -127,10 +130,9 @@ unsigned matrix_solver_GMRES_t<m_N, storage_N>::vsolve_non_dynamic(const bool ne
nl_double RHS[storage_N];
nl_double new_V[storage_N];
- for (unsigned i=0, e=mat.nz_num; i<e; i++)
- m_A[i] = 0.0;
+ mat.set_scalar(0.0);
- for (unsigned k = 0; k < iN; k++)
+ for (std::size_t k = 0; k < iN; k++)
{
nl_double gtot_t = 0.0;
nl_double RHS_t = 0.0;
@@ -142,7 +144,7 @@ unsigned matrix_solver_GMRES_t<m_N, storage_N>::vsolve_non_dynamic(const bool ne
const nl_double * const RESTRICT Idr = this->m_terms[k]->Idr();
const nl_double * const * RESTRICT other_cur_analog = this->m_terms[k]->connected_net_V();
- new_V[k] = this->m_nets[k]->m_cur_Analog;
+ new_V[k] = this->m_nets[k]->Q_Analog();
for (std::size_t i = 0; i < term_count; i++)
{
@@ -156,24 +158,24 @@ unsigned matrix_solver_GMRES_t<m_N, storage_N>::vsolve_non_dynamic(const bool ne
RHS[k] = RHS_t;
// add diagonal element
- m_A[mat.diag[k]] = gtot_t;
+ mat.A[mat.diag[k]] = gtot_t;
for (std::size_t i = 0; i < railstart; i++)
{
- const unsigned pi = m_term_cr[k][i];
- m_A[pi] -= go[i];
+ const std::size_t pi = m_term_cr[k][i];
+ mat.A[pi] -= go[i];
}
}
- mat.ia[iN] = mat.nz_num;
+ mat.ia[iN] = static_cast<mattype>(mat.nz_num);
const nl_double accuracy = this->m_params.m_accuracy;
- unsigned mr = iN;
+ std::size_t mr = iN;
if (iN > 3 )
mr = static_cast<unsigned>(std::sqrt(iN) * 2.0);
unsigned iter = std::max(1u, this->m_params.m_gs_loops);
- unsigned gsl = solve_ilu_gmres(new_V, RHS, iter, mr, accuracy);
- unsigned failed = mr * iter;
+ unsigned gsl = solve_ilu_gmres(new_V, RHS, iter, static_cast<unsigned>(mr), accuracy);
+ unsigned failed = static_cast<unsigned>(mr) * iter;
this->m_iterative_total += gsl;
this->m_stat_calculations++;
@@ -200,7 +202,7 @@ unsigned matrix_solver_GMRES_t<m_N, storage_N>::vsolve_non_dynamic(const bool ne
}
template <typename T>
-inline void givens_mult( const T & c, const T & s, T & g0, T & g1 )
+inline static void givens_mult( const T c, const T s, T & g0, T & g1 )
{
const T tg0 = c * g0 - s * g1;
const T tg1 = s * g0 + c * g1;
@@ -209,8 +211,8 @@ inline void givens_mult( const T & c, const T & s, T & g0, T & g1 )
g1 = tg1;
}
-template <unsigned m_N, unsigned storage_N>
-unsigned matrix_solver_GMRES_t<m_N, storage_N>::solve_ilu_gmres (nl_double * RESTRICT x, const nl_double * RESTRICT rhs, const unsigned restart_max, const unsigned mr, nl_double accuracy)
+template <std::size_t m_N, std::size_t storage_N>
+unsigned matrix_solver_GMRES_t<m_N, storage_N>::solve_ilu_gmres (nl_double (& RESTRICT x)[storage_N], const nl_double * RESTRICT rhs, const unsigned restart_max, const std::size_t mr, nl_double accuracy)
{
/*-------------------------------------------------------------------------
* The code below was inspired by code published by John Burkardt under
@@ -237,10 +239,10 @@ unsigned matrix_solver_GMRES_t<m_N, storage_N>::solve_ilu_gmres (nl_double * RES
unsigned itr_used = 0;
double rho_delta = 0.0;
- const unsigned n = this->N();
+ const std::size_t n = this->N();
if (m_use_iLU_preconditioning)
- mat.incomplete_LU_factorization(m_A, m_LU);
+ mat.incomplete_LU_factorization(m_LU);
if (m_use_more_precise_stop_condition)
{
@@ -258,7 +260,8 @@ unsigned matrix_solver_GMRES_t<m_N, storage_N>::solve_ilu_gmres (nl_double * RES
nl_double t[storage_N];
nl_double Ax[storage_N];
vec_set(n, accuracy, t);
- mat.mult_vec(m_A, t, Ax);
+ mat.mult_vec(t, Ax);
+
mat.solveLUx(m_LU, Ax);
const nl_double rho_to_accuracy = std::sqrt(vecmult2(n, Ax)) / accuracy;
@@ -270,14 +273,13 @@ unsigned matrix_solver_GMRES_t<m_N, storage_N>::solve_ilu_gmres (nl_double * RES
for (unsigned itr = 0; itr < restart_max; itr++)
{
- unsigned last_k = mr;
- nl_double mu;
+ std::size_t last_k = mr;
nl_double rho;
nl_double Ax[storage_N];
nl_double residual[storage_N];
- mat.mult_vec(m_A, x, Ax);
+ mat.mult_vec(x, Ax);
vec_sub(n, rhs, Ax, residual);
@@ -288,24 +290,27 @@ unsigned matrix_solver_GMRES_t<m_N, storage_N>::solve_ilu_gmres (nl_double * RES
rho = std::sqrt(vecmult2(n, residual));
- vec_mult_scalar(n, residual, NL_FCONST(1.0) / rho, m_v[0]);
+ if (rho < rho_delta)
+ return itr_used + 1;
vec_set(mr+1, NL_FCONST(0.0), m_g);
m_g[0] = rho;
- for (unsigned i = 0; i < mr; i++)
+ for (std::size_t i = 0; i < mr; i++)
vec_set(mr + 1, NL_FCONST(0.0), m_ht[i]);
- for (unsigned k = 0; k < mr; k++)
+ vec_mult_scalar(n, residual, NL_FCONST(1.0) / rho, m_v[0]);
+
+ for (std::size_t k = 0; k < mr; k++)
{
- const unsigned k1 = k + 1;
+ const std::size_t k1 = k + 1;
- mat.mult_vec(m_A, m_v[k], m_v[k1]);
+ mat.mult_vec(m_v[k], m_v[k1]);
if (m_use_iLU_preconditioning)
mat.solveLUx(m_LU, m_v[k1]);
- for (unsigned j = 0; j <= k; j++)
+ for (std::size_t j = 0; j <= k; j++)
{
m_ht[j][k] = vecmult(n, m_v[k1], m_v[j]);
vec_add_mult_scalar(n, m_v[j], -m_ht[j][k], m_v[k1]);
@@ -315,13 +320,13 @@ unsigned matrix_solver_GMRES_t<m_N, storage_N>::solve_ilu_gmres (nl_double * RES
if (m_ht[k1][k] != 0.0)
vec_scale(n, m_v[k1], NL_FCONST(1.0) / m_ht[k1][k]);
- for (unsigned j = 0; j < k; j++)
+ for (std::size_t j = 0; j < k; j++)
givens_mult(m_c[j], m_s[j], m_ht[j][k], m_ht[j+1][k]);
- mu = std::hypot(m_ht[k][k], m_ht[k1][k]);
+ const nl_double mu = 1.0 / std::hypot(m_ht[k][k], m_ht[k1][k]);
- m_c[k] = m_ht[k][k] / mu;
- m_s[k] = -m_ht[k1][k] / mu;
+ m_c[k] = m_ht[k][k] * mu;
+ m_s[k] = -m_ht[k1][k] * mu;
m_ht[k][k] = m_c[k] * m_ht[k][k] - m_s[k] * m_ht[k1][k];
m_ht[k1][k] = 0.0;
@@ -344,17 +349,17 @@ unsigned matrix_solver_GMRES_t<m_N, storage_N>::solve_ilu_gmres (nl_double * RES
/* Solve the system H * y = g */
/* x += m_v[j] * m_y[j] */
- for (unsigned i = last_k + 1; i-- > 0;)
+ for (std::size_t i = last_k + 1; i-- > 0;)
{
double tmp = m_g[i];
- for (unsigned j = i + 1; j <= last_k; j++)
+ for (std::size_t j = i + 1; j <= last_k; j++)
{
tmp -= m_ht[i][j] * m_y[j];
}
m_y[i] = tmp / m_ht[i][i];
}
- for (unsigned i = 0; i <= last_k; i++)
+ for (std::size_t i = 0; i <= last_k; i++)
vec_add_mult_scalar(n, m_v[i], m_y[i], x);
#if 1
diff --git a/src/lib/netlist/solver/nld_ms_sm.h b/src/lib/netlist/solver/nld_ms_sm.h
index 2f3597f3a89..b87f5bcc835 100644
--- a/src/lib/netlist/solver/nld_ms_sm.h
+++ b/src/lib/netlist/solver/nld_ms_sm.h
@@ -47,7 +47,7 @@ namespace netlist
//#define nl_ext_double long double // slightly slower
#define nl_ext_double nl_double
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
class matrix_solver_sm_t: public matrix_solver_t
{
friend class matrix_solver_t;
@@ -55,7 +55,7 @@ class matrix_solver_sm_t: public matrix_solver_t
public:
matrix_solver_sm_t(netlist_t &anetlist, const pstring &name,
- const solver_parameters_t *params, const unsigned size);
+ const solver_parameters_t *params, const std::size_t size);
virtual ~matrix_solver_sm_t();
@@ -66,7 +66,7 @@ protected:
virtual unsigned vsolve_non_dynamic(const bool newton_raphson) override;
unsigned solve_non_dynamic(const bool newton_raphson);
- inline unsigned N() const { if (m_N == 0) return m_dim; else return m_N; }
+ constexpr std::size_t N() const { return (m_N == 0) ? m_dim : m_N; }
void LE_invert();
@@ -103,7 +103,7 @@ private:
//nl_ext_double m_RHSx[storage_N];
- const unsigned m_dim;
+ const std::size_t m_dim;
};
@@ -111,20 +111,17 @@ private:
// matrix_solver_direct
// ----------------------------------------------------------------------------------------
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
matrix_solver_sm_t<m_N, storage_N>::~matrix_solver_sm_t()
{
#if (NL_USE_DYNAMIC_ALLOCATION)
- pfree_array(m_A);
+ plib::pfree_array(m_A);
#endif
}
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
void matrix_solver_sm_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
{
- if (m_dim < nets.size())
- log().fatal("Dimension {1} less than {2}", m_dim, nets.size());
-
matrix_solver_t::setup_base(nets);
netlist().save(*this, m_last_RHS, "m_last_RHS");
@@ -135,14 +132,14 @@ void matrix_solver_sm_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
void matrix_solver_sm_t<m_N, storage_N>::LE_invert()
{
- const unsigned kN = N();
+ const std::size_t kN = N();
- for (unsigned i = 0; i < kN; i++)
+ for (std::size_t i = 0; i < kN; i++)
{
- for (unsigned j = 0; j < kN; j++)
+ for (std::size_t j = 0; j < kN; j++)
{
W(i,j) = lA(i,j) = A(i,j);
Ainv(i,j) = 0.0;
@@ -150,7 +147,7 @@ void matrix_solver_sm_t<m_N, storage_N>::LE_invert()
Ainv(i,i) = 1.0;
}
/* down */
- for (unsigned i = 0; i < kN; i++)
+ for (std::size_t i = 0; i < kN; i++)
{
/* FIXME: Singular matrix? */
const nl_double f = 1.0 / W(i,i);
@@ -169,28 +166,28 @@ void matrix_solver_sm_t<m_N, storage_N>::LE_invert()
{
for (std::size_t k = 0; k < e; k++)
W(j,p[k]) += W(i,p[k]) * f1;
- for (unsigned k = 0; k <= i; k ++)
+ for (std::size_t k = 0; k <= i; k ++)
Ainv(j,k) += Ainv(i,k) * f1;
}
}
}
/* up */
- for (unsigned i = kN; i-- > 0; )
+ for (std::size_t i = kN; i-- > 0; )
{
/* FIXME: Singular matrix? */
const nl_double f = 1.0 / W(i,i);
- for (unsigned j = i; j-- > 0; )
+ for (std::size_t j = i; j-- > 0; )
{
const nl_double f1 = - W(j,i) * f;
if (f1 != 0.0)
{
- for (unsigned k = i; k < kN; k++)
+ for (std::size_t k = i; k < kN; k++)
W(j,k) += W(i,k) * f1;
- for (unsigned k = 0; k < kN; k++)
+ for (std::size_t k = 0; k < kN; k++)
Ainv(j,k) += Ainv(i,k) * f1;
}
}
- for (unsigned k = 0; k < kN; k++)
+ for (std::size_t k = 0; k < kN; k++)
{
Ainv(i,k) *= f;
lAinv(i,k) = Ainv(i,k);
@@ -198,27 +195,27 @@ void matrix_solver_sm_t<m_N, storage_N>::LE_invert()
}
}
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
template <typename T>
void matrix_solver_sm_t<m_N, storage_N>::LE_compute_x(
T * RESTRICT x)
{
- const unsigned kN = N();
+ const std::size_t kN = N();
- for (unsigned i=0; i<kN; i++)
+ for (std::size_t i=0; i<kN; i++)
x[i] = 0.0;
- for (unsigned k=0; k<kN; k++)
+ for (std::size_t k=0; k<kN; k++)
{
const nl_double f = RHS(k);
- for (unsigned i=0; i<kN; i++)
+ for (std::size_t i=0; i<kN; i++)
x[i] += Ainv(i,k) * f;
}
}
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
unsigned matrix_solver_sm_t<m_N, storage_N>::solve_non_dynamic(const bool newton_raphson)
{
static const bool incremental = true;
@@ -308,29 +305,26 @@ unsigned matrix_solver_sm_t<m_N, storage_N>::solve_non_dynamic(const bool newton
}
}
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
inline unsigned matrix_solver_sm_t<m_N, storage_N>::vsolve_non_dynamic(const bool newton_raphson)
{
build_LE_A<matrix_solver_sm_t>();
build_LE_RHS<matrix_solver_sm_t>();
- for (unsigned i=0, iN=N(); i < iN; i++)
+ for (std::size_t i=0, iN=N(); i < iN; i++)
m_last_RHS[i] = RHS(i);
this->m_stat_calculations++;
return this->solve_non_dynamic(newton_raphson);
}
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
matrix_solver_sm_t<m_N, storage_N>::matrix_solver_sm_t(netlist_t &anetlist, const pstring &name,
- const solver_parameters_t *params, const unsigned size)
+ const solver_parameters_t *params, const std::size_t size)
: matrix_solver_t(anetlist, name, NOSORT, params)
, m_dim(size)
{
-#if (NL_USE_DYNAMIC_ALLOCATION)
- m_A = palloc_array(nl_ext_double, N() * m_pitch);
-#endif
- for (unsigned k = 0; k < N(); k++)
+ for (std::size_t k = 0; k < N(); k++)
{
m_last_RHS[k] = 0.0;
}
diff --git a/src/lib/netlist/solver/nld_ms_sor.h b/src/lib/netlist/solver/nld_ms_sor.h
index 15f56ee264b..dc3a5d1821c 100644
--- a/src/lib/netlist/solver/nld_ms_sor.h
+++ b/src/lib/netlist/solver/nld_ms_sor.h
@@ -21,12 +21,12 @@ namespace netlist
{
namespace devices
{
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
class matrix_solver_SOR_t: public matrix_solver_direct_t<m_N, storage_N>
{
public:
- matrix_solver_SOR_t(netlist_t &anetlist, const pstring &name, const solver_parameters_t *params, const unsigned size)
+ matrix_solver_SOR_t(netlist_t &anetlist, const pstring &name, const solver_parameters_t *params, const std::size_t size)
: matrix_solver_direct_t<m_N, storage_N>(anetlist, name, matrix_solver_t::ASCENDING, params, size)
, m_lp_fact(*this, "m_lp_fact", 0)
{
@@ -46,16 +46,16 @@ private:
// ----------------------------------------------------------------------------------------
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
void matrix_solver_SOR_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
{
matrix_solver_direct_t<m_N, storage_N>::vsetup(nets);
}
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
unsigned matrix_solver_SOR_t<m_N, storage_N>::vsolve_non_dynamic(const bool newton_raphson)
{
- const unsigned iN = this->N();
+ const std::size_t iN = this->N();
bool resched = false;
unsigned resched_cnt = 0;
@@ -74,7 +74,7 @@ unsigned matrix_solver_SOR_t<m_N, storage_N>::vsolve_non_dynamic(const bool newt
nl_double RHS[storage_N];
nl_double new_V[storage_N];
- for (unsigned k = 0; k < iN; k++)
+ for (std::size_t k = 0; k < iN; k++)
{
nl_double gtot_t = 0.0;
nl_double gabs_t = 0.0;
@@ -86,7 +86,7 @@ unsigned matrix_solver_SOR_t<m_N, storage_N>::vsolve_non_dynamic(const bool newt
const nl_double * const RESTRICT Idr = this->m_terms[k]->Idr();
const nl_double * const *other_cur_analog = this->m_terms[k]->connected_net_V();
- new_V[k] = this->m_nets[k]->m_cur_Analog;
+ new_V[k] = this->m_nets[k]->Q_Analog();
for (std::size_t i = 0; i < term_count; i++)
{
@@ -125,17 +125,10 @@ unsigned matrix_solver_SOR_t<m_N, storage_N>::vsolve_non_dynamic(const bool newt
const nl_double accuracy = this->m_params.m_accuracy;
- /* uncommenting the line below will force dynamic updates every X iterations
- * althought the system has not converged yet. This is a proof of concept,
- *
- */
- const bool interleaved_dynamic_updates = false;
- //const bool interleaved_dynamic_updates = newton_raphson;
-
do {
resched = false;
nl_double err = 0;
- for (unsigned k = 0; k < iN; k++)
+ for (std::size_t k = 0; k < iN; k++)
{
const int * RESTRICT net_other = this->m_terms[k]->connected_net_idx();
const std::size_t railstart = this->m_terms[k]->m_railstart;
@@ -156,29 +149,20 @@ unsigned matrix_solver_SOR_t<m_N, storage_N>::vsolve_non_dynamic(const bool newt
resched_cnt++;
//} while (resched && (resched_cnt < this->m_params.m_gs_loops));
- } while (resched && ((!interleaved_dynamic_updates && resched_cnt < this->m_params.m_gs_loops) || (interleaved_dynamic_updates && resched_cnt < 5 )));
+ } while (resched && ((resched_cnt < this->m_params.m_gs_loops)));
this->m_iterative_total += resched_cnt;
+ this->m_stat_calculations++;
- if (resched && !interleaved_dynamic_updates)
+ if (resched)
{
// Fallback to direct solver ...
this->m_iterative_fail++;
return matrix_solver_direct_t<m_N, storage_N>::vsolve_non_dynamic(newton_raphson);
}
- this->m_stat_calculations++;
-
- if (interleaved_dynamic_updates)
- {
- for (unsigned k = 0; k < iN; k++)
- this->m_nets[k]->m_cur_Analog += 1.0 * (new_V[k] - this->m_nets[k]->m_cur_Analog);
- }
- else
- {
- for (unsigned k = 0; k < iN; k++)
- this->m_nets[k]->m_cur_Analog = new_V[k];
- }
+ for (std::size_t k = 0; k < iN; k++)
+ this->m_nets[k]->set_Q_Analog(new_V[k]);
return resched_cnt;
}
diff --git a/src/lib/netlist/solver/nld_ms_sor_mat.h b/src/lib/netlist/solver/nld_ms_sor_mat.h
index 43b6eeeafb5..265ef821957 100644
--- a/src/lib/netlist/solver/nld_ms_sor_mat.h
+++ b/src/lib/netlist/solver/nld_ms_sor_mat.h
@@ -22,14 +22,14 @@ namespace netlist
{
namespace devices
{
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
class matrix_solver_SOR_mat_t: public matrix_solver_direct_t<m_N, storage_N>
{
friend class matrix_solver_t;
public:
- matrix_solver_SOR_mat_t(netlist_t &anetlist, const pstring &name, const solver_parameters_t *params, const unsigned size)
+ matrix_solver_SOR_mat_t(netlist_t &anetlist, const pstring &name, const solver_parameters_t *params, std::size_t size)
: matrix_solver_direct_t<m_N, storage_N>(anetlist, name, matrix_solver_t::DESCENDING, params, size)
, m_Vdelta(*this, "m_Vdelta", 0.0)
, m_omega(*this, "m_omega", params->m_gs_sor)
@@ -58,7 +58,7 @@ private:
// matrix_solver - Gauss - Seidel
// ----------------------------------------------------------------------------------------
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
void matrix_solver_SOR_mat_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
{
matrix_solver_direct_t<m_N, storage_N>::vsetup(nets);
@@ -113,7 +113,7 @@ nl_double matrix_solver_SOR_mat_t<m_N, storage_N>::vsolve()
}
#endif
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
unsigned matrix_solver_SOR_mat_t<m_N, storage_N>::vsolve_non_dynamic(const bool newton_raphson)
{
/* The matrix based code looks a lot nicer but actually is 30% slower than
@@ -123,7 +123,7 @@ unsigned matrix_solver_SOR_mat_t<m_N, storage_N>::vsolve_non_dynamic(const bool
nl_double new_v[storage_N] = { 0.0 };
- const unsigned iN = this->N();
+ const std::size_t iN = this->N();
matrix_solver_t::build_LE_A<matrix_solver_SOR_mat_t>();
matrix_solver_t::build_LE_RHS<matrix_solver_SOR_mat_t>();
@@ -169,14 +169,14 @@ unsigned matrix_solver_SOR_mat_t<m_N, storage_N>::vsolve_non_dynamic(const bool
}
#endif
- for (unsigned k = 0; k < iN; k++)
- new_v[k] = this->m_nets[k]->m_cur_Analog;
+ for (std::size_t k = 0; k < iN; k++)
+ new_v[k] = this->m_nets[k]->Q_Analog();
do {
resched = false;
nl_double cerr = 0.0;
- for (unsigned k = 0; k < iN; k++)
+ for (std::size_t k = 0; k < iN; k++)
{
nl_double Idrive = 0;
@@ -199,10 +199,12 @@ unsigned matrix_solver_SOR_mat_t<m_N, storage_N>::vsolve_non_dynamic(const bool
} while (resched && (resched_cnt < this->m_params.m_gs_loops));
this->m_stat_calculations++;
+ this->m_iterative_total += resched_cnt;
this->m_gs_total += resched_cnt;
if (resched)
{
+ this->m_iterative_fail++;
//this->netlist().warning("Falling back to direct solver .. Consider increasing RESCHED_LOOPS");
this->m_gs_fail++;
diff --git a/src/lib/netlist/solver/nld_ms_w.h b/src/lib/netlist/solver/nld_ms_w.h
index e644ce40085..c2e016e4dec 100644
--- a/src/lib/netlist/solver/nld_ms_w.h
+++ b/src/lib/netlist/solver/nld_ms_w.h
@@ -54,13 +54,13 @@ namespace netlist
//#define nl_ext_double long double // slightly slower
#define nl_ext_double nl_double
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
class matrix_solver_w_t: public matrix_solver_t
{
friend class matrix_solver_t;
public:
- matrix_solver_w_t(netlist_t &anetlist, const pstring &name, const solver_parameters_t *params, const unsigned size);
+ matrix_solver_w_t(netlist_t &anetlist, const pstring &name, const solver_parameters_t *params, const std::size_t size);
virtual ~matrix_solver_w_t();
@@ -71,7 +71,7 @@ protected:
virtual unsigned vsolve_non_dynamic(const bool newton_raphson) override;
unsigned solve_non_dynamic(const bool newton_raphson);
- inline unsigned N() const { if (m_N == 0) return m_dim; else return m_N; }
+ constexpr std::size_t N() const { return (m_N == 0) ? m_dim : m_N; }
void LE_invert();
@@ -115,7 +115,7 @@ private:
//nl_ext_double m_RHSx[storage_N];
- const unsigned m_dim;
+ const std::size_t m_dim;
};
@@ -123,17 +123,14 @@ private:
// matrix_solver_direct
// ----------------------------------------------------------------------------------------
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
matrix_solver_w_t<m_N, storage_N>::~matrix_solver_w_t()
{
}
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
void matrix_solver_w_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
{
- if (m_dim < nets.size())
- log().fatal("Dimension {1} less than {2}", m_dim, nets.size());
-
matrix_solver_t::setup_base(nets);
netlist().save(*this, m_last_RHS, "m_last_RHS");
@@ -144,14 +141,14 @@ void matrix_solver_w_t<m_N, storage_N>::vsetup(analog_net_t::list_t &nets)
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
void matrix_solver_w_t<m_N, storage_N>::LE_invert()
{
- const unsigned kN = N();
+ const std::size_t kN = N();
- for (unsigned i = 0; i < kN; i++)
+ for (std::size_t i = 0; i < kN; i++)
{
- for (unsigned j = 0; j < kN; j++)
+ for (std::size_t j = 0; j < kN; j++)
{
W(i,j) = lA(i,j) = A(i,j);
Ainv(i,j) = 0.0;
@@ -159,7 +156,7 @@ void matrix_solver_w_t<m_N, storage_N>::LE_invert()
Ainv(i,i) = 1.0;
}
/* down */
- for (unsigned i = 0; i < kN; i++)
+ for (std::size_t i = 0; i < kN; i++)
{
/* FIXME: Singular matrix? */
const nl_double f = 1.0 / W(i,i);
@@ -170,63 +167,63 @@ void matrix_solver_w_t<m_N, storage_N>::LE_invert()
const auto * RESTRICT const pb = m_terms[i]->m_nzbd.data();
const size_t eb = m_terms[i]->m_nzbd.size();
- for (unsigned jb = 0; jb < eb; jb++)
+ for (std::size_t jb = 0; jb < eb; jb++)
{
const auto j = pb[jb];
const nl_double f1 = - W(j,i) * f;
if (f1 != 0.0)
{
- for (unsigned k = 0; k < e; k++)
+ for (std::size_t k = 0; k < e; k++)
W(j,p[k]) += W(i,p[k]) * f1;
- for (unsigned k = 0; k <= i; k ++)
+ for (std::size_t k = 0; k <= i; k ++)
Ainv(j,k) += Ainv(i,k) * f1;
}
}
}
/* up */
- for (unsigned i = kN; i-- > 0; )
+ for (std::size_t i = kN; i-- > 0; )
{
/* FIXME: Singular matrix? */
const nl_double f = 1.0 / W(i,i);
- for (unsigned j = i; j-- > 0; )
+ for (std::size_t j = i; j-- > 0; )
{
const nl_double f1 = - W(j,i) * f;
if (f1 != 0.0)
{
- for (unsigned k = i; k < kN; k++)
+ for (std::size_t k = i; k < kN; k++)
W(j,k) += W(i,k) * f1;
- for (unsigned k = 0; k < kN; k++)
+ for (std::size_t k = 0; k < kN; k++)
Ainv(j,k) += Ainv(i,k) * f1;
}
}
- for (unsigned k = 0; k < kN; k++)
+ for (std::size_t k = 0; k < kN; k++)
{
Ainv(i,k) *= f;
}
}
}
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
template <typename T>
void matrix_solver_w_t<m_N, storage_N>::LE_compute_x(
T * RESTRICT x)
{
- const unsigned kN = N();
+ const std::size_t kN = N();
- for (unsigned i=0; i<kN; i++)
+ for (std::size_t i=0; i<kN; i++)
x[i] = 0.0;
- for (unsigned k=0; k<kN; k++)
+ for (std::size_t k=0; k<kN; k++)
{
const nl_double f = RHS(k);
- for (unsigned i=0; i<kN; i++)
+ for (std::size_t i=0; i<kN; i++)
x[i] += Ainv(i,k) * f;
}
}
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
unsigned matrix_solver_w_t<m_N, storage_N>::solve_non_dynamic(const bool newton_raphson)
{
const auto iN = N();
@@ -372,27 +369,27 @@ unsigned matrix_solver_w_t<m_N, storage_N>::solve_non_dynamic(const bool newton_
}
}
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
inline unsigned matrix_solver_w_t<m_N, storage_N>::vsolve_non_dynamic(const bool newton_raphson)
{
build_LE_A<matrix_solver_w_t>();
build_LE_RHS<matrix_solver_w_t>();
- for (unsigned i=0, iN=N(); i < iN; i++)
+ for (std::size_t i=0, iN=N(); i < iN; i++)
m_last_RHS[i] = RHS(i);
this->m_stat_calculations++;
return this->solve_non_dynamic(newton_raphson);
}
-template <unsigned m_N, unsigned storage_N>
+template <std::size_t m_N, std::size_t storage_N>
matrix_solver_w_t<m_N, storage_N>::matrix_solver_w_t(netlist_t &anetlist, const pstring &name,
- const solver_parameters_t *params, const unsigned size)
+ const solver_parameters_t *params, const std::size_t size)
: matrix_solver_t(anetlist, name, NOSORT, params)
,m_cnt(0)
, m_dim(size)
{
- for (unsigned k = 0; k < N(); k++)
+ for (std::size_t k = 0; k < N(); k++)
{
m_last_RHS[k] = 0.0;
}
diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp
index 52cccfd8419..d2ecf3c5bd2 100644
--- a/src/lib/netlist/solver/nld_solver.cpp
+++ b/src/lib/netlist/solver/nld_solver.cpp
@@ -10,34 +10,37 @@
*/
#if 0
-#pragma GCC optimize "-ffast-math"
-#pragma GCC optimize "-fstrict-aliasing"
-#pragma GCC optimize "-ftree-vectorizer-verbose=2"
-#pragma GCC optimize "-fopt-info-vec"
-#pragma GCC optimize "-fopt-info-vec-missed"
-//#pragma GCC optimize "-ftree-parallelize-loops=4"
-#pragma GCC optimize "-funroll-loops"
-#pragma GCC optimize "-funswitch-loops"
-#pragma GCC optimize "-fvariable-expansion-in-unroller"
-#pragma GCC optimize "-funsafe-loop-optimizations"
-#pragma GCC optimize "-fvect-cost-model"
-#pragma GCC optimize "-fvariable-expansion-in-unroller"
-#pragma GCC optimize "-ftree-loop-if-convert-stores"
-#pragma GCC optimize "-ftree-loop-distribution"
-#pragma GCC optimize "-ftree-loop-im"
-#pragma GCC optimize "-ftree-loop-ivcanon"
-#pragma GCC optimize "-fivopts"
+#pragma GCC optimize "fast-math"
+#pragma GCC optimize "strict-aliasing"
+#pragma GCC optimize "tree-vectorize"
+#pragma GCC optimize "tree-vectorizer-verbose=7"
+#pragma GCC optimize "opt-info-vec"
+#pragma GCC optimize "opt-info-vec-missed"
+//#pragma GCC optimize "tree-parallelize-loops=4"
+#pragma GCC optimize "unroll-loops"
+#pragma GCC optimize "unswitch-loops"
+#pragma GCC optimize "variable-expansion-in-unroller"
+#pragma GCC optimize "unsafe-loop-optimizations"
+#pragma GCC optimize "vect-cost-model"
+#pragma GCC optimize "variable-expansion-in-unroller"
+#pragma GCC optimize "tree-loop-if-convert-stores"
+#pragma GCC optimize "tree-loop-distribution"
+#pragma GCC optimize "tree-loop-im"
+#pragma GCC optimize "tree-loop-ivcanon"
+#pragma GCC optimize "ivopts"
#endif
-#include <iostream>
#include <algorithm>
+#include <cmath> // <<= needed by windows build
+
#include "nl_lists.h"
#if HAS_OPENMP
#include "omp.h"
#endif
-#include "plib/putil.h"
+#include "nl_factory.h"
+
#include "nld_solver.h"
#include "nld_matrix_solver.h"
@@ -107,6 +110,10 @@ NETLIB_UPDATE(solver)
ATTR_UNUSED const netlist_time ts = m_mat_solvers[i]->solve();
}
}
+
+ for (auto & solver : m_mat_solvers)
+ if (solver->has_timestep_devices() || force_solve)
+ solver->update_inputs();
}
else
for (int i = 0; i < t_cnt; i++)
@@ -114,12 +121,16 @@ NETLIB_UPDATE(solver)
{
// Ignore return value
ATTR_UNUSED const netlist_time ts = m_mat_solvers[i]->solve();
+ solver->update_inputs();
}
#else
for (auto & solver : m_mat_solvers)
if (solver->has_timestep_devices() || force_solve)
+ {
// Ignore return value
ATTR_UNUSED const netlist_time ts = solver->solve();
+ solver->update_inputs();
+ }
#endif
/* step circuit */
@@ -131,65 +142,65 @@ NETLIB_UPDATE(solver)
}
template <class C>
-std::unique_ptr<matrix_solver_t> create_it(netlist_t &nl, pstring name, solver_parameters_t &params, unsigned size)
+std::unique_ptr<matrix_solver_t> create_it(netlist_t &nl, pstring name, solver_parameters_t &params, std::size_t size)
{
typedef C solver;
return plib::make_unique<solver>(nl, name, &params, size);
}
-template <int m_N, int storage_N>
-std::unique_ptr<matrix_solver_t> NETLIB_NAME(solver)::create_solver(unsigned size, const bool use_specific)
+template <std::size_t m_N, std::size_t storage_N>
+std::unique_ptr<matrix_solver_t> NETLIB_NAME(solver)::create_solver(std::size_t size, const pstring &solvername)
{
- pstring solvername = plib::pfmt("Solver_{1}")(m_mat_solvers.size());
- if (use_specific && m_N == 1)
- return plib::make_unique<matrix_solver_direct1_t>(netlist(), solvername, &m_params);
- else if (use_specific && m_N == 2)
- return plib::make_unique<matrix_solver_direct2_t>(netlist(), solvername, &m_params);
- else
+ if (pstring("SOR_MAT").equals(m_method()))
{
- if (pstring("SOR_MAT").equals(m_method()))
- {
- return create_it<matrix_solver_SOR_mat_t<m_N, storage_N>>(netlist(), solvername, m_params, size);
- //typedef matrix_solver_SOR_mat_t<m_N,storage_N> solver_sor_mat;
- //return plib::make_unique<solver_sor_mat>(netlist(), solvername, &m_params, size);
- }
- else if (pstring("MAT_CR").equals(m_method()))
+ return create_it<matrix_solver_SOR_mat_t<m_N, storage_N>>(netlist(), solvername, m_params, size);
+ //typedef matrix_solver_SOR_mat_t<m_N,storage_N> solver_sor_mat;
+ //return plib::make_unique<solver_sor_mat>(netlist(), solvername, &m_params, size);
+ }
+ else if (pstring("MAT_CR").equals(m_method()))
+ {
+ if (size > 0) // GCR always outperforms MAT solver
{
typedef matrix_solver_GCR_t<m_N,storage_N> solver_mat;
return plib::make_unique<solver_mat>(netlist(), solvername, &m_params, size);
}
- else if (pstring("MAT").equals(m_method()))
+ else
{
typedef matrix_solver_direct_t<m_N,storage_N> solver_mat;
return plib::make_unique<solver_mat>(netlist(), solvername, &m_params, size);
}
- else if (pstring("SM").equals(m_method()))
- {
- /* Sherman-Morrison Formula */
- typedef matrix_solver_sm_t<m_N,storage_N> solver_mat;
- return plib::make_unique<solver_mat>(netlist(), solvername, &m_params, size);
- }
- else if (pstring("W").equals(m_method()))
- {
- /* Woodbury Formula */
- typedef matrix_solver_w_t<m_N,storage_N> solver_mat;
- return plib::make_unique<solver_mat>(netlist(), solvername, &m_params, size);
- }
- else if (pstring("SOR").equals(m_method()))
- {
- typedef matrix_solver_SOR_t<m_N,storage_N> solver_GS;
- return plib::make_unique<solver_GS>(netlist(), solvername, &m_params, size);
- }
- else if (pstring("GMRES").equals(m_method()))
- {
- typedef matrix_solver_GMRES_t<m_N,storage_N> solver_GMRES;
- return plib::make_unique<solver_GMRES>(netlist(), solvername, &m_params, size);
- }
- else
- {
- netlist().log().fatal("Unknown solver type: {1}\n", m_method());
- return nullptr;
- }
+ }
+ else if (pstring("MAT").equals(m_method()))
+ {
+ typedef matrix_solver_direct_t<m_N,storage_N> solver_mat;
+ return plib::make_unique<solver_mat>(netlist(), solvername, &m_params, size);
+ }
+ else if (pstring("SM").equals(m_method()))
+ {
+ /* Sherman-Morrison Formula */
+ typedef matrix_solver_sm_t<m_N,storage_N> solver_mat;
+ return plib::make_unique<solver_mat>(netlist(), solvername, &m_params, size);
+ }
+ else if (pstring("W").equals(m_method()))
+ {
+ /* Woodbury Formula */
+ typedef matrix_solver_w_t<m_N,storage_N> solver_mat;
+ return plib::make_unique<solver_mat>(netlist(), solvername, &m_params, size);
+ }
+ else if (pstring("SOR").equals(m_method()))
+ {
+ typedef matrix_solver_SOR_t<m_N,storage_N> solver_GS;
+ return plib::make_unique<solver_GS>(netlist(), solvername, &m_params, size);
+ }
+ else if (pstring("GMRES").equals(m_method()))
+ {
+ typedef matrix_solver_GMRES_t<m_N,storage_N> solver_GMRES;
+ return plib::make_unique<solver_GMRES>(netlist(), solvername, &m_params, size);
+ }
+ else
+ {
+ log().fatal(MF_1_UNKNOWN_SOLVER_TYPE, m_method());
+ return nullptr;
}
}
@@ -214,7 +225,7 @@ struct net_splitter
groups.back().push_back(n);
for (auto &p : n->m_core_terms)
{
- if (p->is_type(terminal_t::TERMINAL))
+ if (p->is_type(detail::terminal_type::TERMINAL))
{
terminal_t *pt = static_cast<terminal_t *>(p);
analog_net_t *other_net = &pt->m_otherterm->net();
@@ -275,13 +286,13 @@ void NETLIB_NAME(solver)::post_start()
//m_params.m_max_timestep = std::max(m_params.m_max_timestep, m_params.m_max_timestep::)
// Override log statistics
- pstring p = plib::util::environment("NL_STATS");
+ pstring p = plib::util::environment("NL_STATS", "");
if (p != "")
m_params.m_log_stats = p.as_long();
else
m_params.m_log_stats = m_log_stats();
- netlist().log().verbose("Scanning net groups ...");
+ log().verbose("Scanning net groups ...");
// determine net groups
net_splitter splitter;
@@ -289,86 +300,103 @@ void NETLIB_NAME(solver)::post_start()
splitter.run(netlist());
// setup the solvers
- netlist().log().verbose("Found {1} net groups in {2} nets\n", splitter.groups.size(), netlist().m_nets.size());
+ log().verbose("Found {1} net groups in {2} nets\n", splitter.groups.size(), netlist().m_nets.size());
for (auto & grp : splitter.groups)
{
std::unique_ptr<matrix_solver_t> ms;
- unsigned net_count = static_cast<unsigned>(grp.size());
+ std::size_t net_count = grp.size();
+ pstring sname = plib::pfmt("Solver_{1}")(m_mat_solvers.size());
switch (net_count)
{
#if 1
case 1:
- ms = create_solver<1,1>(1, use_specific);
+ if (use_specific)
+ ms = plib::make_unique<matrix_solver_direct1_t>(netlist(), sname, &m_params);
+ else
+ ms = create_solver<1,1>(1, sname);
break;
case 2:
- ms = create_solver<2,2>(2, use_specific);
+ if (use_specific)
+ ms = plib::make_unique<matrix_solver_direct2_t>(netlist(), sname, &m_params);
+ else
+ ms = create_solver<2,2>(2, sname);
break;
case 3:
- ms = create_solver<3,3>(3, use_specific);
+ ms = create_solver<3,3>(3, sname);
break;
case 4:
- ms = create_solver<4,4>(4, use_specific);
+ ms = create_solver<4,4>(4, sname);
break;
case 5:
- ms = create_solver<5,5>(5, use_specific);
+ ms = create_solver<5,5>(5, sname);
break;
case 6:
- ms = create_solver<6,6>(6, use_specific);
+ ms = create_solver<6,6>(6, sname);
break;
case 7:
- ms = create_solver<7,7>(7, use_specific);
+ ms = create_solver<7,7>(7, sname);
break;
case 8:
- ms = create_solver<8,8>(8, use_specific);
+ ms = create_solver<8,8>(8, sname);
+ break;
+ case 9:
+ ms = create_solver<9,9>(9, sname);
break;
case 10:
- ms = create_solver<10,10>(10, use_specific);
+ ms = create_solver<10,10>(10, sname);
break;
case 11:
- ms = create_solver<11,11>(11, use_specific);
+ ms = create_solver<11,11>(11, sname);
break;
case 12:
- ms = create_solver<12,12>(12, use_specific);
+ ms = create_solver<12,12>(12, sname);
break;
case 15:
- ms = create_solver<15,15>(15, use_specific);
+ ms = create_solver<15,15>(15, sname);
break;
case 31:
- ms = create_solver<31,31>(31, use_specific);
+ ms = create_solver<31,31>(31, sname);
+ break;
+ case 35:
+ ms = create_solver<31,31>(31, sname);
break;
case 49:
- ms = create_solver<49,49>(49, use_specific);
+ ms = create_solver<49,49>(49, sname);
break;
#if 0
case 87:
- ms = create_solver<87,87>(87, use_specific);
+ ms = create_solver<87,87>(87, sname);
break;
#endif
#endif
default:
- netlist().log().warning("No specific solver found for netlist of size {1}", net_count);
- if (net_count <= 16)
+ log().warning(MW_1_NO_SPECIFIC_SOLVER, net_count);
+ if (net_count <= 8)
+ {
+ ms = create_solver<0, 8>(net_count, sname);
+ }
+ else if (net_count <= 16)
{
- ms = create_solver<0,16>(net_count, use_specific);
+ ms = create_solver<0,16>(net_count, sname);
}
else if (net_count <= 32)
{
- ms = create_solver<0,32>(net_count, use_specific);
+ ms = create_solver<0,32>(net_count, sname);
}
else
if (net_count <= 64)
{
- ms = create_solver<0,64>(net_count, use_specific);
+ ms = create_solver<0,64>(net_count, sname);
}
else
if (net_count <= 128)
{
- ms = create_solver<0,128>(net_count, use_specific);
+ ms = create_solver<0,128>(net_count, sname);
}
else
{
- netlist().log().fatal("Encountered netgroup with > 128 nets");
+ log().fatal(MF_1_NETGROUP_SIZE_EXCEEDED_1, 128);
ms = nullptr; /* tease compilers */
}
@@ -379,16 +407,16 @@ void NETLIB_NAME(solver)::post_start()
ms->set_delegate_pointer();
ms->setup(grp);
- netlist().log().verbose("Solver {1}", ms->name());
- netlist().log().verbose(" ==> {2} nets", grp.size());
- netlist().log().verbose(" has {1} elements", ms->has_dynamic_devices() ? "dynamic" : "no dynamic");
- netlist().log().verbose(" has {1} elements", ms->has_timestep_devices() ? "timestep" : "no timestep");
+ log().verbose("Solver {1}", ms->name());
+ log().verbose(" ==> {2} nets", grp.size());
+ log().verbose(" has {1} elements", ms->has_dynamic_devices() ? "dynamic" : "no dynamic");
+ log().verbose(" has {1} elements", ms->has_timestep_devices() ? "timestep" : "no timestep");
for (auto &n : grp)
{
- netlist().log().verbose("Net {1}", n->name());
+ log().verbose("Net {1}", n->name());
for (const auto &pcore : n->m_core_terms)
{
- netlist().log().verbose(" {1}", pcore->name());
+ log().verbose(" {1}", pcore->name());
}
}
@@ -396,12 +424,16 @@ void NETLIB_NAME(solver)::post_start()
}
}
-void NETLIB_NAME(solver)::create_solver_code(plib::postream &strm)
+void NETLIB_NAME(solver)::create_solver_code(std::map<pstring, pstring> &mp)
{
for (auto & s : m_mat_solvers)
- s->create_solver_code(strm);
+ {
+ auto r = s->create_solver_code();
+ mp[r.first] = r.second; // automatically overwrites identical names
+ }
}
+ NETLIB_DEVICE_IMPL(solver)
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/solver/nld_solver.h b/src/lib/netlist/solver/nld_solver.h
index e3ba6419f8b..4f6eb2a21d9 100644
--- a/src/lib/netlist/solver/nld_solver.h
+++ b/src/lib/netlist/solver/nld_solver.h
@@ -8,7 +8,8 @@
#ifndef NLD_SOLVER_H_
#define NLD_SOLVER_H_
-#include "nl_setup.h"
+#include <map>
+
#include "nl_base.h"
#include "plib/pstream.h"
#include "solver/nld_matrix_solver.h"
@@ -17,14 +18,6 @@
#define ATTR_ALIGNED(N) ATTR_ALIGN
// ----------------------------------------------------------------------------------------
-// Macros
-// ----------------------------------------------------------------------------------------
-
-#define SOLVER(name, freq) \
- NET_REGISTER_DEV(SOLVER, name) \
- PARAM(name.FREQ, freq)
-
-// ----------------------------------------------------------------------------------------
// solver
// ----------------------------------------------------------------------------------------
@@ -59,7 +52,7 @@ NETLIB_OBJECT(solver)
/* automatic time step */
, m_dynamic_ts(*this, "DYNAMIC_TS", 0)
- , m_dynamic_lte(*this, "DYNAMIC_LTE", 5e-5) // diff/timestep
+ , m_dynamic_lte(*this, "DYNAMIC_LTE", 1e-5) // diff/timestep
, m_dynamic_min_ts(*this, "DYNAMIC_MIN_TIMESTEP", 1e-6) // nl_double timestep resolution
, m_log_stats(*this, "LOG_STATS", 1) // nl_double timestep resolution
@@ -76,7 +69,7 @@ NETLIB_OBJECT(solver)
inline nl_double gmin() { return m_gmin(); }
- void create_solver_code(plib::postream &strm);
+ void create_solver_code(std::map<pstring, pstring> &mp);
NETLIB_UPDATEI();
NETLIB_RESETI();
@@ -107,8 +100,8 @@ private:
solver_parameters_t m_params;
- template <int m_N, int storage_N>
- std::unique_ptr<matrix_solver_t> create_solver(unsigned size, bool use_specific);
+ template <std::size_t m_N, std::size_t storage_N>
+ std::unique_ptr<matrix_solver_t> create_solver(std::size_t size, const pstring &solvername);
};
} //namespace devices
diff --git a/src/lib/netlist/solver/vector_base.h b/src/lib/netlist/solver/vector_base.h
index 3f0c53c8ade..b294eb0ee48 100644..100755
--- a/src/lib/netlist/solver/vector_base.h
+++ b/src/lib/netlist/solver/vector_base.h
@@ -36,14 +36,14 @@ private:
#endif
template<typename T>
-inline void vec_set (const std::size_t & n, const T &scalar, T * RESTRICT result)
+inline static void vec_set (const std::size_t n, const T scalar, T * RESTRICT result)
{
for ( std::size_t i = 0; i < n; i++ )
result[i] = scalar;
}
template<typename T>
-inline T vecmult (const std::size_t & n, const T * RESTRICT a1, const T * RESTRICT a2 )
+inline static T vecmult (const std::size_t n, const T * RESTRICT a1, const T * RESTRICT a2 )
{
T value = 0.0;
for ( std::size_t i = 0; i < n; i++ )
@@ -52,7 +52,7 @@ inline T vecmult (const std::size_t & n, const T * RESTRICT a1, const T * RESTRI
}
template<typename T>
-inline T vecmult2 (const std::size_t & n, const T *a1)
+inline static T vecmult2 (const std::size_t n, const T *a1)
{
T value = 0.0;
for ( std::size_t i = 0; i < n; i++ )
@@ -63,43 +63,56 @@ inline T vecmult2 (const std::size_t & n, const T *a1)
return value;
}
-template<typename T>
-inline void vec_mult_scalar (const std::size_t & n, const T * RESTRICT v, const T & scalar, T * RESTRICT result)
+template<typename T, std::size_t N>
+inline static void vec_mult_scalar (const std::size_t n, const T (& RESTRICT v)[N], const T & scalar, T (& RESTRICT result)[N])
{
- for ( std::size_t i = 0; i < n; i++ )
- {
- result[i] = scalar * v[i];
- }
+ if (n != N)
+ for ( std::size_t i = 0; i < n; i++ )
+ result[i] = scalar * v[i];
+ else
+ for ( std::size_t i = 0; i < N; i++ )
+ result[i] = scalar * v[i];
+}
+
+template<typename T, std::size_t N>
+inline static void vec_add_mult_scalar (const std::size_t n, const T (& RESTRICT v)[N], const T scalar, T (& RESTRICT result)[N])
+{
+ if (n != N)
+ for ( std::size_t i = 0; i < n; i++ )
+ result[i] = result[i] + scalar * v[i];
+ else
+ for ( std::size_t i = 0; i < N; i++ )
+ result[i] = result[i] + scalar * v[i];
}
template<typename T>
-inline void vec_add_mult_scalar (const std::size_t & n, const T * RESTRICT v, const T scalar, T * RESTRICT result)
+inline static void vec_add_mult_scalar_p(const std::size_t & n, const T * RESTRICT v, const T scalar, T * RESTRICT result)
{
for ( std::size_t i = 0; i < n; i++ )
result[i] += scalar * v[i];
}
-inline void vec_add_ip(const std::size_t & n, const double * RESTRICT v, double * RESTRICT result)
+inline static void vec_add_ip(const std::size_t n, const double * RESTRICT v, double * RESTRICT result)
{
for ( std::size_t i = 0; i < n; i++ )
result[i] += v[i];
}
template<typename T>
-inline void vec_sub(const std::size_t & n, const T * RESTRICT v1, const T * RESTRICT v2, T * RESTRICT result)
+inline void vec_sub(const std::size_t n, const T * RESTRICT v1, const T * RESTRICT v2, T * RESTRICT result)
{
for ( std::size_t i = 0; i < n; i++ )
result[i] = v1[i] - v2[i];
}
template<typename T>
-inline void vec_scale (const std::size_t & n, T * RESTRICT v, const T scalar)
+inline void vec_scale (const std::size_t n, T * RESTRICT v, const T scalar)
{
for ( std::size_t i = 0; i < n; i++ )
v[i] = scalar * v[i];
}
-inline double vec_maxabs(const std::size_t & n, const double * RESTRICT v)
+inline double vec_maxabs(const std::size_t n, const double * RESTRICT v)
{
double ret = 0.0;
for ( std::size_t i = 0; i < n; i++ )
diff --git a/src/lib/netlist/tools/nl_convert.cpp b/src/lib/netlist/tools/nl_convert.cpp
index 9523febf06a..5b0bfd267c3 100644
--- a/src/lib/netlist/tools/nl_convert.cpp
+++ b/src/lib/netlist/tools/nl_convert.cpp
@@ -6,7 +6,6 @@
*/
#include <algorithm>
-#include <cstdio>
#include <cmath>
#include <unordered_map>
#include "nl_convert.h"
@@ -18,7 +17,7 @@
* define a model param on core device
*/
/* Format: external name,netlist device,model */
-static const char *s_lib_map =
+static const pstring s_lib_map =
"SN74LS00D, TTL_7400_DIP, 74LSXX\n"
"SN74LS04D, TTL_7404_DIP, 74LSXX\n"
"SN74ALS08D, TTL_7408_DIP, 74ALSXX\n"
@@ -44,11 +43,12 @@ using lib_map_t = std::unordered_map<pstring, lib_map_entry>;
static lib_map_t read_lib_map(const pstring lm)
{
plib::pistringstream istrm(lm);
+ plib::putf8_reader reader(istrm);
lib_map_t m;
pstring line;
- while (istrm.readline(line))
+ while (reader.readline(line))
{
- plib::pstring_vector_t split(line, ",");
+ std::vector<pstring> split(plib::psplit(line, ","));
m[split[0].trim()] = { split[1].trim(), split[2].trim() };
}
return m;
@@ -185,21 +185,21 @@ const pstring nl_convert_base_t::get_nl_val(const double val)
{
{
int i = 0;
- while (m_units[i].m_unit != "-" )
+ while (pstring(m_units[i].m_unit, pstring::UTF8) != "-" )
{
if (m_units[i].m_mult <= std::abs(val))
break;
i++;
}
- return plib::pfmt(m_units[i].m_func.c_str())(val / m_units[i].m_mult);
+ return plib::pfmt(pstring(m_units[i].m_func, pstring::UTF8))(val / m_units[i].m_mult);
}
}
double nl_convert_base_t::get_sp_unit(const pstring &unit)
{
int i = 0;
- while (m_units[i].m_unit != "-")
+ while (pstring(m_units[i].m_unit, pstring::UTF8) != "-")
{
- if (m_units[i].m_unit == unit)
+ if (pstring(m_units[i].m_unit, pstring::UTF8) == unit)
return m_units[i].m_mult;
i++;
}
@@ -242,7 +242,7 @@ nl_convert_base_t::unit_t nl_convert_base_t::m_units[] = {
void nl_convert_spice_t::convert(const pstring &contents)
{
- plib::pstring_vector_t spnl(contents, "\n");
+ std::vector<pstring> spnl(plib::psplit(contents, "\n"));
// Add gnd net
@@ -274,7 +274,7 @@ void nl_convert_spice_t::process_line(const pstring &line)
{
if (line != "")
{
- plib::pstring_vector_t tt(line, " ", true);
+ std::vector<pstring> tt(plib::psplit(line, " ", true));
double val = 0.0;
switch (tt[0].code_at(0))
{
@@ -313,7 +313,7 @@ void nl_convert_spice_t::process_line(const pstring &line)
model = tt[5];
else
model = tt[4];
- plib::pstring_vector_t m(model,"{");
+ std::vector<pstring> m(plib::psplit(model,"{"));
if (m.size() == 2)
{
if (m[1].len() != 4)
@@ -401,19 +401,13 @@ void nl_convert_spice_t::process_line(const pstring &line)
Eagle converter
-------------------------------------------------*/
-nl_convert_eagle_t::tokenizer::tokenizer(nl_convert_eagle_t &convert, plib::pistream &strm)
+nl_convert_eagle_t::tokenizer::tokenizer(nl_convert_eagle_t &convert, plib::putf8_reader &strm)
: plib::ptokenizer(strm)
, m_convert(convert)
{
set_identifier_chars("abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-");
set_number_chars(".0123456789", "0123456789eE-."); //FIXME: processing of numbers
- char ws[5];
- ws[0] = ' ';
- ws[1] = 9;
- ws[2] = 10;
- ws[3] = 13;
- ws[4] = 0;
- set_whitespace(ws);
+ set_whitespace(pstring("").cat(' ').cat(9).cat(10).cat(13));
/* FIXME: gnetlist doesn't print comments */
set_comment("/*", "*/", "//");
set_string_char('\'');
@@ -435,7 +429,8 @@ void nl_convert_eagle_t::tokenizer::verror(const pstring &msg, int line_num, con
void nl_convert_eagle_t::convert(const pstring &contents)
{
plib::pistringstream istrm(contents);
- tokenizer tok(*this, istrm);
+ plib::putf8_reader reader(istrm);
+ tokenizer tok(*this, reader);
out("NETLIST_START(dummy)\n");
add_term("GND", "GND");
@@ -543,19 +538,13 @@ void nl_convert_eagle_t::convert(const pstring &contents)
RINF converter
-------------------------------------------------*/
-nl_convert_rinf_t::tokenizer::tokenizer(nl_convert_rinf_t &convert, plib::pistream &strm)
+nl_convert_rinf_t::tokenizer::tokenizer(nl_convert_rinf_t &convert, plib::putf8_reader &strm)
: plib::ptokenizer(strm)
, m_convert(convert)
{
set_identifier_chars(".abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_-");
set_number_chars("0123456789", "0123456789eE-."); //FIXME: processing of numbers
- char ws[5];
- ws[0] = ' ';
- ws[1] = 9;
- ws[2] = 10;
- ws[3] = 13;
- ws[4] = 0;
- set_whitespace(ws);
+ set_whitespace(pstring("").cat(' ').cat(9).cat(10).cat(13));
/* FIXME: gnetlist doesn't print comments */
set_comment("","","//"); // FIXME:needs to be confirmed
set_string_char('"');
@@ -589,7 +578,8 @@ void nl_convert_rinf_t::tokenizer::verror(const pstring &msg, int line_num, cons
void nl_convert_rinf_t::convert(const pstring &contents)
{
plib::pistringstream istrm(contents);
- tokenizer tok(*this, istrm);
+ plib::putf8_reader reader(istrm);
+ tokenizer tok(*this, reader);
auto lm = read_lib_map(s_lib_map);
out("NETLIST_START(dummy)\n");
diff --git a/src/lib/netlist/tools/nl_convert.h b/src/lib/netlist/tools/nl_convert.h
index 3536488c766..d0d12c377e0 100644
--- a/src/lib/netlist/tools/nl_convert.h
+++ b/src/lib/netlist/tools/nl_convert.h
@@ -49,7 +49,7 @@ protected:
double get_sp_val(const pstring &sin);
- plib::pstream_fmt_writer_t out;
+ plib::putf8_fmt_writer out;
private:
struct net_t
@@ -59,14 +59,14 @@ private:
: m_name(aname), m_no_export(false) {}
const pstring &name() { return m_name;}
- plib::pstring_vector_t &terminals() { return m_terminals; }
+ std::vector<pstring> &terminals() { return m_terminals; }
void set_no_export() { m_no_export = true; }
bool is_no_export() { return m_no_export; }
private:
pstring m_name;
bool m_no_export;
- plib::pstring_vector_t m_terminals;
+ std::vector<pstring> m_terminals;
};
struct dev_t
@@ -101,8 +101,8 @@ private:
};
struct unit_t {
- pstring m_unit;
- pstring m_func;
+ const char *m_unit;
+ const char *m_func;
double m_mult;
};
@@ -166,7 +166,7 @@ public:
class tokenizer : public plib::ptokenizer
{
public:
- tokenizer(nl_convert_eagle_t &convert, plib::pistream &strm);
+ tokenizer(nl_convert_eagle_t &convert, plib::putf8_reader &strm);
token_id_t m_tok_ADD;
token_id_t m_tok_VALUE;
@@ -202,7 +202,7 @@ public:
class tokenizer : public plib::ptokenizer
{
public:
- tokenizer(nl_convert_rinf_t &convert, plib::pistream &strm);
+ tokenizer(nl_convert_rinf_t &convert, plib::putf8_reader &strm);
token_id_t m_tok_HEA;
token_id_t m_tok_APP;
diff --git a/src/lib/util/chd.cpp b/src/lib/util/chd.cpp
index 0db64344861..dc7c334b1bf 100644
--- a/src/lib/util/chd.cpp
+++ b/src/lib/util/chd.cpp
@@ -885,7 +885,7 @@ chd_error chd_file::read_hunk(uint32_t hunknum, void *buffer)
// get a pointer to the map entry
uint64_t blockoffs;
uint32_t blocklen;
- uint32_t blockcrc;
+ util::crc32_t blockcrc;
uint8_t *rawmap;
uint8_t *dest = reinterpret_cast<uint8_t *>(buffer);
switch (m_version)
@@ -2147,12 +2147,12 @@ void chd_file::decompress_v5_map()
// read the reader
uint8_t rawbuf[16];
file_read(m_mapoffset, rawbuf, sizeof(rawbuf));
- uint32_t mapbytes = be_read(&rawbuf[0], 4);
- uint64_t firstoffs = be_read(&rawbuf[4], 6);
- uint16_t mapcrc = be_read(&rawbuf[10], 2);
- uint8_t lengthbits = rawbuf[12];
- uint8_t selfbits = rawbuf[13];
- uint8_t parentbits = rawbuf[14];
+ uint32_t const mapbytes = be_read(&rawbuf[0], 4);
+ uint64_t const firstoffs = be_read(&rawbuf[4], 6);
+ util::crc16_t const mapcrc = be_read(&rawbuf[10], 2);
+ uint8_t const lengthbits = rawbuf[12];
+ uint8_t const selfbits = rawbuf[13];
+ uint8_t const parentbits = rawbuf[14];
// now read the map
std::vector<uint8_t> compressed(mapbytes);
diff --git a/src/lib/util/hashing.h b/src/lib/util/hashing.h
index 906bad047b4..5e9c9134c97 100644
--- a/src/lib/util/hashing.h
+++ b/src/lib/util/hashing.h
@@ -15,10 +15,12 @@
#include "osdcore.h"
#include "corestr.h"
-#include <string>
#include "md5.h"
#include "sha1.h"
+#include <functional>
+#include <string>
+
namespace util {
//**************************************************************************
@@ -132,13 +134,23 @@ protected:
// final digest
struct crc32_t
{
- bool operator==(const crc32_t &rhs) const { return m_raw == rhs.m_raw; }
- bool operator!=(const crc32_t &rhs) const { return m_raw != rhs.m_raw; }
+ crc32_t() { }
+ constexpr crc32_t(const crc32_t &rhs) = default;
+ constexpr crc32_t(const uint32_t crc) : m_raw(crc) { }
+
+ constexpr bool operator==(const crc32_t &rhs) const { return m_raw == rhs.m_raw; }
+ constexpr bool operator!=(const crc32_t &rhs) const { return m_raw != rhs.m_raw; }
+
+ crc32_t &operator=(const crc32_t &rhs) = default;
crc32_t &operator=(const uint32_t crc) { m_raw = crc; return *this; }
- operator uint32_t() const { return m_raw; }
+
+ constexpr operator uint32_t() const { return m_raw; }
+
bool from_string(const char *string, int length = -1);
std::string as_string() const;
+
uint32_t m_raw;
+
static const crc32_t null;
};
@@ -178,13 +190,23 @@ protected:
// final digest
struct crc16_t
{
- bool operator==(const crc16_t &rhs) const { return m_raw == rhs.m_raw; }
- bool operator!=(const crc16_t &rhs) const { return m_raw != rhs.m_raw; }
+ crc16_t() { }
+ constexpr crc16_t(const crc16_t &rhs) = default;
+ constexpr crc16_t(const uint16_t crc) : m_raw(crc) { }
+
+ constexpr bool operator==(const crc16_t &rhs) const { return m_raw == rhs.m_raw; }
+ constexpr bool operator!=(const crc16_t &rhs) const { return m_raw != rhs.m_raw; }
+
+ crc16_t &operator=(const crc16_t &rhs) = default;
crc16_t &operator=(const uint16_t crc) { m_raw = crc; return *this; }
- operator uint16_t() const { return m_raw; }
+
+ constexpr operator uint16_t() const { return m_raw; }
+
bool from_string(const char *string, int length = -1);
std::string as_string() const;
+
uint16_t m_raw;
+
static const crc16_t null;
};
@@ -220,4 +242,22 @@ protected:
} // namespace util
+namespace std {
+
+template <> struct hash<::util::crc32_t>
+{
+ typedef ::util::crc32_t argument_type;
+ typedef std::size_t result_type;
+ result_type operator()(argument_type const & s) const { return std::hash<std::uint32_t>()(s); }
+};
+
+template <> struct hash<::util::crc16_t>
+{
+ typedef ::util::crc16_t argument_type;
+ typedef std::size_t result_type;
+ result_type operator()(argument_type const & s) const { return std::hash<std::uint16_t>()(s); }
+};
+
+} // namespace std
+
#endif // __HASHING_H__
diff --git a/src/lib/util/path_to_regex.cpp b/src/lib/util/path_to_regex.cpp
index 927ababbb8a..89a21a5e7f6 100644
--- a/src/lib/util/path_to_regex.cpp
+++ b/src/lib/util/path_to_regex.cpp
@@ -1,7 +1,7 @@
// license:MIT
// copyright-holders:Alfred Bratterud
-// NOTE: Author allowed MAME project to distribute this file under MIT
-// license. Other projects need to do it under Apache 2 license
+// NOTE: Author allowed MAME project to distribute this file under MIT
+// license. Other projects need to do it under Apache 2 license
//
// This file is a part of the IncludeOS unikernel - www.includeos.org
//
diff --git a/src/lib/util/path_to_regex.hpp b/src/lib/util/path_to_regex.hpp
index 7608d77bb5d..a6b11a22031 100644
--- a/src/lib/util/path_to_regex.hpp
+++ b/src/lib/util/path_to_regex.hpp
@@ -1,7 +1,7 @@
// license:MIT
// copyright-holders:Alfred Bratterud
-// NOTE: Author allowed MAME project to distribute this file under MIT
-// license. Other projects need to do it under Apache 2 license
+// NOTE: Author allowed MAME project to distribute this file under MIT
+// license. Other projects need to do it under Apache 2 license
//
// This file is a part of the IncludeOS unikernel - www.includeos.org
//
diff --git a/src/lib/util/server_ws.hpp b/src/lib/util/server_ws.hpp
index 170dc31ae63..b9d4721e96b 100644
--- a/src/lib/util/server_ws.hpp
+++ b/src/lib/util/server_ws.hpp
@@ -64,7 +64,7 @@ namespace webpp {
}
};
-
+
class Connection {
friend class SocketServerBase<socket_type>;
friend class SocketServer<socket_type>;
@@ -142,7 +142,7 @@ namespace webpp {
catch (...) {}
}
};
-
+
class Message : public std::istream {
friend class SocketServerBase<socket_type>;
diff --git a/src/lib/util/sha1.hpp b/src/lib/util/sha1.hpp
index 7befbd326f0..a293bebb7cc 100644
--- a/src/lib/util/sha1.hpp
+++ b/src/lib/util/sha1.hpp
@@ -36,76 +36,76 @@ namespace { // local
// Rotate an integer value to left.
inline unsigned int rol(unsigned int value, unsigned int steps) {
- return ((value << steps) | (value >> (32 - steps)));
+ return ((value << steps) | (value >> (32 - steps)));
}
// Sets the first 16 integers in the buffert to zero.
// Used for clearing the W buffert.
inline void clearWBuffert(unsigned int * buffert)
{
- for (int pos = 16; --pos >= 0;)
- {
- buffert[pos] = 0;
- }
+ for (int pos = 16; --pos >= 0;)
+ {
+ buffert[pos] = 0;
+ }
}
inline void innerHash(unsigned int * result, unsigned int * w)
{
- unsigned int a = result[0];
- unsigned int b = result[1];
- unsigned int c = result[2];
- unsigned int d = result[3];
- unsigned int e = result[4];
-
- int round = 0;
-
- #define sha1macro(func,val) \
- { \
- const unsigned int t = rol(a, 5) + (func) + e + val + w[round]; \
- e = d; \
- d = c; \
- c = rol(b, 30); \
- b = a; \
- a = t; \
- }
-
- while (round < 16)
- {
- sha1macro((b & c) | (~b & d), 0x5a827999)
- ++round;
- }
- while (round < 20)
- {
- w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
- sha1macro((b & c) | (~b & d), 0x5a827999)
- ++round;
- }
- while (round < 40)
- {
- w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
- sha1macro(b ^ c ^ d, 0x6ed9eba1)
- ++round;
- }
- while (round < 60)
- {
- w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
- sha1macro((b & c) | (b & d) | (c & d), 0x8f1bbcdc)
- ++round;
- }
- while (round < 80)
- {
- w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
- sha1macro(b ^ c ^ d, 0xca62c1d6)
- ++round;
- }
-
- #undef sha1macro
-
- result[0] += a;
- result[1] += b;
- result[2] += c;
- result[3] += d;
- result[4] += e;
+ unsigned int a = result[0];
+ unsigned int b = result[1];
+ unsigned int c = result[2];
+ unsigned int d = result[3];
+ unsigned int e = result[4];
+
+ int round = 0;
+
+ #define sha1macro(func,val) \
+ { \
+ const unsigned int t = rol(a, 5) + (func) + e + val + w[round]; \
+ e = d; \
+ d = c; \
+ c = rol(b, 30); \
+ b = a; \
+ a = t; \
+ }
+
+ while (round < 16)
+ {
+ sha1macro((b & c) | (~b & d), 0x5a827999)
+ ++round;
+ }
+ while (round < 20)
+ {
+ w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
+ sha1macro((b & c) | (~b & d), 0x5a827999)
+ ++round;
+ }
+ while (round < 40)
+ {
+ w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
+ sha1macro(b ^ c ^ d, 0x6ed9eba1)
+ ++round;
+ }
+ while (round < 60)
+ {
+ w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
+ sha1macro((b & c) | (b & d) | (c & d), 0x8f1bbcdc)
+ ++round;
+ }
+ while (round < 80)
+ {
+ w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
+ sha1macro(b ^ c ^ d, 0xca62c1d6)
+ ++round;
+ }
+
+ #undef sha1macro
+
+ result[0] += a;
+ result[1] += b;
+ result[2] += c;
+ result[3] += d;
+ result[4] += e;
}
} // namespace
@@ -118,62 +118,62 @@ inline void innerHash(unsigned int * result, unsigned int * w)
* the sha1 result in.
*/
inline void calc(void const * src, size_t bytelength, unsigned char * hash) {
- // Init the result array.
- unsigned int result[5] = { 0x67452301, 0xefcdab89, 0x98badcfe,
- 0x10325476, 0xc3d2e1f0 };
-
- // Cast the void src pointer to be the byte array we can work with.
- unsigned char const * sarray = static_cast<unsigned char const *>(src);
-
- // The reusable round buffer
- unsigned int w[80];
-
- // Loop through all complete 64byte blocks.
-
- size_t endCurrentBlock;
- size_t currentBlock = 0;
-
- if (bytelength >= 64) {
- size_t const endOfFullBlocks = bytelength - 64;
-
- while (currentBlock <= endOfFullBlocks) {
- endCurrentBlock = currentBlock + 64;
-
- // Init the round buffer with the 64 byte block data.
- for (int roundPos = 0; currentBlock < endCurrentBlock; currentBlock += 4)
- {
- // This line will swap endian on big endian and keep endian on
- // little endian.
- w[roundPos++] = static_cast<unsigned int>(sarray[currentBlock + 3])
- | (static_cast<unsigned int>(sarray[currentBlock + 2]) << 8)
- | (static_cast<unsigned int>(sarray[currentBlock + 1]) << 16)
- | (static_cast<unsigned int>(sarray[currentBlock]) << 24);
- }
- innerHash(result, w);
- }
- }
-
- // Handle the last and not full 64 byte block if existing.
- endCurrentBlock = bytelength - currentBlock;
- clearWBuffert(w);
- size_t lastBlockBytes = 0;
- for (;lastBlockBytes < endCurrentBlock; ++lastBlockBytes) {
- w[lastBlockBytes >> 2] |= static_cast<unsigned int>(sarray[lastBlockBytes + currentBlock]) << ((3 - (lastBlockBytes & 3)) << 3);
- }
-
- w[lastBlockBytes >> 2] |= 0x80 << ((3 - (lastBlockBytes & 3)) << 3);
- if (endCurrentBlock >= 56) {
- innerHash(result, w);
- clearWBuffert(w);
- }
- w[15] = bytelength << 3;
- innerHash(result, w);
-
- // Store hash in result pointer, and make sure we get in in the correct
- // order on both endian models.
- for (int hashByte = 20; --hashByte >= 0;) {
- hash[hashByte] = (result[hashByte >> 2] >> (((3 - hashByte) & 0x3) << 3)) & 0xff;
- }
+ // Init the result array.
+ unsigned int result[5] = { 0x67452301, 0xefcdab89, 0x98badcfe,
+ 0x10325476, 0xc3d2e1f0 };
+
+ // Cast the void src pointer to be the byte array we can work with.
+ unsigned char const * sarray = static_cast<unsigned char const *>(src);
+
+ // The reusable round buffer
+ unsigned int w[80];
+
+ // Loop through all complete 64byte blocks.
+
+ size_t endCurrentBlock;
+ size_t currentBlock = 0;
+
+ if (bytelength >= 64) {
+ size_t const endOfFullBlocks = bytelength - 64;
+
+ while (currentBlock <= endOfFullBlocks) {
+ endCurrentBlock = currentBlock + 64;
+
+ // Init the round buffer with the 64 byte block data.
+ for (int roundPos = 0; currentBlock < endCurrentBlock; currentBlock += 4)
+ {
+ // This line will swap endian on big endian and keep endian on
+ // little endian.
+ w[roundPos++] = static_cast<unsigned int>(sarray[currentBlock + 3])
+ | (static_cast<unsigned int>(sarray[currentBlock + 2]) << 8)
+ | (static_cast<unsigned int>(sarray[currentBlock + 1]) << 16)
+ | (static_cast<unsigned int>(sarray[currentBlock]) << 24);
+ }
+ innerHash(result, w);
+ }
+ }
+
+ // Handle the last and not full 64 byte block if existing.
+ endCurrentBlock = bytelength - currentBlock;
+ clearWBuffert(w);
+ size_t lastBlockBytes = 0;
+ for (;lastBlockBytes < endCurrentBlock; ++lastBlockBytes) {
+ w[lastBlockBytes >> 2] |= static_cast<unsigned int>(sarray[lastBlockBytes + currentBlock]) << ((3 - (lastBlockBytes & 3)) << 3);
+ }
+
+ w[lastBlockBytes >> 2] |= 0x80 << ((3 - (lastBlockBytes & 3)) << 3);
+ if (endCurrentBlock >= 56) {
+ innerHash(result, w);
+ clearWBuffert(w);
+ }
+ w[15] = bytelength << 3;
+ innerHash(result, w);
+
+ // Store hash in result pointer, and make sure we get in in the correct
+ // order on both endian models.
+ for (int hashByte = 20; --hashByte >= 0;) {
+ hash[hashByte] = (result[hashByte >> 2] >> (((3 - hashByte) & 0x3) << 3)) & 0xff;
+ }
}
} // namespace sha1
diff --git a/src/lib/util/unicode.cpp b/src/lib/util/unicode.cpp
index 5849abb8d73..b48cef44c79 100644
--- a/src/lib/util/unicode.cpp
+++ b/src/lib/util/unicode.cpp
@@ -15,7 +15,7 @@
#define UTF8PROC_DLLEXPORT
#endif
-#include "utf8proc/utf8proc.h"
+#include <utf8proc.h>
#include <codecvt>
#include <locale>
@@ -389,7 +389,7 @@ std::string utf8_from_wstring(const std::wstring &string)
//-------------------------------------------------
// internal_normalize_unicode - uses utf8proc to
-// normalize unicode
+// normalize unicode
//-------------------------------------------------
static std::string internal_normalize_unicode(const char *s, size_t length, unicode_normalization_form normalization_form, bool null_terminated)
@@ -437,7 +437,7 @@ static std::string internal_normalize_unicode(const char *s, size_t length, unic
//-------------------------------------------------
// normalize_unicode - uses utf8proc to normalize
-// unicode
+// unicode
//-------------------------------------------------
std::string normalize_unicode(const std::string &s, unicode_normalization_form normalization_form)
@@ -448,7 +448,7 @@ std::string normalize_unicode(const std::string &s, unicode_normalization_form n
//-------------------------------------------------
// normalize_unicode - uses utf8proc to normalize
-// unicode
+// unicode
//-------------------------------------------------
std::string normalize_unicode(const char *s, unicode_normalization_form normalization_form)
@@ -459,7 +459,7 @@ std::string normalize_unicode(const char *s, unicode_normalization_form normaliz
//-------------------------------------------------
// normalize_unicode - uses utf8proc to normalize
-// unicode
+// unicode
//-------------------------------------------------
std::string normalize_unicode(const char *s, size_t length, unicode_normalization_form normalization_form)