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:
Matt Guthaus 2018-01-26 12:39:00 -08:00
parent fb0355ebaf
commit 1dc7752429
17 changed files with 315 additions and 299 deletions

View File

@ -115,8 +115,8 @@ class bitcell_array(design.design):
gnd_pins = self.cell_inst[0,col].get_pins("gnd")
for gnd_pin in gnd_pins:
# avoid duplicates by only doing even rows
# also skip if it is not the full height (a through rail)
if gnd_pin.layer=="metal2" and col%2 == 0 and gnd_pin.height()>=self.cell.height:
# 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.by()==lower_y:
self.add_layout_pin(text="gnd",
layer="metal2",
offset=gnd_pin.ll(),

View File

@ -27,8 +27,13 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout):
# Check if the name already exists, if so, give an error
# because each reference must be a unique name.
ok_list = ['ms_flop.ms_flop', 'bitcell.bitcell', 'contact.contact',
'ptx.ptx', 'sram.sram',
# These modules ensure unique names or have no changes if they
# aren't unique
ok_list = ['ms_flop.ms_flop',
'bitcell.bitcell',
'contact.contact',
'ptx.ptx',
'sram.sram',
'hierarchical_predecode2x4.hierarchical_predecode2x4',
'hierarchical_predecode3x8.hierarchical_predecode3x8']
if name not in design.name_map:
@ -41,6 +46,7 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout):
def setup_drc_constants(self):
""" These are some DRC constants used in many places in the compiler."""
from tech import drc
self.well_width = drc["minwidth_well"]
self.poly_width = drc["minwidth_poly"]
self.poly_space = drc["poly_to_poly"]
self.m1_width = drc["minwidth_metal1"]
@ -49,7 +55,16 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout):
self.m2_space = drc["metal2_to_metal2"]
self.m3_width = drc["minwidth_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):
""" Return a map of pin locations of the instance offset """
# find the instance

View File

@ -336,14 +336,14 @@ class layout(lef.lef):
implant_type=implant_type,
well_type=well_type)
self.add_mod(via)
self.add_inst(name=via.name,
mod=via,
offset=offset,
mirror=mirror,
rotate=rotate)
inst=self.add_inst(name=via.name,
mod=via,
offset=offset,
mirror=mirror,
rotate=rotate)
# We don't model the logical connectivity of wires/paths
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):
""" 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_inst(name=via.name,
mod=via,
offset=corrected_offset,
mirror=mirror,
rotate=rotate)
inst=self.add_inst(name=via.name,
mod=via,
offset=corrected_offset,
mirror=mirror,
rotate=rotate)
# We don't model the logical connectivity of wires/paths
self.connect_inst([])
return via
return inst
def add_ptx(self, offset, mirror="R0", rotate=0, width=1, mults=1, tx_type="nmos"):
"""Adds a ptx module to the design."""
@ -387,12 +387,12 @@ class layout(lef.lef):
mults=mults,
tx_type=tx_type)
self.add_mod(mos)
self.add_inst(name=mos.name,
mod=mos,
offset=offset,
mirror=mirror,
rotate=rotate)
return mos
inst=self.add_inst(name=mos.name,
mod=mos,
offset=offset,
mirror=mirror,
rotate=rotate)
return inst

View File

@ -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.")
# 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)
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 """
# 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
nwell_height = self.max_y_offset - middle_position.y
nwell_height = max_y_offset - middle_position.y
if info["has_nwell"]:
self.add_rect(layer="nwell",
offset=middle_position,
@ -111,15 +111,15 @@ class pgate(design.design):
width=self.well_width,
height=nwell_height)
self.pwell_position = vector(0,-0.5*drc["minwidth_metal1"])
pwell_height = middle_position.y-self.pwell_position.y
pwell_position = vector(0,-0.5*self.m1_width)
pwell_height = middle_position.y-pwell_position.y
if info["has_pwell"]:
self.add_rect(layer="pwell",
offset=self.pwell_position,
offset=pwell_position,
width=self.well_width,
height=pwell_height)
self.add_rect(layer="vtg",
offset=self.pwell_position,
offset=pwell_position,
width=self.well_width,
height=pwell_height)
@ -132,8 +132,9 @@ class pgate(design.design):
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
# 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,
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)
# Offset by half a contact in x and y
contact_offset += vector(0.5*pmos.active_contact.first_layer_width,
@ -144,11 +145,11 @@ class pgate(design.design):
well_type="n")
self.add_rect_center(layer="metal1",
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)
# 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
# self.add_rect(layer="active",
# offset=active_offset,
@ -156,27 +157,29 @@ class pgate(design.design):
# height=pmos.active_height)
# 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_offset = active_offset + vector(implant_spacing,0) - vector(0,drc["implant_enclosure_active"])
implant_width = pmos.active_contact.width + 2*drc["implant_enclosure_active"]
implant_height = pmos.active_height + 2*drc["implant_enclosure_active"]
# implant_spacing = self.implant_space+self.implant_enclose_active
# implant_offset = active_offset + vector(implant_spacing,0) - vector(0,self.implant_enclose_active)
# implant_width = pmos.active_contact.width + 2*self.implant_enclose_active
# implant_height = pmos.active_height + 2*self.implant_enclose_active
# self.add_rect(layer="nimplant",
# offset=implant_offset,
# width=implant_width,
# height=implant_height)
# Return the top of the well
def add_pwell_contact(self, nmos, nmos_pos):
""" Add an pwell contact next to the given nmos device. """
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
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
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)
# Offset by half a contact
@ -188,21 +191,21 @@ class pgate(design.design):
well_type="p")
self.add_rect_center(layer="metal1",
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)
# 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
# self.add_rect(layer="active",
# offset=active_offset,
# width=nmos.active_contact.width,
# height=nmos.active_height)
implant_spacing = drc["implant_to_implant"]+drc["implant_enclosure_active"]
implant_offset = active_offset + vector(implant_spacing,0) - vector(0,drc["implant_enclosure_active"])
implant_width = nmos.active_contact.width + 2*drc["implant_enclosure_active"]
implant_height = nmos.active_height + 2*drc["implant_enclosure_active"]
# implant_spacing = self.implant_space+self.implant_enclose_active
# implant_offset = active_offset + vector(implant_spacing,0) - vector(0,self.implant_enclose_active)
# implant_width = nmos.active_contact.width + 2*self.implant_enclose_active
# implant_height = nmos.active_height + 2*self.implant_enclose_active
# self.add_rect(layer="pimplant",
# offset=implant_offset,
# width=implant_width,

View File

@ -57,8 +57,8 @@ class pinv(pgate.pgate):
self.setup_layout_constants()
self.add_supply_rails()
self.add_ptx()
self.extend_wells(self.well_pos)
self.add_well_contacts()
self.extend_wells(self.well_pos)
self.connect_rails()
self.route_input_gate(self.pmos_inst, self.nmos_inst, self.output_pos.y, "A", rotate=0)
self.route_outputs()
@ -128,9 +128,6 @@ class pinv(pgate.pgate):
self.width = self.well_width
# 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):
@ -183,9 +180,14 @@ class pinv(pgate.pgate):
self.connect_inst(["Z", "A", "gnd", "gnd"])
# Output position will be in between the PMOS and NMOS
self.output_pos = vector(0,0.5*(self.pmos_pos.y+self.nmos_pos.y+self.nmos.active_height))
# Output position will be in between the PMOS and NMOS drains
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())
def route_outputs(self):
@ -196,8 +198,8 @@ class pinv(pgate.pgate):
pmos_drain_pin = self.pmos_inst.get_pin("D")
# 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)
pmos_drain_pos = vector(nmos_drain_pos.x,pmos_drain_pin.bc().y)
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)
self.add_path("metal1",[nmos_drain_pos,pmos_drain_pos])
# Remember the mid for the output

View File

@ -51,8 +51,8 @@ class pnand2(pgate.pgate):
self.add_supply_rails()
self.add_ptx()
self.connect_rails()
self.extend_wells(self.well_pos)
self.add_well_contacts()
self.extend_wells(self.well_pos)
self.route_inputs()
self.route_output()
@ -94,9 +94,6 @@ class pnand2(pgate.pgate):
self.width = self.well_width
# 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
extra_contact_space = max(-self.nmos.get_pin("D").by(),0)
# 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
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):
""" Add n/p well taps to the layout and connect to supplies AFTER the wells are created """

View File

@ -51,8 +51,8 @@ class pnand3(pgate.pgate):
self.add_supply_rails()
self.add_ptx()
self.connect_rails()
self.extend_wells(self.well_pos)
self.add_well_contacts()
self.extend_wells(self.well_pos)
self.route_inputs()
self.route_output()
@ -88,7 +88,6 @@ class pnand3(pgate.pgate):
# This will help with the wells and the input/output placement
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 extra liberal for pnand3 because we know there are big transistor sizes
@ -153,6 +152,8 @@ class pnand3(pgate.pgate):
offset=self.nmos3_pos)
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):
""" Add n/p well taps to the layout and connect to supplies """

View File

@ -52,8 +52,8 @@ class pnor2(pgate.pgate):
self.add_supply_rails()
self.add_ptx()
self.connect_rails()
self.extend_wells(self.well_pos)
self.add_well_contacts()
self.extend_wells(self.well_pos)
self.route_inputs()
self.route_output()
@ -98,9 +98,6 @@ class pnor2(pgate.pgate):
self.width = self.well_width
# 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
extra_contact_space = max(-self.nmos.get_pin("D").by(),0)
# 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
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):
""" Add n/p well taps to the layout and connect to supplies """

View File

@ -94,25 +94,19 @@ class ptx(design.design):
self.active_contact = contact(layer_stack=("active", "contact", "metal1"),
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)
self.poly_pitch = max(2*drc["contact_to_gate"] + self.contact_width + self.poly_width,
drc["poly_to_poly"])
self.poly_pitch = max(2*self.contact_to_gate + self.contact_width + self.poly_width,
self.poly_space)
# 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.
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
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,
@ -125,22 +119,25 @@ class ptx(design.design):
# Poly height must include poly extension over 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
if info["has_{}well".format(self.well_type)]:
self.well_width = max(self.active_width + 2*drc["well_enclosure_active"],
drc["minwidth_well"])
self.well_height = max(self.tx_width + 2*drc["well_enclosure_active"],
drc["minwidth_well"])
self.height = self.well_height
self.width = self.well_width
self.cell_well_width = max(self.active_width + 2*self.well_enclose_active,
self.well_width)
self.cell_well_height = max(self.tx_width + 2*self.well_enclose_active,
self.well_width)
# We are going to shift the 0,0, so include that in the width and height
self.height = self.cell_well_height - self.active_offset.y
self.width = self.cell_well_width - self.active_offset.x
else:
# If no well, use the boundary of the active and poly
self.height = self.poly_height
self.width = self.active_width
# 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)
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
# of the contacts to avoid DRC violations to the other contacts
pin_offset = vector(0, 0.5*self.active_contact.second_layer_height \
+ drc["metal1_to_metal1"] + 0.5*drc["minwidth_metal1"])
# This is the width of a contact to extend the ends of the pin
end_offset = vector(self.active_contact.second_layer_width/2,0)
+ self.m1_space + 0.5*self.m1_width)
# This is the width of a m1 extend the ends of the pin
end_offset = vector(self.m1_width/2,0)
# 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.
@ -280,12 +277,12 @@ class ptx(design.design):
if info["has_{}well".format(self.well_type)]:
self.add_rect(layer="{}well".format(self.well_type),
offset=(0,0),
width=self.well_width,
height=self.well_height)
width=self.cell_well_width,
height=self.cell_well_height)
self.add_rect(layer="vtg",
offset=(0,0),
width=self.well_width,
height=self.well_height)
width=self.cell_well_width,
height=self.cell_well_height)
def calculate_num_contacts(self):
@ -331,8 +328,8 @@ class ptx(design.design):
self.add_layout_pin_center_rect(text="S",
layer="metal1",
offset=pos,
width=contact.second_layer_width,
height=contact.second_layer_height)
width=contact.mod.second_layer_width,
height=contact.mod.second_layer_height)
for pos in drain_positions:
@ -344,8 +341,8 @@ class ptx(design.design):
self.add_layout_pin_center_rect(text="D",
layer="metal1",
offset=pos,
width=contact.second_layer_width,
height=contact.second_layer_height)
width=contact.mod.second_layer_width,
height=contact.mod.second_layer_height)
if self.connect_active:
self.connect_fingered_active(drain_positions, source_positions)

View File

@ -12,12 +12,13 @@ ln -s 2001a current
#!/bin/sh
magic -dnull -noconsole << EOF
tech load SCN3ME_SUBM.30
gds rescale false
scalegrid 1 2
gds rescale no
gds polygon subcell true
gds warning default
gds read $1
load $1
save $1
writeall force
drc count
drc why
quit -noprompt
@ -29,7 +30,8 @@ rm -f $1.ext
rm -f $1.spice
magic -dnull -noconsole << EOF
tech load SCN3ME_SUBM.30
gds rescale false
scalegrid 1 2
gds rescale no
gds polygon subcell true
gds warning default
gds read $1
@ -72,12 +74,13 @@ def write_magic_script(cell_name, gds_name, extract=False):
f.write("#!/bin/sh\n")
f.write("{} -dnull -noconsole << EOF\n".format(OPTS.drc_exe[1]))
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 warning default\n")
f.write("gds read {}\n".format(gds_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 catchup\n")
f.write("drc count total\n")
@ -123,6 +126,12 @@ def write_netgen_script(cell_name, sp_name):
cell_name))
f.write("property {{{0}{1}.spice pfet}} remove as ad ps pd\n".format(OPTS.openram_temp,
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("log start\n")
f.write("compare hierarchical {0}{1}.spice {{{2} {1}}}\n".format(OPTS.openram_temp,

View File

@ -149,8 +149,8 @@ class wordline_driver(design.design):
self.add_segment_center(layer="metal1",
start=clk_offset,
end=a_pos)
m1m2_via = self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=clk_offset)
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=clk_offset)
# first inv to nand2 A
zb_pos = inv1_inst.get_pin("Z").bc()

Binary file not shown.

View File

@ -1,119 +1,114 @@
magic
tech scmos
timestamp 1516665972
timestamp 1516839303
<< nwell >>
rect -5 31 42 52
rect -8 29 42 50
<< pwell >>
rect -5 -6 42 31
rect -8 -8 42 29
<< ntransistor >>
rect 7 12 9 20
rect 29 12 31 20
rect 10 5 14 7
rect 24 5 28 7
rect 7 10 9 18
rect 29 10 31 18
rect 10 3 14 5
rect 24 3 28 5
<< ptransistor >>
rect 7 39 11 42
rect 27 39 31 42
rect 7 37 11 40
rect 27 37 31 40
<< ndiffusion >>
rect 2 20 6 23
rect 32 20 36 23
rect 6 16 7 20
rect -2 16 7 18
rect 2 12 7 16
rect 9 16 10 20
rect 9 12 14 16
rect 28 16 29 20
rect 24 12 29 16
rect 31 16 32 20
rect 31 12 36 16
rect 10 7 14 12
rect 24 7 28 12
rect 10 4 14 5
rect 24 4 28 5
rect -2 10 7 12
rect 9 14 10 18
rect 9 10 14 14
rect 28 14 29 18
rect 24 10 29 14
rect 31 16 36 18
rect 31 12 32 16
rect 31 10 36 12
rect 10 5 14 10
rect 24 5 28 10
rect 10 2 14 3
rect 24 2 28 3
<< pdiffusion >>
rect 2 42 6 45
rect 32 42 36 45
rect 6 39 7 42
rect 11 39 12 42
rect 26 39 27 42
rect 31 39 32 42
rect 32 40 36 43
rect 2 37 7 40
rect 11 37 12 40
rect 26 37 27 40
rect 31 37 32 40
<< ndcontact >>
rect 2 16 6 20
rect 10 16 14 20
rect 24 16 28 20
rect 32 16 36 20
rect 10 0 14 4
rect 24 0 28 4
rect -2 12 2 16
rect 10 14 14 18
rect 24 14 28 18
rect 32 12 36 16
rect 10 -2 14 2
rect 24 -2 28 2
<< pdcontact >>
rect 2 38 6 42
rect 12 38 16 42
rect 22 38 26 42
rect 32 38 36 42
rect -2 36 2 40
rect 12 36 16 40
rect 22 36 26 40
rect 32 36 36 40
<< psubstratepcontact >>
rect 2 23 6 27
rect 32 23 36 27
rect 32 22 36 26
<< nsubstratencontact >>
rect 0 45 6 49
rect 32 45 36 49
rect 32 43 36 47
<< polysilicon >>
rect 7 42 11 44
rect 27 42 31 44
rect 7 37 11 39
rect 7 23 9 37
rect 27 36 31 39
rect 15 35 31 36
rect 19 34 31 35
rect 7 22 21 23
rect 7 21 24 22
rect 7 20 9 21
rect 29 20 31 34
rect 7 10 9 12
rect 17 7 21 8
rect 29 10 31 12
rect 0 5 10 7
rect 14 5 24 7
rect 28 5 36 7
rect 7 40 11 42
rect 27 40 31 42
rect 7 35 11 37
rect 7 21 9 35
rect 27 34 31 37
rect 15 33 31 34
rect 19 32 31 33
rect 7 20 21 21
rect 7 19 24 20
rect 7 18 9 19
rect 29 18 31 32
rect 7 8 9 10
rect 17 5 21 6
rect 29 8 31 10
rect -2 3 10 5
rect 14 3 24 5
rect 28 3 36 5
<< polycontact >>
rect 15 31 19 35
rect 21 22 25 26
rect 17 8 21 12
rect 15 29 19 33
rect 21 20 25 24
rect 17 6 21 10
<< metal1 >>
rect 6 45 32 49
rect 2 42 6 45
rect 32 42 36 45
rect 2 27 6 31
rect 2 20 6 23
rect 11 20 15 38
rect 23 26 27 38
rect 25 22 27 26
rect 23 20 27 22
rect 32 27 36 31
rect 32 20 36 23
rect 0 8 17 11
rect 21 8 36 11
rect 0 7 36 8
rect 9 0 10 4
rect 23 0 24 4
rect -2 43 32 47
rect -2 40 2 43
rect 32 40 36 43
rect -2 16 2 29
rect 11 18 15 36
rect 23 24 27 36
rect 25 20 27 24
rect 23 18 27 20
rect 32 26 36 29
rect 32 16 36 22
rect -2 6 17 9
rect 21 6 36 9
rect -2 5 36 6
rect 9 -2 10 2
rect 23 -2 24 2
<< m2contact >>
rect 2 31 6 35
rect 32 31 36 35
rect 5 0 9 4
rect 19 0 23 4
rect -2 29 2 33
rect 32 29 36 33
rect 5 -2 9 2
rect 19 -2 23 2
<< metal2 >>
rect 0 35 6 49
rect 0 31 2 35
rect 0 14 6 31
rect 10 4 14 49
rect 20 4 24 49
rect 9 0 14 4
rect 23 0 24 4
rect 32 35 36 49
rect 32 0 36 31
rect -2 33 2 47
rect -2 12 2 29
rect 10 2 14 47
rect 20 2 24 47
rect 9 -2 14 2
rect 23 -2 24 2
rect 32 33 36 47
rect 32 -2 36 29
<< m3p >>
rect 0 0 34 49
rect 0 0 34 45
<< labels >>
rlabel m2contact 20 4 20 4 1 BR
rlabel metal2 10 4 10 4 1 BL
rlabel metal2 32 31 32 31 7 gnd
rlabel metal1 32 45 32 45 4 vdd
rlabel metal2 2 31 2 31 3 gnd
rlabel metal1 2 8 2 8 3 WL
rlabel m2contact 20 2 20 2 1 BR
rlabel metal2 10 2 10 2 1 BL
rlabel metal1 2 6 2 6 3 WL
rlabel metal2 -1 28 -1 28 1 gnd
rlabel metal2 33 28 33 28 1 gnd
rlabel metal1 17 45 17 45 5 vdd
<< end >>

View File

@ -1,122 +1,116 @@
magic
tech scmos
timestamp 1516666672
timestamp 1516980606
<< nwell >>
rect -4 31 42 53
rect -8 29 42 50
<< pwell >>
rect -4 -6 42 31
rect -8 -8 42 29
<< ntransistor >>
rect 7 12 9 20
rect 29 12 31 20
rect 10 5 14 7
rect 24 5 28 7
rect 7 10 9 18
rect 29 10 31 18
rect 10 3 14 5
rect 24 3 28 5
<< ptransistor >>
rect 7 39 11 42
rect 27 39 31 42
rect 7 37 11 40
rect 27 37 31 40
<< ndiffusion >>
rect 2 20 6 23
rect 32 20 36 23
rect 6 16 7 20
rect -2 16 7 18
rect 2 12 7 16
rect 9 16 10 20
rect 9 12 14 16
rect 28 16 29 20
rect 24 12 29 16
rect 31 16 32 20
rect 31 12 36 16
rect 10 7 14 12
rect 24 7 28 12
rect 10 4 14 5
rect 24 4 28 5
rect -2 10 7 12
rect 9 14 10 18
rect 9 10 14 14
rect 28 14 29 18
rect 24 10 29 14
rect 31 16 36 18
rect 31 12 32 16
rect 31 10 36 12
rect 10 5 14 10
rect 24 5 28 10
rect 10 2 14 3
rect 24 2 28 3
<< pdiffusion >>
rect 2 42 6 45
rect 32 42 36 45
rect 6 39 7 42
rect 11 39 12 42
rect 26 39 27 42
rect 31 39 32 42
rect 32 40 36 43
rect 2 37 7 40
rect 11 37 12 40
rect 26 37 27 40
rect 31 37 32 40
<< ndcontact >>
rect 2 16 6 20
rect 10 16 14 20
rect 24 16 28 20
rect 32 16 36 20
rect 10 0 14 4
rect 24 0 28 4
rect -2 12 2 16
rect 10 14 14 18
rect 24 14 28 18
rect 32 12 36 16
rect 10 -2 14 2
rect 24 -2 28 2
<< pdcontact >>
rect 2 38 6 42
rect 12 38 16 42
rect 22 38 26 42
rect 32 38 36 42
rect -2 36 2 40
rect 12 36 16 40
rect 22 36 26 40
rect 32 36 36 40
<< psubstratepcontact >>
rect 2 23 6 27
rect 32 23 36 27
rect 32 22 36 26
<< nsubstratencontact >>
rect 0 45 6 49
rect 32 45 36 49
rect 32 43 36 47
<< polysilicon >>
rect 7 42 11 44
rect 27 42 31 44
rect 7 37 11 39
rect 7 23 9 37
rect 27 36 31 39
rect 15 35 31 36
rect 19 34 31 35
rect 7 22 21 23
rect 7 21 24 22
rect 7 20 9 21
rect 29 20 31 34
rect 7 10 9 12
rect 17 7 21 8
rect 29 10 31 12
rect 0 5 10 7
rect 14 5 24 7
rect 28 5 36 7
rect 7 40 11 42
rect 27 40 31 42
rect 7 35 11 37
rect 7 21 9 35
rect 27 34 31 37
rect 15 33 31 34
rect 19 32 31 33
rect 7 20 21 21
rect 7 19 24 20
rect 7 18 9 19
rect 29 18 31 32
rect 7 8 9 10
rect 17 5 21 6
rect 29 8 31 10
rect -2 3 10 5
rect 14 3 24 5
rect 28 3 36 5
<< polycontact >>
rect 15 31 19 35
rect 21 22 25 26
rect 17 8 21 12
rect 15 29 19 33
rect 21 20 25 24
rect 17 6 21 10
<< metal1 >>
rect 6 45 32 49
rect 2 42 6 45
rect 32 42 36 45
rect 11 35 15 38
rect 6 31 15 35
rect 2 27 6 31
rect 2 20 6 23
rect 11 20 15 31
rect 23 26 27 38
rect 25 22 27 26
rect 23 20 27 22
rect 32 27 36 31
rect 32 20 36 23
rect 2 14 6 16
rect 0 8 17 11
rect 21 8 36 11
rect 0 7 36 8
rect 9 0 10 4
rect 23 0 24 4
rect -2 43 32 47
rect -2 40 2 43
rect 32 40 36 43
rect -2 18 2 29
rect 11 18 15 36
rect 23 24 27 36
rect 25 20 27 24
rect 23 18 27 20
rect 32 26 36 29
rect -2 16 10 18
rect 2 14 10 16
rect 32 16 36 22
rect -2 6 17 9
rect 21 6 36 9
rect -2 5 36 6
rect 9 -2 10 2
rect 23 -2 24 2
<< m2contact >>
rect 2 31 6 35
rect 32 31 36 35
rect 5 0 9 4
rect 19 0 23 4
rect -2 29 2 33
rect 32 29 36 33
rect 5 -2 9 2
rect 19 -2 23 2
<< metal2 >>
rect 0 35 6 49
rect 0 31 2 35
rect 0 14 6 31
rect 10 4 14 49
rect 20 4 24 49
rect 9 0 14 4
rect 23 0 24 4
rect 32 35 36 49
rect 32 0 36 31
rect -2 33 2 47
rect -2 12 2 29
rect 10 2 14 47
rect 20 2 24 47
rect 9 -2 14 2
rect 23 -2 24 2
rect 32 33 36 47
rect 32 -2 36 29
<< m3p >>
rect 0 0 34 49
rect 0 0 34 45
<< labels >>
rlabel metal2 2 31 2 31 3 gnd
rlabel metal2 32 31 32 31 7 gnd
rlabel metal2 10 4 10 4 1 BL
rlabel m2contact 20 4 20 4 1 BR
rlabel nsubstratencontact 2 45 2 45 4 vdd
rlabel metal1 2 7 2 7 3 WL
rlabel m2contact 20 2 20 2 1 BR
rlabel metal2 10 2 10 2 1 BL
rlabel metal1 2 6 2 6 3 WL
rlabel metal2 -1 28 -1 28 1 gnd
rlabel metal2 33 28 33 28 1 gnd
rlabel metal1 17 45 17 45 5 vdd
<< end >>

View File

@ -58,7 +58,7 @@ parameter["beta"] = 2
drclvs_home=os.environ.get("DRCLVS_HOME")
drc={}
#grid size
#grid size is 1/2 a lambda
drc["grid"]=0.15
#DRC/LVS test set_up
drc["drc_rules"]=drclvs_home+"/calibreDRC_scn3me_subm.rul"