mirror of https://github.com/VLSIDA/OpenRAM.git
Merge branch 'laptop_checkpoint' into dev
This commit is contained in:
commit
cf61096936
|
|
@ -176,7 +176,7 @@ class cell_properties():
|
|||
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_2port"] = "row_cap_cell_2rw"
|
||||
|
||||
self.use_strap = False
|
||||
self._ptx = _ptx(model_is_subckt=False,
|
||||
bin_spice_models=False)
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,8 @@ class design(hierarchy_design):
|
|||
self.add_pin_indices(prop.port_indices)
|
||||
self.add_pin_names(prop.port_map)
|
||||
self.add_pin_types(prop.port_types)
|
||||
|
||||
|
||||
|
||||
(width, height) = utils.get_libcell_size(self.cell_name,
|
||||
GDS["unit"],
|
||||
layer[prop.boundary_layer])
|
||||
|
|
|
|||
|
|
@ -1257,22 +1257,24 @@ class layout():
|
|||
height=ymax - ymin)
|
||||
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.
|
||||
If it is on M1, it will add a power via too.
|
||||
"""
|
||||
pins = inst.get_pins(name)
|
||||
for pin in pins:
|
||||
if new_name == "":
|
||||
new_name = pin.name
|
||||
if pin.layer == self.pwr_grid_layer:
|
||||
self.add_layout_pin(name,
|
||||
self.add_layout_pin(new_name,
|
||||
pin.layer,
|
||||
pin.ll(),
|
||||
pin.width(),
|
||||
pin.height())
|
||||
|
||||
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):
|
||||
"""
|
||||
|
|
@ -1318,13 +1320,15 @@ class layout():
|
|||
width=width,
|
||||
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
|
||||
the given center location. The starting layer is specified to determine
|
||||
which vias are needed.
|
||||
"""
|
||||
|
||||
if new_name == "":
|
||||
new_name = pin.name
|
||||
if not loc:
|
||||
loc = pin.center()
|
||||
|
||||
|
|
@ -1338,7 +1342,7 @@ class layout():
|
|||
height = None
|
||||
|
||||
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,
|
||||
offset=loc,
|
||||
width=width,
|
||||
|
|
@ -1353,7 +1357,7 @@ class layout():
|
|||
width = via.width
|
||||
if not 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,
|
||||
offset=loc,
|
||||
width=width,
|
||||
|
|
|
|||
|
|
@ -148,12 +148,15 @@ def get_gds_pins(pin_names, name, gds_filename, units):
|
|||
cell[str(pin_name)] = []
|
||||
pin_list = cell_vlsi.getPinShape(str(pin_name))
|
||||
for pin_shape in pin_list:
|
||||
(lpp, boundary) = pin_shape
|
||||
rect = [vector(boundary[0], boundary[1]),
|
||||
vector(boundary[2], boundary[3])]
|
||||
# this is a list because other cells/designs
|
||||
# may have must-connect pins
|
||||
cell[str(pin_name)].append(pin_layout(pin_name, rect, lpp))
|
||||
if pin_shape != None:
|
||||
(lpp, boundary) = pin_shape
|
||||
rect = [vector(boundary[0], boundary[1]),
|
||||
vector(boundary[2], boundary[3])]
|
||||
# this is a list because other cells/designs
|
||||
# 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))
|
||||
|
||||
_GDS_PINS_CACHE[k] = cell
|
||||
return dict(cell)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ from datetime import *
|
|||
import numpy as np
|
||||
import math
|
||||
import debug
|
||||
|
||||
from tech import use_purpose
|
||||
|
||||
class VlsiLayout:
|
||||
"""Class represent a hierarchical layout"""
|
||||
|
|
@ -215,9 +215,13 @@ class VlsiLayout:
|
|||
self.deduceHierarchy()
|
||||
# self.traverseTheHierarchy()
|
||||
self.populateCoordinateMap()
|
||||
|
||||
#only ones with text
|
||||
for layerNumber in self.layerNumbersInUse:
|
||||
self.processLabelPins((layerNumber, None))
|
||||
#if layerNumber not in no_pin_shape:
|
||||
if layerNumber in use_purpose:
|
||||
self.processLabelPins((layerNumber, use_purpose[layerNumber]))
|
||||
else:
|
||||
self.processLabelPins((layerNumber, None))
|
||||
|
||||
def populateCoordinateMap(self):
|
||||
def addToXyTree(startingStructureName = None,transformPath = None):
|
||||
|
|
@ -903,6 +907,16 @@ def sameLPP(lpp1, lpp2):
|
|||
if lpp1[1] == None or lpp2[1] == None:
|
||||
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]
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -238,8 +238,8 @@ def setup_bitcell():
|
|||
OPTS.dummy_bitcell = "dummy_pbitcell"
|
||||
OPTS.replica_bitcell = "replica_pbitcell"
|
||||
else:
|
||||
num_ports = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports
|
||||
OPTS.bitcell = "bitcell_{}port".format(num_ports)
|
||||
OPTS.num_ports = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports
|
||||
OPTS.bitcell = "bitcell_{}port".format(OPTS.num_ports)
|
||||
OPTS.dummy_bitcell = "dummy_" + OPTS.bitcell
|
||||
OPTS.replica_bitcell = "replica_" + OPTS.bitcell
|
||||
|
||||
|
|
|
|||
|
|
@ -366,18 +366,13 @@ class bank(design.design):
|
|||
|
||||
# A space for wells or jogging m2
|
||||
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):
|
||||
""" 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
|
||||
|
||||
|
|
@ -397,12 +392,26 @@ class bank(design.design):
|
|||
cols=self.num_cols + self.num_spare_cols,
|
||||
rows=self.num_rows)
|
||||
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.bit_offsets = self.get_column_offsets()
|
||||
for port in self.all_ports:
|
||||
temp_pre = factory.create(module_type="port_data",
|
||||
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,
|
||||
bit_offsets=self.bit_offsets)
|
||||
self.port_data.append(temp_pre)
|
||||
|
|
@ -430,7 +439,9 @@ class bank(design.design):
|
|||
|
||||
temp.append("vdd")
|
||||
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)
|
||||
|
||||
def place_bitcell_array(self, offset):
|
||||
|
|
@ -489,7 +500,7 @@ class bank(design.design):
|
|||
mod=self.port_address[port])
|
||||
|
||||
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("wl_en{}".format(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, "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.
|
||||
# Other decoders already have them.
|
||||
if self.col_addr_size == 1:
|
||||
|
|
@ -1062,7 +1077,6 @@ class bank(design.design):
|
|||
to_layer="m2",
|
||||
offset=control_pos)
|
||||
|
||||
|
||||
def graph_exclude_precharge(self):
|
||||
"""
|
||||
Precharge adds a loop between bitlines, can be excluded to reduce complexity
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@ from vector import vector
|
|||
from sram_factory import factory
|
||||
from globals import OPTS
|
||||
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):
|
||||
|
|
@ -29,7 +33,7 @@ class hierarchical_predecode(design.design):
|
|||
self.cell_height = height
|
||||
|
||||
self.column_decoder = column_decoder
|
||||
|
||||
self.input_and_rail_pos = []
|
||||
self.number_of_outputs = int(math.pow(2, self.number_of_inputs))
|
||||
super().__init__(name)
|
||||
|
||||
|
|
@ -183,9 +187,9 @@ class hierarchical_predecode(design.design):
|
|||
def route(self):
|
||||
|
||||
self.route_input_inverters()
|
||||
self.route_output_inverters()
|
||||
self.route_inputs_to_rails()
|
||||
self.route_input_ands()
|
||||
self.route_output_inverters()
|
||||
self.route_inputs_to_rails()
|
||||
self.route_output_ands()
|
||||
self.route_vdd_gnd()
|
||||
|
||||
|
|
@ -274,8 +278,46 @@ class hierarchical_predecode(design.design):
|
|||
# pins in the and gates.
|
||||
inv_out_pos = inv_out_pin.rc()
|
||||
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)
|
||||
|
||||
# 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_via_stack_center(from_layer=inv_out_pin.layer,
|
||||
|
|
@ -316,6 +358,7 @@ class hierarchical_predecode(design.design):
|
|||
to_layer=self.bus_layer,
|
||||
offset=rail_pos,
|
||||
directions=self.bus_directions)
|
||||
self.input_and_rail_pos.append(rail_pos)
|
||||
if gate_pin == "A":
|
||||
direction = None
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ from sram_factory import factory
|
|||
from collections import namedtuple
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
from tech import cell_properties
|
||||
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.
|
||||
"""
|
||||
|
||||
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)
|
||||
if dimension_override:
|
||||
self.num_rows = rows
|
||||
self.num_cols = cols
|
||||
self.word_size = sram_config.word_size
|
||||
|
||||
self.port = port
|
||||
if self.write_size is not None:
|
||||
self.num_wmasks = int(math.ceil(self.word_size / self.write_size))
|
||||
else:
|
||||
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
|
||||
|
||||
if not bit_offsets:
|
||||
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 = []
|
||||
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:
|
||||
self.bit_offsets = bit_offsets
|
||||
|
||||
if name == "":
|
||||
name = "port_data_{0}".format(self.port)
|
||||
super().__init__(name)
|
||||
|
|
@ -117,7 +128,6 @@ class port_data(design.design):
|
|||
for bit in range(self.num_spare_cols):
|
||||
self.add_pin("sparebl_{0}".format(bit), "INOUT")
|
||||
self.add_pin("sparebr_{0}".format(bit), "INOUT")
|
||||
|
||||
if self.port in self.read_ports:
|
||||
for bit in range(self.word_size + self.num_spare_cols):
|
||||
self.add_pin("dout_{}".format(bit), "OUTPUT")
|
||||
|
|
@ -191,14 +201,19 @@ class port_data(design.design):
|
|||
# and mirroring happens correctly
|
||||
|
||||
# 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:
|
||||
# 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:
|
||||
# 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",
|
||||
columns=self.num_cols + self.num_spare_cols + 1,
|
||||
offsets=precharge_bit_offsets,
|
||||
|
|
@ -567,19 +582,32 @@ class port_data(design.design):
|
|||
off = 1
|
||||
else:
|
||||
off = 0
|
||||
if OPTS.num_ports > 1:
|
||||
self.channel_route_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.channel_route_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.channel_route_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)
|
||||
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.channel_route_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)
|
||||
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:
|
||||
self.channel_route_bitlines(inst1=inst1,
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@ class precharge_array(design.design):
|
|||
size=self.size,
|
||||
bitcell_bl=self.bitcell_bl,
|
||||
bitcell_br=self.bitcell_br)
|
||||
|
||||
self.add_mod(self.pc_cell)
|
||||
|
||||
self.cell = factory.create(module_type=OPTS.bitcell)
|
||||
|
||||
def add_layout_pins(self):
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import debug
|
||||
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 globals import OPTS
|
||||
from sram_factory import factory
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
import design
|
||||
from vector import vector
|
||||
from sram_factory import factory
|
||||
from tech import cell_properties
|
||||
import debug
|
||||
from globals import OPTS
|
||||
|
||||
|
|
@ -41,7 +42,6 @@ class sense_amp_array(design.design):
|
|||
self.en_layer = "m3"
|
||||
else:
|
||||
self.en_layer = "m1"
|
||||
|
||||
self.create_netlist()
|
||||
if not OPTS.netlist_only:
|
||||
self.create_layout()
|
||||
|
|
@ -109,15 +109,22 @@ class sense_amp_array(design.design):
|
|||
self.en_name, "vdd", "gnd"])
|
||||
|
||||
def place_sense_amp_array(self):
|
||||
if self.bitcell.width > self.amp.width:
|
||||
self.amp_spacing = self.bitcell.width
|
||||
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 precharge_width > self.amp.width:
|
||||
self.amp_spacing = precharge_width
|
||||
else:
|
||||
self.amp_spacing = self.amp.width
|
||||
|
||||
if not self.offsets:
|
||||
self.offsets = []
|
||||
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]):
|
||||
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)
|
||||
self.local_insts[i].place(offset=amp_position, mirror=mirror)
|
||||
|
||||
# place spare sense amps (will share the same enable as regular sense amps)
|
||||
for i, xoffset in enumerate(self.offsets[self.num_cols:]):
|
||||
index = self.word_size + i
|
||||
if self.bitcell.mirror.y and (index + self.column_offset) % 2:
|
||||
mirror = "MY"
|
||||
xoffset = xoffset + self.amp_width
|
||||
xoffset = xoffset + self.amp_spacing
|
||||
else:
|
||||
mirror = ""
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,9 @@ class options(optparse.Values):
|
|||
# This is the temp directory where all intermediate results are stored.
|
||||
try:
|
||||
# If user defined the temporary location in their environment, use it
|
||||
|
||||
openram_temp = os.path.abspath(os.environ.get("OPENRAM_TMP"))
|
||||
|
||||
except:
|
||||
openram_temp = "/tmp"
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,13 @@ class column_mux(pgate.pgate):
|
|||
|
||||
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.connect_poly()
|
||||
|
|
@ -217,10 +223,15 @@ class column_mux(pgate.pgate):
|
|||
Add a well and implant over the whole cell. Also, add the
|
||||
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
|
||||
active_pos = vector(self.bitcell.width,
|
||||
active_pos = vector(rbc_width,
|
||||
self.nmos_upper.by() - 0.5 * self.poly_space)
|
||||
|
||||
self.add_via_center(layers=self.active_stack,
|
||||
offset=active_pos,
|
||||
implant_type="p",
|
||||
|
|
@ -239,5 +250,5 @@ class column_mux(pgate.pgate):
|
|||
if "pwell" in layer:
|
||||
self.add_rect(layer="pwell",
|
||||
offset=vector(0, 0),
|
||||
width=self.bitcell.width,
|
||||
width=rbc_width,
|
||||
height=self.height)
|
||||
|
|
|
|||
|
|
@ -30,7 +30,11 @@ class precharge(design.design):
|
|||
self.beta = parameter["beta"]
|
||||
self.ptx_width = self.beta * parameter["min_tx_size"]
|
||||
self.ptx_mults = 1
|
||||
self.width = self.bitcell.width
|
||||
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.bitcell_bl = bitcell_bl
|
||||
self.bitcell_br = bitcell_br
|
||||
self.bitcell_bl_pin =self.bitcell.get_pin(self.bitcell_bl)
|
||||
|
|
|
|||
|
|
@ -472,6 +472,12 @@ class sram_base(design, verilog, lef):
|
|||
self.bitcell = factory.create(module_type=OPTS.bitcell)
|
||||
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)
|
||||
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)
|
||||
|
|
@ -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.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
|
||||
if(self.num_banks > 1):
|
||||
self.add_multi_bank_modules()
|
||||
|
|
|
|||
|
|
@ -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 GND 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")
|
||||
# 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,
|
||||
|
|
|
|||
|
|
@ -135,6 +135,8 @@ layer["m10"] = (29, 0)
|
|||
layer["text"] = (239, 0)
|
||||
layer["boundary"]= (239, 0)
|
||||
|
||||
use_purpose = {}
|
||||
|
||||
# Layer names for external PDKs
|
||||
layer_names = {}
|
||||
layer_names["active"] = "active"
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ layer["text"] = (63, 0)
|
|||
layer["boundary"] = (63, 0)
|
||||
layer["blockage"] = (83, 0)
|
||||
|
||||
use_purpose = {}
|
||||
###################################################
|
||||
##END GDS Layer Map
|
||||
###################################################
|
||||
|
|
|
|||
|
|
@ -119,6 +119,8 @@ layer["m4"] = (31, 0)
|
|||
layer["text"] = (63, 0)
|
||||
layer["boundary"] = (63, 0)
|
||||
|
||||
use_purpose = {}
|
||||
|
||||
# Layer names for external PDKs
|
||||
layer_names = {}
|
||||
layer_names["active"] = "active"
|
||||
|
|
|
|||
Loading…
Reference in New Issue