Merge pull request #2 from ucb-art/primitives_pr

Fix the BAG3 primitives setup to match the technology design parameters.
 * Updated BAG routing grid
 * Updated metal width/space and via specs in `tech_params.yaml`
 * Changed transistor gate and implant implementation in primitives
diff --git a/src/templates_skywater130/data/tech_params.yaml b/src/templates_skywater130/data/tech_params.yaml
index 8bbfd51..b610fed 100644
--- a/src/templates_skywater130/data/tech_params.yaml
+++ b/src/templates_skywater130/data/tech_params.yaml
@@ -85,8 +85,8 @@
     - [[60, .inf]]
     - [[60, 2001]]
   5:
-    - [[320, .inf]]
-    - [[320, .inf]]
+    - [[284, .inf]]
+    - [[284, .inf]]
 
 # mapping from tuple of via layers to via ID.
 via_id:
@@ -227,7 +227,7 @@
     bot_layer: 0
     # wire_w, is_horiz, v_w, v_h, v_sp, v_bot_enc, v_top_enc
     info_list:
-      - [34, True, 34, 34, 34, 16, 16]
+      - [34, True, 34, 34, 34, 10, 10]
       - [52, False, 34, 34, 38, 8, 12]
 
   # minimum horizontal space between OD, in resolution units
@@ -238,8 +238,8 @@
   od_spy_gr: 4000
   # maximum vertical space between OD, in resolution units
   od_spy_max: 4000
-  # set by via enclosure
-  od_po_extx: 56
+  # set by via enclosure, licon.5
+  od_po_extx: 96
 
   # poly.2
   po_spy: 42
@@ -269,7 +269,8 @@
 
   grid_info:
     - [1, 52, 1]
-    - [3, 66, 2]
+    - [3, 66, 1]
+    - [5, 284, 1]
 
 fill: {}
 
@@ -863,3 +864,4 @@
     - [22, 4294967295]
     - [27902976, 4294967295]
     - [6, 4294967295]
+
diff --git a/src/templates_skywater130/mos/tech.py b/src/templates_skywater130/mos/tech.py
index 837dded..437893c 100644
--- a/src/templates_skywater130/mos/tech.py
+++ b/src/templates_skywater130/mos/tech.py
@@ -21,15 +21,15 @@
 #
 # SPDX-License-Identifier: BSD-3-Clause OR Apache 2.0
 
-
-from typing import Tuple, FrozenSet, List
-
+from typing import Tuple, Optional, FrozenSet, List, Mapping, Any
 
 from dataclasses import dataclass
+from itertools import chain
 
 from pybag.enum import Orient2D
-from pybag.core import BBox
+from pybag.core import COORD_MAX, BBox
 
+from bag.util.immutable import ImmutableSortedDict, ImmutableList, Param
 from bag.layout.tech import TechInfo
 from bag.layout.routing.grid import TrackSpec
 from bag.util.immutable import ImmutableSortedDict, ImmutableList, Param
@@ -42,9 +42,10 @@
     MOSRowSpecs, MOSRowInfo, BlkExtInfo, MOSEdgeInfo, MOSLayInfo, ExtWidthInfo, LayoutInfo,
     ExtEndLayInfo, RowExtInfo
 )
-
 from ..util import add_base, get_arr_edge_dim
 
+MConnInfoType = Tuple[int, int, Orient2D, int, Tuple[str, str]]
+
 
 @dataclass(eq=True, frozen=True)
 class ConnInfo:
@@ -95,8 +96,8 @@
 class MOSTechSkywater130(MOSTech):
     ignore_vm_sp_le_layers: FrozenSet[str] = frozenset(('m1',))
 
-    def __init__(self, tech_info: TechInfo, lch: int, mos_entry_name: str = 'mos') -> None:
-        MOSTech.__init__(self, tech_info, lch, mos_entry_name)
+    def __init__(self, tech_info: TechInfo, lch: int, arr_options: Mapping[str, Any]) -> None:
+        MOSTech.__init__(self, tech_info, lch, arr_options) 
 
     @property
     def blk_h_pitch(self) -> int:
@@ -353,7 +354,7 @@
         od_y = self._add_mos_active(builder, row_info, 0, fg, w)
 
         # draw gate connection
-        self._draw_g_conn(builder, sep_g, g_xc, po_y_gate, num_g, g_pitch)
+        self._draw_g_conn(builder, sep_g, g_xc, po_y_gate, fg, g_pitch, g_on_s)
 
         # draw drain/source connections
         d0_info = self.get_conn_info(0, False)
@@ -375,9 +376,7 @@
         else:
             m_info = None
 
-        # draw base
         bbox = BBox(0, 0, fg * sd_pitch, height)
-        add_base(builder, row_type, threshold, imp_y, bbox)
 
         edge_info = MOSEdgeInfo(mos_type=row_type, imp_y=imp_y, has_od=True)
         be = BlkExtInfo(row_type, row_info.threshold, False, ImmutableList([(fg, row_type)]),
@@ -388,7 +387,7 @@
                           shorted_ports=ImmutableList([MOSPortType.G]))
 
     def _draw_g_conn(self, builder: LayoutInfoBuilder, sep_g: bool, g_xc: int,
-                     po_y_gate: Tuple[int, int], num_g: int, conn_pitch: int) -> None:
+                     po_y_gate: Tuple[int, int], fg: int, conn_pitch: int, g_on_s: bool) -> None:
         lch = self.lch
         sd_pitch = self.sd_pitch
 
@@ -404,8 +403,29 @@
         po_lp = ('poly', 'drawing')
         po_conn_w = sd_pitch + lch
         po_xl_gate = g_xc - po_conn_w // 2
-        builder.add_rect_arr(po_lp, BBox(po_xl_gate, po_y_gate[0], po_xl_gate + po_conn_w,
-                                         po_y_gate[1]), nx=num_g, spx=conn_pitch)
+
+        if g_on_s:
+            g_xc = 0
+            num_g = fg // 2 + 1
+            po_xl_even = g_xc
+            po_xh_even = g_xc + sd_pitch // 2 + lch // 2
+            po_xl_odd = sd_pitch + sd_pitch // 2 - lch // 2
+            po_xh_odd = 2 * sd_pitch
+        else:
+            g_xc = sd_pitch
+            num_g = (fg + 1) // 2
+            po_xl_even = sd_pitch // 2 - lch // 2
+            po_xh_even = sd_pitch
+            po_xl_odd = sd_pitch
+            po_xh_odd = sd_pitch + sd_pitch // 2 + lch // 2
+
+        # builder.add_rect_arr(po_lp, BBox(po_xl_gate, po_y_gate[0], po_xl_gate + po_conn_w,
+                                         # po_y_gate[1]), nx=num_g, spx=conn_pitch)
+        builder.add_rect_arr(po_lp, BBox(po_xl_even, po_y_gate[0], po_xh_even, po_y_gate[1]),
+                             nx=(fg - (fg // 2)), spx=conn_pitch)
+        builder.add_rect_arr(po_lp, BBox(po_xl_odd, po_y_gate[0], po_xh_odd, po_y_gate[1]),
+                             nx=(fg // 2), spx=conn_pitch)
+
         po_yc_gate = (po_y_gate[0] + po_y_gate[1]) // 2
         po_h_gate = po_y_gate[1] - po_y_gate[0]
         builder.add_via(g0_info.get_via_info('PYL1_C', g_xc, po_yc_gate, po_h_gate,
@@ -737,6 +757,11 @@
         od_xh = stop * sd_pitch + od_sd_dx
         builder.add_rect_arr(od_lp, BBox(od_xl, od_yl, od_xh, od_yh))
 
+        # draw base
+        imp_od_encx: int = self.mos_config['imp_od_encx']
+        bbox = BBox(od_xl-imp_od_encx, 0, od_xh+imp_od_encx, row_info.height)
+        add_base(builder, row_info.row_type, row_info.threshold, row_info['imp_y'], bbox)
+
         return od_yl, od_yh
 
     def _add_po_array(self, builder: LayoutInfoBuilder, po_y: Tuple[int, int], start: int,
@@ -806,3 +831,4 @@
         xcur = xh
 
     return xcur
+