Merge branch 'laptop_checkpoint' into dev

This commit is contained in:
mrg 2021-06-04 15:22:37 -07:00
commit cf61096936
20 changed files with 210 additions and 73 deletions

View File

@ -176,7 +176,7 @@ class cell_properties():
self.names["col_cap_bitcell_2port"] = "col_cap_cell_2rw" self.names["col_cap_bitcell_2port"] = "col_cap_cell_2rw"
self.names["row_cap_bitcell_1port"] = "row_cap_cell_1rw" self.names["row_cap_bitcell_1port"] = "row_cap_cell_1rw"
self.names["row_cap_bitcell_2port"] = "row_cap_cell_2rw" self.names["row_cap_bitcell_2port"] = "row_cap_cell_2rw"
self.use_strap = False
self._ptx = _ptx(model_is_subckt=False, self._ptx = _ptx(model_is_subckt=False,
bin_spice_models=False) bin_spice_models=False)

View File

@ -49,6 +49,7 @@ class design(hierarchy_design):
self.add_pin_names(prop.port_map) self.add_pin_names(prop.port_map)
self.add_pin_types(prop.port_types) self.add_pin_types(prop.port_types)
(width, height) = utils.get_libcell_size(self.cell_name, (width, height) = utils.get_libcell_size(self.cell_name,
GDS["unit"], GDS["unit"],
layer[prop.boundary_layer]) layer[prop.boundary_layer])

View File

@ -1257,22 +1257,24 @@ class layout():
height=ymax - ymin) height=ymax - ymin)
return rect return rect
def copy_power_pins(self, inst, name, add_vias=True): def copy_power_pins(self, inst, name, add_vias=True, new_name=""):
""" """
This will copy a power pin if it is on the lowest power_grid layer. This will copy a power pin if it is on the lowest power_grid layer.
If it is on M1, it will add a power via too. If it is on M1, it will add a power via too.
""" """
pins = inst.get_pins(name) pins = inst.get_pins(name)
for pin in pins: for pin in pins:
if new_name == "":
new_name = pin.name
if pin.layer == self.pwr_grid_layer: if pin.layer == self.pwr_grid_layer:
self.add_layout_pin(name, self.add_layout_pin(new_name,
pin.layer, pin.layer,
pin.ll(), pin.ll(),
pin.width(), pin.width(),
pin.height()) pin.height())
elif add_vias: elif add_vias:
self.copy_power_pin(pin) self.copy_power_pin(pin, new_name=new_name)
def add_io_pin(self, instance, pin_name, new_name, start_layer=None): def add_io_pin(self, instance, pin_name, new_name, start_layer=None):
""" """
@ -1318,13 +1320,15 @@ class layout():
width=width, width=width,
height=height) height=height)
def copy_power_pin(self, pin, loc=None, directions=None): def copy_power_pin(self, pin, loc=None, directions=None, new_name=""):
""" """
Add a single power pin from the lowest power_grid layer down to M1 (or li) at Add a single power pin from the lowest power_grid layer down to M1 (or li) at
the given center location. The starting layer is specified to determine the given center location. The starting layer is specified to determine
which vias are needed. which vias are needed.
""" """
if new_name == "":
new_name = pin.name
if not loc: if not loc:
loc = pin.center() loc = pin.center()
@ -1338,7 +1342,7 @@ class layout():
height = None height = None
if pin.layer == self.pwr_grid_layer: if pin.layer == self.pwr_grid_layer:
self.add_layout_pin_rect_center(text=pin.name, self.add_layout_pin_rect_center(text=new_name,
layer=self.pwr_grid_layer, layer=self.pwr_grid_layer,
offset=loc, offset=loc,
width=width, width=width,
@ -1353,7 +1357,7 @@ class layout():
width = via.width width = via.width
if not height: if not height:
height = via.height height = via.height
self.add_layout_pin_rect_center(text=pin.name, self.add_layout_pin_rect_center(text=new_name,
layer=self.pwr_grid_layer, layer=self.pwr_grid_layer,
offset=loc, offset=loc,
width=width, width=width,

View File

@ -148,11 +148,14 @@ def get_gds_pins(pin_names, name, gds_filename, units):
cell[str(pin_name)] = [] cell[str(pin_name)] = []
pin_list = cell_vlsi.getPinShape(str(pin_name)) pin_list = cell_vlsi.getPinShape(str(pin_name))
for pin_shape in pin_list: for pin_shape in pin_list:
if pin_shape != None:
(lpp, boundary) = pin_shape (lpp, boundary) = pin_shape
rect = [vector(boundary[0], boundary[1]), rect = [vector(boundary[0], boundary[1]),
vector(boundary[2], boundary[3])] vector(boundary[2], boundary[3])]
# this is a list because other cells/designs # this is a list because other cells/designs
# may have must-connect pins # may have must-connect pins
if isinstance(lpp[1], list):
lpp = (lpp[0], None)
cell[str(pin_name)].append(pin_layout(pin_name, rect, lpp)) cell[str(pin_name)].append(pin_layout(pin_name, rect, lpp))
_GDS_PINS_CACHE[k] = cell _GDS_PINS_CACHE[k] = cell

View File

@ -3,7 +3,7 @@ from datetime import *
import numpy as np import numpy as np
import math import math
import debug import debug
from tech import use_purpose
class VlsiLayout: class VlsiLayout:
"""Class represent a hierarchical layout""" """Class represent a hierarchical layout"""
@ -215,8 +215,12 @@ class VlsiLayout:
self.deduceHierarchy() self.deduceHierarchy()
# self.traverseTheHierarchy() # self.traverseTheHierarchy()
self.populateCoordinateMap() self.populateCoordinateMap()
#only ones with text
for layerNumber in self.layerNumbersInUse: for layerNumber in self.layerNumbersInUse:
#if layerNumber not in no_pin_shape:
if layerNumber in use_purpose:
self.processLabelPins((layerNumber, use_purpose[layerNumber]))
else:
self.processLabelPins((layerNumber, None)) self.processLabelPins((layerNumber, None))
def populateCoordinateMap(self): def populateCoordinateMap(self):
@ -903,6 +907,16 @@ def sameLPP(lpp1, lpp2):
if lpp1[1] == None or lpp2[1] == None: if lpp1[1] == None or lpp2[1] == None:
return lpp1[0] == lpp2[0] return lpp1[0] == lpp2[0]
if isinstance(lpp1[1], list):
for i in range(len(lpp1[1])):
if lpp1[0] == lpp2[0] and lpp1[1][i] == lpp2[1]:
return True
if isinstance(lpp2[1], list):
for i in range(len(lpp2[1])):
if lpp1[0] == lpp2[0] and lpp1[1] == lpp2[1][i]:
return True
return lpp1[0] == lpp2[0] and lpp1[1] == lpp2[1] return lpp1[0] == lpp2[0] and lpp1[1] == lpp2[1]

View File

@ -238,8 +238,8 @@ def setup_bitcell():
OPTS.dummy_bitcell = "dummy_pbitcell" OPTS.dummy_bitcell = "dummy_pbitcell"
OPTS.replica_bitcell = "replica_pbitcell" OPTS.replica_bitcell = "replica_pbitcell"
else: else:
num_ports = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports OPTS.num_ports = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports
OPTS.bitcell = "bitcell_{}port".format(num_ports) OPTS.bitcell = "bitcell_{}port".format(OPTS.num_ports)
OPTS.dummy_bitcell = "dummy_" + OPTS.bitcell OPTS.dummy_bitcell = "dummy_" + OPTS.bitcell
OPTS.replica_bitcell = "replica_" + OPTS.bitcell OPTS.replica_bitcell = "replica_" + OPTS.bitcell

View File

@ -366,18 +366,13 @@ class bank(design.design):
# A space for wells or jogging m2 # A space for wells or jogging m2
self.m2_gap = max(2 * drc("pwell_to_nwell") + drc("nwell_enclose_active"), self.m2_gap = max(2 * drc("pwell_to_nwell") + drc("nwell_enclose_active"),
3 * self.m2_pitch) 3 * self.m2_pitch,
drc("nwell_to_nwell"))
def add_modules(self): def add_modules(self):
""" Add all the modules using the class loader """ """ Add all the modules using the class loader """
self.port_address = []
for port in self.all_ports:
self.port_address.append(factory.create(module_type="port_address",
cols=self.num_cols + self.num_spare_cols,
rows=self.num_rows,
port=port))
self.add_mod(self.port_address[port])
local_array_size = OPTS.local_array_size local_array_size = OPTS.local_array_size
@ -397,12 +392,26 @@ class bank(design.design):
cols=self.num_cols + self.num_spare_cols, cols=self.num_cols + self.num_spare_cols,
rows=self.num_rows) rows=self.num_rows)
self.add_mod(self.bitcell_array) self.add_mod(self.bitcell_array)
if self.num_spare_cols == 0:
self.num_spare_cols = (self.bitcell_array.column_size % (self.word_size *self.words_per_row))
self.port_address = []
for port in self.all_ports:
self.port_address.append(factory.create(module_type="port_address",
cols=self.bitcell_array.column_size,
rows=self.bitcell_array.row_size,
port=port))
self.add_mod(self.port_address[port])
self.port_data = [] self.port_data = []
self.bit_offsets = self.get_column_offsets() self.bit_offsets = self.get_column_offsets()
for port in self.all_ports: for port in self.all_ports:
temp_pre = factory.create(module_type="port_data", temp_pre = factory.create(module_type="port_data",
sram_config=self.sram_config, sram_config=self.sram_config,
dimension_override=True,
cols=self.bitcell_array.column_size - self.num_spare_cols,
rows=self.bitcell_array.row_size,
num_spare_cols=self.num_spare_cols,
port=port, port=port,
bit_offsets=self.bit_offsets) bit_offsets=self.bit_offsets)
self.port_data.append(temp_pre) self.port_data.append(temp_pre)
@ -430,7 +439,9 @@ class bank(design.design):
temp.append("vdd") temp.append("vdd")
temp.append("gnd") temp.append("gnd")
if 'vpb' in self.bitcell_array_inst.mod.pins and 'vnb' in self.bitcell_array_inst.mod.pins:
temp.append('vpb')
temp.append('vnb')
self.connect_inst(temp) self.connect_inst(temp)
def place_bitcell_array(self, offset): def place_bitcell_array(self, offset):
@ -489,7 +500,7 @@ class bank(design.design):
mod=self.port_address[port]) mod=self.port_address[port])
temp = [] temp = []
for bit in range(self.row_addr_size): for bit in range(ceil(log(self.bitcell_array.row_size, 2))):
temp.append("addr{0}_{1}".format(port, bit + self.col_addr_size)) temp.append("addr{0}_{1}".format(port, bit + self.col_addr_size))
temp.append("wl_en{}".format(port)) temp.append("wl_en{}".format(port))
wordline_names = self.bitcell_array.get_wordline_names(port) wordline_names = self.bitcell_array.get_wordline_names(port)
@ -614,6 +625,10 @@ class bank(design.design):
self.copy_power_pins(inst, "vdd", add_vias=False) self.copy_power_pins(inst, "vdd", add_vias=False)
self.copy_power_pins(inst, "gnd", add_vias=False) self.copy_power_pins(inst, "gnd", add_vias=False)
if 'vpb' in self.bitcell_array_inst.mod.pins and 'vnb' in self.bitcell_array_inst.mod.pins:
for pin_name, supply_name in zip(['vpb','vnb'],['vdd','gnd']):
self.copy_power_pins(self.bitcell_array_inst, pin_name, new_name=supply_name)
# If we use the pinvbuf as the decoder, we need to add power pins. # If we use the pinvbuf as the decoder, we need to add power pins.
# Other decoders already have them. # Other decoders already have them.
if self.col_addr_size == 1: if self.col_addr_size == 1:
@ -1062,7 +1077,6 @@ class bank(design.design):
to_layer="m2", to_layer="m2",
offset=control_pos) offset=control_pos)
def graph_exclude_precharge(self): def graph_exclude_precharge(self):
""" """
Precharge adds a loop between bitlines, can be excluded to reduce complexity Precharge adds a loop between bitlines, can be excluded to reduce complexity

View File

@ -12,6 +12,10 @@ from vector import vector
from sram_factory import factory from sram_factory import factory
from globals import OPTS from globals import OPTS
from tech import layer_properties as layer_props from tech import layer_properties as layer_props
from tech import layer_indices
from tech import layer_stacks
from tech import preferred_directions
from tech import drc
class hierarchical_predecode(design.design): class hierarchical_predecode(design.design):
@ -29,7 +33,7 @@ class hierarchical_predecode(design.design):
self.cell_height = height self.cell_height = height
self.column_decoder = column_decoder self.column_decoder = column_decoder
self.input_and_rail_pos = []
self.number_of_outputs = int(math.pow(2, self.number_of_inputs)) self.number_of_outputs = int(math.pow(2, self.number_of_inputs))
super().__init__(name) super().__init__(name)
@ -183,9 +187,9 @@ class hierarchical_predecode(design.design):
def route(self): def route(self):
self.route_input_inverters() self.route_input_inverters()
self.route_input_ands()
self.route_output_inverters() self.route_output_inverters()
self.route_inputs_to_rails() self.route_inputs_to_rails()
self.route_input_ands()
self.route_output_ands() self.route_output_ands()
self.route_vdd_gnd() self.route_vdd_gnd()
@ -274,8 +278,46 @@ class hierarchical_predecode(design.design):
# pins in the and gates. # pins in the and gates.
inv_out_pos = inv_out_pin.rc() inv_out_pos = inv_out_pin.rc()
y_offset = (inv_num + 1) * self.inv.height - self.output_layer_pitch y_offset = (inv_num + 1) * self.inv.height - self.output_layer_pitch
right_pos = inv_out_pos + vector(self.inv.width - self.inv.get_pin("Z").rx(), 0)
rail_pos = vector(self.decode_rails[out_pin].cx(), y_offset) rail_pos = vector(self.decode_rails[out_pin].cx(), y_offset)
# create via for dimensions
from_layer = self.output_layer
to_layer = self.bus_layer
cur_layer = from_layer
from_id = layer_indices[cur_layer]
to_id = layer_indices[to_layer]
if from_id < to_id: # grow the stack up
search_id = 0
next_id = 2
else: # grow the stack down
search_id = 2
next_id = 0
curr_stack = next(filter(lambda stack: stack[search_id] == cur_layer, layer_stacks), None)
via = factory.create(module_type="contact",
layer_stack=curr_stack,
dimensions=[1, 1],
directions=self.bus_directions)
overlapping_pin_space = drc["{0}_to_{0}".format(self.output_layer)]
total_buffer_space = (overlapping_pin_space + via.height)
#FIXME: compute rail locations instead of just guessing and nudging
while(True):
drc_error = 0
for and_input in self.input_and_rail_pos:
if and_input.x == rail_pos.x:
if (abs(y_offset - and_input.y) < total_buffer_space) and (abs(y_offset - and_input.y) > via.height):
drc_error = 1
if drc_error == 0:
break
else:
y_offset += drc["grid"]
rail_pos.y = y_offset
right_pos = inv_out_pos + vector(self.inv.width - self.inv.get_pin("Z").rx(), 0)
self.add_path(self.output_layer, [inv_out_pos, right_pos, vector(right_pos.x, y_offset), rail_pos]) self.add_path(self.output_layer, [inv_out_pos, right_pos, vector(right_pos.x, y_offset), rail_pos])
self.add_via_stack_center(from_layer=inv_out_pin.layer, self.add_via_stack_center(from_layer=inv_out_pin.layer,
@ -316,6 +358,7 @@ class hierarchical_predecode(design.design):
to_layer=self.bus_layer, to_layer=self.bus_layer,
offset=rail_pos, offset=rail_pos,
directions=self.bus_directions) directions=self.bus_directions)
self.input_and_rail_pos.append(rail_pos)
if gate_pin == "A": if gate_pin == "A":
direction = None direction = None
else: else:

View File

@ -11,6 +11,7 @@ from sram_factory import factory
from collections import namedtuple from collections import namedtuple
from vector import vector from vector import vector
from globals import OPTS from globals import OPTS
from tech import cell_properties
from tech import layer_properties as layer_props from tech import layer_properties as layer_props
@ -20,26 +21,36 @@ class port_data(design.design):
Port 0 always has the RBL on the left while port 1 is on the right. Port 0 always has the RBL on the left while port 1 is on the right.
""" """
def __init__(self, sram_config, port, bit_offsets=None, name=""): def __init__(self, sram_config, port, num_spare_cols=None, bit_offsets=None, name="", rows=None, cols=None, dimension_override=False):
sram_config.set_local_config(self) sram_config.set_local_config(self)
if dimension_override:
self.num_rows = rows
self.num_cols = cols
self.word_size = sram_config.word_size
self.port = port self.port = port
if self.write_size is not None: if self.write_size is not None:
self.num_wmasks = int(math.ceil(self.word_size / self.write_size)) self.num_wmasks = int(math.ceil(self.word_size / self.write_size))
else: else:
self.num_wmasks = 0 self.num_wmasks = 0
if self.num_spare_cols is None: if num_spare_cols:
self.num_spare_cols = num_spare_cols
elif self.num_spare_cols is None:
self.num_spare_cols = 0 self.num_spare_cols = 0
if not bit_offsets: if not bit_offsets:
bitcell = factory.create(module_type=OPTS.bitcell) bitcell = factory.create(module_type=OPTS.bitcell)
if(cell_properties.use_strap == True and OPTS.num_ports == 1):
strap = factory.create(module_type=cell_properties.strap_module, version=cell_properties.strap_version)
precharge_width = bitcell.width + strap.width
else:
precharge_width = bitcell.width
self.bit_offsets = [] self.bit_offsets = []
for i in range(self.num_cols + self.num_spare_cols): for i in range(self.num_cols + self.num_spare_cols):
self.bit_offsets.append(i * bitcell.width) self.bit_offsets.append(i * precharge_width)
else: else:
self.bit_offsets = bit_offsets self.bit_offsets = bit_offsets
if name == "": if name == "":
name = "port_data_{0}".format(self.port) name = "port_data_{0}".format(self.port)
super().__init__(name) super().__init__(name)
@ -117,7 +128,6 @@ class port_data(design.design):
for bit in range(self.num_spare_cols): for bit in range(self.num_spare_cols):
self.add_pin("sparebl_{0}".format(bit), "INOUT") self.add_pin("sparebl_{0}".format(bit), "INOUT")
self.add_pin("sparebr_{0}".format(bit), "INOUT") self.add_pin("sparebr_{0}".format(bit), "INOUT")
if self.port in self.read_ports: if self.port in self.read_ports:
for bit in range(self.word_size + self.num_spare_cols): for bit in range(self.word_size + self.num_spare_cols):
self.add_pin("dout_{}".format(bit), "OUTPUT") self.add_pin("dout_{}".format(bit), "OUTPUT")
@ -191,14 +201,19 @@ class port_data(design.design):
# and mirroring happens correctly # and mirroring happens correctly
# Used for names/dimensions only # Used for names/dimensions only
self.cell = factory.create(module_type=OPTS.bitcell) cell = factory.create(module_type=OPTS.bitcell)
if(cell_properties.use_strap == True and OPTS.num_ports == 1):
strap = factory.create(module_type=cell_properties.strap_module, version=cell_properties.strap_version)
precharge_width = cell.width + strap.width
else:
precharge_width = cell.width
if self.port == 0: if self.port == 0:
# Append an offset on the left # Append an offset on the left
precharge_bit_offsets = [self.bit_offsets[0] - self.cell.width] + self.bit_offsets precharge_bit_offsets = [self.bit_offsets[0] - precharge_width] + self.bit_offsets
else: else:
# Append an offset on the right # Append an offset on the right
precharge_bit_offsets = self.bit_offsets + [self.bit_offsets[-1] + self.cell.width] precharge_bit_offsets = self.bit_offsets + [self.bit_offsets[-1] + precharge_width]
self.precharge_array = factory.create(module_type="precharge_array", self.precharge_array = factory.create(module_type="precharge_array",
columns=self.num_cols + self.num_spare_cols + 1, columns=self.num_cols + self.num_spare_cols + 1,
offsets=precharge_bit_offsets, offsets=precharge_bit_offsets,
@ -567,7 +582,7 @@ class port_data(design.design):
off = 1 off = 1
else: else:
off = 0 off = 0
if OPTS.num_ports > 1:
self.channel_route_bitlines(inst1=self.column_mux_array_inst, self.channel_route_bitlines(inst1=self.column_mux_array_inst,
inst1_bls_template="{inst}_out_{bit}", inst1_bls_template="{inst}_out_{bit}",
inst2=inst2, inst2=inst2,
@ -580,6 +595,19 @@ class port_data(design.design):
num_bits=self.num_spare_cols, num_bits=self.num_spare_cols,
inst1_start_bit=self.num_cols + off, inst1_start_bit=self.num_cols + off,
inst2_start_bit=self.word_size) inst2_start_bit=self.word_size)
else:
self.connect_bitlines(inst1=self.column_mux_array_inst,
inst1_bls_template="{inst}_out_{bit}",
inst2=inst2,
num_bits=self.word_size,
inst1_start_bit=start_bit)
self.connect_bitlines(inst1=self.precharge_array_inst,
inst1_bls_template="{inst}_{bit}",
inst2=inst2,
num_bits=self.num_spare_cols,
inst1_start_bit=self.num_cols + off,
inst2_start_bit=self.word_size)
elif layer_props.port_data.channel_route_bitlines: elif layer_props.port_data.channel_route_bitlines:
self.channel_route_bitlines(inst1=inst1, self.channel_route_bitlines(inst1=inst1,

View File

@ -76,8 +76,8 @@ class precharge_array(design.design):
size=self.size, size=self.size,
bitcell_bl=self.bitcell_bl, bitcell_bl=self.bitcell_bl,
bitcell_br=self.bitcell_br) bitcell_br=self.bitcell_br)
self.add_mod(self.pc_cell)
self.add_mod(self.pc_cell)
self.cell = factory.create(module_type=OPTS.bitcell) self.cell = factory.create(module_type=OPTS.bitcell)
def add_layout_pins(self): def add_layout_pins(self):

View File

@ -6,7 +6,7 @@
import debug import debug
from bitcell_base_array import bitcell_base_array from bitcell_base_array import bitcell_base_array
from tech import drc, spice from tech import drc, spice, cell_properties
from vector import vector from vector import vector
from globals import OPTS from globals import OPTS
from sram_factory import factory from sram_factory import factory

View File

@ -8,6 +8,7 @@
import design import design
from vector import vector from vector import vector
from sram_factory import factory from sram_factory import factory
from tech import cell_properties
import debug import debug
from globals import OPTS from globals import OPTS
@ -41,7 +42,6 @@ class sense_amp_array(design.design):
self.en_layer = "m3" self.en_layer = "m3"
else: else:
self.en_layer = "m1" self.en_layer = "m1"
self.create_netlist() self.create_netlist()
if not OPTS.netlist_only: if not OPTS.netlist_only:
self.create_layout() self.create_layout()
@ -109,15 +109,22 @@ class sense_amp_array(design.design):
self.en_name, "vdd", "gnd"]) self.en_name, "vdd", "gnd"])
def place_sense_amp_array(self): def place_sense_amp_array(self):
if self.bitcell.width > self.amp.width: cell = factory.create(module_type=OPTS.bitcell)
self.amp_spacing = self.bitcell.width if(cell_properties.use_strap == True and OPTS.num_ports == 1):
strap = factory.create(module_type=cell_properties.strap_module, version=cell_properties.strap_version)
precharge_width = cell.width + strap.width
else:
precharge_width = cell.width
if precharge_width > self.amp.width:
self.amp_spacing = precharge_width
else: else:
self.amp_spacing = self.amp.width self.amp_spacing = self.amp.width
if not self.offsets: if not self.offsets:
self.offsets = [] self.offsets = []
for i in range(self.num_cols + self.num_spare_cols): for i in range(self.num_cols + self.num_spare_cols):
self.offsets.append(i * self.bitcell.width) self.offsets.append(i * self.amp_spacing)
for i, xoffset in enumerate(self.offsets[0:self.num_cols:self.words_per_row]): for i, xoffset in enumerate(self.offsets[0:self.num_cols:self.words_per_row]):
if self.bitcell.mirror.y and (i * self.words_per_row + self.column_offset) % 2: if self.bitcell.mirror.y and (i * self.words_per_row + self.column_offset) % 2:
@ -128,13 +135,12 @@ class sense_amp_array(design.design):
amp_position = vector(xoffset, 0) amp_position = vector(xoffset, 0)
self.local_insts[i].place(offset=amp_position, mirror=mirror) self.local_insts[i].place(offset=amp_position, mirror=mirror)
# place spare sense amps (will share the same enable as regular sense amps) # place spare sense amps (will share the same enable as regular sense amps)
for i, xoffset in enumerate(self.offsets[self.num_cols:]): for i, xoffset in enumerate(self.offsets[self.num_cols:]):
index = self.word_size + i index = self.word_size + i
if self.bitcell.mirror.y and (index + self.column_offset) % 2: if self.bitcell.mirror.y and (index + self.column_offset) % 2:
mirror = "MY" mirror = "MY"
xoffset = xoffset + self.amp_width xoffset = xoffset + self.amp_spacing
else: else:
mirror = "" mirror = ""

View File

@ -72,7 +72,9 @@ class options(optparse.Values):
# This is the temp directory where all intermediate results are stored. # This is the temp directory where all intermediate results are stored.
try: try:
# If user defined the temporary location in their environment, use it # If user defined the temporary location in their environment, use it
openram_temp = os.path.abspath(os.environ.get("OPENRAM_TMP")) openram_temp = os.path.abspath(os.environ.get("OPENRAM_TMP"))
except: except:
openram_temp = "/tmp" openram_temp = "/tmp"

View File

@ -56,7 +56,13 @@ class column_mux(pgate.pgate):
self.place_ptx() self.place_ptx()
self.width = self.bitcell.width cell = factory.create(module_type=OPTS.bitcell)
if(cell_props.use_strap == True and OPTS.num_ports == 1):
strap = factory.create(module_type=cell_props.strap_module, version=cell_props.strap_version)
precharge_width = cell.width + strap.width
else:
precharge_width = cell.width
self.width = precharge_width
self.height = self.nmos_upper.uy() + self.pin_height self.height = self.nmos_upper.uy() + self.pin_height
self.connect_poly() self.connect_poly()
@ -217,10 +223,15 @@ class column_mux(pgate.pgate):
Add a well and implant over the whole cell. Also, add the Add a well and implant over the whole cell. Also, add the
pwell contact (if it exists) pwell contact (if it exists)
""" """
if(cell_props.use_strap == True and OPTS.num_ports == 1):
strap = factory.create(module_type=cell_props.strap_module, version=cell_props.strap_version)
rbc_width = self.bitcell.width + strap.width
else:
rbc_width = self.bitcell.width
# Add it to the right, aligned in between the two tx # Add it to the right, aligned in between the two tx
active_pos = vector(self.bitcell.width, active_pos = vector(rbc_width,
self.nmos_upper.by() - 0.5 * self.poly_space) self.nmos_upper.by() - 0.5 * self.poly_space)
self.add_via_center(layers=self.active_stack, self.add_via_center(layers=self.active_stack,
offset=active_pos, offset=active_pos,
implant_type="p", implant_type="p",
@ -239,5 +250,5 @@ class column_mux(pgate.pgate):
if "pwell" in layer: if "pwell" in layer:
self.add_rect(layer="pwell", self.add_rect(layer="pwell",
offset=vector(0, 0), offset=vector(0, 0),
width=self.bitcell.width, width=rbc_width,
height=self.height) height=self.height)

View File

@ -30,6 +30,10 @@ class precharge(design.design):
self.beta = parameter["beta"] self.beta = parameter["beta"]
self.ptx_width = self.beta * parameter["min_tx_size"] self.ptx_width = self.beta * parameter["min_tx_size"]
self.ptx_mults = 1 self.ptx_mults = 1
if(cell_props.use_strap == True and OPTS.num_ports == 1):
strap = factory.create(module_type=cell_props.strap_module, version=cell_props.strap_version)
self.width = self.bitcell.width + strap.width
else:
self.width = self.bitcell.width self.width = self.bitcell.width
self.bitcell_bl = bitcell_bl self.bitcell_bl = bitcell_bl
self.bitcell_br = bitcell_br self.bitcell_br = bitcell_br

View File

@ -472,6 +472,12 @@ class sram_base(design, verilog, lef):
self.bitcell = factory.create(module_type=OPTS.bitcell) self.bitcell = factory.create(module_type=OPTS.bitcell)
self.dff = factory.create(module_type="dff") self.dff = factory.create(module_type="dff")
# Create the bank module (up to four are instantiated)
self.bank = factory.create("bank", sram_config=self.sram_config, module_name="bank")
self.add_mod(self.bank)
self.num_spare_cols = self.bank.num_spare_cols
# Create the address and control flops (but not the clk) # Create the address and control flops (but not the clk)
self.row_addr_dff = factory.create("dff_array", module_name="row_addr_dff", rows=self.row_addr_size, columns=1) self.row_addr_dff = factory.create("dff_array", module_name="row_addr_dff", rows=self.row_addr_size, columns=1)
self.add_mod(self.row_addr_dff) self.add_mod(self.row_addr_dff)
@ -493,10 +499,6 @@ class sram_base(design, verilog, lef):
self.spare_wen_dff = factory.create("dff_array", module_name="spare_wen_dff", rows=1, columns=self.num_spare_cols) self.spare_wen_dff = factory.create("dff_array", module_name="spare_wen_dff", rows=1, columns=self.num_spare_cols)
self.add_mod(self.spare_wen_dff) self.add_mod(self.spare_wen_dff)
# Create the bank module (up to four are instantiated)
self.bank = factory.create("bank", sram_config=self.sram_config, module_name="bank")
self.add_mod(self.bank)
# Create bank decoder # Create bank decoder
if(self.num_banks > 1): if(self.num_banks > 1):
self.add_multi_bank_modules() self.add_multi_bank_modules()

View File

@ -92,7 +92,7 @@ def write_drc_script(cell_name, gds_name, extract, final_verification, output_pa
f.write("set VDD vdd\n") f.write("set VDD vdd\n")
f.write("set GND gnd\n") f.write("set GND gnd\n")
f.write("set SUB gnd\n") f.write("set SUB gnd\n")
f.write("gds polygon subcell true\n") #f.write("gds polygon subcell true\n")
f.write("gds warning default\n") f.write("gds warning default\n")
# These two options are temporarily disabled until Tim fixes a bug in magic related # These two options are temporarily disabled until Tim fixes a bug in magic related
# to flattening channel routes and vias (hierarchy with no devices in it). Otherwise, # to flattening channel routes and vias (hierarchy with no devices in it). Otherwise,

View File

@ -135,6 +135,8 @@ layer["m10"] = (29, 0)
layer["text"] = (239, 0) layer["text"] = (239, 0)
layer["boundary"]= (239, 0) layer["boundary"]= (239, 0)
use_purpose = {}
# Layer names for external PDKs # Layer names for external PDKs
layer_names = {} layer_names = {}
layer_names["active"] = "active" layer_names["active"] = "active"

View File

@ -63,6 +63,7 @@ layer["text"] = (63, 0)
layer["boundary"] = (63, 0) layer["boundary"] = (63, 0)
layer["blockage"] = (83, 0) layer["blockage"] = (83, 0)
use_purpose = {}
################################################### ###################################################
##END GDS Layer Map ##END GDS Layer Map
################################################### ###################################################

View File

@ -119,6 +119,8 @@ layer["m4"] = (31, 0)
layer["text"] = (63, 0) layer["text"] = (63, 0)
layer["boundary"] = (63, 0) layer["boundary"] = (63, 0)
use_purpose = {}
# Layer names for external PDKs # Layer names for external PDKs
layer_names = {} layer_names = {}
layer_names["active"] = "active" layer_names["active"] = "active"