diff --git a/src/devices/machine/netlist.cpp b/src/devices/machine/netlist.cpp index b5e2ae547c9..48d81cacbdb 100644 --- a/src/devices/machine/netlist.cpp +++ b/src/devices/machine/netlist.cpp @@ -11,14 +11,11 @@ #include "emu.h" #include "netlist.h" -#include "netlist/nl_base.h" #include "netlist/nl_setup.h" #include "netlist/nl_factory.h" #include "netlist/nl_parser.h" #include "netlist/nl_interface.h" -#include "netlist/plib/palloc.h" -#include "netlist/plib/pmempool.h" #include "netlist/plib/pdynlib.h" #include "netlist/plib/pstonum.h" diff --git a/src/devices/video/fixfreq.cpp b/src/devices/video/fixfreq.cpp index 37fc6d3b44c..607289c92b0 100644 --- a/src/devices/video/fixfreq.cpp +++ b/src/devices/video/fixfreq.cpp @@ -2,24 +2,26 @@ // copyright-holders:Couriersud /*************************************************************************** - fixfreq.h + fixfreq.h - 2013-2021 Couriersud + 2013-2021 Couriersud - Fixed frequency monochrome monitor emulation + Fixed frequency monochrome monitor emulation - The driver is intended for drivers which provide an analog video signal. - VSYNC and HSYNC levels are used to create the bitmap. + The driver is intended for drivers which provide an analog video signal. + VSYNC and HSYNC levels are used to create the bitmap. ***************************************************************************/ +// emu.h must be first to be included #include "emu.h" + #include "fixfreq.h" #include "render.h" #include "ui/uimain.h" -#include +#include // for quick and dirty debugging #define VERBOSE 0 @@ -36,20 +38,24 @@ // -------------------------------------------------------------------------- // device type definition -DEFINE_DEVICE_TYPE(FIXFREQ, fixedfreq_device, "fixfreq", "Fixed-Frequency Monochrome Monitor") +DEFINE_DEVICE_TYPE(FIXFREQ, fixedfreq_device, "fixfreq", + "Fixed-Frequency Monochrome Monitor") // -------------------------------------------------------------------------- // Port adjuster support // -------------------------------------------------------------------------- -#define PORT_ADJUSTERX(_id, _name, _min, _max) \ - PORT_START(# _id) \ - configurer.field_alloc(IPT_ADJUSTER, (static_cast(owner).monitor_val(_id)), 0xffff, ("Monitor - " _name)); \ - PORT_MINMAX(_min, _max) \ - PORT_CHANGED_MEMBER(DEVICE_SELF, fixedfreq_device, port_changed, _id) \ +#define PORT_ADJUSTERX(_id, _name, _min, _max) \ + PORT_START(#_id) \ + configurer.field_alloc( \ + IPT_ADJUSTER, \ + (static_cast(owner).monitor_val(_id)), 0xffff, \ + ("Monitor - " _name)); \ + PORT_MINMAX(_min, _max) \ + PORT_CHANGED_MEMBER(DEVICE_SELF, fixedfreq_device, port_changed, _id) \ PORT_CONDITION("ENABLE", 0x01, EQUALS, 0x01) -#define IOPORT_ID(_id) ioport(# _id) +#define IOPORT_ID(_id) ioport(#_id) enum fixedfreq_tag_id_e { @@ -67,30 +73,36 @@ enum fixedfreq_tag_id_e SCANLINE_HEIGHT }; -void fixedfreq_monitor_state::update_sync_channel(const time_type &time, const double newval) +void fixedfreq_monitor_state::update_sync_channel(const time_type &time, + const double newval) { const time_type delta_time = time - m_last_sync_time; const int last_vsync = m_sig_vsync; const int last_comp = m_sig_composite; - m_vsync_filter += ((double) last_comp - m_vsync_filter) * (1.0 - exp(-delta_time * m_desc.vsync_filter_timeconst())); - m_sig_composite = (newval < m_desc.m_sync_threshold) ? 1 : 0 ; + m_vsync_filter += ((double)last_comp - m_vsync_filter) + * (1.0 + - exp(-delta_time * m_desc.vsync_filter_timeconst())); + m_sig_composite = (newval < m_desc.m_sync_threshold) ? 1 : 0; m_sig_vsync = (m_vsync_filter > m_desc.m_vsync_threshold) ? 1 : 0; if (!last_vsync && m_sig_vsync) { LOG("VSYNC UP %f %d\n", m_last_x, m_last_y); - const int has_fields = (m_desc.m_fieldcount > 1) ? 1: 0; + const int has_fields = (m_desc.m_fieldcount > 1) ? 1 : 0; - // FIXME: add modes: true interlaced, overlayed, false progressive (see popeye video) + // FIXME: add modes: true interlaced, overlayed, false progressive (see + // popeye video) if (has_fields) { - const auto avg_line_dur = (time - m_last_field_time) * m_desc.m_fieldcount / (m_last_y + 1); + const auto avg_line_dur = (time - m_last_field_time) + * m_desc.m_fieldcount / (m_last_y + 1); m_last_field_time = time; m_sig_field = avg_line_dur * 0.75 > m_last_line_duration; - LOG("%d %f %f %f\n", m_sig_field, m_last_line_duration, avg_line_dur, time); + LOG("%d %f %f %f\n", m_sig_field, m_last_line_duration, + avg_line_dur, time); } // notify the controlling device about the vsync and the field. @@ -108,12 +120,13 @@ void fixedfreq_monitor_state::update_sync_channel(const time_type &time, const d { if (m_sig_vsync) LOG("Hsync in vsync\n"); - //LOG("HSYNC up %d\n", m_last_x); - // FIXME: pixels > 0 filters some spurious hysnc on line 23/24 in breakout - // The hsync signal transition from high to low is 7 pixels too - // early, goes up again after 6.8 pix and down after 7.2 pix. - // Therefore we need to filter early low to high transitions - // and base hsync on the start of the hsync signal. + // LOG("HSYNC up %d\n", m_last_x); + // FIXME: pixels > 0 filters some spurious hysnc on line + // 23/24 in breakout + // The hsync signal transition from high to low is 7 pixels too + // early, goes up again after 6.8 pix and down after 7.2 pix. + // Therefore we need to filter early low to high transitions + // and base hsync on the start of the hsync signal. if (!m_sig_vsync && (m_last_x > 0)) { m_last_y += m_desc.m_fieldcount; @@ -122,13 +135,12 @@ void fixedfreq_monitor_state::update_sync_channel(const time_type &time, const d m_last_line_duration = time - m_last_hsync_time; m_last_hsync_time = time; - } } else if (last_comp && !m_sig_composite) { /* falling composite */ - //LOG("HSYNC down %f %d %f\n", time * 1e6, m_last_x, m_sync_signal); + // LOG("HSYNC down %f %d %f\n", time * 1e6, m_last_x, m_sync_signal); } m_last_sync_val = newval; m_last_sync_time = time; @@ -136,99 +148,109 @@ void fixedfreq_monitor_state::update_sync_channel(const time_type &time, const d void fixedfreq_monitor_state::update_bm(const time_type &time) { - const float pixels = (time - m_line_time) * (double) m_desc.monitor_clock(); - const int has_fields = (m_desc.m_fieldcount > 1) ? 1: 0; + const float pixels = (time - m_line_time) * (double)m_desc.monitor_clock(); + const int has_fields = (m_desc.m_fieldcount > 1) ? 1 : 0; const float fhscale(static_cast(m_desc.m_hscale)); - //uint32_t col(0xffff0000); // Mark sync areas - //if (m_last_sync >= m_desc.m_sync_threshold) - // col = m_col; + // uint32_t col(0xffff0000); // Mark sync areas + // if (m_last_sync >= m_desc.m_sync_threshold) + // col = m_col; if (!m_sig_vsync && !m_sig_composite) { - //uint32_t mask = m_sig_field ? 0xffffffff : 0xffff0000; - m_fragments.push_back({static_cast(m_last_y + m_sig_field * has_fields), - m_last_x * fhscale, pixels * fhscale, m_col}); // & mask}); + // uint32_t mask = m_sig_field ? 0xffffffff : 0xffff0000; + m_fragments.push_back( + {static_cast(m_last_y + m_sig_field * has_fields), + m_last_x * fhscale, pixels * fhscale, m_col}); // & mask}); } - //m_intf.plot_hline(m_last_x, m_last_y + m_sig_field * has_fields, pixels, col); + // m_intf.plot_hline(m_last_x, m_last_y + m_sig_field * has_fields, pixels, + // col); m_last_x = pixels; } -void fixedfreq_monitor_state::update_composite_monochrome(const time_type &time, const double data) +void fixedfreq_monitor_state::update_composite_monochrome(const time_type &time, + const double data) { update_bm(time); update_sync_channel(time, data); - //int colv = (int) ((data - m_desc.m_sync_threshold) * m_desc.m_gain * 255.0); - int colv = (int) ((data - 1.5) * m_desc.m_gain * 255.0); + //#int colv = (int) ((data - m_desc.m_sync_threshold) * m_desc.m_gain * 255.0); + int colv = (int)((data - 1.5) * m_desc.m_gain * 255.0); if (colv > 255) colv = 255; if (colv < 0) - //m_col = 0xffff0000; + // m_col = 0xffff0000; m_col = 0x0000000; else - m_col = 0xff000000 | (colv<<16) | (colv<<8) | colv; + m_col = 0xff000000 | (colv << 16) | (colv << 8) | colv; } -void fixedfreq_monitor_state::update_red(const time_type &time, const double data) +void fixedfreq_monitor_state::update_red(const time_type &time, + const double data) { update_bm(time); - int colv = (int) ((data - m_desc.m_sync_threshold) * m_desc.m_gain * 255.0); + int colv = (int)((data - m_desc.m_sync_threshold) * m_desc.m_gain * 255.0); if (colv > 255) colv = 255; if (colv < 0) colv = 0; - m_col = (m_col & 0xff00ffff) | (colv<<16); + m_col = (m_col & 0xff00ffff) | (colv << 16); } -void fixedfreq_monitor_state::update_green(const time_type &time, const double data) +void fixedfreq_monitor_state::update_green(const time_type &time, + const double data) { update_bm(time); - //update_sync_channel(ctime, data); + // update_sync_channel(ctime, data); - int colv = (int) ((data - m_desc.m_sync_threshold) * m_desc.m_gain * 255.0); + int colv = (int)((data - m_desc.m_sync_threshold) * m_desc.m_gain * 255.0); if (colv > 255) colv = 255; if (colv < 0) colv = 0; - m_col = (m_col & 0xffff00ff) | (colv<<8); + m_col = (m_col & 0xffff00ff) | (colv << 8); } -void fixedfreq_monitor_state::update_blue(const time_type &time, const double data) +void fixedfreq_monitor_state::update_blue(const time_type &time, + const double data) { update_bm(time); - //update_sync_channel(ctime, data); + // update_sync_channel(ctime, data); - int colv = (int) ((data - m_desc.m_sync_threshold) * m_desc.m_gain * 255.0); + int colv = (int)((data - m_desc.m_sync_threshold) * m_desc.m_gain * 255.0); if (colv > 255) colv = 255; if (colv < 0) colv = 0; m_col = (m_col & 0xffffff00) | colv; - } -void fixedfreq_monitor_state::update_sync(const time_type &time, const double data) +void fixedfreq_monitor_state::update_sync(const time_type &time, + const double data) { update_bm(time); update_sync_channel(time, data); } -fixedfreq_device::fixedfreq_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, type, tag, owner, clock), - device_video_interface(mconfig, *this, false), - m_enable(*this, "ENABLE"), - m_vector(*this, "VECTOR"), - m_scanline_height(1.0), - m_last_rt(0.0), - m_monitor(), - m_state(m_monitor, *this) +fixedfreq_device::fixedfreq_device(const machine_config &mconfig, + device_type type, const char *tag, + device_t *owner, uint32_t clock) +: device_t(mconfig, type, tag, owner, clock) +, device_video_interface(mconfig, *this, false) +, m_enable(*this, "ENABLE") +, m_vector(*this, "VECTOR") +, m_scanline_height(1.0) +, m_last_rt(0.0) +, m_monitor() +, m_state(m_monitor, *this) { } -fixedfreq_device::fixedfreq_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : fixedfreq_device(mconfig, FIXFREQ, tag, owner, clock) +fixedfreq_device::fixedfreq_device(const machine_config &mconfig, + const char *tag, device_t *owner, + uint32_t clock) +: fixedfreq_device(mconfig, FIXFREQ, tag, owner, clock) { } @@ -251,10 +273,11 @@ void fixedfreq_device::device_config_complete() // to specify the window size. if (!screen().refresh_attoseconds()) screen().set_raw(m_monitor.m_monitor_clock, m_monitor.htotal(), 0, - m_monitor.htotal(), m_monitor.vtotal(), 0, - m_monitor.vtotal()); + m_monitor.htotal(), m_monitor.vtotal(), 0, + m_monitor.vtotal()); if (!screen().has_screen_update()) - screen().set_screen_update(*this, FUNC(fixedfreq_device::screen_update)); + screen().set_screen_update(*this, + FUNC(fixedfreq_device::screen_update)); LOG("config complete\n"); } @@ -288,7 +311,7 @@ void fixedfreq_device::device_reset() { m_state.reset(); LOG("Reset\n"); - //ioport("YYY")->field(0xffff)->live().value = 20; + // ioport("YYY")->field(0xffff)->live().value = 20; #if 0 //IOPORT_ID(HVISIBLE)->field(~0)->set_value(m_monitor.m_hvisible); //IOPORT_ID(HVISIBLE)->update_defvalue(false); @@ -307,36 +330,39 @@ void fixedfreq_device::device_reset() void fixedfreq_device::device_post_load() { - //recompute_parameters(); + // recompute_parameters(); LOG("post load\n"); } static uint32_t nom_col(uint32_t col) { float r = ((col >> 16) & 0xff); - float g = ((col >> 8) & 0xff); - float b = ((col >> 0) & 0xff); + float g = ((col >> 8) & 0xff); + float b = ((col >> 0) & 0xff); - float m = std::max(r, std::max(g,b)); + float m = std::max(r, std::max(g, b)); if (m == 0.0f) return 0; - return (((uint32_t) m ) << 24) | (((uint32_t) (r/m*255.0f) ) << 16) - | (((uint32_t) (g/m*255.0f) ) << 8) | (((uint32_t) (b/m*255.0f) ) << 0); + return (((uint32_t)m) << 24) | (((uint32_t)(r / m * 255.0f)) << 16) + | (((uint32_t)(g / m * 255.0f)) << 8) + | (((uint32_t)(b / m * 255.0f)) << 0); } -static void draw_testpat(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +static void draw_testpat(screen_device &screen, bitmap_rgb32 &bitmap, + const rectangle &cliprect) { // Test pattern Grey scale const int stripes = 255; - //auto va(screen.visible_area()); + // auto va(screen.visible_area()); auto &va(cliprect); for (int i = 0; i < stripes; i++) { int l = va.left() + (i * va.width() / stripes); - int w = (va.left() + (i+1) * va.width() / stripes) - l; + int w = (va.left() + (i + 1) * va.width() / stripes) - l; int v = (255 * i) / stripes; - bitmap.plot_box(l, va.top()+20, w, va.height()/2-20, rgb_t(0xff, v, v, v)); + bitmap.plot_box(l, va.top() + 20, w, va.height() / 2 - 20, + rgb_t(0xff, v, v, v)); } int l(va.left() + va.width() / 4); @@ -353,14 +379,20 @@ static void draw_testpat(screen_device &screen, bitmap_rgb32 &bitmap, const rect bitmap.plot_box(l, t, w, h, rgb_t(0xff, 0xc3, 0xc3, 0xc3)); // 195 } -uint32_t fixedfreq_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +uint32_t +fixedfreq_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, + const rectangle &cliprect) { - //printf("%f\n", machine().time().as_double()); - //printf("%d %lu %f %f\n", m_state.m_sig_vsync, m_state.m_fragments.size(), m_state.m_fragments[0].y, m_state.m_fragments[m_state.m_fragments.size()-1].y); - bool force_vector = screen.screen_type() == SCREEN_TYPE_VECTOR || (m_vector->read() & 1); - bool debug_timing = (m_enable->read() & 2) == 2; - bool test_pat = (m_enable->read() & 4) == 4; - rgb_t backcol = debug_timing ? rgb_t(0xff, 0xff, 0x00, 0x00) : rgb_t(0xff, 0x00, 0x00, 0x00); + // printf("%f\n", machine().time().as_double()); + // printf("%d %lu %f %f\n", m_state.m_sig_vsync, m_state.m_fragments.size(), + // m_state.m_fragments[0].y, + // m_state.m_fragments[m_state.m_fragments.size()-1].y); + bool force_vector = screen.screen_type() == SCREEN_TYPE_VECTOR + || (m_vector->read() & 1); + bool debug_timing = (m_enable->read() & 2) == 2; + bool test_pat = (m_enable->read() & 4) == 4; + rgb_t backcol = debug_timing ? rgb_t(0xff, 0xff, 0x00, 0x00) + : rgb_t(0xff, 0x00, 0x00, 0x00); if (!force_vector) { @@ -377,18 +409,22 @@ uint32_t fixedfreq_device::screen_update(screen_device &screen, bitmap_rgb32 &bi { screen.set_video_attributes(VIDEO_SELF_RENDER); - const uint32_t flags(PRIMFLAG_ANTIALIAS(1) - | PRIMFLAG_BLENDMODE(BLENDMODE_ADD) - | (screen.screen_type() == SCREEN_TYPE_VECTOR ? PRIMFLAG_VECTOR(1) : 0)); + const uint32_t flags( + PRIMFLAG_ANTIALIAS(1) | PRIMFLAG_BLENDMODE(BLENDMODE_ADD) + | (screen.screen_type() == SCREEN_TYPE_VECTOR ? PRIMFLAG_VECTOR(1) + : 0)); const rectangle &visarea = screen.visible_area(); - float xscale = 1.0f / (float)visarea.width(); - float yscale = 1.0f / (float)visarea.height(); - float xoffs = (float)visarea.min_x; - float yoffs = (float)visarea.min_y; + float xscale = 1.0f / (float)visarea.width(); + float yscale = 1.0f / (float)visarea.height(); + float xoffs = (float)visarea.min_x; + float yoffs = (float)visarea.min_y; screen.container().empty(); - screen.container().add_rect(0.0f, 0.0f, 1.0f, 1.0f, rgb_t(0xff,0x00,0x00,0x00), + screen.container().add_rect( + 0.0f, 0.0f, 1.0f, 1.0f, rgb_t(0xff, 0x00, 0x00, 0x00), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) - | (screen.screen_type() == SCREEN_TYPE_VECTOR ? PRIMFLAG_VECTORBUF(1) : 0)); + | (screen.screen_type() == SCREEN_TYPE_VECTOR + ? PRIMFLAG_VECTORBUF(1) + : 0)); float last_y = -1e6; for (auto &f : m_state.m_fragments) @@ -397,7 +433,7 @@ uint32_t fixedfreq_device::screen_update(screen_device &screen, bitmap_rgb32 &bi const float y0((f.y - yoffs) * yscale); const float x1((f.xr - xoffs) * xscale); - rgb_t col = (debug_timing && f.y < last_y) ? backcol : (rgb_t) f.col; + rgb_t col = (debug_timing && f.y < last_y) ? backcol : (rgb_t)f.col; // FIXME: Debug check for proper vsync timing #if 0 auto w = m_scanline_height * xscale * 0.5; @@ -407,21 +443,18 @@ uint32_t fixedfreq_device::screen_update(screen_device &screen, bitmap_rgb32 &bi // (0xff << 24) | (f.col & 0xffffff), flags); #elif 1 - const float y1((f.y + m_scanline_height - yoffs) * yscale); - screen.container().add_rect( - x0, y0, x1, y1, - nom_col(col), -// (0xaf << 24) | (f.col & 0xffffff), - flags); + const float y1((f.y + m_scanline_height - yoffs) * yscale); + screen.container().add_rect(x0, y0, x1, y1, nom_col(col), + // (0xaf << 24) | + // (f.col & 0xffffff), + flags); #else - const float y1((f.y + m_scanline_height - yoffs) * yscale); - // Crashes with bgfx - screen.container().add_quad( - x0, y0, x1, y1, - rgb_t(nom_col(f.col)), -// (0xaf << 24) | (f.col & 0xffffff), - m_texture, - flags); + const float y1((f.y + m_scanline_height - yoffs) * yscale); + // Crashes with bgfx + screen.container().add_quad(x0, y0, x1, y1, rgb_t(nom_col(f.col)), + // (0xaf << 24) | + // (f.col & 0xffffff), + m_texture, flags); #endif last_y = f.y; } @@ -432,8 +465,9 @@ uint32_t fixedfreq_device::screen_update(screen_device &screen, bitmap_rgb32 &bi void fixedfreq_device::vsync_end_cb(double refresh_time, uint32_t field) { - const auto expected_frame_period(m_monitor.clock_period() * m_monitor.vtotal() * m_monitor.htotal()); - bool progressive = (m_enable->read() & 8) == 8; + const auto expected_frame_period(m_monitor.clock_period() + * m_monitor.vtotal() * m_monitor.htotal()); + bool progressive = (m_enable->read() & 8) == 8; double mult = 0.5; @@ -448,15 +482,21 @@ void fixedfreq_device::vsync_end_cb(double refresh_time, uint32_t field) mult = 1.0; } - const auto refresh_limited(std::min(4.0 * expected_frame_period, - std::max((refresh_time + m_last_rt) * mult, 0.25 * expected_frame_period))); + const auto refresh_limited(std::min( + 4.0 * expected_frame_period, std::max((refresh_time + m_last_rt) * mult, + 0.25 * expected_frame_period))); m_last_rt = refresh_time; - rectangle visarea(m_monitor.minh(), m_monitor.maxh(), m_monitor.minv(), m_monitor.maxv()); + rectangle visarea(m_monitor.minh(), m_monitor.maxh(), m_monitor.minv(), + m_monitor.maxv()); // reset_origin must be called first. - screen().reset_origin(m_state.m_last_y-(m_monitor.vsync_width() + m_monitor.vbackporch_width()), 0); - screen().configure(m_monitor.htotal_scaled(), m_monitor.vtotal(), visarea, DOUBLE_TO_ATTOSECONDS(refresh_limited)); + screen().reset_origin( + m_state.m_last_y + - (m_monitor.vsync_width() + m_monitor.vbackporch_width()), + 0); + screen().configure(m_monitor.htotal_scaled(), m_monitor.vtotal(), visarea, + DOUBLE_TO_ATTOSECONDS(refresh_limited)); } NETDEV_ANALOG_CALLBACK_MEMBER(fixedfreq_device::update_composite_monochrome) @@ -501,6 +541,8 @@ NETDEV_ANALOG_CALLBACK_MEMBER(fixedfreq_device::update_sync) /***************************************************************************/ +// clang-format off + static INPUT_PORTS_START(fixedfreq_base_ports) PORT_START("ENABLE") PORT_CONFNAME( 0x01, 0x00, "Display Monitor sliders" ) @@ -549,6 +591,9 @@ static INPUT_PORTS_START(fixedfreq_vector_ports) PORT_ADJUSTERX(SCANLINE_HEIGHT, "Scanline Height", 10, 300) INPUT_PORTS_END +// +// clang-format on + ioport_constructor fixedfreq_device::device_input_ports() const { LOG("input ports\n"); @@ -567,30 +612,18 @@ unsigned fixedfreq_device::monitor_val(unsigned param) const { switch (param) { - case HVISIBLE: - return m_monitor.hvisible_width(); - case HFRONTPORCH: - return m_monitor.hfrontporch_width(); - case HSYNC: - return m_monitor.hsync_width(); - case HBACKPORCH: - return m_monitor.hbackporch_width(); - case VVISIBLE: - return m_monitor.vvisible_width(); - case VFRONTPORCH: - return m_monitor.vfrontporch_width(); - case VSYNC: - return m_monitor.vsync_width(); - case VBACKPORCH: - return m_monitor.vbackporch_width(); - case SYNCTHRESHOLD: - return m_monitor.m_sync_threshold * 1000.0; - case VSYNCTHRESHOLD: - return m_monitor.m_vsync_threshold * 1000.0; - case GAIN: - return m_monitor.m_gain * 100.0; - case SCANLINE_HEIGHT: - return m_scanline_height * 100.0; + case HVISIBLE: return m_monitor.hvisible_width(); + case HFRONTPORCH: return m_monitor.hfrontporch_width(); + case HSYNC: return m_monitor.hsync_width(); + case HBACKPORCH: return m_monitor.hbackporch_width(); + case VVISIBLE: return m_monitor.vvisible_width(); + case VFRONTPORCH: return m_monitor.vfrontporch_width(); + case VSYNC: return m_monitor.vsync_width(); + case VBACKPORCH: return m_monitor.vbackporch_width(); + case SYNCTHRESHOLD: return m_monitor.m_sync_threshold * 1000.0; + case VSYNCTHRESHOLD: return m_monitor.m_vsync_threshold * 1000.0; + case GAIN: return m_monitor.m_gain * 100.0; + case SCANLINE_HEIGHT: return m_scanline_height * 100.0; } return 0; } @@ -603,28 +636,36 @@ INPUT_CHANGED_MEMBER(fixedfreq_device::port_changed) switch (param) { case HVISIBLE: - m.set_h_rel(newval, m.hfrontporch_width(), m.hsync_width(), m.hbackporch_width()); + m.set_h_rel(newval, m.hfrontporch_width(), m.hsync_width(), + m.hbackporch_width()); break; case HFRONTPORCH: - m.set_h_rel(m.hvisible_width(), newval, m.hsync_width(), m.hbackporch_width()); + m.set_h_rel(m.hvisible_width(), newval, m.hsync_width(), + m.hbackporch_width()); break; case HSYNC: - m.set_h_rel(m.hvisible_width(), m.hfrontporch_width(), newval, m.hbackporch_width()); + m.set_h_rel(m.hvisible_width(), m.hfrontporch_width(), newval, + m.hbackporch_width()); break; case HBACKPORCH: - m.set_h_rel(m.hvisible_width(), m.hfrontporch_width(), m.hsync_width(), newval); + m.set_h_rel(m.hvisible_width(), m.hfrontporch_width(), + m.hsync_width(), newval); break; case VVISIBLE: - m.set_v_rel(newval, m.vfrontporch_width(), m.vsync_width(), m.vbackporch_width()); + m.set_v_rel(newval, m.vfrontporch_width(), m.vsync_width(), + m.vbackporch_width()); break; case VFRONTPORCH: - m.set_v_rel(m.vvisible_width(), newval, m.vsync_width(), m.vbackporch_width()); + m.set_v_rel(m.vvisible_width(), newval, m.vsync_width(), + m.vbackporch_width()); break; case VSYNC: - m.set_v_rel(m.vvisible_width(), m.vfrontporch_width(), newval, m.vbackporch_width()); + m.set_v_rel(m.vvisible_width(), m.vfrontporch_width(), newval, + m.vbackporch_width()); break; case VBACKPORCH: - m.set_v_rel(m.vvisible_width(), m.vfrontporch_width(), m.vsync_width(), newval); + m.set_v_rel(m.vvisible_width(), m.vfrontporch_width(), + m.vsync_width(), newval); break; case SYNCTHRESHOLD: m.m_sync_threshold = static_cast(newval) / 1000.0; @@ -632,13 +673,12 @@ INPUT_CHANGED_MEMBER(fixedfreq_device::port_changed) case VSYNCTHRESHOLD: m.m_vsync_threshold = static_cast(newval) / 1000.0; break; - case GAIN: - m.m_gain = static_cast(newval) / 100.0; - break; + case GAIN: m.m_gain = static_cast(newval) / 100.0; break; case SCANLINE_HEIGHT: m_scanline_height = static_cast(newval) / 100.0; break; } - machine().ui().popup_time(5, "Screen Dim %d x %d\n", m.htotal(), m.vtotal()); - //ioport("YYY")->update_defvalue(true); + machine().ui().popup_time(5, "Screen Dim %d x %d\n", m.htotal(), + m.vtotal()); + // ioport("YYY")->update_defvalue(true); } diff --git a/src/devices/video/fixfreq.h b/src/devices/video/fixfreq.h index 22b84d12779..dd0cde5cce6 100644 --- a/src/devices/video/fixfreq.h +++ b/src/devices/video/fixfreq.h @@ -2,12 +2,12 @@ // copyright-holders:Couriersud /*************************************************************************** - fixfreq.h + fixfreq.h - Fixed frequency monochrome monitor emulation + Fixed frequency monochrome monitor emulation - The driver is intended for drivers which provide an analog video signal. - VSYNC and HSYNC levels are used to create the bitmap. + The driver is intended for drivers which provide an analog video signal. + VSYNC and HSYNC levels are used to create the bitmap. ***************************************************************************/ @@ -21,41 +21,58 @@ struct fixedfreq_monitor_desc { fixedfreq_monitor_desc() // default to NTSC "704x480@30i" - : m_monitor_clock(13500000), - m_fieldcount(2), - m_sync_threshold(0.3), - m_gain(1.0 / 3.7), - m_hscale(1), - m_vsync_threshold(0.600), // trigger at 91% of vsync length 1-exp(-0.6) - m_hvisible(704), - m_hfrontporch(728), - m_hsync(791), - m_hbackporch(858), - m_vvisible(480), - m_vfrontporch(486), - m_vsync(492), - m_vbackporch(525) - {} + : m_monitor_clock(13500000) + , m_fieldcount(2) + , m_sync_threshold(0.3) + , m_gain(1.0 / 3.7) + , m_hscale(1) + , m_vsync_threshold(0.600) + , // trigger at 91% of vsync length 1-exp(-0.6) + m_hvisible(704) + , m_hfrontporch(728) + , m_hsync(791) + , m_hbackporch(858) + , m_vvisible(480) + , m_vfrontporch(486) + , m_vsync(492) + , m_vbackporch(525) + { + } uint32_t monitor_clock() const noexcept { return m_monitor_clock; } - double clock_period() const noexcept { return 1.0 / (double) m_monitor_clock; } + double clock_period() const noexcept + { + return 1.0 / (double)m_monitor_clock; + } int minh() const noexcept { return (m_hbackporch - m_hsync) * m_hscale; } - int maxh() const noexcept { return (m_hbackporch - m_hsync + m_hvisible) * m_hscale - 1; } + int maxh() const noexcept + { + return (m_hbackporch - m_hsync + m_hvisible) * m_hscale - 1; + } int minv() const noexcept { return m_vbackporch - m_vsync; } - int maxv() const noexcept { return m_vbackporch - m_vsync + m_vvisible - 1; } + int maxv() const noexcept + { + return m_vbackporch - m_vsync + m_vvisible - 1; + } int htotal_scaled() const noexcept { return m_hbackporch * m_hscale; } int vbackporch_width() const noexcept { return m_vbackporch - m_vsync; } int vsync_width() const noexcept { return m_vsync - m_vfrontporch; } - int vfrontporch_width() const noexcept { return m_vfrontporch - m_vvisible; } + int vfrontporch_width() const noexcept + { + return m_vfrontporch - m_vvisible; + } int vvisible_width() const noexcept { return m_vvisible; } int vtotal() const noexcept { return m_vbackporch; } int hbackporch_width() const noexcept { return m_hbackporch - m_hsync; } int hsync_width() const noexcept { return m_hsync - m_hfrontporch; } - int hfrontporch_width() const noexcept { return m_hfrontporch - m_hvisible; } + int hfrontporch_width() const noexcept + { + return m_hfrontporch - m_hvisible; + } int hvisible_width() const noexcept { return m_hvisible; } int htotal() const noexcept { return m_hbackporch; } @@ -77,20 +94,22 @@ struct fixedfreq_monitor_desc double vsync_filter_timeconst() const noexcept { - return (double) (m_monitor_clock) / ((double) m_hbackporch * vsync_width()); + return (double)(m_monitor_clock) + / ((double)m_hbackporch * vsync_width()); } double hsync_filter_timeconst() const noexcept { - return (double) m_monitor_clock / (double) hsync_width(); + return (double)m_monitor_clock / (double)hsync_width(); } uint32_t m_monitor_clock; - int m_fieldcount; - double m_sync_threshold; - double m_gain; - int m_hscale; - double m_vsync_threshold; + int m_fieldcount; + double m_sync_threshold; + double m_gain; + int m_hscale; + double m_vsync_threshold; + private: int m_hvisible; int m_hfrontporch; @@ -110,9 +129,9 @@ struct fixedfreq_monitor_intf struct fixedfreq_monitor_line { - float y; - float x; - float xr; + float y; + float x; + float xr; uint32_t col; }; @@ -120,24 +139,26 @@ struct fixedfreq_monitor_state { using time_type = double; - fixedfreq_monitor_state(fixedfreq_monitor_desc &desc, fixedfreq_monitor_intf &intf) - : m_desc(desc), - m_intf(intf), - m_last_sync_val(0), - m_col(0), - m_last_x(0), - m_last_y(0), - m_last_sync_time(time_type(0)), - m_line_time(time_type(0)), - m_last_hsync_time(time_type(0)), - m_last_vsync_time(time_type(0)), - m_last_line_duration(time_type(0)), - m_last_field_time(time_type(0)), - m_vsync_filter(0), - m_sig_vsync(0), - m_sig_composite(0), - m_sig_field(0) - {} + fixedfreq_monitor_state(fixedfreq_monitor_desc &desc, + fixedfreq_monitor_intf &intf) + : m_desc(desc) + , m_intf(intf) + , m_last_sync_val(0) + , m_col(0) + , m_last_x(0) + , m_last_y(0) + , m_last_sync_time(time_type(0)) + , m_line_time(time_type(0)) + , m_last_hsync_time(time_type(0)) + , m_last_vsync_time(time_type(0)) + , m_last_line_duration(time_type(0)) + , m_last_field_time(time_type(0)) + , m_vsync_filter(0) + , m_sig_vsync(0) + , m_sig_composite(0) + , m_sig_field(0) + { + } /*** * \brief To be called after monitor parameters are set @@ -148,7 +169,7 @@ struct fixedfreq_monitor_state // Only copies constructor init m_last_sync_val = 0.0; - m_col = rgb_t(0,0,0); + m_col = rgb_t(0, 0, 0); m_last_x = 0; m_last_y = 0; m_last_sync_time = time_type(0); @@ -168,13 +189,15 @@ struct fixedfreq_monitor_state /* sync separator */ - //m_vsync_threshold = (exp(- 3.0/(3.0+3.0))) - exp(-1.0); - //printf("trigger %f with len %f\n", m_vsync_threshold, 1e6 / m_vsync_filter_timeconst); - // Minimum frame period to be passed to video system ? + // m_vsync_threshold = (exp(- 3.0/(3.0+3.0))) - exp(-1.0); + // printf("trigger %f with len %f\n", m_vsync_threshold, 1e6 / + // m_vsync_filter_timeconst); + // Minimum frame period to be passed to video system ? m_fragments.clear(); - //m_intf.vsync_end_cb(m_desc.clock_period() * m_desc.vtotal() * m_desc.htotal(), 0); + // m_intf.vsync_end_cb(m_desc.clock_period() * m_desc.vtotal() * + // m_desc.htotal(), 0); } void reset() @@ -192,19 +215,20 @@ struct fixedfreq_monitor_state void update_sync_channel(const time_type &time, const double newval); void update_bm(const time_type &time); - void update_composite_monochrome(const time_type &time, const double newval); + void + update_composite_monochrome(const time_type &time, const double newval); void update_red(const time_type &time, const double data); void update_green(const time_type &time, const double data); void update_blue(const time_type &time, const double data); void update_sync(const time_type &time, const double data); const fixedfreq_monitor_desc &m_desc; - fixedfreq_monitor_intf &m_intf; + fixedfreq_monitor_intf &m_intf; - double m_last_sync_val; - uint32_t m_col; - float m_last_x; - int m_last_y; + double m_last_sync_val; + uint32_t m_col; + float m_last_x; + int m_last_y; time_type m_last_sync_time; time_type m_line_time; time_type m_last_hsync_time; @@ -216,52 +240,76 @@ struct fixedfreq_monitor_state /* sync separator */ double m_vsync_filter; - int m_sig_vsync; - int m_sig_composite; - int m_sig_field; + int m_sig_vsync; + int m_sig_composite; + int m_sig_field; std::vector m_fragments; }; // ======================> fixedfreq_device -class fixedfreq_device : public device_t, public device_video_interface, - public fixedfreq_monitor_intf +class fixedfreq_device +: public device_t +, public device_video_interface +, public fixedfreq_monitor_intf { public: - using time_type = fixedfreq_monitor_state::time_type; // construction/destruction - fixedfreq_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + fixedfreq_device(const machine_config &mconfig, const char *tag, + device_t *owner, uint32_t clock = 0); // inline configuration helpers - fixedfreq_device &set_monitor_clock(uint32_t clock) { m_monitor.m_monitor_clock = clock; return *this;} - fixedfreq_device &set_fieldcount(int count) { m_monitor.m_fieldcount = count; return *this; } - fixedfreq_device &set_threshold(double threshold) { m_monitor.m_sync_threshold = threshold; return *this; } - fixedfreq_device &set_vsync_threshold(double threshold) { m_monitor.m_vsync_threshold = threshold; return *this; } - fixedfreq_device &set_gain(double gain) { m_monitor.m_gain = gain; return *this; } - fixedfreq_device &set_horz_params(int visible, int frontporch, int sync, int backporch) + fixedfreq_device &set_monitor_clock(uint32_t clock) { - m_monitor.set_h_rel( - visible, - frontporch - visible, - sync - frontporch, - backporch - sync); + m_monitor.m_monitor_clock = clock; return *this; } - fixedfreq_device &set_vert_params(int visible, int frontporch, int sync, int backporch) + fixedfreq_device &set_fieldcount(int count) { - m_monitor.set_v_rel( - visible, - frontporch - visible, - sync - frontporch, - backporch - sync); + m_monitor.m_fieldcount = count; + return *this; + } + fixedfreq_device &set_threshold(double threshold) + { + m_monitor.m_sync_threshold = threshold; + return *this; + } + fixedfreq_device &set_vsync_threshold(double threshold) + { + m_monitor.m_vsync_threshold = threshold; + return *this; + } + fixedfreq_device &set_gain(double gain) + { + m_monitor.m_gain = gain; + return *this; + } + fixedfreq_device & + set_horz_params(int visible, int frontporch, int sync, int backporch) + { + m_monitor.set_h_rel(visible, frontporch - visible, sync - frontporch, + backporch - sync); + return *this; + } + fixedfreq_device & + set_vert_params(int visible, int frontporch, int sync, int backporch) + { + m_monitor.set_v_rel(visible, frontporch - visible, sync - frontporch, + backporch - sync); + return *this; + } + fixedfreq_device &set_horz_scale(int hscale) + { + m_monitor.m_hscale = hscale; return *this; } - fixedfreq_device &set_horz_scale(int hscale) { m_monitor.m_hscale = hscale; return *this;} // pre-defined configurations - fixedfreq_device &set_mode_ntsc720() //ModeLine "720x480@30i" 13.5 720 736 799 858 480 486 492 525 interlace -hsync -vsync + fixedfreq_device &set_mode_ntsc720() // ModeLine "720x480@30i" 13.5 720 736 + // 799 858 480 486 492 525 interlace + // -hsync -vsync { set_monitor_clock(13500000); set_horz_params(720, 736, 799, 858); @@ -270,7 +318,8 @@ public: set_threshold(0.3); return *this; } - fixedfreq_device &set_mode_ntsc704() //ModeLine "704x480@30i" 13.5 704 728 791 858 480 486 492 525 + fixedfreq_device &set_mode_ntsc704() // ModeLine "704x480@30i" 13.5 704 728 + // 791 858 480 486 492 525 { set_monitor_clock(13500000); set_horz_params(704, 728, 791, 858); @@ -280,7 +329,8 @@ public: return *this; } - virtual uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + virtual uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, + const rectangle &cliprect); NETDEV_ANALOG_CALLBACK_MEMBER(update_composite_monochrome); NETDEV_ANALOG_CALLBACK_MEMBER(update_red); @@ -293,8 +343,8 @@ public: unsigned monitor_val(unsigned param) const; protected: - - fixedfreq_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + fixedfreq_device(const machine_config &mconfig, device_type type, + const char *tag, device_t *owner, uint32_t clock); // device-level overrides virtual void device_config_complete() override; @@ -309,16 +359,14 @@ protected: private: required_ioport m_enable; required_ioport m_vector; - float m_scanline_height; - double m_last_rt; + float m_scanline_height; + double m_last_rt; /* adjustable by drivers */ - fixedfreq_monitor_desc m_monitor; + fixedfreq_monitor_desc m_monitor; fixedfreq_monitor_state m_state; - }; - // device type definition DECLARE_DEVICE_TYPE(FIXFREQ, fixedfreq_device) diff --git a/src/lib/netlist/analog/nld_bjt.cpp b/src/lib/netlist/analog/nld_bjt.cpp index cae3c9649b0..2152f8f431a 100644 --- a/src/lib/netlist/analog/nld_bjt.cpp +++ b/src/lib/netlist/analog/nld_bjt.cpp @@ -353,8 +353,6 @@ namespace netlist::analog nld_two_terminal m_P0_P1; // 0, -gec, -gcc, 0 | 0 }; -#define USE_THREE (1) - // ----------------------------------------------------------------------------- // nld_QBJT_EB // ----------------------------------------------------------------------------- diff --git a/src/lib/netlist/analog/nld_mosfet.cpp b/src/lib/netlist/analog/nld_mosfet.cpp index 8cbd368759f..63911ceb02f 100644 --- a/src/lib/netlist/analog/nld_mosfet.cpp +++ b/src/lib/netlist/analog/nld_mosfet.cpp @@ -21,14 +21,16 @@ /// http://jaco.ec.t.kanazawa-u.ac.jp/edu/mix/pdf/3.pdf /// /// Farid N. Naim, Circuit Simulation (Wiley-IEEE Press, 2010). -/// Stefan Jahn, Michael Margraf, Vincent Habchi and Raimund Jacob, "Qucs Technical Papers" (2007) +/// Stefan Jahn, Michael Margraf, Vincent Habchi and Raimund Jacob, "Qucs +/// Technical Papers" (2007) /// -#include "solver/nld_solver.h" #include "../nl_setup.h" #include "nlid_twoterm.h" -#define BODY_CONNECTED_TO_SOURCE (1) +#include "solver/nld_solver.h" + +#define BODY_CONNECTED_TO_SOURCE (1) namespace netlist::analog { @@ -99,11 +101,11 @@ namespace netlist::analog { public: fet_model_t(param_model_t &model) - : m_VTO(model, "VTO") - , m_N(model, "N") - , m_ISS(model, "IS") // Haven't seen a model using ISS / ISD - , m_ISD(model, "IS") - , m_LD(model, "LD") + : m_VTO(model, "VTO") + , m_N(model, "N") + , m_ISS(model, "IS") // Haven't seen a model using ISS / ISD + , m_ISD(model, "IS") + , m_LD(model, "LD") , m_L(model, "L") , m_W(model, "W") , m_TOX(model, "TOX") @@ -119,28 +121,33 @@ namespace netlist::analog , m_CGDO(model, "CGDO") , m_CGBO(model, "CGBO") , m_CAPMOD(model, "CAPMOD") - {} + { + } - param_model_t::value_t m_VTO; //!< Threshold voltage [V] - param_model_t::value_t m_N; //!< Bulk diode emission coefficient - param_model_t::value_t m_ISS; //!< Body diode saturation current - param_model_t::value_t m_ISD; //!< Body diode saturation current - param_model_t::value_t m_LD; //!< Lateral diffusion [m] - param_model_t::value_t m_L; //!< Length scaling - param_model_t::value_t m_W; //!< Width scaling - param_model_t::value_t m_TOX; //!< Oxide thickness - param_model_t::value_t m_KP; //!< Transconductance parameter [A/V²] - param_model_t::value_t m_UO; //!< Surface mobility [cm²/V/s] - param_model_t::value_t m_PHI; //!< Surface inversion potential [V] - param_model_t::value_t m_NSUB; //!< Substrate doping [1/cm³] - param_model_t::value_t m_GAMMA; //!< Bulk threshold parameter [V^½] - param_model_t::value_t m_LAMBDA; //!< Channel-length modulation [1/V] - param_model_t::value_t m_RD; //!< Drain ohmic resistance - param_model_t::value_t m_RS; //!< Source ohmic resistance - param_model_t::value_t m_CGSO; //!< Gate-source overlap capacitance per meter channel width - param_model_t::value_t m_CGDO; //!< Gate-drain overlap capacitance per meter channel width - param_model_t::value_t m_CGBO; //!< Gate-bulk overlap capacitance per meter channel width - param_model_t::value_base_t m_CAPMOD; //!< Capacitance model (0=no model 2=Meyer) + param_model_t::value_t m_VTO; //!< Threshold voltage [V] + param_model_t::value_t m_N; //!< Bulk diode emission coefficient + param_model_t::value_t m_ISS; //!< Body diode saturation current + param_model_t::value_t m_ISD; //!< Body diode saturation current + param_model_t::value_t m_LD; //!< Lateral diffusion [m] + param_model_t::value_t m_L; //!< Length scaling + param_model_t::value_t m_W; //!< Width scaling + param_model_t::value_t m_TOX; //!< Oxide thickness + param_model_t::value_t m_KP; //!< Transconductance parameter [A/V²] + param_model_t::value_t m_UO; //!< Surface mobility [cm²/V/s] + param_model_t::value_t m_PHI; //!< Surface inversion potential [V] + param_model_t::value_t m_NSUB; //!< Substrate doping [1/cm³] + param_model_t::value_t m_GAMMA; //!< Bulk threshold parameter [V^½] + param_model_t::value_t m_LAMBDA; //!< Channel-length modulation [1/V] + param_model_t::value_t m_RD; //!< Drain ohmic resistance + param_model_t::value_t m_RS; //!< Source ohmic resistance + param_model_t::value_t m_CGSO; //!< Gate-source overlap capacitance per + //!< meter channel width + param_model_t::value_t m_CGDO; //!< Gate-drain overlap capacitance per + //!< meter channel width + param_model_t::value_t m_CGBO; //!< Gate-bulk overlap capacitance per + //!< meter channel width + param_model_t::value_base_t m_CAPMOD; //!< Capacitance model (0=no + //!< model 2=Meyer) }; // ----------------------------------------------------------------------------- @@ -150,7 +157,6 @@ namespace netlist::analog class nld_MOSFET : public base_device_t { public: - public: \ nld_MOSFET(constructor_param_t data) : base_device_t(data) , m_model(*this, "MODEL", "NMOS") @@ -171,7 +177,7 @@ namespace netlist::analog , m_lambda(nlconst::zero()) , m_Leff(nlconst::zero()) , m_CoxWL(nlconst::zero()) - //S, m_polarity(qtype() == FET_NMOS ? nlconst::one() : -nlconst::one()) + // S, m_polarity(qtype() == FET_NMOS ? nlconst::one() : -nlconst::one()) , m_Cgb(nlconst::zero()) , m_Cgs(nlconst::zero()) , m_Cgd(nlconst::zero()) @@ -179,28 +185,30 @@ namespace netlist::analog , m_Vgs(*this, "m_Vgs", nlconst::zero()) , m_Vgd(*this, "m_Vgd", nlconst::zero()) , m_model_acc(m_model) - { - register_sub_alias("S", m_SG.P()); // Source - register_sub_alias("G", m_SG.N()); // Gate + { + register_sub_alias("S", m_SG.P()); // Source + register_sub_alias("G", m_SG.N()); // Gate - register_sub_alias("D", m_DG.P()); // Drain + register_sub_alias("D", m_DG.P()); // Drain connect(m_SG.P(), m_SD.P()); connect(m_SG.N(), m_DG.N()); connect(m_DG.P(), m_SD.N()); - m_polarity = (m_model.type() == "NMOS_DEFAULT" ? nlconst::one() : -nlconst::one()); + m_polarity = (m_model.type() == "NMOS_DEFAULT" ? nlconst::one() + : -nlconst::one()); m_capacitor_model = m_model_acc.m_CAPMOD; //# printf("capmod %d %g %g\n", m_capacitor_model, (nl_fptype)m_model_acc.m_VTO, m_polarity); - nl_assert_always(m_capacitor_model == 0 || m_capacitor_model == 2, "Error: CAPMODEL invalid value"); + nl_assert_always(m_capacitor_model == 0 || m_capacitor_model == 2, + "Error: CAPMODEL invalid value"); // // From http://ltwiki.org/LTspiceHelp/LTspiceHelp/M_MOSFET.htm : // - // VTO, KP, LAMBDA, PHI and GAMMA. These parameters are computed - // if the process parameters(NSUB, TOX,...) are given, but - // user-specified values always override. + // VTO, KP, LAMBDA, PHI and GAMMA. These parameters are + // computed if the process parameters(NSUB, TOX,...) are given, + // but user-specified values always override. // // But couldn't find a formula for lambda anywhere // @@ -209,20 +217,28 @@ namespace netlist::analog // calculate effective channel length m_Leff = m_model_acc.m_L - 2 * m_model_acc.m_LD; - nl_assert_always(m_Leff > nlconst::zero(), "Effective Lateral diffusion would be negative for model"); + nl_assert_always( + m_Leff > nlconst::zero(), + "Effective Lateral diffusion would be negative for model"); - nl_fptype Cox = (m_model_acc.m_TOX > nlconst::zero()) ? (constants::eps_SiO2() * constants::eps_0() / m_model_acc.m_TOX) : nlconst::zero(); + nl_fptype Cox = (m_model_acc.m_TOX > nlconst::zero()) + ? (constants::eps_SiO2() * constants::eps_0() + / m_model_acc.m_TOX) + : nlconst::zero(); // calculate DC transconductance coefficient if (m_model_acc.m_KP > nlconst::zero()) m_beta = m_model_acc.m_KP * m_model_acc.m_W / m_Leff; - else if (Cox > nlconst::zero() && m_model_acc.m_UO > nlconst::zero()) - m_beta = m_model_acc.m_UO * nlconst::magic(1e-4) * Cox * m_model_acc.m_W / m_Leff; + else if (Cox > nlconst::zero() + && m_model_acc.m_UO > nlconst::zero()) + m_beta = m_model_acc.m_UO * nlconst::magic(1e-4) * Cox + * m_model_acc.m_W / m_Leff; else m_beta = nlconst::magic(2e-5) * m_model_acc.m_W / m_Leff; - //FIXME::UT can disappear - const nl_fptype Vt = constants::T0() * constants::k_b() / constants::Q_e(); + // FIXME::UT can disappear + const nl_fptype Vt = constants::T0() * constants::k_b() + / constants::Q_e(); // calculate surface potential if not given @@ -230,8 +246,12 @@ namespace netlist::analog m_phi = m_model_acc.m_PHI; else if (m_model_acc.m_NSUB > nlconst::zero()) { - nl_assert_always(m_model_acc.m_NSUB * nlconst::magic(1e6) >= constants::NiSi(), "Error calculating phi for model"); - m_phi = nlconst::two() * Vt * plib::log (m_model_acc.m_NSUB * nlconst::magic(1e6) / constants::NiSi()); + nl_assert_always(m_model_acc.m_NSUB * nlconst::magic(1e6) + >= constants::NiSi(), + "Error calculating phi for model"); + m_phi = nlconst::two() * Vt + * plib::log(m_model_acc.m_NSUB * nlconst::magic(1e6) + / constants::NiSi()); } else m_phi = nlconst::magic(0.6); @@ -241,21 +261,24 @@ namespace netlist::analog m_gamma = m_model_acc.m_GAMMA; else { - if (Cox > nlconst::zero() && m_model_acc.m_NSUB > nlconst::zero()) - m_gamma = plib::sqrt (nlconst::two() - * constants::Q_e() * constants::eps_Si() * constants::eps_0() - * m_model_acc.m_NSUB * nlconst::magic(1e6)) / Cox; + if (Cox > nlconst::zero() + && m_model_acc.m_NSUB > nlconst::zero()) + m_gamma = plib::sqrt( + nlconst::two() * constants::Q_e() + * constants::eps_Si() * constants::eps_0() + * m_model_acc.m_NSUB * nlconst::magic(1e6)) + / Cox; else m_gamma = nlconst::zero(); } m_vto = m_model_acc.m_VTO; // FIXME zero conversion - if(m_vto == nlconst::zero()) + if (m_vto == nlconst::zero()) log().warning(MW_MOSFET_THRESHOLD_VOLTAGE(m_model.name())); - // FIXME: VTO if missing may be calculated from TPG, NSS and temperature. Usually models - // specify VTO so skip this here. + // FIXME: VTO if missing may be calculated from TPG, NSS and + // temperature. Usually models specify VTO so skip this here. m_CoxWL = Cox * m_model_acc.m_W * m_Leff; @@ -269,13 +292,14 @@ namespace netlist::analog { if (m_capacitor_model != 0) { - if (ts_type == time_step_type::FORWARD) + if (ts_type == detail::time_step_type::FORWARD) { //#const nl_nl_fptype Ugd = -m_DG.deltaV() * m_polarity; // Gate - Drain //#const nl_nl_fptype Ugs = -m_SG.deltaV() * m_polarity; // Gate - Source - const nl_fptype Ugd = m_Vgd; // Gate - Drain - const nl_fptype Ugs = m_Vgs; // Gate - Source - const nl_fptype Ubs = nlconst::zero(); // Bulk - Source == 0 if connected + const nl_fptype Ugd = m_Vgd; // Gate - Drain + const nl_fptype Ugs = m_Vgs; // Gate - Source + const nl_fptype Ubs = nlconst::zero(); // Bulk - Source == 0 + // if connected const nl_fptype Ugb = Ugs - Ubs; m_cap_gb.time_step(m_Cgb, Ugb, step); @@ -292,20 +316,22 @@ namespace netlist::analog } protected: - NETLIB_RESETI() { // Bulk diodes - m_D_BD.set_param(m_model_acc.m_ISD, m_model_acc.m_N, exec().gmin(), constants::T0()); - #if (!BODY_CONNECTED_TO_SOURCE) - m_D_BS.set_param(m_model_acc.m_ISS, m_model_acc.m_N, exec().gmin(), constants::T0()); - #endif + m_D_BD.set_param(m_model_acc.m_ISD, m_model_acc.m_N, exec().gmin(), + constants::T0()); +#if (!BODY_CONNECTED_TO_SOURCE) + m_D_BS.set_param(m_model_acc.m_ISS, m_model_acc.m_N, exec().gmin(), + constants::T0()); +#endif } NETLIB_HANDLERI(terminal_handler) { - // only called if connected to a rail net ==> notify the solver to recalculate + // only called if connected to a rail net ==> notify the solver to + // recalculate auto *solv(m_SG.solver()); if (solv != nullptr) solv->solve_now(); @@ -316,7 +342,6 @@ namespace netlist::analog NETLIB_UPDATE_TERMINALSI(); private: - param_model_t m_model; NETLIB_NAME(two_terminal) m_DG; @@ -349,25 +374,30 @@ namespace netlist::analog nl_fptype m_Cgs; nl_fptype m_Cgd; - int m_capacitor_model; + int m_capacitor_model; state_var m_Vgs; state_var m_Vgd; - fet_model_t m_model_acc; + fet_model_t m_model_acc; void set_cap(generic_capacitor &cap, - nl_fptype capval, nl_fptype V, - nl_fptype &g11, nl_fptype &g12, nl_fptype &g21, nl_fptype &g22, - nl_fptype &I1, nl_fptype &I2) const + nl_fptype capval, nl_fptype V, nl_fptype &g11, + nl_fptype &g12, nl_fptype &g21, nl_fptype &g22, + nl_fptype &I1, nl_fptype &I2) const { const nl_fptype I = cap.Ieq(capval, V) * m_polarity; const nl_fptype G = cap.G(capval); - g11 += G; g12 -= G; g21 -= G; g22 += G; - I1 -= I; I2 += I; - //printf("Cap: %g\n", capval); + g11 += G; + g12 -= G; + g21 -= G; + g22 += G; + I1 -= I; + I2 += I; + // printf("Cap: %g\n", capval); } - void calculate_caps(nl_fptype Vgs, nl_fptype Vgd, nl_fptype Vth, - nl_fptype &Cgs, nl_fptype &Cgd, nl_fptype &Cgb) const + void + calculate_caps(nl_fptype Vgs, nl_fptype Vgd, nl_fptype Vth, + nl_fptype &Cgs, nl_fptype &Cgd, nl_fptype &Cgb) const { nl_fptype Vctrl = Vgs - Vth * m_polarity; // Cut off - now further differentiated into 3 different formulas @@ -388,7 +418,8 @@ namespace netlist::analog else if (Vctrl <= 0) { Cgb = -Vctrl * m_CoxWL / m_phi; - Cgs = Vctrl * m_CoxWL * nlconst::fraction(4.0, 3.0) / m_phi + nlconst::two_thirds() * m_CoxWL; + Cgs = Vctrl * m_CoxWL * nlconst::fraction(4.0, 3.0) / m_phi + + nlconst::two_thirds() * m_CoxWL; Cgd = nlconst::zero(); } else @@ -405,11 +436,15 @@ namespace netlist::analog else { // linear - const auto Sqr1(plib::narrow_cast(plib::pow(Vdsat - Vds, 2))); - const auto Sqr2(plib::narrow_cast(plib::pow(nlconst::two() * Vdsat - Vds, 2))); + const auto Sqr1(plib::narrow_cast( + plib::pow(Vdsat - Vds, 2))); + const auto Sqr2(plib::narrow_cast( + plib::pow(nlconst::two() * Vdsat - Vds, 2))); Cgb = 0; - Cgs = m_CoxWL * (nlconst::one() - Sqr1 / Sqr2) * nlconst::two_thirds(); - Cgd = m_CoxWL * (nlconst::one() - Vdsat * Vdsat / Sqr2) * nlconst::two_thirds(); + Cgs = m_CoxWL * (nlconst::one() - Sqr1 / Sqr2) + * nlconst::two_thirds(); + Cgd = m_CoxWL * (nlconst::one() - Vdsat * Vdsat / Sqr2) + * nlconst::two_thirds(); } } } @@ -426,19 +461,26 @@ namespace netlist::analog // limit step sizes - const nl_fptype k = nlconst::magic(3.5); // see "Circuit Simulation", page 185 + const nl_fptype k = nlconst::magic(3.5); // see "Circuit Simulation", + // page 185 nl_fptype d = (Vgs - m_Vgs); - Vgs = m_Vgs + plib::reciprocal(k) * plib::signum(d) * plib::log1p(k * plib::abs(d)); + Vgs = m_Vgs + + plib::reciprocal(k) * plib::signum(d) + * plib::log1p(k * plib::abs(d)); d = (Vgd - m_Vgd); - Vgd = m_Vgd + plib::reciprocal(k) * plib::signum(d) * plib::log1p(k * plib::abs(d)); + Vgd = m_Vgd + + plib::reciprocal(k) * plib::signum(d) + * plib::log1p(k * plib::abs(d)); m_Vgs = Vgs; m_Vgd = Vgd; - const nl_fptype Vbs = nlconst::zero(); // Bulk - Source == 0 if connected - //const nl_nl_fptype Vbd = m_SD.deltaV() * m_polarity; // Bulk - Drain = Source - Drain + const nl_fptype Vbs = nlconst::zero(); // Bulk - Source == 0 if + // connected + // const nl_nl_fptype Vbd = m_SD.deltaV() * m_polarity; // Bulk - Drain + // = Source - Drain const nl_fptype Vds = Vgs - Vgd; - const nl_fptype Vbd = -Vds; // Bulk - Drain = Source - Drain + const nl_fptype Vbd = -Vds; // Bulk - Drain = Source - Drain #if (!BODY_CONNECTED_TO_SOURCE) m_D_BS.update_diode(Vbs); @@ -451,8 +493,11 @@ namespace netlist::analog // calculate Vth const nl_fptype Vbulk = is_forward ? Vbs : Vbd; - const nl_fptype phi_m_Vbulk = (m_phi > Vbulk) ? plib::sqrt(m_phi - Vbulk) : nlconst::zero(); - const nl_fptype Vth = m_vto * m_polarity + m_gamma * (phi_m_Vbulk - plib::sqrt(m_phi)); + const nl_fptype phi_m_Vbulk = (m_phi > Vbulk) + ? plib::sqrt(m_phi - Vbulk) + : nlconst::zero(); + const nl_fptype Vth = m_vto * m_polarity + + m_gamma * (phi_m_Vbulk - plib::sqrt(m_phi)); const nl_fptype Vctrl = (is_forward ? Vgs : Vgd) - Vth; @@ -467,30 +512,36 @@ namespace netlist::analog { // cutoff region Ids = nlconst::zero(); - gm = nlconst::zero(); + gm = nlconst::zero(); gds = nlconst::zero(); gmb = nlconst::zero(); } else { - const nl_fptype beta = m_beta * (nlconst::one() + m_lambda * absVds); + const nl_fptype beta = m_beta + * (nlconst::one() + m_lambda * absVds); if (Vctrl <= absVds) { // saturation region Ids = beta * Vctrl * Vctrl / nlconst::two(); - gm = beta * Vctrl; + gm = beta * Vctrl; gds = m_lambda * m_beta * Vctrl * Vctrl / nlconst::two(); } else { // linear region Ids = beta * absVds * (Vctrl - absVds / nlconst::two()); - gm = beta * absVds; - gds = beta * (Vctrl - absVds) + m_lambda * m_beta * absVds * (Vctrl - absVds / nlconst::two()); + gm = beta * absVds; + gds = beta * (Vctrl - absVds) + + m_lambda * m_beta * absVds + * (Vctrl - absVds / nlconst::two()); } // back gate transconductance - const nl_fptype bgtc = (phi_m_Vbulk != nlconst::zero()) ? (m_gamma / phi_m_Vbulk / nlconst::two()) : nlconst::zero(); + const nl_fptype bgtc = (phi_m_Vbulk != nlconst::zero()) + ? (m_gamma / phi_m_Vbulk + / nlconst::two()) + : nlconst::zero(); gmb = gm * bgtc; } @@ -512,11 +563,11 @@ namespace netlist::analog #endif // exchange controlling nodes if necessary const nl_fptype gate_source = is_forward ? (gm + gmb) : nlconst::zero(); - const nl_fptype gate_drain = is_forward ? nlconst::zero() : (gm + gmb); + const nl_fptype gate_drain = is_forward ? nlconst::zero() : (gm + gmb); - const nl_fptype IeqDS = (is_forward) ? - Ids - gm * Vgs - gmb * Vbs - gds * Vds - : -Ids - gm * Vgd - gmb * Vbd - gds * Vds; + const nl_fptype IeqDS = (is_forward) + ? Ids - gm * Vgs - gmb * Vbs - gds * Vds + : -Ids - gm * Vgd - gmb * Vbd - gds * Vds; // IG = 0 nl_fptype IG = nlconst::zero(); @@ -529,20 +580,20 @@ namespace netlist::analog nl_fptype gGS = nlconst::zero(); nl_fptype gGB = nlconst::zero(); - nl_fptype gDG = gm; - nl_fptype gDD = gds + gbd - gate_drain; + nl_fptype gDG = gm; + nl_fptype gDD = gds + gbd - gate_drain; const nl_fptype gDS = -gds - gate_source; - const nl_fptype gDB = gmb - gbd; + const nl_fptype gDB = gmb - gbd; - nl_fptype gSG = -gm; + nl_fptype gSG = -gm; const nl_fptype gSD = -gds + gate_drain; - nl_fptype gSS = gbs + gds + gate_source; + nl_fptype gSS = gbs + gds + gate_source; const nl_fptype gSB = -gbs - gmb; - nl_fptype gBG = nlconst::zero(); + nl_fptype gBG = nlconst::zero(); const nl_fptype gBD = -gbd; const nl_fptype gBS = -gbs; - nl_fptype gBB = gbs + gbd; + nl_fptype gBB = gbs + gbd; if (m_capacitor_model != 0) { @@ -553,23 +604,26 @@ namespace netlist::analog else calculate_caps(Vgd, Vgs, Vth, m_Cgd, m_Cgs, m_Cgb); - set_cap(m_cap_gb, m_Cgb + m_model_acc.m_CGBO * m_Leff, Vgb, gGG, gGB, gBG, gBB, IG, IB); - set_cap(m_cap_gs, m_Cgs + m_model_acc.m_CGSO * m_model_acc.m_W, Vgs, gGG, gGS, gSG, gSS, IG, IS); - set_cap(m_cap_gd, m_Cgd + m_model_acc.m_CGDO * m_model_acc.m_W, Vgd, gGG, gGD, gDG, gDD, IG, ID); + set_cap(m_cap_gb, m_Cgb + m_model_acc.m_CGBO * m_Leff, Vgb, gGG, + gGB, gBG, gBB, IG, IB); + set_cap(m_cap_gs, m_Cgs + m_model_acc.m_CGSO * m_model_acc.m_W, Vgs, + gGG, gGS, gSG, gSS, IG, IS); + set_cap(m_cap_gd, m_Cgd + m_model_acc.m_CGDO * m_model_acc.m_W, Vgd, + gGG, gGD, gDG, gDD, IG, ID); } // Source connected to body, Diode S-B shorted! const nl_fptype gSSBB = gSS + gBB + gBS + gSB; - const auto zero(nlconst::zero()); + const auto zero(nlconst::zero()); // S G - m_SG.set_mat( gSSBB, gSG + gBG, +(IS + IB), // S - gGS + gGB, gGG, IG ); // G + m_SG.set_mat(gSSBB, gSG + gBG, +(IS + IB), // S + gGS + gGB, gGG, IG); // G // D G - m_DG.set_mat( gDD, gDG, +ID, // D - gGD, zero, zero ); // G + m_DG.set_mat(gDD, gDG, +ID, // D + gGD, zero, zero); // G // S D - m_SD.set_mat( zero, gSD + gBD, zero, // S - gDS + gDB, zero, zero ); // D + m_SD.set_mat(zero, gSD + gBD, zero, // S + gDS + gDB, zero, zero); // D /// | /// | D S G I @@ -600,13 +654,11 @@ namespace netlist::analog /// | } - NETLIB_UPDATE_PARAM(MOSFET) - { - } + NETLIB_UPDATE_PARAM(MOSFET) {} } // namespace netlist::analog -namespace netlist::devices { +namespace netlist::devices +{ NETLIB_DEVICE_IMPL_NS(analog, MOSFET, "MOSFET", "MODEL") } // namespace netlist::devices - diff --git a/src/lib/netlist/analog/nlid_twoterm.cpp b/src/lib/netlist/analog/nlid_twoterm.cpp index 3d5d0721dfb..1a3c79e713f 100644 --- a/src/lib/netlist/analog/nlid_twoterm.cpp +++ b/src/lib/netlist/analog/nlid_twoterm.cpp @@ -125,7 +125,7 @@ namespace netlist::analog NETLIB_TIMESTEP(L) { - if (ts_type == time_step_type::FORWARD) + if (ts_type == detail::time_step_type::FORWARD) { m_last_I = m_I; m_last_G = m_G; diff --git a/src/lib/netlist/analog/nlid_twoterm.h b/src/lib/netlist/analog/nlid_twoterm.h index f940b8fa6dc..d84356fe82d 100644 --- a/src/lib/netlist/analog/nlid_twoterm.h +++ b/src/lib/netlist/analog/nlid_twoterm.h @@ -312,7 +312,7 @@ namespace netlist::analog NETLIB_IS_TIMESTEP(true) NETLIB_TIMESTEPI() { - if (ts_type == time_step_type::FORWARD) + if (ts_type == detail::time_step_type::FORWARD) { // G, Ieq const auto res(m_cap.time_step(m_C(), deltaV(), step)); @@ -584,7 +584,7 @@ namespace netlist::analog NETLIB_TIMESTEPI() { - if (ts_type == time_step_type::FORWARD) + if (ts_type == detail::time_step_type::FORWARD) { m_t += step; m_funcparam[0] = m_t; @@ -637,7 +637,7 @@ namespace netlist::analog NETLIB_IS_TIMESTEP(!m_func().empty()) NETLIB_TIMESTEPI() { - if (ts_type == time_step_type::FORWARD) + if (ts_type == detail::time_step_type::FORWARD) { m_t += step; m_funcparam[0] = m_t; diff --git a/src/lib/netlist/build/.clang-format b/src/lib/netlist/build/.clang-format index 09d57438f7b..d312a0798cc 100644 --- a/src/lib/netlist/build/.clang-format +++ b/src/lib/netlist/build/.clang-format @@ -25,13 +25,14 @@ BreakStringLiterals: false AlwaysBreakTemplateDeclarations: Yes # AfterComma does not work <= 13 #BreakInheritanceList: AfterComma -#BreakInheritanceList: BeforeComma +BreakInheritanceList: BeforeComma #BreakInheritanceList: false SpaceBeforeInheritanceColon: true #AlignAfterOpenBracket: DontAlign AlignAfterOpenBracket: Align PointerAlignment: Right +ReferenceAlignment: Right SpacesInAngles: false SpaceBeforeAssignmentOperators: true AlignConsecutiveDeclarations: true @@ -90,16 +91,17 @@ StatementMacros: TypenameMacros: - "NETLIST_NAME" - "NETLIB_NAME" + - "PENUM" WhitespaceSensitiveMacros: - "ALIAS" - - "NET_C" - "DIPPINS" + - "NET_C" + - "PENUM" IndentPPDirectives: BeforeHash MacroBlockBegin: "^static NETLIST_START\\(.+\\)|static TRUTHTABLE_START\\(.*\\)$" MacroBlockEnd: "^NETLIST_END\\(\\)|TRUTHTABLE_END\\(\\)$" -# ReferenceAlignment: Middle # Avoid formatting # -- clang-tidy diff --git a/src/lib/netlist/build/cspell.json b/src/lib/netlist/build/cspell.json index f242083ac82..bf46cc2e992 100644 --- a/src/lib/netlist/build/cspell.json +++ b/src/lib/netlist/build/cspell.json @@ -19,6 +19,7 @@ "Schmitt", "Schottky", "Zener", + "Thevenin", // Company names "Fairchild", "Signetics", @@ -69,6 +70,7 @@ // FIXME: Remove everything below here again // Excluded for now ... Still over 1000 in the log "plib", // namespace + "isnull", "pstring", "passert", "putf", @@ -79,6 +81,8 @@ "idrn", "preprocessor", "ppreprocessor", + "psource", + "psemaphore", "modacc", "Ainv", "anetlist", diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile index ab89d6adcdd..077b72b028f 100644 --- a/src/lib/netlist/build/makefile +++ b/src/lib/netlist/build/makefile @@ -114,7 +114,7 @@ TIDY_DB = $(OBJ)/compile_commands.json #LTO decreases performance :-( #LTO = -flto=4 -fuse-linker-plugin -Wodr -CCOREFLAGS = -g -O3 -std=c++17 -I$(SRC) -I$(SRC)/.. -I$(SRC)/../.. +CCOREFLAGS = -g -O3 -std=c++17 -I$(SRC) CFLAGS = $(LTO) $(CCOREFLAGS) $(CEXTRAFLAGS) LDFLAGS = $(LTO) -g -O3 -std=c++17 $(LDEXTRAFLAGS) diff --git a/src/lib/netlist/core/base_objects.h b/src/lib/netlist/core/base_objects.h index 1f924d988dc..b62c82e160c 100644 --- a/src/lib/netlist/core/base_objects.h +++ b/src/lib/netlist/core/base_objects.h @@ -17,9 +17,19 @@ #include "../plib/pexception.h" #include "../plib/plists.h" #include "../plib/pmempool.h" +#include "../plib/ppmf.h" #include +namespace netlist +{ + /// \brief Delegate type for device notification. + /// + using nl_delegate = plib::pmfp; + using nl_delegate_ts = plib::pmfp; + using nl_delegate_dyn = plib::pmfp; +} // namespace netlist + namespace netlist::detail { @@ -131,16 +141,16 @@ namespace netlist::detail PCOPYASSIGNMOVE(netlist_object_t, delete) - netlist_state_t & state() noexcept; + netlist_state_t &state() noexcept; const netlist_state_t &state() const noexcept; - constexpr netlist_t & exec() noexcept { return m_netlist; } + constexpr netlist_t &exec() noexcept { return m_netlist; } constexpr const netlist_t &exec() const noexcept { return m_netlist; } // to ease template design template - device_arena::unique_ptr make_pool_object(Args &&...args) noexcept( - false) + device_arena::unique_ptr + make_pool_object(Args &&...args) noexcept(false) { return state().make_pool_object(std::forward(args)...); } @@ -174,13 +184,13 @@ namespace netlist::detail /// \brief returns reference to owning device. /// \returns reference to owning device. - core_device_t & device() noexcept { return *m_device; } + core_device_t &device() noexcept { return *m_device; } const core_device_t &device() const noexcept { return *m_device; } /// \brief The netlist owning the owner of this object. /// \returns reference to netlist object. - netlist_state_t & state() noexcept; + netlist_state_t &state() noexcept; const netlist_state_t &state() const noexcept; private: @@ -218,7 +228,7 @@ namespace netlist::detail static constexpr netlist_sig_t OUT_TRISTATE() { return INP_MASK; } static_assert(INP_BITS * 2 <= sizeof(netlist_sig_t) * 8, - "netlist_sig_t size not sufficient"); + "netlist_sig_t size not sufficient"); enum state_e { @@ -231,7 +241,7 @@ namespace netlist::detail }; core_terminal_t(core_device_t &dev, const pstring &aname, state_e state, - nl_delegate delegate); + nl_delegate delegate); virtual ~core_terminal_t() noexcept = default; PCOPYASSIGNMOVE(core_terminal_t, delete) @@ -271,12 +281,12 @@ namespace netlist::detail void reset() noexcept { - set_state( - is_type(terminal_type::OUTPUT) ? STATE_OUT : STATE_INP_ACTIVE); + set_state(is_type(terminal_type::OUTPUT) ? STATE_OUT + : STATE_INP_ACTIVE); } - constexpr void set_copied_input( - [[maybe_unused]] netlist_sig_t val) noexcept + constexpr void + set_copied_input([[maybe_unused]] netlist_sig_t val) noexcept { if constexpr (config::use_copy_instead_of_reference::value) { @@ -298,7 +308,7 @@ namespace netlist::detail private: nl_delegate m_delegate; - net_t * m_net; + net_t *m_net; state_var m_state; }; diff --git a/src/lib/netlist/core/core_device.h b/src/lib/netlist/core/core_device.h index 87391450787..305a5aed14e 100644 --- a/src/lib/netlist/core/core_device.h +++ b/src/lib/netlist/core/core_device.h @@ -33,7 +33,7 @@ namespace netlist friend class factory::device_element_t; friend class factory::library_element_t; - template + template friend struct sub_device_wrapper; friend class solver::matrix_solver_t; @@ -103,7 +103,7 @@ namespace netlist log_type &log(); public: - virtual void time_step([[maybe_unused]] time_step_type ts_type, + virtual void time_step([[maybe_unused]] detail::time_step_type ts_type, [[maybe_unused]] nl_fptype st) noexcept { } diff --git a/src/lib/netlist/core/device.h b/src/lib/netlist/core/device.h index 5f4a6937f23..12f3f7d174e 100644 --- a/src/lib/netlist/core/device.h +++ b/src/lib/netlist/core/device.h @@ -73,40 +73,42 @@ namespace netlist // FIXME: Rename // ------------------------------------------------------------------------- - template + template struct sub_device_wrapper { - using constructor_data_t = typename CX::constructor_data_t; - using constructor_param_t = typename CX::constructor_param_t; + using constructor_data_t = typename DEVICE::constructor_data_t; + using constructor_param_t = typename DEVICE::constructor_param_t; template sub_device_wrapper(base_device_t &owner, const pstring &name, - Args &&...args) + Args &&...args) { - // m_dev = owner.state().make_pool_object(owner, name, + // m_dev = owner.state().make_pool_object(owner, name, // std::forward(args)...); - m_dev = owner.state().make_pool_object( + m_dev = owner.state().make_pool_object( constructor_data_t{owner.state(), owner.name() + "." + name}, std::forward(args)...); - owner.state().register_device(m_dev->name(), + owner.state().register_device( + m_dev->name(), device_arena::owned_ptr(m_dev.get(), false)); } template sub_device_wrapper(device_t &owner, const pstring &name, Args &&...args) { - // m_dev = owner.state().make_pool_object(owner, name, + // m_dev = owner.state().make_pool_object(owner, name, // std::forward(args)...); - m_dev = owner.state().make_pool_object( + m_dev = owner.state().make_pool_object( constructor_data_t{owner.state(), owner.name() + "." + name}, std::forward(args)...); - owner.state().register_device(m_dev->name(), + owner.state().register_device( + m_dev->name(), device_arena::owned_ptr(m_dev.get(), false)); } - CX & operator()() { return *m_dev; } - const CX &operator()() const { return *m_dev; } + DEVICE & operator()() { return *m_dev; } + const DEVICE &operator()() const { return *m_dev; } private: - device_arena::unique_ptr m_dev; + device_arena::unique_ptr m_dev; }; } // namespace netlist diff --git a/src/lib/netlist/core/device_macros.h b/src/lib/netlist/core/device_macros.h index af1fb15e78f..8f46f036412 100644 --- a/src/lib/netlist/core/device_macros.h +++ b/src/lib/netlist/core/device_macros.h @@ -107,7 +107,7 @@ public: \ #define NETLIB_TIMESTEPI() \ public: \ - virtual void time_step(time_step_type ts_type, \ + virtual void time_step(detail::time_step_type ts_type, \ nl_fptype step) noexcept override /// \brief Used to implement the body of the time stepping code. @@ -119,7 +119,7 @@ public: \ /// \param cname Name of object as given to \ref NETLIB_OBJECT /// #define NETLIB_TIMESTEP(cname) \ - void NETLIB_NAME(cname)::time_step(time_step_type ts_type, \ + void NETLIB_NAME(cname)::time_step(detail::time_step_type ts_type, \ nl_fptype step) noexcept //#define NETLIB_DELEGATE(name) nl_delegate(&this_type :: name, this) diff --git a/src/lib/netlist/core/logic_family.h b/src/lib/netlist/core/logic_family.h index 97084dd4dc0..216e74ead2a 100644 --- a/src/lib/netlist/core/logic_family.h +++ b/src/lib/netlist/core/logic_family.h @@ -10,6 +10,8 @@ #include "../nltypes.h" +#include "../plib/palloc.h" +#include "../plib/pmempool.h" #include "../plib/pstring.h" namespace netlist diff --git a/src/lib/netlist/core/netlist_state.h b/src/lib/netlist/core/netlist_state.h index f8a87b9280f..505665d9acf 100644 --- a/src/lib/netlist/core/netlist_state.h +++ b/src/lib/netlist/core/netlist_state.h @@ -12,6 +12,7 @@ #include "queue.h" #include "../plib/plists.h" +#include "../plib/pmempool.h" #include "../plib/pstate.h" #include "../plib/pstring.h" @@ -31,8 +32,8 @@ namespace netlist public: using nets_collection_type = std::vector< device_arena::owned_ptr>; - using family_collection_type = std::unordered_map>; + using family_collection_type = std::unordered_map< + pstring, host_arena::unique_ptr>; // need to preserve order of device creation ... using devices_collection_type = std::vector< @@ -55,8 +56,9 @@ namespace netlist return bool(plib::dynamic_downcast(p)); } - core_device_t *get_single_device(const pstring &classname, - bool (*cc)(core_device_t *)) const noexcept(false); + core_device_t * + get_single_device(const pstring &classname, + bool (*cc)(core_device_t *)) const noexcept(false); /// \brief Get single device filtered by class and name /// @@ -91,7 +93,7 @@ namespace netlist // logging - log_type & log() noexcept { return m_log; } + log_type &log() noexcept { return m_log; } const log_type &log() const noexcept { return m_log; } plib::dynamic_library_base &static_solver_lib() const noexcept @@ -108,23 +110,23 @@ namespace netlist void set_static_solver_lib( std::unique_ptr &&lib); - netlist_t & exec() noexcept { return *m_netlist; } + netlist_t &exec() noexcept { return *m_netlist; } const netlist_t &exec() const noexcept { return *m_netlist; } // state handling plib::state_manager_t &run_state_manager() noexcept { return m_state; } template - void save(O &owner, C &state, const pstring &module, - const pstring &stname) + void + save(O &owner, C &state, const pstring &module, const pstring &stname) { this->run_state_manager().save_item(plib::void_ptr_cast(&owner), - state, module + "." + stname); + state, module + "." + stname); } template void save(O &owner, C *state, const pstring &module, - const pstring &stname, const std::size_t count) + const pstring &stname, const std::size_t count) { this->run_state_manager().save_state_ptr( plib::void_ptr_cast(&owner), module + "." + stname, @@ -165,8 +167,8 @@ namespace netlist /// \param dev Device to be registered template - void register_device(const pstring &name, - device_arena::owned_ptr && dev) noexcept(false) + void register_device(const pstring &name, + device_arena::owned_ptr &&dev) noexcept(false) { for (auto &d : m_devices) if (d.first == name) @@ -187,11 +189,11 @@ namespace netlist /// \param dev Device to be registered template - void register_device(const pstring &name, - device_arena::unique_ptr && dev) + void + register_device(const pstring &name, device_arena::unique_ptr &&dev) { - register_device(name, device_arena::owned_ptr(dev.release(), - true, dev.get_deleter())); + register_device(name, device_arena::owned_ptr( + dev.release(), true, dev.get_deleter())); } /// \brief Remove device @@ -203,24 +205,24 @@ namespace netlist void remove_device(core_device_t *dev); - setup_t & setup() noexcept { return *m_setup; } + setup_t &setup() noexcept { return *m_setup; } const setup_t &setup() const noexcept { return *m_setup; } - nlparse_t & parser() noexcept; + nlparse_t &parser() noexcept; const nlparse_t &parser() const noexcept; // FIXME: make a post load member and include code there void rebuild_lists(); // must be called after post_load ! - static void compile_defines( - std::vector> &defs); + static void + compile_defines(std::vector> &defs); static pstring version(); static pstring version_patchlevel(); - nets_collection_type & nets() noexcept { return m_nets; } + nets_collection_type &nets() noexcept { return m_nets; } const nets_collection_type &nets() const noexcept { return m_nets; } - devices_collection_type & devices() noexcept { return m_devices; } + devices_collection_type &devices() noexcept { return m_devices; } const devices_collection_type &devices() const noexcept { return m_devices; @@ -234,13 +236,13 @@ namespace netlist return plib::make_unique(m_pool, std::forward(args)...); } // memory pool - still needed in some places - device_arena & pool() noexcept { return m_pool; } + device_arena &pool() noexcept { return m_pool; } const device_arena &pool() const noexcept { return m_pool; } struct stats_info { - const detail::queue_t & m_queue; // performance - const plib::pperftime_t & m_stat_mainloop; + const detail::queue_t &m_queue; // performance + const plib::pperftime_t &m_stat_mainloop; const plib::pperfcount_t &m_perf_out_processed; }; @@ -256,8 +258,8 @@ namespace netlist /// void free_setup_resources(); #if !(NL_USE_INPLACE_CORE_TERMS) - std::vector &core_terms( - const detail::net_t &net) + std::vector & + core_terms(const detail::net_t &net) { return m_core_terms[&net]; } @@ -281,7 +283,7 @@ namespace netlist #if !(NL_USE_INPLACE_CORE_TERMS) // all terms for a net std::unordered_map> + std::vector> m_core_terms; #endif // dummy version diff --git a/src/lib/netlist/core/object_array.h b/src/lib/netlist/core/object_array.h index 08b66a64990..cf1bc5ea4af 100644 --- a/src/lib/netlist/core/object_array.h +++ b/src/lib/netlist/core/object_array.h @@ -8,8 +8,12 @@ #ifndef NL_CORE_OBJECT_ARRAY_H_ #define NL_CORE_OBJECT_ARRAY_H_ +#include "base_objects.h" +#include "logic.h" + #include "../nltypes.h" +#include "../plib/pfmtlog.h" #include "../plib/plists.h" #include "../plib/pstring.h" diff --git a/src/lib/netlist/core/state_var.h b/src/lib/netlist/core/state_var.h index 7c6e7aec8be..a2b0ae5f477 100644 --- a/src/lib/netlist/core/state_var.h +++ b/src/lib/netlist/core/state_var.h @@ -10,6 +10,7 @@ #include "../nltypes.h" +#include "../plib/pfmtlog.h" #include "../plib/pstring.h" namespace netlist diff --git a/src/lib/netlist/devices/nld_4013.cpp b/src/lib/netlist/devices/nld_4013.cpp index 30ddb2d63d1..5fa3aa25586 100644 --- a/src/lib/netlist/devices/nld_4013.cpp +++ b/src/lib/netlist/devices/nld_4013.cpp @@ -78,7 +78,7 @@ namespace netlist::devices { } else { - newstate_setreset(set, reset); + set_reset(set, reset); m_CLK.inactivate(); m_D.inactivate(); } @@ -86,7 +86,7 @@ namespace netlist::devices { NETLIB_HANDLERI(clk) { - newstate_clk(m_nextD); + set_output(m_nextD); m_CLK.inactivate(); } @@ -101,14 +101,14 @@ namespace netlist::devices { nld_power_pins m_power_pins; - void newstate_clk(const netlist_sig_t stateQ) + void set_output(const netlist_sig_t stateQ) { - static constexpr auto delay = NLTIME_FROM_NS(150); + static constexpr const auto delay = NLTIME_FROM_NS(150); m_Q.push(stateQ, delay); m_QQ.push(!stateQ, delay); } - void newstate_setreset(const netlist_sig_t stateQ, const netlist_sig_t stateQQ) + void set_reset(const netlist_sig_t stateQ, const netlist_sig_t stateQQ) { // Q: 150 ns, QQ: 200 ns static constexpr const std::array delay = { NLTIME_FROM_NS(150), NLTIME_FROM_NS(200) }; diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h index d06d3767bd9..d191a4537ba 100644 --- a/src/lib/netlist/nl_base.h +++ b/src/lib/netlist/nl_base.h @@ -17,6 +17,7 @@ namespace netlist { // nothing in here. This should not change. + } // namespace netlist #endif // NLBASE_H_ diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h index 01bc99dc706..7306de88cde 100644 --- a/src/lib/netlist/nl_config.h +++ b/src/lib/netlist/nl_config.h @@ -134,7 +134,7 @@ namespace netlist /// brief default minimum alignment of mempool_arena /// /// 256 is the best compromise between logic applications like MAME - /// TTL games (e.g. pong) and analog applications like e.g. kidnikik + /// TTL games (e.g. pong) and analog applications like e.g. kidniki /// sound. /// /// Best performance for pong is achieved with a value of 16, but this @@ -178,7 +178,7 @@ namespace netlist /// | 63 | 1,000,000,000,000 | 9,223,372 | 107| 0.3 | /// using INTERNAL_RES = std::integral_constant; // NOLINT + 10'000'000'000LL>; // NOLINT /// \brief Recommended clock to be used /// @@ -187,7 +187,7 @@ namespace netlist /// contains code illustrating how to deal with remainders if \ref /// INTERNAL_RES is bigger than NETLIST_CLOCK. using DEFAULT_CLOCK = std::integral_constant; // NOLINT + 1'000'000'000>; // NOLINT /// \brief Default logic family /// @@ -196,27 +196,27 @@ namespace netlist /// \brief Maximum queue size /// using max_queue_size = std::integral_constant; // NOLINT + 1024>; // NOLINT /// \brief Maximum queue size for solvers /// using max_solver_queue_size = std::integral_constant; // NOLINT + 512>; // NOLINT /// \brief Support float type for matrix calculations. /// /// Defaults to NL_USE_ACADEMIC_SOLVERS to provide faster build times - using use_float_matrix = std::integral_constant; + using use_float_matrix = std::integral_constant< + bool, NL_USE_ACADEMIC_SOLVERS>; /// \brief Support long double type for matrix calculations. /// /// Defaults to NL_USE_ACADEMIC_SOLVERS to provide faster build times - using use_long_double_matrix = std::integral_constant; + using use_long_double_matrix = std::integral_constant< + bool, NL_USE_ACADEMIC_SOLVERS>; using use_float128_matrix = std::integral_constant; + NL_USE_FLOAT128>; /// \brief Floating point types used /// @@ -242,7 +242,7 @@ namespace netlist /// the default approach. It is ~20% slower. /// using use_copy_instead_of_reference = std::integral_constant; + false>; /// \brief Avoid unnecessary queue pushes /// @@ -416,16 +416,4 @@ namespace netlist #endif } // namespace netlist -//============================================================ -// Asserts -//============================================================ - -#define nl_assert(x) \ - do \ - { \ - if (NL_DEBUG) \ - passert_always(x); \ - } while (0) -#define nl_assert_always(x, msg) passert_always_msg(x, msg) - #endif // NLCONFIG_H_ diff --git a/src/lib/netlist/nl_errstr.h b/src/lib/netlist/nl_errstr.h index 46f2ac3e5e1..c65ff257846 100644 --- a/src/lib/netlist/nl_errstr.h +++ b/src/lib/netlist/nl_errstr.h @@ -8,13 +8,53 @@ #ifndef NL_ERRSTR_H_ #define NL_ERRSTR_H_ +#include "plib/pexception.h" #include "plib/pfmtlog.h" namespace netlist { - static constexpr const char sHINT_NO_DEACTIVATE[] = ".HINT_NO_DEACTIVATE"; // NOLINT(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays) - static constexpr const char sHINT_NC[] = ".HINT_NC"; // NOLINT(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays) + static constexpr const char sHINT_NO_DEACTIVATE[] + = ".HINT_NO_DEACTIVATE"; // NOLINT(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays) + static constexpr const char sHINT_NC[] + = ".HINT_NC"; // NOLINT(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays) + + // ------------------------------------------------------------------------- + // Exceptions + // ------------------------------------------------------------------------- + + /// \brief Generic netlist exception. + /// The exception is used in all events which are considered fatal. + + class nl_exception : public plib::pexception + { + public: + /// \brief Constructor. + /// Allows a descriptive text to be passed to the exception + + explicit nl_exception(const pstring &text //!< text to be passed + ) + : plib::pexception(text) + { + } + + /// \brief Constructor. + /// Allows to use \ref plib::pfmt logic to be used in exception + + template + explicit nl_exception(const pstring &fmt, //!< format to be used + Args &&...args //!< arguments to be passed + ) + : plib::pexception(plib::pfmt(fmt)(std::forward(args)...)) + { + } + }; + + // ------------------------------------------------------------------------- + // Error messages + // ------------------------------------------------------------------------- + + // clang-format off // nl_base.cpp @@ -187,9 +227,19 @@ namespace netlist PERRMSGV(MF_FILE_OPEN_ERROR, 1, "Error opening file: {1}") - - + // clang-format on } // namespace netlist +// ------------------------------------------------------------------------- +// Asserts +// ------------------------------------------------------------------------- + +#define nl_assert(x) \ + do \ + { \ + if (NL_DEBUG) \ + passert_always(x); \ + } while (0) +#define nl_assert_always(x, msg) passert_always_msg(x, msg) #endif // NL_ERRSTR_H_ diff --git a/src/lib/netlist/nl_setup.h b/src/lib/netlist/nl_setup.h index 7c5cc2e7930..31e971026e9 100644 --- a/src/lib/netlist/nl_setup.h +++ b/src/lib/netlist/nl_setup.h @@ -8,14 +8,14 @@ #ifndef NLSETUP_H_ #define NLSETUP_H_ +#include "nl_config.h" +#include "nltypes.h" + #include "plib/ppreprocessor.h" #include "plib/psource.h" #include "plib/pstream.h" #include "plib/pstring.h" -#include "nl_config.h" -#include "nltypes.h" - #include #include #include @@ -26,118 +26,95 @@ // MACROS - netlist definitions //============================================================ -#define NET_STR(x) # x +#define NET_STR(x) #x -#define NET_MODEL(model) \ - setup.register_model(model); +#define NET_MODEL(model) setup.register_model(model); -#define ALIAS(alias, name) \ - setup.register_alias(# alias, # name); +#define ALIAS(alias, name) setup.register_alias(#alias, #name); #define DIPPINS(pin1, ...) \ - setup.register_dip_alias_arr( # pin1 ", " # __VA_ARGS__); + setup.register_dip_alias_arr(#pin1 ", " #__VA_ARGS__); // to be used to reference new library truth table devices -#define NET_REGISTER_DEV(type, name) \ - setup.register_dev(# type, # name); +#define NET_REGISTER_DEV(type, name) setup.register_dev(#type, #name); // name is first element so that __VA_ARGS__ always has one element -#define NET_REGISTER_DEVEXT(type, ...) \ - setup.register_dev(# type, { PSTRINGIFY_VA(__VA_ARGS__) }); +#define NET_REGISTER_DEVEXT(type, ...) \ + setup.register_dev(#type, {PSTRINGIFY_VA(__VA_ARGS__)}); #define NET_CONNECT(name, input, output) \ - setup.register_link(# name "." # input, # output); + setup.register_link(#name "." #input, #output); #define NET_C(term1, ...) \ - setup.register_connection_arr( # term1 ", " # __VA_ARGS__); + setup.register_connection_arr(#term1 ", " #__VA_ARGS__); -#define PARAM(name, val) \ - setup.register_param(NET_STR(name), NET_STR(val)); +#define PARAM(name, val) setup.register_param(NET_STR(name), NET_STR(val)); #define DEFPARAM(name, val) \ - setup.register_default_param(NET_STR(name), NET_STR(val)); + setup.register_default_param(NET_STR(name), NET_STR(val)); -#define HINT(name, val) \ - setup.register_hint(# name , ".HINT_" # val); +#define HINT(name, val) setup.register_hint(#name, ".HINT_" #val); #define NETDEV_PARAMI(name, param, val) \ - setup.register_param(# name "." # param, val); + setup.register_param(#name "." #param, val); -#define NETLIST_NAME(name) netlist ## _ ## name +#define NETLIST_NAME(name) netlist##_##name #define NETLIST_EXTERNAL(name) \ - void NETLIST_NAME(name)(netlist::nlparse_t &setup); + void NETLIST_NAME(name)(netlist::nlparse_t & setup); #define NETLIST_START(name) \ -void NETLIST_NAME(name)([[maybe_unused]] netlist::nlparse_t &setup) \ + void NETLIST_NAME(name)([[maybe_unused]] netlist::nlparse_t & setup) #define LOCAL_SOURCE(name) \ - setup.register_source_proc(# name, &NETLIST_NAME(name)); + setup.register_source_proc(#name, &NETLIST_NAME(name)); #define EXTERNAL_SOURCE(name) \ - setup.register_source_proc(# name, &NETLIST_NAME(name)); + setup.register_source_proc(#name, &NETLIST_NAME(name)); #define LOCAL_LIB_ENTRY_2(type, name) \ - type ## _SOURCE(name) \ - setup.register_lib_entry(# name, "", PSOURCELOC()); + type##_SOURCE(name) setup.register_lib_entry(#name, "", PSOURCELOC()); #define LOCAL_LIB_ENTRY_3(type, name, param_spec) \ - type ## _SOURCE(name) \ - setup.register_lib_entry(# name, param_spec, PSOURCELOC()); + type##_SOURCE(name) \ + setup.register_lib_entry(#name, param_spec, PSOURCELOC()); #define LOCAL_LIB_ENTRY(...) PCALLVARARG(LOCAL_LIB_ENTRY_, LOCAL, __VA_ARGS__) -#define EXTERNAL_LIB_ENTRY(...) PCALLVARARG(LOCAL_LIB_ENTRY_, EXTERNAL, __VA_ARGS__) +#define EXTERNAL_LIB_ENTRY(...) \ + PCALLVARARG(LOCAL_LIB_ENTRY_, EXTERNAL, __VA_ARGS__) -#define INCLUDE(name) \ - setup.include(# name); +#define INCLUDE(name) setup.include(#name); #define SUBMODEL(model, name) \ - setup.namespace_push(# name); \ - setup.include(# model); \ - setup.namespace_pop(); + setup.namespace_push(#name); \ + setup.include(#model); \ + setup.namespace_pop(); #define OPTIMIZE_FRONTIER(attach, r_in, r_out) \ - setup.register_frontier(# attach, PSTRINGIFY_VA(r_in), PSTRINGIFY_VA(r_out)); + setup.register_frontier(#attach, PSTRINGIFY_VA(r_in), PSTRINGIFY_VA(r_out)); // ----------------------------------------------------------------------------- // truth table defines // ----------------------------------------------------------------------------- -#if 0 -#define TRUTHTABLE_START(cname, in, out, pdef_params) \ - void NETLIST_NAME(cname ## _impl)(netlist::tt_desc &desc); \ - static NETLIST_START(cname) -{ \ - netlist::tt_desc xdesc{ #cname, in, out, "" }; \ - auto sloc = PSOURCELOC(); \ - const pstring def_params = pdef_params; \ - NETLIST_NAME(cname ## _impl)(xdesc); \ - setup.truth_table_create(xdesc, def_params, std::move(sloc)); \ - } \ - static void NETLIST_NAME(cname ## _impl)(netlist::tt_desc &desc) \ - { -#else -#define TRUTH_TABLE(cname, in, out, pdef_params) \ - void NETLIST_NAME(cname ## _impl)(netlist::nlparse_t &setup, netlist::tt_desc &desc); \ - static void NETLIST_NAME(cname)(netlist::nlparse_t &setup) \ - { \ - netlist::tt_desc desc{ #cname, in, out, "", {} }; \ - NETLIST_NAME(cname ## _impl)(setup, desc); \ - setup.truth_table_create(desc, pdef_params, PSOURCELOC()); \ - } \ - static void NETLIST_NAME(cname ## _impl)([[maybe_unused]] netlist::nlparse_t &setup, netlist::tt_desc &desc) \ +#define TRUTH_TABLE(cname, in, out, params) \ + void NETLIST_NAME(cname##_impl)(netlist::nlparse_t & setup, \ + netlist::tt_desc & desc); \ + static void NETLIST_NAME(cname)(netlist::nlparse_t & setup) \ + { \ + netlist::tt_desc desc{#cname, in, out, "", {}}; \ + NETLIST_NAME(cname##_impl)(setup, desc); \ + setup.truth_table_create(desc, params, PSOURCELOC()); \ + } \ + static void NETLIST_NAME(cname##_impl)( \ + [[maybe_unused]] netlist::nlparse_t & setup, netlist::tt_desc & desc) -#endif +#define TT_HEAD(x) desc.desc.emplace_back(x); -#define TT_HEAD(x) \ - desc.desc.emplace_back(x); +#define TT_LINE(x) desc.desc.emplace_back(x); -#define TT_LINE(x) \ - desc.desc.emplace_back(x); - -#define TT_FAMILY(x) \ - desc.family = x; +#define TT_FAMILY(x) desc.family = x; #define TRUTHTABLE_ENTRY(name) \ LOCAL_SOURCE(name) \ @@ -152,10 +129,10 @@ namespace netlist struct tt_desc { - pstring name; - unsigned long ni; - unsigned long no; - pstring family; + pstring name; + unsigned long ni; + unsigned long no; + pstring family; std::vector desc; }; @@ -193,25 +170,29 @@ namespace netlist /// \param type the alias type see \ref alias_type /// \param alias the alias to be qualified /// \param points_to the pin aliased - void register_alias(detail::alias_type type, const pstring &alias, const pstring &points_to); + void register_alias(detail::alias_type type, const pstring &alias, + const pstring &points_to); /// \brief Register an aliases where alias and references are fully qualified names /// \param type the alias type see \ref alias_type /// \param alias the alias to be qualified /// \param points_to the pin aliased - void register_fqn_alias(detail::alias_type type, const pstring &alias, const pstring &points_to); + void register_fqn_alias(detail::alias_type type, const pstring &alias, + const pstring &points_to); void register_dip_alias_arr(const pstring &terms); // last argument only needed by nltool void register_dev(const pstring &classname, const pstring &name, - const std::vector ¶ms_and_connections, - factory::element_t **factory_element = nullptr); - void register_dev(const pstring &classname, std::initializer_list more_parameters); + const std::vector ¶ms_and_connections, + factory::element_t **factory_element = nullptr); + void register_dev(const pstring &classname, + std::initializer_list more_parameters); void register_dev(const pstring &classname, const pstring &name) { register_dev(classname, name, std::vector()); } - void register_hint(const pstring &object_name, const pstring &hint_name); + void + register_hint(const pstring &object_name, const pstring &hint_name); void register_connection(const pstring &sin, const pstring &sout); void register_connection_arr(const pstring &terms); @@ -230,20 +211,23 @@ namespace netlist register_param_fp(param, plib::narrow_cast(value)); } - void register_lib_entry(const pstring &name, const pstring &def_params, plib::source_location &&loc); + void register_lib_entry(const pstring &name, const pstring &def_params, + plib::source_location &&loc); - void register_frontier(const pstring &attach, const pstring &r_IN, const pstring &r_OUT); + void register_frontier(const pstring &attach, const pstring &r_IN, + const pstring &r_OUT); // register a source template - void register_source(Args&&... args) + void register_source(Args &&...args) { m_sources.add_source(std::forward(args)...); } void register_source_proc(const pstring &name, nlsetup_func func); - void truth_table_create(tt_desc &desc, const pstring &def_params, plib::source_location &&loc); + void truth_table_create(tt_desc &desc, const pstring &def_params, + plib::source_location &&loc); // include other files @@ -256,17 +240,18 @@ namespace netlist // FIXME: used by source_t - need a different approach at some time bool parse_stream(plib::istream_uptr &&in_stream, const pstring &name); - bool parse_tokens(const plib::detail::token_store_t &tokens, const pstring &name); + bool parse_tokens(const plib::detail::token_store_t &tokens, + const pstring &name); template - void add_include(Args&&... args) + void add_include(Args &&...args) { m_includes.add_source(std::forward(args)...); } void add_define(const pstring &def, const pstring &val) { - m_defines.insert({ def, plib::ppreprocessor::define_t(def, val)}); + m_defines.insert({def, plib::ppreprocessor::define_t(def, val)}); } void add_define(const pstring &define); @@ -274,10 +259,10 @@ namespace netlist // register a list of logs void register_dynamic_log_devices(const std::vector &log_list); - factory::list_t &factory() noexcept; + factory::list_t &factory() noexcept; const factory::list_t &factory() const noexcept; - log_type &log() noexcept { return m_log; } + log_type &log() noexcept { return m_log; } const log_type &log() const noexcept { return m_log; } plib::istream_uptr get_data_stream(const pstring &name); @@ -285,23 +270,22 @@ namespace netlist private: pstring namespace_prefix() const; pstring build_fqn(const pstring &obj_name) const; - void register_param_fp(const pstring ¶m, nl_fptype value); - bool device_exists(const pstring &name) const; + void register_param_fp(const pstring ¶m, nl_fptype value); + bool device_exists(const pstring &name) const; // FIXME: stale? - remove later void remove_connections(const pstring &pin); - plib::ppreprocessor::defines_map_type m_defines; - plib::psource_collection_t m_includes; - std::stack m_namespace_stack; - plib::psource_collection_t m_sources; - detail::abstract_t & m_abstract; + plib::ppreprocessor::defines_map_type m_defines; + plib::psource_collection_t m_includes; + std::stack m_namespace_stack; + plib::psource_collection_t m_sources; + detail::abstract_t &m_abstract; log_type &m_log; - unsigned m_frontier_cnt; + unsigned m_frontier_cnt; }; } // namespace netlist - #endif // NLSETUP_H_ diff --git a/src/lib/netlist/nltypes.h b/src/lib/netlist/nltypes.h index 15cd65a9471..e6a74db1c9d 100644 --- a/src/lib/netlist/nltypes.h +++ b/src/lib/netlist/nltypes.h @@ -14,9 +14,6 @@ #include "nl_config.h" -#include "plib/pmempool.h" -#include "plib/ppmf.h" -#include "plib/pstring.h" #include "plib/ptime.h" #include "plib/ptypes.h" @@ -170,12 +167,12 @@ namespace netlist /// /// \note This is not the right location yet. /// - using device_arena = std::conditional_t< config::use_mempool::value, plib::mempool_arena, config::mempool_align::value>, plib::aligned_arena<>>; + using host_arena = plib::aligned_arena<>; using log_type = plib::plog_base; @@ -184,25 +181,19 @@ namespace netlist // Types needed by various includes //============================================================ - /// \brief Time step type. - /// - /// May be either FORWARD or RESTORE - /// - enum class time_step_type - { - FORWARD, //!< forward time - RESTORE //!< restore state before last forward - }; - - /// \brief Delegate type for device notification. - /// - using nl_delegate = plib::pmfp; - using nl_delegate_ts = plib::pmfp; - using nl_delegate_dyn = plib::pmfp; - namespace detail { + /// \brief Time step type. + /// + /// May be either FORWARD or RESTORE + /// + enum class time_step_type + { + FORWARD, //!< forward time + RESTORE //!< restore state before last forward + }; + /// \brief Enum specifying the type of object /// enum class terminal_type @@ -220,10 +211,10 @@ namespace netlist /// enum class alias_type { - UNKNOWN, //!< Used as a placeholder during code changes - INTERNAL, //!< the alias references a internal pin - FUNCTIONAL, //!< Used for aliases e.g. in BJTs : ALIAS("B", - //!< somesub.p()) + UNKNOWN, //!< Used as a placeholder during code changes + INTERNAL, //!< the alias references a internal pin + FUNCTIONAL, //!< Used for aliases e.g. in BJTs : ALIAS("B", + //!< somesub.p()) PACKAGE_PIN, //!< the alias references a package pin, e.g. ALIAS(13, //!< B.CLK) READABILITY, //!< the alias is used to improved readability, e.g. @@ -317,37 +308,6 @@ namespace netlist using desc_const_t = std::integral_constant; }; - //============================================================ - // Exceptions - //============================================================ - - /// \brief Generic netlist exception. - /// The exception is used in all events which are considered fatal. - - class nl_exception : public plib::pexception - { - public: - /// \brief Constructor. - /// Allows a descriptive text to be passed to the exception - - explicit nl_exception(const pstring &text //!< text to be passed - ) - : plib::pexception(text) - { - } - - /// \brief Constructor. - /// Allows to use \ref plib::pfmt logic to be used in exception - - template - explicit nl_exception(const pstring &fmt, //!< format to be used - Args &&...args //!< arguments to be passed - ) - : plib::pexception(plib::pfmt(fmt)(std::forward(args)...)) - { - } - }; - } // namespace netlist #endif // NLTYPES_H_ diff --git a/src/lib/netlist/plib/pmath.h b/src/lib/netlist/plib/pmath.h index 311a928a597..96f815bcca7 100644 --- a/src/lib/netlist/plib/pmath.h +++ b/src/lib/netlist/plib/pmath.h @@ -9,6 +9,7 @@ /// #include "pconfig.h" +#include "pgsl.h" #include "ptypes.h" #include @@ -271,8 +272,7 @@ namespace plib /// FIXME: limited implementation /// template - static inline - auto pow(T1 v, T2 p) noexcept -> decltype(std::pow(v, p)) + static inline auto pow(T1 v, T2 p) noexcept -> decltype(std::pow(v, p)) { return std::pow(v, p); } @@ -283,60 +283,30 @@ namespace plib return constants::one() / v; } - static FLOAT128 abs(FLOAT128 v) noexcept - { - return fabsq(v); - } + static FLOAT128 abs(FLOAT128 v) noexcept { return fabsq(v); } - static FLOAT128 sqrt(FLOAT128 v) noexcept - { - return sqrtq(v); - } + static FLOAT128 sqrt(FLOAT128 v) noexcept { return sqrtq(v); } static FLOAT128 hypot(FLOAT128 v1, FLOAT128 v2) noexcept { return hypotq(v1, v2); } - static FLOAT128 exp(FLOAT128 v) noexcept - { - return expq(v); - } + static FLOAT128 exp(FLOAT128 v) noexcept { return expq(v); } - static FLOAT128 log(FLOAT128 v) noexcept - { - return logq(v); - } + static FLOAT128 log(FLOAT128 v) noexcept { return logq(v); } - static FLOAT128 tanh(FLOAT128 v) noexcept - { - return tanhq(v); - } + static FLOAT128 tanh(FLOAT128 v) noexcept { return tanhq(v); } - static FLOAT128 floor(FLOAT128 v) noexcept - { - return floorq(v); - } + static FLOAT128 floor(FLOAT128 v) noexcept { return floorq(v); } - static FLOAT128 log1p(FLOAT128 v) noexcept - { - return log1pq(v); - } + static FLOAT128 log1p(FLOAT128 v) noexcept { return log1pq(v); } - static FLOAT128 sin(FLOAT128 v) noexcept - { - return sinq(v); - } + static FLOAT128 sin(FLOAT128 v) noexcept { return sinq(v); } - static FLOAT128 cos(FLOAT128 v) noexcept - { - return cosq(v); - } + static FLOAT128 cos(FLOAT128 v) noexcept { return cosq(v); } - static FLOAT128 trunc(FLOAT128 v) noexcept - { - return truncq(v); - } + static FLOAT128 trunc(FLOAT128 v) noexcept { return truncq(v); } template static FLOAT128 pow(FLOAT128 v, T p) noexcept @@ -346,8 +316,8 @@ namespace plib static FLOAT128 pow(FLOAT128 v, int p) noexcept { - if (p==2) - return v*v; + if (p == 2) + return v * v; else return powq(v, static_cast(p)); } @@ -364,7 +334,7 @@ namespace plib constexpr bool is_pow2(T v) noexcept { static_assert(is_integral::value, "is_pow2 needs integer arguments"); - return !(v & (v-1)); + return !(v & (v - 1)); } /// \brief return absolute value of signed argument @@ -373,9 +343,9 @@ namespace plib /// \param v argument /// \return absolute value of argument /// - template - constexpr - std::enable_if_t::value && plib::is_signed::value, T> + template + constexpr std::enable_if_t< + plib::is_integral::value && plib::is_signed::value, T> abs(T v) noexcept { return v < 0 ? -v : v; @@ -387,9 +357,9 @@ namespace plib /// \param v argument /// \return argument since it has no sign /// - template - constexpr - std::enable_if_t::value && plib::is_unsigned::value, T> + template + constexpr std::enable_if_t< + plib::is_integral::value && plib::is_unsigned::value, T> abs(T v) noexcept { return v; @@ -406,16 +376,14 @@ namespace plib /// \param n first argument /// \return greatest common denominator of m and n /// - template + template constexpr typename std::common_type::type - gcd(M m, N n) noexcept //NOLINT(misc-no-recursion) + gcd(M m, N n) noexcept // NOLINT(misc-no-recursion) { static_assert(plib::is_integral::value, "gcd: M must be an integer"); static_assert(plib::is_integral::value, "gcd: N must be an integer"); - return m == 0 ? plib::abs(n) - : n == 0 ? plib::abs(m) - : gcd(n, m % n); + return m == 0 ? plib::abs(n) : n == 0 ? plib::abs(m) : gcd(n, m % n); } /// \brief return least common multiple @@ -429,24 +397,25 @@ namespace plib /// \param n first argument /// \return least common multiple of m and n /// - template - constexpr typename std::common_type::type - lcm(M m, N n) noexcept + template + constexpr typename std::common_type::type lcm(M m, N n) noexcept { static_assert(plib::is_integral::value, "lcm: M must be an integer"); static_assert(plib::is_integral::value, "lcm: N must be an integer"); - return (m != 0 && n != 0) ? (plib::abs(m) / gcd(m, n)) * plib::abs(n) : 0; + return (m != 0 && n != 0) ? (plib::abs(m) / gcd(m, n)) * plib::abs(n) + : 0; } - template - constexpr const T& clamp( const T& v, const T& low, const T& high) + template + constexpr const T &clamp(const T &v, const T &low, const T &high) { gsl_Expects(high >= low); return (v < low) ? low : (high < v) ? high : v; } - static_assert(noexcept(constants::one()), "Not evaluated as constexpr"); + static_assert(noexcept(constants::one()), + "Not evaluated as constexpr"); } // namespace plib diff --git a/src/lib/netlist/solver/nld_matrix_solver.cpp b/src/lib/netlist/solver/nld_matrix_solver.cpp index a918aac1c58..d382da0f7d5 100644 --- a/src/lib/netlist/solver/nld_matrix_solver.cpp +++ b/src/lib/netlist/solver/nld_matrix_solver.cpp @@ -7,35 +7,40 @@ // Specific technical terms // spell-checker: words vsolver -#include "nld_solver.h" -#include "core/setup.h" -#include "nl_setup.h" #include "nld_matrix_solver.h" + +#include "nl_setup.h" +#include "nld_solver.h" + +#include "core/setup.h" + #include "plib/putil.h" namespace netlist::solver { - terms_for_net_t::terms_for_net_t(arena_type &arena, analog_net_t * net) - : m_nz(arena) - , m_nzrd(arena) - , m_nzbd(arena) - , m_connected_net_idx(arena) - , m_terms(arena) - , m_net(net) - , m_rail_start(0) + terms_for_net_t::terms_for_net_t(arena_type &arena, analog_net_t *net) + : m_nz(arena) + , m_nzrd(arena) + , m_nzbd(arena) + , m_connected_net_idx(arena) + , m_terms(arena) + , m_net(net) + , m_rail_start(0) { } - void terms_for_net_t::add_terminal(terminal_t *term, int net_other, bool sorted) + void + terms_for_net_t::add_terminal(terminal_t *term, int net_other, bool sorted) { if (sorted) - for (std::size_t i=0; i < m_connected_net_idx.size(); i++) + for (std::size_t i = 0; i < m_connected_net_idx.size(); i++) { if (m_connected_net_idx[i] > net_other) { plib::container::insert_at(m_terms, i, term); - plib::container::insert_at(m_connected_net_idx, i, net_other); + plib::container::insert_at(m_connected_net_idx, i, + net_other); return; } } @@ -47,34 +52,36 @@ namespace netlist::solver // matrix_solver // ---------------------------------------------------------------------------------------- - matrix_solver_t::matrix_solver_t(devices::nld_solver &main_solver, const pstring &name, - const net_list_t &nets, - const solver::solver_parameters_t *params) - //: device_t(static_cast(main_solver), name) - : device_t(device_data_t{main_solver.state(), main_solver.name() + "." + name}) - , m_params(*params) - , m_gonn(m_arena) - , m_gtn(m_arena) - , m_Idrn(m_arena) - , m_connected_net_Vn(m_arena) - , m_iterative_fail(*this, "m_iterative_fail", 0) - , m_iterative_total(*this, "m_iterative_total", 0) - , m_main_solver(main_solver) - , m_stat_calculations(*this, "m_stat_calculations", 0) - , m_stat_newton_raphson(*this, "m_stat_newton_raphson", 0) - , m_stat_newton_raphson_fail(*this, "m_stat_newton_raphson_fail", 0) - , m_stat_vsolver_calls(*this, "m_stat_vsolver_calls", 0) - , m_last_step(*this, "m_last_step", netlist_time_ext::zero()) - , m_step_funcs(m_arena) - , m_dynamic_funcs(m_arena) - , m_inputs(m_arena) - , m_ops(0) + matrix_solver_t::matrix_solver_t(devices::nld_solver &main_solver, + const pstring &name, + const net_list_t &nets, + const solver::solver_parameters_t *params) + //: device_t(static_cast(main_solver), name) + : device_t( + device_data_t{main_solver.state(), main_solver.name() + "." + name}) + , m_params(*params) + , m_gonn(m_arena) + , m_gtn(m_arena) + , m_Idrn(m_arena) + , m_connected_net_Vn(m_arena) + , m_iterative_fail(*this, "m_iterative_fail", 0) + , m_iterative_total(*this, "m_iterative_total", 0) + , m_main_solver(main_solver) + , m_stat_calculations(*this, "m_stat_calculations", 0) + , m_stat_newton_raphson(*this, "m_stat_newton_raphson", 0) + , m_stat_newton_raphson_fail(*this, "m_stat_newton_raphson_fail", 0) + , m_stat_vsolver_calls(*this, "m_stat_vsolver_calls", 0) + , m_last_step(*this, "m_last_step", netlist_time_ext::zero()) + , m_step_funcs(m_arena) + , m_dynamic_funcs(m_arena) + , m_inputs(m_arena) + , m_ops(0) { setup_base(this->state().setup(), nets); // now setup the matrix setup_matrix(); - //printf("Freq: %f\n", m_params.m_freq()); + // printf("Freq: %f\n", m_params.m_freq()); } analog_net_t *matrix_solver_t::get_connected_net(terminal_t *term) @@ -87,7 +94,8 @@ namespace netlist::solver m_main_solver.reschedule(this, ts); } - void matrix_solver_t::setup_base([[maybe_unused]] setup_t &setup, const net_list_t &nets) + void matrix_solver_t::setup_base([[maybe_unused]] setup_t &setup, + const net_list_t &nets) { log().debug("New solver setup\n"); std::vector step_devices; @@ -95,7 +103,7 @@ namespace netlist::solver m_terms.clear(); - for (const auto & net : nets) + for (const auto &net : nets) { m_terms.emplace_back(m_arena, net); m_rails_temp.emplace_back(m_arena); @@ -108,68 +116,87 @@ namespace netlist::solver analog_net_t &net = *nets[k]; // FIXME: add size() to list - // log().debug("adding net with {1} populated connections\n", net.core_terms().size()); + // log().debug("adding net with {1} populated connections\n", + // net.core_terms().size()); net.set_solver(this); - for (detail::core_terminal_t * p : net.core_terms_copy()) + for (detail::core_terminal_t *p : net.core_terms_copy()) { nl_assert_always(&p->net() == &net, "Net integrity violated"); - log().debug("{1} {2} {3}\n", p->name(), net.name(), net.is_rail_net()); + log().debug("{1} {2} {3}\n", p->name(), net.name(), + net.is_rail_net()); switch (p->type()) { case detail::terminal_type::TERMINAL: if (p->device().is_time_step()) - if (!plib::container::contains(step_devices, &p->device())) + if (!plib::container::contains(step_devices, + &p->device())) step_devices.push_back(&p->device()); if (p->device().is_dynamic()) - if (!plib::container::contains(dynamic_devices, &p->device())) + if (!plib::container::contains(dynamic_devices, + &p->device())) dynamic_devices.push_back(&p->device()); { - auto pterm = plib::dynamic_downcast(p); - nl_assert_always(bool(pterm), "cast to terminal_t * failed"); + auto pterm = plib::dynamic_downcast( + p); + nl_assert_always(bool(pterm), + "cast to terminal_t * failed"); add_term(k, *pterm); } log().debug("Added terminal {1}\n", p->name()); break; case detail::terminal_type::INPUT: - { - proxied_analog_output_t *net_proxy_output = nullptr; - for (auto & input : m_inputs) - if (input->proxied_net() == &p->net()) - { - net_proxy_output = input.get(); - break; - } - - if (net_proxy_output == nullptr) + { + proxied_analog_output_t *net_proxy_output = nullptr; + for (auto &input : m_inputs) + if (input->proxied_net() == &p->net()) { - pstring new_name(this->name() + "." + pstring(plib::pfmt("m{1}")(m_inputs.size()))); - auto proxied_net = plib::dynamic_downcast(p->net()); - nl_assert_always(proxied_net, "Net is not an analog net"); - auto net_proxy_output_u = state().make_pool_object(*this, new_name, *proxied_net); - net_proxy_output = net_proxy_output_u.get(); - m_inputs.emplace_back(std::move(net_proxy_output_u)); + net_proxy_output = input.get(); + break; } - net.remove_terminal(*p); - net_proxy_output->net().add_terminal(*p); - // FIXME: repeated calling - kind of brute force - net_proxy_output->net().rebuild_list(); - log().debug("Added input {1}", net_proxy_output->name()); + + if (net_proxy_output == nullptr) + { + pstring new_name( + this->name() + "." + + pstring(plib::pfmt("m{1}")(m_inputs.size()))); + auto proxied_net = plib::dynamic_downcast< + analog_net_t *>(p->net()); + nl_assert_always(proxied_net, + "Net is not an analog net"); + auto net_proxy_output_u + = state() + .make_pool_object< + proxied_analog_output_t>( + *this, new_name, *proxied_net); + net_proxy_output = net_proxy_output_u.get(); + m_inputs.emplace_back( + std::move(net_proxy_output_u)); } - break; + net.remove_terminal(*p); + net_proxy_output->net().add_terminal(*p); + // FIXME: repeated calling - kind of brute force + net_proxy_output->net().rebuild_list(); + log().debug("Added input {1}", + net_proxy_output->name()); + } + break; case detail::terminal_type::OUTPUT: log().fatal(MF_UNHANDLED_ELEMENT_1_FOUND(p->name())); - throw nl_exception(MF_UNHANDLED_ELEMENT_1_FOUND(p->name())); + throw nl_exception( + MF_UNHANDLED_ELEMENT_1_FOUND(p->name())); } } net.rebuild_list(); } for (auto &d : step_devices) - m_step_funcs.emplace_back(nl_delegate_ts(&core_device_t::time_step, d)); + m_step_funcs.emplace_back( + nl_delegate_ts(&core_device_t::time_step, d)); for (auto &d : dynamic_devices) - m_dynamic_funcs.emplace_back(nl_delegate_dyn(&core_device_t::update_terminals, d)); + m_dynamic_funcs.emplace_back( + nl_delegate_dyn(&core_device_t::update_terminals, d)); } /// \brief Sort terminals @@ -192,7 +219,8 @@ namespace netlist::solver /// literature but I have found no articles about Gauss Seidel. /// /// For Gaussian Elimination however increasing order is better suited. - /// NOTE: 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. /// FIXME: This entry needs an update. /// void matrix_solver_t::sort_terms(matrix_sort_type_e sort) @@ -202,65 +230,69 @@ namespace netlist::solver switch (sort) { case matrix_sort_type_e::PREFER_BAND_MATRIX: + { + for (std::size_t k = 0; k < iN - 1; k++) { - for (std::size_t k = 0; k < iN - 1; k++) + auto pk = get_weight_around_diagonal(k, k); + for (std::size_t i = k + 1; i < iN; i++) { - auto pk = get_weight_around_diagonal(k,k); - for (std::size_t i = k+1; i < iN; i++) + auto pi = get_weight_around_diagonal(i, k); + if (pi < pk) { - auto pi = get_weight_around_diagonal(i,k); - if (pi < pk) - { - std::swap(m_terms[i], m_terms[k]); - pk = get_weight_around_diagonal(k,k); - } + std::swap(m_terms[i], m_terms[k]); + pk = get_weight_around_diagonal(k, k); } } } - break; + } + break; case matrix_sort_type_e::PREFER_IDENTITY_TOP_LEFT: + { + for (std::size_t k = 0; k < iN - 1; k++) { - for (std::size_t k = 0; k < iN - 1; k++) + auto pk = get_left_right_of_diagonal(k, k); + for (std::size_t i = k + 1; i < iN; i++) { - auto pk = get_left_right_of_diagonal(k,k); - for (std::size_t i = k+1; i < iN; i++) + auto pi = get_left_right_of_diagonal(i, k); + if (pi.first <= pk.first && pi.second >= pk.second) { - auto pi = get_left_right_of_diagonal(i,k); - if (pi.first <= pk.first && pi.second >= pk.second) - { - std::swap(m_terms[i], m_terms[k]); - pk = get_left_right_of_diagonal(k,k); - } + std::swap(m_terms[i], m_terms[k]); + pk = get_left_right_of_diagonal(k, k); } } } - break; + } + break; case matrix_sort_type_e::ASCENDING: case matrix_sort_type_e::DESCENDING: - { - int sort_order = (sort == matrix_sort_type_e::DESCENDING ? 1 : -1); + { + int sort_order = (sort == matrix_sort_type_e::DESCENDING ? 1 + : -1); - for (std::size_t k = 0; k < iN - 1; k++) - for (std::size_t i = k+1; i < iN; i++) + for (std::size_t k = 0; k < iN - 1; k++) + for (std::size_t i = k + 1; i < iN; i++) + { + if ((static_cast(m_terms[k].rail_start()) + - static_cast(m_terms[i].rail_start())) + * sort_order + < 0) { - if ((static_cast(m_terms[k].rail_start()) - static_cast(m_terms[i].rail_start())) * sort_order < 0) - { - std::swap(m_terms[i], m_terms[k]); - } + std::swap(m_terms[i], m_terms[k]); } - } - break; - case matrix_sort_type_e::NOSORT: - break; + } + } + break; + case matrix_sort_type_e::NOSORT: break; } // rebuild for (auto &term : m_terms) { - //int *other = term.m_connected_net_idx.data(); + // int *other = term.m_connected_net_idx.data(); for (std::size_t i = 0; i < term.count(); i++) - //FIXME: this is weird + // FIXME: this is weird if (term.m_connected_net_idx[i] != -1) - term.m_connected_net_idx[i] = get_net_idx(get_connected_net(term.terms()[i])); + term.m_connected_net_idx[i] = get_net_idx( + get_connected_net(term.terms()[i])); } } @@ -272,7 +304,9 @@ namespace netlist::solver { m_terms[k].set_rail_start(m_terms[k].count()); for (std::size_t i = 0; i < m_rails_temp[k].count(); i++) - this->m_terms[k].add_terminal(m_rails_temp[k].terms()[i], m_rails_temp[k].m_connected_net_idx.data()[i], false); + this->m_terms[k].add_terminal( + m_rails_temp[k].terms()[i], + m_rails_temp[k].m_connected_net_idx.data()[i], false); } // free all - no longer needed @@ -285,17 +319,18 @@ namespace netlist::solver // 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]; // pretty brutal int *other = t.m_connected_net_idx.data(); t.m_nz.clear(); for (std::size_t i = 0; i < t.rail_start(); i++) - if (!plib::container::contains(t.m_nz, static_cast(other[i]))) + if (!plib::container::contains(t.m_nz, + static_cast(other[i]))) t.m_nz.push_back(static_cast(other[i])); - t.m_nz.push_back(k); // add diagonal + t.m_nz.push_back(k); // add diagonal // and sort std::sort(t.m_nz.begin(), t.m_nz.end()); @@ -307,16 +342,16 @@ namespace netlist::solver for (std::size_t k = 0; k < iN; k++) { - terms_for_net_t & t = m_terms[k]; + terms_for_net_t &t = m_terms[k]; // pretty brutal int *other = t.m_connected_net_idx.data(); - if (k==0) + if (k == 0) t.m_nzrd.clear(); else { - t.m_nzrd = m_terms[k-1].m_nzrd; - for (auto j = t.m_nzrd.begin(); j != t.m_nzrd.end(); ) + t.m_nzrd = m_terms[k - 1].m_nzrd; + for (auto j = t.m_nzrd.begin(); j != t.m_nzrd.end();) { if (*j < k + 1) j = t.m_nzrd.erase(j); @@ -326,7 +361,9 @@ namespace netlist::solver } for (std::size_t i = 0; i < t.rail_start(); i++) - if (!plib::container::contains(t.m_nzrd, static_cast(other[i])) && other[i] >= static_cast(k + 1)) + if (!plib::container::contains(t.m_nzrd, + static_cast(other[i])) + && other[i] >= static_cast(k + 1)) t.m_nzrd.push_back(static_cast(other[i])); // and sort @@ -366,7 +403,8 @@ namespace netlist::solver } } } - log().verbose("Number of multiplications/additions for {1}: {2}", name(), m_ops); + log().verbose("Number of multiplications/additions for {1}: {2}", + name(), m_ops); // Dumps non zero elements right of diagonal -> to much output, disabled // NOLINTNEXTLINE(readability-simplify-boolean-expr) @@ -374,7 +412,7 @@ namespace netlist::solver for (std::size_t k = 0; k < iN; k++) { pstring line = plib::pfmt("{1:3}")(k); - for (const auto & nzrd : m_terms[k].m_nzrd) + for (const auto &nzrd : m_terms[k].m_nzrd) line += plib::pfmt(" {1:3}")(nzrd); log().verbose("{1}", line); } @@ -387,9 +425,12 @@ namespace netlist::solver { pstring num = plib::pfmt("{1}")(k); - state().save(*this, m_gonn[k],"GO" + num, this->name(), m_terms[k].count()); - state().save(*this, m_gtn[k],"GT" + num, this->name(), m_terms[k].count()); - state().save(*this, m_Idrn[k],"IDR" + num, this->name(), m_terms[k].count()); + state().save(*this, m_gonn[k], "GO" + num, this->name(), + m_terms[k].count()); + state().save(*this, m_gtn[k], "GT" + num, this->name(), + m_terms[k].count()); + state().save(*this, m_Idrn[k], "IDR" + num, this->name(), + m_terms[k].count()); } } @@ -414,20 +455,22 @@ namespace netlist::solver for (std::size_t k = 0; k < iN; k++) for (std::size_t j = 0; j < m_terms[k].count(); j++) { - m_gtn.set(k,j, nlconst::zero()); - m_gonn.set(k,j, nlconst::zero()); - m_Idrn.set(k,j, nlconst::zero()); + m_gtn.set(k, j, nlconst::zero()); + m_gonn.set(k, j, nlconst::zero()); + m_Idrn.set(k, j, nlconst::zero()); m_connected_net_Vn.set(k, j, nullptr); } - for (std::size_t k = 0; k < iN; k++) { auto count = m_terms[k].count(); for (std::size_t i = 0; i < count; i++) { - m_terms[k].terms()[i]->set_ptrs(&m_gtn[k][i], &m_gonn[k][i], &m_Idrn[k][i]); - m_connected_net_Vn[k][i] = get_connected_net(m_terms[k].terms()[i])->Q_Analog_state_ptr(); + m_terms[k].terms()[i]->set_ptrs(&m_gtn[k][i], &m_gonn[k][i], + &m_Idrn[k][i]); + m_connected_net_Vn[k][i] = get_connected_net( + m_terms[k].terms()[i]) + ->Q_Analog_state_ptr(); } } } @@ -448,10 +491,11 @@ namespace netlist::solver void matrix_solver_t::reset() { - //m_last_step = netlist_time_ext::zero(); + // m_last_step = netlist_time_ext::zero(); } - void matrix_solver_t::step(time_step_type ts_type, netlist_time delta) noexcept + void matrix_solver_t::step(detail::time_step_type ts_type, + netlist_time delta) noexcept { const auto dd(delta.as_fp()); for (auto &d : m_step_funcs) @@ -460,12 +504,13 @@ namespace netlist::solver bool matrix_solver_t::solve_nr_base() { - bool this_resched(false); + bool this_resched(false); std::size_t newton_loops = 0; do { update_dynamic(); - // Gauss-Seidel will revert to Gaussian elimination if steps exceeded. + // Gauss-Seidel will revert to Gaussian elimination if steps + // exceeded. this->m_stat_calculations++; this->upstream_solve_non_dynamic(); this_resched = this->check_err(); @@ -482,18 +527,21 @@ namespace netlist::solver netlist_time matrix_solver_t::newton_loops_exceeded(netlist_time delta) { netlist_time next_time_step; - bool resched(false); + bool resched(false); restore(); - step(time_step_type::RESTORE, delta); + step(detail::time_step_type::RESTORE, delta); - for (std::size_t i=0; i< 10; i++) + for (std::size_t i = 0; i < 10; i++) { backup(); - step(time_step_type::FORWARD, netlist_time::from_fp(m_params.m_min_ts_ts())); + step(detail::time_step_type::FORWARD, + netlist_time::from_fp(m_params.m_min_ts_ts())); resched = solve_nr_base(); // update time step calculation - next_time_step = compute_next_time_step(m_params.m_min_ts_ts(), m_params.m_min_ts_ts(), m_params.m_max_time_step); + next_time_step = compute_next_time_step(m_params.m_min_ts_ts(), + m_params.m_min_ts_ts(), + m_params.m_max_time_step); delta -= netlist_time::from_fp(m_params.m_min_ts_ts()); } // try remaining time using compute_next_time step @@ -502,19 +550,23 @@ namespace netlist::solver if (next_time_step > delta) next_time_step = delta; backup(); - step(time_step_type::FORWARD, next_time_step); + step(detail::time_step_type::FORWARD, next_time_step); delta -= next_time_step; resched = solve_nr_base(); - next_time_step = compute_next_time_step(next_time_step.as_fp(), m_params.m_min_ts_ts(), m_params.m_max_time_step); + next_time_step = compute_next_time_step( + next_time_step.as_fp(), m_params.m_min_ts_ts(), + m_params.m_max_time_step); } if (m_stat_newton_raphson % 100 == 0) - log().warning(MW_NEWTON_LOOPS_EXCEEDED_INVOCATION_3(100, this->name(), exec().time().as_double() * 1e6)); + log().warning(MW_NEWTON_LOOPS_EXCEEDED_INVOCATION_3( + 100, this->name(), exec().time().as_double() * 1e6)); if (resched) { // reschedule .... - log().warning(MW_NEWTON_LOOPS_EXCEEDED_ON_NET_2(this->name(), exec().time().as_double() * 1e6)); + log().warning(MW_NEWTON_LOOPS_EXCEEDED_ON_NET_2( + this->name(), exec().time().as_double() * 1e6)); return netlist_time::from_fp(m_params.m_nr_recalc_delay()); } if (m_params.m_dynamic_ts) @@ -523,7 +575,8 @@ namespace netlist::solver return netlist_time::from_fp(m_params.m_max_time_step); } - netlist_time matrix_solver_t::solve(netlist_time_ext now, [[maybe_unused]] const char *source) + netlist_time matrix_solver_t::solve(netlist_time_ext now, + [[maybe_unused]] const char *source) { auto delta = static_cast(now - m_last_step()); PFDEBUG(printf("solve %.10f\n", delta.as_double());) @@ -532,8 +585,10 @@ namespace netlist::solver // FIXME: Make this a parameter! if (delta < netlist_time::quantum()) { - //printf("solve return %s at %f\n", source, now.as_double()); - return time_step_device_count() > 0 ? netlist_time::from_fp(m_params.m_min_time_step) : netlist_time::zero(); + // printf("solve return %s at %f\n", source, now.as_double()); + return time_step_device_count() > 0 + ? netlist_time::from_fp(m_params.m_min_time_step) + : netlist_time::zero(); } backup(); // save voltages for backup and time step calculation @@ -543,7 +598,7 @@ namespace netlist::solver ++m_stat_vsolver_calls; if (dynamic_device_count() != 0) { - step(time_step_type::FORWARD, delta); + step(detail::time_step_type::FORWARD, delta); const auto resched = solve_nr_base(); if (resched) @@ -551,7 +606,7 @@ namespace netlist::solver } else { - step(time_step_type::FORWARD, delta); + step(detail::time_step_type::FORWARD, delta); this->m_stat_calculations++; this->upstream_solve_non_dynamic(); this->store(); @@ -560,14 +615,15 @@ namespace netlist::solver if (m_params.m_dynamic_ts) { if (time_step_device_count() > 0) - return compute_next_time_step(delta.as_fp(), m_params.m_min_time_step, m_params.m_max_time_step); + return compute_next_time_step(delta.as_fp(), + m_params.m_min_time_step, + m_params.m_max_time_step); } if (time_step_device_count() > 0) return netlist_time::from_fp(m_params.m_max_time_step); return netlist_time::zero(); - } int matrix_solver_t::get_net_idx(const analog_net_t *net) const noexcept @@ -578,11 +634,14 @@ namespace netlist::solver return -1; } - std::pair matrix_solver_t::get_left_right_of_diagonal(std::size_t irow, std::size_t idiag) + std::pair + matrix_solver_t::get_left_right_of_diagonal(std::size_t irow, + std::size_t idiag) { // // return the maximum column left of the diagonal (-1 if no cols found) - // return the minimum column right of the diagonal (999999 if no cols found) + // return the minimum column right of the diagonal (999999 if no cols + // found) // const auto row = static_cast(irow); @@ -598,8 +657,10 @@ namespace netlist::solver auto col = get_net_idx(get_connected_net(term.terms()[i])); if (col != -1) { - if (col==row) col = diag; - else if (col==diag) col = row; + if (col == row) + col = diag; + else if (col == diag) + col = row; if (col > diag && col < colmin) colmin = col; @@ -610,7 +671,9 @@ namespace netlist::solver return {colmax, colmin}; } - matrix_solver_t::fptype matrix_solver_t::get_weight_around_diagonal(std::size_t row, std::size_t diag) + matrix_solver_t::fptype + matrix_solver_t::get_weight_around_diagonal(std::size_t row, + std::size_t diag) { { // @@ -620,7 +683,7 @@ namespace netlist::solver std::vector touched(1024, false); // FIXME! fptype weight = nlconst::zero(); - auto &term = m_terms[row]; + auto &term = m_terms[row]; for (std::size_t i = 0; i < term.count(); i++) { auto col = get_net_idx(get_connected_net(term.terms()[i])); @@ -629,10 +692,14 @@ namespace netlist::solver auto colu = static_cast(col); if (!touched[colu]) { - if (colu==row) colu = static_cast(diag); - else if (colu==diag) colu = static_cast(row); + if (colu == row) + colu = static_cast(diag); + else if (colu == diag) + colu = static_cast(row); - weight = weight + plib::abs(static_cast(colu) - static_cast(diag)); + weight = weight + + plib::abs(static_cast(colu) + - static_cast(diag)); touched[colu] = true; } } @@ -650,38 +717,46 @@ namespace netlist::solver else { int ot = get_net_idx(get_connected_net(term)); - if (ot>=0) + if (ot >= 0) { m_terms[net_idx].add_terminal(term, ot, true); } else { log().fatal(MF_FOUND_TERM_WITH_MISSING_OTHERNET(term->name())); - throw nl_exception(MF_FOUND_TERM_WITH_MISSING_OTHERNET(term->name())); + throw nl_exception( + MF_FOUND_TERM_WITH_MISSING_OTHERNET(term->name())); } } } void matrix_solver_t::log_stats() { - if (this->m_stat_calculations != 0 && this->m_stat_vsolver_calls && log().verbose.is_enabled()) + if (this->m_stat_calculations != 0 && this->m_stat_vsolver_calls + && log().verbose.is_enabled()) { log().verbose("=============================================="); log().verbose("Solver {1}", this->name()); log().verbose(" ==> {1} nets", this->m_terms.size()); - log().verbose(" has {1} dynamic elements", this->dynamic_device_count()); - log().verbose(" has {1} time step elements", this->time_step_device_count()); - log().verbose(" {1:6.3} average newton raphson loops", - static_cast(this->m_stat_newton_raphson) / static_cast(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(this->m_stat_calculations) / this->exec().time().as_fp(), - this->m_iterative_fail, - nlconst::hundred() * static_cast(this->m_iterative_fail) - / static_cast(this->m_stat_calculations), - static_cast(this->m_iterative_total) / static_cast(this->m_stat_calculations)); + log().verbose(" has {1} dynamic elements", + this->dynamic_device_count()); + log().verbose(" has {1} time step elements", + this->time_step_device_count()); + log().verbose( + " {1:6.3} average newton raphson loops", + static_cast(this->m_stat_newton_raphson) + / static_cast(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(this->m_stat_calculations) + / this->exec().time().as_fp(), + this->m_iterative_fail, + nlconst::hundred() * static_cast(this->m_iterative_fail) + / static_cast(this->m_stat_calculations), + static_cast(this->m_iterative_total) + / static_cast(this->m_stat_calculations)); } } } // namespace netlist::solver - diff --git a/src/lib/netlist/solver/nld_matrix_solver.h b/src/lib/netlist/solver/nld_matrix_solver.h index 21725ab3100..c0b792fd597 100644 --- a/src/lib/netlist/solver/nld_matrix_solver.h +++ b/src/lib/netlist/solver/nld_matrix_solver.h @@ -11,14 +11,14 @@ /// \file nld_matrix_solver.h /// +#include "nl_errstr.h" +#include "nltypes.h" #include "../core/analog.h" #include "../core/device.h" #include "../core/device_macros.h" #include "../core/param.h" -#include "nl_errstr.h" -#include "nltypes.h" #include "plib/palloc.h" #include "plib/penum.h" #include "plib/pmatrix2d.h" @@ -29,7 +29,7 @@ #include -//FIXME: remove again +// FIXME: remove again #define PFDEBUG(x) @@ -42,6 +42,8 @@ namespace netlist::solver CXX_STATIC }; + // clang-format off + PENUM(matrix_sort_type_e, NOSORT, ASCENDING, @@ -67,40 +69,63 @@ namespace netlist::solver , FLOATQ128 ) + // clang-format on + using arena_type = plib::mempool_arena, 1024>; using static_compile_container = std::vector>; struct solver_parameter_defaults { - static constexpr nl_fptype m_freq() { return nlconst::magic(48000.0); } + static constexpr nl_fptype m_freq() { return nlconst::magic(48000.0); } // iteration parameters - static constexpr nl_fptype m_gs_sor() { return nlconst::magic(1.059); } - static constexpr matrix_type_e m_method() { return matrix_type_e::MAT_CR; } - static constexpr matrix_fp_type_e m_fp_type() { return matrix_fp_type_e::DOUBLE; } - static constexpr nl_fptype m_reltol() { return nlconst::magic(1e-3); } - static constexpr nl_fptype m_vntol() { return nlconst::magic(1e-7); } - static constexpr nl_fptype m_accuracy() { return nlconst::magic(1e-7); } - static constexpr std::size_t m_nr_loops() { return 250; } - static constexpr std::size_t m_gs_loops() { return 50; } + static constexpr nl_fptype m_gs_sor() { return nlconst::magic(1.059); } + static constexpr matrix_type_e m_method() + { + return matrix_type_e::MAT_CR; + } + static constexpr matrix_fp_type_e m_fp_type() + { + return matrix_fp_type_e::DOUBLE; + } + static constexpr nl_fptype m_reltol() { return nlconst::magic(1e-3); } + static constexpr nl_fptype m_vntol() { return nlconst::magic(1e-7); } + static constexpr nl_fptype m_accuracy() { return nlconst::magic(1e-7); } + static constexpr std::size_t m_nr_loops() { return 250; } + static constexpr std::size_t m_gs_loops() { return 50; } // general parameters - static constexpr nl_fptype m_gmin() { return nlconst::magic(1e-9); } - static constexpr bool m_pivot() { return false; } - static constexpr nl_fptype m_nr_recalc_delay(){ return netlist_time::quantum().as_fp(); } - static constexpr int m_parallel() { return 0; } + static constexpr nl_fptype m_gmin() { return nlconst::magic(1e-9); } + static constexpr bool m_pivot() { return false; } + static constexpr nl_fptype m_nr_recalc_delay() + { + return netlist_time::quantum().as_fp(); + } + static constexpr int m_parallel() { return 0; } - static constexpr nl_fptype m_min_ts_ts() { return nlconst::magic(1e-9); } + static constexpr nl_fptype m_min_ts_ts() + { + return nlconst::magic(1e-9); + } // automatic time step - static constexpr bool m_dynamic_ts() { return false; } - static constexpr nl_fptype m_dynamic_lte() { return nlconst::magic(1e-5); } - static constexpr nl_fptype m_dynamic_min_ts() { return nlconst::magic(1e-6); } + static constexpr bool m_dynamic_ts() { return false; } + static constexpr nl_fptype m_dynamic_lte() + { + return nlconst::magic(1e-5); + } + static constexpr nl_fptype m_dynamic_min_ts() + { + return nlconst::magic(1e-6); + } // matrix sorting - static constexpr matrix_sort_type_e m_sort_type() { return matrix_sort_type_e::PREFER_IDENTITY_TOP_LEFT; } + static constexpr matrix_sort_type_e m_sort_type() + { + return matrix_sort_type_e::PREFER_IDENTITY_TOP_LEFT; + } // special - static constexpr bool m_use_gabs() { return true; } + static constexpr bool m_use_gabs() { return true; } static solver_parameter_defaults &get_instance() { @@ -112,30 +137,52 @@ namespace netlist::solver struct solver_parameters_t { template - solver_parameters_t(device_t &parent, const pstring &prefix, D &defaults) + solver_parameters_t(device_t &parent, const pstring &prefix, + D &defaults) : m_freq(parent, prefix + "FREQ", defaults.m_freq()) // iteration parameters - , m_gs_sor(parent, prefix + "SOR_FACTOR", defaults.m_gs_sor()) - , m_method(parent, prefix + "METHOD", defaults.m_method()) - , m_fp_type(parent, prefix + "FPTYPE", defaults.m_fp_type()) - , m_reltol(parent, prefix + "RELTOL", defaults.m_reltol()) //!< SPICE RELTOL parameter - , m_vntol(parent, prefix + "VNTOL", defaults.m_vntol()) //!< SPICE VNTOL parameter - , m_accuracy(parent, prefix + "ACCURACY", defaults.m_accuracy()) //!< Iterative solver accuracy - , m_nr_loops(parent, prefix + "NR_LOOPS", defaults.m_nr_loops()) //!< Maximum number of Newton-Raphson loops - , m_gs_loops(parent, prefix + "GS_LOOPS", defaults.m_gs_loops()) //!< Maximum number of Gauss-Seidel loops + , m_gs_sor(parent, prefix + "SOR_FACTOR", defaults.m_gs_sor()) + , m_method(parent, prefix + "METHOD", defaults.m_method()) + , m_fp_type(parent, prefix + "FPTYPE", defaults.m_fp_type()) + , m_reltol(parent, prefix + "RELTOL", + defaults.m_reltol()) //!< SPICE RELTOL parameter + , m_vntol(parent, prefix + "VNTOL", defaults.m_vntol()) //!< SPICE VNTOL + //!< parameter + , m_accuracy(parent, prefix + "ACCURACY", + defaults.m_accuracy()) //!< Iterative solver accuracy + , m_nr_loops(parent, prefix + "NR_LOOPS", + defaults.m_nr_loops()) //!< Maximum number of + //!< Newton-Raphson loops + , m_gs_loops(parent, prefix + "GS_LOOPS", + defaults.m_gs_loops()) //!< Maximum number of Gauss-Seidel + //!< loops // general parameters , m_gmin(parent, prefix + "GMIN", defaults.m_gmin()) - , m_pivot(parent, prefix + "PIVOT", defaults.m_pivot()) //!< use pivoting on supported solvers - , m_nr_recalc_delay(parent, prefix + "NR_RECALC_DELAY", defaults.m_nr_recalc_delay()) //!< Delay to next solve attempt if nr loops exceeded + , m_pivot(parent, prefix + "PIVOT", defaults.m_pivot()) //!< use + //!< pivoting on + //!< supported + //!< solvers + , m_nr_recalc_delay(parent, prefix + "NR_RECALC_DELAY", + defaults.m_nr_recalc_delay()) //!< Delay to next + //!< solve attempt if + //!< nr loops exceeded , m_parallel(parent, prefix + "PARALLEL", defaults.m_parallel()) - , m_min_ts_ts(parent, prefix + "MIN_TS_TS", defaults.m_min_ts_ts()) //!< The minimum time step for solvers with time stepping devices. + , m_min_ts_ts(parent, prefix + "MIN_TS_TS", + defaults.m_min_ts_ts()) //!< The minimum time step for + //!< solvers with time stepping + //!< devices. // automatic time step - , m_dynamic_ts(parent, prefix + "DYNAMIC_TS", defaults.m_dynamic_ts()) //!< Use dynamic time stepping - , m_dynamic_lte(parent, prefix + "DYNAMIC_LTE", defaults.m_dynamic_lte()) //!< dynamic time stepping slope - , m_dynamic_min_ts(parent, prefix + "DYNAMIC_MIN_TIMESTEP", defaults.m_dynamic_min_ts()) //!< smallest time step allowed + , m_dynamic_ts(parent, prefix + "DYNAMIC_TS", + defaults.m_dynamic_ts()) //!< Use dynamic time stepping + , m_dynamic_lte(parent, prefix + "DYNAMIC_LTE", + defaults.m_dynamic_lte()) //!< dynamic time stepping + //!< slope + , m_dynamic_min_ts(parent, prefix + "DYNAMIC_MIN_TIMESTEP", + defaults.m_dynamic_min_ts()) //!< smallest time step + //!< allowed // matrix sorting , m_sort_type(parent, prefix + "SORT_TYPE", defaults.m_sort_type()) @@ -144,11 +191,12 @@ namespace netlist::solver , m_use_gabs(parent, prefix + "USE_GABS", defaults.m_use_gabs()) , m_min_time_step(m_dynamic_min_ts()) { - m_max_time_step = netlist_time::from_fp(plib::reciprocal(m_freq())).as_fp(); + m_max_time_step = netlist_time::from_fp(plib::reciprocal(m_freq())) + .as_fp(); if (m_dynamic_ts) { - m_max_time_step *= 1;//NL_FCONST(1000.0); + m_max_time_step *= 1; // NL_FCONST(1000.0); } else { @@ -156,23 +204,23 @@ namespace netlist::solver } } - param_fp_t m_freq; - param_fp_t m_gs_sor; - param_enum_t m_method; - param_enum_t m_fp_type; - param_fp_t m_reltol; - param_fp_t m_vntol; - param_fp_t m_accuracy; - param_num_t m_nr_loops; - param_num_t m_gs_loops; - param_fp_t m_gmin; - param_logic_t m_pivot; - param_fp_t m_nr_recalc_delay; - param_int_t m_parallel; - param_fp_t m_min_ts_ts; - param_logic_t m_dynamic_ts; - param_fp_t m_dynamic_lte; - param_fp_t m_dynamic_min_ts; + param_fp_t m_freq; + param_fp_t m_gs_sor; + param_enum_t m_method; + param_enum_t m_fp_type; + param_fp_t m_reltol; + param_fp_t m_vntol; + param_fp_t m_accuracy; + param_num_t m_nr_loops; + param_num_t m_gs_loops; + param_fp_t m_gmin; + param_logic_t m_pivot; + param_fp_t m_nr_recalc_delay; + param_int_t m_parallel; + param_fp_t m_min_ts_ts; + param_logic_t m_dynamic_ts; + param_fp_t m_dynamic_lte; + param_fp_t m_dynamic_min_ts; param_enum_t m_sort_type; param_logic_t m_use_gabs; @@ -181,11 +229,10 @@ namespace netlist::solver nl_fptype m_max_time_step; }; - class terms_for_net_t { public: - terms_for_net_t(arena_type &arena, analog_net_t * net = nullptr); + terms_for_net_t(arena_type &arena, analog_net_t *net = nullptr); void clear(); @@ -201,35 +248,49 @@ namespace netlist::solver void setV(nl_fptype v) noexcept { m_net->set_Q_Analog(v); } - bool is_net(const analog_net_t * net) const noexcept { return net == m_net; } + bool is_net(const analog_net_t *net) const noexcept + { + return net == m_net; + } void set_rail_start(std::size_t val) noexcept { m_rail_start = val; } PALIGNAS_VECTOROPT() - plib::arena_vector m_nz; //!< all non zero for multiplication - plib::arena_vector m_nzrd; //!< non zero right of the diagonal for elimination, may include RHS element - plib::arena_vector m_nzbd; //!< non zero below of the diagonal for elimination + plib::arena_vector m_nz; //!< all non zero for + //!< multiplication + plib::arena_vector m_nzrd; //!< non zero right of + //!< the diagonal for + //!< elimination, may + //!< include RHS + //!< element + plib::arena_vector m_nzbd; //!< non zero below of + //!< the diagonal for + //!< elimination plib::arena_vector m_connected_net_idx; + private: plib::arena_vector m_terms; - analog_net_t * m_net; - std::size_t m_rail_start; + analog_net_t *m_net; + std::size_t m_rail_start; }; class proxied_analog_output_t : public analog_output_t { public: - - proxied_analog_output_t(core_device_t &dev, const pstring &aname, analog_net_t *pnet) + proxied_analog_output_t(core_device_t &dev, const pstring &aname, + analog_net_t *pnet) : analog_output_t(dev, aname) , m_proxied_net(pnet) - { } + { + } + + analog_net_t *proxied_net() const { return m_proxied_net; } - analog_net_t *proxied_net() const { return m_proxied_net;} private: - analog_net_t *m_proxied_net; // only for proxy nets in analog input logic + analog_net_t *m_proxied_net; // only for proxy nets in analog input + // logic }; class matrix_solver_t : public device_t @@ -237,16 +298,22 @@ namespace netlist::solver public: using list_t = std::vector; using fptype = nl_fptype; - using net_list_t = std::vector; + using net_list_t = std::vector; // after every call to solve, update inputs must be called. // this can be done as well as a batch to ease parallel processing. netlist_time solve(netlist_time_ext now, const char *source); - void update_inputs(); + void update_inputs(); - std::size_t dynamic_device_count() const noexcept { return m_dynamic_funcs.size(); } - std::size_t time_step_device_count() const noexcept { return m_step_funcs.size(); } + std::size_t dynamic_device_count() const noexcept + { + return m_dynamic_funcs.size(); + } + std::size_t time_step_device_count() const noexcept + { + return m_step_funcs.size(); + } /// \brief reschedule solver execution /// @@ -264,23 +331,28 @@ namespace netlist::solver // this should only occur outside of execution and thus // using time should be safe. - [[maybe_unused]] const netlist_time new_time_step = solve(exec().time(), "solve_now"); + [[maybe_unused]] const netlist_time new_time_step = solve( + exec().time(), "solve_now"); update_inputs(); if (time_step_device_count() > 0) { - this->reschedule(netlist_time::from_fp(m_params.m_dynamic_ts ? m_params.m_min_time_step : m_params.m_max_time_step)); + this->reschedule(netlist_time::from_fp( + m_params.m_dynamic_ts ? m_params.m_min_time_step + : m_params.m_max_time_step)); } } template void change_state(F f) { - // We only need to update the net first if this is a time stepping net + // We only need to update the net first if this is a time stepping + // net if (time_step_device_count() > 0) { - [[maybe_unused]] const netlist_time new_time_step = solve(exec().time(), "change_state"); + [[maybe_unused]] const netlist_time new_time_step = solve( + exec().time(), "change_state"); update_inputs(); } f(); @@ -297,9 +369,11 @@ namespace netlist::solver virtual void log_stats(); - virtual std::pair create_solver_code([[maybe_unused]] solver::static_compile_target target) + virtual std::pair create_solver_code( + [[maybe_unused]] solver::static_compile_target target) { - return { "", plib::pfmt("// solver doesn't support static compile\n\n") }; + return {"", + plib::pfmt("// solver doesn't support static compile\n\n")}; } // return number of floating point operations for solve @@ -307,11 +381,13 @@ namespace netlist::solver protected: matrix_solver_t(devices::nld_solver &main_solver, const pstring &name, - const net_list_t &nets, - const solver_parameters_t *params); + const net_list_t &nets, + const solver_parameters_t *params); virtual void upstream_solve_non_dynamic() = 0; - virtual netlist_time compute_next_time_step(fptype cur_ts, fptype min_ts, fptype max_ts) = 0; + virtual netlist_time + compute_next_time_step(fptype cur_ts, fptype min_ts, fptype max_ts) + = 0; virtual bool check_err() const = 0; virtual void store() = 0; virtual void backup() = 0; @@ -326,7 +402,7 @@ namespace netlist::solver } const solver_parameters_t &m_params; - arena_type m_arena; + arena_type m_arena; plib::pmatrix2d_vrl m_gonn; plib::pmatrix2d_vrl m_gtn; @@ -339,20 +415,20 @@ namespace netlist::solver std::vector m_terms; // setup only private: - // base setup - called from constructor void setup_base(setup_t &setup, const net_list_t &nets) noexcept(false); - bool solve_nr_base(); + bool solve_nr_base(); netlist_time newton_loops_exceeded(netlist_time delta); void sort_terms(matrix_sort_type_e sort); void update_dynamic() noexcept; - void step(time_step_type ts_type, netlist_time delta) noexcept; + void step(detail::time_step_type ts_type, netlist_time delta) noexcept; int get_net_idx(const analog_net_t *net) const noexcept; - std::pair get_left_right_of_diagonal(std::size_t irow, std::size_t idiag); + std::pair + get_left_right_of_diagonal(std::size_t irow, std::size_t idiag); fptype get_weight_around_diagonal(std::size_t row, std::size_t diag); void add_term(std::size_t net_idx, terminal_t *term) noexcept(false); @@ -371,10 +447,12 @@ namespace netlist::solver state_var m_stat_newton_raphson_fail; state_var m_stat_vsolver_calls; - state_var m_last_step; - plib::arena_vector m_step_funcs; + state_var m_last_step; + plib::arena_vector m_step_funcs; plib::arena_vector m_dynamic_funcs; - plib::arena_vector> m_inputs; + plib::arena_vector> + m_inputs; std::size_t m_ops; diff --git a/src/lib/netlist/tests/test_precommit.cpp b/src/lib/netlist/tests/test_precommit.cpp index 15575fbbe7f..6faf8029c0b 100644 --- a/src/lib/netlist/tests/test_precommit.cpp +++ b/src/lib/netlist/tests/test_precommit.cpp @@ -2,12 +2,12 @@ // copyright-holders:Couriersud /// -/// \file test_pmfp.cpp +/// \file test_precommit.cpp /// -/// tests for `plib::pmfp` +/// tests to check for experimental code before commit /// -#include "netlist/nl_config.h" +#include "nl_config.h" #include "plib/pconfig.h" #include "plib/ppmf.h"