;================================================================================ ; Robert Johnstone ; Simon Fraser University ; ; Copyright 2000,2001,2002 Robert W. Johnstone ;-------------------------------------------------------------------------------- ; 2002/07/25 ; - modified code so that sub procedure is a lambda function ; - prevent polution of public namespace ; 2002/07/23 ; - modified code so that sub procedure lever_CreateDimple is defined ; within the pcell code. This means that the function does not need to ; be defined externally ; 2002/06/03 ; - modified code because interface to dbCreateRoundRect changed ; 2001/11/07 ; - removed dimple_maxSpacing parameter ; - dimple placement now calculated using library maxSpacing rule unless( boundp( 'admLibraryName ) warn( "Setting the destination library to default value of ADM" ) admLibraryName = "ADM" ) pcDefinePCell( list( ddGetObj(admLibraryName) "lever" "layout" ) ; end of list for first argument ( ( arm1 21.0 ) ( arm2 42.0 ) ( chamfer 0.0 ) ( flange_to_end t ) ( include_poly0 "boolean" nil ) ) ; end of parameter list prog( let( pcTechFile rodObj lever_CreateDimple p0p1_enclosure p0p2_enclosure p1_minSpacing p1_minWidth p1_nomWidth p1_a1_enclosure p1p2_enclosure p1d_enclosure p1v_enclosure p1a2_minSpacing a1_nomWidth p2p1_minOverlap p2a2_enclosure a2_nomWidth v_nomWidth d_nomWidth d_maxSpacing x1 y1 x2 y2 x3 y3 hub_o hub_i width dimple_count tmp tmp_x tmp_y arm1_sp arm2_sp ) ; create sub procedure lever_CreateDimple = lambda( ( pcCellView w x y p2 ) if( (w>=4) dbCreateRoundRect( pcCellView "DIMPLE" 1 list( x-w*0.5:y-w*0.5 x+w*0.5:y+w*.05 ) ) dbCreateRect( pcCellView "DIMPLE" list( x-w*0.5:y-w*0.5 x+w*0.5:y+w*0.5 ) ) ) if( (p2==t) dbCreateRect( pcCellView "HOLE2" list( x-w*0.5:y-w*0.5 x+w*0.5:y+w*0.5 ) ) ) ) ; load tech file rules pcTechFile = techGetTechFile( pcCellView ) p0p1_enclosure = techGetOrderedSpacingRule( pcTechFile "minEnclosure" "POLY0" "POLY1" ) unless( p0p1_enclosure warn("minEnclosure rule for POLY0->POLY1 not set") ) p0p2_enclosure = techGetOrderedSpacingRule( pcTechFile "minEnclosure" "POLY0" "POLY2" ) unless( p0p2_enclosure warn("minEnclosure rule for POLY0->POLY2 not set") ) p1_minSpacing = techGetSpacingRule( pcTechFile "minSpacing" "POLY1" ) unless( p1_minSpacing warn("minSpacing rule for POLY1 not set") ) p1_minWidth = techGetSpacingRule( pcTechFile "minWidth" "POLY1" ) unless( p1_minWidth warn("minWidth rule for POLY1 not set") ) p1_nomWidth = techGetSpacingRule( pcTechFile "nomWidth" "POLY1" ) unless( p1_nomWidth warn("nomWidth rule for POLY1 not set") ) p1a1_enclosure = techGetOrderedSpacingRule( pcTechFile "minEnclosure" "POLY1" "ANCHOR1" ) unless( p1a1_enclosure warn("minEnclosure rule for POLY1->ANCHOR1 not set") ) p1p2_enclosure = techGetOrderedSpacingRule( pcTechFile "minEnclosure" "POLY1" "POLY2" ) unless( p1p2_enclosure warn("minEnclosure rule for POLY1->POLY2 not set") ) p1d_enclosure = techGetOrderedSpacingRule( pcTechFile "minEnclosure" "POLY1" "DIMPLE" ) unless( p1d_enclosure warn("minEnclosure rule for POLY1->DIMPLE not set") ) p1v_enclosure = techGetOrderedSpacingRule( pcTechFile "minEnclosure" "POLY1" "P1P2VIA" ) unless( p1v_enclosure warn("minEnclosure rule for POLY1->P1P2VIA not set") ) p1a2_minSpacing = techGetSpacingRule( pcTechFile "minSpacing" "POLY1" "ANCHOR2" ) unless( p1a2_minSpacing warn("minSpacing rule for POLY1 and ANCHOR2 not set") ) a1_nomWidth = techGetSpacingRule( pcTechFile "nomWidth" "ANCHOR1" ) unless( a1_nomWidth warn("nomWidth rule for ANCHOR1 not set") ) p2p1_minOverlap = techGetOrderedSpacingRule( pcTechFile "minOverlap" "POLY2" "POLY1" ) unless( p2p1_minOverlap warn("minOverlap rule for POLY2->POLY1 not set") ) p2a2_enclosure = techGetOrderedSpacingRule( pcTechFile "minEnclosure" "POLY2" "ANCHOR2" ) unless( p2a2_enclosure warn("minEnclosure rule for POLY2->ANCHOR2 not set") ) a2_nomWidth = techGetSpacingRule( pcTechFile "nomWidth" "ANCHOR2" ) unless( a2_nomWidth warn("nomWidth rule for ANCHOR2 not set") ) v_nomWidth = techGetSpacingRule( pcTechFile "nomWidth" "P1P2VIA" ) unless( v_nomWidth warn("nomWidth rule for P1P2VIA not set") ) d_nomWidth = techGetSpacingRule( pcTechFile "nomWidth" "DIMPLE" ) unless( d_nomWidth warn("nomWIdth rule for DIMPLE not set") ) d_maxSpacing = techGetSpacingRule( pcTechFile "maxSpacing" "DIMPLE" ) unless( d_maxSpacing warn( "maxSpacing rule for DIMPLE not set") ) ; check parameters chamfer = if( (chamfer<0) 0 chamfer ) ; precalculate some distances hub_i = if( (a1_nomWidth+p1a1_enclosure > v_nomWidth+p1v_enclosure ) (a1_nomWidth*1.1+p1a1_enclosure*1.025) (v_nomWidth*1.1+p1v_enclosure)*1.025 ) hub_o = hub_i + p1_minSpacing*1.025 width = ceiling( hub_o + p1_nomWidth ) tmp = sqrt( (arm2+p1_minWidth*0.5)*(arm2+p1_minWidth*0.5) + width*width ) arm2_sp = tmp + p1a2_minSpacing tmp = sqrt( (arm1+p1_minWidth*0.5)*(arm1+p1_minWidth*0.5) + width*width ) arm1_sp = tmp + p1a2_minSpacing ; create central hub for lever dbCreateEllipse( pcCellView "ANCHOR1" list( -(a1_nomWidth*1.1):-(a1_nomWidth*1.1) (a1_nomWidth*1.1):(a1_nomWidth*1.1) ) ) dbCreateEllipse( pcCellView "P1P2VIA" list( -(v_nomWidth*1.1):-(v_nomWidth*1.1) (v_nomWidth*1.1):(v_nomWidth*1.1) ) ) ; create lever block x1 = arm1+p1_minWidth*0.5 x2 = arm1_sp - p1a2_minSpacing x3 = arm1+p1_minWidth*0.5 ax = x1 cx = 2 * ( ax + x3 - 2*x2 ) bx = x3 - ax - cx y1 = -width y2 = 0 y3 = width ay = y1 cy = 2 * ( ay + y3 - 2*y2 ) by = y3 - ay - cy poly = list( ) for( lp 0 10 tmp = lp / 10.0 tmp_x = ax + bx*tmp + cx*tmp*tmp tmp_y = ay + by*tmp + cy*tmp*tmp poly = cons( tmp_x:tmp_y poly ) ) x1 = -arm2 - p1_minWidth*0.5 x2 = -arm2_sp + p1a2_minSpacing x3 = -arm2 - p1_minWidth*0.5 ax = x1 cx = 2 * ( ax + x3 - 2*x2 ) bx = x3 - ax - cx y1 = width y2 = 0 y3 = -width ay = y1 cy = 2 * ( ay + y3 - 2*y2 ) by = y3 - ay - cy for( lp 0 10 tmp = lp / 10.0 tmp_x = ax + bx*tmp + cx*tmp*tmp tmp_y = ay + by*tmp + cy*tmp*tmp poly = cons( tmp_x:tmp_y poly ) ) dbCreatePolygon( pcCellView "POLY1" poly ) dbCreateDonut( pcCellView "HOLE1" 0:0 hub_o hub_i ) ; create poly2 cap tmp = hub_o + p2p1_minOverlap*1.1 dbCreateEllipse( pcCellView, "POLY2" list( -tmp:-tmp tmp:tmp ) ) tmp = hub_o + p2p1_minOverlap*1.1 + p1p2_enclosure*1.1 dbCreateEllipse( pcCellView, "POLY1" list( -tmp:-tmp tmp:tmp ) ) if( (flange_to_end==t) then x1 = -arm2_sp y1 = width - p2a2_enclosure - p1p2_enclosure x2 = -arm2_sp - a2_nomWidth y2 = -y1 dbCreateRect( pcCellView "ANCHOR2" list( x1:y1 x2:y2 ) ) x1 = arm1_sp x2 = arm1_sp + a2_nomWidth dbCreateRect( pcCellView "ANCHOR2" list( x1:y1 x2:y2 ) ) x1 = -arm2_sp - a2_nomWidth - p2a2_enclosure y1 = width - p1p2_enclosure x2 = arm1_sp + a2_nomWidth + p2a2_enclosure y2 = -width + p1p2_enclosure dbCreateRoundRect( pcCellView "POLY2" list( x1:y2 x2:y1 ) chamfer ) ) ; create poly0 ground if( (include_poly0==t) then x1 = -arm2_sp - a2_nomWidth - p2a2_enclosure - p0p2_enclosure y1 = width + p0p1_enclosure x2 = arm1_sp + a2_nomWidth + p2a2_enclosure + p0p2_enclosure y2 = -width - p0p1_enclosure dbCreateRoundRect( pcCellView "POLY0" list( x1:y2 x2:y1 ) chamfer ) x1 = hub_o + p2p1_minOverlap*1.1 + p1p2_enclosure*1.1 + p0p1_enclosure*1.1 dbCreateEllipse( pcCellView "POLY0" list( -x1:-x1 x1:x1 ) ) ) ; create attachment points dbCreateRect( pcCellView "TMP" list( -arm2-p1_minWidth*0.5:width -arm2+p1_minWidth*0.5:width+p1_minWidth ) ) dbCreateRect( pcCellView "TMP" list( arm1-p1_minWidth*0.5:width arm1+p1_minWidth*0.5:width+p1_minWidth ) ) ; create outside dimples x1 = -arm2 - p1_minWidth*0.5 + max(p1d_enclosure,p2p1_minOverlap) y1 = width - p1d_enclosure funcall( lever_CreateDimple pcCellView d_nomWidth (x1 + d_nomWidth *0.5) (y1 - d_nomWidth *0.5) flange_to_end ) funcall( lever_CreateDimple pcCellView d_nomWidth (x1 + d_nomWidth *0.5) (-y1 + d_nomWidth *0.5) flange_to_end ) x1 = arm1 + p1_minWidth*0.5 - max(p1d_enclosure,p2p1_minOverlap) funcall( lever_CreateDimple pcCellView d_nomWidth (x1 - d_nomWidth *0.5) (y1 - d_nomWidth *0.5) flange_to_end ) funcall( lever_CreateDimple pcCellView d_nomWidth (x1 - d_nomWidth *0.5) (-y1 + d_nomWidth *0.5) flange_to_end ) if( (arm2 - p1d_enclosure - max(p1d_enclosure,p2p1_minOverlap) - d_nomWidth *2 - hub_o > d_maxSpacing*0.5) dimple_count = ceiling( (arm2 + p1_minSpacing*0.5 - p1d_enclosure - max(p1d_enclosure,p2p1_minOverlap) - hub_o) / d_maxSpacing ) dimple_count = 0 ) for( lp 1 dimple_count tmp = arm2+p1_minSpacing*0.5 - p1d_enclosure - max(p1d_enclosure,p2p1_minOverlap) - hub_o - d_nomWidth x1 = -arm2 - p1_minWidth*0.5 + p1d_enclosure + lp * tmp / dimple_count y1 = width - p1d_enclosure funcall( lever_CreateDimple pcCellView d_nomWidth x1+d_nomWidth *0.5 y1-d_nomWidth *0.5 flange_to_end ) funcall( lever_CreateDimple pcCellView d_nomWidth x1+d_nomWidth *0.5 -y1+d_nomWidth *0.5 flange_to_end ) ) if( (arm1 - p1d_enclosure - max(p1d_enclosure,p2p1_minOverlap) - d_nomWidth *2 - hub_o > d_maxSpacing*0.5) dimple_count = ceiling( (arm1 + p1_minSpacing*0.5 - p1d_enclosure - max(p1d_enclosure,p2p1_minOverlap) - hub_o) / d_maxSpacing ) dimple_count = 0 ) for( lp 1 dimple_count tmp = ( arm1+p1_minSpacing*0.5 - p1d_enclosure - max(p1d_enclosure,p2p1_minOverlap) - hub_o - d_nomWidth ) x1 = arm1 + p1_minWidth*0.5 - p1d_enclosure - lp * tmp / dimple_count y1 = width - p1d_enclosure funcall( lever_CreateDimple pcCellView d_nomWidth x1-d_nomWidth *0.5 y1-d_nomWidth *0.5 flange_to_end ) funcall( lever_CreateDimple pcCellView d_nomWidth x1-d_nomWidth *0.5 -y1+d_nomWidth *0.5 flange_to_end ) ) ; create stretch handles rodObj = rodGetObj( "" pcCellView ) rodCreateHandle( ?name "arm1_handle" ?rodObj rodObj ?type "point" ?value arm1_sp - p1a2_minSpacing:0 ) rodAssignHandleToParameter( ?parameter "arm1" ?rodObj rodObj ?handleName "arm1_handle" ?displayName "arm1" ?stretchDir "x" ) rodCreateHandle( ?name "arm2_handle" ?rodObj rodObj ?type "point" ?value -arm2_sp + p1a2_minSpacing:0 ) rodAssignHandleToParameter( ?parameter "arm2" ?rodObj rodObj ?handleName "arm2_handle" ?displayName "arm2" ?stretchDir "x" ) ; Create the instNamePrefix property dbReplaceProp( pcCellView "instNamePrefix" "string" "lever" ) ; set version string dbReplaceProp( pcCellView "version" "string" "1.1.1" ) ; body SKILL code returns value t return(t) ) )