#!/usr/bin/env python3 # See LICENSE for licensing information. # # Copyright (c) 2016-2023 Regents of the University of California # All rights reserved. # from openram import debug from openram.base import geometry from openram.modules import bitcell_base_array from openram.sram_factory import factory from openram.tech import layer from openram import OPTS from openram.modules import pattern class sky130_bitcell_base_array(bitcell_base_array): """ Abstract base class for bitcell-arrays -- bitcell, dummy, replica """ def __init__(self, name, rows, cols, column_offset, row_offset): super().__init__(name, rows, cols, column_offset, row_offset) debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols)) self.cell = factory.create(module_type=OPTS.bitcell, version="opt1") def get_bitcell_pins(self, row, col, swap = False): """ Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array """ bitcell_pins = [] for port in self.all_ports: bitcell_pins.extend([x for x in self.get_bitline_names(port) if x.endswith("_{0}".format(col))]) bitcell_pins.append("gnd") # gnd bitcell_pins.append("vdd") # vdd bitcell_pins.append("vdd") # vpb bitcell_pins.append("gnd") # vnb bitcell_pins.extend([x for x in self.all_wordline_names if x.endswith("_{0}".format(row))]) return bitcell_pins def get_strap_pins(self, row, col, name=""): """ Creates a list of connections in the strap cell, indexed by column and row, for instance use in bitcell_array """ if name and "_p" in name: strap_pins = ["gnd"] else: strap_pins = ["vdd"] return strap_pins def get_col_cap_p_pins(self, row, col): """ """ strap_pins = ["gnd", "vdd", "gnd"] return strap_pins def get_col_cap_pins(self, row, col): """ """ strap_pins = [] for port in self.all_ports: strap_pins.extend([x for x in self.get_bitline_names(port) if "bl" in x and x.endswith("_{0}".format(col))]) for port in self.all_ports: strap_pins.extend([x for x in self.get_bitline_names(port) if "br" in x and x.endswith("_{0}".format(col))]) # col_cap_1port_bitcell port order: # [bl, br, vdd, gnd, vpb, vnb, gate] strap_pins.extend(["vdd", "gnd", "vdd", "gnd"]) if row == 0: strap_pins.append("top_gate") else: strap_pins.append("bot_gate") return strap_pins def get_row_cap_pins(self, row, col): """ """ strap_pins = ["gnd", "vdd", "gnd"] return strap_pins def get_corner_pins(self): """ """ strap_pins = ["vdd", "gnd", "vdd"] return strap_pins def route_supplies(self): # Copy a vdd/gnd layout pin from every cell super().route_supplies() for inst in self.insts: if "VPWR" in inst.mod.pins: self.copy_layout_pin(inst, "VPWR", "vdd") if "VGND" in inst.mod.pins: self.copy_layout_pin(inst, "VGND", "gnd") if hasattr(self, 'cell_inst'): for col in range(self.column_size): inst = self.cell_inst[0,col] pin = inst.get_pin("vpb") self.objs.append(geometry.rectangle(layer["nwell"], pin.ll(), pin.width(), pin.height())) self.objs.append(geometry.label("vdd", layer["nwell"], pin.center())) try: from openram.tech import layer_override if layer_override['VNB']: pin = inst.get_pin("vnb") self.objs.append(geometry.label("gnd", layer["pwellp"], pin.center())) self.objs.append(geometry.rectangle(layer["pwellp"], pin.ll(), pin.width(), pin.height())) except: pin = inst.get_pin("vnb") self.add_label("vdd", pin.layer, pin.center())