I have many layout cells in my library in which I need to do two changes
You have a lot of questions, so I highly recommend you read some Skill documentation. I am including some "untested" skill code. It should be almost ready to run. You should take a look at what I have done and look at some documentation to make sure you understand it. Your description of what you wanted is somewhat vague. It is unclear to me if "xxx", "yyy" and "zzz" are literal, or if wildcard matching is necessary. I assumed wildcards since that is the more complicated scenario. If the names are literal, then a simple == comparison is all that is needed in the check rather than a rexMatchp. Also, if it is literal, then you could skip the rexReplace and rexCompile commands altogether and do simple string assignments.
I broke the code into a routine that runs on a cellview. This makes code testing easier. Run the "changeCell" routine on the current open layout cellview to make sure your labels and cellview are change appropriately. Since the save takes place in the calling routine, you can discard your edits, adjust the code and retest. If you change the value of the badLibrary in the optional arguments to whatever you are referring to in #3, then you can actually run "changeCell()" with no arguments and it will get the current open cellview and use the bad library name that you wish to check for.
;You must define myLibary and badRefLibrary
procedure(doAllCells(myLibrary badRefLibrary) let((libId cv) libId = ddGetObj(myLibrary) foreach(cell libId~>cells~>name when(ddGetObj(myLibrary cell "layout") printf("Working on cell %s\n" cell) cv = dbOpenCellViewByType(myLibrary cell "layout" nil "a") changeCellView(cv badRefLibrary) dbSave(cv) dbClose(cv) ) ) ) ;let) ;proc
procedure(changeCellView(@optional (cv geGetEditCellView()) (badRefLibrary "myBadLibrary")) let((labels newLabel insts cellName newCellName badRefs) labels = setof(x cv~>shapes x~>objType=="label") rexCompile("AB") foreach(lbl labels ;If only replacing labels that are currently m1 then use this when statement when(lbl~>lpp == list("m1" "drawing") newLabel = rexReplace(lbl~>theLabel "CD" 0) lbl~>theLabel = newLabel ) ;OR if wanting to convert the label to m1, use this lbl~>lpp = list("m1" "drawing") )
insts = setof(x cv~>instances x~>libName == "YYYY" && rexMatchp("AB" x~>cellName)) foreach(inst insts cellName = inst~>cellName rexCompile("yyy") newCellName = rexReplace(cellName "zzz" 0) rexCompile("AB") newCellName = rexReplace(newCellName "CD" 0) leReplaceAnyInstMaster(inst "ZZZZ" newCellName nil) )
;You must specify badRefLibrary badRefs = setof(x cv~>instances x~>libName == badRefLibrary) when(badRefs foreach(r badRefs printf("**ERROR: Found reference from library %s in %s\n" badRefLibrary r~>cellName) ) ) ) ;let) ;proc
Thanks Derek. The examples provided by you have provided me clarity to proceed. But I am having some syntax problem while using the foreach ...
procedure(checkWireCell(libname wireCellList) let((outfNameError outfError error libid cellList cellId cell cv inst) libid=ddGetObj(libname) foreach(cell wireCellList if(member("layout" dbAllCellViews(libid cell~>name)) then cv=dbOpenCellViewByType(libname cell~>name "layout" nil "r") if(length(cv~>instances)!=0 foreach(inst cv~>instances if((inst~>libName!=libname && inst~>libName!="ALL_PARTS" ) then fprintf(outfError "\nWARNING: INSTANCE %s Of Cell %s points to a different Library (%s)" inst~>cellName cell~>name inst~>libName) error = 1 ) ; if ) ; foreach ) ; if dbClose(cv) else fprintf(outfError "\nWARNING: Cell %s does not contain a layout view" cell~>name) error = 1 ) ) ) ; let) ; proc
0 am trying the point 3 first, to check whether the instance comes from any other library. I I add the libray names in the if condition, I can get the thing going, but got stuck with the foreach syntax ... it says
*Error* foreach: second argument must be a list - "list"
Your second argument needs to be in this form: list("a" "b" "c") or list(obj1 obj2 obj3)
In your example, wireCellList must be a list of items, even if it is a list of only one item. The second foreach in the code you posted is using cv~>instances which will either be nil (a valid list), or a list of object ids like: list(db:421865904 db:421865868 db:421865832 db:421865796)
If you have a string that has multiple items separated by a space, you can convert this to a list using parseString.
From the error, it looks like you are passing in the string "list". This is what needs to change.
I'd like to make one suggestion about your piece of code. You have two if statements without a then clause. This syntax is perfectly legal, but will only work if there is only one statement within the if. If you add a second statement, it becomes an implied else statement unless you add a then. I find that it is a clearer coding practice to use when if my if clause is not going to have an else.
if(a==1 doThis())if(a==1 then doThis())
All three of the above will do the same thing, but the when statement is the most clear and can avoid the following coding mistake which is difficult to catch:
if(a==1 doThis() doThisAlso())
The above statement is actually an implied if/else. The doThisAlso() will only be called if a does not equal 1, unless you add the then to the syntax. I will use the above statement in my code only if it is clear in the context of what I am doing so I avoid confusing anyone who edits my code.
if(a==1 b = t b = nil)
Notice that it is clear this is two different actions since I wouldn't set b to t and then set it to nil.
Just my opinion.