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_m3(): p = Pdk().load( '../PDK_Abstraction/FinFET14nm_Mock_PDK/FinFET_Mock_PDK_Abstraction.json' ) c = DefaultCanvas(p) m = c.generators['m3'] mt = MetalTemplate(m) print("m3 clg grid", m.clg.grid, "m3 clg legal indices", m.clg.legalIndices) print("m3 spg grid", m.spg.grid, "m3 spg legal indices", m.spg.legalIndices) assert 1 in m.spg.legalIndices assert 3 in m.spg.legalIndices ### The following assertions are modified based on the updtaed PDK assert m.spg.grid[1][0] == 36 assert m.spg.grid[3][0] == 48 assert mt.widths == [40, 40, 40] assert mt.colors == ["c1", "c2", "c1"] assert mt.spaces == [40, 40] assert mt.offset == 0 assert mt.stop_offset == 36 assert mt.stops == [12, 72]
def setup(): p = Pdk().load( '../PDK_Abstraction/FinFET14nm_Mock_PDK/FinFET_Mock_PDK_Abstraction.json' ) c = DefaultCanvas(p) for (i, nm) in itertools.chain(itertools.product([0, 2, 4], ['a']), itertools.product([1, 3, 5], ['b'])): c.addWire(c.m1, nm, None, i, (0, -1), (3, -1)) return c
def test_v3(setup): p = Pdk().load( '../PDK_Abstraction/FinFET14nm_Mock_PDK/FinFET_Mock_PDK_Abstraction.json' ) c = DefaultCanvas(p) c.addWire(c.m3, "a", None, 1, (-2, 1), (4, -1)) c.addWire(c.m4, "a", None, 1, (-2, 1), (4, -1)) c.addVia(c.v3, None, None, 1, 1) data = c.gen_data() fn = "tests/__json_v3" with open(fn + "_cand", "wt") as fp: fp.write(json.dumps(data, indent=2) + '\n')
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 remove_duplicates(hN): p = Pdk().load( "../../PDK_Abstraction/FinFET14nm_Mock_PDK/FinFET_Mock_PDK_Abstraction.json" ) cnv = DefaultCanvas(p) cnv.bbox = transformation.Rect(0, 0, hN.width, hN.height) cnv.terminals = [] def add_terminal(netName, layer, b): check_bbox(b) cnv.terminals.append({ "netName": netName, "layer": layer, "rect": [b.LL.x, b.LL.y, b.UR.x, b.UR.y] }) for n in hN.Nets: print(n.name) for c in n.connected: if c.type == 'Block': cblk = hN.Blocks[c.iter2] blk = cblk.instance[cblk.selectedInstance] block_name = blk.name master_name = blk.master pin = blk.blockPins[c.iter] formal_name = pin.name print( f'\tBlock formal_index: {c.iter},{formal_name} block_index: {c.iter2},{block_name},{master_name}' ) for con in pin.pinContacts: add_terminal(n.name, con.metal, con.placedBox) else: term = hN.Terminals[c.iter] terminal_name = term.name assert terminal_name == n.name print(f'\tTerminal formal_index: {c.iter},{terminal_name}') for con in term.termContacts: add_terminal(n.name, con.metal, con.placedBox) for metal in n.path_metal: con = metal.MetalRect add_terminal(n.name, con.metal, con.placedBox) for via in n.path_via: for con in [via.UpperMetalRect, via.LowerMetalRect, via.ViaRect]: add_terminal(n.name, con.metal, con.placedBox) for via in n.interVias: for con in [via.UpperMetalRect, via.LowerMetalRect, via.ViaRect]: add_terminal(n.name, con.metal, con.placedBox) for cblk in hN.Blocks: blk = cblk.instance[cblk.selectedInstance] for con in blk.interMetals: # add_terminal( '!interMetals', con.metal, con.placedBox) pass for via in blk.interVias: for con in [via.UpperMetalRect, via.LowerMetalRect, via.ViaRect]: # add_terminal( '!interVias', con.metal, con.placedBox) pass cnv.removeDuplicates() return cnv
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 setup(): p = Pdk().load('../PDK_Abstraction/FinFET14nm_Mock_PDK/FinFET_Mock_PDK_Abstraction.json') c = DefaultCanvas(p) return c
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, 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 test_one(): p = Pdk().load( '../PDK_Abstraction/FinFET14nm_Mock_PDK/FinFET_Mock_PDK_Abstraction.json' ) c = DefaultCanvas(p) assert c.generate_routing_collateral("tests/routing_collateral_cand")