| { |
| "cells": [ |
| { |
| "cell_type": "markdown", |
| "metadata": {}, |
| "source": [ |
| "## SF Amplifier Solution\n", |
| "\n", |
| "The following cell contains the source-follwer amplifier layout solution. If you evaluate the following cell LVS should pass." |
| ] |
| }, |
| { |
| "cell_type": "code", |
| "execution_count": 5, |
| "metadata": {}, |
| "outputs": [ |
| { |
| "name": "stdout", |
| "output_type": "stream", |
| "text": [ |
| "using existing BagProject\n", |
| "computing layout\n", |
| "ext_w0 = 1, ext_wend=7, ytop=2880\n", |
| "ext_w0 = 2, ext_wend=9, ytop=3024\n", |
| "final: ext_w0 = 1, ext_wend=7, ytop=2880\n", |
| "creating layout\n", |
| "layout done\n", |
| "computing AMP_SF schematics\n", |
| "creating AMP_SF schematics\n", |
| "running lvs\n", |
| "Running tasks, Press Ctrl-C to cancel.\n", |
| "lvs passed\n", |
| "lvs log is /users/erichang/projects/bag_gen/BAG2_cds_ff_mpt/pvs_run/lvs_run_dir/DEMO_AMP_SF/AMP_SF/lvsLog_20180906_110128hvrv5244\n", |
| "LVS flow done\n" |
| ] |
| } |
| ], |
| "source": [ |
| "from abs_templates_ec.analog_core import AnalogBase\n", |
| "\n", |
| "\n", |
| "\n", |
| "class AmpSF(AnalogBase):\n", |
| " \"\"\"A template of a single transistor with dummies.\n", |
| "\n", |
| " This class is mainly used for transistor characterization or\n", |
| " design exploration with config views.\n", |
| "\n", |
| " Parameters\n", |
| " ----------\n", |
| " temp_db : :class:`bag.layout.template.TemplateDB`\n", |
| " the template database.\n", |
| " lib_name : str\n", |
| " the layout library name.\n", |
| " params : dict[str, any]\n", |
| " the parameter values.\n", |
| " used_names : set[str]\n", |
| " a set of already used cell names.\n", |
| " kwargs : dict[str, any]\n", |
| " dictionary of optional parameters. See documentation of\n", |
| " :class:`bag.layout.template.TemplateBase` for details.\n", |
| " \"\"\"\n", |
| "\n", |
| " def __init__(self, temp_db, lib_name, params, used_names, **kwargs):\n", |
| " AnalogBase.__init__(self, temp_db, lib_name, params, used_names, **kwargs)\n", |
| " self._sch_params = None\n", |
| "\n", |
| " @property\n", |
| " def sch_params(self):\n", |
| " return self._sch_params\n", |
| "\n", |
| " @classmethod\n", |
| " def get_params_info(cls):\n", |
| " \"\"\"Returns a dictionary containing parameter descriptions.\n", |
| "\n", |
| " Override this method to return a dictionary from parameter names to descriptions.\n", |
| "\n", |
| " Returns\n", |
| " -------\n", |
| " param_info : dict[str, str]\n", |
| " dictionary from parameter name to description.\n", |
| " \"\"\"\n", |
| " return dict(\n", |
| " lch='channel length, in meters.',\n", |
| " w_dict='width dictionary.',\n", |
| " intent_dict='intent dictionary.',\n", |
| " fg_dict='number of fingers dictionary.',\n", |
| " ndum='number of dummies on each side.',\n", |
| " ptap_w='NMOS substrate width, in meters/number of fins.',\n", |
| " ntap_w='PMOS substrate width, in meters/number of fins.',\n", |
| " show_pins='True to draw pin geometries.',\n", |
| " )\n", |
| "\n", |
| " def draw_layout(self):\n", |
| " \"\"\"Draw the layout of a transistor for characterization.\n", |
| " \"\"\"\n", |
| "\n", |
| " lch = self.params['lch']\n", |
| " w_dict = self.params['w_dict']\n", |
| " intent_dict = self.params['intent_dict']\n", |
| " fg_dict = self.params['fg_dict']\n", |
| " ndum = self.params['ndum']\n", |
| " ptap_w = self.params['ptap_w']\n", |
| " ntap_w = self.params['ntap_w']\n", |
| " show_pins = self.params['show_pins']\n", |
| "\n", |
| " fg_amp = fg_dict['amp']\n", |
| " fg_bias = fg_dict['bias']\n", |
| "\n", |
| " if fg_bias % 2 != 0 or fg_amp % 2 != 0:\n", |
| " raise ValueError('fg_bias=%d and fg_amp=%d must all be even.' % (fg_bias, fg_amp))\n", |
| "\n", |
| " fg_half_bias = fg_bias // 2\n", |
| " fg_half_amp = fg_amp // 2\n", |
| " fg_half = max(fg_half_bias, fg_half_amp)\n", |
| " fg_tot = (fg_half + ndum) * 2\n", |
| "\n", |
| " nw_list = [w_dict['bias'], w_dict['amp']]\n", |
| " nth_list = [intent_dict['bias'], intent_dict['amp']]\n", |
| "\n", |
| " ng_tracks = [1, 3]\n", |
| " nds_tracks = [1, 1]\n", |
| "\n", |
| " n_orient = ['R0', 'MX']\n", |
| "\n", |
| " self.draw_base(lch, fg_tot, ptap_w, ntap_w, nw_list,\n", |
| " nth_list, [], [],\n", |
| " ng_tracks=ng_tracks, nds_tracks=nds_tracks,\n", |
| " pg_tracks=[], pds_tracks=[],\n", |
| " n_orientations=n_orient,\n", |
| " )\n", |
| "\n", |
| " if (fg_amp - fg_bias) % 4 == 0:\n", |
| " s_net, d_net = 'VDD', 'vout'\n", |
| " aout, aoutb, nsdir, nddir = 'd', 's', 2, 0\n", |
| " else:\n", |
| " s_net, d_net = 'vout', 'VDD'\n", |
| " aout, aoutb, nsdir, nddir = 's', 'd', 0, 2\n", |
| "\n", |
| " bias_col = ndum + fg_half - fg_half_bias\n", |
| " amp_col = ndum + fg_half - fg_half_amp\n", |
| " amp_ports = self.draw_mos_conn('nch', 1, amp_col, fg_amp, nsdir, nddir,\n", |
| " s_net=s_net, d_net=d_net)\n", |
| " bias_ports = self.draw_mos_conn('nch', 0, bias_col, fg_bias, 0, 2,\n", |
| " s_net='', d_net='vout')\n", |
| "\n", |
| " vdd_tid = self.make_track_id('nch', 1, 'g', 0)\n", |
| " vin_tid = self.make_track_id('nch', 1, 'g', 2)\n", |
| " vout_tid = self.make_track_id('nch', 0, 'ds', 0)\n", |
| " vbias_tid = self.make_track_id('nch', 0, 'g', 0)\n", |
| "\n", |
| " vin_warr = self.connect_to_tracks(amp_ports['g'], vin_tid)\n", |
| " vout_warr = self.connect_to_tracks([amp_ports[aout], bias_ports['d']], vout_tid)\n", |
| " vbias_warr = self.connect_to_tracks(bias_ports['g'], vbias_tid)\n", |
| " vdd_warr = self.connect_to_tracks(amp_ports[aoutb], vdd_tid)\n", |
| " self.connect_to_substrate('ptap', bias_ports['s'])\n", |
| "\n", |
| " vss_warrs, _ = self.fill_dummy()\n", |
| "\n", |
| " self.add_pin('VSS', vss_warrs, show=show_pins)\n", |
| " self.add_pin('VDD', vdd_warr, show=show_pins)\n", |
| " self.add_pin('vin', vin_warr, show=show_pins)\n", |
| " self.add_pin('vout', vout_warr, show=show_pins)\n", |
| " self.add_pin('vbias', vbias_warr, show=show_pins)\n", |
| "\n", |
| " self._sch_params = dict(\n", |
| " lch=lch,\n", |
| " w_dict=w_dict,\n", |
| " intent_dict=intent_dict,\n", |
| " fg_dict=fg_dict,\n", |
| " dum_info=self.get_sch_dummy_info(),\n", |
| " )\n", |
| "\n", |
| "\n", |
| "import os\n", |
| "\n", |
| "# import bag package\n", |
| "import bag\n", |
| "from bag.io import read_yaml\n", |
| "\n", |
| "# import BAG demo Python modules\n", |
| "import xbase_demo.core as demo_core\n", |
| "from xbase_demo.demo_layout.core import AmpSFSoln\n", |
| "\n", |
| "# load circuit specifications from file\n", |
| "spec_fname = os.path.join(os.environ['BAG_WORK_DIR'], 'specs_demo/demo.yaml')\n", |
| "top_specs = read_yaml(spec_fname)\n", |
| "\n", |
| "# obtain BagProject instance\n", |
| "local_dict = locals()\n", |
| "if 'bprj' in local_dict:\n", |
| " print('using existing BagProject')\n", |
| " bprj = local_dict['bprj']\n", |
| "else:\n", |
| " print('creating BagProject')\n", |
| " bprj = bag.BagProject()\n", |
| "\n", |
| "demo_core.run_flow(bprj, top_specs, 'amp_sf_soln', AmpSF, run_lvs=True, lvs_only=True)" |
| ] |
| } |
| ], |
| "metadata": { |
| "anaconda-cloud": {}, |
| "kernelspec": { |
| "display_name": "Python 3", |
| "language": "python", |
| "name": "python3" |
| }, |
| "language_info": { |
| "codemirror_mode": { |
| "name": "ipython", |
| "version": 3 |
| }, |
| "file_extension": ".py", |
| "mimetype": "text/x-python", |
| "name": "python", |
| "nbconvert_exporter": "python", |
| "pygments_lexer": "ipython3", |
| "version": "3.6.5" |
| } |
| }, |
| "nbformat": 4, |
| "nbformat_minor": 1 |
| } |