mirror of https://github.com/VLSIDA/OpenRAM.git
Pbitcell updates.
Fix module offset error. Add boundary for debugging. Line wrap code.
This commit is contained in:
parent
17d42d43b4
commit
1268a7927b
|
|
@ -30,6 +30,8 @@ class design(hierarchy_design):
|
||||||
self.m2_pitch = max(contact.m2m3.width,contact.m2m3.height) + max(self.m2_space, self.m3_space)
|
self.m2_pitch = max(contact.m2m3.width,contact.m2m3.height) + max(self.m2_space, self.m3_space)
|
||||||
if contact.m3m4:
|
if contact.m3m4:
|
||||||
self.m3_pitch = max(contact.m3m4.width,contact.m3m4.height) + max(self.m3_space, self.m4_space)
|
self.m3_pitch = max(contact.m3m4.width,contact.m3m4.height) + max(self.m3_space, self.m4_space)
|
||||||
|
else:
|
||||||
|
self.m3_pitch = self.m2_pitch
|
||||||
|
|
||||||
def setup_drc_constants(self):
|
def setup_drc_constants(self):
|
||||||
""" These are some DRC constants used in many places in the compiler."""
|
""" These are some DRC constants used in many places in the compiler."""
|
||||||
|
|
|
||||||
|
|
@ -79,9 +79,7 @@ class pbitcell(design.design):
|
||||||
# in netlist_only mode, calling offset_all_coordinates or translate_all will not be possible
|
# in netlist_only mode, calling offset_all_coordinates or translate_all will not be possible
|
||||||
# this function is not needed to calculate the dimensions of pbitcell in netlist_only mode though
|
# this function is not needed to calculate the dimensions of pbitcell in netlist_only mode though
|
||||||
if not OPTS.netlist_only:
|
if not OPTS.netlist_only:
|
||||||
self.offset_all_coordinates()
|
self.translate_all(vector(self.leftmost_xpos, self.botmost_ypos))
|
||||||
gnd_overlap = vector(0, 0.5*contact.well.width)
|
|
||||||
self.translate_all(gnd_overlap)
|
|
||||||
|
|
||||||
|
|
||||||
def add_pins(self):
|
def add_pins(self):
|
||||||
|
|
@ -141,7 +139,8 @@ class pbitcell(design.design):
|
||||||
|
|
||||||
def add_modules(self):
|
def add_modules(self):
|
||||||
""" Determine size of transistors and add ptx modules """
|
""" Determine size of transistors and add ptx modules """
|
||||||
# if there are any read/write ports, then the inverter nmos is sized based the number of read/write ports
|
# if there are any read/write ports,
|
||||||
|
# then the inverter nmos is sized based the number of read/write ports
|
||||||
if(self.num_rw_ports > 0):
|
if(self.num_rw_ports > 0):
|
||||||
inverter_nmos_width = self.num_rw_ports*parameter["6T_inv_nmos_size"]
|
inverter_nmos_width = self.num_rw_ports*parameter["6T_inv_nmos_size"]
|
||||||
inverter_pmos_width = parameter["6T_inv_pmos_size"]
|
inverter_pmos_width = parameter["6T_inv_pmos_size"]
|
||||||
|
|
@ -149,7 +148,8 @@ class pbitcell(design.design):
|
||||||
write_nmos_width = parameter["6T_access_size"]
|
write_nmos_width = parameter["6T_access_size"]
|
||||||
read_nmos_width = 2*parameter["6T_inv_pmos_size"]
|
read_nmos_width = 2*parameter["6T_inv_pmos_size"]
|
||||||
|
|
||||||
# if there are no read/write ports, then the inverter nmos is statically sized for the dual port case
|
# if there are no read/write ports,
|
||||||
|
# then the inverter nmos is statically sized for the dual port case
|
||||||
else:
|
else:
|
||||||
inverter_nmos_width = 2*parameter["6T_inv_pmos_size"]
|
inverter_nmos_width = 2*parameter["6T_inv_pmos_size"]
|
||||||
inverter_pmos_width = parameter["6T_inv_pmos_size"]
|
inverter_pmos_width = parameter["6T_inv_pmos_size"]
|
||||||
|
|
@ -183,14 +183,21 @@ class pbitcell(design.design):
|
||||||
|
|
||||||
def calculate_spacing(self):
|
def calculate_spacing(self):
|
||||||
""" Calculate transistor spacings """
|
""" Calculate transistor spacings """
|
||||||
|
|
||||||
# calculate metal contact extensions over transistor active
|
# calculate metal contact extensions over transistor active
|
||||||
readwrite_nmos_contact_extension = 0.5*(self.readwrite_nmos.active_contact.height - self.readwrite_nmos.active_height)
|
readwrite_nmos_contact_extension = 0.5*(self.readwrite_nmos.active_contact.height \
|
||||||
write_nmos_contact_extension = 0.5*(self.write_nmos.active_contact.height - self.write_nmos.active_height)
|
- self.readwrite_nmos.active_height)
|
||||||
read_nmos_contact_extension = 0.5*(self.read_nmos.active_contact.height - self.read_nmos.active_height)
|
write_nmos_contact_extension = 0.5*(self.write_nmos.active_contact.height \
|
||||||
max_contact_extension = max(readwrite_nmos_contact_extension, write_nmos_contact_extension, read_nmos_contact_extension)
|
- self.write_nmos.active_height)
|
||||||
|
read_nmos_contact_extension = 0.5*(self.read_nmos.active_contact.height \
|
||||||
|
- self.read_nmos.active_height)
|
||||||
|
max_contact_extension = max(readwrite_nmos_contact_extension,
|
||||||
|
write_nmos_contact_extension,
|
||||||
|
read_nmos_contact_extension)
|
||||||
|
|
||||||
# y-offset for the access transistor's gate contact
|
# y-offset for the access transistor's gate contact
|
||||||
self.gate_contact_yoffset = max_contact_extension + self.m2_space + 0.5*max(contact.poly.height, contact.m1m2.height)
|
self.gate_contact_yoffset = max_contact_extension + self.m2_space \
|
||||||
|
+ 0.5*max(contact.poly.height, contact.m1m2.height)
|
||||||
|
|
||||||
# y-position of access transistors
|
# y-position of access transistors
|
||||||
self.port_ypos = self.m1_space + 0.5*contact.m1m2.height + self.gate_contact_yoffset
|
self.port_ypos = self.m1_space + 0.5*contact.m1m2.height + self.gate_contact_yoffset
|
||||||
|
|
@ -199,8 +206,10 @@ class pbitcell(design.design):
|
||||||
self.inverter_nmos_ypos = self.port_ypos
|
self.inverter_nmos_ypos = self.port_ypos
|
||||||
|
|
||||||
# spacing between ports (same for read/write and write ports)
|
# spacing between ports (same for read/write and write ports)
|
||||||
self.bitline_offset = -0.5*self.readwrite_nmos.active_width + 0.5*contact.m1m2.height + self.m2_space + self.m2_width
|
self.bitline_offset = -0.5*self.readwrite_nmos.active_width + 0.5*contact.m1m2.height \
|
||||||
m2_constraint = self.bitline_offset + self.m2_space + 0.5*contact.m1m2.height - 0.5*self.readwrite_nmos.active_width
|
+ self.m2_space + self.m2_width
|
||||||
|
m2_constraint = self.bitline_offset + self.m2_space + 0.5*contact.m1m2.height \
|
||||||
|
- 0.5*self.readwrite_nmos.active_width
|
||||||
self.write_port_spacing = max(self.active_space, self.m1_space, m2_constraint)
|
self.write_port_spacing = max(self.active_space, self.m1_space, m2_constraint)
|
||||||
self.read_port_spacing = self.bitline_offset + self.m2_space
|
self.read_port_spacing = self.bitline_offset + self.m2_space
|
||||||
|
|
||||||
|
|
@ -211,7 +220,7 @@ class pbitcell(design.design):
|
||||||
inverter_pmos_contact_extension = 0.5*(self.inverter_pmos.active_contact.height - self.inverter_pmos.active_height)
|
inverter_pmos_contact_extension = 0.5*(self.inverter_pmos.active_contact.height - self.inverter_pmos.active_height)
|
||||||
inverter_nmos_contact_extension = 0.5*(self.inverter_nmos.active_contact.height - self.inverter_nmos.active_height)
|
inverter_nmos_contact_extension = 0.5*(self.inverter_nmos.active_contact.height - self.inverter_nmos.active_height)
|
||||||
self.inverter_gap = max(self.poly_to_active, self.m1_space + inverter_nmos_contact_extension) \
|
self.inverter_gap = max(self.poly_to_active, self.m1_space + inverter_nmos_contact_extension) \
|
||||||
+ self.poly_to_polycontact + 2*contact.poly.width \
|
+ self.poly_to_polycontact + 2*contact.poly.height \
|
||||||
+ self.m1_space + inverter_pmos_contact_extension
|
+ self.m1_space + inverter_pmos_contact_extension
|
||||||
self.cross_couple_lower_ypos = self.inverter_nmos_ypos + self.inverter_nmos.active_height \
|
self.cross_couple_lower_ypos = self.inverter_nmos_ypos + self.inverter_nmos.active_height \
|
||||||
+ max(self.poly_to_active, self.m1_space + inverter_nmos_contact_extension) \
|
+ max(self.poly_to_active, self.m1_space + inverter_nmos_contact_extension) \
|
||||||
|
|
@ -222,11 +231,11 @@ class pbitcell(design.design):
|
||||||
+ 1.5*contact.poly.width
|
+ 1.5*contact.poly.width
|
||||||
|
|
||||||
# spacing between wordlines (and gnd)
|
# spacing between wordlines (and gnd)
|
||||||
self.rowline_spacing = self.m1_space + contact.m1m2.width
|
self.m1_offset = -0.5*self.m1_width
|
||||||
self.rowline_offset = -0.5*self.m1_width
|
|
||||||
|
|
||||||
# spacing for vdd
|
# spacing for vdd
|
||||||
implant_constraint = max(inverter_pmos_contact_extension, 0) + 2*self.implant_enclose_active + 0.5*(contact.well.width - self.m1_width)
|
implant_constraint = max(inverter_pmos_contact_extension, 0) + 2*self.implant_enclose_active \
|
||||||
|
+ 0.5*(contact.well.width - self.m1_width)
|
||||||
metal1_constraint = max(inverter_pmos_contact_extension, 0) + self.m1_space
|
metal1_constraint = max(inverter_pmos_contact_extension, 0) + self.m1_space
|
||||||
self.vdd_offset = max(implant_constraint, metal1_constraint) + 0.5*self.m1_width
|
self.vdd_offset = max(implant_constraint, metal1_constraint) + 0.5*self.m1_width
|
||||||
|
|
||||||
|
|
@ -236,8 +245,10 @@ class pbitcell(design.design):
|
||||||
|
|
||||||
def calculate_postions(self):
|
def calculate_postions(self):
|
||||||
""" Calculate positions that describe the edges and dimensions of the cell """
|
""" Calculate positions that describe the edges and dimensions of the cell """
|
||||||
self.botmost_ypos = -0.5*self.m1_width - self.total_ports*self.rowline_spacing
|
self.botmost_ypos = self.m1_offset - self.total_ports*self.m1_pitch
|
||||||
self.topmost_ypos = self.inverter_nmos_ypos + self.inverter_nmos.active_height + self.inverter_gap + self.inverter_pmos.active_height + self.vdd_offset
|
self.topmost_ypos = self.inverter_nmos_ypos + self.inverter_nmos.active_height \
|
||||||
|
+ self.inverter_gap + self.inverter_pmos.active_height \
|
||||||
|
+ self.vdd_offset
|
||||||
|
|
||||||
self.leftmost_xpos = -0.5*self.inverter_to_inverter_spacing - self.inverter_nmos.active_width \
|
self.leftmost_xpos = -0.5*self.inverter_to_inverter_spacing - self.inverter_nmos.active_width \
|
||||||
- self.num_rw_ports*(self.readwrite_nmos.active_width + self.write_port_spacing) \
|
- self.num_rw_ports*(self.readwrite_nmos.active_width + self.write_port_spacing) \
|
||||||
|
|
@ -247,9 +258,14 @@ class pbitcell(design.design):
|
||||||
|
|
||||||
self.width = -2*self.leftmost_xpos
|
self.width = -2*self.leftmost_xpos
|
||||||
self.height = self.topmost_ypos - self.botmost_ypos
|
self.height = self.topmost_ypos - self.botmost_ypos
|
||||||
|
|
||||||
self.center_ypos = 0.5*(self.topmost_ypos + self.botmost_ypos)
|
self.center_ypos = 0.5*(self.topmost_ypos + self.botmost_ypos)
|
||||||
|
|
||||||
|
# Add this boundary for visual debug
|
||||||
|
self.add_rect(layer="boundary",
|
||||||
|
offset=vector(self.leftmost_xpos,self.botmost_ypos),
|
||||||
|
height=self.height,
|
||||||
|
width=self.width)
|
||||||
|
|
||||||
def create_storage(self):
|
def create_storage(self):
|
||||||
"""
|
"""
|
||||||
Creates the crossed coupled inverters that act as storage for the bitcell.
|
Creates the crossed coupled inverters that act as storage for the bitcell.
|
||||||
|
|
@ -307,13 +323,15 @@ class pbitcell(design.design):
|
||||||
width=contact.active.second_layer_width)
|
width=contact.active.second_layer_width)
|
||||||
|
|
||||||
# add contacts to connect gate poly to drain/source metal1 (to connect Q to Q_bar)
|
# add contacts to connect gate poly to drain/source metal1 (to connect Q to Q_bar)
|
||||||
contact_offset_left = vector(self.inverter_nmos_left.get_pin("D").rc().x + 0.5*contact.poly.height, self.cross_couple_upper_ypos)
|
contact_offset_left = vector(self.inverter_nmos_left.get_pin("D").rc().x + 0.5*contact.poly.height,
|
||||||
|
self.cross_couple_upper_ypos)
|
||||||
self.add_via_center(layers=("poly", "contact", "metal1"),
|
self.add_via_center(layers=("poly", "contact", "metal1"),
|
||||||
offset=contact_offset_left,
|
offset=contact_offset_left,
|
||||||
directions=("H","H"))
|
directions=("H","H"))
|
||||||
|
|
||||||
|
|
||||||
contact_offset_right = vector(self.inverter_nmos_right.get_pin("S").lc().x - 0.5*contact.poly.height, self.cross_couple_lower_ypos)
|
contact_offset_right = vector(self.inverter_nmos_right.get_pin("S").lc().x - 0.5*contact.poly.height,
|
||||||
|
self.cross_couple_lower_ypos)
|
||||||
self.add_via_center(layers=("poly", "contact", "metal1"),
|
self.add_via_center(layers=("poly", "contact", "metal1"),
|
||||||
offset=contact_offset_right,
|
offset=contact_offset_right,
|
||||||
directions=("H","H"))
|
directions=("H","H"))
|
||||||
|
|
@ -328,21 +346,21 @@ class pbitcell(design.design):
|
||||||
def route_rails(self):
|
def route_rails(self):
|
||||||
""" Adds gnd and vdd rails and connects them to the inverters """
|
""" Adds gnd and vdd rails and connects them to the inverters """
|
||||||
# Add rails for vdd and gnd
|
# Add rails for vdd and gnd
|
||||||
gnd_ypos = self.rowline_offset - self.total_ports*self.rowline_spacing
|
gnd_ypos = self.m1_offset - self.total_ports*self.m1_pitch
|
||||||
self.gnd_position = vector(0, gnd_ypos)
|
self.gnd_position = vector(0, gnd_ypos)
|
||||||
self.add_rect_center(layer="metal1",
|
self.add_rect_center(layer="metal1",
|
||||||
offset=self.gnd_position,
|
offset=self.gnd_position,
|
||||||
width=self.width,
|
width=self.width)
|
||||||
height=self.m1_width)
|
|
||||||
self.add_power_pin("gnd", vector(0,gnd_ypos))
|
self.add_power_pin("gnd", vector(0,gnd_ypos))
|
||||||
|
|
||||||
|
|
||||||
vdd_ypos = self.inverter_nmos_ypos + self.inverter_nmos.active_height + self.inverter_gap + self.inverter_pmos.active_height + self.vdd_offset
|
vdd_ypos = self.inverter_nmos_ypos + self.inverter_nmos.active_height \
|
||||||
|
+ self.inverter_gap + self.inverter_pmos.active_height \
|
||||||
|
+ self.vdd_offset
|
||||||
self.vdd_position = vector(0, vdd_ypos)
|
self.vdd_position = vector(0, vdd_ypos)
|
||||||
self.add_rect_center(layer="metal1",
|
self.add_rect_center(layer="metal1",
|
||||||
offset=self.vdd_position,
|
offset=self.vdd_position,
|
||||||
width=self.width,
|
width=self.width)
|
||||||
height=self.m1_width)
|
|
||||||
self.add_power_pin("vdd", vector(0,vdd_ypos))
|
self.add_power_pin("vdd", vector(0,vdd_ypos))
|
||||||
|
|
||||||
def create_readwrite_ports(self):
|
def create_readwrite_ports(self):
|
||||||
|
|
@ -393,13 +411,12 @@ class pbitcell(design.design):
|
||||||
self.readwrite_nmos_right[k].place(offset=[right_readwrite_transistor_xpos, self.port_ypos])
|
self.readwrite_nmos_right[k].place(offset=[right_readwrite_transistor_xpos, self.port_ypos])
|
||||||
|
|
||||||
# add pin for RWWL
|
# add pin for RWWL
|
||||||
rwwl_ypos = self.rowline_offset - k*self.rowline_spacing
|
rwwl_ypos = self.m1_offset - k*self.m1_pitch
|
||||||
self.rwwl_positions[k] = vector(0, rwwl_ypos)
|
self.rwwl_positions[k] = vector(0, rwwl_ypos)
|
||||||
self.add_layout_pin_rect_center(text=self.rw_wl_names[k],
|
self.add_layout_pin_rect_center(text=self.rw_wl_names[k],
|
||||||
layer="metal1",
|
layer="metal1",
|
||||||
offset=self.rwwl_positions[k],
|
offset=self.rwwl_positions[k],
|
||||||
width=self.width,
|
width=self.width)
|
||||||
height=self.m1_width)
|
|
||||||
|
|
||||||
# add pins for RWBL and RWBR
|
# add pins for RWBL and RWBR
|
||||||
rwbl_xpos = left_readwrite_transistor_xpos - self.bitline_offset + 0.5*self.m2_width
|
rwbl_xpos = left_readwrite_transistor_xpos - self.bitline_offset + 0.5*self.m2_width
|
||||||
|
|
@ -409,7 +426,8 @@ class pbitcell(design.design):
|
||||||
offset=self.rwbl_positions[k],
|
offset=self.rwbl_positions[k],
|
||||||
height=self.height)
|
height=self.height)
|
||||||
|
|
||||||
rwbr_xpos = right_readwrite_transistor_xpos + self.readwrite_nmos.active_width + self.bitline_offset - 0.5*self.m2_width
|
rwbr_xpos = right_readwrite_transistor_xpos + self.readwrite_nmos.active_width \
|
||||||
|
+ self.bitline_offset - 0.5*self.m2_width
|
||||||
self.rwbr_positions[k] = vector(rwbr_xpos, self.center_ypos)
|
self.rwbr_positions[k] = vector(rwbr_xpos, self.center_ypos)
|
||||||
self.add_layout_pin_rect_center(text=self.rw_br_names[k],
|
self.add_layout_pin_rect_center(text=self.rw_br_names[k],
|
||||||
layer="metal2",
|
layer="metal2",
|
||||||
|
|
@ -468,13 +486,13 @@ class pbitcell(design.design):
|
||||||
self.write_nmos_right[k].place(offset=[right_write_transistor_xpos, self.port_ypos])
|
self.write_nmos_right[k].place(offset=[right_write_transistor_xpos, self.port_ypos])
|
||||||
|
|
||||||
# add pin for WWL
|
# add pin for WWL
|
||||||
wwl_ypos = rwwl_ypos = self.rowline_offset - self.num_rw_ports*self.rowline_spacing - k*self.rowline_spacing
|
wwl_ypos = rwwl_ypos = self.m1_offset - self.num_rw_ports*self.m1_pitch \
|
||||||
|
- k*self.m1_pitch
|
||||||
self.wwl_positions[k] = vector(0, wwl_ypos)
|
self.wwl_positions[k] = vector(0, wwl_ypos)
|
||||||
self.add_layout_pin_rect_center(text=self.w_wl_names[k],
|
self.add_layout_pin_rect_center(text=self.w_wl_names[k],
|
||||||
layer="metal1",
|
layer="metal1",
|
||||||
offset=self.wwl_positions[k],
|
offset=self.wwl_positions[k],
|
||||||
width=self.width,
|
width=self.width)
|
||||||
height=self.m1_width)
|
|
||||||
|
|
||||||
# add pins for WBL and WBR
|
# add pins for WBL and WBR
|
||||||
wbl_xpos = left_write_transistor_xpos - self.bitline_offset + 0.5*self.m2_width
|
wbl_xpos = left_write_transistor_xpos - self.bitline_offset + 0.5*self.m2_width
|
||||||
|
|
@ -484,7 +502,8 @@ class pbitcell(design.design):
|
||||||
offset=self.wbl_positions[k],
|
offset=self.wbl_positions[k],
|
||||||
height=self.height)
|
height=self.height)
|
||||||
|
|
||||||
wbr_xpos = right_write_transistor_xpos + self.write_nmos.active_width + self.bitline_offset - 0.5*self.m2_width
|
wbr_xpos = right_write_transistor_xpos + self.write_nmos.active_width + self.bitline_offset \
|
||||||
|
- 0.5*self.m2_width
|
||||||
self.wbr_positions[k] = vector(wbr_xpos, self.center_ypos)
|
self.wbr_positions[k] = vector(wbr_xpos, self.center_ypos)
|
||||||
self.add_layout_pin_rect_center(text=self.w_br_names[k],
|
self.add_layout_pin_rect_center(text=self.w_br_names[k],
|
||||||
layer="metal2",
|
layer="metal2",
|
||||||
|
|
@ -565,13 +584,13 @@ class pbitcell(design.design):
|
||||||
self.read_nmos_right[k].place(offset=[right_read_transistor_xpos+overlap_offset, self.port_ypos])
|
self.read_nmos_right[k].place(offset=[right_read_transistor_xpos+overlap_offset, self.port_ypos])
|
||||||
|
|
||||||
# add pin for RWL
|
# add pin for RWL
|
||||||
rwl_ypos = rwwl_ypos = self.rowline_offset - self.num_rw_ports*self.rowline_spacing - self.num_w_ports*self.rowline_spacing - k*self.rowline_spacing
|
rwl_ypos = rwwl_ypos = self.m1_offset - self.num_rw_ports*self.m1_pitch \
|
||||||
|
- self.num_w_ports*self.m1_pitch - k*self.m1_pitch
|
||||||
self.rwl_positions[k] = vector(0, rwl_ypos)
|
self.rwl_positions[k] = vector(0, rwl_ypos)
|
||||||
self.add_layout_pin_rect_center(text=self.r_wl_names[k],
|
self.add_layout_pin_rect_center(text=self.r_wl_names[k],
|
||||||
layer="metal1",
|
layer="metal1",
|
||||||
offset=self.rwl_positions[k],
|
offset=self.rwl_positions[k],
|
||||||
width=self.width,
|
width=self.width)
|
||||||
height=self.m1_width)
|
|
||||||
|
|
||||||
# add pins for RBL and RBR
|
# add pins for RBL and RBR
|
||||||
rbl_xpos = left_read_transistor_xpos - self.bitline_offset + 0.5*self.m2_width
|
rbl_xpos = left_read_transistor_xpos - self.bitline_offset + 0.5*self.m2_width
|
||||||
|
|
@ -581,7 +600,8 @@ class pbitcell(design.design):
|
||||||
offset=self.rbl_positions[k],
|
offset=self.rbl_positions[k],
|
||||||
height=self.height)
|
height=self.height)
|
||||||
|
|
||||||
rbr_xpos = right_read_transistor_xpos + self.read_port_width + self.bitline_offset - 0.5*self.m2_width
|
rbr_xpos = right_read_transistor_xpos + self.read_port_width + self.bitline_offset \
|
||||||
|
- 0.5*self.m2_width
|
||||||
self.rbr_positions[k] = vector(rbr_xpos, self.center_ypos)
|
self.rbr_positions[k] = vector(rbr_xpos, self.center_ypos)
|
||||||
self.add_layout_pin_rect_center(text=self.r_br_names[k],
|
self.add_layout_pin_rect_center(text=self.r_br_names[k],
|
||||||
layer="metal2",
|
layer="metal2",
|
||||||
|
|
@ -739,12 +759,14 @@ class pbitcell(design.design):
|
||||||
def route_read_access(self):
|
def route_read_access(self):
|
||||||
""" Routes read access transistors to the storage component of the bitcell """
|
""" Routes read access transistors to the storage component of the bitcell """
|
||||||
# add poly to metal1 contacts for gates of the inverters
|
# add poly to metal1 contacts for gates of the inverters
|
||||||
left_storage_contact = vector(self.inverter_nmos_left.get_pin("G").lc().x - self.poly_to_polycontact - 0.5*contact.poly.width, self.cross_couple_upper_ypos)
|
left_storage_contact = vector(self.inverter_nmos_left.get_pin("G").lc().x - self.poly_to_polycontact - 0.5*contact.poly.width,
|
||||||
|
self.cross_couple_upper_ypos)
|
||||||
self.add_via_center(layers=("poly", "contact", "metal1"),
|
self.add_via_center(layers=("poly", "contact", "metal1"),
|
||||||
offset=left_storage_contact,
|
offset=left_storage_contact,
|
||||||
directions=("H","H"))
|
directions=("H","H"))
|
||||||
|
|
||||||
right_storage_contact = vector(self.inverter_nmos_right.get_pin("G").rc().x + self.poly_to_polycontact + 0.5*contact.poly.width, self.cross_couple_upper_ypos)
|
right_storage_contact = vector(self.inverter_nmos_right.get_pin("G").rc().x + self.poly_to_polycontact + 0.5*contact.poly.width,
|
||||||
|
self.cross_couple_upper_ypos)
|
||||||
self.add_via_center(layers=("poly", "contact", "metal1"),
|
self.add_via_center(layers=("poly", "contact", "metal1"),
|
||||||
offset=right_storage_contact,
|
offset=right_storage_contact,
|
||||||
directions=("H","H"))
|
directions=("H","H"))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue