diff --git a/compiler/bitcell_array.py b/compiler/bitcell_array.py index 4e1abb0f..10bbf78a 100644 --- a/compiler/bitcell_array.py +++ b/compiler/bitcell_array.py @@ -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(), diff --git a/compiler/design.py b/compiler/design.py index bed5de15..f32807d2 100644 --- a/compiler/design.py +++ b/compiler/design.py @@ -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 diff --git a/compiler/hierarchy_layout.py b/compiler/hierarchy_layout.py index a3663481..1c136dd9 100644 --- a/compiler/hierarchy_layout.py +++ b/compiler/hierarchy_layout.py @@ -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 diff --git a/compiler/pgate.py b/compiler/pgate.py index d636d429..0a258048 100644 --- a/compiler/pgate.py +++ b/compiler/pgate.py @@ -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, diff --git a/compiler/pinv.py b/compiler/pinv.py index fbf18e2c..8bcd7841 100644 --- a/compiler/pinv.py +++ b/compiler/pinv.py @@ -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 diff --git a/compiler/pnand2.py b/compiler/pnand2.py index 1ed44890..df3ceca7 100644 --- a/compiler/pnand2.py +++ b/compiler/pnand2.py @@ -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 """ diff --git a/compiler/pnand3.py b/compiler/pnand3.py index e08fd94d..0c7b2072 100644 --- a/compiler/pnand3.py +++ b/compiler/pnand3.py @@ -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 """ diff --git a/compiler/pnor2.py b/compiler/pnor2.py index b24cca47..684a2b51 100644 --- a/compiler/pnor2.py +++ b/compiler/pnor2.py @@ -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 """ diff --git a/compiler/ptx.py b/compiler/ptx.py index 77bc5041..7cb89474 100644 --- a/compiler/ptx.py +++ b/compiler/ptx.py @@ -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) diff --git a/compiler/verify/magic.py b/compiler/verify/magic.py index 54071b4f..aec94566 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -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, diff --git a/compiler/wordline_driver.py b/compiler/wordline_driver.py index 853c6b89..95896177 100644 --- a/compiler/wordline_driver.py +++ b/compiler/wordline_driver.py @@ -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() diff --git a/docs/openram_manual.pdf b/docs/openram_manual.pdf index 2470032e..18521195 100644 Binary files a/docs/openram_manual.pdf and b/docs/openram_manual.pdf differ diff --git a/technology/scn3me_subm/gds_lib/cell_6t.gds b/technology/scn3me_subm/gds_lib/cell_6t.gds index ed612df4..7433d63f 100644 Binary files a/technology/scn3me_subm/gds_lib/cell_6t.gds and b/technology/scn3me_subm/gds_lib/cell_6t.gds differ diff --git a/technology/scn3me_subm/gds_lib/replica_cell_6t.gds b/technology/scn3me_subm/gds_lib/replica_cell_6t.gds index e611851a..fbe8a28a 100644 Binary files a/technology/scn3me_subm/gds_lib/replica_cell_6t.gds and b/technology/scn3me_subm/gds_lib/replica_cell_6t.gds differ diff --git a/technology/scn3me_subm/mag_lib/cell_6t.mag b/technology/scn3me_subm/mag_lib/cell_6t.mag index cdd4a0fb..57fd0cb8 100644 --- a/technology/scn3me_subm/mag_lib/cell_6t.mag +++ b/technology/scn3me_subm/mag_lib/cell_6t.mag @@ -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 >> diff --git a/technology/scn3me_subm/mag_lib/replica_cell_6t.mag b/technology/scn3me_subm/mag_lib/replica_cell_6t.mag index a6cc4fd7..573dc5f0 100644 --- a/technology/scn3me_subm/mag_lib/replica_cell_6t.mag +++ b/technology/scn3me_subm/mag_lib/replica_cell_6t.mag @@ -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 >> diff --git a/technology/scn3me_subm/tech/tech.py b/technology/scn3me_subm/tech/tech.py index 0a0909c8..b797b81b 100755 --- a/technology/scn3me_subm/tech/tech.py +++ b/technology/scn3me_subm/tech/tech.py @@ -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"