diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/formats/p2000t_cas.cpp | 321 | ||||
-rw-r--r-- | src/lib/formats/p2000t_cas.h | 19 | ||||
-rw-r--r-- | src/lib/netlist/analog/nld_generic_models.h | 1 | ||||
-rw-r--r-- | src/lib/netlist/core/setup.h | 19 | ||||
-rw-r--r-- | src/lib/netlist/devices/net_lib.h | 2 | ||||
-rwxr-xr-x | src/lib/netlist/generated/nlm_modules_lib.cpp | 4 | ||||
-rw-r--r-- | src/lib/netlist/generated/static_solvers.cpp | 8 | ||||
-rw-r--r-- | src/lib/netlist/macro/modules/nlmod_ICL8038_DIP.cpp | 61 | ||||
-rw-r--r-- | src/lib/netlist/macro/modules/nlmod_NE556_DIP.cpp | 24 | ||||
-rw-r--r-- | src/lib/netlist/macro/nlm_base_lib.cpp | 21 | ||||
-rw-r--r-- | src/lib/netlist/nl_base.cpp | 4 | ||||
-rw-r--r-- | src/lib/netlist/nl_parser.cpp | 22 | ||||
-rw-r--r-- | src/lib/netlist/nl_parser.h | 23 | ||||
-rw-r--r-- | src/lib/netlist/nl_setup.cpp | 24 | ||||
-rw-r--r-- | src/lib/netlist/nl_setup.h | 3 | ||||
-rw-r--r-- | src/lib/netlist/nltypes.h | 16 | ||||
-rw-r--r-- | src/lib/netlist/plib/pexception.h | 4 | ||||
-rw-r--r-- | src/lib/netlist/plib/ptokenizer.h | 46 | ||||
-rw-r--r-- | src/lib/netlist/plib/ptypes.h | 24 | ||||
-rw-r--r-- | src/lib/netlist/prg/nltool.cpp | 4 | ||||
-rw-r--r-- | src/lib/netlist/solver/nld_solver.cpp | 2 |
21 files changed, 570 insertions, 82 deletions
diff --git a/src/lib/formats/p2000t_cas.cpp b/src/lib/formats/p2000t_cas.cpp new file mode 100644 index 00000000000..e3351dc99dc --- /dev/null +++ b/src/lib/formats/p2000t_cas.cpp @@ -0,0 +1,321 @@ +// license:BSD-3-Clause +// copyright-holders:Curt Coder + +#include <cassert> + +#include "cassimg.h" +#include "p2000t_cas.h" +#include <ostream> + +// This code will reproduce the timing of a P2000 mini cassette tape. +constexpr double P2000_CLOCK_PERIOD = 0.000084; +constexpr double P2000_BOT_GAP = 1; +constexpr double P2000_BOB_GAP = 0.515; +constexpr double P2000_MARK_GAP = 0.085; +constexpr double P2000_END_GAP = 0.155; +constexpr double P2000_EOT_GAP = 1.8; +constexpr int P2000_HIGH = 0x7FFFFFFF; +constexpr int P2000_LOW = -1 * 0x7FFFFFFF; + + +#define CHR(x) \ + err = (x); \ + if (err != cassette_image::error::SUCCESS) \ + return err; + +/* +Here's a description on how the P2000t stores data on tape. + +## Tape Format + +Each track (or side) of a cassette is divided into 40 block of information. A +file may comprise between 1 and 40 blocks, depending on its length. + +## Blocks, Gaps, Marks and Records + +At the start of the tape is an area of clear (erased) tape, the BOT (beginning +of tape) gap; to read pas this gap takes approximately 1 second. After this, the +first block starts, followed directly by the second, third and so on. After the +last block on the track comes the EOT (end of tape) gap; if all 40 blocks on the +tracks are used, this area of erased tape has a length equivalent to 1.8 seconds +of reading time. + + | BOT | BLOCK 1 | BLOCK 2 | BLOCK ... | EOT | + +### BLOCK + +Each tape block is made up of five sections of tape: + +| START GAP | MARK | MARK GAP | DATA RECORD | END GAP | + +- Start gap: A section of erased tape separating the start of one block from the + end of the previous block. This takes approx. 515ms to read over. +- Mark: Four bytes of recorded information (described below) +- Mark Gap: A section of erased tape separating the mark from the data record; + length about 85ms. +- Data Record: 1056 bytes of recorded data (described below) +- End Gap: A section of erased tape of around 155 ms. + +### MARK + +The mark is made up of four bytes with the following bit patterns: + + - preamble syncronization pattern (0xAA) + - 0000 0000 (0x00) + - 0000 0000 (0x00) + - postamble syncronization pattern (0xAA) + +The function of the synchronisation byte is to make sure the RDC clock is set +properly. + +### DATA RECORD + +The data record contains the information which has been written onto the tape. +It compromises five sections: + +| sync byte | header | data | check sum | post sync | + +- sync byte: Preamble synchronisation pattern 0xAA +- header: 32 bytes which specify the contents and type of the data section. (See below) +- data section: 1024 bytes of information. +- checksum: 2 bytes that contain checksum +- post sync: 0xAA + +### HEADER + +See the struct declaration below for details on what is contained. + +### DATA + +The data section consists of 1024 bytes written in serial form, least +significant byte first. + +### Checksum + +The checksum is only calculated for the header and data section. The algorithm +is not documented, an implementation can be found below. +*/ + +// Specifies the type of data stored in the tape block +enum P2000_File_Type : uint8_t +{ + Basic = 'B', + Program = 'P', + Viewdata = 'V', + WordProcessing = 'W', + Other = 'O', +}; + +// Represents the internal code for data, differrent codes are used in different countries +// only relevant when P2000_File_Type is Program. +enum P2000_Data_Type : uint8_t +{ + German = 'D', + Swedish = 'S', + Dutch_English = 'U', +}; + + +// This is the 32 byte header definition used by the P2000, it is mainly +// here for documentation. +struct P2000T_Header +{ + // Starting address in ram where data should go. This address is supplied by + // the application program when calling the monitor cassette routine to write + // the data on cassette in the first place. + uint16_t data_transfer_address; + // Total # of bytes which make up the file (can be spread over many blocks). + // The monitor uses this to determine how many blocks to read. + uint16_t file_length; + // # bytes in this record that are actually used. For example if this is 256 + // only 256 bytes will be loaded in ram + uint16_t data_section_length; + // The eight character file name identifies the file to which the record + // belongs; it will be the same in all records making up the file. Each record + // except the first is considered an extension. + char file_name[8]; + // Addition file extension. + char ext[3]; + // This file type specifies the type of data stored. + P2000_File_Type file_type; + // Code and region information. + P2000_Data_Type data_code; + // Start address where program should start. (if type = Program) + uint16_t start_addr; + // Address in ram where the program should load (if type = Program) + uint16_t load_addr; + // Unused. + char reserved[8]; + // Record number (i.e. which block) + uint8_t rec_nr; +}; + +std::ostream &operator<<(std::ostream &os, P2000T_Header const &hdr) +{ + return os << "File: " << std::string(hdr.file_name, 8) << '.' + << std::string(hdr.ext, 3) << " " << hdr.file_length; +} + +static cassette_image::error p2000t_cas_identify(cassette_image *cass, struct CassetteOptions *opts) +{ + opts->bits_per_sample = 32; + opts->channels = 1; + opts->sample_frequency = 44100; + return cassette_image::error::SUCCESS; +} + +uint16_t rotr16a(uint16_t x, uint16_t n) +{ + return (x >> n) | (x << (16 - n)); +} + +void update_chksum(uint16_t *de, bool bit) +{ + // Reverse engineered from monitor.rom + // code is at: [0x07ac, 0x07c5] + uint8_t e = *de & 0xff; + uint8_t d = (*de >> 8) & 0xff; + e = e ^ (bit ? 1 : 0); + if (e & 0x01) + { + e = e ^ 2; + d = d ^ 0x40; + } + else + { + d = d ^ 0x00; + } + *de = rotr16a((d << 8) | e, 1); +} + +/* + A transition on a clock boundary from low to high is a 1. + A transition on a clock boundary from high to low is a 0 + An intermediate transition halfway between the clock boundary + can occur when there are consecutive 0s or 1s. See the example + below where the clock is marked by a | + + + 1 0 1 1 0 0 + RDA: _|----|____|--__|----|__--|__-- + RDC: _|-___|-___|-___|-___|-___|-___ + ^ ^ + |-- clock signal |-- intermediate transition. + + This signal can be written by a simple algorithm where the first bit + is always false (transition to low, half clock). Now only one bit is needed + to determine what the next partial clock should look like. + + This works because we are always guaranteed that a block starts with 0xAA, + and hence will ALWAYS find a signal like this on tape: _-- (low, high, high) + after a gap. This is guaranteed when the tape is moving forward as well as + backwards. +*/ +cassette_image::error p2000t_put_bit(cassette_image *cass, double *time_index, bool bit) +{ + const int channel = 0; + cassette_image::error err = cassette_image::error::SUCCESS; + CHR(cassette_put_sample(cass, channel, *time_index, P2000_CLOCK_PERIOD, bit ? P2000_HIGH : P2000_LOW)); + *time_index += P2000_CLOCK_PERIOD; + + CHR(cassette_put_sample(cass, channel, *time_index, P2000_CLOCK_PERIOD, bit ? P2000_LOW : P2000_HIGH)); + *time_index += P2000_CLOCK_PERIOD; + return err; +} + +// Store byte of data, updating the checksum +cassette_image::error p2000t_put_byte(cassette_image *cass, double *time_index, uint16_t *chksum, uint8_t byte) +{ + cassette_image::error err = cassette_image::error::SUCCESS; + for (int i = 0; i < 8 && err == cassette_image::error::SUCCESS; i++) + { + update_chksum(chksum, util::BIT(byte, i)); + CHR(p2000t_put_bit(cass, time_index, util::BIT(byte, i))); + } + return err; +} + +// Store a sequence of bytes, updating the checksum +cassette_image::error p2000t_put_bytes(cassette_image *cass, double *time_index, uint16_t *chksum, const uint8_t *bytes, const uint16_t cByte) +{ + cassette_image::error err = cassette_image::error::SUCCESS; + for (int i = 0; i < cByte && err == cassette_image::error::SUCCESS; i++) + { + CHR(p2000t_put_byte(cass, time_index, chksum, bytes[i])); + } + return err; +} + +// Insert time seconds of silence. +cassette_image::error p2000t_silence(cassette_image *cassette, +double *time_index, +double time) +{ + auto err = cassette_put_sample(cassette, 0, *time_index, time, 0); + *time_index += time; + return err; +} + +static cassette_image::error p2000t_cas_load(cassette_image *cassette) +{ + cassette_image::error err = cassette_image::error::SUCCESS; + uint64_t image_size = cassette_image_size(cassette); + constexpr int CAS_BLOCK = 1280; + + /* + The cas format is pretty simple. it consists of a sequence of blocks, + where a block consists of the following: + + [0-256] P2000 memory address 0x6000 - 0x6100 + .... Nonsense (keyboard status etc.) + 0x30 P200T_Header + 0x50 + ... Nonsense.. + [0-1024] Data block + + This means that one block gets stored in 1280 bytes. + */ + if (image_size % CAS_BLOCK != 0) + { + return cassette_image::error::INVALID_IMAGE; + } + + uint8_t block[CAS_BLOCK]; + constexpr uint8_t BLOCK_MARK[4] = { 0xAA, 0x00, 0x00, 0xAA }; + auto blocks = image_size / CAS_BLOCK; + double time_idx = 0; + + // Beginning of tape marker + CHR(p2000t_silence(cassette, &time_idx, P2000_BOT_GAP)); + for (int i = 0; i < blocks; i++) + { + uint16_t crc = 0, unused = 0; + cassette_image_read(cassette, &block, CAS_BLOCK * i, CAS_BLOCK); + + // Insert sync header.. 0xAA, 0x00, 0x00, 0xAA + CHR(p2000t_silence(cassette, &time_idx, P2000_BOB_GAP)); + CHR(p2000t_put_bytes(cassette, &time_idx, &unused, BLOCK_MARK, ARRAY_LENGTH(BLOCK_MARK))); + CHR(p2000t_silence(cassette, &time_idx, P2000_MARK_GAP)); + + // Insert data block + CHR(p2000t_put_byte(cassette, &time_idx, &unused, 0xAA)); + CHR(p2000t_put_bytes(cassette, &time_idx, &crc, block + 0x30, 32)); + CHR(p2000t_put_bytes(cassette, &time_idx, &crc, block + 256, 1024)); + CHR(p2000t_put_bytes(cassette, &time_idx, &unused, ( uint8_t * )&crc, 2)); + CHR(p2000t_put_byte(cassette, &time_idx, &unused, 0xAA)); + + // Block finished. + CHR(p2000t_silence(cassette, &time_idx, P2000_END_GAP)); + } + + // End of tape marker + return p2000t_silence(cassette, &time_idx, P2000_EOT_GAP); +} + +static const struct CassetteFormat p2000t_cas = { + "cas", p2000t_cas_identify, p2000t_cas_load, nullptr /* no save */ +}; + +CASSETTE_FORMATLIST_START(p2000t_cassette_formats) +CASSETTE_FORMAT(p2000t_cas) +CASSETTE_FORMATLIST_END diff --git a/src/lib/formats/p2000t_cas.h b/src/lib/formats/p2000t_cas.h new file mode 100644 index 00000000000..6d63e314a33 --- /dev/null +++ b/src/lib/formats/p2000t_cas.h @@ -0,0 +1,19 @@ +// license:BSD-3-Clause +// copyright-holders:Erwin Jansen +/********************************************************************* + + p2000t_cas.h + + Format code for P2000t .cas cassette files. + +*********************************************************************/ +#ifndef MAME_FORMATS_P2000T_CAS_H +#define MAME_FORMATS_P2000T_CAS_H + +#pragma once + +#include "cassimg.h" + +CASSETTE_FORMATLIST_EXTERN(p2000t_cassette_formats); + +#endif // MAME_FORMATS_P2000T_CAS_H diff --git a/src/lib/netlist/analog/nld_generic_models.h b/src/lib/netlist/analog/nld_generic_models.h index 781dc2a16bb..bb8adc466eb 100644 --- a/src/lib/netlist/analog/nld_generic_models.h +++ b/src/lib/netlist/analog/nld_generic_models.h @@ -9,7 +9,6 @@ /// #include "nl_base.h" -//#include "../nl_setup.h" // // Set to 0 to use a linearized diode model in the range exceeding diff --git a/src/lib/netlist/core/setup.h b/src/lib/netlist/core/setup.h index 61ab79de545..8b8a49dbc34 100644 --- a/src/lib/netlist/core/setup.h +++ b/src/lib/netlist/core/setup.h @@ -340,25 +340,6 @@ namespace netlist pstring m_setup_func_name; }; - class source_token_t : public source_netlist_t - { - public: - source_token_t(const pstring &name, const parser_t::token_store &store) - : m_store(store) - , m_name(name) - { - } - - bool parse(nlparse_t &setup, const pstring &name) override; - - protected: - plib::istream_uptr stream(const pstring &name) override; - - private: - parser_t::token_store m_store; - pstring m_name; - }; - } // namespace netlist diff --git a/src/lib/netlist/devices/net_lib.h b/src/lib/netlist/devices/net_lib.h index db3f9c1519d..1a8b72fcd5a 100644 --- a/src/lib/netlist/devices/net_lib.h +++ b/src/lib/netlist/devices/net_lib.h @@ -28,8 +28,6 @@ #define IND_P(ind) ((ind) * 1e-12) #endif -NETLIST_EXTERNAL(base_lib) - #include "../generated/nld_devinc.h" diff --git a/src/lib/netlist/generated/nlm_modules_lib.cpp b/src/lib/netlist/generated/nlm_modules_lib.cpp index d9fe63979d9..7f91075ac40 100755 --- a/src/lib/netlist/generated/nlm_modules_lib.cpp +++ b/src/lib/netlist/generated/nlm_modules_lib.cpp @@ -1,12 +1,14 @@ // license:CC0 // copyright-holders:Couriersud -// File programmatically created Sat Sep 12 14:42:49 2020 +// File programmatically created Sun Sep 13 20:49:39 2020 #include "devices/net_lib.h" NETLIST_START(modules_lib) + EXTERNAL_LIB_ENTRY(ICL8038_DIP) + EXTERNAL_LIB_ENTRY(NE556_DIP) EXTERNAL_LIB_ENTRY(RTEST) NETLIST_END() diff --git a/src/lib/netlist/generated/static_solvers.cpp b/src/lib/netlist/generated/static_solvers.cpp index 8c3173b98d2..367af35bbb9 100644 --- a/src/lib/netlist/generated/static_solvers.cpp +++ b/src/lib/netlist/generated/static_solvers.cpp @@ -1,5 +1,7 @@ #include "plib/pdynlib.h" +#if !defined(__EMSCRIPTEN__) + // elim static void nl_gcr_11c2ae166b240b6e_10_double_double(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV) @@ -72411,8 +72413,12 @@ static void nl_gcr_feae15b80dd73620_7_double_double(double * __restrict V, const V[0] = (RHS0 - tmp0) / m_A0; } +#endif + extern const plib::dynlib_static_sym nl_static_solver_syms[]; const plib::dynlib_static_sym nl_static_solver_syms[] = { +#if !defined(__EMSCRIPTEN__) + // elim {"nl_gcr_11c2ae166b240b6e_10_double_double", reinterpret_cast<void *>(&nl_gcr_11c2ae166b240b6e_10_double_double)}, // tankbatt @@ -72809,5 +72815,7 @@ const plib::dynlib_static_sym nl_static_solver_syms[] = { {"nl_gcr_fd2796828f1ebd00_36_double_double", reinterpret_cast<void *>(&nl_gcr_fd2796828f1ebd00_36_double_double)}, // starfire {"nl_gcr_feae15b80dd73620_7_double_double", reinterpret_cast<void *>(&nl_gcr_feae15b80dd73620_7_double_double)}, +#endif + {"", nullptr} }; diff --git a/src/lib/netlist/macro/modules/nlmod_ICL8038_DIP.cpp b/src/lib/netlist/macro/modules/nlmod_ICL8038_DIP.cpp new file mode 100644 index 00000000000..05a4d300099 --- /dev/null +++ b/src/lib/netlist/macro/modules/nlmod_ICL8038_DIP.cpp @@ -0,0 +1,61 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz + +#include "devices/net_lib.h" + +// +// ICL8038 is broadly similar to a 566 VCO, and can be simulated partially as such. +// + +NETLIST_START(ICL8038_DIP) + VCVS(VI, 1) + CCCS(CI1, -1) + CCCS(CI2, 2) + SYS_COMPD(COMP) + SYS_DSW2(SW) + VCVS(VO, 1) + RES(R_SHUNT, RES_R(50)) + + PARAM(VO.RO, 50) + PARAM(COMP.MODEL, "FAMILY(TYPE=CUSTOM IVL=0.16 IVH=0.4 OVL=0.01 OVH=0.01 ORL=50 ORH=50)") + PARAM(SW.GOFF, 0) // This has to be zero to block current sources + + NET_C(VI.OP, CI1.IN, CI2.IN) + NET_C(CI1.OP, VO.IP) + NET_C(COMP.Q, SW.I) + NET_C(CI2.OP, SW.2) + NET_C(COMP.VCC, R_SHUNT.1) + NET_C(SW.1, R_SHUNT.2) + NET_C(SW.3, VO.IP) + NET_C(VO.OP, COMP.IN) + + // Avoid singular Matrix due to G=0 switch + RES(RX1, 1e10) + RES(RX2, 1e10) + NET_C(RX1.1, SW.1) + NET_C(RX2.1, SW.3) + + NET_C(COMP.GND, RX1.2, RX2.2) + + RES(R1, 5000) + RES(R2, 5000) + RES(R3, 5000) + + // Square output wave + VCVS(V_SQR, 1) + NET_C(COMP.Q, V_SQR.IP) + + NET_C(COMP.GND, SW.GND, VI.ON, VI.IN, CI1.ON, CI2.ON, VO.IN, VO.ON, R2.2, V_SQR.IN, V_SQR.ON) + NET_C(COMP.VCC, SW.VCC, R1.2) + NET_C(COMP.IP, R1.1, R2.1, R3.1) + NET_C(COMP.Q, R3.2) + + ALIAS(11, VI.ON) // GND + ALIAS(9, V_SQR.OP) // Square out + ALIAS(3, VO.OP) // Triag out + ALIAS(8, VI.IP) // VC + ALIAS(4, CI1.IP) // R1 + ALIAS(5, CI2.IP) // R2 + ALIAS(10, VO.IP) // C1 + ALIAS(6, COMP.VCC) // V+ +NETLIST_END() diff --git a/src/lib/netlist/macro/modules/nlmod_NE556_DIP.cpp b/src/lib/netlist/macro/modules/nlmod_NE556_DIP.cpp new file mode 100644 index 00000000000..7f278a18b6d --- /dev/null +++ b/src/lib/netlist/macro/modules/nlmod_NE556_DIP.cpp @@ -0,0 +1,24 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +// + +#include "devices/net_lib.h" + +NETLIST_START(NE556_DIP) + NE555(A) + NE555(B) + + NET_C(A.GND, B.GND) + NET_C(A.VCC, B.VCC) + + DIPPINS( /* +--------------+ */ + A.DISCH, /* 1DISCH |1 ++ 14| VCC */ A.VCC, + A.THRESH, /* 1THRES |2 13| 2DISCH */ B.DISCH, + A.CONT, /* 1CONT |3 12| 2THRES */ B.THRESH, + A.RESET, /* 1RESET |4 NE556 11| 2CONT */ B.CONT, + A.OUT, /* 1OUT |5 10| 2RESET */ B.RESET, + A.TRIG, /* 1TRIG |6 9| 2OUT */ B.OUT, + A.GND, /* GND |7 8| 2TRIG */ B.TRIG + /* +--------------+ */ + ) +NETLIST_END() diff --git a/src/lib/netlist/macro/nlm_base_lib.cpp b/src/lib/netlist/macro/nlm_base_lib.cpp index c5f4c7c695b..b9c4165a46b 100644 --- a/src/lib/netlist/macro/nlm_base_lib.cpp +++ b/src/lib/netlist/macro/nlm_base_lib.cpp @@ -13,6 +13,7 @@ static NETLIST_START(diode_models) // FIXME: 1N916 currently only a copy of 1N914! NET_MODEL("1N916 D(Is=2.52n Rs=.568 N=1.752 Cjo=4p M=.4 tt=20n Iave=200m Vpk=75 mfg=OnSemi type=silicon)") NET_MODEL("1N4001 D(Is=14.11n N=1.984 Rs=33.89m Ikf=94.81 Xti=3 Eg=1.11 Cjo=25.89p M=.44 Vj=.3245 Fc=.5 Bv=75 Ibv=10u Tt=5.7u Iave=1 Vpk=50 mfg=GI type=silicon)") + NET_MODEL("1N4002 D(IS=65.4p RS=42.2m BV=100 IBV=5.00u CJO=14.8p M=0.333 N=1.36 TT=2.88u)") NET_MODEL("1N4148 D(Is=2.52n Rs=.568 N=1.752 Cjo=4p M=.4 tt=20n Iave=200m Vpk=75 mfg=OnSemi type=silicon)") NET_MODEL("1N4154 D(Is=0.1n Rs=4 N=1.67 Cjo=2p M=.333 tt=3n Iave=150m Vpk=35 Bv=60 Ibv=0.1p mfg=Vishay type=silicon)") NET_MODEL("1N4454 D(Is=168.1e-21 Rs=.1 N=1 Cjo=2p M=.333 tt=5.771n Iave=400m Vpk=35 Bv=75 Ibv=100u mfg=OnSemi type=silicon)") @@ -25,6 +26,15 @@ static NETLIST_START(diode_models) NET_MODEL("LedBlue D(IS=93.2p RS=42M N=7.47 BV=5 IBV=10U CJO=2.97P VJ=.75 M=.333 TT=4.32U Iave=40m Vpk=5 type=LED)") NET_MODEL("LedWhite D(Is=0.27n Rs=5.65 N=6.79 Cjo=42p Iave=30m Vpk=5 type=LED)") + // Zdiodes ... + + // not really found anywhere, just took the 5239 and changed the + // breakdown voltage to 5.1 according to the datasheet + NET_MODEL("1N5231 D(BV=5.1 IBV=0.020 NBV=1)") + NET_MODEL("1N5236B D(BV=7.5 IS=27.5p RS=33.8 N=1.10 CJO=58.2p VJ=0.750 M=0.330 TT=50.1n)") + NET_MODEL("1N5240 D(BV=10 IS=14.4p RS=32.0 N=1.10 CJO=24.1p VJ=0.750 M=0.330 TT=50.1n)") + NET_MODEL("1N5240B D(BV=10 IS=14.4p RS=32.0 N=1.10 CJO=24.1p VJ=0.750 M=0.330 TT=50.1n)") + NETLIST_END() /* ---------------------------------------------------------------------------- @@ -58,13 +68,24 @@ static NETLIST_START(bjt_models) NET_MODEL("2N3644 PNP(IS=650.6E-18 ISE=54.81E-15 ISC=0 XTI=3 BF=231.7 BR=3.563 IKF=1.079 IKR=0 XTB=1.5 VAF=115.7 VAR=35 VJE=0.65 VJC=0.65 RE=0.15 RC=0.715 RB=10 CJE=19.82E-12 CJC=14.76E-12 XCJC=0.75 FC=0.5 NF=1 NR=1 NE=1.829 NC=2 MJE=0.3357 MJC=0.5383 TF=603.7E-12 TR=111.3E-9 ITF=0.65 VTF=5 XTF=1.7 EG=1.11 KF=0 AF=1 VCEO=60 ICRATING=500m MFG=NSC)") NET_MODEL("2N3702 PNP(Is=650.6E-18 Xti=3 Eg=1.11 Vaf=115.7 Bf=133.8 Ne=1.832 Ise=97.16f Ikf=1.081 Xtb=1.5 Br=3.73 Nc=2 Isc=0 Ikr=0 Rc=.715 Cjc=14.76p Mjc=.5383 Vjc=.75 Fc=.5 Cje=19.82p Mje=.3357 Vje=.75 Tr=114.1n Tf=761.3p Itf=.65 Vtf=5 Xtf=1.7 Rb=10 mfg=National)") NET_MODEL("2N3704 NPN(IS=26.03f VAF=90.7 Bf=736.1K IKF=.1983 XTB=1.5 BR=1.024 CJC=11.01p CJE=24.07p RB=10 RC=.5 RE=.5 TR=233.8n TF=1.03n ITF=0 VTF=0 XTF=0 mfg=Motorola)") + // SPICE model parameters taken from Fairchild Semiconductor datasheet NET_MODEL("2N3904 NPN(IS=1E-14 VAF=100 Bf=300 IKF=0.4 XTB=1.5 BR=4 CJC=4E-12 CJE=8E-12 RB=20 RC=0.1 RE=0.1 TR=250E-9 TF=350E-12 ITF=1 VTF=2 XTF=3 Vceo=40 Icrating=200m mfg=Philips)") + // SPICE model parameters taken from Fairchild Semiconductor datasheet + NET_MODEL("2N3906 PNP(Is=1.41f Xti=3 Eg=1.11 Vaf=18.7 Bf=180.7 Ne=1.5 Ise=0 Ikf=80m Xtb=1.5 Br=4.977 Nc=2 Isc=0 Ikr=0 Rc=2.5 Cjc=9.728p Mjc=.5776 Vjc=.75 Fc=.5 Cje=8.063p Mje=.3677 Vje=.75 Tr=33.42n Tf=179.3p Itf=.4 Vtf=4 Xtf=6 Rb=10)") // 2N5190 = BC817-25 NET_MODEL("2N5190 NPN(IS=9.198E-14 NF=1.003 ISE=4.468E-16 NE=1.65 BF=338.8 IKF=0.4913 VAF=107.9 NR=1.002 ISC=5.109E-15 NC=1.071 BR=29.48 IKR=0.193 VAR=25 RB=1 IRB=1000 RBM=1 RE=0.2126 RC=0.143 XTB=0 EG=1.11 XTI=3 CJE=3.825E-11 VJE=0.7004 MJE=0.364 TF=5.229E-10 XTF=219.7 VTF=3.502 ITF=7.257 PTF=0 CJC=1.27E-11 VJC=0.4431 MJC=0.3983 XCJC=0.4555 TR=7E-11 CJS=0 VJS=0.75 MJS=0.333 FC=0.905 Vceo=45 Icrating=500m mfg=Philips)") NET_MODEL("2N4401 NPN(IS=26.03f XTI=3 EG=1.11 VAF=90.7 BF=4.292K NE=1.244 ISE=26.03f IKF=0.2061 XTB=1.5 BR=1.01 NC=2 ISC=0 IKR=0 RC=0.5 CJC=11.01p MJC=0.3763 VJC=0.75 FC=0.5 CJE=24.07p MJE=0.3641 VJE=0.75 TR=233.7n TF=466.5p ITF=0 VTF=0 XTF=0 RB=10 VCEO=40)") + NET_MODEL("2N4403 PNP(Is=650.6E-18 Xti=3 Eg=1.11 Vaf=115.7 Bf=216.2 Ne=1.829 Ise=58.72f Ikf=1.079 Xtb=1.5 Br=3.578 Nc=2 Isc=0 Ikr=0 Rc=.715 Cjc=14.76p Mjc=.5383 Vjc=.75 Fc=.5 Cje=19.82p Mje=.3357 Vje=.75 Tr=111.6n Tf=603.7p Itf=.65 Vtf=5 Xtf=1.7 Rb=10)") NET_MODEL("2N4124 NPN(IS=6.734f XTI=3 EG=1.11 VAF=74.03 BF=495 NE=1.28 ISE=6.734f IKF=69.35m XTB=1.5 BR=0.7214 NC=2 ISC=0 IKR=0 RC=1 CJC=3.638p MJC=0.3085 VJC=0.75 FC=0.5 CJE=4.493p MJE=0.2593 VJE=0.75 TR=238.3n TF=301.3p ITF=.4 VTF=4 XTF=2 RB=10 VCEO=25)") NET_MODEL("2N4126 PNP(IS=1.41f XTI=3 EG=1.11 VAF=18.7 BF=203.7 NE=1.5 ISE=0 IKF=80m XTB=1.5 BR=4.924 NC=2 ISC=0 IKR=0 RC=2.5 CJC=9.728p MJC=0.5776 VJC=0.75 FC=0.5 CJE=8.063p MJE=0.3677 VJE=0.75 TR=33.23n TF=179.3p ITF=.4 VTF=4 XTF=6 RB=10 VCEO=25)") + // SPICE model parameters taken from http://ltwiki.org/files/LTspiceIV/Vendor%20List/Fairchild/2N/index.html + NET_MODEL("2N5210 NPN(Is=5.911f Xti=3 Eg=1.11 Vaf=62.37 Bf=809.9 Ne=1.358 Ise=5.911f Ikf=14.26m Xtb=1.5 Br=1.287 Nc=2 Isc=0 Ikr=0 Rc=1.61 Cjc=4.017p Mjc=.3174 Vjc=.75 Fc=.5 Cje=4.973p Mje=.4146 Vje=.75 Tr=4.68n Tf=820.9p Itf=.35 Vtf=4 Xtf=7 Rb=10)") + // SPICE model parameters taken from https://www.onsemi.com/support/design-resources/models?rpn=2N6107 + NET_MODEL("2N6107 PNP(IS=7.62308e-14 BF=6692.56 NF=0.85 VAF=10 IKF=0.032192 ISE=2.07832e-13 NE=2.41828 BR=15.6629 NR=1.5 VAR=1.44572 IKR=0.32192 ISC=4.75e-16 NC=3.9375 RB=7.19824 IRB=0.1 RBM=0.1 RE=0.0001 RC=0.355458 XTB=0.1 XTI=2.97595 EG=1.206 CJE=1.84157e-10 VJE=0.99 MJE=0.347177 TF=6.63757e-09 XTF=1.50003 VTF=1.0001 ITF=1 CJC=1.06717e-10 VJC=0.942679 MJC=0.245405 XCJC=0.8 FC=0.533334 CJS=0 VJS=0.75 MJS=0.5 TR=1.32755e-07 PTF=0 KF=0 AF=1)") + // SPICE model parameters taken from https://www.onsemi.com/support/design-resources/models?rpn=2N6292 + NET_MODEL("2N6292 NPN(IS=9.3092e-13 BF=2021.8 NF=0.85 VAF=63.2399 IKF=1 ISE=1.92869e-13 NE=1.97024 BR=40.0703 NR=1.5 VAR=0.89955 IKR=10 ISC=4.92338e-16 NC=3.9992 RB=6.98677 IRB=0.1 RBM=0.1 RE=0.0001 RC=0.326141 XTB=0.1 XTI=2.86739 EG=1.206 CJE=1.84157e-10 VJE=0.99 MJE=0.347174 TF=6.73756e-09 XTF=1.49917 VTF=0.997395 ITF=0.998426 CJC=1.06717e-10 VJC=0.942694 MJC=0.245406 XCJC=0.8 FC=0.533405 CJS=0 VJS=0.75 MJS=0.5 TR=6.0671e-08 PTF=0 KF=0 AF=1)") + NET_MODEL("2SC945 NPN(IS=3.577E-14 BF=2.382E+02 NF=1.01 VAF=1.206E+02 IKF=3.332E-01 ISE=3.038E-16 NE=1.205 BR=1.289E+01 NR=1.015 VAR=1.533E+01 IKR=2.037E-01 ISC=3.972E-14 NC=1.115 RB=3.680E+01 IRB=1.004E-04 RBM=1 RE=8.338E-01 RC=1.557E+00 CJE=1.877E-11 VJE=7.211E-01 MJE=3.486E-01 TF=4.149E-10 XTF=1.000E+02 VTF=9.956 ITF=5.118E-01 PTF=0 CJC=6.876p VJC=3.645E-01 MJC=3.074E-01 TR=5.145E-08 XTB=1.5 EG=1.11 XTI=3 FC=0.5 Vceo=50 Icrating=100m MFG=NEC)") NET_MODEL("BC237B NPN(IS=1.8E-14 ISE=5.0E-14 ISC=1.72E-13 XTI=3 BF=400 BR=35.5 IKF=0.14 IKR=0.03 XTB=1.5 VAF=80 VAR=12.5 VJE=0.58 VJC=0.54 RE=0.6 RC=0.25 RB=0.56 CJE=13E-12 CJC=4E-12 XCJC=0.75 FC=0.5 NF=0.9955 NR=1.005 NE=1.46 NC=1.27 MJE=0.33 MJC=0.33 TF=0.64E-9 TR=50.72E-9 EG=1.11 KF=0 AF=1 VCEO=45 ICRATING=100M MFG=ZETEX)") diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp index a4510fe5765..d0a0e707aaf 100644 --- a/src/lib/netlist/nl_base.cpp +++ b/src/lib/netlist/nl_base.cpp @@ -16,10 +16,10 @@ #include "nl_errstr.h" -#include "devices/net_lib.h" - #include <limits> +NETLIST_EXTERNAL(base_lib) + namespace netlist { diff --git a/src/lib/netlist/nl_parser.cpp b/src/lib/netlist/nl_parser.cpp index 32a5c542a16..3e7ff32e804 100644 --- a/src/lib/netlist/nl_parser.cpp +++ b/src/lib/netlist/nl_parser.cpp @@ -561,4 +561,26 @@ pstring parser_t::stringify_expression(token_t &tok) return ret; } +// ---------------------------------------------------------------------------------------- +// source_token_t +// ---------------------------------------------------------------------------------------- + +bool source_token_t::parse(nlparse_t &setup, const pstring &name) +{ + if (name == m_name) + { + auto ret = setup.parse_tokens(m_store, name); + return ret; + } + + return false; +} + +plib::istream_uptr source_token_t::stream(const pstring &name) +{ + plib::unused_var(name); + return plib::istream_uptr(); +} + + } // namespace netlist diff --git a/src/lib/netlist/nl_parser.h b/src/lib/netlist/nl_parser.h index 077f1b10792..cbc757307d5 100644 --- a/src/lib/netlist/nl_parser.h +++ b/src/lib/netlist/nl_parser.h @@ -9,6 +9,7 @@ #define NL_PARSER_H_ #include "nltypes.h" // for setup_t +#include "core/setup.h" #include "plib/ptokenizer.h" #include <unordered_map> @@ -89,7 +90,27 @@ namespace netlist std::unordered_map<pstring, token_store> m_local; token_store *m_cur_local; -}; + }; + + class source_token_t : public source_netlist_t + { + public: + source_token_t(const pstring &name, const parser_t::token_store &store) + : m_store(store) + , m_name(name) + { + } + + bool parse(nlparse_t &setup, const pstring &name) override; + + protected: + plib::istream_uptr stream(const pstring &name) override; + + private: + parser_t::token_store m_store; + pstring m_name; + }; + } // namespace netlist diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp index b2ade9d48ce..9af1ec92d51 100644 --- a/src/lib/netlist/nl_setup.cpp +++ b/src/lib/netlist/nl_setup.cpp @@ -352,7 +352,7 @@ namespace netlist return false; } - bool nlparse_t::parse_tokens(const parser_t::token_store &tokens, const pstring &name) + bool nlparse_t::parse_tokens(const plib::detail::token_store &tokens, const pstring &name) { parser_t parser(*this); return parser.parse(tokens, name); @@ -1282,7 +1282,10 @@ void models_t::model_parse(const pstring &model_in, map_t &map) key = plib::ucase(model); auto i = m_models.find(key); if (i == m_models.end()) - throw nl_exception(MF_MODEL_NOT_FOUND("xx" + model)); + { + throw nl_exception(MF_MODEL_NOT_FOUND(pstring("xx") + model)); + } + model = i->second; } pstring xmodel = plib::left(model, pos); @@ -1759,22 +1762,5 @@ plib::istream_uptr source_proc_t::stream(const pstring &name) return plib::istream_uptr(); } -bool source_token_t::parse(nlparse_t &setup, const pstring &name) -{ - if (name == m_name) - { - auto ret = setup.parse_tokens(m_store, name); - return ret; - } - - return false; -} - -plib::istream_uptr source_token_t::stream(const pstring &name) -{ - plib::unused_var(name); - return plib::istream_uptr(); -} - } // namespace netlist diff --git a/src/lib/netlist/nl_setup.h b/src/lib/netlist/nl_setup.h index 7f6988f2951..fd9cb11afab 100644 --- a/src/lib/netlist/nl_setup.h +++ b/src/lib/netlist/nl_setup.h @@ -14,7 +14,6 @@ #include "plib/pstring.h" #include "nl_config.h" -#include "nl_parser.h" #include "nltypes.h" #include <initializer_list> @@ -229,7 +228,7 @@ namespace netlist // FIXME: used by source_t - need a different approach at some time bool parse_stream(plib::istream_uptr &&istrm, const pstring &name); - bool parse_tokens(const parser_t::token_store &tokens, const pstring &name); + bool parse_tokens(const plib::detail::token_store &tokens, const pstring &name); template <typename S, typename... Args> void add_include(Args&&... args) diff --git a/src/lib/netlist/nltypes.h b/src/lib/netlist/nltypes.h index 422a9ddfac4..5781619af1a 100644 --- a/src/lib/netlist/nltypes.h +++ b/src/lib/netlist/nltypes.h @@ -22,22 +22,6 @@ #include <memory> -// FIXME: Move to ptypes -namespace plib -{ - // FORWARD declarations - template <typename BASEARENA, std::size_t MINALIGN> - class mempool_arena; - - struct aligned_arena; - class dynlib_base; - - template<bool debug_enabled> - class plog_base; - - struct plog_level; -} // namespace plib - namespace netlist { // ----------------------------------------------------------------------------- diff --git a/src/lib/netlist/plib/pexception.h b/src/lib/netlist/plib/pexception.h index 2023fb91c38..709f8810b83 100644 --- a/src/lib/netlist/plib/pexception.h +++ b/src/lib/netlist/plib/pexception.h @@ -40,10 +40,10 @@ namespace plib { explicit pexception(const pstring &text); const pstring &text() const noexcept { return m_text; } - const char* what() const noexcept override { return putf8string(m_text).c_str(); } + const char* what() const noexcept override { return m_text.c_str(); } private: - pstring m_text; + putf8string m_text; }; class file_e : public plib::pexception diff --git a/src/lib/netlist/plib/ptokenizer.h b/src/lib/netlist/plib/ptokenizer.h index 717d3fcd550..9a194a542d5 100644 --- a/src/lib/netlist/plib/ptokenizer.h +++ b/src/lib/netlist/plib/ptokenizer.h @@ -19,22 +19,7 @@ namespace plib { - class ptokenizer - { - public: - explicit ptokenizer() // NOLINT(misc-forwarding-reference-overload, bugprone-forwarding-reference-overload) - : m_strm(nullptr) - , m_unget(0) - , m_string('"') - , m_support_line_markers(true) // FIXME - , m_token_queue(nullptr) - { - clear(); - } - - PCOPYASSIGNMOVE(ptokenizer, delete) - - virtual ~ptokenizer() = default; + namespace detail { PENUM(token_type, IDENTIFIER, @@ -109,7 +94,34 @@ namespace plib { pstring m_token; }; - using token_store = std::vector<token_t>; + class token_store : public std::vector<token_t> + { + using std::vector<token_t>::vector; + }; + + } // namespace detail + + class ptokenizer + { + public: + explicit ptokenizer() // NOLINT(misc-forwarding-reference-overload, bugprone-forwarding-reference-overload) + : m_strm(nullptr) + , m_unget(0) + , m_string('"') + , m_support_line_markers(true) // FIXME + , m_token_queue(nullptr) + { + clear(); + } + + PCOPYASSIGNMOVE(ptokenizer, delete) + + virtual ~ptokenizer() = default; + + using token_type = detail::token_type; + using token_id_t = detail::token_id_t; + using token_t = detail::token_t; + using token_store = detail::token_store; // tokenizer stuff follows ... diff --git a/src/lib/netlist/plib/ptypes.h b/src/lib/netlist/plib/ptypes.h index 5c5cb37695a..544b8ab0eff 100644 --- a/src/lib/netlist/plib/ptypes.h +++ b/src/lib/netlist/plib/ptypes.h @@ -39,6 +39,30 @@ #undef EMSCRIPTEN #endif +// ----------------------------------------------------------------------------- +// forward definitions +// ----------------------------------------------------------------------------- + +namespace plib +{ + template <typename BASEARENA, std::size_t MINALIGN> + class mempool_arena; + + struct aligned_arena; + class dynlib_base; + + template<bool debug_enabled> + class plog_base; + + struct plog_level; + + namespace detail + { + class token_store; + } // namespace detail + +} // namespace plib + namespace plib { //============================================================ diff --git a/src/lib/netlist/prg/nltool.cpp b/src/lib/netlist/prg/nltool.cpp index 27aa5b293c3..44b96bf0d6d 100644 --- a/src/lib/netlist/prg/nltool.cpp +++ b/src/lib/netlist/prg/nltool.cpp @@ -694,18 +694,22 @@ void tool_app_t::static_compile() throw netlist::nl_exception(netlist::MF_FILE_OPEN_ERROR(opt_out())); sout << "#include \"plib/pdynlib.h\"\n\n"; + sout << "#if !defined(__EMSCRIPTEN__)\n\n"; for (auto &e : map) { sout << "// " << putf8string(e.second.m_module) << "\n"; sout << putf8string(e.second.m_code); } + sout << "#endif\n\n"; sout << "extern const plib::dynlib_static_sym nl_static_solver_syms[];\n"; sout << "const plib::dynlib_static_sym nl_static_solver_syms[] = {\n"; + sout << "#if !defined(__EMSCRIPTEN__)\n\n"; for (auto &e : map) { sout << "// " << putf8string(e.second.m_module) << "\n"; sout << "\t{\"" << putf8string(e.first) << "\", reinterpret_cast<void *>(&" << putf8string(e.first) << ")},\n"; } + sout << "#endif\n\n"; sout << "{\"\", nullptr}\n"; sout << "};\n"; diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp index 92a4af61399..9ea31925b98 100644 --- a/src/lib/netlist/solver/nld_solver.cpp +++ b/src/lib/netlist/solver/nld_solver.cpp @@ -227,6 +227,7 @@ namespace devices std::size_t net_count = nets.size(); switch (net_count) { +#if !defined(__EMSCRIPTEN__) case 1: return plib::make_unique<solver::matrix_solver_direct1_t<FT>, device_arena>(*this, sname, nets, params); case 2: @@ -243,6 +244,7 @@ namespace devices return create_solver<FT, 7>(7, sname, params, nets); case 8: return create_solver<FT, 8>(8, sname, params, nets); +#endif default: log().info(MI_NO_SPECIFIC_SOLVER(net_count)); if (net_count <= 16) |