def test_via_multi_terminal_open(): c = Canvas() c.addGen(Wire(nm='m1', layer='M1', direction='v', clg=None, spg=None)) c.addGen(Wire(nm='m2', layer='M2', direction='h', clg=None, spg=None)) c.addGen(Via(nm="v1", layer="via1", h_clg=None, v_clg=None)) c.terminals = [{ 'layer': 'M2', 'netName': None, 'rect': [0, -50, 300, 50] }, { 'layer': 'M1', 'netName': 'M1:S', 'rect': [100, -150, 200, 150] }, { 'layer': 'M1', 'netName': 'M1:D', 'rect': [0, -150, 50, 150] }, { 'layer': 'via1', 'netName': None, 'rect': [100, -50, 200, 50] }, { 'layer': 'via1', 'netName': None, 'rect': [0, -50, 50, 50] }] c.removeDuplicates() assert len(c.rd.shorts) == 0 assert len(c.rd.opens) == 2 assert len(c.rd.subinsts) == 1 assert len(c.rd.subinsts['M1']) == 2
def setup(): p = Pdk().load('../PDK_Abstraction/FinFET14nm_Mock_PDK/FinFET_Mock_PDK_Abstraction.json') c = Canvas(p) c.addGen( Wire( nm='m1', layer='M1', direction='v', clg=None, spg=None)) c.addGen( Wire( nm='m2', layer='M2', direction='h', clg=None, spg=None)) c.addGen( Via( nm="v1", layer="V1", h_clg=None, v_clg=None)) return c
def test_m2_and_m3(): c = Canvas() m1 = c.addGen( Wire( nm='m1', layer='M1', direction='v', clg=UncoloredCenterLineGrid( width=400, pitch=720, repeat=2), spg=EnclosureGrid( pitch=720, stoppoint=360))) m2 = c.addGen( Wire( nm='m2', layer='M2', direction='h', clg=UncoloredCenterLineGrid( width=400, pitch=720, repeat=5), spg=EnclosureGrid( pitch=720, stoppoint=360))) m3 = c.addGen( Wire( nm='m3', layer='M3', direction='v', clg=UncoloredCenterLineGrid( width=400, pitch=720, repeat=2), spg=EnclosureGrid( pitch=720, stoppoint=360))) v1 = c.addGen( Via( nm='v1', layer='via1', h_clg=m2.clg, v_clg=m1.clg)) v2 = c.addGen( Via( nm='v2', layer='via2', h_clg=m2.clg, v_clg=m3.clg)) for i in [0,2,4]: c.addWire( m1, 'a', None, i, (0,1), (4,-1)) for i in [1,3,5]: c.addWire( m1, 'b', None, i, (0,1), (4,-1)) c.addWireAndViaSet( 'b', None, m2, v1, 3, [(0,1), (1,1), (2,1)]) c.addWireAndViaSet( 'a', None, m2, v1, 2, [(0,0), (1,0), (2,0)]) c.addWireAndMultiViaSet( 'b', None, m2, 1, [(v1, [(0,1), (1,1)]), (v2, [(2,1)])]) c.addWireAndViaSet( 'b', None, m3, v2, (2,1), [1,3]) print( c.terminals) c.computeBbox() fn = "tests/__json_via_set_m2_m3" data = { 'bbox' : c.bbox.toList(), 'globalRoutes' : [], 'globalRouteGrid' : [], # 'terminals' : c.terminals} 'terminals' : c.removeDuplicates()} with open( fn + "_cand", "wt") as fp: fp.write( json.dumps( data, indent=2) + '\n') with open( fn + "_gold", "rt") as fp: data2 = json.load( fp) assert data == data2
def test_via_multi_terminal_short(): c = Canvas() c.addGen(Wire(nm='m1', layer='M1', direction='v', clg=None, spg=None)) c.addGen(Via(nm="v0", layer="via0", h_clg=None, v_clg=None)) c.terminals = [{ 'layer': 'M1', 'netName': 'x', 'rect': [100, -150, 200, 150] }, { 'layer': 'M1', 'netName': 'y', 'rect': [300, -150, 600, 150] }, { 'layer': 'via0', 'netName': 'M1:S', 'rect': [100, -50, 200, 50] }, { 'layer': 'via0', 'netName': 'M1:S', 'rect': [300, -50, 600, 50] }] c.layer_stack.append(('via0', ('M1', None))) c.removeDuplicates() assert len(c.rd.subinsts) == 1 assert len(c.rd.subinsts['M1']) == 1 assert len(c.rd.shorts) == 1 assert len(c.rd.opens) == 0
def test_metal_multi_terminal_connection(): c = Canvas() c.addGen(Wire(nm='m2', layer='metal2', direction='h', clg=None, spg=None)) c.terminals = [{ 'layer': 'metal2', 'netName': 'M1:S', 'rect': [0, -50, 300, 50] }, { 'layer': 'metal2', 'netName': 'inp1', 'rect': [200, -50, 600, 50] }, { 'layer': 'metal2', 'netName': 'M1:D', 'rect': [400, -50, 800, 50] }, { 'layer': 'metal2', 'netName': None, 'rect': [700, -50, 1000, 50] }, { 'layer': 'metal2', 'netName': 'M2:inp', 'rect': [900, -50, 1200, 50] }] c.removeDuplicates() assert len(c.rd.shorts) == 0 assert len(c.rd.subinsts) == 2 assert len(c.rd.subinsts['M1']) == 2 assert len(c.rd.subinsts['M2']) == 1 assert len(c.rd.opens) == 0
def test_vertical(): c = Canvas() c.addGen(Wire(nm='m1', layer='metal1', direction='v', clg=None, spg=None)) c.terminals = [{ 'layer': 'metal1', 'netName': 'x', 'rect': [0, 0, 100, 300] }] c.removeDuplicates()
def setup(): c = Canvas() m1 = c.addGen( Wire( nm='m1', layer='M1', direction='v', clg=UncoloredCenterLineGrid( width=400, pitch=720, repeat=2), spg=EnclosureGrid( pitch=720, stoppoint=360))) m2 = c.addGen( Wire( nm='m2', layer='M2', direction='h', clg=UncoloredCenterLineGrid( width=400, pitch=720, repeat=5), spg=EnclosureGrid( pitch=720, stoppoint=360))) m3 = c.addGen( Wire( nm='m3', layer='M3', direction='v', clg=UncoloredCenterLineGrid( width=400, pitch=720, repeat=2), spg=EnclosureGrid( pitch=720, stoppoint=360))) v1 = c.addGen( Via( nm='v1', layer='via1', h_clg=m2.clg, v_clg=m1.clg)) v2 = c.addGen( Via( nm='v2', layer='via2', h_clg=m2.clg, v_clg=m3.clg)) return (c, m1, v1, m2, v2, m3)
def test_via_short1(): c = Canvas() c.addGen(Wire(nm='m1', layer='M1', direction='v', clg=None, spg=None)) c.addGen(Wire(nm='m2', layer='M2', direction='h', clg=None, spg=None)) c.addGen(Via(nm="v1", layer="via1", h_clg=None, v_clg=None)) c.terminals = [{ 'layer': 'M2', 'netName': 'a', 'rect': [0, -50, 300, 50] }, { 'layer': 'M1', 'netName': 'b', 'rect': [100, -150, 200, 150] }, { 'layer': 'via1', 'netName': None, 'rect': [100, -50, 200, 50] }] print(c.removeDuplicates()) assert len(c.rd.shorts) == 1
def test_via_connectf(): c = Canvas() c.addGen(Wire(nm='m1', layer='M1', direction='v', clg=None, spg=None)) c.addGen(Wire(nm='m2', layer='M2', direction='h', clg=None, spg=None)) c.addGen(Via(nm="v1", layer="via1", h_clg=None, v_clg=None)) c.terminals = [{ 'layer': 'M2', 'netName': 'b', 'rect': [0, -50, 300, 50] }, { 'layer': 'M1', 'netName': None, 'rect': [100, -150, 200, 150] }, { 'layer': 'via1', 'netName': None, 'rect': [100, -50, 200, 50] }] terms = c.removeDuplicates() print(terms) assert len(c.rd.shorts) == 0 assert {d['netName'] for d in terms} == {'b'}
def test_open(): c = Canvas() c.addGen(Wire(nm='m2', layer='metal2', direction='h', clg=None, spg=None)) c.terminals = [{ 'layer': 'metal2', 'netName': 'x', 'rect': [0, -50, 300, 50] }, { 'layer': 'metal2', 'netName': 'x', 'rect': [400, -50, 600, 50] }] c.removeDuplicates() assert len(c.rd.opens) == 1
def test_metal_terminal_connection(): c = Canvas() c.addGen(Wire(nm='m2', layer='metal2', direction='h', clg=None, spg=None)) c.terminals = [{ 'layer': 'metal2', 'netName': 'x', 'rect': [0, -50, 300, 50] }, { 'layer': 'metal2', 'netName': 'M1:S', 'rect': [200, -50, 600, 50] }] c.removeDuplicates() assert len(c.rd.shorts) == 0 assert len(c.rd.subinsts) == 1
def test_different_widths(): c = Canvas() c.addGen(Wire(nm='m2', layer='metal2', direction='h', clg=None, spg=None)) c.terminals = [{ 'layer': 'metal2', 'netName': 'x', 'rect': [0, -50, 300, 50] }, { 'layer': 'metal2', 'netName': 'x', 'rect': [0, -60, 300, 60] }] # with pytest.raises(AssertionError) as excinfo: if True: c.removeDuplicates()
def test_overlapping(): c = Canvas() c.addGen(Wire(nm='m2', layer='metal2', direction='h', clg=None, spg=None)) c.terminals = [{ 'layer': 'metal2', 'netName': 'x', 'rect': [0, -50, 300, 50] }, { 'layer': 'metal2', 'netName': 'x', 'rect': [200, -50, 600, 50] }] newTerminals = c.removeDuplicates() assert len(newTerminals) == 1 assert newTerminals[0]['rect'] == [0, -50, 600, 50]
def test_different_widths(): c = Canvas() c.addGen(Wire(nm='m2', layer='metal2', direction='h', clg=None, spg=None)) c.terminals = [{ 'layer': 'metal2', 'netName': 'x', 'rect': [0, -50, 300, 50] }, { 'layer': 'metal2', 'netName': 'x', 'rect': [0, -60, 300, 60] }] with pytest.raises(AssertionError) as excinfo: c.removeDuplicates() assert "Rectangles on layer metal2 with the same centerline 0 but" in str( excinfo.value)
def __init__(self, fin_u, fin, finDummy, gate, gateDummy, pdkfile=pdkfile): p = Pdk().load(pdkfile) super().__init__(p) assert 3 * p['Fin']['Pitch'] < 2 * p['M2']['Pitch'] ######### Derived Parameters ############ self.gatesPerUnitCell = gate + 2 * gateDummy self.finsPerUnitCell = fin + 2 * finDummy # Should be a multiple of 4 for maximum utilization assert self.finsPerUnitCell % 4 == 0 assert fin >= fin_u, "number of fins in the transistor is greater than unit cell fins" assert fin_u > 3, "number of fins in the transistor must be more than 2" assert finDummy % 2 == 0 assert gateDummy > 0 self.m2PerUnitCell = self.finsPerUnitCell // 2 + 0 self.unitCellHeight = self.m2PerUnitCell * p['M2']['Pitch'] unitCellLength = self.gatesPerUnitCell * p['Poly']['Pitch'] activeWidth1 = p['Fin']['Pitch'] * fin_u activeWidth = p['Fin']['Pitch'] * fin activeOffset = activeWidth // 2 + finDummy * p['Fin']['Pitch'] - p[ 'Fin']['Pitch'] // 2 activePitch = self.unitCellHeight RVTWidth = activeWidth1 + 2 * p['Feol']['active_enclosure'] self.m0 = self.addGen( Wire('m0', 'M0', 'v', clg=UncoloredCenterLineGrid(pitch=p['Feol']['m0Pitch'], width=p['Feol']['m0Width'], offset=p['Feol']['m0Pitch'] // 2), spg=EnclosureGrid(pitch=activePitch, offset=activeOffset, stoppoint=activeWidth // 2, check=True))) self.pl = self.addGen( Wire('pl', 'poly', 'v', clg=UncoloredCenterLineGrid(pitch=p['Poly']['Pitch'], width=p['Poly']['Width'], offset=p['Poly']['Offset']), spg=SingleGrid(offset=p['M2']['Offset'], pitch=self.unitCellHeight))) self.fin = self.addGen( Wire('fin', 'fin', 'h', clg=UncoloredCenterLineGrid(pitch=p['Fin']['Pitch'], width=p['Fin']['Width'], offset=p['Fin']['Offset']), spg=SingleGrid(offset=0, pitch=unitCellLength))) stoppoint = (gateDummy - 1) * p['Poly']['Pitch'] + p['Poly']['Offset'] self.active = self.addGen( Wire('active', 'active', 'h', clg=UncoloredCenterLineGrid(pitch=activePitch, width=activeWidth1, offset=activeOffset), spg=EnclosureGrid(pitch=unitCellLength, offset=0, stoppoint=stoppoint, check=True))) self.RVT = self.addGen( Wire('RVT', 'polycon', 'h', clg=UncoloredCenterLineGrid(pitch=activePitch, width=RVTWidth, offset=activeOffset), spg=EnclosureGrid(pitch=unitCellLength, offset=0, stoppoint=stoppoint, check=True))) self.nselect = self.addGen( Region('nselect', 'nselect', v_grid=CenteredGrid(offset=p['Poly']['Pitch'] // 2, pitch=p['Poly']['Pitch']), h_grid=self.fin.clg)) self.pselect = self.addGen( Region('pselect', 'pselect', v_grid=CenteredGrid(offset=p['Poly']['Pitch'] // 2, pitch=p['Poly']['Pitch']), h_grid=self.fin.clg)) self.nwell = self.addGen( Region('nwell', 'nwell', v_grid=CenteredGrid(offset=p['Poly']['Pitch'] // 2, pitch=p['Poly']['Pitch']), h_grid=self.fin.clg)) self.v0 = self.addGen( Via('v0', 'V0', h_clg=CenterLineGrid(), v_clg=self.m1.clg)) self.v0.h_clg.addCenterLine(0, p['V0']['WidthY'], False) for i in range( max(activeWidth1 // (2 * p['M2']['Pitch']), 1) + ((fin - fin_u) // 2 + finDummy + 1) // 2): self.v0.h_clg.addCenterLine( (i - 1 + fin_u // fin) * 3 * p['Fin']['Pitch'], p['V0']['WidthY'], True) self.v0.h_clg.addCenterLine(self.unitCellHeight, p['V0']['WidthY'], False)
def __init__( self, fin_u, fin, finDummy, gate, gateDummy): p = Pdk().load('../PDK_Abstraction/FinFET14nm_Mock_PDK/FinFET_Mock_PDK_Abstraction.json') super().__init__(p) assert 3*p['Fin']['Pitch'] < 2*p['M2']['Pitch'] ######### Derived Parameters ############ self.gatesPerUnitCell = gate + 2*gateDummy self.finsPerUnitCell = fin + 2*finDummy # Must be a multiple of 2 assert self.finsPerUnitCell % 2 == 0 assert finDummy % 2 == 0 assert gateDummy > 0 # Should be a multiple of 4 for maximum utilization assert self.finsPerUnitCell % 4 == 0 self.m2PerUnitCell = self.finsPerUnitCell//2 + 0 self.unitCellHeight = self.m2PerUnitCell* p['M2']['Pitch'] unitCellLength = self.gatesPerUnitCell* p['Poly']['Pitch'] activeWidth = p['Fin']['Pitch']*fin activeOffset = activeWidth//2 + finDummy* p['Fin']['Pitch']-p['M2']['Pitch']//2+p['Fin']['Offset'] activePitch = self.unitCellHeight RVTPitch = activePitch RVTWidth = activeWidth + 2*p['Feol']['active_enclosure'] RVTOffset = RVTWidth//2 + finDummy* p['Fin']['Pitch']-p['Fin']['Pitch']//2-p['Feol']['active_enclosure']+p['Fin']['Offset'] ############Include these all ########### self.m0 = self.addGen( Wire( 'm0', 'M0', 'v', clg=UncoloredCenterLineGrid( pitch= p['Feol']['m0Pitch'], width= p['Feol']['m0Width'], offset= p['Feol']['m0Pitch']//2), spg=EnclosureGrid( pitch=activePitch, offset=activeOffset, stoppoint=activeWidth//2, check=True))) self.pl = self.addGen( Wire( 'pl', 'poly', 'v', clg=UncoloredCenterLineGrid( pitch= p['Poly']['Pitch'], width= p['Poly']['Width'], offset= p['Poly']['Offset']), spg=SingleGrid( offset= p['M2']['Offset'], pitch=self.unitCellHeight))) self.fin = self.addGen( Wire( 'fin', 'fin', 'h', clg=UncoloredCenterLineGrid( pitch= p['Fin']['Pitch'], width= p['Fin']['Width'], offset= p['Fin']['Offset']), spg=SingleGrid( offset=0, pitch=unitCellLength))) stoppoint = (gateDummy-1)* p['Poly']['Pitch'] + p['Poly']['Offset'] self.active = self.addGen( Wire( 'active', 'active', 'h', clg=UncoloredCenterLineGrid( pitch=activePitch, width=activeWidth, offset=activeOffset), spg=EnclosureGrid( pitch=unitCellLength, offset=0, stoppoint=stoppoint, check=True))) self.RVT = self.addGen( Wire( 'RVT', 'polycon', 'h', clg=UncoloredCenterLineGrid( pitch=RVTPitch, width=RVTWidth, offset=RVTOffset), spg=EnclosureGrid( pitch=unitCellLength, offset=0, stoppoint=stoppoint, check=True))) self.nselect = self.addGen( Region( 'nselect', 'nselect', v_grid=CenteredGrid( offset= p['Poly']['Pitch']//2, pitch= p['Poly']['Pitch']), h_grid=self.fin.clg)) self.pselect = self.addGen( Region( 'pselect', 'pselect', v_grid=CenteredGrid( offset= p['Poly']['Pitch']//2, pitch= p['Poly']['Pitch']), h_grid=self.fin.clg)) self.nwell = self.addGen( Region( 'nwell', 'nwell', v_grid=CenteredGrid( offset= p['Poly']['Pitch']//2, pitch= p['Poly']['Pitch']), h_grid=self.fin.clg)) v0x_offset = p['M2']['Offset'] + (1+finDummy//2)* p['M2']['Pitch'] self.v0 = self.addGen( Via( 'v0', 'V0', h_clg=CenterLineGrid(), v_clg=self.m1.clg)) self.v0.h_clg.addCenterLine( 0, p['V0']['WidthY'], False) for i in range(activeWidth//(2* p['M2']['Pitch'])): self.v0.h_clg.addCenterLine( v0x_offset+i* 3*p['Fin']['Pitch'], p['V0']['WidthY'], True) self.v0.h_clg.addCenterLine( self.unitCellHeight, p['V0']['WidthY'], False)
def __init__( self): super().__init__() self.finsPerUnitCell = 14 self.m2PerUnitCell = 7 ndPitch = 360 pdPitch = 360 m2Pitch = 720 self.unitCellHeight = self.m2PerUnitCell*m2Pitch pcPitch = self.unitCellHeight//2 m1Pitch = 864 m1hPitch = m2Pitch m3Pitch = 720 self.unitCellWidth = 2*m1Pitch plPitch = m1Pitch plOffset = plPitch//2 dcPitch = m1Pitch pcWidth = 200 m1Width = 400 m2Width = 400 m3Width = 400 dcWidth = 200 plWidth = 200 ndWidth = 120 ndPitch = 360 self.pl = self.addGen( Wire( 'pl', 'poly', 'v', clg=CenterLineGrid(), spg=EnclosureGrid( pitch=m2Pitch//2, stoppoint=16))) for i in range(5): self.pl.clg.addCenterLine( i*plPitch//2, plWidth, i % 2 == 1) self.pl.clg.semantic() self.nd = self.addGen( Region( 'nd', 'ndiff', h_grid=SingleGrid( pitch=ndPitch), v_grid=self.pl.clg)) self.pd = self.addGen( Region( 'pd', 'pdiff', h_grid=SingleGrid( pitch=pdPitch), v_grid=self.pl.clg)) self.pc = self.addGen( Wire( 'pc', 'polycon', 'h', clg=UncoloredCenterLineGrid( width=pcWidth, pitch=pcPitch), spg=EnclosureGrid( pitch=dcPitch, stoppoint=plOffset-plWidth//2))) self.m1 = self.addGen( Wire( 'm1', 'M1', 'v', clg=UncoloredCenterLineGrid( width=m1Width, pitch=m1Pitch, repeat=2), spg=EnclosureGrid( pitch=m2Pitch, stoppoint=m2Width//2))) self.m2 = self.addGen( Wire( 'm2', 'M2', 'h', clg=UncoloredCenterLineGrid( width=m2Width, pitch=m2Pitch, repeat=self.m2PerUnitCell), spg=EnclosureGrid( pitch=2*m1Pitch, stoppoint=m1Pitch//2))) self.m3 = self.addGen( Wire( 'm3', 'M3', 'v', clg=UncoloredCenterLineGrid( width=m3Width, pitch=m3Pitch), spg=EnclosureGrid( pitch=self.unitCellHeight, stoppoint=self.unitCellHeight//2-m2Pitch))) self.dc = self.addGen( Wire( 'dc', 'diffcon', 'v', clg=CenterLineGrid(), spg=EnclosureGrid( pitch=m2Pitch//2, stoppoint=0))) for i in range(5): self.dc.clg.addCenterLine( i*dcPitch//2, dcWidth, i % 2 == 0) self.dc.clg.semantic() self.v0 = self.addGen( Via( 'v0', 'via0', v_clg=self.m1.clg, h_clg=self.pc.clg)) self.v1 = self.addGen( Via( 'v1', 'via1', v_clg=self.m1.clg, h_clg=self.m2.clg)) self.v2 = self.addGen( Via( 'v2', 'via2', v_clg=self.m3.clg, h_clg=self.m2.clg))
def __init__(self): super().__init__() self.m1Pitch = 64 self.m1Width = 32 self.m2Pitch_narrow = 64 self.m2Pitch_standard = 84 self.m2Width = 32 self.m3Pitch = 64 self.m3Width = 32 self.v1_xenclosure = 20 self.v1_yenclosure = 20 self.v2_xenclosure = 20 self.v2_yenclosure = 20 self.m1 = self.addGen( Wire('m1', 'M1', 'v', clg=ColoredCenterLineGrid(colors=['c1', 'c2'], pitch=self.m1Pitch, width=self.m1Width), spg=EnclosureGrid(pitch=self.m2Pitch_standard, stoppoint=self.v1_yenclosure + self.m2Width // 2, check=True))) self.m2 = self.addGen( Wire('m2', 'M2', 'h', clg=ColoredCenterLineGrid(colors=['c1', 'c2'], pitch=self.m2Pitch_standard, width=self.m2Width), spg=EnclosureGrid(pitch=self.m1Pitch, stoppoint=self.v1_xenclosure + self.m1Width // 2, check=False))) self.m2n = self.addGen( Wire('m2n', 'M2', 'h', clg=ColoredCenterLineGrid(colors=['c1', 'c2'], pitch=self.m2Pitch_narrow, width=self.m2Width), spg=EnclosureGrid(pitch=self.m1Pitch, stoppoint=self.v1_xenclosure + self.m1Width // 2))) self.m3 = self.addGen( Wire('m3', 'M3', 'v', clg=ColoredCenterLineGrid(colors=['c1', 'c2'], pitch=self.m3Pitch, width=self.m3Width), spg=EnclosureGrid(pitch=self.m2Pitch_standard, stoppoint=self.v2_yenclosure + self.m2Width // 2, check=True))) self.boundary = self.addGen( Region('nwell', 'nwell', h_grid=self.m2.clg, v_grid=self.m1.clg)) self.v1 = self.addGen( Via('v1', 'via1', h_clg=self.m2.clg, v_clg=self.m1.clg)) self.v2 = self.addGen( Via('v2', 'via2', h_clg=self.m2.clg, v_clg=self.m3.clg))
def __init__(self, gate_u, fin_u, fin_u1): super().__init__() ##### PDK Abstraction ##### self.plPitch = 80 ### Use from DRM self.plWidth = 14 self.finPitch = 42 ### finPitch from DRM self.finWidth = 10 self.m0Pitch = self.plPitch self.m0Width = 34 self.m1Pitch = self.plPitch ### Distance between Source and Drain self.m1Width = 32 self.m2Pitch = 84 ### Can be directly used from DRM (usually twice of the fin pitch) self.m2Width = 32 self.m3Pitch = self.plPitch ### Use same as for m1 self.m3Width = 32 self.v0Pitch = 3 * self.finPitch ### V0 spacing rule self.v0Width = 32 self.plActive_s = 73 ### Active horizontal extension over the Gate self.plActive = 7 self.v_enclosure = 20 self.fin_enclosure = (self.finPitch - self.finWidth) // 2 ### Fin enclosure by active self.active_enclosure = 42 self.finOffset = 0 self.plOffset = 0 self.finDummy = 5 ### Number of dummy fins self.gateDummy = 3 ### Number of dummy gates self.gate = int( round(gate_u + 2 * self.gateDummy)) #### Total number of gates per unit cell self.extension_x = ( self.plPitch - self.plWidth ) // 2 ### Minimum horizontal extension of GCUT past GATE self.activeWidth = self.finPitch * fin_u1 self.activeWidth_h = ( (gate_u - 1) * self.plPitch) + (self.plActive_s * 2) + self.plWidth self.activePitch = self.finPitch * (fin_u + 2 * self.finDummy) self.activeOffset = ( self.activeWidth // 2 ) + self.finDummy * self.finPitch - self.fin_enclosure - self.finWidth // 2 + self.finOffset self.RVTWidth = self.activeWidth + 2 * self.active_enclosure self.RVTPitch = self.activePitch self.RVTOffset = ( self.RVTWidth // 2 ) + self.finDummy * self.finPitch - self.fin_enclosure - self.active_enclosure - self.finWidth // 2 + self.finOffset self.m0 = self.addGen( Wire('m0', 'M0', 'v', clg=UncoloredCenterLineGrid(pitch=self.m0Pitch, width=self.m0Width, offset=self.m0Pitch // 2), spg=EnclosureGrid(pitch=self.activePitch, offset=self.activeOffset, stoppoint=self.activeWidth // 2, check=True))) self.m1 = self.addGen( Wire('m1', 'M1', 'v', clg=ColoredCenterLineGrid(colors=['c1', 'c2'], pitch=self.m1Pitch, width=self.m1Width, offset=self.m1Pitch // 2), spg=EnclosureGrid(pitch=self.m2Pitch, offset=self.m2Pitch // 2, stoppoint=self.m2Width // 2 + self.v_enclosure, check=True))) self.m2 = self.addGen( Wire('m2', 'M2', 'h', clg=ColoredCenterLineGrid(colors=['c2', 'c1'], pitch=self.m2Pitch, width=self.m2Width, offset=self.m2Pitch // 2), spg=EnclosureGrid(pitch=self.m1Pitch, offset=self.m1Pitch // 2, stoppoint=self.m1Width // 2 + self.v_enclosure, check=True))) self.m3 = self.addGen( Wire('m3', 'M3', 'v', clg=ColoredCenterLineGrid(colors=['c1', 'c2'], pitch=self.m3Pitch, width=self.m3Width, offset=self.m3Pitch // 2), spg=EnclosureGrid(pitch=self.m2Pitch, offset=self.m2Pitch // 2, stoppoint=self.m2Width // 2 + self.v_enclosure, check=True))) self.pl = self.addGen( Wire('pl', 'poly', 'v', clg=UncoloredCenterLineGrid(pitch=self.plPitch, width=self.plWidth, offset=self.plOffset), spg=EnclosureGrid(pitch=self.finPitch, stoppoint=self.m2Pitch // 2))) self.fin = self.addGen( Wire('fin', 'fin', 'h', clg=UncoloredCenterLineGrid(pitch=self.finPitch, width=self.finWidth, offset=self.finOffset), spg=CenteredGrid(pitch=self.plPitch))) self.active = self.addGen( Wire('active', 'active', 'h', clg=UncoloredCenterLineGrid(pitch=self.activePitch, width=self.activeWidth, offset=self.activeOffset), spg=SingleGrid(pitch=self.plPitch))) self.RVT = self.addGen( Wire('RVT', 'polycon', 'h', clg=UncoloredCenterLineGrid(pitch=self.RVTPitch, width=self.RVTWidth, offset=self.RVTOffset), spg=SingleGrid(pitch=self.plPitch))) self.nselect = self.addGen( Region('nselect', 'nselect', v_grid=CenteredGrid(pitch=self.plPitch), h_grid=self.fin.clg)) v0x_offset = self.finDummy * self.finPitch - self.fin_enclosure - self.finWidth // 2 + self.finOffset + self.v0Width // 2 self.v0 = self.addGen( Via('v0', 'via0', h_clg=UncoloredCenterLineGrid(pitch=self.v0Pitch, width=self.v0Width, offset=v0x_offset), v_clg=self.m1.clg)) self.v1 = self.addGen( Via('v1', 'via1', h_clg=self.m2.clg, v_clg=self.m1.clg)) self.v2 = self.addGen( Via('v2', 'via2', h_clg=self.m2.clg, v_clg=self.m3.clg))
def __init__(self, x_length, y_length): super().__init__() p = Pdk().load(pdkfile) self.x_number = int(2 * round( ((x_length + p['Cap']['m1Pitch'] - p['Cap']['m1Width']) / (2.0 * p['Cap']['m1Pitch'])))) self.y_number = int(2 * round( ((y_length + p['Cap']['m2Pitch'] - p['Cap']['m2Width']) / (2.0 * p['Cap']['m2Pitch'])))) self.last_y1_track = ((self.y_number - 1) * p['Cap']['m2Pitch'] + p['M2']['Pitch'] - 1) // p['M2']['Pitch'] self.last_x_track = self.x_number - 1 self.m1 = self.addGen( Wire('m1', 'M1', 'v', clg=ColoredCenterLineGrid(colors=['c1', 'c2'], pitch=p['Cap']['m1Pitch'], width=p['Cap']['m1Width']), spg=EnclosureGrid(pitch=p['M2']['Pitch'], stoppoint=p['V1']['VencA_L'] + p['Cap']['m2Width'] // 2, check=True))) self.m2 = self.addGen( Wire('m2', 'M2', 'h', clg=ColoredCenterLineGrid(colors=['c1', 'c2'], pitch=p['M2']['Pitch'], width=p['Cap']['m2Width']), spg=EnclosureGrid(pitch=p['Cap']['m1Pitch'], stoppoint=p['V1']['VencA_H'] + p['Cap']['m1Width'] // 2, check=False))) self.m2n = self.addGen( Wire('m2n', 'M2', 'h', clg=ColoredCenterLineGrid(colors=['c1', 'c2'], pitch=p['Cap']['m2Pitch'], width=p['Cap']['m2Width']), spg=EnclosureGrid(pitch=p['Cap']['m1Pitch'], stoppoint=p['V1']['VencA_H'] + p['Cap']['m1Width'] // 2))) self.m3 = self.addGen( Wire('m3', 'M3', 'v', clg=ColoredCenterLineGrid(colors=['c1', 'c2'], pitch=p['Cap']['m3Pitch'], width=p['Cap']['m3Width']), spg=EnclosureGrid(pitch=p['M2']['Pitch'], stoppoint=p['V2']['VencA_H'] + p['Cap']['m2Width'] // 2, check=True))) self.boundary = self.addGen( Region('boundary', 'boundary', h_grid=self.m2.clg, v_grid=self.m1.clg)) self.v1 = self.addGen( Via('v1', 'V1', h_clg=self.m2.clg, v_clg=self.m1.clg)) self.v2 = self.addGen( Via('v2', 'V1', h_clg=self.m2.clg, v_clg=self.m3.clg))
def __init__(self): super().__init__() self.finsPerUnitCell = 12 # Must be a multiple of 2 assert self.finsPerUnitCell % 2 == 0 # Should be a multiple of 4 for maximum utilization assert self.finsPerUnitCell % 4 == 0 self.m2PerUnitCell = self.finsPerUnitCell // 2 + 3 m2Pitch = 720 unitCellHeight = self.m2PerUnitCell * m2Pitch pcPitch = unitCellHeight // 2 m1Pitch = 720 m3Pitch = 720 plPitch = m1Pitch plOffset = plPitch // 2 dcPitch = 2 * m1Pitch pcWidth = 200 m1Width = 400 m2Width = 400 m3Width = 400 dcWidth = 200 plWidth = 200 ndWidth = 120 ndPitch = 360 self.nd = self.addGen( Wire('nd', 'ndiff', 'h', clg=UncoloredCenterLineGrid(pitch=ndPitch, width=ndWidth, repeat=2 * self.m2PerUnitCell), spg=SingleGrid(pitch=dcPitch))) self.pc = self.addGen( Wire('pc', 'polycon', 'h', clg=UncoloredCenterLineGrid(width=pcWidth, pitch=pcPitch), spg=EnclosureGrid(pitch=dcPitch, stoppoint=plOffset - plWidth // 2))) self.m1 = self.addGen( Wire('m1', 'M1', 'v', clg=UncoloredCenterLineGrid(width=m1Width, pitch=m1Pitch, repeat=2), spg=EnclosureGrid(pitch=unitCellHeight, stoppoint=unitCellHeight // 2 - m2Pitch))) self.m3 = self.addGen( Wire('m3', 'M3', 'v', clg=UncoloredCenterLineGrid(width=m3Width, pitch=m3Pitch, repeat=2), spg=EnclosureGrid(pitch=unitCellHeight, stoppoint=unitCellHeight // 2 - m2Pitch))) self.m2 = self.addGen( Wire('m2', 'M2', 'h', clg=UncoloredCenterLineGrid(width=m2Width, pitch=m2Pitch, repeat=self.m2PerUnitCell), spg=EnclosureGrid(pitch=2 * m1Pitch, stoppoint=m1Pitch // 2))) self.pl = self.addGen( Wire('pl', 'poly', 'v', clg=UncoloredCenterLineGrid(width=plWidth, pitch=plPitch, offset=plOffset, repeat=2), spg=EnclosureGrid(pitch=unitCellHeight, stoppoint=m1Pitch // 2))) self.dc = self.addGen( Wire('dc', 'diffcon', 'v', clg=UncoloredCenterLineGrid(width=dcWidth, pitch=dcPitch), spg=Grid())) stoppoint = m1Pitch // 2 self.dc.spg.addGridLine(0, False) self.dc.spg.addGridLine(stoppoint, True) self.dc.spg.addGridLine(unitCellHeight // 2 - stoppoint, True) self.dc.spg.addGridLine(unitCellHeight // 2, False) self.dc.spg.addGridLine(unitCellHeight // 2 + stoppoint, True) self.dc.spg.addGridLine(unitCellHeight - stoppoint, True) self.dc.spg.addGridLine(unitCellHeight, False)
def unit(self, x, y, x_cells, y_cells): m2factor = 2 ### number of m2-tracks (m2factor-1)in between two unitcells in y-direction m1factor = 3 if (self.y_number - 1) % 2 != self.last_y1_track % 2: self.last_y1_track += 1 # so the last color is compatible with the external view of the cell if self.last_y1_track % 2 == 1: m2factor += 1 # so colors match in arrayed blocks grid_cell_x_pitch = m1factor + self.last_x_track grid_cell_y_pitch = m2factor + self.last_y1_track #print( "last_x_track (m1Pitches)", last_x_track, "last_y1_track (m2Pitch_standards)", last_y1_track) #gcd = math.gcd( self.m2Pitch_narrow, self.m2Pitch_standard) #print( "GCD,LCM,(LCM in m2Pitch_narrowes),(LCM in m2Pitch_standards) of m2Pitch_narrow (minimum) and m2Pitch_standard (devices)", gcd, self.m2Pitch_narrow, self.m2Pitch_standard, (self.m2Pitch_narrow*self.m2Pitch_standard)//gcd, self.m2Pitch_standard//gcd, self.m2Pitch_narrow//gcd) grid_y0 = y * grid_cell_y_pitch grid_y1 = grid_y0 + self.last_y1_track for i in range(x_number): (k, p) = (2 * i, 1) if x_number == 2 else (i, 0) grid_x = k + x * grid_cell_x_pitch self.addWire(self.m1, 'M1', None, grid_x, (grid_y0, -1), (grid_y1, 1)) if i < x_number - 1: grid_yh = ((i + 1) % 2) * self.last_y1_track self.addWire(self.m1h, 'M1', None, grid_yh, (i, -1), (i + p + 1, 1)) # # Build the narrow m2 pitch grid starting at grid_cell_y_pitch*y in standard m2 pitch grids (m2.clg) # m2n = Wire(self.m2n.nm, self.m2n.layer, self.m2n.direction, clg=self.m2n.clg.copyShift( self.m2.clg.value(grid_cell_y_pitch * y)[0]), spg=self.m2n.spg) #v1n = Via( 'v1', 'via1', h_clg=m2n.clg, v_clg=self.m1.clg) #v2n = Via( 'v2', 'via2', h_clg=m2n.clg, v_clg=self.m3.clg) grid_x0 = x * grid_cell_x_pitch grid_x1 = grid_x0 + self.last_x_track grid_y = (x_number % 2) * self.last_y1_track pin = 'PLUS' self.addWire(m2n, 'PLUS', pin, 0, (0, -1), (0, 1)) self.addVia(self.v1, 'V1', None, 0, 0) pin = 'MINUS' self.addWire(self.m2, 'MINUS', pin, grid_y, (grid_x1 + p, -1), (grid_x1 + p, 1)) self.addVia(self.v1, 'V1', None, grid_x1 + p, grid_y) if x == x_cells - 1 and y == y_cells - 1: self.addRegion(self.boundary, 'boundary', None, -1, -1, self.last_x_track + x * grid_cell_x_pitch + 1 + p, self.last_y1_track + y * grid_cell_y_pitch + 1)
def __init__(self, x_number, y_length): super().__init__() p = Pdk().load(pdkfile) ga = 2 if x_number == 1 else 1 ## when number of wires is 2 then large spacing req. so contact can be placed without a DRC error self.x_length = (x_number - 1) * ga * p['Cap']['m1Pitch'] self.y_number = int(2 * round( ((y_length + p['Cap']['m2Pitch'] - p['Cap']['m2Width']) / (2.0 * p['Cap']['m2Pitch'])))) self.last_y1_track = ((self.y_number - 1) * p['Cap']['m2Pitch'] + p['M2']['Pitch'] - 1) // p['M2']['Pitch'] self.last_x_track = x_number - 1 self.m1 = self.addGen( Wire('m1', 'M1', 'v', clg=ColoredCenterLineGrid(colors=['c1', 'c2'], pitch=p['Cap']['m1Pitch'], width=p['Cap']['m1Width']), spg=EnclosureGrid(pitch=p['M2']['Pitch'], stoppoint=p['V1']['VencA_L'] + p['Cap']['m2Width'] // 2, check=True))) self.m1h = self.addGen( Wire('m1h', 'M1', 'h', clg=ColoredCenterLineGrid(colors=['c1', 'c2'], pitch=p['M2']['Pitch'], width=p['Cap']['m1Width']), spg=EnclosureGrid(pitch=p['Cap']['m1Pitch'], stoppoint=p['Cap']['m1Width'] // 2, check=False))) self.m2 = self.addGen( Wire('m2', 'M2', 'h', clg=ColoredCenterLineGrid(colors=['c1', 'c2'], pitch=p['M2']['Pitch'], width=p['Cap']['m2Width']), spg=EnclosureGrid(pitch=p['Cap']['m1Pitch'], stoppoint=p['V1']['VencA_H'] + p['Cap']['m1Width'] // 2, check=False))) self.m2n = self.addGen( Wire('m2n', 'M2', 'h', clg=ColoredCenterLineGrid(colors=['c1', 'c2'], pitch=p['Cap']['m2Pitch'], width=p['Cap']['m2Width']), spg=EnclosureGrid(pitch=p['Cap']['m1Pitch'], stoppoint=p['V1']['VencA_H'] + p['Cap']['m1Width'] // 2))) self.m3 = self.addGen( Wire('m3', 'M3', 'v', clg=ColoredCenterLineGrid(colors=['c1', 'c2'], pitch=p['Cap']['m3Pitch'], width=p['Cap']['m3Width']), spg=EnclosureGrid(pitch=p['M2']['Pitch'], stoppoint=p['V2']['VencA_H'] + p['Cap']['m2Width'] // 2, check=True))) self.boundary = self.addGen( Region('boundary', 'boundary', h_grid=self.m2.clg, v_grid=self.m1.clg)) self.v1 = self.addGen( Via('v1', 'V1', h_clg=self.m2.clg, v_clg=self.m1.clg)) self.v2 = self.addGen( Via('v2', 'V2', h_clg=self.m2.clg, v_clg=self.m3.clg))
def unit(self, x, y, x_length, y_length, x_cells, y_cells): m2factor = 2 ### number of m2-tracks (m2factor-1)in between two unitcells in y-direction m1factor = 3 x_number = int(2 * round( ((x_length + self.m1Pitch - self.m1Width) / (2.0 * self.m1Pitch)))) y_number = int(2 * round( ((y_length + self.m2Pitch_narrow - self.m2Width) / (2.0 * self.m2Pitch_narrow)))) print("x_number, y_number:", x_number, y_number) last_y1_track = ((y_number - 1) * self.m2Pitch_narrow + self.m2Pitch_standard - 1) // self.m2Pitch_standard last_x_track = x_number - 1 if (y_number - 1) % 2 != last_y1_track % 2: last_y1_track += 1 # so the last color is compatible with the external view of the cell if last_y1_track % 2 == 1: m2factor += 1 # so colors match in arrayed blocks grid_cell_x_pitch = m1factor + last_x_track grid_cell_y_pitch = m2factor + last_y1_track print("last_x_track (m1Pitches)", last_x_track, "last_y1_track (m2Pitch_standards)", last_y1_track) gcd = math.gcd(self.m2Pitch_narrow, self.m2Pitch_standard) print( "GCD,LCM,(LCM in m2Pitch_narrowes),(LCM in m2Pitch_standards) of m2Pitch_narrow (minimum) and m2Pitch_standard (devices)", gcd, self.m2Pitch_narrow, self.m2Pitch_standard, (self.m2Pitch_narrow * self.m2Pitch_standard) // gcd, self.m2Pitch_standard // gcd, self.m2Pitch_narrow // gcd) grid_y0 = y * grid_cell_y_pitch grid_y1 = grid_y0 + last_y1_track for i in range(x_number): grid_x = i + x * grid_cell_x_pitch net = 'PLUS' if i % 2 == 1 else 'MINUS' self.addWire(self.m1, net, None, grid_x, (grid_y0, -1), (grid_y1, 1)) self.addWire(self.m3, net, None, grid_x, (grid_y0, -1), (grid_y1, 1)) grid_y = ((i + 1) % 2) * last_y1_track + grid_y0 self.addVia(self.v1, net, None, grid_x, grid_y) self.addVia(self.v2, net, None, grid_x, grid_y) # # Build the narrow m2 pitch grid starting at grid_cell_y_pitch*y in standard m2 pitch grids (m2.clg) # m2n = Wire(self.m2n.nm, self.m2n.layer, self.m2n.direction, clg=self.m2n.clg.copyShift( self.m2.clg.value(grid_cell_y_pitch * y)[0]), spg=self.m2n.spg) v1n = Via('v1', 'via1', h_clg=m2n.clg, v_clg=self.m1.clg) v2n = Via('v2', 'via2', h_clg=m2n.clg, v_clg=self.m3.clg) grid_x0 = x * grid_cell_x_pitch grid_x1 = grid_x0 + last_x_track for i in range(y_number - 1): grid_x = x * grid_cell_x_pitch + ((i + 1) % 2) * (x_number - 1) pin = 'PLUS' if y == 0 and x == 0 and i == 0 else None net = 'PLUS' if i % 2 == 0 else 'MINUS' self.addVia(v1n, net, None, grid_x, i) self.addVia(v2n, net, None, grid_x, i) self.addWire(m2n, net, pin, i, (grid_x0, -1), (grid_x1, 1)) grid_y = last_y1_track + grid_cell_y_pitch * y pin = 'MINUS' self.addWire(self.m2, 'MINUS', pin, grid_y, (grid_x0, -1), (grid_x1, 1)) if x == x_cells - 1 and y == y_cells - 1: self.addRegion(self.boundary, 'boundary', None, -1, -1, last_x_track + x * grid_cell_x_pitch + 1, last_y1_track + y * grid_cell_y_pitch + 1)
def test_one(): c = Canvas() m1 = c.addGen( Wire(nm='m1', layer='M1', direction='v', clg=UncoloredCenterLineGrid(width=320, pitch=720, offset=2 * 720, repeat=20), spg=EnclosureGrid(pitch=720, stoppoint=360))) m2 = c.addGen( Wire(nm='m2', layer='M2', direction='h', clg=UncoloredCenterLineGrid(width=400, pitch=720, offset=720, repeat=10), spg=EnclosureGrid(pitch=720, stoppoint=360))) v1 = c.addGen(Via(nm='v1', layer='via1', h_clg=m2.clg, v_clg=m1.clg)) m3 = c.addGen( Wire(nm='m3', layer='M3', direction='v', clg=UncoloredCenterLineGrid(width=400, pitch=720, offset=2 * 720, repeat=20), spg=EnclosureGrid(pitch=720, stoppoint=360))) v2 = c.addGen(Via(nm='v2', layer='via2', h_clg=m2.clg, v_clg=m3.clg)) ch = 5 for base in [0, ch]: c.addWire(m1, 'S', None, 0, (base + 1, 1), (base + ch + 1, -1)) c.addWire(m1, 'S', None, 6, (base + 1, 1), (base + ch + 1, -1)) c.addWire(m1, 'S', None, 12, (base + 1, 1), (base + ch + 1, -1)) c.addWire(m1, 'S', None, 18, (base + 1, 1), (base + ch + 1, -1)) c.addWire(m1, 'DA', None, 2, (base + 1, 1), (base + ch + 1, -1)) c.addWire(m1, 'DA', None, 20, (base + 1, 1), (base + ch + 1, -1)) c.addWire(m1, 'DB', None, 8, (base + 1, 1), (base + ch + 1, -1)) c.addWire(m1, 'DB', None, 14, (base + 1, 1), (base + ch + 1, -1)) c.addWire(m2, 'GND', None, 0 + base, (0, 1), (24, -1)) c.addWireAndViaSet('S', None, m2, v1, 1 + base, [0, 6, 12, 18]) c.addWireAndViaSet('DA', None, m2, v1, 2 + base, [2, 20]) c.addWireAndViaSet('DB', None, m2, v1, 3 + base, [8, 14]) c.addWireAndViaSet('S', 'S', m3, v2, 5, [1, ch + 1]) c.addWireAndViaSet('DA', 'DA', m3, v2, 4, [2, ch + 2]) c.addWireAndViaSet('DB', 'DB', m3, v2, 9, [3, ch + 3]) fn = "tests/__json_diff_pair" print(c.terminals) with open(fn + "_cand", "wt") as fp: data = c.writeJSON(fp) with open(fn + "_gold", "rt") as fp: data2 = json.load(fp) assert data == data2