mirror of https://github.com/VLSIDA/OpenRAM.git
Fix 6T and replica cell contact spacing issues with Magic DRC.
DRC/LVS passing for all parameterized gates. Magic and GDS match for SCMOS rules again.
This commit is contained in:
parent
fb0355ebaf
commit
1dc7752429
|
|
@ -115,8 +115,8 @@ class bitcell_array(design.design):
|
||||||
gnd_pins = self.cell_inst[0,col].get_pins("gnd")
|
gnd_pins = self.cell_inst[0,col].get_pins("gnd")
|
||||||
for gnd_pin in gnd_pins:
|
for gnd_pin in gnd_pins:
|
||||||
# avoid duplicates by only doing even rows
|
# avoid duplicates by only doing even rows
|
||||||
# also skip if it is not the full height (a through rail)
|
# also skip if it isn't the pin that spans the entire cell down to the bottom
|
||||||
if gnd_pin.layer=="metal2" and col%2 == 0 and gnd_pin.height()>=self.cell.height:
|
if gnd_pin.layer=="metal2" and col%2 == 0 and gnd_pin.by()==lower_y:
|
||||||
self.add_layout_pin(text="gnd",
|
self.add_layout_pin(text="gnd",
|
||||||
layer="metal2",
|
layer="metal2",
|
||||||
offset=gnd_pin.ll(),
|
offset=gnd_pin.ll(),
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,13 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout):
|
||||||
|
|
||||||
# Check if the name already exists, if so, give an error
|
# Check if the name already exists, if so, give an error
|
||||||
# because each reference must be a unique name.
|
# because each reference must be a unique name.
|
||||||
ok_list = ['ms_flop.ms_flop', 'bitcell.bitcell', 'contact.contact',
|
# These modules ensure unique names or have no changes if they
|
||||||
'ptx.ptx', 'sram.sram',
|
# aren't unique
|
||||||
|
ok_list = ['ms_flop.ms_flop',
|
||||||
|
'bitcell.bitcell',
|
||||||
|
'contact.contact',
|
||||||
|
'ptx.ptx',
|
||||||
|
'sram.sram',
|
||||||
'hierarchical_predecode2x4.hierarchical_predecode2x4',
|
'hierarchical_predecode2x4.hierarchical_predecode2x4',
|
||||||
'hierarchical_predecode3x8.hierarchical_predecode3x8']
|
'hierarchical_predecode3x8.hierarchical_predecode3x8']
|
||||||
if name not in design.name_map:
|
if name not in design.name_map:
|
||||||
|
|
@ -41,6 +46,7 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout):
|
||||||
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."""
|
||||||
from tech import drc
|
from tech import drc
|
||||||
|
self.well_width = drc["minwidth_well"]
|
||||||
self.poly_width = drc["minwidth_poly"]
|
self.poly_width = drc["minwidth_poly"]
|
||||||
self.poly_space = drc["poly_to_poly"]
|
self.poly_space = drc["poly_to_poly"]
|
||||||
self.m1_width = drc["minwidth_metal1"]
|
self.m1_width = drc["minwidth_metal1"]
|
||||||
|
|
@ -49,6 +55,15 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout):
|
||||||
self.m2_space = drc["metal2_to_metal2"]
|
self.m2_space = drc["metal2_to_metal2"]
|
||||||
self.m3_width = drc["minwidth_metal3"]
|
self.m3_width = drc["minwidth_metal3"]
|
||||||
self.m3_space = drc["metal3_to_metal3"]
|
self.m3_space = drc["metal3_to_metal3"]
|
||||||
|
self.active_width = drc["minwidth_active"]
|
||||||
|
self.contact_width = drc["minwidth_contact"]
|
||||||
|
|
||||||
|
self.poly_to_active = drc["poly_to_active"]
|
||||||
|
self.poly_extend_active = drc["poly_extend_active"]
|
||||||
|
self.contact_to_gate = drc["contact_to_gate"]
|
||||||
|
self.well_enclose_active = drc["well_enclosure_active"]
|
||||||
|
self.implant_enclose_active = drc["implant_enclosure_active"]
|
||||||
|
self.implant_space = drc["implant_to_implant"]
|
||||||
|
|
||||||
def get_layout_pins(self,inst):
|
def get_layout_pins(self,inst):
|
||||||
""" Return a map of pin locations of the instance offset """
|
""" Return a map of pin locations of the instance offset """
|
||||||
|
|
|
||||||
|
|
@ -336,14 +336,14 @@ class layout(lef.lef):
|
||||||
implant_type=implant_type,
|
implant_type=implant_type,
|
||||||
well_type=well_type)
|
well_type=well_type)
|
||||||
self.add_mod(via)
|
self.add_mod(via)
|
||||||
self.add_inst(name=via.name,
|
inst=self.add_inst(name=via.name,
|
||||||
mod=via,
|
mod=via,
|
||||||
offset=offset,
|
offset=offset,
|
||||||
mirror=mirror,
|
mirror=mirror,
|
||||||
rotate=rotate)
|
rotate=rotate)
|
||||||
# We don't model the logical connectivity of wires/paths
|
# We don't model the logical connectivity of wires/paths
|
||||||
self.connect_inst([])
|
self.connect_inst([])
|
||||||
return via
|
return inst
|
||||||
|
|
||||||
def add_via_center(self, layers, offset, size=[1,1], mirror="R0", rotate=0, implant_type=None, well_type=None):
|
def add_via_center(self, layers, offset, size=[1,1], mirror="R0", rotate=0, implant_type=None, well_type=None):
|
||||||
""" Add a three layer via structure by the center coordinate accounting for mirroring and rotation. """
|
""" Add a three layer via structure by the center coordinate accounting for mirroring and rotation. """
|
||||||
|
|
@ -371,14 +371,14 @@ class layout(lef.lef):
|
||||||
|
|
||||||
|
|
||||||
self.add_mod(via)
|
self.add_mod(via)
|
||||||
self.add_inst(name=via.name,
|
inst=self.add_inst(name=via.name,
|
||||||
mod=via,
|
mod=via,
|
||||||
offset=corrected_offset,
|
offset=corrected_offset,
|
||||||
mirror=mirror,
|
mirror=mirror,
|
||||||
rotate=rotate)
|
rotate=rotate)
|
||||||
# We don't model the logical connectivity of wires/paths
|
# We don't model the logical connectivity of wires/paths
|
||||||
self.connect_inst([])
|
self.connect_inst([])
|
||||||
return via
|
return inst
|
||||||
|
|
||||||
def add_ptx(self, offset, mirror="R0", rotate=0, width=1, mults=1, tx_type="nmos"):
|
def add_ptx(self, offset, mirror="R0", rotate=0, width=1, mults=1, tx_type="nmos"):
|
||||||
"""Adds a ptx module to the design."""
|
"""Adds a ptx module to the design."""
|
||||||
|
|
@ -387,12 +387,12 @@ class layout(lef.lef):
|
||||||
mults=mults,
|
mults=mults,
|
||||||
tx_type=tx_type)
|
tx_type=tx_type)
|
||||||
self.add_mod(mos)
|
self.add_mod(mos)
|
||||||
self.add_inst(name=mos.name,
|
inst=self.add_inst(name=mos.name,
|
||||||
mod=mos,
|
mod=mos,
|
||||||
offset=offset,
|
offset=offset,
|
||||||
mirror=mirror,
|
mirror=mirror,
|
||||||
rotate=rotate)
|
rotate=rotate)
|
||||||
return mos
|
return inst
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ class pgate(design.design):
|
||||||
debug.check(nmos_gate_pin.ll().x==pmos_gate_pin.ll().x, "Connecting unaligned gates not supported.")
|
debug.check(nmos_gate_pin.ll().x==pmos_gate_pin.ll().x, "Connecting unaligned gates not supported.")
|
||||||
|
|
||||||
# Pick point on the left of NMOS and connect down to PMOS
|
# Pick point on the left of NMOS and connect down to PMOS
|
||||||
nmos_gate_pos = nmos_gate_pin.ll() + vector(0.5*drc["minwidth_poly"],0)
|
nmos_gate_pos = nmos_gate_pin.ll() + vector(0.5*self.poly_width,0)
|
||||||
pmos_gate_pos = vector(nmos_gate_pos.x,pmos_gate_pin.bc().y)
|
pmos_gate_pos = vector(nmos_gate_pos.x,pmos_gate_pin.bc().y)
|
||||||
self.add_path("poly",[nmos_gate_pos,pmos_gate_pos])
|
self.add_path("poly",[nmos_gate_pos,pmos_gate_pos])
|
||||||
|
|
||||||
|
|
@ -98,9 +98,9 @@ class pgate(design.design):
|
||||||
""" Extend the n/p wells to cover whole cell """
|
""" Extend the n/p wells to cover whole cell """
|
||||||
|
|
||||||
# Add a rail width to extend the well to the top of the rail
|
# Add a rail width to extend the well to the top of the rail
|
||||||
self.max_y_offset = self.height + 0.5*drc["minwidth_metal1"]
|
max_y_offset = self.height + 0.5*self.m1_width
|
||||||
self.nwell_position = middle_position
|
self.nwell_position = middle_position
|
||||||
nwell_height = self.max_y_offset - middle_position.y
|
nwell_height = max_y_offset - middle_position.y
|
||||||
if info["has_nwell"]:
|
if info["has_nwell"]:
|
||||||
self.add_rect(layer="nwell",
|
self.add_rect(layer="nwell",
|
||||||
offset=middle_position,
|
offset=middle_position,
|
||||||
|
|
@ -111,15 +111,15 @@ class pgate(design.design):
|
||||||
width=self.well_width,
|
width=self.well_width,
|
||||||
height=nwell_height)
|
height=nwell_height)
|
||||||
|
|
||||||
self.pwell_position = vector(0,-0.5*drc["minwidth_metal1"])
|
pwell_position = vector(0,-0.5*self.m1_width)
|
||||||
pwell_height = middle_position.y-self.pwell_position.y
|
pwell_height = middle_position.y-pwell_position.y
|
||||||
if info["has_pwell"]:
|
if info["has_pwell"]:
|
||||||
self.add_rect(layer="pwell",
|
self.add_rect(layer="pwell",
|
||||||
offset=self.pwell_position,
|
offset=pwell_position,
|
||||||
width=self.well_width,
|
width=self.well_width,
|
||||||
height=pwell_height)
|
height=pwell_height)
|
||||||
self.add_rect(layer="vtg",
|
self.add_rect(layer="vtg",
|
||||||
offset=self.pwell_position,
|
offset=pwell_position,
|
||||||
width=self.well_width,
|
width=self.well_width,
|
||||||
height=pwell_height)
|
height=pwell_height)
|
||||||
|
|
||||||
|
|
@ -132,8 +132,9 @@ class pgate(design.design):
|
||||||
contact_xoffset = pmos_pos.x + pmos.active_width + drc["active_to_body_active"]
|
contact_xoffset = pmos_pos.x + pmos.active_width + drc["active_to_body_active"]
|
||||||
# Must be at least an well enclosure of active down from the top of the well
|
# Must be at least an well enclosure of active down from the top of the well
|
||||||
# OR align the active with the top of PMOS active.
|
# OR align the active with the top of PMOS active.
|
||||||
|
max_y_offset = self.height + 0.5*self.m1_width
|
||||||
contact_yoffset = min(pmos_pos.y + pmos.active_height - pmos.active_contact.first_layer_height,
|
contact_yoffset = min(pmos_pos.y + pmos.active_height - pmos.active_contact.first_layer_height,
|
||||||
self.max_y_offset - pmos.active_contact.first_layer_height/2 - drc["well_enclosure_active"])
|
max_y_offset - pmos.active_contact.first_layer_height/2 - self.well_enclose_active)
|
||||||
contact_offset = vector(contact_xoffset, contact_yoffset)
|
contact_offset = vector(contact_xoffset, contact_yoffset)
|
||||||
# Offset by half a contact in x and y
|
# Offset by half a contact in x and y
|
||||||
contact_offset += vector(0.5*pmos.active_contact.first_layer_width,
|
contact_offset += vector(0.5*pmos.active_contact.first_layer_width,
|
||||||
|
|
@ -144,11 +145,11 @@ class pgate(design.design):
|
||||||
well_type="n")
|
well_type="n")
|
||||||
self.add_rect_center(layer="metal1",
|
self.add_rect_center(layer="metal1",
|
||||||
offset=contact_offset + vector(0,0.5*(self.height-contact_offset.y)),
|
offset=contact_offset + vector(0,0.5*(self.height-contact_offset.y)),
|
||||||
width=self.nwell_contact.second_layer_width,
|
width=self.nwell_contact.mod.second_layer_width,
|
||||||
height=self.height - contact_offset.y)
|
height=self.height - contact_offset.y)
|
||||||
|
|
||||||
# Now add the full active and implant for the PMOS
|
# Now add the full active and implant for the PMOS
|
||||||
active_offset = pmos_pos + vector(pmos.active_width,0)
|
#active_offset = pmos_pos + vector(pmos.active_width,0)
|
||||||
# This might be needed if the spacing between the actives is not satisifed
|
# This might be needed if the spacing between the actives is not satisifed
|
||||||
# self.add_rect(layer="active",
|
# self.add_rect(layer="active",
|
||||||
# offset=active_offset,
|
# offset=active_offset,
|
||||||
|
|
@ -156,27 +157,29 @@ class pgate(design.design):
|
||||||
# height=pmos.active_height)
|
# height=pmos.active_height)
|
||||||
|
|
||||||
# we need to ensure implants don't overlap and are spaced far enough apart
|
# we need to ensure implants don't overlap and are spaced far enough apart
|
||||||
implant_spacing = drc["implant_to_implant"]+drc["implant_enclosure_active"]
|
# implant_spacing = self.implant_space+self.implant_enclose_active
|
||||||
implant_offset = active_offset + vector(implant_spacing,0) - vector(0,drc["implant_enclosure_active"])
|
# implant_offset = active_offset + vector(implant_spacing,0) - vector(0,self.implant_enclose_active)
|
||||||
implant_width = pmos.active_contact.width + 2*drc["implant_enclosure_active"]
|
# implant_width = pmos.active_contact.width + 2*self.implant_enclose_active
|
||||||
implant_height = pmos.active_height + 2*drc["implant_enclosure_active"]
|
# implant_height = pmos.active_height + 2*self.implant_enclose_active
|
||||||
# self.add_rect(layer="nimplant",
|
# self.add_rect(layer="nimplant",
|
||||||
# offset=implant_offset,
|
# offset=implant_offset,
|
||||||
# width=implant_width,
|
# width=implant_width,
|
||||||
# height=implant_height)
|
# height=implant_height)
|
||||||
|
|
||||||
|
# Return the top of the well
|
||||||
|
|
||||||
def add_pwell_contact(self, nmos, nmos_pos):
|
def add_pwell_contact(self, nmos, nmos_pos):
|
||||||
""" Add an pwell contact next to the given nmos device. """
|
""" Add an pwell contact next to the given nmos device. """
|
||||||
|
|
||||||
layer_stack = ("active", "contact", "metal1")
|
layer_stack = ("active", "contact", "metal1")
|
||||||
|
|
||||||
|
pwell_position = vector(0,-0.5*self.m1_width)
|
||||||
|
|
||||||
# To the right a spacing away from the nmos right active edge
|
# To the right a spacing away from the nmos right active edge
|
||||||
contact_xoffset = nmos_pos.x + nmos.active_width + drc["active_to_body_active"]
|
contact_xoffset = nmos_pos.x + nmos.active_width + drc["active_to_body_active"]
|
||||||
# Must be at least an well enclosure of active up from the bottom of the well
|
# Must be at least an well enclosure of active up from the bottom of the well
|
||||||
contact_yoffset = max(nmos_pos.y,
|
contact_yoffset = max(nmos_pos.y,
|
||||||
drc["well_enclosure_active"] - nmos.active_contact.first_layer_height/2 - self.pwell_position.y)
|
self.well_enclose_active - nmos.active_contact.first_layer_height/2)
|
||||||
contact_offset = vector(contact_xoffset, contact_yoffset)
|
contact_offset = vector(contact_xoffset, contact_yoffset)
|
||||||
|
|
||||||
# Offset by half a contact
|
# Offset by half a contact
|
||||||
|
|
@ -188,21 +191,21 @@ class pgate(design.design):
|
||||||
well_type="p")
|
well_type="p")
|
||||||
self.add_rect_center(layer="metal1",
|
self.add_rect_center(layer="metal1",
|
||||||
offset=contact_offset.scale(1,0.5),
|
offset=contact_offset.scale(1,0.5),
|
||||||
width=self.pwell_contact.second_layer_width,
|
width=self.pwell_contact.mod.second_layer_width,
|
||||||
height=contact_offset.y)
|
height=contact_offset.y)
|
||||||
|
|
||||||
# Now add the full active and implant for the NMOS
|
# Now add the full active and implant for the NMOS
|
||||||
active_offset = nmos_pos + vector(nmos.active_width,0)
|
# active_offset = nmos_pos + vector(nmos.active_width,0)
|
||||||
# This might be needed if the spacing between the actives is not satisifed
|
# This might be needed if the spacing between the actives is not satisifed
|
||||||
# self.add_rect(layer="active",
|
# self.add_rect(layer="active",
|
||||||
# offset=active_offset,
|
# offset=active_offset,
|
||||||
# width=nmos.active_contact.width,
|
# width=nmos.active_contact.width,
|
||||||
# height=nmos.active_height)
|
# height=nmos.active_height)
|
||||||
|
|
||||||
implant_spacing = drc["implant_to_implant"]+drc["implant_enclosure_active"]
|
# implant_spacing = self.implant_space+self.implant_enclose_active
|
||||||
implant_offset = active_offset + vector(implant_spacing,0) - vector(0,drc["implant_enclosure_active"])
|
# implant_offset = active_offset + vector(implant_spacing,0) - vector(0,self.implant_enclose_active)
|
||||||
implant_width = nmos.active_contact.width + 2*drc["implant_enclosure_active"]
|
# implant_width = nmos.active_contact.width + 2*self.implant_enclose_active
|
||||||
implant_height = nmos.active_height + 2*drc["implant_enclosure_active"]
|
# implant_height = nmos.active_height + 2*self.implant_enclose_active
|
||||||
# self.add_rect(layer="pimplant",
|
# self.add_rect(layer="pimplant",
|
||||||
# offset=implant_offset,
|
# offset=implant_offset,
|
||||||
# width=implant_width,
|
# width=implant_width,
|
||||||
|
|
|
||||||
|
|
@ -57,8 +57,8 @@ class pinv(pgate.pgate):
|
||||||
self.setup_layout_constants()
|
self.setup_layout_constants()
|
||||||
self.add_supply_rails()
|
self.add_supply_rails()
|
||||||
self.add_ptx()
|
self.add_ptx()
|
||||||
self.extend_wells(self.well_pos)
|
|
||||||
self.add_well_contacts()
|
self.add_well_contacts()
|
||||||
|
self.extend_wells(self.well_pos)
|
||||||
self.connect_rails()
|
self.connect_rails()
|
||||||
self.route_input_gate(self.pmos_inst, self.nmos_inst, self.output_pos.y, "A", rotate=0)
|
self.route_input_gate(self.pmos_inst, self.nmos_inst, self.output_pos.y, "A", rotate=0)
|
||||||
self.route_outputs()
|
self.route_outputs()
|
||||||
|
|
@ -128,9 +128,6 @@ class pinv(pgate.pgate):
|
||||||
self.width = self.well_width
|
self.width = self.well_width
|
||||||
# Height is an input parameter, so it is not recomputed.
|
# Height is an input parameter, so it is not recomputed.
|
||||||
|
|
||||||
# This will help with the wells
|
|
||||||
self.well_pos = vector(0,0.4*self.height)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def create_ptx(self):
|
def create_ptx(self):
|
||||||
|
|
@ -183,8 +180,13 @@ class pinv(pgate.pgate):
|
||||||
self.connect_inst(["Z", "A", "gnd", "gnd"])
|
self.connect_inst(["Z", "A", "gnd", "gnd"])
|
||||||
|
|
||||||
|
|
||||||
# Output position will be in between the PMOS and NMOS
|
# Output position will be in between the PMOS and NMOS drains
|
||||||
self.output_pos = vector(0,0.5*(self.pmos_pos.y+self.nmos_pos.y+self.nmos.active_height))
|
pmos_drain_pos = self.pmos_inst.get_pin("D").ll()
|
||||||
|
nmos_drain_pos = self.nmos_inst.get_pin("D").ul()
|
||||||
|
self.output_pos = vector(0,0.5*(pmos_drain_pos.y+nmos_drain_pos.y))
|
||||||
|
|
||||||
|
# This will help with the wells
|
||||||
|
self.well_pos = vector(0,self.nmos_inst.uy())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -196,7 +198,7 @@ class pinv(pgate.pgate):
|
||||||
pmos_drain_pin = self.pmos_inst.get_pin("D")
|
pmos_drain_pin = self.pmos_inst.get_pin("D")
|
||||||
|
|
||||||
# Pick point at right most of NMOS and connect down to PMOS
|
# Pick point at right most of NMOS and connect down to PMOS
|
||||||
nmos_drain_pos = nmos_drain_pin.ur() - vector(0.5*self.m1_width,0)
|
nmos_drain_pos = nmos_drain_pin.lr() - vector(0.5*self.m1_width,0)
|
||||||
pmos_drain_pos = vector(nmos_drain_pos.x, pmos_drain_pin.bc().y)
|
pmos_drain_pos = vector(nmos_drain_pos.x, pmos_drain_pin.bc().y)
|
||||||
self.add_path("metal1",[nmos_drain_pos,pmos_drain_pos])
|
self.add_path("metal1",[nmos_drain_pos,pmos_drain_pos])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,8 @@ class pnand2(pgate.pgate):
|
||||||
self.add_supply_rails()
|
self.add_supply_rails()
|
||||||
self.add_ptx()
|
self.add_ptx()
|
||||||
self.connect_rails()
|
self.connect_rails()
|
||||||
self.extend_wells(self.well_pos)
|
|
||||||
self.add_well_contacts()
|
self.add_well_contacts()
|
||||||
|
self.extend_wells(self.well_pos)
|
||||||
self.route_inputs()
|
self.route_inputs()
|
||||||
self.route_output()
|
self.route_output()
|
||||||
|
|
||||||
|
|
@ -94,9 +94,6 @@ class pnand2(pgate.pgate):
|
||||||
self.width = self.well_width
|
self.width = self.well_width
|
||||||
# Height is an input parameter, so it is not recomputed.
|
# Height is an input parameter, so it is not recomputed.
|
||||||
|
|
||||||
# This will help with the wells
|
|
||||||
self.well_pos = vector(0,0.4*self.height)
|
|
||||||
|
|
||||||
# This is the extra space needed to ensure DRC rules to the active contacts
|
# This is the extra space needed to ensure DRC rules to the active contacts
|
||||||
extra_contact_space = max(-self.nmos.get_pin("D").by(),0)
|
extra_contact_space = max(-self.nmos.get_pin("D").by(),0)
|
||||||
# This is a poly-to-poly of a flipped cell
|
# This is a poly-to-poly of a flipped cell
|
||||||
|
|
@ -150,6 +147,9 @@ class pnand2(pgate.pgate):
|
||||||
# Output position will be in between the PMOS and NMOS
|
# Output position will be in between the PMOS and NMOS
|
||||||
self.output_pos = vector(0,0.5*(pmos1_pos.y+nmos1_pos.y+self.nmos.active_height))
|
self.output_pos = vector(0,0.5*(pmos1_pos.y+nmos1_pos.y+self.nmos.active_height))
|
||||||
|
|
||||||
|
# This will help with the wells
|
||||||
|
self.well_pos = vector(0,self.nmos1_inst.uy())
|
||||||
|
|
||||||
def add_well_contacts(self):
|
def add_well_contacts(self):
|
||||||
""" Add n/p well taps to the layout and connect to supplies AFTER the wells are created """
|
""" Add n/p well taps to the layout and connect to supplies AFTER the wells are created """
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,8 @@ class pnand3(pgate.pgate):
|
||||||
self.add_supply_rails()
|
self.add_supply_rails()
|
||||||
self.add_ptx()
|
self.add_ptx()
|
||||||
self.connect_rails()
|
self.connect_rails()
|
||||||
self.extend_wells(self.well_pos)
|
|
||||||
self.add_well_contacts()
|
self.add_well_contacts()
|
||||||
|
self.extend_wells(self.well_pos)
|
||||||
self.route_inputs()
|
self.route_inputs()
|
||||||
self.route_output()
|
self.route_output()
|
||||||
|
|
||||||
|
|
@ -88,7 +88,6 @@ class pnand3(pgate.pgate):
|
||||||
|
|
||||||
# This will help with the wells and the input/output placement
|
# This will help with the wells and the input/output placement
|
||||||
self.output_pos = vector(0,0.5*self.height)
|
self.output_pos = vector(0,0.5*self.height)
|
||||||
self.well_pos = vector(0,0.4*self.height)
|
|
||||||
|
|
||||||
# This is a poly-to-poly of a flipped cell
|
# This is a poly-to-poly of a flipped cell
|
||||||
# This is extra liberal for pnand3 because we know there are big transistor sizes
|
# This is extra liberal for pnand3 because we know there are big transistor sizes
|
||||||
|
|
@ -153,6 +152,8 @@ class pnand3(pgate.pgate):
|
||||||
offset=self.nmos3_pos)
|
offset=self.nmos3_pos)
|
||||||
self.connect_inst(["net2", "C", "gnd", "gnd"])
|
self.connect_inst(["net2", "C", "gnd", "gnd"])
|
||||||
|
|
||||||
|
# This should be placed at the top of the NMOS well
|
||||||
|
self.well_pos = vector(0,self.nmos1_inst.uy())
|
||||||
|
|
||||||
def add_well_contacts(self):
|
def add_well_contacts(self):
|
||||||
""" Add n/p well taps to the layout and connect to supplies """
|
""" Add n/p well taps to the layout and connect to supplies """
|
||||||
|
|
|
||||||
|
|
@ -52,8 +52,8 @@ class pnor2(pgate.pgate):
|
||||||
self.add_supply_rails()
|
self.add_supply_rails()
|
||||||
self.add_ptx()
|
self.add_ptx()
|
||||||
self.connect_rails()
|
self.connect_rails()
|
||||||
self.extend_wells(self.well_pos)
|
|
||||||
self.add_well_contacts()
|
self.add_well_contacts()
|
||||||
|
self.extend_wells(self.well_pos)
|
||||||
self.route_inputs()
|
self.route_inputs()
|
||||||
self.route_output()
|
self.route_output()
|
||||||
|
|
||||||
|
|
@ -98,9 +98,6 @@ class pnor2(pgate.pgate):
|
||||||
self.width = self.well_width
|
self.width = self.well_width
|
||||||
# Height is an input parameter, so it is not recomputed.
|
# Height is an input parameter, so it is not recomputed.
|
||||||
|
|
||||||
# This will help with the wells
|
|
||||||
self.well_pos = vector(0,0.4*self.height)
|
|
||||||
|
|
||||||
# This is the extra space needed to ensure DRC rules to the active contacts
|
# This is the extra space needed to ensure DRC rules to the active contacts
|
||||||
extra_contact_space = max(-self.nmos.get_pin("D").by(),0)
|
extra_contact_space = max(-self.nmos.get_pin("D").by(),0)
|
||||||
# This is a poly-to-poly of a flipped cell
|
# This is a poly-to-poly of a flipped cell
|
||||||
|
|
@ -154,6 +151,9 @@ class pnor2(pgate.pgate):
|
||||||
# Output position will be in between the PMOS and NMOS
|
# Output position will be in between the PMOS and NMOS
|
||||||
self.output_pos = vector(0,0.5*(pmos1_pos.y+nmos1_pos.y+self.nmos.active_height))
|
self.output_pos = vector(0,0.5*(pmos1_pos.y+nmos1_pos.y+self.nmos.active_height))
|
||||||
|
|
||||||
|
# This will help with the wells
|
||||||
|
self.well_pos = vector(0,self.nmos1_inst.uy())
|
||||||
|
|
||||||
def add_well_contacts(self):
|
def add_well_contacts(self):
|
||||||
""" Add n/p well taps to the layout and connect to supplies """
|
""" Add n/p well taps to the layout and connect to supplies """
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -94,25 +94,19 @@ class ptx(design.design):
|
||||||
self.active_contact = contact(layer_stack=("active", "contact", "metal1"),
|
self.active_contact = contact(layer_stack=("active", "contact", "metal1"),
|
||||||
dimensions=(1, self.num_contacts))
|
dimensions=(1, self.num_contacts))
|
||||||
|
|
||||||
# Standard DRC rules
|
|
||||||
self.min_active_width = drc["minwidth_active"]
|
|
||||||
self.contact_width = drc["minwidth_contact"]
|
|
||||||
self.poly_width = drc["minwidth_poly"]
|
|
||||||
self.poly_to_active = drc["poly_to_active"]
|
|
||||||
self.poly_extend_active = drc["poly_extend_active"]
|
|
||||||
|
|
||||||
# The contacted poly pitch (or uncontacted in an odd technology)
|
# The contacted poly pitch (or uncontacted in an odd technology)
|
||||||
self.poly_pitch = max(2*drc["contact_to_gate"] + self.contact_width + self.poly_width,
|
self.poly_pitch = max(2*self.contact_to_gate + self.contact_width + self.poly_width,
|
||||||
drc["poly_to_poly"])
|
self.poly_space)
|
||||||
|
|
||||||
# The contacted poly pitch (or uncontacted in an odd technology)
|
# The contacted poly pitch (or uncontacted in an odd technology)
|
||||||
self.contact_pitch = 2*drc["contact_to_gate"] + self.contact_width + self.poly_width
|
self.contact_pitch = 2*self.contact_to_gate + self.contact_width + self.poly_width
|
||||||
|
|
||||||
# The enclosure of an active contact. Not sure about second term.
|
# The enclosure of an active contact. Not sure about second term.
|
||||||
active_enclose_contact = max(drc["active_enclosure_contact"],
|
active_enclose_contact = max(drc["active_enclosure_contact"],
|
||||||
(self.min_active_width - self.contact_width)/2)
|
(self.active_width - self.contact_width)/2)
|
||||||
# This is the distance from the edge of poly to the contacted end of active
|
# This is the distance from the edge of poly to the contacted end of active
|
||||||
self.end_to_poly = active_enclose_contact + self.contact_width + drc["contact_to_gate"]
|
self.end_to_poly = active_enclose_contact + self.contact_width + self.contact_to_gate
|
||||||
|
|
||||||
|
|
||||||
# Active width is determined by enclosure on both ends and contacted pitch,
|
# Active width is determined by enclosure on both ends and contacted pitch,
|
||||||
|
|
@ -125,22 +119,25 @@ class ptx(design.design):
|
||||||
# Poly height must include poly extension over active
|
# Poly height must include poly extension over active
|
||||||
self.poly_height = self.tx_width + 2*self.poly_extend_active
|
self.poly_height = self.tx_width + 2*self.poly_extend_active
|
||||||
|
|
||||||
|
# The active offset is due to the well extension
|
||||||
|
self.active_offset = vector([self.well_enclose_active]*2)
|
||||||
|
|
||||||
# Well enclosure of active, ensure minwidth as well
|
# Well enclosure of active, ensure minwidth as well
|
||||||
if info["has_{}well".format(self.well_type)]:
|
if info["has_{}well".format(self.well_type)]:
|
||||||
self.well_width = max(self.active_width + 2*drc["well_enclosure_active"],
|
self.cell_well_width = max(self.active_width + 2*self.well_enclose_active,
|
||||||
drc["minwidth_well"])
|
self.well_width)
|
||||||
self.well_height = max(self.tx_width + 2*drc["well_enclosure_active"],
|
self.cell_well_height = max(self.tx_width + 2*self.well_enclose_active,
|
||||||
drc["minwidth_well"])
|
self.well_width)
|
||||||
|
# We are going to shift the 0,0, so include that in the width and height
|
||||||
self.height = self.well_height
|
self.height = self.cell_well_height - self.active_offset.y
|
||||||
self.width = self.well_width
|
self.width = self.cell_well_width - self.active_offset.x
|
||||||
else:
|
else:
|
||||||
# If no well, use the boundary of the active and poly
|
# If no well, use the boundary of the active and poly
|
||||||
self.height = self.poly_height
|
self.height = self.poly_height
|
||||||
self.width = self.active_width
|
self.width = self.active_width
|
||||||
|
|
||||||
# The active offset is due to the well extension
|
# The active offset is due to the well extension
|
||||||
self.active_offset = vector([drc["well_enclosure_active"]]*2)
|
self.active_offset = vector([self.well_enclose_active]*2)
|
||||||
|
|
||||||
# This is the center of the first active contact offset (centered vertically)
|
# This is the center of the first active contact offset (centered vertically)
|
||||||
self.contact_offset = self.active_offset + vector(active_enclose_contact + 0.5*self.contact_width,
|
self.contact_offset = self.active_offset + vector(active_enclose_contact + 0.5*self.contact_width,
|
||||||
|
|
@ -189,9 +186,9 @@ class ptx(design.design):
|
||||||
# This is the distance that we must route up or down from the center
|
# This is the distance that we must route up or down from the center
|
||||||
# of the contacts to avoid DRC violations to the other contacts
|
# of the contacts to avoid DRC violations to the other contacts
|
||||||
pin_offset = vector(0, 0.5*self.active_contact.second_layer_height \
|
pin_offset = vector(0, 0.5*self.active_contact.second_layer_height \
|
||||||
+ drc["metal1_to_metal1"] + 0.5*drc["minwidth_metal1"])
|
+ self.m1_space + 0.5*self.m1_width)
|
||||||
# This is the width of a contact to extend the ends of the pin
|
# This is the width of a m1 extend the ends of the pin
|
||||||
end_offset = vector(self.active_contact.second_layer_width/2,0)
|
end_offset = vector(self.m1_width/2,0)
|
||||||
|
|
||||||
# drains always go to the MIDDLE of the cell, so top of NMOS, bottom of PMOS
|
# drains always go to the MIDDLE of the cell, so top of NMOS, bottom of PMOS
|
||||||
# so reverse the directions for NMOS compared to PMOS.
|
# so reverse the directions for NMOS compared to PMOS.
|
||||||
|
|
@ -280,12 +277,12 @@ class ptx(design.design):
|
||||||
if info["has_{}well".format(self.well_type)]:
|
if info["has_{}well".format(self.well_type)]:
|
||||||
self.add_rect(layer="{}well".format(self.well_type),
|
self.add_rect(layer="{}well".format(self.well_type),
|
||||||
offset=(0,0),
|
offset=(0,0),
|
||||||
width=self.well_width,
|
width=self.cell_well_width,
|
||||||
height=self.well_height)
|
height=self.cell_well_height)
|
||||||
self.add_rect(layer="vtg",
|
self.add_rect(layer="vtg",
|
||||||
offset=(0,0),
|
offset=(0,0),
|
||||||
width=self.well_width,
|
width=self.cell_well_width,
|
||||||
height=self.well_height)
|
height=self.cell_well_height)
|
||||||
|
|
||||||
|
|
||||||
def calculate_num_contacts(self):
|
def calculate_num_contacts(self):
|
||||||
|
|
@ -331,8 +328,8 @@ class ptx(design.design):
|
||||||
self.add_layout_pin_center_rect(text="S",
|
self.add_layout_pin_center_rect(text="S",
|
||||||
layer="metal1",
|
layer="metal1",
|
||||||
offset=pos,
|
offset=pos,
|
||||||
width=contact.second_layer_width,
|
width=contact.mod.second_layer_width,
|
||||||
height=contact.second_layer_height)
|
height=contact.mod.second_layer_height)
|
||||||
|
|
||||||
|
|
||||||
for pos in drain_positions:
|
for pos in drain_positions:
|
||||||
|
|
@ -344,8 +341,8 @@ class ptx(design.design):
|
||||||
self.add_layout_pin_center_rect(text="D",
|
self.add_layout_pin_center_rect(text="D",
|
||||||
layer="metal1",
|
layer="metal1",
|
||||||
offset=pos,
|
offset=pos,
|
||||||
width=contact.second_layer_width,
|
width=contact.mod.second_layer_width,
|
||||||
height=contact.second_layer_height)
|
height=contact.mod.second_layer_height)
|
||||||
|
|
||||||
if self.connect_active:
|
if self.connect_active:
|
||||||
self.connect_fingered_active(drain_positions, source_positions)
|
self.connect_fingered_active(drain_positions, source_positions)
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,13 @@ ln -s 2001a current
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
magic -dnull -noconsole << EOF
|
magic -dnull -noconsole << EOF
|
||||||
tech load SCN3ME_SUBM.30
|
tech load SCN3ME_SUBM.30
|
||||||
gds rescale false
|
scalegrid 1 2
|
||||||
|
gds rescale no
|
||||||
gds polygon subcell true
|
gds polygon subcell true
|
||||||
gds warning default
|
gds warning default
|
||||||
gds read $1
|
gds read $1
|
||||||
load $1
|
load $1
|
||||||
save $1
|
writeall force
|
||||||
drc count
|
drc count
|
||||||
drc why
|
drc why
|
||||||
quit -noprompt
|
quit -noprompt
|
||||||
|
|
@ -29,7 +30,8 @@ rm -f $1.ext
|
||||||
rm -f $1.spice
|
rm -f $1.spice
|
||||||
magic -dnull -noconsole << EOF
|
magic -dnull -noconsole << EOF
|
||||||
tech load SCN3ME_SUBM.30
|
tech load SCN3ME_SUBM.30
|
||||||
gds rescale false
|
scalegrid 1 2
|
||||||
|
gds rescale no
|
||||||
gds polygon subcell true
|
gds polygon subcell true
|
||||||
gds warning default
|
gds warning default
|
||||||
gds read $1
|
gds read $1
|
||||||
|
|
@ -72,12 +74,13 @@ def write_magic_script(cell_name, gds_name, extract=False):
|
||||||
f.write("#!/bin/sh\n")
|
f.write("#!/bin/sh\n")
|
||||||
f.write("{} -dnull -noconsole << EOF\n".format(OPTS.drc_exe[1]))
|
f.write("{} -dnull -noconsole << EOF\n".format(OPTS.drc_exe[1]))
|
||||||
f.write("tech load SCN3ME_SUBM.30\n")
|
f.write("tech load SCN3ME_SUBM.30\n")
|
||||||
f.write("gds rescale false\n")
|
f.write("scalegrid 1 2\n")
|
||||||
|
f.write("gds rescale no\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")
|
||||||
f.write("gds read {}\n".format(gds_name))
|
f.write("gds read {}\n".format(gds_name))
|
||||||
f.write("load {}\n".format(cell_name))
|
f.write("load {}\n".format(cell_name))
|
||||||
f.write("save {}\n".format(cell_name))
|
f.write("writeall force\n")
|
||||||
f.write("drc check\n")
|
f.write("drc check\n")
|
||||||
f.write("drc catchup\n")
|
f.write("drc catchup\n")
|
||||||
f.write("drc count total\n")
|
f.write("drc count total\n")
|
||||||
|
|
@ -123,6 +126,12 @@ def write_netgen_script(cell_name, sp_name):
|
||||||
cell_name))
|
cell_name))
|
||||||
f.write("property {{{0}{1}.spice pfet}} remove as ad ps pd\n".format(OPTS.openram_temp,
|
f.write("property {{{0}{1}.spice pfet}} remove as ad ps pd\n".format(OPTS.openram_temp,
|
||||||
cell_name))
|
cell_name))
|
||||||
|
# Allow some flexibility in W size because magic will snap to a lambda grid
|
||||||
|
# This can also cause disconnects unfortunately!
|
||||||
|
# f.write("property {{{0}{1}.spice nfet}} tolerance {{w 0.1}}\n".format(OPTS.openram_temp,
|
||||||
|
# cell_name))
|
||||||
|
# f.write("property {{{0}{1}.spice pfet}} tolerance {{w 0.1}}\n".format(OPTS.openram_temp,
|
||||||
|
# cell_name))
|
||||||
f.write("permute default\n")
|
f.write("permute default\n")
|
||||||
f.write("log start\n")
|
f.write("log start\n")
|
||||||
f.write("compare hierarchical {0}{1}.spice {{{2} {1}}}\n".format(OPTS.openram_temp,
|
f.write("compare hierarchical {0}{1}.spice {{{2} {1}}}\n".format(OPTS.openram_temp,
|
||||||
|
|
|
||||||
|
|
@ -149,7 +149,7 @@ class wordline_driver(design.design):
|
||||||
self.add_segment_center(layer="metal1",
|
self.add_segment_center(layer="metal1",
|
||||||
start=clk_offset,
|
start=clk_offset,
|
||||||
end=a_pos)
|
end=a_pos)
|
||||||
m1m2_via = self.add_via_center(layers=("metal1", "via1", "metal2"),
|
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||||
offset=clk_offset)
|
offset=clk_offset)
|
||||||
|
|
||||||
# first inv to nand2 A
|
# first inv to nand2 A
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,119 +1,114 @@
|
||||||
magic
|
magic
|
||||||
tech scmos
|
tech scmos
|
||||||
timestamp 1516665972
|
timestamp 1516839303
|
||||||
<< nwell >>
|
<< nwell >>
|
||||||
rect -5 31 42 52
|
rect -8 29 42 50
|
||||||
<< pwell >>
|
<< pwell >>
|
||||||
rect -5 -6 42 31
|
rect -8 -8 42 29
|
||||||
<< ntransistor >>
|
<< ntransistor >>
|
||||||
rect 7 12 9 20
|
rect 7 10 9 18
|
||||||
rect 29 12 31 20
|
rect 29 10 31 18
|
||||||
rect 10 5 14 7
|
rect 10 3 14 5
|
||||||
rect 24 5 28 7
|
rect 24 3 28 5
|
||||||
<< ptransistor >>
|
<< ptransistor >>
|
||||||
rect 7 39 11 42
|
rect 7 37 11 40
|
||||||
rect 27 39 31 42
|
rect 27 37 31 40
|
||||||
<< ndiffusion >>
|
<< ndiffusion >>
|
||||||
rect 2 20 6 23
|
rect -2 16 7 18
|
||||||
rect 32 20 36 23
|
|
||||||
rect 6 16 7 20
|
|
||||||
rect 2 12 7 16
|
rect 2 12 7 16
|
||||||
rect 9 16 10 20
|
rect -2 10 7 12
|
||||||
rect 9 12 14 16
|
rect 9 14 10 18
|
||||||
rect 28 16 29 20
|
rect 9 10 14 14
|
||||||
rect 24 12 29 16
|
rect 28 14 29 18
|
||||||
rect 31 16 32 20
|
rect 24 10 29 14
|
||||||
rect 31 12 36 16
|
rect 31 16 36 18
|
||||||
rect 10 7 14 12
|
rect 31 12 32 16
|
||||||
rect 24 7 28 12
|
rect 31 10 36 12
|
||||||
rect 10 4 14 5
|
rect 10 5 14 10
|
||||||
rect 24 4 28 5
|
rect 24 5 28 10
|
||||||
|
rect 10 2 14 3
|
||||||
|
rect 24 2 28 3
|
||||||
<< pdiffusion >>
|
<< pdiffusion >>
|
||||||
rect 2 42 6 45
|
rect 32 40 36 43
|
||||||
rect 32 42 36 45
|
rect 2 37 7 40
|
||||||
rect 6 39 7 42
|
rect 11 37 12 40
|
||||||
rect 11 39 12 42
|
rect 26 37 27 40
|
||||||
rect 26 39 27 42
|
rect 31 37 32 40
|
||||||
rect 31 39 32 42
|
|
||||||
<< ndcontact >>
|
<< ndcontact >>
|
||||||
rect 2 16 6 20
|
rect -2 12 2 16
|
||||||
rect 10 16 14 20
|
rect 10 14 14 18
|
||||||
rect 24 16 28 20
|
rect 24 14 28 18
|
||||||
rect 32 16 36 20
|
rect 32 12 36 16
|
||||||
rect 10 0 14 4
|
rect 10 -2 14 2
|
||||||
rect 24 0 28 4
|
rect 24 -2 28 2
|
||||||
<< pdcontact >>
|
<< pdcontact >>
|
||||||
rect 2 38 6 42
|
rect -2 36 2 40
|
||||||
rect 12 38 16 42
|
rect 12 36 16 40
|
||||||
rect 22 38 26 42
|
rect 22 36 26 40
|
||||||
rect 32 38 36 42
|
rect 32 36 36 40
|
||||||
<< psubstratepcontact >>
|
<< psubstratepcontact >>
|
||||||
rect 2 23 6 27
|
rect 32 22 36 26
|
||||||
rect 32 23 36 27
|
|
||||||
<< nsubstratencontact >>
|
<< nsubstratencontact >>
|
||||||
rect 0 45 6 49
|
rect 32 43 36 47
|
||||||
rect 32 45 36 49
|
|
||||||
<< polysilicon >>
|
<< polysilicon >>
|
||||||
rect 7 42 11 44
|
rect 7 40 11 42
|
||||||
rect 27 42 31 44
|
rect 27 40 31 42
|
||||||
rect 7 37 11 39
|
rect 7 35 11 37
|
||||||
rect 7 23 9 37
|
rect 7 21 9 35
|
||||||
rect 27 36 31 39
|
rect 27 34 31 37
|
||||||
rect 15 35 31 36
|
rect 15 33 31 34
|
||||||
rect 19 34 31 35
|
rect 19 32 31 33
|
||||||
rect 7 22 21 23
|
rect 7 20 21 21
|
||||||
rect 7 21 24 22
|
rect 7 19 24 20
|
||||||
rect 7 20 9 21
|
rect 7 18 9 19
|
||||||
rect 29 20 31 34
|
rect 29 18 31 32
|
||||||
rect 7 10 9 12
|
rect 7 8 9 10
|
||||||
rect 17 7 21 8
|
rect 17 5 21 6
|
||||||
rect 29 10 31 12
|
rect 29 8 31 10
|
||||||
rect 0 5 10 7
|
rect -2 3 10 5
|
||||||
rect 14 5 24 7
|
rect 14 3 24 5
|
||||||
rect 28 5 36 7
|
rect 28 3 36 5
|
||||||
<< polycontact >>
|
<< polycontact >>
|
||||||
rect 15 31 19 35
|
rect 15 29 19 33
|
||||||
rect 21 22 25 26
|
rect 21 20 25 24
|
||||||
rect 17 8 21 12
|
rect 17 6 21 10
|
||||||
<< metal1 >>
|
<< metal1 >>
|
||||||
rect 6 45 32 49
|
rect -2 43 32 47
|
||||||
rect 2 42 6 45
|
rect -2 40 2 43
|
||||||
rect 32 42 36 45
|
rect 32 40 36 43
|
||||||
rect 2 27 6 31
|
rect -2 16 2 29
|
||||||
rect 2 20 6 23
|
rect 11 18 15 36
|
||||||
rect 11 20 15 38
|
rect 23 24 27 36
|
||||||
rect 23 26 27 38
|
rect 25 20 27 24
|
||||||
rect 25 22 27 26
|
rect 23 18 27 20
|
||||||
rect 23 20 27 22
|
rect 32 26 36 29
|
||||||
rect 32 27 36 31
|
rect 32 16 36 22
|
||||||
rect 32 20 36 23
|
rect -2 6 17 9
|
||||||
rect 0 8 17 11
|
rect 21 6 36 9
|
||||||
rect 21 8 36 11
|
rect -2 5 36 6
|
||||||
rect 0 7 36 8
|
rect 9 -2 10 2
|
||||||
rect 9 0 10 4
|
rect 23 -2 24 2
|
||||||
rect 23 0 24 4
|
|
||||||
<< m2contact >>
|
<< m2contact >>
|
||||||
rect 2 31 6 35
|
rect -2 29 2 33
|
||||||
rect 32 31 36 35
|
rect 32 29 36 33
|
||||||
rect 5 0 9 4
|
rect 5 -2 9 2
|
||||||
rect 19 0 23 4
|
rect 19 -2 23 2
|
||||||
<< metal2 >>
|
<< metal2 >>
|
||||||
rect 0 35 6 49
|
rect -2 33 2 47
|
||||||
rect 0 31 2 35
|
rect -2 12 2 29
|
||||||
rect 0 14 6 31
|
rect 10 2 14 47
|
||||||
rect 10 4 14 49
|
rect 20 2 24 47
|
||||||
rect 20 4 24 49
|
rect 9 -2 14 2
|
||||||
rect 9 0 14 4
|
rect 23 -2 24 2
|
||||||
rect 23 0 24 4
|
rect 32 33 36 47
|
||||||
rect 32 35 36 49
|
rect 32 -2 36 29
|
||||||
rect 32 0 36 31
|
|
||||||
<< m3p >>
|
<< m3p >>
|
||||||
rect 0 0 34 49
|
rect 0 0 34 45
|
||||||
<< labels >>
|
<< labels >>
|
||||||
rlabel m2contact 20 4 20 4 1 BR
|
rlabel m2contact 20 2 20 2 1 BR
|
||||||
rlabel metal2 10 4 10 4 1 BL
|
rlabel metal2 10 2 10 2 1 BL
|
||||||
rlabel metal2 32 31 32 31 7 gnd
|
rlabel metal1 2 6 2 6 3 WL
|
||||||
rlabel metal1 32 45 32 45 4 vdd
|
rlabel metal2 -1 28 -1 28 1 gnd
|
||||||
rlabel metal2 2 31 2 31 3 gnd
|
rlabel metal2 33 28 33 28 1 gnd
|
||||||
rlabel metal1 2 8 2 8 3 WL
|
rlabel metal1 17 45 17 45 5 vdd
|
||||||
<< end >>
|
<< end >>
|
||||||
|
|
|
||||||
|
|
@ -1,122 +1,116 @@
|
||||||
magic
|
magic
|
||||||
tech scmos
|
tech scmos
|
||||||
timestamp 1516666672
|
timestamp 1516980606
|
||||||
<< nwell >>
|
<< nwell >>
|
||||||
rect -4 31 42 53
|
rect -8 29 42 50
|
||||||
<< pwell >>
|
<< pwell >>
|
||||||
rect -4 -6 42 31
|
rect -8 -8 42 29
|
||||||
<< ntransistor >>
|
<< ntransistor >>
|
||||||
rect 7 12 9 20
|
rect 7 10 9 18
|
||||||
rect 29 12 31 20
|
rect 29 10 31 18
|
||||||
rect 10 5 14 7
|
rect 10 3 14 5
|
||||||
rect 24 5 28 7
|
rect 24 3 28 5
|
||||||
<< ptransistor >>
|
<< ptransistor >>
|
||||||
rect 7 39 11 42
|
rect 7 37 11 40
|
||||||
rect 27 39 31 42
|
rect 27 37 31 40
|
||||||
<< ndiffusion >>
|
<< ndiffusion >>
|
||||||
rect 2 20 6 23
|
rect -2 16 7 18
|
||||||
rect 32 20 36 23
|
|
||||||
rect 6 16 7 20
|
|
||||||
rect 2 12 7 16
|
rect 2 12 7 16
|
||||||
rect 9 16 10 20
|
rect -2 10 7 12
|
||||||
rect 9 12 14 16
|
rect 9 14 10 18
|
||||||
rect 28 16 29 20
|
rect 9 10 14 14
|
||||||
rect 24 12 29 16
|
rect 28 14 29 18
|
||||||
rect 31 16 32 20
|
rect 24 10 29 14
|
||||||
rect 31 12 36 16
|
rect 31 16 36 18
|
||||||
rect 10 7 14 12
|
rect 31 12 32 16
|
||||||
rect 24 7 28 12
|
rect 31 10 36 12
|
||||||
rect 10 4 14 5
|
rect 10 5 14 10
|
||||||
rect 24 4 28 5
|
rect 24 5 28 10
|
||||||
|
rect 10 2 14 3
|
||||||
|
rect 24 2 28 3
|
||||||
<< pdiffusion >>
|
<< pdiffusion >>
|
||||||
rect 2 42 6 45
|
rect 32 40 36 43
|
||||||
rect 32 42 36 45
|
rect 2 37 7 40
|
||||||
rect 6 39 7 42
|
rect 11 37 12 40
|
||||||
rect 11 39 12 42
|
rect 26 37 27 40
|
||||||
rect 26 39 27 42
|
rect 31 37 32 40
|
||||||
rect 31 39 32 42
|
|
||||||
<< ndcontact >>
|
<< ndcontact >>
|
||||||
rect 2 16 6 20
|
rect -2 12 2 16
|
||||||
rect 10 16 14 20
|
rect 10 14 14 18
|
||||||
rect 24 16 28 20
|
rect 24 14 28 18
|
||||||
rect 32 16 36 20
|
rect 32 12 36 16
|
||||||
rect 10 0 14 4
|
rect 10 -2 14 2
|
||||||
rect 24 0 28 4
|
rect 24 -2 28 2
|
||||||
<< pdcontact >>
|
<< pdcontact >>
|
||||||
rect 2 38 6 42
|
rect -2 36 2 40
|
||||||
rect 12 38 16 42
|
rect 12 36 16 40
|
||||||
rect 22 38 26 42
|
rect 22 36 26 40
|
||||||
rect 32 38 36 42
|
rect 32 36 36 40
|
||||||
<< psubstratepcontact >>
|
<< psubstratepcontact >>
|
||||||
rect 2 23 6 27
|
rect 32 22 36 26
|
||||||
rect 32 23 36 27
|
|
||||||
<< nsubstratencontact >>
|
<< nsubstratencontact >>
|
||||||
rect 0 45 6 49
|
rect 32 43 36 47
|
||||||
rect 32 45 36 49
|
|
||||||
<< polysilicon >>
|
<< polysilicon >>
|
||||||
rect 7 42 11 44
|
rect 7 40 11 42
|
||||||
rect 27 42 31 44
|
rect 27 40 31 42
|
||||||
rect 7 37 11 39
|
rect 7 35 11 37
|
||||||
rect 7 23 9 37
|
rect 7 21 9 35
|
||||||
rect 27 36 31 39
|
rect 27 34 31 37
|
||||||
rect 15 35 31 36
|
rect 15 33 31 34
|
||||||
rect 19 34 31 35
|
rect 19 32 31 33
|
||||||
rect 7 22 21 23
|
rect 7 20 21 21
|
||||||
rect 7 21 24 22
|
rect 7 19 24 20
|
||||||
rect 7 20 9 21
|
rect 7 18 9 19
|
||||||
rect 29 20 31 34
|
rect 29 18 31 32
|
||||||
rect 7 10 9 12
|
rect 7 8 9 10
|
||||||
rect 17 7 21 8
|
rect 17 5 21 6
|
||||||
rect 29 10 31 12
|
rect 29 8 31 10
|
||||||
rect 0 5 10 7
|
rect -2 3 10 5
|
||||||
rect 14 5 24 7
|
rect 14 3 24 5
|
||||||
rect 28 5 36 7
|
rect 28 3 36 5
|
||||||
<< polycontact >>
|
<< polycontact >>
|
||||||
rect 15 31 19 35
|
rect 15 29 19 33
|
||||||
rect 21 22 25 26
|
rect 21 20 25 24
|
||||||
rect 17 8 21 12
|
rect 17 6 21 10
|
||||||
<< metal1 >>
|
<< metal1 >>
|
||||||
rect 6 45 32 49
|
rect -2 43 32 47
|
||||||
rect 2 42 6 45
|
rect -2 40 2 43
|
||||||
rect 32 42 36 45
|
rect 32 40 36 43
|
||||||
rect 11 35 15 38
|
rect -2 18 2 29
|
||||||
rect 6 31 15 35
|
rect 11 18 15 36
|
||||||
rect 2 27 6 31
|
rect 23 24 27 36
|
||||||
rect 2 20 6 23
|
rect 25 20 27 24
|
||||||
rect 11 20 15 31
|
rect 23 18 27 20
|
||||||
rect 23 26 27 38
|
rect 32 26 36 29
|
||||||
rect 25 22 27 26
|
rect -2 16 10 18
|
||||||
rect 23 20 27 22
|
rect 2 14 10 16
|
||||||
rect 32 27 36 31
|
rect 32 16 36 22
|
||||||
rect 32 20 36 23
|
rect -2 6 17 9
|
||||||
rect 2 14 6 16
|
rect 21 6 36 9
|
||||||
rect 0 8 17 11
|
rect -2 5 36 6
|
||||||
rect 21 8 36 11
|
rect 9 -2 10 2
|
||||||
rect 0 7 36 8
|
rect 23 -2 24 2
|
||||||
rect 9 0 10 4
|
|
||||||
rect 23 0 24 4
|
|
||||||
<< m2contact >>
|
<< m2contact >>
|
||||||
rect 2 31 6 35
|
rect -2 29 2 33
|
||||||
rect 32 31 36 35
|
rect 32 29 36 33
|
||||||
rect 5 0 9 4
|
rect 5 -2 9 2
|
||||||
rect 19 0 23 4
|
rect 19 -2 23 2
|
||||||
<< metal2 >>
|
<< metal2 >>
|
||||||
rect 0 35 6 49
|
rect -2 33 2 47
|
||||||
rect 0 31 2 35
|
rect -2 12 2 29
|
||||||
rect 0 14 6 31
|
rect 10 2 14 47
|
||||||
rect 10 4 14 49
|
rect 20 2 24 47
|
||||||
rect 20 4 24 49
|
rect 9 -2 14 2
|
||||||
rect 9 0 14 4
|
rect 23 -2 24 2
|
||||||
rect 23 0 24 4
|
rect 32 33 36 47
|
||||||
rect 32 35 36 49
|
rect 32 -2 36 29
|
||||||
rect 32 0 36 31
|
|
||||||
<< m3p >>
|
<< m3p >>
|
||||||
rect 0 0 34 49
|
rect 0 0 34 45
|
||||||
<< labels >>
|
<< labels >>
|
||||||
rlabel metal2 2 31 2 31 3 gnd
|
rlabel m2contact 20 2 20 2 1 BR
|
||||||
rlabel metal2 32 31 32 31 7 gnd
|
rlabel metal2 10 2 10 2 1 BL
|
||||||
rlabel metal2 10 4 10 4 1 BL
|
rlabel metal1 2 6 2 6 3 WL
|
||||||
rlabel m2contact 20 4 20 4 1 BR
|
rlabel metal2 -1 28 -1 28 1 gnd
|
||||||
rlabel nsubstratencontact 2 45 2 45 4 vdd
|
rlabel metal2 33 28 33 28 1 gnd
|
||||||
rlabel metal1 2 7 2 7 3 WL
|
rlabel metal1 17 45 17 45 5 vdd
|
||||||
<< end >>
|
<< end >>
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ parameter["beta"] = 2
|
||||||
drclvs_home=os.environ.get("DRCLVS_HOME")
|
drclvs_home=os.environ.get("DRCLVS_HOME")
|
||||||
|
|
||||||
drc={}
|
drc={}
|
||||||
#grid size
|
#grid size is 1/2 a lambda
|
||||||
drc["grid"]=0.15
|
drc["grid"]=0.15
|
||||||
#DRC/LVS test set_up
|
#DRC/LVS test set_up
|
||||||
drc["drc_rules"]=drclvs_home+"/calibreDRC_scn3me_subm.rul"
|
drc["drc_rules"]=drclvs_home+"/calibreDRC_scn3me_subm.rul"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue