def genWires( self): horizontalMetals = ['metal2'] verticalMetals = ['metal3'] self.wires = OrderedDict() for (k,v) in self.per_net_grid.items(): self.wires[k] = {} for (ly,bv) in v.items(): if ly in horizontalMetals: for y in range(self.ny): x0,x1 = None,None for x in range(self.nx): filled = bv.val(self.idx(x,y)) if filled: if x0 is None: x0 = x x1 = x if filled and x == self.nx-1 or not filled and x1 is not None: if ly not in self.wires[k]: self.wires[k][ly] = [] self.wires[k][ly].append( GR( k, ly, 400, Rect( x0, y, x1, y))) x0,x1 = None,None if ly in verticalMetals: for x in range(self.nx): y0,y1 = None,None for y in range(self.ny): filled = bv.val(self.idx(x,y)) if filled: if y0 is None: y0 = y y1 = y if filled and y == self.ny-1 or not filled and y1 is not None: if ly not in self.wires[k]: self.wires[k][ly] = [] self.wires[k][ly].append( GR( k, ly, 400, Rect( x, y0, x, y1))) y0,y1 = None,None
def write_globalrouting_json( self, fp, tech, placer_results=None): grs = [] terminals = [] hack = 1 # gridFactor == 4 if placer_results is not None: globalScale = Transformation( 0, 0, hack*tech.halfXADTGrid*tech.pitchPoly, hack*tech.halfYADTGrid*tech.pitchDG) b = globalScale.hitRect( Rect( *placer_results['bbox'])).canonical() terminals.append( { "netName" : placer_results['nm'], "layer" : "diearea", "rect" : b.toList()}) print( "placer_results bbox:", b.toList()) leaves_map = { leaf['template_name'] : leaf for leaf in placer_results['leaves']} for inst in placer_results['instances']: leaf = leaves_map[inst['template_name']] tr = inst['transformation'] trans = Transformation( tr['oX'], tr['oY'], tr['sX'], tr['sY']) r = globalScale.hitRect( trans.hitRect( Rect( *leaf['bbox'])).canonical()) nm = placer_results['nm'] + '/' + inst['instance_name'] + ':' + inst['template_name'] print( nm, r) terminals.append( { "netName" : nm, "layer" : "cellarea", "rect" : r.toList()}) for term in placer_results['terminals']: nm = term['net_name'] + ':' + term['hier_name'] b = globalScale.hitRect( Rect( *term['rect'])).canonical() b.llx -= 200 b.urx += 200 b.lly += 360 b.ury -= 360 terminals.append( { "netName" : nm, "layer" : term['layer'], "rect" : b.toList()}) for (k,v) in self.wires.items(): for (ly, vv) in v.items(): for gr in vv: terminals.append(gr) # halfXGRGrid should be 2 # hack = 1 works if gridFactor is 2 # what should hack be if gridFactor is 4 hack = self.gridFactor // 2 grGrid = [] globalScale = Transformation( 0, 0, hack*tech.halfXGRGrid*tech.pitchPoly, hack*tech.halfYGRGrid*tech.pitchDG) self.bbox = globalScale.hitRect( Rect( 0, 0, self.nx, self.ny)) for x in range( self.nx): for y in range( self.ny): r = globalScale.hitRect( Rect( x, y, x+1, y+1)) print( "global route:", x, y, r) grGrid.append( r.toList()) data = { "bbox" : [self.bbox.llx, self.bbox.lly, self.bbox.urx, self.bbox.ury], "globalRoutes" : grs, "globalRouteGrid" : grGrid, "terminals" : terminals} print( 'Grid bbox:', data['bbox']) fp.write( json.dumps( data, indent=2, default=lambda x: encode_GR(tech,x)) + "\n")
def addTerminalOverlapConstraints( self): print( "Building bit vectors for %d nets" % len(self.nets)) self.net_bvs = OrderedDict() for k in self.nets.keys(): print( "Building bit vectors for %s" % k) self.net_bvs[k] = tally.BitVec( self.s, ('net_terminal_%s' % k), (self.nx+1)*self.ny) for ri in self.ris: inst = ri.ci for ( x, y, bv, tr) in ri.tGen( plusOneIfMirrored=True): anchor = bv.var( self.idx( x, y)) for (f,v) in inst.template.terminals.items(): a = inst.fa_map[f] for term in v: for yy in range(term.lly, term.ury): newterm = Rect( term.llx, yy, term.urx, yy+1) r = tr.hitRect( newterm).canonical() if 0 <= r.llx and r.llx < self.nx+1 and 0 <= r.lly and r.lly < self.ny: self.s.emit_implies( anchor, self.net_bvs[a].var( self.idx( r.llx, r.lly))) for x in range(self.nx+1): for y in range(self.ny): vector = [ bv.var( self.idx( x, y)) for (k,bv) in self.net_bvs.items()] self.s.emit_at_most_one( vector)
def write_globalrouting_json( self, fp, tech): grs = [] terminals = [] terminals.append( { "netName" : self.nm, "layer" : "diearea", "rect" : self.bbox}) for inst in self.instances.values(): r = inst.transformation.hitRect( inst.template.bbox) nm = self.nm + '/' + inst.nm + ':' + inst.template.nm terminals.append( { "netName" : nm, "layer" : "cellarea", "rect" : r.canonical()}) for inst in self.instances.values(): r = inst.transformation.hitRect( inst.template.bbox) for (k,v) in inst.template.terminals.items(): for term in v: nm = inst.fa_map[k] + ':' + inst.nm + '/' + k terminals.append( Terminal( nm, "metal1", inst.transformation.hitRect( term).canonical())) grGrid = [] for x in range( self.bbox.llx, self.bbox.urx): for y in range( self.bbox.lly, self.bbox.ury): grGrid.append( Rect( x,y,x+1,y+1)) data = { "bbox" : self.bbox, "globalRoutes" : grs, "globalRouteGrid" : grGrid, "terminals" : terminals} fp.write( json.dumps( data, indent=2, default=lambda x: encode_T(tech,x)) + "\n")
def updateBbox( self): self.bbox = Rect(None,None,None,None) for inst in self.instances.values(): r = inst.transformation.hitRect( inst.template.bbox).canonical() if self.bbox.llx is None or self.bbox.llx > r.llx: self.bbox.llx = r.llx if self.bbox.lly is None or self.bbox.lly > r.lly: self.bbox.lly = r.lly if self.bbox.urx is None or self.bbox.urx < r.urx: self.bbox.urx = r.urx if self.bbox.ury is None or self.bbox.ury < r.ury: self.bbox.ury = r.ury
def test_sc(): ndev = CellLeaf( "ndev", Rect(0,0,2,2)) ndev.addTerminal( "d", Rect(0,0,0,2)) ndev.addTerminal( "g", Rect(1,0,1,2)) ndev.addTerminal( "s", Rect(2,0,2,2)) cc = CellLeaf( "cc", Rect(0,0,3,2)) cc.addTerminal( "cp1", Rect(0,0,0,2)) cc.addTerminal( "cn1", Rect(1,0,1,2)) cc.addTerminal( "cn2", Rect(2,0,2,2)) cc.addTerminal( "cp2", Rect(3,0,3,2)) ccbig = CellLeaf( "ccbig", Rect(0,0,5,2)) ccbig.addTerminal( "cp1", Rect(0,0,0,2)) ccbig.addTerminal( "cn1", Rect(1,0,1,2)) ccbig.addTerminal( "cn2", Rect(4,0,4,2)) ccbig.addTerminal( "cp2", Rect(5,0,5,2)) sc = CellHier( "sc") sc.addInstance( CellInstance( "L0_MM0", ndev)) sc.addInstance( CellInstance( "L0_MM1", ndev)) sc.addInstance( CellInstance( "L0_MM2", ndev)) sc.addInstance( CellInstance( "L0_MM3", ndev)) sc.addInstance( CellInstance( "L0_MM4", ndev)) sc.addInstance( CellInstance( "L0_MM5", ndev)) sc.addInstance( CellInstance( "L0_MM6", ndev)) sc.addInstance( CellInstance( "L0_MM7", ndev)) sc.addInstance( CellInstance( "L0_MM8", ndev)) sc.addInstance( CellInstance( "L0_MM9", ndev)) sc.addInstance( CellInstance( "L0_MM10", ndev)) sc.addInstance( CellInstance( "L0_MM11", ndev)) sc.addInstance( CellInstance( "L1_CC5_CC7", cc)) sc.addInstance( CellInstance( "L1_CC4_CC6", ccbig)) sc.addInstance( CellInstance( "L1_CC1_CC3", ccbig)) sc.addInstance( CellInstance( "L1_CC0_CC2", ccbig)) sc.connect( 'L1_CC5_CC7', 'cp1', 'net23') sc.connect( 'L1_CC0_CC2', 'cp1', 'net23') sc.connect( 'L0_MM1', 's', 'net23') # sc.connect( 'I0', 'Vinn', 'net23') sc.connect( 'L0_MM0', 's', 'net3') sc.connect( 'L0_MM10', 's', 'net3') sc.connect( 'L1_CC4_CC6', 'cn1', 'net3') sc.connect( 'L0_MM11', 's', 'net12') sc.connect( 'L0_MM8', 'd', 'net12') sc.connect( 'L1_CC1_CC3', 'cn2', 'net12') sc.connect( 'L0_MM3', 'd', 'net7') sc.connect( 'L1_CC5_CC7', 'cp2', 'net7') sc.connect( 'L1_CC0_CC2', 'cp2', 'net7') # sc.connect( 'I0', 'Vinp', 'net7') sc.connect( 'L0_MM5', 'd', 'net5') sc.connect( 'L0_MM3', 's', 'net5') sc.connect( 'L1_CC4_CC6', 'cp2', 'net5') sc.connect( 'L1_CC1_CC3', 'cp1', 'net5') sc.connect( 'L0_MM9', 's', 'net6') sc.connect( 'L0_MM1', 'd', 'net6') sc.connect( 'L1_CC4_CC6', 'cp1', 'net6') sc.connect( 'L1_CC1_CC3', 'cp2', 'net6') # sc.connect( 'terminal Vbiasn', 'Vbiasn') # sc.connect( 'I0', 'Vbiasn', 'Vbiasn') # sc.connect( 'terminal Vbiasp1', 'Vbiasp1') # sc.connect( 'I0', 'Vbiasp1', 'Vbiasp1') # sc.connect( 'terminal Vbiasp2', 'Vbiasp2') # sc.connect( 'I0', 'Vbiasp2', 'Vbiasp2') sc.connect( 'L0_MM2', 's', 'Vinn') sc.connect( 'L1_CC5_CC7', 'cn1', 'Vinn') # sc.connect( 'terminal Vinn', 'Vinn') sc.connect( 'L0_MM0', 'd', 'Vinp') sc.connect( 'L1_CC5_CC7', 'cn2', 'Vinp') # sc.connect( 'terminal Vinp', 'Vinp') sc.connect( 'L0_MM7', 'd', 'Voutn') sc.connect( 'L1_CC0_CC2', 'cn2', 'Voutn') # sc.connect( 'I0', 'Voutn', 'Voutn') # sc.connect( 'terminal Voutn', 'Voutn') sc.connect( 'L0_MM8', 's', 'Voutp') sc.connect( 'L1_CC0_CC2', 'cn1', 'Voutp') # sc.connect( 'I0', 'Voutp', 'Voutp') # sc.connect( 'terminal Voutp', 'Voutp') sc.connect( 'L0_MM11', 'g', 'phi1') sc.connect( 'L0_MM6', 'g', 'phi1') sc.connect( 'L0_MM1', 'g', 'phi1') sc.connect( 'L0_MM3', 'g', 'phi1') sc.connect( 'L0_MM0', 'g', 'phi1') sc.connect( 'L0_MM2', 'g', 'phi1') # sc.connect( 'terminal phi1', 'phi1') sc.connect( 'L0_MM2', 'd', 'net4') sc.connect( 'L0_MM4', 'd', 'net4') sc.connect( 'L1_CC4_CC6', 'cn2', 'net4') sc.connect( 'L0_MM8', 'g', 'phi2') sc.connect( 'L0_MM7', 'g', 'phi2') sc.connect( 'L0_MM9', 'g', 'phi2') sc.connect( 'L0_MM5', 'g', 'phi2') sc.connect( 'L0_MM4', 'g', 'phi2') sc.connect( 'L0_MM10', 'g', 'phi2') # sc.connect( 'terminal phi2', 'phi2') # sc.connect( 'I0', 'vdd!', 'vdd!') # sc.connect( 'terminal vdd!', 'vdd!') # sc.connect( 'terminal Id', 'Id') # sc.connect( 'I0', 'Id', 'Id') sc.connect( 'L0_MM11', 'd', 'gnd!') sc.connect( 'L0_MM6', 's', 'gnd!') sc.connect( 'L0_MM9', 'd', 'gnd!') sc.connect( 'L0_MM5', 's', 'gnd!') sc.connect( 'L0_MM4', 's', 'gnd!') sc.connect( 'L0_MM10', 'd', 'gnd!') # sc.connect( 'I0', 'gnd!', 'gnd!') # sc.connect( 'terminal gnd!', 'gnd!') sc.connect( 'L0_MM6', 'd', 'net11') sc.connect( 'L0_MM7', 's', 'net11') sc.connect( 'L1_CC1_CC3', 'cn1', 'net11') nx = 16 ny = 12 sc.bbox = Rect( 0, 0, nx, ny) s = tally.Tally() r = Raster( s, sc, nx, ny) r.semantic( skipTerminals=False) for x in range(nx): for y in range(ny): for ri in r.ris: if y % 2 != 0: s.emit_never( ri.anchor.var( r.idx( x,y))) s.emit_never( ri.anchorMX.var( r.idx( x,y))) s.emit_never( ri.anchorMY.var( r.idx( x,y))) s.emit_never( ri.anchorMXY.var( r.idx( x,y))) else: s.emit_never( ri.anchorMX.var( r.idx( x,y))) s.emit_never( ri.anchorMXY.var( r.idx( x,y))) #put a raft on the left and right for x in [0,nx-1]: for y in range(ny): for ri in r.ris: print( ri.ci.nm, x, y) s.emit_never( ri.filled.var( r.idx( x, y))) print( "First solve") s.solve() assert s.state == 'SAT' priority_nets_0 = ['net7','net23'] priority_nets_1 = ['phi1','phi2'] power_nets = ['gnd!'] specified_nets = set( priority_nets_0 + priority_nets_1 + power_nets) remaining_nets = [ n for n in r.nets.keys() if n not in specified_nets] def chunk( it, size): it = iter(it) return iter( lambda: tuple(itertools.islice(it, size)), ()) groups = [ list(tup) for tup in chunk( remaining_nets, 6)] r.optimizeNets( [priority_nets_0, priority_nets_1] + groups + [power_nets]) sc.dump()
def test_ota_bigger(): ndual = CellLeaf( "ndual", Rect(0,0,10,4)) ndual.addTerminal( "d1", Rect(0,0,0,4)) ndual.addTerminal( "g1", Rect(2,0,2,4)) ndual.addTerminal( "s1", Rect(4,0,4,4)) ndual.addTerminal( "s2", Rect(6,0,6,4)) ndual.addTerminal( "g2", Rect(8,0,8,4)) ndual.addTerminal( "d2", Rect(10,0,10,4)) ndualss = CellLeaf( "ndualss", Rect(0,0,8,4)) ndualss.addTerminal( "d1", Rect(0,0,0,4)) ndualss.addTerminal( "g1", Rect(2,0,2,4)) ndualss.addTerminal( "s", Rect(4,0,4,4)) ndualss.addTerminal( "g2", Rect(6,0,6,4)) ndualss.addTerminal( "d2", Rect(8,0,8,4)) ncap = CellLeaf( "ncap", Rect(0,0,8,4)) ncap.addTerminal( "d1", Rect(0,0,0,4)) ncap.addTerminal( "s", Rect(4,0,4,4)) ncap.addTerminal( "d2", Rect(8,0,8,4)) ota = CellHier( "ota") ota.addInstance( CellInstance( "L1_MM4_MM3", ncap)) ota.addInstance( CellInstance( "L1_MM1_MM0", ndualss)) ota.addInstance( CellInstance( "L1_MM9_MM8", ndual)) ota.addInstance( CellInstance( "L1_MM7_MM6", ndual)) ota.addInstance( CellInstance( "L1_MM10_MM2", ndual)) ota.connect('L1_MM1_MM0','g1','Vinp') ota.connect('L1_MM7_MM6','s1','net13') ota.connect('L1_MM9_MM8','d1','net13') ota.connect('L1_MM7_MM6','d2','Voutp') ota.connect('L1_MM10_MM2','d2','Voutp') ota.connect('L1_MM7_MM6','d1','Voutn') ota.connect('L1_MM10_MM2','d1','Voutn') ota.connect('L1_MM10_MM2','s1','net10') ota.connect('L1_MM1_MM0','d1','net10') ota.connect('L1_MM9_MM8','s1','vdd!') ota.connect('L1_MM9_MM8','s2','vdd!') ota.connect('L1_MM10_MM2','g1','Vbiasn') ota.connect('L1_MM10_MM2','g2','Vbiasn') ota.connect('L1_MM10_MM2','s2','net11') ota.connect('L1_MM1_MM0','d2','net11') ota.connect('L1_MM9_MM8','g1','Vbiasp2') ota.connect('L1_MM9_MM8','g2','Vbiasp2') ota.connect('L1_MM7_MM6','g1','Vbiasp1') ota.connect('L1_MM7_MM6','g2','Vbiasp1') ota.connect('L1_MM4_MM3','s','gnd!') ota.connect('L1_MM7_MM6','s2','net12') ota.connect('L1_MM9_MM8','d2','net12') ota.connect('L1_MM1_MM0','s','net6') ota.connect('L1_MM4_MM3','d2','net6') ota.connect('L1_MM1_MM0','g2','Vinn') ota.connect('L1_MM4_MM3','d1','net1') nx = 12 ny = 20 ota.bbox = Rect( 0, 0, nx, ny) s = tally.Tally() r = Raster( s, ota, nx, ny) r.semantic() #put a raft on the left and right for x in [0,nx-1]: for y in range(ny): for ri in r.ris: print( ri.ci.nm, x, y) s.emit_never( ri.filled.var( r.idx( x, y))) for x in range(nx): for y in range(ny): for ri in r.ris: if y % 4 != 0: s.emit_never( ri.anchor.var( r.idx( x,y))) s.emit_never( ri.anchorMX.var( r.idx( x,y))) s.emit_never( ri.anchorMY.var( r.idx( x,y))) s.emit_never( ri.anchorMXY.var( r.idx( x,y))) else: s.emit_never( ri.anchorMX.var( r.idx( x,y))) s.emit_never( ri.anchorMXY.var( r.idx( x,y))) s.solve() assert s.state == 'SAT' priority0_nets = ['net6', 'Voutn', 'Voutp', 'net12', 'net13'] priority1_nets = ['Vbiasn', 'Vbiasp1', 'Vbiasp2'] mentioned_nets = set( priority0_nets + priority1_nets) other_nets = [ n for n in r.nets.keys() if n not in mentioned_nets] r.optimizeNets( [priority0_nets,priority1_nets,other_nets]) ota.dump()
def test_ota(): ndual = CellLeaf( "ndual", Rect(0,0,5,2)) ndual.addTerminal( "d1", Rect(0,0,0,2)) ndual.addTerminal( "g1", Rect(1,0,1,2)) ndual.addTerminal( "s1", Rect(2,0,2,2)) ndual.addTerminal( "s2", Rect(3,0,3,2)) ndual.addTerminal( "g2", Rect(4,0,4,2)) ndual.addTerminal( "d2", Rect(5,0,5,2)) ndualss = CellLeaf( "ndualss", Rect(0,0,4,2)) ndualss.addTerminal( "d1", Rect(0,0,0,2)) ndualss.addTerminal( "g1", Rect(1,0,1,2)) ndualss.addTerminal( "s", Rect(2,0,2,2)) ndualss.addTerminal( "g2", Rect(3,0,3,2)) ndualss.addTerminal( "d2", Rect(4,0,4,2)) ncap = CellLeaf( "ncap", Rect(0,0,4,2)) ncap.addTerminal( "d1", Rect(0,0,0,2)) ncap.addTerminal( "s", Rect(2,0,2,2)) ncap.addTerminal( "d2", Rect(4,0,4,2)) ota = CellHier( "ota") ota.addInstance( CellInstance( "L1_MM4_MM3", ncap)) ota.addInstance( CellInstance( "L1_MM1_MM0", ndualss)) ota.addInstance( CellInstance( "L1_MM9_MM8", ndual)) ota.addInstance( CellInstance( "L1_MM7_MM6", ndual)) ota.addInstance( CellInstance( "L1_MM10_MM2", ndual)) ota.connect('L1_MM1_MM0','g1','Vinp') ota.connect('L1_MM7_MM6','s1','net13') ota.connect('L1_MM9_MM8','d1','net13') ota.connect('L1_MM7_MM6','d2','Voutp') ota.connect('L1_MM10_MM2','d2','Voutp') ota.connect('L1_MM7_MM6','d1','Voutn') ota.connect('L1_MM10_MM2','d1','Voutn') ota.connect('L1_MM10_MM2','s1','net10') ota.connect('L1_MM1_MM0','d1','net10') ota.connect('L1_MM9_MM8','s1','vdd!') ota.connect('L1_MM9_MM8','s2','vdd!') ota.connect('L1_MM10_MM2','g1','Vbiasn') ota.connect('L1_MM10_MM2','g2','Vbiasn') ota.connect('L1_MM10_MM2','s2','net11') ota.connect('L1_MM1_MM0','d2','net11') ota.connect('L1_MM9_MM8','g1','Vbiasp2') ota.connect('L1_MM9_MM8','g2','Vbiasp2') ota.connect('L1_MM7_MM6','g1','Vbiasp1') ota.connect('L1_MM7_MM6','g2','Vbiasp1') ota.connect('L1_MM4_MM3','s','gnd!') ota.connect('L1_MM7_MM6','s2','net12') ota.connect('L1_MM9_MM8','d2','net12') ota.connect('L1_MM1_MM0','s','net6') ota.connect('L1_MM4_MM3','d2','net6') ota.connect('L1_MM1_MM0','g2','Vinn') ota.connect('L1_MM4_MM3','d1','net1') nx = 8 ny = 12 ota.bbox = Rect( 0, 0, nx, ny) s = tally.Tally() r = Raster( s, ota, nx, ny) r.semantic() for x in range(nx): for y in range(ny): for ri in r.ris: if y % 2 == 1: s.emit_never( ri.anchor.var( r.idx( x,y))) s.emit_never( ri.anchorMX.var( r.idx( x,y))) s.emit_never( ri.anchorMY.var( r.idx( x,y))) s.emit_never( ri.anchorMXY.var( r.idx( x,y))) else: s.emit_never( ri.anchorMX.var( r.idx( x,y))) s.emit_never( ri.anchorMXY.var( r.idx( x,y))) #put a raft on the left and right for x in [0,nx-1]: for y in range(ny): for ri in r.ris: print( ri.ci.nm, x, y) s.emit_never( ri.filled.var( r.idx( x, y))) s.solve() assert s.state == 'SAT' priority0_nets = ['net6', 'Voutn', 'Voutp', 'net12', 'net13'] priority1_nets = ['Vbiasn', 'Vbiasp1', 'Vbiasp2'] mentioned_nets = set( priority0_nets + priority1_nets) other_nets = [ n for n in r.nets.keys() if n not in mentioned_nets] r.optimizeNets( [priority0_nets,priority1_nets,other_nets]) with open( "mydesign_dr_globalrouting.json", "wt") as fp: tech = Tech() ota.write_globalrouting_json( fp, tech) with open( "ota_placer_out.json", "wt") as fp: tech = Tech() ota.dumpJson( fp, tech)
def __init__( self, nm, bbox=None): super().__init__(nm) if bbox is None: self.bbox = Rect(0,0,1,1) else: self.bbox = bbox