Table of Contents

Matrix Solver Plugins

Framework

Like other plugins, solvers are loaded using the load command or -a cmdline argument. The SIM_DATA class has two matrices, _aa and _lu. The former for dc/tran/op (real valued) and the latter for small signal analysis like ac, pz, noise etc. (complex). SIM_DATA is currently statically instanciated in CKT_BASE::_sim.

A matrix is a BSMATRIX<numerical_type>, a “bump and spike” structure for storage. It has a pointer to a solver of type BSMATRIX_SOLVER<numerical_type>, which has a reference to the matrix to solve and a virtual interface. A solver plugin essentially attaches a solver to a matrix, replacing the current solver.

struct set{
  set(){ 
    auto x = new MY_SOLVER<double>(CKT_BASE::_sim->_aa);
    CKT_BASE::_sim->_aa.set_solver(x);
  }
  ~set(){
    CKT_BASE::_sim->_aa.set_solver(nullptr);
  }
} s;

The simulator will call virtual functions in the solver that MY_SOLVER is expected to implement. These are (see m_matrix.h for the definite interface) as follows.

  virtual void init(int ss) = 0;
  virtual void uninit() = 0;
  virtual void iwant(int, int);
  virtual void allocate() = 0;
  virtual void unallocate() = 0;
  virtual void set_min_pivot(double x) = 0;

  virtual void lu_decomp(bool do_partial) = 0;
  virtual void fbsub(T*) const;
  virtual void fbsub(T* x, const T* b, T* c = nullptr)const;
  virtual void fbsubt(T*) const;
  
  virtual void zero();
  
  virtual void load_diagonal_point(int i, T value);
  virtual void load_point(int i, int j, T value);
  virtual void load_couple(int i, int j, T value);
  virtual void load_symmetric(int i, int j, T value);
  virtual void load_asymmetric(int r1, int r2, int c1, int c2, T value);

Once a matrix is initialised (ss=number of rows/columns), it accepts “iwant” calls passing the coordinates that devices will load into later on. The allocate function is meant to arrange memory for both the load_* and lu_decomp calls. Forward/backward substitution is provided as usual, with variants for “separate output memory” and “transposed”.

Examples

Gnucap has two solvers built in and set by default, see m_matrix_solver.h. An in-place solver, LU_INPLACE, for use in small signal analysis. Another, LU_COPY, solves a copy of the matrix, allowing for partial updates, in cases where repeated solutions of very similar matrices are required.

A compressed sparse version of LU_COPY is (currently) available in tests/cbs.cc. It reduces both the memory use, by computing the exact footprint prior to allocation, and saves time by avoiding operations involving the known zeroes. It also tweaks propagation rules a bit, still numerical results are identical to LU_COPY, by construction.

Using alternative general purpose solvers like KLU or UMFPACK is relatively easy, and wrapper plugins are circulating. Now here's the platform to develop and benchmark the next generation (free/libre) matrix solvers ready for VLSI.