/* d_mos.h  94.01.14
 * Copyright 1983-1992   Albert Davis
 * data structures and defaults for mos model.
 * internal units all mks (meters)
 * but some user input parameters are in cm.
 */
#define CM2M	(1e-2)			/*    centimeters to meters 	 */
#define CM2M2	(1e-4)			/*          ...........  squared */
#define ICM2M	(1e2)			/* inverse  ...........    	 */
#define ICM2M2	(1e4)			/* inverse  ...........  squared */
#define ICM2M3	(1e6)			/* inverse  ...........  cubed   */
#define SCALE	(1e-6)
#define NI	(1.45e16)		/* intrinsic carrier concentration */

#define nDRAIN	n[0]	/* nodes */
#define	nGATE	n[1]
#define nSOURCE	n[2]
#define	nBULK	n[3]

#define	gSAME	(1)	/* tpg (type of gate) */
#define	gOPP	(-1)
#define	gMETAL	(0)

#define	pN	(1)	/* polarity (n or p channel) */
#define	pP	(-1)

#define mDEFDEV_modelname	"-n-"		/* device card defaults */
#define mDEFDEV_l		NOT_INPUT
#define mDEFDEV_w		NOT_INPUT
#define mDEFDEV_ad		NOT_INPUT
#define mDEFDEV_as		NOT_INPUT
#define mDEFDEV_pd		0.0
#define mDEFDEV_ps		0.0
#define mDEFDEV_nrd		1.0
#define mDEFDEV_nrs		1.0
#define	mDEFDEV_ic_vds		0.0
#define	mDEFDEV_ic_vgs		0.0
#define	mDEFDEV_ic_vbs		0.0
#define NUM_INIT_COND		3

#define mDEFMODLR_vto		0.0		/* last resort defaults */
#define	mDEFMODLR_gamma		0.0		/* in case can't calculate */
#define	mDEFMODLR_phi		0.6
#define	mDEFMODLR_cj		0.0
#define mDEFMODLR_is		1e-14

#define mDEFMOD_modelname	"-n-"		/* model card defaults */
#define mDEFMOD_vto		NOT_INPUT	/*calc*/
#define mDEFMOD_kp		NOT_INPUT	/*calc*/
#define mDEFMOD_gamma		NOT_INPUT	/*calc*/
#define mDEFMOD_phi		NOT_INPUT	/*calc*/
#define mDEFMOD_lambda		NOT_INPUT
#define mDEFMOD_rd		NOT_INPUT
#define mDEFMOD_rs		NOT_INPUT
#define mDEFMOD_cbd		NOT_INPUT
#define mDEFMOD_cbs		NOT_INPUT
#define mDEFMOD_is		NOT_INPUT
#define mDEFMOD_cgso		0.0
#define mDEFMOD_cgdo		0.0
#define mDEFMOD_cgbo		0.0
#define mDEFMOD_rsh		NOT_INPUT
#define mDEFMOD_js		NOT_INPUT
#define mDEFMOD_tox		1e-7
#define mDEFMOD_nsub		NOT_INPUT	/*flag*/
#define mDEFMOD_nss		0.0
#define mDEFMOD_nfs		0.0
#define mDEFMOD_tpg		gSAME
#define mDEFMOD_xj		NOT_INPUT
#define mDEFMOD_ld		0.0
#define mDEFMOD_uo		(600.*CM2M2)
#define mDEFMOD_ucrit		(1e4*ICM2M)
#define mDEFMOD_uexp		NOT_INPUT
#define mDEFMOD_utra		NOT_INPUT
#define mDEFMOD_vmax		NOT_INPUT
#define mDEFMOD_neff		1.0
#define mDEFMOD_kf		NOT_INPUT
#define mDEFMOD_af		NOT_INPUT
#define mDEFMOD_fc		0.5
#define mDEFMOD_delta		0.0
#define mDEFMOD_theta		NOT_INPUT
#define mDEFMOD_eta		NOT_INPUT
#define mDEFMOD_kappa		NOT_INPUT
#define mDEFMOD_level		2
#define mDEFMOD_polarity	pN
#define mDEFMOD_xd		NOT_INPUT	/*calc if nsub spec, else not*/
#define mDEFMOD_cox		(E_OX / mDEFMOD_tox)
#define mDEFMOD_vfb		NOT_INPUT
#define mDEFMOD_vbi		NOT_INPUT
#define mDEFMOD_xwb		.25e-6
#define mDEFMOD_vbp		NOT_INPUT
#define mDEFMOD_cfsox		NOT_INPUT

						/* stored elsewhere */
#define mDEFMOD_cj		NOT_INPUT	/*calc*/
#define mDEFMOD_mj		0.5
#define mDEFMOD_cjsw		0.0
#define mDEFMOD_mjsw		0.33


#define mdDEFMOD_modelname	"-md-"		/* mos-diode model defaults */
#define mdDEFMOD_js		dDEFMOD_js
#define mdDEFMOD_rs		0.0
#define mdDEFMOD_n		1.0
#define mdDEFMOD_tt		0.0
#define mdDEFMOD_cj		mDEFMOD_cj
#define mdDEFMOD_pb		0.8
#define mdDEFMOD_mj		mDEFMOD_mj
#define mdDEFMOD_eg		1.11
#define mdDEFMOD_xti		3.0
#define mdDEFMOD_kf		0.0
#define mdDEFMOD_af		1.0
#define mdDEFMOD_fc		0.5
#define mdDEFMOD_bv		0.0		/* infinity */
#define mdDEFMOD_ibv		1e-3
#define mdDEFMOD_cjsw		mDEFMOD_cjsw
#define mdDEFMOD_mjsw		mDEFMOD_mjsw
#define mdDEFMOD_fcpb		(mdDEFMOD_fc * mdDEFMOD_pb)

struct mos {
   generic_t *x;
   size_t	ssize;
   struct mmod	*m;		/* process dependent model params	*/
   char		modelname[LABELEN+1];
   double	lo;		/* drawn (optical) channel length	*/
   double	wo;		/* channel width (drawn)		*/
   double	ad_in;		/* drain area, drawn			*/
   double	as_in;		/* source area, drawn			*/
   double	pd;		/* drain perimeter			*/
   double	ps;		/* source perimeter			*/
   double	nrd;		/* drain # squares			*/
   double	nrs;		/* source # squares			*/
   double	ic[NUM_INIT_COND];	/* initial conditions		*/
   int		off;		/* off flag				*/
   int		icset;		/* flag: initial conditions set		*/
   				/* up to here initialized		*/
   double	le;		/* actual (electrical) channel length	*/
   double	we;		/* actual (electrical) channel width	*/
   double	ad;		/* drain area, actual			*/
   double	as;		/* source area, actual			*/
   double	cgate;		/* gate to channel capacitance		*/
   double	beta;	/*?*/	/* transconductance term (kp*w/l)	*/
   double	relxj;	/*?*/
   double	eta_1;	/*?*/
   double	eta;	/*?*/
   double	eta_2;	/*?*/
   double	idsat;	/*?*/	/* drain junction saturation current	*/
   double	issat;	/*?*/	/* source junction saturation current	*/
   double	rd;	/*?*/	/* ohmic drain resistance		*/
   double	rs;	/*?*/	/* ohmic source resistance		*/
   double	ids;		/* iterated parameters, latest		*/
   double	gm;
   double	gds;
   double	gmb;
   double	vgs;		/* terminal voltages			*/
   double	vds;
   double	vbs;
   double	vdsat;		/* saturation voltage			*/
   double	vgst;		/* vgs - von.				*/
   double	von;		/* actual threshold voltage		*/
   int		cutoff;		/* flag: in cut off region		*/
   int		subthreshold;	/* flag: subthreshold region (L2 only)	*/
   int		saturated;	/* flag: in saturation region		*/
   int		reversed;	/* flag: Vgs < 0, reverse s & d		*/
   int		dbfwd;		/* flag: db diode fwd biased		*/
   int		sbfwd;		/* flag: sb diode fwd biased		*/
   node_t	drainnode;	/* internal drain node			*/
   node_t	sourcenode;	/* internal source node			*/
   branch_t	*Rs;		/* subckt elements, for probe		*/
   branch_t	*Rd;
   branch_t	*Ddb;
   branch_t	*Dsb;
   branch_t	*Cgs;
   branch_t	*Cgd;
   branch_t	*Cgb;
   branch_t	*Gmbf;
   branch_t	*Gmbr;
   branch_t	*Yds;
   branch_t	*Gmf;
   branch_t	*Gmr;
   branch_t	*Ids;
};

struct mmod {
   struct dmod	*d;		/* diode model				*/
   size_t	ssize;
   double	vto;		/* zero-bias threshold voltage		*/
   double	kp;		/* transconductance parameter		*/
   double	gamma;		/* bulk threshold parameter		*/
   double	phi;		/* surface potential			*/
   double	lambda;		/* channel-length modulation		*/
   double	rd;		/* drain ohmic resistance		*/
   double	rs;		/* source ohmic resistance		*/
   double	cbd;
   double	cbs;
   double	is;
   double	cgso;
   double	cgdo;
   double	cgbo;
   double	rsh;
   double	js;
   double	tox;
   double	nsub;
   double	nss;
   double	nfs;
   double	xj;
   double	ld;
   double	uo;
   double	ucrit;
   double	uexp;
   double	utra;
   double	vmax;
   double	neff;
   double	kf;
   double	af;
   double	delta;
   double	theta;
   double	eta;
   double	kappa;
   int		level;
   int		tpg;
   int		polarity;
   double	xd;
   double	cox;
   double	vfb;
   double	vbi;
   double	xwb;
   double	vbp;
   double	cfsox;
   struct {
      unsigned	vto:1,
		kp:1,
		gamma:1,
		phi:1,
		cj:1;
      } calc;
};

	void	eval_mos1(branch_t*);
	void	eval_mos2(branch_t*);
	void	eval_mos3(branch_t*);
	void	mos2_ids0(branch_t*);
	void	mos2_gmf0(branch_t*);
	void	mos2_gmr0(branch_t*);
	void	mos2_gds0(branch_t*);
	void	mos2_gmbf0(branch_t*);
	void	mos2_gmbr0(branch_t*);
	void	mos_cgb0(branch_t*);
	void	mos_cgd0(branch_t*);
	void	mos_cgs0(branch_t*);
	void	mos2_ids1(branch_t*);
	void	mos2_gmf1(branch_t*);
	void	mos2_gmr1(branch_t*);
	void	mos2_gds1(branch_t*);
	void	mos2_gmbf1(branch_t*);
	void	mos2_gmbr1(branch_t*);
	void	mos_cgb1(branch_t*);
	void	mos_cgd1(branch_t*);
	void	mos_cgs1(branch_t*);
