/*$Id: bmm_table.cc,v 26.14 2007/02/07 09:06:48 al Exp $ -*- C++ -*- * Copyright (C) 2001 Albert Davis * Author: Albert Davis * * This file is part of "Gnucap", the Gnu Circuit Analysis Package * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. *------------------------------------------------------------------ * behavioral modeling * table as a .model card */ //testing=script 2006.04.18 #include "l_dispatcher.h" #include "e_elemnt.h" #include "e_model.h" #include "ap.h" #include "m_spline.h" //#include "bmm_table.h" /*--------------------------------------------------------------------------*/ #include "e_model.h" #include "bm.h" /*--------------------------------------------------------------------------*/ class SPLINE; /*--------------------------------------------------------------------------*/ class EVAL_BM_TABLE : public EVAL_BM_ACTION_BASE { protected: explicit EVAL_BM_TABLE(const EVAL_BM_TABLE& p); public: explicit EVAL_BM_TABLE(int c=0); ~EVAL_BM_TABLE() {} private: // override virtual bool operator==(const COMMON_COMPONENT&)const; COMMON_COMPONENT* clone()const {untested(); return new EVAL_BM_TABLE(*this);} //void parse(CS&); //COMPONENT_COMMON void print(OMSTREAM&, LANGUAGE)const; void elabo3(const COMPONENT*); //COMMON_COMPONENT* deflate(); //COMPONENT_COMMON/nothing void tr_eval(ELEMENT*)const; //void ac_eval(ELEMENT*)const; //EVAL_BM_ACTION_BASE //bool has_tr_eval()const; //EVAL_BM_BASE/true //bool has_ac_eval()const; //EVAL_BM_BASE/true const char* name()const {untested();return modelname().c_str();} bool ac_too()const {untested();return false;} //bool parse_numlist(CS&); //COMPONENT_COMMON/nothing //bool parse_params(CS&); //EVAL_BM_ACTION_BASE }; /*--------------------------------------------------------------------------*/ class MODEL_TABLE : public MODEL_CARD { public: PARAMETER _order; PARAMETER _below; PARAMETER _above; std::vector,PARAMETER > > _table; SPLINE* _spline; private: static int const _default_order; static double const _default_below; static double const _default_above; private: explicit MODEL_TABLE(const MODEL_TABLE& p); public: explicit MODEL_TABLE(); ~MODEL_TABLE(); private: // override virtual void elabo1(); COMMON_COMPONENT* new_common()const {return new EVAL_BM_TABLE;} CARD* clone()const {return new MODEL_TABLE(*this);} bool parse_front(CS&); bool parse_params(CS&); void print_front(OMSTREAM&,LANGUAGE)const; void print_params(OMSTREAM&,LANGUAGE)const; //void print_calculated(OMSTREAM&,LANGUAGE)const //MODEL_CARD/nothing void tr_eval(COMPONENT*)const; }; /*--------------------------------------------------------------------------*/ int const MODEL_TABLE::_default_order = 3; double const MODEL_TABLE::_default_below = NOT_INPUT; double const MODEL_TABLE::_default_above = NOT_INPUT; /*--------------------------------------------------------------------------*/ extern DISPATCHER model_dispatcher; static MODEL_TABLE p1; static DISPATCHER::INSTALL d1(&model_dispatcher, "TABLE", &p1); /*--------------------------------------------------------------------------*/ EVAL_BM_TABLE::EVAL_BM_TABLE(int c) :EVAL_BM_ACTION_BASE(c) { } /*--------------------------------------------------------------------------*/ EVAL_BM_TABLE::EVAL_BM_TABLE(const EVAL_BM_TABLE& p) :EVAL_BM_ACTION_BASE(p) { untested(); } /*--------------------------------------------------------------------------*/ bool EVAL_BM_TABLE::operator==(const COMMON_COMPONENT& x)const { const EVAL_BM_TABLE* p = dynamic_cast(&x); bool rv = p && EVAL_BM_ACTION_BASE::operator==(x); if (rv) { untested(); }else{ untested(); } return rv; } /*--------------------------------------------------------------------------*/ void EVAL_BM_TABLE::print(OMSTREAM& o, LANGUAGE lang)const { untested(); assert(lang == lSPICE || lang == lVERILOG); o << modelname(); EVAL_BM_ACTION_BASE::print(o, lang); untested(); } /*--------------------------------------------------------------------------*/ void EVAL_BM_TABLE::elabo3(const COMPONENT* d) { EVAL_BM_ACTION_BASE::elabo3(d); const MODEL_TABLE* m = dynamic_cast(attach_model(d)); if (!m) { untested(); error(bERROR, d->long_label() + "model " + modelname() + " is not a table\n"); } } /*--------------------------------------------------------------------------*/ void EVAL_BM_TABLE::tr_eval(ELEMENT* d)const { model()->tr_eval(d); tr_final_adjust(&(d->_y0), d->f_is_value()); } /*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/ MODEL_TABLE::MODEL_TABLE() :MODEL_CARD(), _order(_default_order), _below(_default_below), _above(_default_above), _table(), _spline(0) { } /*--------------------------------------------------------------------------*/ MODEL_TABLE::MODEL_TABLE(const MODEL_TABLE& p) :MODEL_CARD(p), _order(p._order), _below(p._below), _above(p._above), _table(p._table), _spline(p._spline) { } /*--------------------------------------------------------------------------*/ MODEL_TABLE::~MODEL_TABLE() { delete _spline; } /*--------------------------------------------------------------------------*/ bool MODEL_TABLE::parse_front(CS& cmd) { bool dummy; return set(cmd, "TABLE", &dummy, true); } /*--------------------------------------------------------------------------*/ bool MODEL_TABLE::parse_params(CS& cmd) { int here = cmd.cursor(); { get(cmd, "Order", &_order); get(cmd, "Below", &_below); get(cmd, "Above", &_above); bool got_opening_paren = cmd.skip1b('('); int here = cmd.cursor(); for (;;) { int start_of_pair = here; std::pair, PARAMETER > p; cmd >> p.first; // key if (cmd.stuck(&here)) { break; }else{ cmd >> p.second; // value if (cmd.stuck(&here)) { cmd.reset(start_of_pair); break; }else{ _table.push_back(p); } } } if (got_opening_paren && !cmd.skip1b(')')) { untested(); cmd.warn(bWARNING, "need )"); }else if (!got_opening_paren && cmd.skip1b(')')) { untested(); cmd.warn(bWARNING, here, "need ("); } } return !(cmd.stuck(&here)); } /*--------------------------------------------------------------------------*/ void MODEL_TABLE::print_front(OMSTREAM& o, LANGUAGE lang)const { assert(lang == lSPICE || lang == lVERILOG); o << "table"; } /*--------------------------------------------------------------------------*/ void MODEL_TABLE::print_params(OMSTREAM& o, LANGUAGE lang)const { assert(lang == lSPICE || lang == lVERILOG); print_pair(o, lang, "order", _order); print_pair_if_has_value(o, lang, "below", _below); print_pair_if_has_value(o, lang, "above", _above); o << " ("; for (std::vector,PARAMETER > >:: const_iterator p = _table.begin(); p != _table.end(); ++p) { o << p->first << ',' << p->second << ' '; } o << ')'; } /*--------------------------------------------------------------------------*/ void MODEL_TABLE::elabo1() { if (1 || !evaluated()) { const CARD_LIST* par_scope = scope(); assert(par_scope); MODEL_CARD::elabo1(); _order.e_val(_default_order, par_scope); _below.e_val(_default_below, par_scope); _above.e_val(_default_above, par_scope); { double last = -BIGBIG; for (std::vector,PARAMETER > >:: iterator p = _table.begin(); p != _table.end(); ++p) { p->first.e_val(0, par_scope); p->second.e_val(0, par_scope); if (last > p->first) { untested(); error(bWARNING, "%s: table is out of order: (%g, %g)\n", long_label().c_str(), last, double(p->first)); }else{ //std::pair x(p->first, p->second); //_num_table.push_back(x); } last = p->first; } } delete _spline; double below = _below.has_value() ? _below : NOT_INPUT; double above = _above.has_value() ? _above : NOT_INPUT; _spline = new SPLINE(_table, below, above, _order); }else{ untested(); } } /*--------------------------------------------------------------------------*/ void MODEL_TABLE::tr_eval(COMPONENT* brh)const { ELEMENT* d = prechecked_cast(brh); assert(d); d->_y0 = _spline->at(d->_y0.x); } /*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/