summaryrefslogblamecommitdiffstatshomepage
path: root/src/lib/netlist/devices/nlid_system.h
blob: 6448dfff3d618bd3b5b8fddc49779d4f9fe6a81b (plain) (tree)
1
2
3
4
5
6
7
8
9

                               


                      



                       



                                        


                 

                 






                                                                                        

                                                                  
                                                                  
                                                                        






                                               



                                                                           

          






                                                                                        

                                         
                                                                        
                 
                                                                                                 
 
                                                 
                 
                                  


                                      
                                                                                                 





                                                       
 
                


                                         
                                  



                                                                                        









                                                                                              
                                                

                                           
                                                                                                     






                                                 

                                                                                                           







                                                       
                                                      
                                                   


                                                                                        





                                                                                        
                                                                        
                                                    
                                                            

                                         

                                                             
                 
                                                                                                    
 
                                                 
 
                                                                                                             
                                                                                
                                                                  





                                                                       
                         

                                                                                     
                                                                              
                                                 
                         








                                                                    
                 
 


                                         




                                           
 
                                  
                                      
                                    


                                         
                                   
                                    
                                              
                                                   








                                                                                        
                                 
                                          
                                                    

                                                               
                                                                                        
                                                                   
                 
 


                                                                                            
 
                








                                                
                                 
                                                    
                 
                 
 
                                     
                                                                 


                                                            
                                    
                                








                                                                                        
                                 
                 


                                
                                                  









                                                                                        
                                  

               
                                               
                                 
                 















                                                                                        
                               

               
                                            
                                             


                                               

                                                               

                 

                                                          
                                                
 

                                                             
                                                 



                               

                                                                           



                                
                                        


                 
                                                   
                                                                                   
                                                    


                                    

                                    

          




                                                                                           



                                            

                                             
                                 
                                                                                              
                 
                                                  
                                                     

                                                                  
                                                                                            
                                                  
                                                                  
                         
                                                           



                  



                                           
 







                                                                                      

                


                                    
                                                                 
 
                                              
                                                      









                                                                                        
                                  
                                 

                                                               
                                                        
                 

                                                        

                 




















                                                                                                             
                                         
 
                                               
                                  

                                  
 
                
                                                      

          



                                                                                        



                                                                                 


                            

                                                                                         
                 
                                                                                                 
                         

                                                                                                                           


                            
                                                                                         

                                                                                            


                         
                                                                           

                                                                               
 
                
                               



                                                                                                           

          
                      

                      
                       
// license:GPL-2.0+
// copyright-holders:Couriersud
#ifndef NLID_SYSTEM_H_
#define NLID_SYSTEM_H_

///
/// \file nlid_system.h
///

#include "netlist/analog/nlid_twoterm.h"
#include "netlist/nl_base.h"
#include "netlist/nl_setup.h"
#include "plib/putil.h"

namespace netlist
{
namespace devices
{
	// -----------------------------------------------------------------------------
	// netlistparams
	// -----------------------------------------------------------------------------

	NETLIB_OBJECT(netlistparams)
	{
		NETLIB_CONSTRUCTOR(netlistparams)
		, m_use_deactivate(*this, "USE_DEACTIVATE", false)
		, m_startup_strategy(*this, "STARTUP_STRATEGY", 1)
		, m_mos_capmodel(*this, "DEFAULT_MOS_CAPMODEL", 2)
		, m_max_link_loops(*this, "MAX_LINK_RESOLVE_LOOPS", 100)
		{
		}
		NETLIB_UPDATEI() { }
		//NETLIB_RESETI() { }
		//NETLIB_UPDATE_PARAMI() { }
	public:
		param_logic_t m_use_deactivate;
		param_num_t<unsigned>   m_startup_strategy;
		param_num_t<unsigned>   m_mos_capmodel;
		//! How many times do we try to resolve links (connections)
		param_num_t<unsigned>   m_max_link_loops;
	};

	// -----------------------------------------------------------------------------
	// clock
	// -----------------------------------------------------------------------------

	NETLIB_OBJECT(clock)
	{
		NETLIB_CONSTRUCTOR(clock)
		, m_feedback(*this, "FB")
		, m_Q(*this, "Q")
		, m_freq(*this, "FREQ", nlconst::magic(7159000.0 * 5.0))
		{
			m_inc = netlist_time::from_fp(plib::reciprocal(m_freq()*nlconst::two()));

			connect(m_feedback, m_Q);
		}
		//NETLIB_RESETI();

		NETLIB_UPDATE_PARAMI()
		{
			m_inc = netlist_time::from_fp(plib::reciprocal(m_freq()*nlconst::two()));
		}

		NETLIB_UPDATEI()
		{
			m_Q.push(!m_feedback(), m_inc);
		}

	private:
		logic_input_t m_feedback;
		logic_output_t m_Q;

		param_fp_t m_freq;
		netlist_time m_inc;
	};

	// -----------------------------------------------------------------------------
	// varclock
	// -----------------------------------------------------------------------------

	NETLIB_OBJECT(varclock)
	{
		NETLIB_CONSTRUCTOR(varclock)
		, m_feedback(*this, "FB")
		, m_Q(*this, "Q")
		, m_func(*this,"FUNC", "")
		, m_compiled(this->name() + ".FUNCC", this, this->state().run_state_manager())
		, m_funcparam({nlconst::zero()})
		{
			if (m_func() != "")
				m_compiled.compile(m_func(), std::vector<pstring>({{pstring("T")}}));
			connect(m_feedback, m_Q);
		}
		//NETLIB_RESETI();
		//NETLIB_UPDATE_PARAMI()

		NETLIB_UPDATEI()
		{
			m_funcparam[0] = exec().time().as_fp<nl_fptype>();
			const netlist_time m_inc = netlist_time::from_fp(m_compiled.evaluate(m_funcparam));
			m_Q.push(!m_feedback(), m_inc);
		}

	private:
		logic_input_t m_feedback;
		logic_output_t m_Q;

		param_str_t m_func;
		plib::pfunction<nl_fptype> m_compiled;
		std::vector<nl_fptype> m_funcparam;
	};

	// -----------------------------------------------------------------------------
	// extclock
	// -----------------------------------------------------------------------------

	NETLIB_OBJECT(extclock)
	{
		NETLIB_CONSTRUCTOR(extclock)
		, m_freq(*this, "FREQ", nlconst::magic(7159000.0 * 5.0))
		, m_pattern(*this, "PATTERN", "1,1")
		, m_offset(*this, "OFFSET", nlconst::zero())
		, m_feedback(*this, "FB")
		, m_Q(*this, "Q")
		, m_cnt(*this, "m_cnt", 0)
		, m_off(*this, "m_off", netlist_time::zero())
		{
			m_inc[0] = netlist_time::from_fp(plib::reciprocal(m_freq()*nlconst::two()));

			connect(m_feedback, m_Q);

			netlist_time base = netlist_time::from_fp(plib::reciprocal(m_freq()*nlconst::two()));
			std::vector<pstring> pat(plib::psplit(m_pattern(),","));
			m_off = netlist_time::from_fp(m_offset());

			std::array<std::int64_t, 32> pati = { 0 };

			m_size = static_cast<std::uint8_t>(pat.size());
			netlist_time::mult_type total = 0;
			for (unsigned i=0; i<m_size; i++)
			{
				// FIXME: use pstonum_ne
				//pati[i] = plib::pstonum<decltype(pati[i])>(pat[i]);
				pati[i] = plib::pstonum<std::int64_t>(pat[i]);
				total += pati[i];
			}
			netlist_time ttotal = netlist_time::zero();
			auto sm1 = static_cast<uint8_t>(m_size - 1);
			for (unsigned i=0; i < sm1; i++)
			{
				m_inc[i] = base * pati[i];
				ttotal += m_inc[i];
			}
			m_inc[sm1] = base * total - ttotal;

		}

		NETLIB_UPDATEI();
		NETLIB_RESETI();
		//NETLIB_UPDATE_PARAMI();

		NETLIB_HANDLERI(clk2);
		NETLIB_HANDLERI(clk2_pow2);

	private:

		param_fp_t m_freq;
		param_str_t m_pattern;
		param_fp_t m_offset;

		logic_input_t m_feedback;
		logic_output_t m_Q;
		state_var_u8 m_cnt;
		std::uint8_t m_size;
		state_var<netlist_time> m_off;
		std::array<netlist_time, 32> m_inc;
	};

	// -----------------------------------------------------------------------------
	// Special support devices ...
	// -----------------------------------------------------------------------------

	NETLIB_OBJECT(logic_input)
	{
		NETLIB_CONSTRUCTOR(logic_input)
		, m_Q(*this, "Q")
		, m_IN(*this, "IN", false)
		// make sure we get the family first
		, m_FAMILY(*this, "FAMILY", "FAMILY(TYPE=TTL)")
		{
			set_logic_family(state().setup().family_from_model(m_FAMILY()));
			m_Q.set_logic_family(this->logic_family());
		}

		NETLIB_UPDATEI() { }
		NETLIB_RESETI() { m_Q.initial(0); }
		NETLIB_UPDATE_PARAMI() { m_Q.push(m_IN() & 1, netlist_time::from_nsec(1)); }

	private:
		logic_output_t m_Q;

		param_logic_t m_IN;
		param_model_t m_FAMILY;
	};

	NETLIB_OBJECT(analog_input)
	{
		NETLIB_CONSTRUCTOR(analog_input)
		, m_Q(*this, "Q")
		, m_IN(*this, "IN", nlconst::zero())
		{
		}

		NETLIB_UPDATEI() {  }
		NETLIB_RESETI() { m_Q.initial(nlconst::zero()); }
		NETLIB_UPDATE_PARAMI() { m_Q.push(m_IN()); }

	private:
		analog_output_t m_Q;
		param_fp_t m_IN;
	};

	// -----------------------------------------------------------------------------
	// nld_gnd
	// -----------------------------------------------------------------------------

	NETLIB_OBJECT(gnd)
	{
		NETLIB_CONSTRUCTOR(gnd)
		, m_Q(*this, "Q")
		{
		}
		NETLIB_UPDATEI()
		{
			m_Q.push(nlconst::zero());
		}
		NETLIB_RESETI() { }
	protected:
		analog_output_t m_Q;
	};

	// -----------------------------------------------------------------------------
	// nld_dummy_input
	// -----------------------------------------------------------------------------

	NETLIB_OBJECT(dummy_input)
	{
	public:
		NETLIB_CONSTRUCTOR(dummy_input)
		, m_I(*this, "I")
		{
		}

	protected:

		NETLIB_RESETI() { }
		NETLIB_UPDATEI() { }

	private:
		analog_input_t m_I;

	};

	// -----------------------------------------------------------------------------
	// nld_frontier
	// -----------------------------------------------------------------------------

	NETLIB_OBJECT(frontier)
	{
	public:
		NETLIB_CONSTRUCTOR(frontier)
		, m_RIN(*this, "m_RIN", true)
		, m_ROUT(*this, "m_ROUT", true)
		, m_I(*this, "_I")
		, m_Q(*this, "_Q")
		, m_p_RIN(*this, "RIN", nlconst::magic(1.0e6))
		, m_p_ROUT(*this, "ROUT", nlconst::magic(50.0))

		{
			register_subalias("I", m_RIN.m_P);
			register_subalias("G", m_RIN.m_N);
			connect(m_I, m_RIN.m_P);

			register_subalias("_OP", m_ROUT.m_P);
			register_subalias("Q", m_ROUT.m_N);
			connect(m_Q, m_ROUT.m_P);
		}

		NETLIB_RESETI()
		{
			m_RIN.set_G_V_I(plib::reciprocal(m_p_RIN()),0,0);
			m_ROUT.set_G_V_I(plib::reciprocal(m_p_ROUT()),0,0);
		}

		NETLIB_UPDATEI()
		{
			m_Q.push(m_I());
		}

	private:
		analog::NETLIB_NAME(twoterm) m_RIN;
		// Fixme: only works if the device is time-stepped - need to rework
		analog::NETLIB_NAME(twoterm) m_ROUT;
		analog_input_t m_I;
		analog_output_t m_Q;

		param_fp_t m_p_RIN;
		param_fp_t m_p_ROUT;
	};

	// -----------------------------------------------------------------------------
	// nld_function
	//
	// FIXME: Currently a proof of concept to get congo bongo working
	// ----------------------------------------------------------------------------- */

	NETLIB_OBJECT(function)
	{
		NETLIB_CONSTRUCTOR(function)
		, m_N(*this, "N", 1)
		, m_func(*this, "FUNC", "A0")
		, m_Q(*this, "Q")
		, m_compiled(this->name() + ".FUNCC", this, this->state().run_state_manager())
		{
			std::vector<pstring> inps;
			for (int i=0; i < m_N(); i++)
			{
				pstring n = plib::pfmt("A{1}")(i);
				m_I.push_back(pool().make_unique<analog_input_t>(*this, n));
				inps.push_back(n);
				m_vals.push_back(nlconst::zero());
			}
			m_compiled.compile(m_func(), inps);
		}

	protected:

		NETLIB_RESETI()
		{
			//m_Q.initial(0.0);
		}

		NETLIB_UPDATEI()
		{
			for (std::size_t i = 0; i < static_cast<unsigned>(m_N()); i++)
			{
				m_vals[i] = (*m_I[i])();
			}
			m_Q.push(m_compiled.evaluate(m_vals));
		}
	private:

		param_int_t m_N;
		param_str_t m_func;
		analog_output_t m_Q;
		std::vector<unique_pool_ptr<analog_input_t>> m_I;

		std::vector<nl_fptype> m_vals;
		plib::pfunction<nl_fptype> m_compiled;
	};

	// -----------------------------------------------------------------------------
	// nld_res_sw
	// -----------------------------------------------------------------------------

	NETLIB_OBJECT(res_sw)
	{
	public:
		NETLIB_CONSTRUCTOR(res_sw)
		, m_R(*this, "_R")
		, m_I(*this, "I")
		, m_RON(*this, "RON", nlconst::one())
		, m_ROFF(*this, "ROFF", nlconst::magic(1.0E20))
		, m_last_state(*this, "m_last_state", 0)
		{
			register_subalias("1", m_R.m_P);
			register_subalias("2", m_R.m_N);
		}

		NETLIB_RESETI()
		{
			m_last_state = 0;
			m_R.set_R(m_ROFF());
		}

		NETLIB_UPDATEI()
		{
			const netlist_sig_t state = m_I();
			if (state != m_last_state)
			{
				m_last_state = state;
				const nl_fptype R = state ? m_RON() : m_ROFF();

				// FIXME: We only need to update the net first if this is a time stepping net
				m_R.update();
				m_R.set_R(R);
				m_R.solve_later();
			}
		}

		//NETLIB_UPDATE_PARAMI();

		analog::NETLIB_SUB(R_base) m_R;
		logic_input_t m_I;
		param_fp_t m_RON;
		param_fp_t m_ROFF;

	private:
		state_var<netlist_sig_t> m_last_state;
	};

	// -----------------------------------------------------------------------------
	// power pins - not a device, but a helper
	// -----------------------------------------------------------------------------

	/// \brief Power pins class.
	///
	/// Power Pins are passive inputs. Delegate noop will silently ignore any
	/// updates.
	class nld_power_pins
	{
	public:
		explicit nld_power_pins(device_t &owner, const pstring &sVCC = sPowerVCC,
			const pstring &sGND = sPowerGND, bool force_analog_input = false)
		{
			if (owner.state().setup().is_extended_validation() || force_analog_input)
			{
				m_GND = pool().make_unique<analog_input_t>(owner, sGND, NETLIB_DELEGATE(power_pins, noop));
				m_VCC = pool().make_unique<analog_input_t>(owner, sVCC, NETLIB_DELEGATE(power_pins, noop));
			}
			else
			{
				owner.create_and_register_subdevice(sPowerDevRes, m_RVG);
				owner.register_subalias(sVCC, pstring(sPowerDevRes) + ".1");
				owner.register_subalias(sGND, pstring(sPowerDevRes) + ".2");
			}
		}

		// FIXME: this will seg-fault if force_analog_input = false
		nl_fptype VCC() const NL_NOEXCEPT { return m_VCC->Q_Analog(); }
		nl_fptype GND() const NL_NOEXCEPT { return m_GND->Q_Analog(); }

	private:
		void noop() { }
		unique_pool_ptr<analog_input_t> m_VCC; // only used during validation or force_analog_input
		unique_pool_ptr<analog_input_t> m_GND; // only used during validation or force_analog_input

		NETLIB_SUB_UPTR(analog, R) m_RVG; // dummy resistor between VCC and GND
	};

} // namespace devices
} // namespace netlist

#endif // NLD_SYSTEM_H_