Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • generator-tools/librepdk
1 result
Show changes
Commits on Source (8)
......@@ -132,7 +132,7 @@ class Config:
return w
def get_layer_id(self, layer):
ret = (0, 0)
ret = None
if hasattr(self.tech_data, "output_map"):
if layer in self.tech_data.output_map:
ret = self.tech_data.output_map[layer]
......
......@@ -12,8 +12,9 @@ class FET(LibrePDKStructure):
LibrePDKStructure.__init__(self, config, name)
self.have_bulk_tap = have_bulk_tap # enable tap for bulk
self.W = dims[0]
self.L = dims[1]
self.N = dims[0]
self.W = dims[1]
self.L = dims[2]
self.conlayer_name = config.get_pad_connection_layer() if contact_to is None else contact_to # Alternative contact layer
......@@ -22,16 +23,19 @@ class FET(LibrePDKStructure):
self.well_layer_name = "nwell"
self.implant_layer_name = 'pdiffusion'
self.diff_contact_name = "pdiff_contact"
self.plus_layer_name = 'pplus'
elif mtype == ChannelType.NMOS:
self.well_layer_name = "pwell"
self.implant_layer_name = 'ndiffusion'
self.diff_contact_name = "ndiff_contact"
self.plus_layer_name = 'nplus'
else:
raise Exception("It has to be either NMOS or PMOS! This should NEVER happen!")
self.implant_layer = config.get_layer_id(self.implant_layer_name)
self.well_layer = config.get_layer_id(self.well_layer_name)
self.pdiff_contact_layer = config.get_layer_id(self.diff_contact_name)
self.plus_layer = config.get_layer_id(self.plus_layer_name)
via_size = self.config.get_via_size(self.diff_contact_name)
# those are LCLayout standard:
......@@ -69,25 +73,27 @@ class FET(LibrePDKStructure):
# adding taps
via_name = self.name+"_TAP"
ws = self.config.get_min_width(self.conlayer_name)
drain_tap = ViaStripe(self.config, via_name+"_drain", self.implant_layer_name, l, ws, self.conlayer_name, less_vias=True) # drain
gate_tap = ViaStripe(self.config, via_name+"_gate", "poly", ws, w, self.conlayer_name, less_vias=True) # gate
source_tap = ViaStripe(self.config, via_name+"_source", self.implant_layer_name, l, ws, self.conlayer_name, less_vias=True) # source
drain_source_tap = ViaStripe(self.config, via_name+"_ds", self.implant_layer_name, l, ws, self.conlayer_name, less_vias=True) # drain/source
hp = w*self.N
if self.N > 1:
hp += self.N*ws
gate_tap = ViaStripe(self.config, via_name+"_gate", "poly", ws, hp, self.conlayer_name, less_vias=True) # gate
# determine implant width/height
wi = lph.to_nm(self.config, l)
hi = lph.to_nm(self.config, w if sp < w else sp)
# determine gate width/height
wp = drain_tap.xsize+lph.to_nm(self.config, sp)
wp = drain_source_tap.xsize+lph.to_nm(self.config, sp)
hp = lph.to_nm(self.config, w)
# implant and taps
implant = gf.components.rectangle(size=(wi,hi), layer=self.implant_layer)
gate = gf.components.rectangle(size=(wp,hp), layer=self.gate_layer)
gate = gf.components.rectangle(size=(wp+2*gate_tap.xsize,hp), layer=self.gate_layer)
# determine well width/height
ww = gate_tap.xsize+wp+lph.to_nm(self.config, 2*me)
hw = drain_tap.ysize+source_tap.ysize+hi+lph.to_nm(self.config, 2*me)
hw = drain_source_tap.ysize+(drain_source_tap.ysize+hi)*self.N+lph.to_nm(self.config, 2*me)
dy = mef+spf
# place the bulk tap
if self.have_bulk_tap:
......@@ -102,14 +108,30 @@ class FET(LibrePDKStructure):
well = gf.components.rectangle(size=(ww,hw), layer=self.well_layer)
self << well
self.add_pin(2, self << source_tap.move([mef, dy]))
if self.plus_layer is not None:
# Add the nplus/pplus
plus_size=gate_tap.xsize # This is wrong and needs to be calculated properly
plus = gf.components.rectangle(size=(ww+2*plus_size,hw+2*plus_size), layer=self.plus_layer)
self << plus.move([-plus_size,-plus_size])
if self.N > 1:
tap = gf.components.pad(size=s, layer=lid)
self.add_pin(2, self << tap)
tap = gf.components.pad(size=s, layer=lid)
self.add_pin(3, self << tap)
else:
self.add_pin(2, self << drain_source_tap.move([mef, dy]))
dy += drain_source_tap.ysize
self << implant.move([drain_source_tap.xsize-implant.xsize+mef, dy])
dy += source_tap.ysize
self << implant.move([drain_tap.xsize-implant.xsize+mef, dy])
gy = dy+(implant.ysize-hp)/2
gy = dy+(implant.ysize-gate.ysize)/2
self << gate.move([mef,gy])
self.add_pin(1, self << gate_tap.move([mef+gate.xsize,gy]))
self.add_pin(1, self << gate_tap.move([mef+wp,gy]))
for i in range(self.N):
self << gate.move([mef-gate_tap.xsize,gy])
gy+=hp+drain_source_tap.ysize
dy += implant.ysize
self.add_pin(3, self << drain_tap.move([mef, dy]))
if self.N == 1:
dy += implant.ysize
self.add_pin(3, self << drain_source_tap.move([mef, dy]))
......@@ -40,7 +40,7 @@ class StripResistor(LibrePDKStructure):
ps = self.config.get_min_width(self.layer) if self.layer == self.contact_to else get_min_viagroup_pad_size(self.config, self.layer, self.contact_to)
pad = ViaStripe(self.config, self.name+"_CONTACT", self.layer, ps, self.width, self.contact_to, less_vias=True)
mx = pad.xsize
my = (pad.ysize-r.ysize)/2
my = lph.value_to_grid(self.config, (pad.ysize-r.ysize)/2)
py = pad.ysize
x2 = pad.xsize+r.xsize
ret << r.move([mx,my])
......
......@@ -222,7 +222,8 @@ min_spacing = {
(l_metal2, l_metal2): 280*nm, # Mn.2a
(l_metal3, l_metal3): 280*nm, # Mn.2a
(l_metal4, l_metal4): 280*nm, # Mn.2a
(l_metal5, l_metal5): 280*nm, # Mn.2a
#(l_metal5, l_metal5): 280*nm, # Mn.2a
(l_metal5, l_metal5): 460*nm, # MT.2a
# We need metal2 at the border for the power lanes, so we dont put border rules
(l_via1, l_via1): 260*nm, # Vn.2a
......@@ -332,7 +333,7 @@ minimum_width = {
l_metal2: 280*nm, # Mn.1
l_metal3: 280*nm, # Mn.1
l_metal4: 280*nm, # Mn.1
l_metal5: 280*nm, # Mn.1
l_metal5: 460*nm, # Mn.1
l_nwell: 860*nm, # NW.1a
l_pwell: 740*nm, # LPW.1
l_nplus: 400*nm # NP.1
......@@ -352,8 +353,8 @@ minimum_enclosure = {
(l_metal2, l_via1): 60*nm, # Vn.4
# l_*well must overlap l_*diffusion
(l_nwell, l_pdiffusion): 180*nm, # (difftap.8) # This causes notches, I am trying to get rid of them
(l_pwell, l_ndiffusion): 180*nm, # (difftap.8)
(l_nwell, l_pdiffusion): 430*nm, # DF.4c
(l_pwell, l_ndiffusion): 430*nm, # DF.4c
(l_abutment_box, l_nwell): 0, # The nwell and pwell should not go beyond the abutment
(l_abutment_box, l_pwell): 0,
(l_nplus, l_ndiff_contact): 230*nm, # NP.5a Implicitly encodes the size of well taps.
......