This document is for the sole use of Firuz Shomahmadov of Nxp Advanced SKILL® Language Programming Course Version IC 6.1.8/ ICADVM 20.1 Lecture Manual Revision 2.0 This document is for the sole use of Firuz Shomahmadov of Nxp © 1990-2023 Cadence Design Systems, Inc. All rights reserved. Printed in the United States of America. Cadence Design Systems, Inc. (Cadence), 2655 Seely Ave., San Jose, CA 95134, USA. Trademarks: Trademarks and service marks of Cadence Design Systems, Inc. (Cadence) contained in this document are attributed to Cadence with the appropriate symbol. For queries regarding Cadence trademarks, contact the corporate legal department at the address shown above or call 1-800-862-4522. All other trademarks are the property of their respective holders. Restricted Print Permission: This publication is protected by copyright and any unauthorized use of this publication may violate copyright, trademark, and other laws. Except as specified in this permission statement, this publication may not be copied, reproduced, modified, published, uploaded, posted, transmitted, or distributed in any way, without prior written permission from Cadence. This statement grants you permission to print one (1) hard copy of this publication subject to the following conditions: The publication may be used solely for personal, informational, and noncommercial purposes; The publication may not be modified in any way; Any copy of the publication or portion thereof must include all original copyright, trademark, and other proprietary notices and this permission statement; and Cadence reserves the right to revoke this authorization at any time, and any such use shall be discontinued immediately upon written notice from Cadence. Disclaimer: Information in this publication is subject to change without notice and does not represent a commitment on the part of Cadence. The information contained herein is the proprietary and confidential information of Cadence or its licensors, and is supplied subject to, and may be used only by Cadence customers in accordance with, a written agreement between Cadence and the customer. Except as may be explicitly set forth in such agreement, Cadence does not make, and expressly disclaims, any representations or warranties as to the completeness, accuracy or usefulness of the information contained in this document. Cadence does not warrant that use of such information will not infringe any third party rights, nor does Cadence assume any liability for damages or costs of any kind that may result from use of such information. Restricted Rights: Use, duplication, or disclosure by the Government is subject to restrictions as set forth in FAR52.227-14 and DFAR252.227-7013 et seq. or its successor. ii January 13, 2023 This document is for the sole use of Firuz Shomahmadov of Nxp Table of Contents Advanced SKILL Language Programming Module 1 About This Course ............................................................................................. 3 Module 2 Introduction to Advanced SKILL ..................................................................... 11 Module 3 Classes and Objects ......................................................................................... 22 Lab 3-1 Creating SKILL++ Classes Lab 3-2 Creating Instances of a Class Module 4 Class Inheritance .............................................................................................. 40 Lab 4-1 Construct Classes: Single Inheritance Module 5 Symbols and Quotes ........................................................................................ 54 Lab 5-1 Using Quotes and Back Quotes in SKILL Commands Lab 5-2 lineread Module 6 Function Parameters ........................................................................................ 62 Lab 6-1 Implementing Your Own Variable Argument Function Module 7 Assert Lab 7-1 Module 8 Scoping ............................................................................................................ 83 Lab 8-1 Examining the Scope of a Variable in SKILL and SKILL++ Module 9 destructuringBind .......................................................................................... 108 Lab 9-1 Destructuring the Lists Using the destructuringBind Expression Module 10 Methods (Primary)........................................................................................... 117 Lab 10-1 Examining the Primary Methods on a Given Class Module 11 Access SKILL Data Structures with setf ....................................................... 131 Lab 11-1 Using the setf Function to Access List Data Module 12 Methods (Intermediate) ................................................................................... 139 Lab 12-1 Using the @before and @after Methods in SKILL++ Code Lab 12-2 Using Lazy Slots Module 13 Introduction to Macros ................................................................................... 157 Lab 13-1 Implementing SKILL Code with Macros Lab 13-2 Implementing Macros and Defclass Cadence Design Systems, Inc. ............................................................................................................ 79 Examining the assert Function Hands-On to Design a Software Test iii This document is for the sole use of Firuz Shomahmadov of Nxp Module 14 Local Functions ...............................................................................................172 Lab 14-1 Implementing Local Functions in the SKILL Programs Module 15 Packages .........................................................................................................181 Lab 15-1 Implementing a Simple Counter Data Type in the SKILL Language Lab 15-2 Implementing a SKILL++ Counter Data Type Lab 15-3 Re-Implementing the Counter Data Type (Optional) Module 16 Indirect Function Calls....................................................................................187 Lab 16-1 Creating Extended Built-In Functions: Rod and Hi Lab 16-2 Implementing the mapappend Function Lab 16-3 Implementing Flatten and Deep-Copy Module 17 Initializing Objects ......................................................................................... 204 Lab 17-1 Exploring Instance Initialization Examples Module 18 Multiple Inheritance........................................................................................ 212 Lab 18-1 Implementing Multiple Class Inheritance in SKILL++ Code Module 19 Methods (Advanced) ...................................................................................... 225 Lab 19-1 Implementing the Methods by Adding Additional Arguments for Extended Capabilities Lab 19-2 Implementing Equivalence Specializers Lab 19-3 Implementing objType Specializers Module 20 Control Flow (Optional) ................................................................................. 239 Module 21 Next Steps ....................................................................................................... 250 iv Cadence Design Systems, Inc. This document is for the sole use of Firuz Shomahmadov of Nxp Advanced SKILL® Language Programming Version IC 6.1.8/ ICADVM 20.1 Estimated time: 3 Days This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 1 This document is for the sole use of Firuz Shomahmadov of Nxp About This Course Module 1 Revision 2.0 Version IC 6.1.8/ ICADVM 20.1 Estimated Time: ● Lecture 15 minutes ● Lab NA This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 3 This document is for the sole use of Firuz Shomahmadov of Nxp Course Prerequisites Before taking this course, you need to have already ● Developed basic SKILL® programs or completed a SKILL Language Programming course ● Used the Virtuoso® Design Environment or completed a Virtuoso Design Environment, Analog Design, or Analog Layout course 4 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 4 This document is for the sole use of Firuz Shomahmadov of Nxp Course Objectives In this course, you ● Apply advanced capabilities of SKILL and SKILL++ ● Write code that is simpler and create fewer bugs ● Create simple and complex macros ● Develop SKILL++ programs using lexical scoping ● Develop SKILL++ programs using the SKILL++ Object System 5 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 5 This document is for the sole use of Firuz Shomahmadov of Nxp Course Agenda ● Introduction to Advanced SKILL ● Classes and Objects ▪ Creating SKILL++ Classes ▪ Creating Instances of a Class ● Class Inheritance ▪ Construct Classes: Single Inheritance ● Symbols and Quotes ▪ Using Quotes and Back Quotes in SKILL Commands ▪ lineread ● Function Parameters ▪ Implementing Your Own Variable Argument Function ● Assert ▪ Examining the assert Function Hands-On to Design a Software Test 6 ● Scoping ▪ Examining the Scope of a Variable in SKILL and SKILL++ ● destructuringBind ▪ Destructuring the Lists Using the destructuringBind Expression ● Methods (Primary) ▪ Examining the Primary Methods on a Given Class ● Access SKILL Data Structures with setf ▪ Using the setf Function to Access List Data ● Methods (Intermediate) ▪ Using the @before and @after Methods in SKILL++ Code ▪ Using Lazy Slots © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 6 This document is for the sole use of Firuz Shomahmadov of Nxp Course Agenda (continued) ● Introduction to Macros ▪ Implementing SKILL Code with Macros ▪ Implementing Macros and Defclass ● Local Functions ▪ Implementing Local Functions in the SKILL Programs ● Packages ● Initializing Objects ▪ Exploring Instance Initialization Examples ● Multiple Inheritance ▪ Implementing Multiple Class Inheritance in SKILL++ Code ● Methods (Advanced) ▪ Implementing a Simple Counter Data Type in the SKILL Language ▪ Implementing the Methods by Adding Additional Arguments for Extended Capabilities ▪ Implementing a SKILL++ Counter Data Type ▪ Implementing Equivalence Specializers ▪ Re-Implementing the Counter Data Type (Optional) ▪ Implementing objType Specializers ● Indirect Function Calls ● Control Flow (Optional) ▪ Creating Extended Built-In Functions: Rod and Hi ▪ Implementing the mapappend Function ▪ Implementing Flatten and Deep-Copy 7 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 7 This document is for the sole use of Firuz Shomahmadov of Nxp Software and Licenses For the software and licenses used in the labs for this course, go to: https://www.cadence.com/en_US/home/training/all-courses/84401.html If there is additional information regarding the specific software, it is detailed in the lab document and/or the README file of the database provided with this course. 8 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 8 This document is for the sole use of Firuz Shomahmadov of Nxp Become Cadence Certified by Earning a Digital Badge Digital badges indicate mastery in a certain technology or skill and give managers and potential employers a way to validate your expertise. ● Cadence Training Services offers digital badges for our popular training courses. ● Your digital badge can be added to your email signature or social media platforms like LinkedIn or Facebook. Benefits of Cadence Certified Digital Badges ● Validate expertise ▪ Expand career opportunities ● Professional credibility ▪ Stand apart from your peers ● For more information, go to www.cadence.com/training or email es_digitalbadge@cadence.com. How do I register to take the exam? ● Log in to our Learning Management System to locate the exam in your transcript. How long will it take to complete the exam? ● Most exams take 45 to 90 minutes to complete. You may retake the exam multiple times to pass the exam. How do I access and use the digital badge? ● After you pass the exam, you get a digital badge and instructions on how to place it on social media sites. How is the digital badge validated? ● Credly validates the digital badge as issued to you by Cadence and includes the details of the criteria you completed to earn the badge. 9 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 9 This document is for the sole use of Firuz Shomahmadov of Nxp Icons Used in This Class Best Practice Problem & Solution 10 Language/ Command Syntax Quick Reference Concept/ Glossary GUI and Command Frequently Asked Questions/ Quiz How To Error Message Throughout this class, we use icons to draw your attention to certain kinds of information. Here are the icons we use, and what they mean. Lab List © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 10 This document is for the sole use of Firuz Shomahmadov of Nxp Introduction to Advanced SKILL® Module 2 Revision 2.0 Version IC 6.1.8/ ICADVM 20.1 Estimated time: ● Lecture 30 minutes ● Lab NA This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 11 This document is for the sole use of Firuz Shomahmadov of Nxp Module Objectives In this module, you ● Compare the working of SKILL and SKILL++ ● Create and load SKILL++ files ● Identify to control the visibility of variables and functions in the SKILL and SKILL++ dialects 12 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 12 This document is for the sole use of Firuz Shomahmadov of Nxp What Is Advanced SKILL? Advanced features of the SKILL Language can be applied to solve complex problems and create code that is easier to reuse and maintain. Some of the advanced features of the SKILL language are: ● SKILL++ ▪ Lexical scoping ▪ Object-oriented system o Classes and methods ● Symbols and Quoting ▪ Treating the language as data ● Macros ▪ Code that writes code 13 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 13 This document is for the sole use of Firuz Shomahmadov of Nxp Things to Know About SKILL++ ● SKILL++ is an extension of SKILL ● SKILL and SKILL++ are two dialects of the same language ● Functions from both environments can be mixed in the same procedure ● Supports lexical scoping ● Private functions and data (encapsulation) ● Object system Both SKILL and SKILL++ have the same syntax but sometimes different semantics. 14 © Cadence Design Systems, Inc. All rights reserved. SKILL++ was developed as an extension of the SKILL language that supplies critical support for the advanced features required to solve complex problems and create code that is easier to reuse and maintain. The improvements include lexically scoped variables and the creation of private functions, as well as a significantly enhanced object system. © Cadence Design Systems, Inc. All rights reserved. 14 This document is for the sole use of Firuz Shomahmadov of Nxp Defining Function in SKILL and SKILL++ procedure(functionName(argument list) ….body….) defun(functionName (argument list) ….body….) defun and procedure are different syntaxes to do the same work. ● Both define the function. ▪ Either can be used, SKILL or SKILL++. o They can be used interchangeably. The other way to define a function: (procedure (functionName argument list) …body…) (defun functionName (argument list) …body….) 15 © Cadence Design Systems, Inc. All rights reserved. Functions are defined in files using commands like procedure or defun. These are the same command using a different syntax and can be used interchangeably in either SKILL or SKILL++. There are other function creation methods, such as lambda, for creating an unnamed function; defglobalfun, for creating global functions in closures; and flet, for creating functions local to another function. We will explore some of these in this class. © Cadence Design Systems, Inc. All rights reserved. 15 This document is for the sole use of Firuz Shomahmadov of Nxp Defining Global Variables in SKILL and SKILL++ defvar(varName expression) (defvar varName expression) Variables are defined the same in both SKILL and SKILL++. ● It creates a new global variable and assigns the value of the expressions. ● Or modifies the value of the global variable. However, because SKILL++ provides lexical scoping, you can also use defvar within a let statement to define a variable for a local environment. For example: let((a b c) defvar(d 23) defglobalfun(myFunc (e) prog1(d d=e)) ) A call to myFunc(45) returns the last value of d and updates d to the arg (45 in this case). So, in this context, a global variable d doesn't exist. 16 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 16 This document is for the sole use of Firuz Shomahmadov of Nxp What Is an Interactive Interface for SKILL and SKILL++? Virtuoso®, when invoked, supports an interactive Read Eval Print Loop (REPL) in which we type an expression. The system parses, compiles, and evaluates according to either SKILL or SKILL++ syntaxes and displays the result. To determine which REPL you are in, type theEnvironment()in the CIW input pane: ● The SKILL interface return nil. ● The SKILL++ interface returns non-nil environment ID. To start a new interactive interface: ● In the CIW input pane, type toplevel( `ils ) → it starts a new SKILL++ REPL interface. ● In the CIW input pane, type toplevel( `il ) → it starts a new SKILL REPL interface. ● If you type resume() →it exits the current REPL. However, initially, when the Virtuoso environment is invoked, the interface will be using SKILL REPL. 17 © Cadence Design Systems, Inc. All rights reserved. A common technique for debugging functions and methods is to copy and paste from an editor into the CIW. This may be a problem because the function may be redefined in the wrong environment. The command top-level changes the environment between SKILL and SKILL++. Note: If you paste code in the CIW while another function is executing, the environment will be determined by the executing function. © Cadence Design Systems, Inc. All rights reserved. 17 This document is for the sole use of Firuz Shomahmadov of Nxp How to Write SKILL and SKILL++ Code Functions defined in a file with a .ils extension will be defined in the SKILL++ dialect. Functions in any file with a different extension are loaded in SKILL. SKILL 1. Loading the source file ▪ load( "mySKILLFile.il" ) 2. Executing a function ▪ mySKILLfunction( “An argument string” 8) SKILL++ 1. Loading the source file ▪ load( "myAdvSKILLFile.ils" ) 2. Executing a function ▪ myAdvSKILLfunction( “Another string” 12 ) 18 Note: The files with .ilse extension are encrypted SKILL++ files. © Cadence Design Systems, Inc. All rights reserved. The suffix of the source file containing the function definition determines the dialect. Once the source file is loaded, the function can be called/invoked with the same syntax, independent of the dialect at the call site: the procedure name followed by the values for the arguments, the required arguments, and the optional or keyed arguments. Functions defined in a file with a .ils extension will be defined in the SKILL++ dialect. Functions in any file with a different extension are loaded in SKILL. If you want to encrypt your .ils file, use the below command: encrypt("mycode.ils" "mycode.ilse") © Cadence Design Systems, Inc. All rights reserved. 18 This document is for the sole use of Firuz Shomahmadov of Nxp How to Reference Variables Between SKILL and SKILL++ Normally, each SKILL++ global variable is bound to the function slot of the symbol with the same name. In this way, SKILL and SKILL++ can share functions transparently. 1. For a one-time reference of a variable ▪ inScheme( varName ) o Sets a SKILL++ global variable, regardless if it appears in the SKILL file. ▪ inSKILL( varName ) o Sets a SKILL global variable, regardless if it appears in the SKILL++ file. 2. To create a permanent binding of the variable ▪ importSkillVar( varName ) o Creates a permanent binding between a SKILL and SKILL++ (Scheme) global variable. o Updates the variable in one environment and allows for immediate access to the value of the variable in the other environment. 19 © Cadence Design Systems, Inc. All rights reserved. The Scheme is the original standard that SKILL++ is based upon. SKILL originated from a small LISP, Franz LISP, which pre-dates both Common LISP and Scheme. In the early 1990s, there was an organization called the CAD Framework Initiative (CFI), which had the goal of establishing a Scheme as the customization language for CAD tools. The "ils" mode of SKILL was designed to provide Scheme-like features within SKILL without losing compatibility. There was initially a more aggressive Scheme implementation too, but SKILL++ was implemented to adopt some of the concepts without the strict language compatibility with the Scheme. You can define functions in a different environment than the one defined by the source file suffix using the functions inSkill and inScheme. In a SKILL++ source file (.ils), the block defined in the inSkill statement will be executed in the SKILL environment. Global variables and function definitions will be defined in the SKILL environment with the environment’s dynamic scoping. In a SKILL source file (.il), the block defined within the inScheme statement will be executed in the SKILL++ environment. These commands allow you to mix SKILL and SKILL++ function definitions in the same source file. © Cadence Design Systems, Inc. All rights reserved. 19 This document is for the sole use of Firuz Shomahmadov of Nxp What Is Function and Variable Visibility? Since SKILL and SKILL++ functions share the namespace, two functions cannot have the same name, even if one is SKILL and the other is SKILL++. Functions ● A SKILL function may call a SKILL++ function by name. ● A SKILL++ function may call a SKILL function by name. ▪ Consequently, a SKILL function cannot have the same name as a SKILL++ function. Variables ● A SKILL function cannot see SKILL++ global variables. ● A SKILL++ function cannot see SKILL global variables. ● A SKILL++ function sees SKILL and SKILL++ functions as global variables. ▪ Consequently, a SKILL variable may have the same name as a SKILL++ variable. ▪ A SKILL function cannot have the same name as a different SKILL++ global variable. 20 © Cadence Design Systems, Inc. All rights reserved. Since SKILL and SKILL++ functions share the namespace, two functions cannot have the same name, even if one is SKILL and the other is SKILL++. If there are multiple definitions of the same function, the last one overrides any previously defined one, which is the one accessible by the user. © Cadence Design Systems, Inc. All rights reserved. 20 This document is for the sole use of Firuz Shomahmadov of Nxp Module Summary In this module, you ● Compared the working of SKILL and SKILL++ ● Created and loaded SKILL++ files ● Identified how to control the visibility of variables and functions in the SKILL and SKILL++ dialects 21 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 21 This document is for the sole use of Firuz Shomahmadov of Nxp Classes and Objects Module 3 Revision 2.0 Version IC 6.1.8/ ICADVM 20.1 Estimated time: ● Lecture 30 minutes ● Lab 30 minutes This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 22 This document is for the sole use of Firuz Shomahmadov of Nxp Module Objectives In this module, you ● Create a basic class and a SKILL++ instance of that class ● Analyze slots ▪ Define a slot ▪ Set and get the data in the slots ▪ Combine slots in hierarchical classes ● Query the information about an object instance 23 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 23 This document is for the sole use of Firuz Shomahmadov of Nxp What Are Classes and Instances in Object-Oriented Programming? A class is a template definition of the methods and variables in a particular kind of object. Slots An object is an instance of a class. States params params constants rules Methods Behaviors Classes are blueprints that contain: Instances are objects: ● Slots: Data defining the class. ● States: Current settings of the data in the instance. ● Methods: Actions taking place on the data. ● Behaviors: How the methods perform on the instance. 24 © Cadence Design Systems, Inc. All rights reserved. A principle feature of the Object-Oriented programming paradigm (OO) is the class. The simplest explanation of a class, found in the Java® tutorial at java.sun.com, is that a class is the blueprint of a container. The container has data that defines the class and procedures that act on that data. SKILL++, like lisp, calls the data slots and the methods of the procedure. An object is an instance of a class. Multiple instances can be made of the same class, each creating a new object. Each instance of the same class has its own set of slots and methods. Unlike procedures, there can be multiple methods with the same name, each operating on a different class of objects. The first argument of a method is the object on which the method should operate. This determines which method is used. Images inspired by java.sun.com Java Tutorial. © Cadence Design Systems, Inc. All rights reserved. 24 This document is for the sole use of Firuz Shomahmadov of Nxp What Are Classes and Instances in Object-Oriented Programming? (continued) Class ● Multiple instances can be made of the same class: Slots ▪ Each creates a new object with its own set of slots and methods. ● There can be multiple methods with the same name, each operating on a different class of objects. Methods ● The methods are defined separately from the class, unlike languages like C++ and Python. ● The arguments of a method are the objects on which the method should operate. These determine which method is used. States params Behaviors States params constants constants rules rules Behaviors Instances 25 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 25 This document is for the sole use of Firuz Shomahmadov of Nxp Class Declaration in SKILL++ with defclass (Space required) (defclass className ({list of superClasses}) ({list of slot descriptors})) ● Classes must be declared before an instance of the class (the object) is created. ● Slot descriptors indicate data the instances will contain. ● Slot descriptors are also inherited from the superclasses. 26 (defclass library () ((name) (owner))) © Cadence Design Systems, Inc. All rights reserved. Classes are declared using the defclass command. The class has a name. The class can have a superclass or a list of superclasses from which it inherits slots and access to methods. If the class has no declared superclasses, it is a subclass of the SKILL++ standard object. The slots of the class are also declared. These add to the slots of any superclasses. An instance of the class will have the slots of the current class and the slots of any superclasses. © Cadence Design Systems, Inc. All rights reserved. 26 This document is for the sole use of Firuz Shomahmadov of Nxp Creating an Instance of a Class instanceName = makeInstance('className) ● Instances of a class are created with makeInstance. (defclass library () ((name)(owner))) ● Each instance has an identity independent of the other instances. instA = makeInstance('library ) Has slots: name, owner ● Slot values are instance-specific. instB = makeInstance('library ) Has slots: name, owner These slots are independent of instA. 27 © Cadence Design Systems, Inc. All rights reserved. A class must be defined before any objects can be made of it. The object is also called an instance of the class. The function makeInstance is used to create an instance of the class. Each instance is independent of other instances of the same class. They have the same structure, but the slots are associated with the instance and can have different values. Note: The name of the class is passed into makeInstance as a quoted symbol. © Cadence Design Systems, Inc. All rights reserved. 27 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Specifying Class Slots and Their Default Value Class Definition Class name superClasses (defclass library () ( (name) (owner) (path) ) ) Slot descriptors Slot Name Value Class name \*slotUnbound\* library owner \*slotUnbound\* library path \*slotUnbound\* library Object Instantiation instA = makeInstance('library ) instA → An object of class library 28 © Cadence Design Systems, Inc. All rights reserved. The class definition specifies the slots and places to store information on an instance of the class. The makeInstance function creates an instance of the class that contains the slots and their values. By default, the slot values are unbound, returning the value \* slotUnbound \*. These slots are associated with this instance and are independent of any other instance of the class. © Cadence Design Systems, Inc. All rights reserved. 28 This document is for the sole use of Firuz Shomahmadov of Nxp Functions to Find the Information of the Class and Its Objects To find the class of an instance: ● classOf( instA ) ▪ Returns the class of the instance. ● className( classOf( instA ) ) ▪ Returns the print name of the class of the instance. ● classp( object 'class ) ▪ Returns t if the object is an instance of the class or a subclass. To find a class ID: ● class = findClass( 'library ) ▪ Returns the class. ● In SKILL++, a class is a first-class object, unlike Java®, C++, and so on. 29 © Cadence Design Systems, Inc. All rights reserved. The class of an instance can be found using the command classOf. This returns the class of the instance. This can be turned into a print name using className. A straightforward test for the object of a class uses classp to determine if the object is an instance of the class or one of its subclasses. findClass returns the pointer to the class defined by the symbol name. © Cadence Design Systems, Inc. All rights reserved. 29 This document is for the sole use of Firuz Shomahmadov of Nxp Setting and Retrieving the Slot Value putprop( instName "newname" 'slotName ) → writes value to the slot. get( instName 'slotName) → reads values from the slot. The slots are accessed on an instance of the class. ● The putprop function writes the value to the slot. putprop( instA "newValue" 'path ) ● The get function reads the value from the slot. value = get( instA 'path ) To print the contents of an object (can be useful while debugging the code): instA->? → Lists the slots of the instance. instA->?? → Lists the slots and values of the instance. ● The dashed arrow (->) is an accessor for the slot – both read and write. instA->path = list( "lnx18a" "/usr1/libs" ) instA->path → ( "lnx18a" "/usr1/libs" ) 30 © Cadence Design Systems, Inc. All rights reserved. Direct access to the slots is provided by the get/getq, putprop/putpropq, and the dash-arrow (->). Accessing the slots directly is discouraged in object-oriented programming. Accessor methods are usually used so that the underlying data structure can be modified without requiring changes to programs that use the slots. Note that the whole value of the slot is accessed. If a new value is assigned to the slot, the value in the slot is completely replaced. If the slot contains a table, the complete table is retrieved or replaced using these accessors. Complex data structures require the class developer to create a method for accessing the substructure of the slot value. © Cadence Design Systems, Inc. All rights reserved. 30 This document is for the sole use of Firuz Shomahmadov of Nxp Use @initform to Assign a Default Value to a Slot The slot can be assigned a default value when the instance is created by specifying the initial value in the slot declaration using the @initform keyword. ● Initialize simple values in the slots with @initform. ● The initform can be a fixed value or an expression. ▪ The expression is evaluated when the instance is created. ▪ The return value of the expression is assigned to the slot. (defclass library () ( ( name ) ( owner @initform getShellEnvVar("user")) ( path @initform getWorkingDir() ) )) instA = makeInstance( 'library ) In the example: ● The owner slot is assigned the value of the shell environment variable “USER”. Slot Name Value Class name \*slotUnbound\* library ● The slot path is assigned to the current working directory where Virtuoso® was launched. owner “john” library path “/libs” library Note: When the default value of one slot depends on the value given for another slot, @initform cannot be used. 31 © Cadence Design Systems, Inc. All rights reserved. The slot can be assigned a default value when the instance is created by specifying the initial value in the slot declaration using the @initform keyword. The expression that follows the keyword can be a value or an expression that evaluates into a value. The expression is evaluated when the instance is created, and the value is stored in the slot on the class. The expressions were evaluated when the instance was created; changing the USER variable or the working directory will not affect that instance, but the new values will be stored in the slots of new instances. Note: The name slot is unbound as it has no @initform. © Cadence Design Systems, Inc. All rights reserved. 31 This document is for the sole use of Firuz Shomahmadov of Nxp Use @initarg to Initialize a Slot Value The slot values can be assigned when the instance is created through the @initarg keyword. ● @initarg acts like a keyed argument. ● @initarg and @initform can be used together. ▪ @initform supplies the default value. ▪ @initarg overrides the value. In the example: ● The initial values of the Owner and Path slots are overridden using the @initarg keyword. ● The argument is used as a keyed argument to the makeInstance function, and that value is assigned to the slot. 32 (defclass library () ( ( name @initarg libName ) ( owner @initform getShellEnvVar("user") @initarg owner ) ( path @initform getWorkingDir() @initarg path ))) instA = makeInstance( 'library ?libName "skillClassLib" ?path "/libs/training" ) Slot Name Value Class name "skillClassLib" library path “/libs/training” library © Cadence Design Systems, Inc. All rights reserved. The slot values can be assigned when the instance is created through the @initarg keyword. The argument is used like a keyed argument for a procedure when the instance is created. The argument is preceded by a question mark, and the value is the next expression following the key. The value is assigned to the slot. Note: The argument does not have to have the same name as the slot. When the instance is created, the initial values of the slots can be overridden using @initarg in the slot generation. The argument is used as a keyed argument to the makeInstance function. The value is assigned to the slot. If the slot is not initialized using @initarg, it retains the value of its @initform. If that was not specified, the value of the slot is \*slotUnbound\*. © Cadence Design Systems, Inc. All rights reserved. 32 This document is for the sole use of Firuz Shomahmadov of Nxp Things to Remember: @initarg ● The initarg does not have to be the same as the slot name. makeInstance won't complain! (defclass C () ((slot1 @initarg s1))) (makeInstance 'C ?slot1 42) ; ?slot1 42 has NO EFFECT ● Two slots might have the same initarg. (defclass square_matrix (matrix) ((rows @initarg rank) (cols @initarg rank))) ● With inheritance, slots can acquire multiple initargs. ● A common error is typing @initarg when you mean @initform. ● The syntax is: ▪ @initarg X ▪ Not @initarg 'X and not @initarg ?X 33 © Cadence Design Systems, Inc. All rights reserved. In the example above (makeInstance 'C ?slot1 42), ?slot1 42 has no effect because class C does not have a slot with @initarg slot1. This is a source of error because makeInstance will not issue an error or a warning. The programmer might think the slot has been initialized to 42, but it most assuredly has not been. For the class square_matrix, a call to (makeInstance 'square_matrix ?rank (get_rank)) will call the function, get_rank, exactly once and with initialize two slots, rows, and cols, with its return value. The class square_matrix inherits from the matrix. We have not seen the inheritance yet but will shortly. If the matrix class has a slot descriptor (row @initarg row), then square_matrix has two initargs for the row slot. A call to makeInstance can use ?rows or ?rank. This is a source of error because it would, unfortunately, be possible to create a square_matrix with ?rows 3 ?cols 4, which would not be square. You would need to check for this somewhere else, such as the initializeInstance @after method, which we will see later also. © Cadence Design Systems, Inc. All rights reserved. 33 This document is for the sole use of Firuz Shomahmadov of Nxp Setting and Getting Slot Values: Direct Access setSlotValue(instName 'slotName "value" ) → sets the slot value slotValue( instName 'slotName ) → gets the slot value ● Set the slot value using setSlotValue. ● Get the slot value using slotValue. ● -> (the dashed arrow) is the accessor for the slots on a class instance. ● Accessing the slots directly can make your classes harder to maintain. ● Other functions set and retrieve the value directly. ● Changing slot names requires you to find all places where the slots are accessed and fix them. setSlotValue( instA 'name "testLib2" ) value1 = slotValue( instA 'name ) setSlotValue( instA 'owner "Your Name Here" ) => "testLib2" value2 = slotValue( instA 'owner) => "Your Name Here" 34 © Cadence Design Systems, Inc. All rights reserved. Besides the dashed arrow, the functions setSlotValue and slotValue are used to access the slots once an instance has been created. These provide direct access to the slot values. The argument is the slot name itself, not the @initarg. The slot values are overwritten when using setSlotValue directly. This does not support any merging of the values into a data structure like a defstruct or a table. The use of the dashed arrow or the functions setSlotValue and slotValue require the programmer to know the name of the slot to be accessed. If the class changes and the slot is renamed, then the programs that use that access will have to be updated. © Cadence Design Systems, Inc. All rights reserved. 34 This document is for the sole use of Firuz Shomahmadov of Nxp What Are Slot Reader and Writer Methods? The @reader and @writer slot options are used for reading and writing slots when the classes are defined. ● Automatic read/write methods are created when a class is declared. ● Slots are usually accessed through methods. ● Underlying data structure is abstracted through methods. ● Generic methods are available for slots. ▪ @reader reads the data from a slot. (defclass library () (( name @initarg libName @reader getLibName @writer setLibName) ( owner @initform getShellEnvVar( "user" ) @initarg owner @reader getOwner @writer setOwner) ( path @initform getWorkingDir() @initarg path @reader getPath @writer setPath))) ▪ @writer writes the data to the slot. 35 © Cadence Design Systems, Inc. All rights reserved. Accessing slots directly or using slotValue and setSlotValue is discouraged in object-oriented programming if the underlying data structure, such as the slot name, changes, and any program that directly accesses the slot has to be updated to the new structure. Reader and writer methods are used to access the slot data, abstracting away the dependency on the name of the slot. The methods are declared using @reader and @writer keywords, followed by the name of the method. Methods are like procedures, but they are called with the first argument, being the instance of a class to work on. The method to execute that matches the name and the class of the object is found, and that method is executed. We will explore the methods some more in a future module. © Cadence Design Systems, Inc. All rights reserved. 35 This document is for the sole use of Firuz Shomahmadov of Nxp What Happens When a Class Is Redefined? When a class is redefined and the instance is updated, a property list is created that captures the slot names and values of all the discarded slots with values in the original instance. ● During program development, you will redefine your class several times before you get it right. ● If there are instances of the class in virtual memory, SKILL++ will examine them and potentially update them. ▪ Obsolete instance slots may get removed. ▪ New instance slots may get added. ▪ New Uninitialized slots may get initialized. ▪ Old Uninitialized slots remain uninitialized, even if an @initform was added. ● You can customize this behavior using the generic function updateInstanceForRedefinedClass. You will look more at the generic functions and redefining classes in the coming modules. 36 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 36 This document is for the sole use of Firuz Shomahmadov of Nxp defclass Summary ● Classes are blueprints/templates for creating structured containers. ● An object is created by instantiating the class. ● Slots are the place where data is stored. Slots: ▪ Have names. ▪ May have a default value (@initform). ▪ May have an initialization argument (@initarg). ▪ May have reader and writer methods (@reader and @writer). ● Each object has a copy of the slots defined for the class. ▪ Slot values can be different for each instance. ● Class redefinition is allowed and is robust. 37 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 37 This document is for the sole use of Firuz Shomahmadov of Nxp Module Summary In this module, you ● Created a basic class and a SKILL++ instance of that class ● Analyzed @initform, @initargs keywords ● Identified different slot value accessing methods 38 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 38 This document is for the sole use of Firuz Shomahmadov of Nxp Labs Lab 3-1 Creating SKILL++ Classes Lab 3-2 Creating Instances of a Class 39 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 39 This document is for the sole use of Firuz Shomahmadov of Nxp Class Inheritance Module 4 Revision 2.0 Version IC 6.1.8/ ICADVM 20.1 Estimated time: ● Lecture 15 minutes ● Lab 30 minutes This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 40 This document is for the sole use of Firuz Shomahmadov of Nxp Module Objectives In this module, you ● Create classes ● Create a class hierarchy with subclasses and superclasses ● Examine how slots in classes inherit from other classes 41 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 41 This document is for the sole use of Firuz Shomahmadov of Nxp What Is Class Inheritance? Superclass will provide a separate copy of properties to each object of a subclass such that data shared by different objects do not have to be recreated. Characteristics: Class ● Inheritance allows for the reuse of classes. library Least specific ● Shared slots do not have to be repeated. The diagram shown illustrates: ● userLib is a subclass of a library. userLib ● library is a superclass of userLib. ● designLib is a subclass of userLib. ● userLib is a superclass of designLib. ● library is a superclass of designLib. 42 designLib Most specific © Cadence Design Systems, Inc. All rights reserved. The superclasses are further used to specify the class of the object. This can be done by adding new slots or modifying the initial data in slots inherited from the superclass. The userLib class inherits the slots from the library class, and the designLib class inherits the slots of the userLib class, including the classes of the library class. A subclass is said to be more specific than its superclasses, and a superclass is less specific than its subclasses. © Cadence Design Systems, Inc. All rights reserved. 42 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Class Inheritance ● refLib class is a subclass of the library class. ● userLib class is a subclass of the library class. library ● They share the same template for instance creation. ▪ Name ▪ Owner ▪ Path refLib userLib designLib 43 © Cadence Design Systems, Inc. All rights reserved. The advantage of using classes is that template data that is shared by different objects do not have to be recreated. In the example, the refLib and the userLib share the common superclass of the library, each inheriting the slots from that class. If changes were made to the superclass, it would be reflected in both the refLib and userLib classes. © Cadence Design Systems, Inc. All rights reserved. 43 This document is for the sole use of Firuz Shomahmadov of Nxp Creating a Class Hierarchy library (defclass library () (( name @initarg libName … ) ( owner @initform getShellEnvVar( "user" ) … ) ( path @initform getWorkingDir() @initarg path … ) ) ) userLib (defclass userLib ( library ) ;superClass (( users @initform makeTable( "users" nil) @initarg users @reader getUsers @writer setUsers) ) ) Class designLib 44 (defclass designLib ( userLib ) (( users @initform pcoGetProjUsers() @initarg designers ) ( project @initform pcoGetProjectId() @initarg project ) ) User functions ) called when creating the object. © Cadence Design Systems, Inc. All rights reserved. Classes are created using defclass. To create a subclass, specify the name of the superclass when declaring the class. Specify the additional slots for the class and change the initialization of values by creating the instance of the class using the make Instance command. This creates an instance of the class with all the slots from that class and the superclasses. Set the value of the slots using the @initarg from the slot declaration. When a designLib object is created, the slots users and project are initialized by executing the user functions pcoGetProjUsers and pcoGetProjectId and assigning the return value to the slots. © Cadence Design Systems, Inc. All rights reserved. 44 This document is for the sole use of Firuz Shomahmadov of Nxp Finding Class Inheritance Information ● Is a class1 a subclass of class2? subclassp( classOf( inst1 ) classOf( inst2 ) ) => t/nil ● Find the class hierarchy of an instance. superclassesOf( classOf( instA ) ) subclassesOf( classOf( instA ) ) 45 © Cadence Design Systems, Inc. All rights reserved. SKILL++ keeps track of the class inheritance as classes are built. The commands superclassesOf and subclassesOf return the hierarchy as a list of classes with single inheritance. This list is easy to predict. These tools become more useful when analyzing multiple inheritance. © Cadence Design Systems, Inc. All rights reserved. 45 This document is for the sole use of Firuz Shomahmadov of Nxp makeInstance: Instantiation of a Class Inheritance For instantiating a class, we can use the makeInstance function. ● makeInstance function creates an object of the class. ▪ Inherits from library and userLib classes. ● That object can inherit all the slots of the classes in the design hierarchy. ● No need to create any intermediate instances. curProject = makeInstance( 'designLib ?libName "A2_43b" ?designers pcoGetProjUsers( "MEMS" )) 46 © Cadence Design Systems, Inc. All rights reserved. Using makeInstance, a new instance of the designLib class is created. This new object inherits all the slots of the designLib, userLib, and library classes. The userLib and library classes did not have objects allocated for the classes. These are abstract classes that usually are not used in creating objects directly, although they can be used that way. The user’s slot was assigned its value through the @initarg ?designers. This argument was added with the designLib class and can be used in addition to the original @initarg ?users. © Cadence Design Systems, Inc. All rights reserved. 46 This document is for the sole use of Firuz Shomahmadov of Nxp What Is Slot Inheritance? Classes inherit the slots of their superclasses. If the subclass declares a new slot, that slot is added to the class at that level of the class hierarchy. If the subclass declares a new slot: ● The slot is included in the subclass. ● The superclass does not know about the new slot. If the subclass declares a slot that exists in a superclass: ● @initform – the value is inherited from the most specific class. ▪ Overrides value from the superclass. ● @initarg – the argument is added to the initargs in the superclasses. ▪ Merged with initargs from subclasses. 47 © Cadence Design Systems, Inc. All rights reserved. The superclasses of the class do not have access to the data in that slot. If the subclass declares a slot that already exists from a superclass, the initial value is set by the most specific class that declares the slot with an @initform. The initialization argument set by @initarg is added to the existing initargs inherited from the superclasses. © Cadence Design Systems, Inc. All rights reserved. 47 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Class Slot Inheritance for library Class (defclass library () (( name @initarg libName … ) ( owner @initform getShellEnvVar( "user" ) … ) ( path @initform getWorkingDir() @initarg path … ))) 48 Slot Name Value @initarg Created By name \*slotUnbound\* libName library owner "tedp" owner library path “/libs" path library © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 48 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Class Slot Inheritance for userLib Class Class name superClass (defclass userLib ( library ) (( users @initform makeTable( "users" nil) @initarg users @reader getUsers @writer setUsers) )) 49 Slot Name Value @initarg Created By name \*slotUnbound\* libName library owner "tedp" owner library path “/libs" path library users table users userLib Additional Slots © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 49 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Class Slot Inheritance for designLib Class Class name superClass (defclass designLib ( userLib ) ( ( users @initform pcoGetProjUsers() @initarg designers ) ( project @initform pcoGetProjectId() @initarg project ) )) New @initarg Additional Slot Slot Name Value @initarg Created By name 'slotUnbound libName library owner "tedp" owner library path “/libs" path library Table of project users users users designers userLib and designLib “projectld" project designLib project 50 New Initial Value © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 50 This document is for the sole use of Firuz Shomahmadov of Nxp Summary of Class and Inheritance Classes are templates for data containers: ● Slots hold data for the class. ● They identify the data that represents the class. Classes inherit from superclasses: ● Slot information is inherited. ● New slots and new values are assigned by the class. ● Each subclass is more specialized than the superclasses. ● Multiple classes can inherit from the same superclasses. Objects are instances of classes: ● Each object is unique. ● Slot values are not shared. 51 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 51 This document is for the sole use of Firuz Shomahmadov of Nxp Module Summary In this module, you ● Created classes that inherit from other classes ● Examined how initialization is affected by superclasses 52 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 52 This document is for the sole use of Firuz Shomahmadov of Nxp Lab Lab 4-1 Construct Classes: Single Inheritance 53 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 53 This document is for the sole use of Firuz Shomahmadov of Nxp Symbols and Quotes Module 5 Revision 2.0 Version IC 6.1.8/ ICADVM 20.1 Estimated time: ● Lecture 15 minutes ● Lab 30 minutes This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 54 This document is for the sole use of Firuz Shomahmadov of Nxp Module Objectives In this module, you ● Examine the role of symbols in SKILL® ● Examine how to use the quote and back quote in SKILL 55 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 55 This document is for the sole use of Firuz Shomahmadov of Nxp What Are Symbols? In an expression, value is referenced by using the symbol name without modifiers such as a quote, back quote, or surrounded by double quotes. A single quote or back quote refers to the symbol itself. Surrounding the string with double quotes makes it a string. Symbols commonly implement names in SKILL. Quoted names are symbols. ● Without double quotes: abc ● In evaluated positions, refer to an explicit symbol using a quote. ● Double quotes make it a string: "abc" Symbols are often used as variables to store values. abc = 4 + 5 'abc → the symbol abc ● Refer to the value using the symbol name alone. abc → 63 abc * 7 56 © Cadence Design Systems, Inc. All rights reserved. SKILL++ makes more use of symbols than SKILL. In SKILL (and SKILL++), a symbol is a name, starting with an alphabetic character or an underscore (_) without double quotes. Most often, symbols are used as variables to hold values. In an expression, value is referenced by using the symbol name without modifiers such as a quote, back quote, or surrounded by double quotes. A single quote or back quote refers to the symbol itself. Surrounding the string with double quotes makes it a string. © Cadence Design Systems, Inc. All rights reserved. 56 This document is for the sole use of Firuz Shomahmadov of Nxp Uses of Symbols Name of a Function ● procedure( myFunction ▪ Creates a symbol, myFunction, that holds the reference to the procedure body Name of a Variable ● A variable can hold a value ▪ myVar = 7 ● It can hold a function (lambda expression) ▪ comparePoint = lambda( ( x y) list(min(minX x) min(minY y))) Name of a Key ● Disembodied property list ▪ '( nil one 1 two "two" three 9/3) ● Table ▪ layerTable['poly ] Name of a Class ● defclass( myClass ▪ Creates a symbol, 'myClass, that holds the class description 57 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 57 This document is for the sole use of Firuz Shomahmadov of Nxp What Are Quote and Back Quote? Quote and Back quote both operate similarly. All the elements in a quoted list are literal. If a symbol or expression in the list is preceded by a comma, the symbol or expression is evaluated, and the value replaces the expression in the list. '(quote): `(back quote): Everything that follows a quote is taken literally. Like the quote until it encounters a comma. The expression following the comma is evaluated. myList = myList = `( a "b" ,(3 + 5) ,@list(1 2 3 4) ) '( a "b" (3 + 5) ) car( myList ) → a ; the symbol a caddr( myList ) → the list ( 3 + 5 ) car( myList ) caddr( myList ) → 8 myList 58 → a ; the symbol a → ( a "b" 8 1 2 3 4 ) © Cadence Design Systems, Inc. All rights reserved. Two very important operators are the quote and the back quote. They both operate similarly – all the elements in a quoted list are literal. If the element is a symbol, it remains a symbol. An expression in the list is returned as a list. The back quote operates similarly to the quote but with added capabilities. If a symbol or expression in the list is preceded by a comma, the symbol or expression is evaluated, and the value replaces the expression in the list. If the value or expression is preceded by a comma followed by the at sign (@), the expression is evaluated, and the list returned is flattened into the containing list. © Cadence Design Systems, Inc. All rights reserved. 58 This document is for the sole use of Firuz Shomahmadov of Nxp Quote and Back Quote: Comparison of Runtime Allocation '(quote): Does no runtime allocation. `(back quote): Does runtime allocation. (defun listQ () '(1 2 3)) (defun listBQ () `(1 2 3)) (listQ) → (1 2 3) (eq (listQ) (listQ)) → t (listBQ) → (1 2 3) (eq (listBQ) (listBQ)) → nil 59 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 59 This document is for the sole use of Firuz Shomahmadov of Nxp Module Summary In this module, you ● Identified the role of Symbols in SKILL and SKILL++ ● Compared the usage of quote and back quote in SKILL and SKILL++ 60 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 60 This document is for the sole use of Firuz Shomahmadov of Nxp Labs Lab 5-1 Using Quotes and Back Quotes in SKILL Commands Lab 5-2 lineread 61 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 61 This document is for the sole use of Firuz Shomahmadov of Nxp Function Parameters Module 6 Revision 2.0 Version IC 6.1.8/ ICADVM 20.1 Estimated time: ● Lecture 30 minutes ● Lab 30 minutes This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 62 This document is for the sole use of Firuz Shomahmadov of Nxp Module Objectives In this module, you ● Work with the arglist function ● Develop simple type templates ● Examine the following arguments: ▪ @key ▪ @optional ▪ @rest 63 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 63 This document is for the sole use of Firuz Shomahmadov of Nxp Required Arguments for defun and procedure defun( name ( argument_list ) body… ) => s_funcName procedure( name( argument_list ) body… ) => s_funcName ● defun and procedure are equivalent functions. ● All the arguments must be given at the call site, and the order matters. procedure( offset( pt dx dy) list( xCoord( pt ) + dx yCoord( pt ) + dy )) 64 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 64 This document is for the sole use of Firuz Shomahmadov of Nxp The arglist Function Returns the Parameter List arglist( g_function ) => l_argumentList arglist is a built-in function that returns the parameter list of user-defined functions or built-in functions. Examples ● arglist( 'cons ) => (g_general l_list) ● procedure( offset( pt dx dy ) list( xCoord( pt ) + dx yCoord( pt ) + dy )) arglist( 'offset ) => (pt dx dy) 65 ; built-in ; user-defined © Cadence Design Systems, Inc. All rights reserved. Actually, (arglist ‘cons) returns a different value containing a type template. Type templates are seen later in this section. Sometimes, type templates for built-in SKILL® functions are wrong or misleading. © Cadence Design Systems, Inc. All rights reserved. 65 This document is for the sole use of Firuz Shomahmadov of Nxp The Optional Type Template Defines the Parameter Data Types procedure( name( argument_list [ t_typeTemplate ] ) body… ) => s_funcName If the last item in the parameter list is a string, it is taken to be a type template. When the function is invoked, the supplied values must match the specified types. For example: The last template character repeats implicitly. For example: procedure( offset1( pt dx dy "lnn" ) list( xCoord( pt ) + dx yCoord( pt ) + dy ))) In this case, the “n” template type is repeated for the dy and dz variables. ● Match the individual characters of the type template "lnn" with the respective function parameters(pt dx dy). ● Variable dx has type template "n" – declares dx as a number ▪ Variable pt has type template "l" – declares pt as a list ▪ Variable dx has type template "n" – declares dx as a number ▪ Variable dy has type template "n" – declares dy as a number procedure( offset2( pt dx dy dz "ln" ) ...) ● Variable pt has type template "l" – declares pt as a list ● Variable dy has type template "n" – declares dy as a number ● Variable dz has type template "n" – declares dz as a number ● offset1( '(0 0) '(1 2) '(3 4) ) → *Error* offset: argument #2 should be a number (type template = "lnn") - (1 2) 66 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 66 This document is for the sole use of Firuz Shomahmadov of Nxp Type Template Characters Some available type template characters include: 67 Type Template Characters Specify Column Header Type Template Characters Specify Column Header "l" list "R" rodObject "n" number "S" symbol or string "p" port "U" binary or funobj "s" symbol "a" array "t" string "d" dbobject "u" symbol, funobj, or cons "f" flonum "w" wtype "g" t – general – unrestricted "x" fixnum © Cadence Design Systems, Inc. All rights reserved. There are many available type template characters. The SKILL programmer is not allowed to define new ones. The most common ones are listed here. Use "g" to specify generic (meaning unrestricted type). © Cadence Design Systems, Inc. All rights reserved. 67 This document is for the sole use of Firuz Shomahmadov of Nxp Optional Arguments procedure( name( [argument_list] [@optional argument_list] ) body… ) => s_funcName @optional designates optional arguments. ● procedure( offset( pt dx @optional dy ) list( xCoord( pt ) + dx yCoord( pt ) + or( dy dx ))) Default expressions are supported. ● procedure( offset( pt dx @optional (dy 0) ) list( xCoord( pt ) + dx yCoord( pt ) + dy ))) Defaults may reference parameters to the left in SKILL++ but not in SKILL®. ● procedure( offset( pt @optional (dx 0) (dy dx) ) list( xCoord( pt ) + dx yCoord( pt ) + dy ))) 68 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 68 This document is for the sole use of Firuz Shomahmadov of Nxp Optional Arguments: Order of Arguments The order at the call site is important. Examples ● procedure( offset( pt @optional (dx 0) (dy dx) ) list( xCoord( pt ) + dx yCoord( pt ) + dy )) ● offset( '(3 5) ) => (3 5) ● offset( '(3 5) .1 ) => (3.1 5) ● offset( '(3 5) .1 .2 ) => (3.1 5.2) The call site cannot specify dy without also specifying dx. Use @key to avoid this limitation. 69 © Cadence Design Systems, Inc. All rights reserved. This feature, where an optional argument can refer to a prior optional argument, only works with SKILL++. So this code must be in a .iLS file or specify top-level ‘ils prior to testing the code in the CIW. © Cadence Design Systems, Inc. All rights reserved. 69 This document is for the sole use of Firuz Shomahmadov of Nxp Keyword Arguments procedure( name( [argument_list…] [@key argument_list…] ) body… ) => s_funcName ● @key designates keyword arguments. ● Default values are supported. ● Defaults may reference parameters to the left. procedure( offset( pt @key (dx 0)(dy dx) ) list( xCoord( pt ) + dx yCoord( pt ) + dy ) ) ● Optionally, specify the keyword by beginning it with ? at the call site. For example: The order of keyword parameters at the call site is less important. Examples ● offset( '(3 5)) => (3 5) ● offset( '(3 5) ?dx .1 ) => (3.1 5) ● offset( '(3 5) ?dy .2 ) => (3 5.2) ● offset( '(3 5) ?dy .2 ?dx .1 ) => (3.1 5.2) ● offset( '(3 5) ?dx .1 ?dy .2 ) => (3.1 5.2) offset( '(3 5) ?dy .2 ?dx .1) 70 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 70 This document is for the sole use of Firuz Shomahmadov of Nxp Keyword Argument Evaluation The default is not evaluated if the keyword is given at the call site. ● procedure( myDbOpen( lib cell view @key (mode "r") (cellViewType (when view=="layout“ "maskLayout“))) dbOpenCellViewByType( lib cell view cellViewType) ) ● myDbOpen( "des" "cel3" "layout“ ) ● myDbOpen( "des" "cel3" "layout" ?cellViewType nil ) ● myDbOpen( "des" "cel3" "sch" ?cellViewType "schematic“ ) 71 © Cadence Design Systems, Inc. All rights reserved. You may distinguish the case of a keyword given explicitly as nil vs. a keyword not given. In the above example, myDbOpen called with ?cellViewType nil behaves differently than myDbOpen called without ?cellViewType. The analogous behavior also applies to @optional defaults; the default expression is not evaluated if a corresponding argument is provided at the call site. © Cadence Design Systems, Inc. All rights reserved. 71 This document is for the sole use of Firuz Shomahmadov of Nxp Rest Arguments procedure( name( [argument_list…] [@rest arg] ) body… ) => s_funcName ● @rest designates rest/var-args arguments. Examples ● Default values are not supported. ● procedure( offset( pt @rest delta ) list( nil 'pt pt 'delta delta)) ▪ procedure( offset(pt @rest delta) list( nil 'pt pt 'delta delta)) ● Only one @rest parameter is allowed. ● All otherwise unconsumed arguments are combined in a list. ● offset( '(3 5) ) => (nil pt (3 5) delta nil) ● offset( '(3 5) .1 ) => (nil pt (3 5) delta (0.1)) ● offset( '(3 5) .1 .2 ) => (nil pt (3 5) delta (0.1 0.2)) 72 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 72 This document is for the sole use of Firuz Shomahmadov of Nxp Combining Optional Arguments ● @key and @optional cannot be used together. ● @key, @optional, and @rest may be used with or without the required arguments. ● @rest may be used with @optional or @key. Examples ● procedure( offset( pt @key dx (dy 0) @rest delta ) list( nil 'dx dx 'dy dy 'delta delta)) ● offset( '(3 5) ?dx .1 ?dy .2 ) => (nil dx 0.1 dy 0.2 delta nil) ● offset( '(3 5) ?dx .1 ?dz .3 ) => (nil dx 0.1 dy 0 delta (?dz 0.3)) ● offset( '(3 5) ?dx .1 ?dz .3 ?dy .2 ?dx .4 ) => (nil dx 0.1 dy 0.2 delta (?dz 0.3 ?dx 0.4)) 73 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 73 This document is for the sole use of Firuz Shomahmadov of Nxp Functions That Can Use Optional Arguments @optional, @key, and @rest arguments may be used in the following function definitions: ● defun ● procedure ● defmacro ● defgeneric ● lambda ● defglobalfun 74 © Cadence Design Systems, Inc. All rights reserved. There are many different ways to define functions in SKILL++. These will be seen later. However, any function may make use of optional arguments. © Cadence Design Systems, Inc. All rights reserved. 74 This document is for the sole use of Firuz Shomahmadov of Nxp Required Arguments and Keyword Parameters procedure( name( arg_list ) body… ) procedure( name( @key arg_list ) body… ) The dbCreateLabel function has eight required arguments, most of which we do not normally care about. This is difficult to use. An alternative is to write myCreateLabel that accepts @key parameters and internally calls dbCreateLabel with the eight positional arguments. dbCreateLabel( d_cellView txl_layer l_point t_label t_just t_orient t_font x_height ) procedure( myCreateLabel(cellView @key (layer "text" ) (xy '(0 0) ) theLabel (justify "lowerLeft" ) (orient "R0" ) (font "stick" ) (height 1.0 ) "dglttttn" ) dbCreateLabel( cellView layer xy theLabel justify orient font height ) ) 75 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 75 This document is for the sole use of Firuz Shomahmadov of Nxp Required Arguments and Keyword Parameters (continued) ● We have to call dbCreateLabel like this and provide all the required parameters: (dbCreateLabel cvId "text" 5:6 "some text" "lowerLeft" "R0" "stick" 1.0) ● We can then call myCreateLabel like this: (myCreateLabel cvId ?theLabel "some text“ ?xy 5:6)) ● Thus, we can specify the arguments we care about and take the defaults for the ones we do not care about. ● And we do not have to remember the meaning of the 6th, 7th, and 8th, arguments of dbCreateLabel. 76 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 76 This document is for the sole use of Firuz Shomahmadov of Nxp Module Summary In this module, you ● Worked with the arglist function ● Developed simple type templates ● Examined the following arguments: ▪ @key ▪ @optional ▪ @rest 77 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 77 This document is for the sole use of Firuz Shomahmadov of Nxp Lab Lab 6-1 Implementing Your Own Variable Argument Function 78 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 78 This document is for the sole use of Firuz Shomahmadov of Nxp Assert Module 7 Revision 2.0 Version IC 6.1.8/ ICADVM 20.1 Estimated time: ● Lecture 15 minutes ● Lab 30 minutes This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 79 This document is for the sole use of Firuz Shomahmadov of Nxp Module Objective In this module, you ● Examine how assert is used in software testing 80 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 80 This document is for the sole use of Firuz Shomahmadov of Nxp What Is an Assert Function? A new macro named an assert function is used to create software tests. It tests the return value of the expression but does not test the side effects. If the expression returns nil: Examples ● An error is thrown, the error message is printed, and the expression is returned. ● Test for the return value → assert( myFunction( 12.3 "abc" ) ) If the expression returns non-nil: ● Test for equivalence → assert( 2 + 5 == 7 ) ● Assert does not throw an error, and nil is returned. ● Test for nil → assert( !myOddp( 8 ) "Value is even." ) The syntax for the assert function is: assert( expression {"error string“}) 81 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 81 This document is for the sole use of Firuz Shomahmadov of Nxp Lab Lab 7-1 Examining the assert Function Hands-On to Design a Software Test 82 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 82 This document is for the sole use of Firuz Shomahmadov of Nxp Scoping Module 8 Revision 2.0 Version IC 6.1.8/ ICADVM 20.1 Estimated time: ● Lecture 1 hour ● Lab 1 hour This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 83 This document is for the sole use of Firuz Shomahmadov of Nxp Module Objectives In this module, you ● Determine the scope of a variable ● Compare binding and assignment ● Hide data with SKILL++ closures ● Examine the following constructs ▪ prog1 ▪ prog2 ▪ progn ▪ let ▪ letseq ▪ letrec 84 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 84 This document is for the sole use of Firuz Shomahmadov of Nxp What Is the Scope of a Variable? The scope of a variable is where the variable has a particular value. As a procedure or method calls another method, the scope determines if the variable is available in the nested context and if the value is local to the current context or comes from a higher-level context. ● When a variable is "in scope", it is visible. ● Global variables are always in scope, except when they are shadowed by a local variable. ● The scope of a local variable defined by the let statement is the body of the let, where it comes from. ▪ The variable can be seen by code within the ()s. ▪ In SKILL++, when the let statement to which the variable was bound completed, the variable leaves the scope and is de-referenced. ● SKILL++ is easy: the scope is determined by the text. ▪ Lexical scope ▪ Easy to understand ▪ Easy to debug 85 © Cadence Design Systems, Inc. All rights reserved. The scope of a variable is where the variable has a particular value. As a procedure or method calls another method, the scope determines if the variable is available in the nested context and if the value is local to the current context or comes from a higher-level context. This will also determine which contexts are affected when the value is changed in the nested context. Dynamic scoping is supported by SKILL and can introduce errors when a variable value change unanticipated. SKILL++ supports lexical scoping, which helps minimize these bugs. When a variable is in scope, its value is available through the variable. If the variable is out of scope, the variable no longer refers to that value. When the let statement to which the variable was bound is completed, the variable leaves the scope and is de-referenced. © Cadence Design Systems, Inc. All rights reserved. 85 This document is for the sole use of Firuz Shomahmadov of Nxp Binding Variables in a let Statement let( ( var1 var2 … ) body ) ● The let statement creates a block structure in code. Example code using let statement: ▪ Groups expressions in the body. ● It declares local variables. ▪ Body of let is the scope of the local variables. ▪ Declared in the first form of the let statement. let( ( ( x 2 ) ( y 3 ) ) x*y ) ; let => 6 ▪ Body statements are executed. ● The scope of the variable is determined if the code is executed in the SKILL® environment or the SKILL++ environment. ● Return value is the return value of the last executed expression in the statement. 86 © Cadence Design Systems, Inc. All rights reserved. The let statement creates a block of code with local variables. The first form after the let declares the variables. These are local variables that exist only for the scope of the let statement. Once all the expressions in the body are completed, the local variables are de-referenced (SKILL forgets about them), and the memory is marked for reuse (garbage collected). The code in the body can use these local variables; the scoping of the variable will be determined if it is executing in the SKILL environment or the SKILL++ environment. The expressions in the body are executed, and the value of the last expression is returned as the result of the let statement. © Cadence Design Systems, Inc. All rights reserved. 86 This document is for the sole use of Firuz Shomahmadov of Nxp Binding Variables in a let Statement (continued) ● Variables have values. The binding of variables is done when they are declared. let(((layer "Metal" )…) ) let(( layer ) … ) If no value is given, the default is nil. ● Variables bound in the let may be reassigned within the let body. let(( rectId ) … rectId = dbCreateRect(cvId layer bBox) ) 87 © Cadence Design Systems, Inc. All rights reserved. The environment in which the let statement is created determines the scope of the variables. If the let is defined in a .il file, it is loaded in the SKILL environment. If it is defined in a .ils file, it is loaded in the SKILL++ environment. The variables are declared in the let statement. The variables become local variables to the let statement. If this statement is in a nested SKILL let, a new declaration of an existing variable hides the existing variable, and changes are only reflected in the local variable. A variable can be declared with or without a bound value. If the variable is declared as just a name, the variable is assigned the value nil. The value is bound by declaring a list, the variable, and its binding value or expression. The binding value can be static or maybe an expression that is computed each time the block is executed. © Cadence Design Systems, Inc. All rights reserved. 87 This document is for the sole use of Firuz Shomahmadov of Nxp Binding Variables in a let Statement (continued) ● Binding values can be computed expressions. let((( cvId deGetEditCell())) …body…) ● All initial values are computed before any variable becomes bound. ● Any variable exterior to the let may be used in the computed expressions, including: ▪ Parameters to the procedure/defun ▪ Variables declared in an outer let ▪ Global variables ● Variables may be shadowed by reusing the name. let(((a 100)) let(((a 200)) ;;; here a is 200 ... ) ;; here a is 100 ) 88 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 88 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Assigning and Binding Variables in a let Statement procedure( SKcreateLib( libName ) let((libDir (directory getWorkingDir()) (project SKgetProj( libName)) Binding ) ; BODY sprintf( libDir "%s/%s/%s" Assignment directory project libName ) SKgetLib( libDir libName ) ) ; let ) ; procedure libDir is set based on the directory and project defined in the let statement. 89 © Cadence Design Systems, Inc. All rights reserved. In the above procedure definition, the single argument is the variable libName. The let statement declares three variables, libDir which is not given an initial value and default to nil, the variable directory bound to the value returned by getWorkingDir, and the variable project bound to the value returned from SKgetProj called with the value bound to the procedure argument variable libName. libDir is assigned a value using sprintf based on the values of directory, project, and libName. This value could not be computed during the variable binding because it refers to other variables whose values are not yet bound when it would be computed. There are other forms, letseq and letrec, that enable this. The value of the variables is now initialized in the scope of the let statement. When the last expression in the let statement SKgetLib( libName) is executed, and its return value becomes the return value for the let statement. © Cadence Design Systems, Inc. All rights reserved. 89 This document is for the sole use of Firuz Shomahmadov of Nxp Binding Variables in a letseq Statement (Enhanced Binding) letseq(((s_var1 initExp1) (s_var2 initExp2)……) body ) ● A letseq expression can be used in both SKILL and SKILL++ modes. ● The bindings and evaluations are performed sequentially from left to right. ● It controls the order of evaluation of initialization expressions. ● This form is equivalent to a corresponding sequence of nested let expressions. Nested let expression: let( ( ( x 1 ) ) let( ( ( y x+1 ) ) y ) ) Normal let statement: let((a 5) (b a+10) (c b/a)) 90 letseq((a 5) (b a+10) (c b/a)) … … ) Output: y is 2 letseq expression: *error* ) Output: c is 3 © Cadence Design Systems, Inc. All rights reserved. The block declaration letseq compute and bind the initial values of the declared variables sequentially. This allows later variables to reference variables previously bound in the declaration. © Cadence Design Systems, Inc. All rights reserved. 90 This document is for the sole use of Firuz Shomahmadov of Nxp Binding Variables in a letrec Statement (Enhanced Binding) letrec(((s_var1 initExp1) (s_var2 initExp2)……) body ) ● A letrec expression can be used in SKILL++ mode only. ● All the bindings are in effect while their initial values are being computed. ● Thus, it allows mutually recursive definitions. ● Use letrec when you want to declare recursive local functions. ▪ For example, a lambda expression satisfies this restriction because its body gets executed only when called, not when it’s defined. ● Each initialization expression can refer to the other local variables being declared when ▪ Each initialized expression must be executable without accessing any of those variables. ● This form is equivalent to a corresponding recursive let expression. 91 © Cadence Design Systems, Inc. All rights reserved. The block declaration letrec initializes the bindings before computing the values (neat trick), so the order does not have to be sequential, and the computation can be recursive. © Cadence Design Systems, Inc. All rights reserved. 91 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Code for Binding Variables in a letrec Statement This code shows the usage of the letrec statement in the SKILL++ environment. letrec( ( ;;; variable list ( f lambda( ( n ) if( n > 0 then n*f(n-1) else 1 ) ; if ) ; lambda ) ; f ) ; variable list f( 5 ) ) ; letrec => 120 92 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 92 This document is for the sole use of Firuz Shomahmadov of Nxp What Is Lexical Scoping? A program refers to a local variable only within certain textually defined regions of the program. This region is called the lexical scope of the variable. SKILL++ uses lexical scoping. ● If a function refers to non-local variables, they must be global variables. ▪ Outside of a function, local variables are inaccessible. ● Whenever a variable is introduced (by procedure, let, and so on), a "box" is created. ● Dereferencing a variable fetches the value in the box. let( (number) ● Setting variable changes the value in the box. ● You find the right box by looking up the text of the program. procedure( counter1 number Some global variable named number procedure( counter2 number ● If you do not find a box that way, use the global box. ● Procedures not defined in the box cannot see the variable. 93 © Cadence Design Systems, Inc. All rights reserved. SKILL++ uses lexically scoped variables. Access to the variable is limited to the scope in which it is defined, such as within a let statement. Functions defined within the lexical scope can access the variable, reading and setting the value. Functions defined outside the lexical scope cannot refer to the scoped variable; using the symbol name will refer to another variable that may be defined as a global symbol. The variable number in function counter1 is the variable defined in the enclosing let statement. Because counter2 is defined outside the let, counter2 would never access the variable from the lexical scope but rather access a global variable named number. This is true even if counter2 is called from within counter1. Variables declared inside a let in a function only exist within that function and cannot be accessed by any other function. © Cadence Design Systems, Inc. All rights reserved. 93 This document is for the sole use of Firuz Shomahmadov of Nxp Lexical Scoping Is Easy: Example It is easy to know which variable is referenced. Examples toplevel 'ils ; sets evaluation to SKILL++ mode x = 15 procedure( GetX() x ; this is the global x ) procedure( LocalX() let( (x) x=random(); this is the x from the let x ; this is the x from the let GetX() ; returns global x (15) with lexical scoping ; but returns local x (random) with dynamic scoping )) LocalX() => 15 94 © Cadence Design Systems, Inc. All rights reserved. In the GetX procedure, the variable x refers to a global variable and would return 15. In the LocalX procedure, x is scoped within the procedure by its declaration in the let statement. In lexical scoping, the value of x would not be available to any function called by LocalX; if LocalX called GetX, the value returned by GetX would be 15 and not the value from LocalX. © Cadence Design Systems, Inc. All rights reserved. 94 This document is for the sole use of Firuz Shomahmadov of Nxp Dynamic Scoping Is Different and Difficult: Example With dynamic scoping, it is difficult to know which variable is referenced. Examples toplevel 'il ; sets evaluation to SKILL mode (default) x = 15 procedure( GetX() x ; this may be the global x, or some other x ) GetX() => 15 ; returns 15 procedure( LocalX() let( ( (x 1) ) GetX() ; returns 1 ) ) LocalX() => 1 ; returns 1 95 © Cadence Design Systems, Inc. All rights reserved. In the GetX procedure, the variable x refers to a global variable and would return 15. In the LocalX procedure, x is scoped within the procedure by its declaration in the let statement. In lexical scoping, the value of x would not be available to any function called by LocalX; if LocalX called GetX, the value returned by GetX would be 15 and not the value from LocalX. © Cadence Design Systems, Inc. All rights reserved. 95 This document is for the sole use of Firuz Shomahmadov of Nxp What Are Closures? A closure is a function object containing one or more free variables bound to data. Lexical scoping makes closures possible. ● In SKILL, dynamic scoping prevents effective use of closures, but a SKILL++ application can use closures as software building blocks. ● let defines the box of a closure. ● Functions defined in the closure can access the variables defined in the let. let( ((secret 42)) defglobalfun( Guess (guess) if( guess == secret printf( "You guessed right!\n") printf( "So sorry, try again\n")) ) ; defglobalfun ) ; let ● You can use this "textual lookup" to hide data. 96 © Cadence Design Systems, Inc. All rights reserved. Here, we are declaring a variable secret, a value inside the scope of the let statement. It also defines a global function Guess within the lexical scope. The function can access the variable when it is executed, but functions defined outside the scope of the closure cannot see this value. The defglobalfun statement defines a named function within a closure that is available globally. © Cadence Design Systems, Inc. All rights reserved. 96 This document is for the sole use of Firuz Shomahmadov of Nxp Closure Example: Counter and ResetCounter ● The function Counter increments the count variable. ● ResetCounter resets the value of the counter. ● No other functions can see or modify the count variable. let( ((count 0)) defglobalfun( Counter () count++) defglobalfun( ResetCounter (@optional ( new 0 )) count = new) ) ; let 97 © Cadence Design Systems, Inc. All rights reserved. This closure creates a counter by declaring a lexical scoped variable count and declaring two functions that modify the variable. No other functions can access that variable. © Cadence Design Systems, Inc. All rights reserved. 97 This document is for the sole use of Firuz Shomahmadov of Nxp Closure Example: Multiple Counter ● We can also have more than one counter. procedure( MakeCounter(count) procedure( counter() ; a local function count++ ) ; count argument from MakeCounter counter ; return the new function ) toplevel ‘ils counter1 = MakeCounter(10) counter2 = MakeCounter(100) counter1() → 10 counter2() → 100 counter1() → 11 counter2() → 101 98 © Cadence Design Systems, Inc. All rights reserved. This is a more complex counter-implementation. The procedure MakeCounter declares a local function and returns the function object. The variable count is scoped within the function object. The functions counter1 and counter2 are created from MakeCounter. Executing them (using either the infix or prefix format (C or Lisp)) returns the value of their independent lexical scoped variable count. © Cadence Design Systems, Inc. All rights reserved. 98 This document is for the sole use of Firuz Shomahmadov of Nxp Other Block Statements: progn – Creates a Single Block progn( sequence of statements ) or { sequence of statements } ● Simple means of grouping statements where multiple statements are required, but only one is expected. ● Evaluates expressions from left to right and returns the value of the last expression. ● Useful for grouping a sequence of expressions into a single expression. ● Short-hand notation for progn: curly braces ({ }). 99 © Cadence Design Systems, Inc. All rights reserved. There are some commands that will only accept a single expression. In order to use multiple expressions, they can be gathered into a progn block. The block statement progn groups multiple expressions into one expression. The block consists only of expressions; there is no provision for local variables (use let if you need local variables). Braces {} can be used to delimit the block instead of using the progn command. © Cadence Design Systems, Inc. All rights reserved. 99 This document is for the sole use of Firuz Shomahmadov of Nxp progn Examples Example 1 progn( 100 Example 2 { println("expr 1") println("expr 1") println("expr 2") println("expr 2") ) 5 + 4 } O/P → "expr 1" O/P → "expr 1" "expr 2" "expr 2" nil 9 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 100 This document is for the sole use of Firuz Shomahmadov of Nxp Other Block Statements: prog1 and prog2 prog1( g_exp1 [g_exp2..] ) prog2( g_exp1 g_exp2 [g_exp3..] ) => value of g_exp1 => value of g_exp2 ● The arguments may be any SKILL expression. ● The arguments may be any SKILL expression. ● Evaluates expressions from left to right and returns the value of the first expression. ● Evaluates expressions from left to right and returns the value of the second expression. ● No block variables are allowed. ● No block variables are allowed. prog2( prog1( x = 5 x = 12 y = 7 ) y = 10 z = 8 ) => 5 => 10 101 © Cadence Design Systems, Inc. All rights reserved. Although not used much, prog1 and prog2 are very useful block statements. Often a block computes the return value and has to continue processing before the block is completed. Using a let statement, the return value would be captured in a local variable, and its value would be returned at the end of the block. With prog1 and prog2, the local variable would be unnecessary. © Cadence Design Systems, Inc. All rights reserved. 101 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Block Structure for SKILL Testing Create an assert with blocks of code to set up the test, execute the test, and then cleanup after the test. The prog2 returns the results of the test block. assert( prog2( ; Return the value of the 2nd expression { ; Setup block start cvId = deGetEditCellView() numInsts = cvId~>anyInstCount } ; Setup block end { ; Test block start TrPlaceInstances( "testPcell" 3) cvId~>anyInstCount == numInsts + 3 } ; Test block end – return t or nil { ; Cleanup block dbRefreshCellView() } ; End of cleanup block ) ; prog2 "Wrong number of instances!" ; Error message 102 ) © Cadence Design Systems, Inc. All rights reserved. The assert function is useful for testing your procedures. It will evaluate the expression and then if the result is nil, cause an error. assert( 1 == 2 ) => causes an error This use of assert is a complete test that includes a setup blockl and uses prog2 and progn to create a test case that includes a setup block, the assertion test, and a cleanup block. The value tested by assert is the return value of the prog2, the return value of the second expression. This is the test block. It will return nil or non-nil value. The cleanup block will execute after the test block, and then the prog2 will return the value from the test block to assert. This test structure works like this: ▪ Set up conditions for the test (Start block) ▪ Execute the code and test the results (Test block) ▪ Cleanup afterward (Cleanup block) If the test block returns nil, the assert generates an error and prints the error message; if the return value is a non-nil value, the assert command finishes without an error. © Cadence Design Systems, Inc. All rights reserved. 102 This document is for the sole use of Firuz Shomahmadov of Nxp Example: prog1 with Dynamic Scoping let(((nullport outfile( "/dev/null"))) prog1( let(((errport nullport)) errset(1/0 t) ; get info from the error port 20*50 ) close(nullport) ) ) Note: You can use dynamicLet() in SKILL++ code to give you dynamic scoping. 103 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 103 This document is for the sole use of Firuz Shomahmadov of Nxp Quick Reference Guide: Scoping SKILL: Dynamic Scoping ● Local variables can be accessed and changed by any function that gets called while executing the let. ● Dynamic variables cease to exist once the let returns. SKILL++: Lexical Scoping ● Only functions within the text of the let can see the variables. ● Dynamic scoping available via inSkill function. 104 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 104 This document is for the sole use of Firuz Shomahmadov of Nxp Quick Reference Guide: Block Statements Block Statements let( ( variable bindings) body ) letseq( ( variable bindings ) body ) letrec( ( variable bindings ) body ) Remarks Variable bindings can initialize a variable. ● Variables are bound sequentially. ● Use the values in subsequent bindings. ● Variables are bound recursively. ● Use with recursive or out of order bindings. progn( statements ) or { statements } Gathers multiple statements into a single statement. 105 prog1( statements ) Returns first expression values. prog2( statements ) Returns second expression values. © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 105 This document is for the sole use of Firuz Shomahmadov of Nxp Quick Reference Guide: Closures ● Protect data and interface functions in a closure. ● Internal variables can only be accessed by the internal functions. ● Interface functions are exported to external variables. ▪ Use the variables as functions to access the closure data. ● Changes in the internal data format do not affect the interfaces. ▪ Updates without causing maintenance problems. 106 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 106 This document is for the sole use of Firuz Shomahmadov of Nxp Lab Lab 8-1 Examining the Scope of a Variable in SKILL and SKILL++ 107 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 107 This document is for the sole use of Firuz Shomahmadov of Nxp destructuringBind Module 9 Revision 2.0 Version IC 6.1.8/ ICADVM 20.1 Estimated time: ● Lecture 15 minutes ● Lab 15 minutes This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 108 This document is for the sole use of Firuz Shomahmadov of Nxp Module Objectives In this module, you ● Examine how destructuringBind simplifies your code ● Extract/destructure data from hierarchical lists ● Write readable code to destructure complex structures 109 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 109 This document is for the sole use of Firuz Shomahmadov of Nxp What Is destructuringBind? destructuringBind enables you to bind values to variables in a list. It simplifies the code. ● The old way is to use a let or procedure statement and then append the lists to the variables and print the variables. ● The scope of the variables depends on the environment in which the destructuringBind statement is evaluated. 110 Old way: Destructuring: let((first second third) first = car( list1 ) second = cadr( list1 ) third = caddr( list1 ) println( first ) println( second ) println( third ) ) destructuringBind( ( first second third ) list1 println( first ) println( second ) println( third ) ) © Cadence Design Systems, Inc. All rights reserved. Functions or expressions often return lists that have to be taken apart and assigned to variables used in equations and other statements. destructuringBind is a macro that assigns the values in a list to a set of variables that are then used as local variables in the statements in the body of the statement. The scope of the variables depends on whether the destructuringBind statement is evaluated in a SKILL® procedure, where it is dynamically scoped, or a SKILL++ procedure, where it is lexically scoped. © Cadence Design Systems, Inc. All rights reserved. 110 This document is for the sole use of Firuz Shomahmadov of Nxp destructuringBind Syntax destructuringBind( (list of variables) expression body.. ) destructuringBind ● Evaluates the expression. Variables are local to the body. Expression is evaluated and returns a list. ● Binds the returned list values to the variables. ● Executes the body expression with the variables as local variables. ● Returns the return value of the last expression evaluated. destructuringBind( ( list of variables ) expression body expressions… ) masterId = destructuringBind( (lib cell view @optional viewType) parseString( master "/" ) dbOpenCellViewByType( lib cell view viewType "r" )) 111 © Cadence Design Systems, Inc. All rights reserved. destructuringBind operates by evaluating the expression which returns a list. The elements of the list are then assigned to the variables in the list of variables argument. These variables are then treated as local variables during the evaluation of the body statements. The return value of that last expression evaluated is returned from the destructuringBind statement. The example code assigns the results of the parseString to the variables lib, cell, view, and viewType, which are used by the dbOpenCellViewByType command. When the destructuringBind block exits, the value returned by dbOpenCellViewByType is assigned to the variable masterId. The variables lib, cell, view, and viewType are out of scope when the block exits. © Cadence Design Systems, Inc. All rights reserved. 111 This document is for the sole use of Firuz Shomahmadov of Nxp destructuringBind: Examples ● Destructure a list from a database query: figId~>bBox return value: (( 0.0 0.0 ) ( 0.125 0.175)) destructuringBind( ( llPoint urPoint ) figId~>bBox dbCreateRect( cvId implantLayer list( rodAddToPoint( llPoint -iodx:-iody) rodAddToPoint( urPoint iodx:iody)) ) ) ● Destructure the return value of a method or procedure: destructuringBind( ( metalShape diffShape nodeId ) MyCreateCutRegion( device cvId terminal cutRegionParams )) MyTagPinShape( device metalShape ) MyTagShape( device nodeId "currentNode" ) ) 112 © Cadence Design Systems, Inc. All rights reserved. destructuringBind simplifies coding because it automatically assigns the elements of a list to variables that can then be used in the body statement. These variables are local and do not have to be declared in an enclosing let or prog statement. In the first statement, the bounding box is destructured into the variables llPoint and urPoint. These variables are used in the scope of the destructuringBind statement as local variables. pcoCreateCutRegion is a user function that creates a contact region of a top and bottom layer filled with cut shapes. It returns three arguments, the top shape, the bottom shape, and the fig group of all the shapes. These are assigned to the three arguments to the destructuringBind and are local variables for the rest of the expression. © Cadence Design Systems, Inc. All rights reserved. 112 This document is for the sole use of Firuz Shomahmadov of Nxp destructuringBind: Complex Bindings figId~>bBox return value: (( 0.0 0.0 ) ( .125 .175) ) Destructuring supports complex binding: destructuringBind( ( (llx lly) (urx ury) ) figId~>bBox minX = min( minX llx ) minY = min( minY lly ) maxX = max( maxX urx ) maxY = max( maxY ury ) ) ● The bBox is destructed into the four variables. ● The format for the variable list matches the return value. 113 © Cadence Design Systems, Inc. All rights reserved. In this statement value returned by the expression figId~>bBox is a bounding box in the format: list( list( x y) list( x y) ). This value is destructured into the four variables: llx, lly, urx, and ury. The format of the variable list is the same as the return value. Note that on the previous slide, the return value was destructed into two points matching the format of the list of variables. © Cadence Design Systems, Inc. All rights reserved. 113 This document is for the sole use of Firuz Shomahmadov of Nxp destructuringBind: Optional Bindings Returned value: ( 0.03 0.4 3 ) ● If the length of the returned value varies, include @optional variables. destructuringBind( ( length width @optional (fingers 1)) MyCalcSizes( device ) … ) ● Use @rest to capture the rest of the list. destructuringBind( ( length width @rest others) MyCalcSizes( device ) … ) 114 © Cadence Design Systems, Inc. All rights reserved. Expressions can return values that vary in length. If the returned value is to be used, it can be captured with an optional variable using @optional. The optional variables are assigned by the position of the value in the list. A default value for the optional variable can be specified. If the return value will vary greatly and only the first values in the list are used, capture the rest of the list using an @rest variable. After the first values in the return list are destructured into their variables, the rest of the values are assigned as a list to the @rest variable. The @rest variable can be included with @optional and @key variables as well. © Cadence Design Systems, Inc. All rights reserved. 114 This document is for the sole use of Firuz Shomahmadov of Nxp destructuringBind: Keyed Variable Bindings ● Values can be captured in keyed variables. ● Variables are declared as @key variables. ● Return value includes the variable keys (using ? prefix). ● Use @rest to capture extra keys. ● Non-keyed variables require values. destructuringBind(( nodeId @key metalShape diffShape @rest _ignore ) MyGenNextNode( device "source" ) … ) MyGenNextNode return value: => ( nodeId ?metalShape dbId ?diffShape dbId … ) 115 © Cadence Design Systems, Inc. All rights reserved. Keyed variables identify the values returned by the expression. The variable is defined in the @key statement; the expression returns the value list that includes a key/value pair: the variable prefixed with a question mark and the value. If the list does not include a value for one of the keys, the variable is assigned its default value if one is declared or nil. Declaration: arg1 Return value: ?arg1 "value" The return value can contain non-keyed values preceding the keyed values. The variable list must be formatted appropriately. A value is assigned to these non-keyed variables in the return list. If there are additional keyed arguments that may not be returned by the function, use the @rest statement to capture these arguments. © Cadence Design Systems, Inc. All rights reserved. 115 This document is for the sole use of Firuz Shomahmadov of Nxp Lab Lab 9-1 Destructuring the Lists Using the destructuringBind Expression 116 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 116 This document is for the sole use of Firuz Shomahmadov of Nxp Methods (Primary) Module 10 Revision 2.0 Version IC 6.1.8/ ICADVM 20.1 Estimated time: ● Lecture 45 minutes ● Lab 30 minutes This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 117 This document is for the sole use of Firuz Shomahmadov of Nxp Module Objectives In this module, you ● Create generic functions ● Create primary methods and apply them to classes ● Control the execution of methods using callNextMethod 118 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 118 This document is for the sole use of Firuz Shomahmadov of Nxp What Are Methods? Methods are like procedures in which they do something (side effects) and return a value. They define the actions taken on objects. ● Methods, like procedures, have a name. ● Unlike procedures, multiple methods can have the same name. ● Methods are executed like procedures: ▪ Called directly with arguments. ▪ Using callNextMethod() to call the method of the superclass. ● Method calls (which method is executed) are qualified by the specializers on the arguments. ▪ The object passed into specialized arguments determines which method is executed. 119 defmethod( createLib ( ( lib library )) ;; Create a library … ) © Cadence Design Systems, Inc. All rights reserved. The real power of class inheritance is methods. Methods are like procedures in that they do something (side effects) and return a value. In Virtuoso®, we are often more interested in the side effects than the return value. A method has a name and is called by its name. There may be multiple methods with the same name, but each applies to a different class. The method is called with the class in an argument. If the method was defined for that class, it is executed from that class; otherwise, the superclass hierarchy is searched till the method is found and that method is executed for that class. A currently executing method can then execute the method of its superclass using the callNextMethod function. © Cadence Design Systems, Inc. All rights reserved. 119 This document is for the sole use of Firuz Shomahmadov of Nxp What Are Methods?(continued) In some OO programming languages, methods are components inside classes. ● There are often syntactical and semantic differences between calling a method versus calling a normal function. In SKILL++, methods are components of generic functions. ● There is no syntactical nor semantic difference between calling a generic function versus calling a normal function. 120 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 120 This document is for the sole use of Firuz Shomahmadov of Nxp Behavior of a Method The behavior of a generic function/method is determined by which methods are applicable for a given set of arguments at run time. The SKILL++ programmer (who creates an API) ● Customizes the generic function behavior by writing methods specializing in their classes. The SKILL++ programmer (who uses the API) ● Need not know whether a function is a normal function or a generic function. 121 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 121 This document is for the sole use of Firuz Shomahmadov of Nxp How to Create Methods for the Class Before methods can be created for a class, the class itself has to be created and loaded into Virtuoso®. Defining a method without a class will generate a warning. The steps to create the method are: 1. Create a class that will use the method. 2. Define a generic function. (defclass library () ((name) (owner))) Define a class called library. a. Erases all existing methods of this name. b. Sets the required arguments. c. Can be the last method called in the method hierarchy. i. Could generate an error when invoking a generic function that has no default method. ii. Could return a default value such as nil. defgeneric( createLib ( obj) defmethod( createLib ( ( lib library )) Declare a generic function that creates a method template. Define a method specialized on classes. 3. Define class-specific methods. a. Methods are specialized on the classes. 122 © Cadence Design Systems, Inc. All rights reserved. Before methods can be created for a class, the class itself has to be created and loaded into Virtuoso. Defining a method without a class will generate a warning. The next step is to create a generic function. This function is the template for the methods that share the name. The generic function sets the required arguments; methods can only specialize on required arguments. The generic function is executed if none of the method specializers match when the function is called. It often generates an error. The classspecific methods are created using specializers that determine when they will be executed. Primary, @before, and @after methods can be created. © Cadence Design Systems, Inc. All rights reserved. 122 This document is for the sole use of Firuz Shomahmadov of Nxp Generic Function Declaration defgeneric( methodName ( specializer ) ) ● Generic function declaration creates the template. ● Specialized arguments are declared as required arguments. ● Following arguments are available: ▪ @key ▪ @optional ▪ @rest ● @rest can be used to extend the method calls with additional keyed or optional arguments. ;; Generic function can define a default behavior defgeneric( createLib ( obj) error( "no createLib method defined for %s." className( classOf(obj) ))) 123 © Cadence Design Systems, Inc. All rights reserved. The generic function is declared using defgeneric. This establishes the name of the method and the required arguments. All methods with the same name (derived methods) will have these required arguments. A method can only specialize on the required arguments. If the generic function declares any @optional or @key arguments, all derived methods must have the same @optional or @key arguments. The @rest argument should always be included in a generic function definition. This allows the derived methods to extend the argument list with additional @optional or @key arguments. A good practice is to always include an @rest argument when defining a generic method. The generic function can also have a body consisting of a set of expressions. By convention, the generic function expressions should never be called, so this set is often just an error message or returns nil. Note: It is recommended that additional arguments be created as @key arguments instead of @optional arguments. This is especially true with methods. © Cadence Design Systems, Inc. All rights reserved. 123 This document is for the sole use of Firuz Shomahmadov of Nxp Primary Method Declaration defmethod( methodName ( ( varName className )) ;; Create a library … ) ● Primary methods specialize on the required arguments. ● Method executed determined by matching specializer. ● Method specializes on class of instance. ● Must match library class. Method name Method specializes on class library defmethod( createLib ( ( lib library )) ;; Create a library … ) A variable name can be different from a generic function variable. 124 © Cadence Design Systems, Inc. All rights reserved. The primary methods specialize on the class of the instance passed in to the required argument(s). The class is declared in the method argument paired with the variable. The method is called with an object; if the class of the object or any superclass of the object matches the specializer class, the method is available to be executed. It will be executed if it is the most specific method or is a candidate to be called using callNextMethod. © Cadence Design Systems, Inc. All rights reserved. 124 This document is for the sole use of Firuz Shomahmadov of Nxp Primary Method Execution defmethod( methodName ( ( varName className )) ……) instName = makeInstance( 'className ) methodName( instName ) ● Method defined for class: library defmethod( createLib ((lib library)) … Class library ) ● Function called with an instance of designLib. userLib desLib = makeInstance( 'designLib ) createLib( desLib ) designLib ● Method for superclass library executes. 125 © Cadence Design Systems, Inc. All rights reserved. The createLib method was defined for the class: library. If there is no primary method for the designLib class or the userLib class, the method for the superclass library is executed when the specialized argument is an instance of the designLib object. © Cadence Design Systems, Inc. All rights reserved. 125 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Primary Method Execution ● Methods defined on classes: library and designLib defmethod( createLib ((lib library )) …) Class library defmethod( createLib ((lib designLib)) … ) userLib ● Function called with an instance of designLib. desLib = makeInstance( 'designLib ) createLib( desLib ) designLib ● Only method for designLib is executed without explicit execution of inherited class methods. 126 © Cadence Design Systems, Inc. All rights reserved. The createLib method was defined for both the library and the designLib classes. The method was called with an object of the class designLib. This executes the method specific to the class. If that class does not explicitly execute the methods of the super classes, it will not execute the library method. © Cadence Design Systems, Inc. All rights reserved. 126 This document is for the sole use of Firuz Shomahmadov of Nxp Primary Method Execution with callNextMethod() ● Methods defined on classes: library and designLib defmethod( createLib ((lib library )) …) defmethod( createLib ((lib designLib)) callNextMethod() …) ● Function called with an instance of designLib. desLib = makeInstance( 'designLib ) createLib( desLib ) ● Method for designLib class is executed, call to callNextMethod() executes the next most specific method (library class). Class library userLib designLib Changing the value of a specialized argument will give unpredictable results. Call either with all arguments or none, but never with a partial argument list. 127 © Cadence Design Systems, Inc. All rights reserved. To execute the methods from the superclasses, a method can call the function callNextMethod. This executes the next most specific method from the superclasses. That method can call callNextMethod(), continuing to execute the next most specific method until it gets to a method that does not use callNextMethod or the first or generic method. Once that final method has been completed, it returns up the stack to finally reach the first method that was called, which then completes. The callNextMethod function can be used at the beginning of a method, in the end, or the middle, depending on when the code specific to the class should be executed. The value returned from callNextMethod is the value returned by the method itself. The order of execution for the method specializers with callNextMethod is calculated when the first method is executed. If an argument used as specializer changes in the current method, callNextMethod will still call the pre-calculated method, which may be incorrect. © Cadence Design Systems, Inc. All rights reserved. 127 This document is for the sole use of Firuz Shomahmadov of Nxp Flow of the Primary Method Execution with callNextMethod() Class Method Default: createLib( anyObj ) Least specialized library callNextMethod() createLib( libraryInst ) userLib createLib not defined for class userLib callNextMethod() createLib( designLibInst ) Time 128 designLib Most specialized © Cadence Design Systems, Inc. All rights reserved. Methods execute from the most specific class to the least specific class. The function callNextMethod() is executed inside the method, then the method on the superclass is called. In this case, the execution of createLib on designLib does some computing, then calls the next method using callNextMethod(). Because createLib is not defined for class userLib, the next method in the hierarchy is for the class library, and that method is called. Class library is a base class, and its execution of callNextMethod() calls the first primary method or generic function version of createLib. If any method does not execute callNextMethod, the method execution ends with that method. If createLib for class designLib did not call the next method, createLib for the class library would not be executed. When a method has been completed for a class, control is passed to the subClass method, which called it. designLib->library->designLib © Cadence Design Systems, Inc. All rights reserved. 128 This document is for the sole use of Firuz Shomahmadov of Nxp Methods on Invalid Class Names SKILL++ allows you to define a method on a class that does not yet exist, making it easier to build multifile applications. ● You do not need to define all the classes before the methods. ● However, this presents a potentially obscure bug in your program if you misspell a class name. ● When you define a method that does yet exist, defmethod issues a warning which is expected if you will be defining the class later. ● SKILL++ cannot distinguish between misspelled class name vs. a not-yet-defined class. ● Execution of the code may not proceed as expected because the method will not be called if the class does not exist. 129 ● Here is an example class/methods definition that might be a bug in your program: defmethod( Fun2 ((a Class_A)) ; method on not-yet-defined class (do_something a)) defclass( Class_A () ; late class definition ()) defmethod( Fun1 ((a ClassA)) ; method on misspelled class name (do_something_else a)) © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 129 This document is for the sole use of Firuz Shomahmadov of Nxp Lab Lab 10-1 Examining the Primary Methods on a Given Class 130 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 130 This document is for the sole use of Firuz Shomahmadov of Nxp Access SKILL® Data Structures with setf Module 11 Revision 2.0 Version IC 6.1.8/ ICADVM 20.1 Estimated time: ● Lecture 15 minutes ● Lab 30 minutes This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 131 This document is for the sole use of Firuz Shomahmadov of Nxp Module Objectives In this module, you ● Identify the usage of a setf macro ● Build and modify hierarchical lists and structures ● Define and build setf-Able functions 132 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 132 This document is for the sole use of Firuz Shomahmadov of Nxp What Is a setf Macro? The setf function assigns a new value to an existing storage location, destroying the value that was previously in that location. ● It provides an easy and consistent syntax for reading and writing SKILL® objects. ● It works with many SKILL built-in data structures, such as Lists, dbobjects, and Hash tables. The syntax for the setf function is: setf( g_place g_value) or g_place := g_value ● g_place specifies the storage location. ● g_value specifies the new value. Example ● We access the first element of a list, mylist, with the syntax: ▪ (car mylist) ● Therefore, we change the first element to 42 using the syntax: ▪ setf((car mylist) 42 ) 133 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 133 This document is for the sole use of Firuz Shomahmadov of Nxp Example: setf Macro Code mydpl = (list nil 'left_most 23:98'right_most 56:87) mydpl → (nil left_most (23 98) right_most (56 87)) mydpl->left_most → (23 98) yCoord( mydpl->left_most ) → 98 setf( yCoord( mydpl->left_most ) 33) yCoord( mydpl->left_most ) → 33 mydpl → (nil left_most (23 33) right_most (56 87)) 134 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 134 This document is for the sole use of Firuz Shomahmadov of Nxp setf-Able Function setf_expanderName( g_new (g_cell)) =>g_result ● An expander function for setf, which returns the result of the corresponding setf operation. The following is an example of the helper function for getSKILLPath function: ● This function is used to abstract the implementation of data storage. defun(setf_getSkillPath (new) ● In the above syntax, in the place of the expanderName, you can write the functions such as setf_car, setf_cdr, setf_slotValue, etc. ▪ You can also create your own setf helper functions. if(listp(new) setSkillPath(new) setSkillPath(list(new)))) ; alters the skill path with setf setf(getSkillPath() "/home/user/temp") ; now skill path changed to "/home/user/temp" 135 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 135 This document is for the sole use of Firuz Shomahmadov of Nxp setf-Able Function (continued) Another example shows the usage of the setf_helper function by creating our own setf helper function. let( (secret used) defglobalfun( secret_value () secret ) defglobalfun( setf_secret_value (new_value) when( member( new_value used) error( "%L already used" new_value )) push( new_value used ) secret = new_value ) (setf (secret_value) 0) ) secret_value() → 0 setf_secret_value(2) secret_value() → 2 136 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 136 This document is for the sole use of Firuz Shomahmadov of Nxp Module Summary In this module, you ● Examined the usage of setf macro ● Built hierarchical lists and structures and modified it ● Defined and built setf-Able functions 137 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 137 This document is for the sole use of Firuz Shomahmadov of Nxp Lab Lab 11-1 Using the setf Function to Access List Data 138 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 138 This document is for the sole use of Firuz Shomahmadov of Nxp Methods (Intermediate) Module 12 Revision 2.0 Version IC 6.1.8/ ICADVM 20.1 Estimated time: ● Lecture 30 minutes ● Lab 15 minutes This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 139 This document is for the sole use of Firuz Shomahmadov of Nxp Module Objectives In this module, you ● Use @before, @after, and @around methods ● Identify the order of execution of these methods ● Illustrate the use of accessor methods 140 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 140 This document is for the sole use of Firuz Shomahmadov of Nxp What Are Methods? Methods are like procedures in which they do something (side effects) and return a value. They define the actions taken on objects. ● Like procedures, methods have a name. ● Unlike procedures, multiple methods can have the same name. ● Methods are executed like procedures. ▪ Called directly with arguments. ▪ Using callNextMethod() to call the method of the superclass. ● Method calls (which method is executed) are qualified by the specializers on the arguments. ▪ The object passed into specialized arguments determines which method is executed. 141 © Cadence Design Systems, Inc. All rights reserved. The real power of class inheritance is methods. Methods are like procedures in that they do something (side effects) and return a value. In Virtuoso®, we are often more interested in the side effects than the return value. A method has a name and is called by its name. There may be multiple methods with the same name, but each applies to a different class. The method is called with the class in an argument. If the method was defined for that class, it is executed from that class; otherwise, the superclass hierarchy is searched till the method is found and that method is executed for that class. A currently executing method can then execute the method of its superclass using the callNextMethod function. © Cadence Design Systems, Inc. All rights reserved. 141 This document is for the sole use of Firuz Shomahmadov of Nxp Why @before and @after Methods? ● Sometimes, you want to preset conditions before executing the primary methods. ▪ For example, change the design rules based on a Pcell parameter. ● And sometimes, you want to do something after the primary methods are completed. ▪ Like adding implants and wells to the drawn layers. ● SKILL++ supports this by implementing qualified methods: ▪ @before ▪ @after 142 © Cadence Design Systems, Inc. All rights reserved. SKILL++ supports more than the primary methods. Based on the common Lisp object system, SKILL++ includes the additional method types of @before and @after methods. These are useful for executing code to set up for the primary methods or cleaning up after the primary methods. © Cadence Design Systems, Inc. All rights reserved. 142 This document is for the sole use of Firuz Shomahmadov of Nxp What Are @before Methods? @before methods are used to preprocess the data before executing the primary methods. Example ● @before methods have the same name as the primary methods. Characteristics: ● @before qualifier is used to declare @before methods. ● Method defined with the same name as a primary method and an @before qualifier. ● Method selected by matching the specializer. ● Methods are chosen based on the class specializer. ● All applicable @before methods are executed before any primary methods. ▪ Not allowed to call callNextMethod() in a @before method. ▪ Return values are ignored. ● Execution is from most specific to least specific methods. 143 Method name Qualifier Method specializes on class library defmethod( createLib @before ( ( lib library ) ) let(((path getPath( lib )) unless( isDir( path ) createDirHier( path ) ) ; unless ) ; let ) ; defmethod © Cadence Design Systems, Inc. All rights reserved. @before methods perform operations before the execution of the primary methods. They can set up or modify conditions for the execution of the primary methods. Use a primary method to ensure that the required directory structure is created or to reset the values of slots on the class. Like the primary methods, the @before methods are selected based on the specializers of the class. The methods have the same template as the generic function defined with defgeneric. All the applicable @before methods are executed in the most specific to least specific order before any of the primary methods. The @before method for a set of specializers (usually the class) may exist even if there is no primary method for that set of specializers. Like the primary method, the @before method is defined with the same name as the generic method with the addition of the @before qualifier. The required arguments are set by the template generic function; additional keyed or optional arguments can be defined if the generic function includes @rest. The list of @before methods is determined by matching the specializers on the methods; they are executed from the most specific to the least specific order. © Cadence Design Systems, Inc. All rights reserved. 143 This document is for the sole use of Firuz Shomahmadov of Nxp What Are @after Methods? @after methods are used to postprocess the data after executing the primary methods. Characteristics: ● Method defined with the same name as a primary method and an @after qualifier. ● Methods are chosen based on the class specializer. ● All applicable @after methods are executed after any primary methods. ▪ Not allowed to call callNextMethod() in a @after method. ▪ Return values are ignored. ● Execution is from least specific to most specific methods. 144 Example ● @after methods have the same name as the primary methods. ● @after qualifier is used to declare @after methods. ● Method selected by matching the specializer. Method name Qualifier Method specializes on class library defmethod( createLib @after ( ( lib refLib ) unless( assoc( "pcoCheckUsers" ddGetTriggerList( "preCheckOut" )) ddRegTrigger( "preCheckOut" ‘pcoCheckUsers ) ); unless ); defmethod ) © Cadence Design Systems, Inc. All rights reserved. @after methods perform operations after the execution of the primary methods. They can set up or modify conditions for the execution of the primary methods. Use a primary method to ensure that the required directory structure is created or to reset the values of slots on the class. Like the primary methods, the @after methods are selected based on the specializers of the class. The methods have the same template as the generic function defined with defgeneric. All the applicable @after methods are executed in the most specific to least specific order after any of the primary methods. The @after method for a set of specializers (usually the class) may exist even if there is no primary method for that set of specializers. Like the primary method, the @after method is defined with the same name as the generic method with the addition of the @after qualifier. The required arguments are set by the template generic function; additional keyed or optional arguments can be defined if the generic function includes @rest. The list of @after methods is determined by matching the specializers on the methods; they are executed from the least specific to the most specific order. © Cadence Design Systems, Inc. All rights reserved. 144 This document is for the sole use of Firuz Shomahmadov of Nxp Execution Order: @before and @after Qualifiers and Primary Methods Below diagram and table illustrates the execution of @before, primary and @after methods. ● All applicable @before methods are ordered from most specific to least specific and executed in that order. ● The applicable primary methods are ordered the same and will be evaluated only if the methods execute callNextMethod or callAs. ● The applicable @after methods are ordered from least specific to most specific, and all are executed in that order. Class Method Qualifier Specializer library createLib @before designLib userLib @before designLib 145 primary @after createLib @before library createLib primary designLib createLib primary library createLib @after userLib createLib @after designLib © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 145 This document is for the sole use of Firuz Shomahmadov of Nxp Execution Order: @before and @after Qualifiers and Primary Methods (continued) @before primary @after library userLib callNextMethod() designLib 146 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 146 This document is for the sole use of Firuz Shomahmadov of Nxp What Are @around Methods? The @around methods are executed first when they are defined. It invokes callNextMethod, and executes the next most specific @around method, with all its callNextMethod methods. ● @around methods have the same name as the primary methods. ● @around qualifier is used to distinguish @around methods. ● The method is selected by matching the specializer. ● Called before any @before, @after, or primary method. ● callNextMethod() calls the next @around method if there is one. Method name Qualifier Method specializes on class library defmethod( createLib @around ( ( lib library ) ) unless( ddGetObj( getLibName( lib ) ) callNextMethod() ) ; unless ) ; defmethod ● Otherwise, it calls the normal @before/@after/primary. 147 © Cadence Design Systems, Inc. All rights reserved. The return value of the generic function is the return value of the most-specific @around method. It's a way of overriding the behavior of the generic function by wrapping it in something else. © Cadence Design Systems, Inc. All rights reserved. 147 This document is for the sole use of Firuz Shomahmadov of Nxp Execution Order with @around, @before, primary and @after Qualifiers 148 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 148 This document is for the sole use of Firuz Shomahmadov of Nxp Important Method Rules ● The generic function defines the template for the methods: ▪ Method name ▪ Required arguments ● The methods can specialize only on the required arguments. ● Add @rest to the generic function to allow for future additions such as @key or @optional arguments. ● @before and @after methods have the same required arguments as the generic function. ● @before and @after methods are selected for execution by matching their specializers. ● All applicable @before methods are executed before any of the primary methods. ▪ @before methods execute from most specific to least specific. ● All applicable @after methods are executed after any of the primary methods. ▪ @after methods execute from least specific to most specific. ● Primary methods are applicable if their specializers match the arguments. ● Primary methods execute only from the most specific method to the least specific method. ● Primary methods will execute the next method only if the current method calls the function callNextMethod() or executes the method directly. 149 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 149 This document is for the sole use of Firuz Shomahmadov of Nxp Slot Direct Access Versus Accessor Methods setSlotValue/slotValue or dash arrow(->) is the slot direct accessing techniques. ● Direct access techniques can be used as discrete statements. ● For fast and simple access. ● The programmer should know the name of the slot to use these statements. value1 = slotValue( instA 'name ) => "testLib2" value2 = slotValue( instA 'owner) Methods with @reader and @writer keywords are called slot accessing methods. ● Accessor methods should be used in defclass only. ● For augmenting the behavior of the class. ● If the underlying data structure changes, it will update to the new structure automatically. (defclass library () (( name @initarg libName @reader getLibName @writer setLibName))) => "Your Name Here" 150 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 150 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Slot Direct Access Versus Accessor Methods ● Here is an example to set and read the circle radius using the direct access and accessor methods. defclass( Circle () ((radius @initarg r @reader circle_radius @writer set_circle_radius ) ) C = makeInstance('Circle ?r 14.6) R1 = C->r C->r = 10.3 R2 = circle_radius(C) set_circle_radius(C 19.9) ● To force the radius to be returned as a float, define an @around method. defmethod( circle_radius @around ((c Circle)) float( callNextMethod() )) ● To limit the values a slot can take, define a primary method. The subclass Circle_fixed now has a constant radius. defclass( Circle_fixed (Circle) () ) defmethod( set_circle_radius ((c Circle_fixed) value) if( circle_radius( c ) == value then value else error( "cannot set c of %A to %L" c value))) 151 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 151 This document is for the sole use of Firuz Shomahmadov of Nxp Slot Access Using the setf-Able Function (defmethod setf_circle_radius (value (c Circle)) (if (plusp value) c->value = value (error "circle does not support non-positive radius: %L" value))) setf_circle_radius is the setf-Able function. As an alternative to using @writer: ● Make the @reader into a setf-Able place. ● Prepend setf_ onto the name of the @reader function. ● Create a method specializing on the second argument. Now (circle_radius), the @reader function, is setf-Able. 152 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 152 This document is for the sole use of Firuz Shomahmadov of Nxp Slot Access Using setf-Able Function (continued) ● Set the values of C1 and C2. C1 = (makeInstance 'Circle ?r 14.0) (circle_radius C1) → 14.0 C2 = (makeInstance 'Circle ?r 1.0) (circle_radius C2) → 1.0 ● You can also change the C1 value using the setf function. (setf (circle_radius C1) 12.0) (circle_radius C1) → 12.0 153 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 153 This document is for the sole use of Firuz Shomahmadov of Nxp Slot Access Also Works with incf, swapf, etc. (Incf (circle_radius C1)) (circle_radius C1) → 13.0 (Swapf (circle_radius C1) (circle_radius C2)) (circle_radius C1) → 1.0 (circle_radius C2) → 13.0 (decf (circle_radius C1)) → *ERROR* circle does not support non-positive radius: 0.0 154 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 154 This document is for the sole use of Firuz Shomahmadov of Nxp Module Summary In this module, you ● Used @before, @after, and @around methods ● Identified the order of execution of these methods ● Illustrated the use of accessor methods 155 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 155 This document is for the sole use of Firuz Shomahmadov of Nxp Labs Lab 12-1 Using the @before and @after Methods in SKILL++ Code Lab 12-2 Using Lazy Slots 156 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 156 This document is for the sole use of Firuz Shomahmadov of Nxp Introduction to Macros Module 13 Revision 2.0 Version IC 6.1.8/ ICADVM 20.1 Estimated time: ● Lecture 30 minutes ● Lab 30 minutes This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 157 This document is for the sole use of Firuz Shomahmadov of Nxp Module Objectives In this module, you ● Identify the instances of macro creation ● Use macros in SKILL® code ● Implement simple macros ● Create and debug more complex macros ● Examine argument evaluation and return values 158 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 158 This document is for the sole use of Firuz Shomahmadov of Nxp What Is a Macro? A macro is a function that allows you to adapt the normal SKILL function call syntax to the needs of your application. Characteristics: To define a macro in SKILL, use defmacro. Example If you want to check the value of a variable to be a string before calling printf and you don’t want to write the code to perform the check at every place where printf is called, you might consider writing a macro: ● A macro is a code that writes additional code. ▪ Return value is a SKILL or SKILL++ expression. ● Macros help as powerful extensions to the language. ▪ Capable beyond C++ macros. ● Macros are evaluated on first execution. ▪ Code is embedded in the calling procedure. ● The SKILL macros can be used in various situations: 159 ▪ To gain speed by replacing function calls with in-line code. ▪ To expand constant expressions for readability. ▪ As convenience wrappers on top of existing functions. (defmacro myPrintf (arg) `when((stringp ,arg) printf( "%s" ,arg))) As you can see, the macro myPrintf returns an expression constructed using backquote, which is substituted for the call to myPrintf at the time a function calling myPrintf is defined. © Cadence Design Systems, Inc. All rights reserved. Macros are an integral part of SKILL, useful for extending the language in ways that are not supported in C-based languages. A macro is a program that returns a SKILL expression embedded in the program that calls the macro when the program is defined. © Cadence Design Systems, Inc. All rights reserved. 159 This document is for the sole use of Firuz Shomahmadov of Nxp Importance of Using Macro in Your Program ● Minimize repeated coding: ● Do things you cannot do in a procedure ▪ The for loop in SKILL allows only to increment by a value of 1. ▪ To increment by a value other than 1, you need a while loop. ▪ Non-evaluated (or multiply evaluated) arguments ▪ until( sqrt(x)>20 x++ y--) ● Create domain-specific languages ▪ So, in this case, a macro would allow you to use enhanced for loop syntax (like C). ▪ Target design-specific problems (defmacro TrCFor (initExpr testExpr incrExpr @rest bodyExprs) `(progn ,initExpr (while ,testExpr ,@bodyExprs ,incrExpr ; user specified increment ))) Use it as: TrCFor( i=1 b=i*i println(b) ) => prints 1 9 25 49 81 160 i<10 i=i+2 © Cadence Design Systems, Inc. All rights reserved. There are many reasons to use macros. Simple macros can make the source code clearer; using a macro urY to return the upper right Y value of a bounding box is easier to understand than using cadadr. Because it is a macro, there is no overhead as you would get with procedure calls. Macros can replace repeated code; the macro almostEq compares two floating point numbers and returns t if they are within a small fraction of each other. A macro like trTransformPoints expands into a series of commands that transforms the points in a pointList rather than calling a function with its overhead, including copying the pointList to the program stack and returning the modified list; the pointList is modified in-line. There are some things you cannot do in a procedure that can only be done in a macro. Procedure calls always interpret their arguments; macros do not. Macros make it very easy to create domain-specific languages. These languages simplify solving problems within a fixed problem domain. An example of a domain-specific language would be a language tailored to creating pcell and CDF parameters. This is a very advanced topic that is not part of this training course. For more on domain-specific languages: http://en.wikipedia.org/wiki/Domainspecific_language http://www.c2.com/cgi/wiki?DomainSpecificLanguage © Cadence Design Systems, Inc. All rights reserved. 160 This document is for the sole use of Firuz Shomahmadov of Nxp What Is the Use of SKILL Programs? The SKILL programs are the SKILL data because the commands that are evaluated are lists. ● SKILL is made up of list-based expressions. ▪ Lists of symbols, numbers, arrays, strings, etc. ● The SKILL expressions are lists where: sstatus( printinfix nil ) '( x + y + z) (plus x y z) ▪ The first element is the function to evaluate. car( '( x + y + z)) ▪ The other elements are the arguments to that command. plus equal( list( 'difference 'x 'y 'z) '(x – y – z)) 161 t © Cadence Design Systems, Inc. All rights reserved. SKILL commands are actually lists that are evaluated. The first element in the list is the function to evaluate, the other elements are the arguments to that command. A command evaluation can be built up as just such a list. © Cadence Design Systems, Inc. All rights reserved. 161 This document is for the sole use of Firuz Shomahmadov of Nxp How to Write a Function That Returns a Program (Macro) The function which returns a closure with its own variable and named function is called a Macro. Treating functions as data allows creative solutions. Let us write a function that will write functions like Count: /* Or use backquote ` with , for evaluation. This approach provides a more readable macro as it more closely resembles the final SKILL code. */ Approach 2: defun( WriteCount (name starting_num) ‘( let ((count ,starting_num) ) and_so_on)) Approach 1: defun( WriteCount (name starting_num) list( 'let list( WriteCount( 'Count 0) (let ((count 0)) and_so_on) list( 'count starting_num))'and_so_on)) 162 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 162 This document is for the sole use of Firuz Shomahmadov of Nxp How to Write a Function That Returns a Program (Macro) Approach 2 Continuing to write the function, we define the increment function Count. ● The old placeholder has been replaced with a function definition that takes the name based on the WriteCount argument. ● To further fill in the functionality, we have to find the API for incrementing the value; it is postincrement. defun( WriteCount (name starting_num) `(let ( ( count ,starting_num)) ( defglobalfun ,name nil count_plus_plus))) WriteCount( 'Count 0) (let ((count 0)) (defglobalfun Count () count_plus_plus))) '( count++ ) (postincrement count) 163 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 163 This document is for the sole use of Firuz Shomahmadov of Nxp How to Write a Function That Returns a Program (Macro) Approach 2 (continued) Now we can finish the WriteCount function. ● This function creates a closure with a named function and a starting count. ● Executing the named function increments the closure variable. WriteCount('Count 0) (let ((count 0)) (defglobalfun Count () (postincrement count))) eval( WriteCount('Count 10) theEnvironment() ) Count list( Count() Count() Count()) (10 11 12) 164 © Cadence Design Systems, Inc. All rights reserved. How would you create another counter closure named Counter2 that starts at 7? © Cadence Design Systems, Inc. All rights reserved. 164 This document is for the sole use of Firuz Shomahmadov of Nxp Write a Macro by Using defmacro defmacro( s_macroName ( l_formalArglist ) g_expr1 ... ) => s_macroName (defmacro DefineCounter (funName initialCount) ‘(let ((count ,initialCount)) (defglobalfun ,funName () (++count)))) DefineCounter When we use the defmacro function it: ● Takes pieces of a program as input. DefineCounter(Count10 10) ● Returns pieces of a program as output. Count10 The output gets used in place of the "macro call". Count10() This replacement happens when the SKILL code is first executed: 11 ● Really at "macro-expansion time". Count10() ● For most purposes, this is when the file is loaded. 12 ● Changing the macro means reloading not just the macro but also the functions that use the macro. Note: Use `backquote for the list and var to evaluate funName and initialCount. 165 © Cadence Design Systems, Inc. All rights reserved. Macros in SKILL are a standard way of writing programs that write functions. Like the WriteCount function, they return the code that is then inserted in the calling function in place of the macro call. This insertion occurs when the file is loaded; all macros are expanded at load time. This means that once a function that calls a macro is loaded, the macro is expanded, and changing the macro will not affect the function. You have to reload the function after you have loaded the new macro definition so it can be expanded again. We will use the same code in the macro to create counters. © Cadence Design Systems, Inc. All rights reserved. 165 This document is for the sole use of Firuz Shomahmadov of Nxp Bug in First Macro Bug: Count10 starts counting at 11. What do we do now? ● Let us look at the program DefineCounter created. ● Sometimes, it’s useful to set printinfix. (sstatus printinfix t) t (expandMacro '(DefineCounter Count10 10)) let( ((count 10)) defglobalfun( Count10 () ++count )) 166 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 166 This document is for the sole use of Firuz Shomahmadov of Nxp Arguments and Return Values of Macros ● Macros can compute anything from their arguments. ▪ "Arguments" are pieces of source code. ▪ Some code can be executed in the macro. ● Return value is code that is evaluated. (defmacro Macro1 (var @key n @rest forms) (printf "Var is %L, n is %L, forms %L\n“ var n forms) `(for ,var ,n (random 65535) ,@forms) Return value Executed code ) (Macro1 x ?n 1 (printf "X is %d\n" x)) ;; Var is x, n is 1,forms ((printf "X is %d\n" x)) ;; X is 1 ;; X is 2 t 167 © Cadence Design Systems, Inc. All rights reserved. Macros may be easier to visualize using Lisp syntax as the first element in a list is a function, and all the other elements are arguments. Code not quoted is evaluated in the macro; the return value is quoted, so it is not evaluated but returned. If the macro call is in a function, the returned code is inserted into the function. In this case, the macro is evaluated at the top level, so the code is evaluated immediately. © Cadence Design Systems, Inc. All rights reserved. 167 This document is for the sole use of Firuz Shomahmadov of Nxp Selectively Evaluate Arguments in Macros ● All arguments are not evaluated. ● Use backquote, comma, and comma-at to selectively evaluate arguments. (defmacro Macro1 (var @key n @rest forms) (printf "Var is %L, n is %L, forms %L\n“ ) var n forms ) `(for ,var ,n (random 65535) ,@forms) Unevaluated arguments Evaluated arguments ) (Macro1 x ?n 1 (printf "X is %d\n" x)) ;; Var is x, n is 1, forms ((printf "X is %d\n" x)) ;; X is 1 ;; X is 2 t 168 © Cadence Design Systems, Inc. All rights reserved. Macros may be easier to visualize using Lisp syntax as the first element in a list is a function, and all the other elements are arguments. The comma and comma-at inside the back quoted list cause the arguments to be evaluated. © Cadence Design Systems, Inc. All rights reserved. 168 This document is for the sole use of Firuz Shomahmadov of Nxp Function Calls as Arguments in Macros ● Function calls can be passed in as arguments. ● Comma-at evaluates the function call. (defmacro Macro1 (var @key n @rest forms) (printf "Var is %L, n is %L, forms %L\n" var n forms) `(for ,var ,n (random 65535),@forms) ) (Macro1 x ?n 1 (printf "X is %d\n" x) ) ;; Var is x, n is 1, forms ((printf "X is %d\n" x)) ;; X is 1 ;; X is 2 t 169 © Cadence Design Systems, Inc. All rights reserved. The function call to (printf "") is passed as a list to the macro. Inside the macro, it is interpreted in the back quoted list using the @comma-at. © Cadence Design Systems, Inc. All rights reserved. 169 This document is for the sole use of Firuz Shomahmadov of Nxp Module Summary In this module, you ● Identified the instances of macro creation ● Used macros in SKILL code ● Implemented simple macros ● Created and analyzed more complex macros ● Examined argument evaluation and return values 170 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 170 This document is for the sole use of Firuz Shomahmadov of Nxp Labs Lab 13-1 Implementing SKILL Code with Macros Lab 13-2 Implementing Macros and Defclass 171 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 171 This document is for the sole use of Firuz Shomahmadov of Nxp Local Functions Module 14 Revision 2.0 Version IC 6.1.8/ ICADVM 20.1 Estimated time: ● Lecture 30 minutes ● Lab 30 minutes This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 172 This document is for the sole use of Firuz Shomahmadov of Nxp Module Objectives In this module, you ● Identify the usage of local function ● Implement the flet function in a code to define a local function ● Examine the use of labels for recursion 173 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 173 This document is for the sole use of Firuz Shomahmadov of Nxp What Is a Local Function? The function in which the scope of each variable is limited to that function only is called a local function. ● Functions defined within a lexical scope. ▪ Function is only usable within the containing let(). ▪ Function can access variables within the lexical scope. ● Create special function for use within the scope of the current function. flet Local function able to call global function with the same name labels Local function that can be recursive procedure or defun Local declaration within the lexical scope flet( ((foo (x) (list x)))(foo 1)) => (1) 174 © Cadence Design Systems, Inc. All rights reserved. Local functions are valuable for simplifying your code. A function encapsulates a set of steps and equations, assigning a name and arguments. The function is called by its name, assigning the values for the arguments. The steps in the function are executed, and a value is returned. This methodology is already used, creating procedures in SKILL®. These are global procedures; the name exists in the global memory space and can be called by any other function or by the user. Sometimes, the set of steps is specific to the calling function, such as toggling between the "source" and "drain" node in the MOS device. Instead of creating a global function, a local function can be defined and used within the calling function. The local function is named, and the name is local to the lexical scope in which the function is declared. When the function is executed in that scope, that function is executed. Outside the lexical scope, the name may refer to a global function or to another lexically scoped local function without the names clashing. The declarations for local functions are flet, labels, and procedure, or defun can also be used to declare local functions; they act like the labels declaration. © Cadence Design Systems, Inc. All rights reserved. 174 This document is for the sole use of Firuz Shomahmadov of Nxp flet: Local Function Creation flet(( (local_function_name (arg list) local…function…expressions ) ) body…function…expressions local_function_name( argValue listValue ) more…body…expressions ) let((currentNode (firstNode MyGetVal( device 'firstNode ))) ;; local function to swap the source and drain flet(( (swapSD( node ) currentNode = if( node == "drain" then "source" else "drain" ))) MOSdrawFirstNode( device cvId firstNode 0 leftAbut ) swapSD( firstNode ) for( i 2 fingers MOSdrawNextNode( device cvId currentNode i) swapSD( currentNode ) ) ; ** for i ** ) ; flet ) ; let ● Declares local function and sets the limits of its visibility. ● Function name is not known within its own definition. ▪ A call to the function inside the definition executes the function from the containing lexical scope (maybe a global function). 175 © Cadence Design Systems, Inc. All rights reserved. Flet declares functions whose definitions are only available within the body of the flet statement. These functions encapsulate code that would be reused within the block, simplifying the code. Variables defined in the scope containing the flet are accessible within the local functions. The local functions are created in the same manner as global functions, with argument lists that can include @optional or @key optional arguments as well as @rest to capture extra arguments passed in. The body of the local function can be enclosed by let or prog block style statements, and the function will return the value of the last statement executed (excepting prog1 or prog2 blocks). In this example, a local function, swapSD, is created to swap the value of the variable currentNode between "source" and "drain". Note that the variable currentNode is used in the local function; since the function and the variable are defined within the same scope, the function can access the variable. The set of statements to swap the values is used in more than one place in the containing procedure; encapsulating them into a local function simplifies the code and makes the function easier to debug. © Cadence Design Systems, Inc. All rights reserved. 175 This document is for the sole use of Firuz Shomahmadov of Nxp flet: Calling Global Functions ● A local function defined within a flet cannot call itself. ● Executing the function name within the local function calls the global function. ● Use the local function to compute arguments for the global function. flet( ((dbMoveFig ( listOfFigs cvId transform ) unless( listp(listOfFigs) listOfFigs = ncons(listOfFigs)) foreach( fig listOfFigs ;; call to global function dbMoveFig( fig cvId transform )) )) … ) 176 © Cadence Design Systems, Inc. All rights reserved. The local function defined within a flet cannot be recursive; it cannot call itself. If the function name is executed, it will execute the global function of the same name (or generate an error if the global function does not exist). The local function can manipulate the arguments for the global function and then call the global function. The example local function modifies the local call to dbMoveFig to take a list of figures instead of a single figure. © Cadence Design Systems, Inc. All rights reserved. 176 This document is for the sole use of Firuz Shomahmadov of Nxp labels: Recursive Local Functions (labels ( (local_function_name (arg list) local…function…expressions labels( ((getPropInfo (prop) list( prop~>name prop~>valueType prop~>value )) (getPropInfoList (propList) sortcar( mapcar( getPropInfo propList ) ‘alphalessp) ) ) local_function_name( arg1 list1) ) ) body…function…expressions local_function_name( argValue listValue ) more…body…expressions ) let(((sel geGetSelectedSet())) getPropInfoList(sel~>master~>parameters ~>value) ) ; ** let ** ) ; ** labels ** ● Labels create named local functions like flet. ● Functions created inside labels can call themselves. ● The local function has no access to the same named global function. 177 © Cadence Design Systems, Inc. All rights reserved. The labels statement creates local functions that are callable within the lexical scope in which they were defined, just like flet. The difference between flet and labels is that the function defined in labels can call itself. In a flet-defined function, the call to the same function name executes the global version of that function if that exists. The labels defined function will call itself. This example uses labels to declare two local functions, getPropInfo and getPropInfoList. They were declared with labels because getPropInfoList calls getPropInfo inside the lambda. © Cadence Design Systems, Inc. All rights reserved. 177 This document is for the sole use of Firuz Shomahmadov of Nxp procedure: Declared Local Functions ● This is the same as the previous example but implemented using the procedure to define the local functions. It may be easier to understand when written this way; there is no difference in performance. let((sel) procedure(getPropInfo(prop) list( prop~>name prop~>valueType prop~>value) ) procedure(getPropInfoList(propList) sortcar( mapcar( getPropInfo propList) alphalessp) ) sel = geGetSelectedSet() getPropInfoList( sel~>master~>parameters~>value) ) ; ** let ** 178 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 178 This document is for the sole use of Firuz Shomahmadov of Nxp Module Summary In this module, you ● Identified local function usage ● Implemented flet function to define a local function ● Examined the use of labels and procedure functions for recursion 179 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 179 This document is for the sole use of Firuz Shomahmadov of Nxp Lab Lab 14-1 Implementing Local Functions in the SKILL Programs 180 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 180 This document is for the sole use of Firuz Shomahmadov of Nxp Packages Module 15 Revision 2.0 Version IC 6.1.8/ ICADVM 20.1 Estimated time: ● Lecture 15 minutes ● Lab 15 minutes This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 181 This document is for the sole use of Firuz Shomahmadov of Nxp Module Objectives In this module, you ● Identify package contents ● Define the package ● Define and implement stack package in SKILL++ 182 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 182 This document is for the sole use of Firuz Shomahmadov of Nxp What Are Packages? A package is a collection of functions and data. ● SKILL++ facilitates two approaches to packages. ▪ It can explicitly represent the package as a collection of function objects and data. o Different packages can have functions with the same name. ● Functions within a package share private data and private functions that are not accessible outside the package. ● A package hides the implementation details from the client application. o Clients use the arrow(->) operator to retrieve the package functions. ▪ You can reimplement a collection of SKILL® functions as a SKILL++ package. o Because informal SKILL packages have no opportunity to hide private functions or data. ▪ Interface to the package is through the package programming interface. Notes: You can reimplement a collection of SKILL functions as a SKILL++ package because informal SKILL packages have no opportunity to hide private functions or data. 183 © Cadence Design Systems, Inc. All rights reserved. A package is a group of functions and data that provide a programming interface to client applications. The package is self-contained, hiding the implementation details from the client applications. The package supplies procedures to access the data in the package. The data in a package is hidden and usually only accessible through the programming interface provided by the public functions in the package. The package may include helper functions that are private and can only be executed by the public functions of the package. © Cadence Design Systems, Inc. All rights reserved. 183 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Implementing SKILL++ Stack Package The local variable contents is a shared private lexically scoped variable. procedure( TrMakeStack(@key initialContents) let( (( contents initialContents )) procedure( popStack( ) let( (( v car( contents ))) The local variable, contents, is a shared private lexically scoped variable. contents = cdr( contents ) v)) Local Functions procedure( pushStack( value ) contents = cons( value contents ) value) list(nil 'pop popStack 'push pushStack ))) 184 pop and push are returned and access the local functions. © Cadence Design Systems, Inc. All rights reserved. The stack package declares a local variable named contents. Two local functions are declared: push and pop. They are exported in the disembodied property list return value. © Cadence Design Systems, Inc. All rights reserved. 184 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Implementing SKILL++ Stack Package (continued) ● Independent stacks can be created using TrMakeStack. ● Each manages its own contents. stack1 = TrMakeStack( ?initialContents list( 1 2 3 4 5)) stack1->pop() => 1 stack1->push( 7 ) => contents now: (7 2 3 4 5) 185 © Cadence Design Systems, Inc. All rights reserved. The function TrMakeStack creates a new instance of the stack. The variable contents are local to the stack as push and pop functions. The functions are evaluated using the variable holding the stack definition returned by TrMakeStack. © Cadence Design Systems, Inc. All rights reserved. 185 This document is for the sole use of Firuz Shomahmadov of Nxp Labs Lab 15-1 Implementing a Simple Counter Data Type in the SKILL Language Lab 15-2 Implementing a SKILL++ Counter Data Type Lab 15-3 Re-Implementing the Counter Data Type (Optional) 186 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 186 This document is for the sole use of Firuz Shomahmadov of Nxp Indirect Function Calls Module 16 Revision 2.0 Version IC 6.1.8/ ICADVM 20.1 Estimated time: ● Lecture 30 minutes ● Lab 30 minutes This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 187 This document is for the sole use of Firuz Shomahmadov of Nxp Module Objectives In this module, you ● Analyze indirect function calls with apply and funcall statements ● Create anonymous functions using the lambda function ● Use anonymous functions with sort and mapping functions 188 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 188 This document is for the sole use of Firuz Shomahmadov of Nxp apply: Evaluate a Function on a List of Arguments apply(slu_func [g_arg..] l_args) => g_result The apply function applies the given function to the given arguments. ● apply takes two or more arguments. ● The first argument should be a function or an object name or list containing lambda/nlambda expression. ● The last argument to apply must always be a list. Example apply(plus (list 1 2)) ; Apply plus to its argument => 3 189 © Cadence Design Systems, Inc. All rights reserved. The apply function is used to evaluate a function on a list of arguments; it is useful for evaluating lambda functions or named functions. The list of arguments are assigned to the argument list of the function, with keyed or optional arguments mapped to the keyed arguments of the function. The last element in the list must be a list. © Cadence Design Systems, Inc. All rights reserved. 189 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Evaluate a Function on a List of Arguments procedure( sumTail(1) apply(plus cdr(1))) => sumTail ; Define a procedure sumTail( ‘(1 2 3) => 5 setOfNumbers = '(1 2 5 -2 3 9 18 -7 0) sum = apply(plus setOfNumbers) => 29 theMin = apply(min setOfNumbers) => -7 theMax = apply(max setOfNumbers) => 18 Note: In SKILL® mode, call apply with a quoted function name. sum = apply(‘plus setOfNumbers) 190 © Cadence Design Systems, Inc. All rights reserved. The sort commands iterate over a list and use a comparison function to compare each element in the list two at a time. The comparison function takes two arguments and returns t if they are in the proper order or nil if they are not. In the example, the function is an anonymous lambda function that compares the y values of the two arguments and returns t if the y value of the second point in the list is less than the first one. How would you write a lambda sort that sorts by X and Y, where the results are sorted by the X coordinate and, if they are equal, are sorted by the Y coordinate? © Cadence Design Systems, Inc. All rights reserved. 190 This document is for the sole use of Firuz Shomahmadov of Nxp funcall: Evaluating a Function funcall(slu_func [arg……]) => g_result The funcall function calls a function with the set of given arguments. ● This function is similar to the apply function. ● The first argument should be a function or an object name or lambda/nlambda expression. ● The rest of the arguments are to be passed to the slu_func. ● If the slu_func is a lambda function, then: ▪ The length of the arg should match the number of formal arguments unless keywords or optional arguments exist. ▪ The arg is bound directly to the single formal parameter of the function. Example funcall(plus 1 2) ; Apply plus to its argument => 3 191 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 191 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Creating Match and Iterator Functions Using funcall Here we create our own Match and Iterator functions. ;; Match function procedure( TrShapeMatches( shapeId ) shapeId~>layerName == "metal1" && shapeId~>objType == "rect" ) ;; Iterator function procedure(TrIterator(cv matchFunc moveOrCopyFunc @optional (transform '((0 0) "R0" 1))) foreach( mapcan shape cv~>shapes when( funcall(matchFunc shape) list( funcall(moveOrCopyFunc shape cv transform)) ) ; when ) ; foreach ) ; procedure 192 © Cadence Design Systems, Inc. All rights reserved. We will use these two functions next. © Cadence Design Systems, Inc. All rights reserved. 192 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Using TrIterator with TrShapeMatches and dbCopyFig ; Create a cellview with several shapes on several layers cv = dbOpenCellViewByType( "master" "copytest" "layout" "maskLayout" "w") dbCreateRect( cv "metal1" list(0:0 10:10)) ; create a rectangle on metal1 dbCreateRect( cv "metal2" list(20:0 30:10)) ; create a rectangle on metal2 dbCreatePath( cv "metal1" list(0:0 20:0 20:30) 1.0) ; create a path on metal1 ; Query the data – there should be three shapes in the cellview foreach( mapcar shape cv~>shapes list( shape~>layerName shape~>objType )) => (("metal1" "rect") ("metal2" "rect") ("metal1" "path")) ; Copy the metal1 rectangles (see TrShapeMatches on prior slide) ; This will copy just the one metal1 rectangle shape that matches in this case TrIterator( cv ‘TrShapeMatches ‘dbCopyFig) => (db:0x16fed11d) ; Query again - there should now be four shapes in the cellview including two metal1 shapes. Examine the bBox for each to see they have the same coordinates foreach( mapcar shape cv~>shapes list( shape~>layerName shape~>objType shape~>bBox)) => (("metal1" "rect" ( (0.0 0.0) (10.0 10.0) )) ("metal2" "rect“ ( (20.0 0.0) (30.0 10.0) )) ("metal1" "path" ( (0.0 -0.5) (20.5 30.0) )) ("metal1" "rect" ( (0.0 0.0) (10.0 10.0) ))) 193 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 193 This document is for the sole use of Firuz Shomahmadov of Nxp lambda: Creating Anonymous Functions lambda((s_formalArgument) g_expr1……) or (lambda(s_formalArgument) g_expr1……) => U_result The lambda creates a function object. ● (lambda((x y) x + y ) 5 6) ● lambda is the constructor for a function. ● trAddWithMessageFun = lambda((x y) => 11 ● Declares unnamed function object. printf(“Adding %d and %d = %d\n” x y x+y) ● It can be used for immediate use, like x+y ▪ Sort functions ) ▪ Mapping functions => funobj:0x1814b90 ● Function object can be saved in variables. ● apply( trAddWithMessageFun ‘(4 5)) => 9 ● Can pass into other functions. 194 © Cadence Design Systems, Inc. All rights reserved. Lambda declares an unnamed function. These functions are useful for immediate use, such as in map or sorting functions. The function object can be saved in a variable and executed using apply or funcall. © Cadence Design Systems, Inc. All rights reserved. 194 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Sorting Using lambda Functions ● Sort command iterate over a list. ● It uses comparison to compare two elements at a time. ▪ Returns t, if the elements are in order. ▪ Returns nil, if they are not in order. ● Sort points by Y. sort( pointList lambda( ( p1 p2) yCoord(p1) < yCoord(p2)) Sort comparison function lambda( ( p1 p2) yCoord(p1) < yCoord(p2)) Arguments 195 Body © Cadence Design Systems, Inc. All rights reserved. The sort commands iterate over a list and use a comparison function to compare each element in the list two at a time. The comparison function takes two arguments and returns t if they are in the proper order or nil if they are not. In the example, the function is an anonymous lambda function that compares the y values of the two arguments and returns t if the y value of the second point in the list is less than the first one. How would you write a lambda sort that sorts by X and Y, where the results are sorted by the X coordinate and, if they are equal, are sorted by the Y coordinate? © Cadence Design Systems, Inc. All rights reserved. 195 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Mapping Across a List Using lambda Function ● mapcar evaluates the function over a list. ● The function is applied to each element in the list. ● The return value is determined by the mapping function. newPtList = mapcar( lambda(( xy ) dbTransformPoint( xy transform )) pointList ) lambda list ● Equivalent foreach( mapcar… expression) newPtList = foreach( mapcar xy pointList dbTransformPoint( xy transform )) 196 © Cadence Design Systems, Inc. All rights reserved. The map functions in SKILL are map, mapc, mapcan, mapcar, and maplist. These are non-destructive mapping functions that apply a function to each element in a list. They can be used with fo reach but are faster used standalone. The lambda function is useful for creating the processing function. The example function iterates over the list of points and applies dbTransformPoint to each point. The transform is a variable set outside the mapcar call. To see the difference between using mapcar and foreach, measure the time each iterates over a large list of data using the function measureTime. © Cadence Design Systems, Inc. All rights reserved. 196 This document is for the sole use of Firuz Shomahmadov of Nxp Example: lambda Functions as Variables ● lambda functions can be stored in variables. ● apply or funcall can be used to execute the function. ● The function can be passed in as an argument to a procedure. hypt = (lambda (x y) (sqrt (x*x + y*y))) apply(hypt '(2 8)) funcall(hypt 2 8) Both in SKILL and SKILL++ mode or hypt(2 8) 197 Only in SKILL++ mode © Cadence Design Systems, Inc. All rights reserved. The function object created by lambda can be stored in a variable. This variable can be used as any other variable; it can be passed into another function. Use apply or funcall to evaluate the function. © Cadence Design Systems, Inc. All rights reserved. 197 This document is for the sole use of Firuz Shomahmadov of Nxp Mapping Functions: Mapping for Side Effect (mapc/map) mapc( u_func l_arg1 [l_arg2…]) map( u_func l_arg1 [l_arg2…]) => l_arg1 => l_arg1 ● Primarily used with the u_func, which has side effects. ● This function does not preserve the values returned by this function. ● Applies the given function to successive sub lists of the argument lists. ● Returns the first argument list. ● Generally used for side effects, not for the return value. ● Returns the first argument list. ● Not same as standard Scheme map function. u_func Function to apply the argument lists u_func u_arg1 Function to apply successive sub lists Argument list u_arg2 u_arg1 Argument list Additional argument list (length same as u_arg1) u_arg2 l_arg1 Additional argument list (length same as u_arg1) The first argument list l_arg1 The first argument list Note: See the notes section for examples. 198 © Cadence Design Systems, Inc. All rights reserved. Examples for mapc and map functions: mapc: mapc( '(lambda (x y) (print (list x y))) '(1 2 3) '(9 8 7) ) => (1 9) (2 8) (3 7) ; prints three lists as side effects (1 2 3) ; actual return value mapc( lambda((@rest args) println(args)) '(4 3 5) '(6 7 6) '(1 2 3)) =>(4 6 1) (3 7 2) (4 6 3) ; the three lists are side effects (4 3 4) ; actual return value map: map( '(lambda (x y) (print (append x y))) '(1 2 3) '(9 8 7) ) => (1 2 3 9 8 7) (2 3 8 7) (3 7) ; the three lists are side effects (1 2 3) ; actual return value map( lambda((@rest args) println(args)) '(4 3 5) '(6 7 6) '(1 2 3)) => ((4 3 4) (6 7 6) (1 2 3)) ((3 4) (7 6) (2 3)) ((4) (6) (3)) ; the three lists are side effects (4 3 5) ; actual return value © Cadence Design Systems, Inc. All rights reserved. 198 This document is for the sole use of Firuz Shomahmadov of Nxp Mapping Functions: Mapping for Accumulation (mapcar/maplist) mapcar( u_func l_arg1 [l_arg2…]) maplist( u_func l_arg1 [l_arg2…]) => l_result => l_result ● Applies the u_func to the successive elements of the argument list. ● Applies the given function to successive sub lists of the argument lists. ● Returned values are put into a list. ● Returns a list of the corresponding results. ● If argument lengths are different, mapcar iterates till the end of the shortest list. ● The returned values of the successive function calls are concatenated using the list function. u_func Function to apply the argument lists u_func u_arg1 Function to apply the argument lists Argument list u_arg1 u_arg2 Argument list Additional argument list u_arg2 l_arg1 Additional argument list (length same as u_arg1) List of results from applying to successive elements of the argument list l_arg1 The first argument list mapcar( ‘plus ‘(4 3 5 7) ‘(6 7 6)) (10 10 11) mapcar( evenp ‘(4 3 5 7)) (t nil nil nil) 199 maplist( ‘list ‘(2 3 4) ‘(8 7 6)) (((2 3 4) (8 7 6)) ((3 4) (7 6)) ((4) (6))) maplist( copy ‘(4 3 5 7)) ((4 3 5 7) (3 5 7) (5 7) (7)) © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 199 This document is for the sole use of Firuz Shomahmadov of Nxp Mapping Functions: Mapping for Concatenation (mapcan/mapcon) mapcan( u_func l_arg1 [l_arg2…]) mapcon( u_func l_arg1 [l_arg2…]) => l_result => l_result ● The first argument must designate a function that returns a list. ● The first argument must designate a function that returns a list. ● The lists are concatenated as if by nconc. ● The lists are concatenated as if by nconc. ● mapcan example: ● mapcon example: u_func Function to apply the argument lists u_func Function to apply the argument lists u_arg1 Argument list u_arg1 Argument list u_arg2 Additional argument list (length same as u_arg1) u_arg2 Additional argument list (length same as u_arg1) l_arg1 List consisting of concatenated results l_arg1 The first argument list mapcan(( lambda (x) (println x) (list x x)) '(1 2 3)) ;; prints the following 1 2 3 Returns → (1 1 2 2 3 3) 200 mapcon((lambda (x) (println x) (copy (cdr x))) '(1 2 3)) ;; prints the following (1 2 3) (2 3) (3) Returns → (2 3 3) © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 200 This document is for the sole use of Firuz Shomahmadov of Nxp Mapping Functions with Multiple Arguments ● The mapping functions are usually called with exactly two arguments. ▪ An iteration function. ▪ A list of values to pass iteratively to that function. ● Any mapping function may be called with multiple arguments. ● Mapping function will iterate until the shortest list is exhausted. (mapc (lambda (@rest x) (println x)) '(1 2 3) '(x y z) '(10 20 30 40 50)) ;; prints the following (1 x 10) (2 y 20) (3 z 30) 201 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 201 This document is for the sole use of Firuz Shomahmadov of Nxp Module Summary In this module, you ● Analyzed different functions, including: ▪ apply/funcall ▪ lambda ▪ mapc ▪ mapcar ▪ mapcon ● Implemented SKILL code using the above-listed functions for creating your own iteration and matching procedures ● Implemented anonymous functions with sort and mapping functions 202 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 202 This document is for the sole use of Firuz Shomahmadov of Nxp Labs Lab 16-1 Creating Extended Built-In Functions: Rod and Hi Lab 16-2 Implementing the mapappend Function Lab 16-3 Implementing Flatten and Deep-Copy 203 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 203 This document is for the sole use of Firuz Shomahmadov of Nxp Initializing Objects Module 17 Revision 2.0 Version IC 6.1.8/ ICADVM 20.1 Estimated time: ● Lecture 15 minutes ● Lab 30 minutes This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 204 This document is for the sole use of Firuz Shomahmadov of Nxp Module Objective In this module, you ● Create an instance of a class by using: ▪ makeInstance function ▪ initializeInstance @after method (for more flexibility in creating instances) 205 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 205 This document is for the sole use of Firuz Shomahmadov of Nxp What a makeInstance Function Does The makeInstance function creates an instance of a class. ● makeInstance ▪ Makes a new object of that class ▪ Initializes the instance's slots by calling the initializeInstance method internally on the class o Assigns the slot values using @initform and @initarg values us_class Class object or a symbol denoting a class object. The class must be either standardObject or a subclass of standardObject. u_?initArg1 value1 u_?initArg2 value2 The symbol u_initArg1 is specified in one of the slot specifiers in the defclass declaration of either us_class or a superclass of us_class. value1 is the initial value for that slot. Similarly for the pair u_initArg2 value2 and so forth. g_instance The instance which is created. The print representation of the instance resembles stdobj:xxxx, where xxxx is a hexadecimal number. ▪ Returns the initialized instance ● makeInstance syntax: makeInstance( us_class [ u_?initArg1 [ u_?initArg2 ) => g_instance 206 value1 ] value2 ] ... © Cadence Design Systems, Inc. All rights reserved. Objects are instances of classes. makeInstance creates an instance of a class by allocating the object and initializing the slots on the instance with the values assigned to the @initform and @initarg for the slots. The slot initialization is executed by calling the initializeInstance method on the pre-allocated instance. This method can be overwritten or enhanced for the class to initialize the slots with more complex data structures. To create an empty instance where the slots are not initialized, use allocateInstance. © Cadence Design Systems, Inc. All rights reserved. 206 This document is for the sole use of Firuz Shomahmadov of Nxp Example: makeInstance defclass( Circle ( GeometricObject ) (( center @initarg c ) ( radius @initarg r )) ) => t P = makeInstance( 'Point ?name "P" ?x 3 ?y 4 ) => stdobj:0x1d003c C = makeInstance( 'Circle ?c P ?r 5.0 ) => stdobj:0x1d0048 makeInstance( 'fixnum ) *Error* unknown: non-instantiable class - fixnum Note: When the slot initialization depends on other slots, we use initializeInstance @after methods 207 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 207 This document is for the sole use of Firuz Shomahmadov of Nxp What Is an initializeInstance @after Method? An initializeInstance @after method is a class-specific initialization method. ● When an instance of the class is initialized, the initializeInstance @after method is called. Characteristics of initializeInstance @after Method: ● This is the object constructor function for a class. ● Complex slot value calculations ● Self-referential slot setup Syntax: (defmethod initializeInstance @after ((self designLib ) @rest initargs ) … ) ▪ Get values from other slots ● Additional processing on input arguments ● Interface with other data ▪ Read data from disk ● Create or modify related data ▪ Create a library or cell 208 © Cadence Design Systems, Inc. All rights reserved. Create class-specific initialization methods by creating an initalizeInstance method for the class. This method is called when an instance of the class is initialized. If the method is defined as a primary method, it is more specific than the default primary method and will be called on an instance that contains uninitialized slots. The default value for the slot, specified by the @initform for the slot, will not be assigned without the user method executing callNextMethod. Any @initarg passed into the call to initializeInstance will be assigned to the proper slot. Another methodology for initializing the instance is to create an @after method rather than the primary method. The default primary method will execute initializing the @initarg and @initform slots; then, the class-specific initialize method will execute after the completion of all the primary methods. © Cadence Design Systems, Inc. All rights reserved. 208 This document is for the sole use of Firuz Shomahmadov of Nxp Example: initializeInstance @after Method Example 1: Pass the newly created object as the first argument. (defmethod initializeInstance @after ((curInst library ) @rest initargs ) ddCreateLib( getLibName( curInst ) getPath( curInst ) ) ) Example 2: Set the value of a slot based on an existing slot value. (defmethod initializeInstance @after ((curInst designLib) @rest initargs ) setProject( TRprojectLookup( getLibName( curInst ))) ) 209 © Cadence Design Systems, Inc. All rights reserved. The initializeInstance is executed after the object is created. Any @initarg arguments are used to initialize the slots before calling the initializeInstance method. The initial values for the slots may be set depending on whether the generic primary function is executed. This may be done by directly setting the initial value, using callNextMethod if there are overriding primary methods, or by writing @after methods. The initial values set with @initform are not available if the initializeInstance method is an @before method. © Cadence Design Systems, Inc. All rights reserved. 209 This document is for the sole use of Firuz Shomahmadov of Nxp Initializing Objects Summary ● Simple instance initialization can be done using the slot descriptors: ▪ @initform ▪ @initarg ● More complex initialization should be done with initializeInstance @after, for example: ▪ Slot initialization which depends on the order of slots initialized. ▪ Slots that depend on other slots. 210 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 210 This document is for the sole use of Firuz Shomahmadov of Nxp Lab Lab 17-1 Exploring Instance Initialization Examples 211 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 211 This document is for the sole use of Firuz Shomahmadov of Nxp Multiple Inheritance Module 18 Revision 2.0 Version IC 6.1.8/ ICADVM 20.1 Estimated time: ● Lecture 15 minutes ● Lab 15 minutes This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 212 This document is for the sole use of Firuz Shomahmadov of Nxp Module Objectives In this module, you ● Analyze the mechanics of multiple inheritance ● Create a class that inherits from multiple classes ● Analyze the order of inheritance of classes ● Identify the order of inheritance for slot values ● Plan and develop classes using multiple inheritance 213 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 213 This document is for the sole use of Firuz Shomahmadov of Nxp Single Versus Multiple Inheritance Single Inheritance is a feature defined as when a class inherits from a single superclass. ● The class hierarchy is built in a linear fashion. ● The subclass inherits slots and methods from only one superclass. A Multiple Inheritance is a feature defined when a class inherits from multiple immediate superclasses. ● The subclass inherits the slots and methods from each of the superclasses. ● It is determined by the order of the subclass declaration. B h C 214 Super Classes Sub Class © Cadence Design Systems, Inc. All rights reserved. SKILL++ has always supported single inheritance. Single inheritance means that a class can have only one superclass. The class hierarchy is built in a linear fashion, with each class inheriting methods and slots from its direct superclass. Single Inheritance is often the only hierarchy allowed by some languages. IC615 supports both single and multiple inheritance. A class with multiple immediate superclasses uses multiple inheritance. The subclass inherits the slots and methods from each of the superclasses determined by the order of the subclass declaration. © Cadence Design Systems, Inc. All rights reserved. 214 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Multiple Class Inheritance ZZtop A defclass( A () (…) ) defclass( B (A) (…) ) defclass( C (B) (…) ) XX defclass( XX () (…) ) B ZZ C h designClass defclass( ZZtop () (…) ) defclass( ZZ (ZZtop)(…) ) defclass( designClass (C XX ZZ) (…) ) instDC = makeInstance( 'designClass ) 215 © Cadence Design Systems, Inc. All rights reserved. Multiple inheritance is created using the same command as single inheritance. The superclasses are specified as a list. The order of the list determines the order of inheritance, the most specific and the first class in the superclass list, and its inherited superclasses. Then the designClass inherits the classes (and their superclasses) in the order of the list. The instance of designClass inherits all the slots of the superclasses. © Cadence Design Systems, Inc. All rights reserved. 215 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Multiple Class Inheritance (continued) ZZtop A XX B ZZ C h Most Specific designClass C B A XX ZZ ZZtop Least Specific designClass superclassesOf( classOf( instDC ) ) (Class:designClass class:C class:B class:A Class:XX class:ZZ class:ZZtop class:standardObject class:t) 216 © Cadence Design Systems, Inc. All rights reserved. It initially looks hard to determine the most specific to the least specific inherited classes. This order determines the initial value of the slots and the order of method evaluation. Use the information provided by superclassesOf and subclassesOf to determine the graph for the class hierarchy. The inheritance rule applied to the example is that the first class in the superclasses list is the most specific, and the classes it inherits from are more specific than the next class in the superclass list. This continues down the list of superClasses defclass( designClass ( C XX ZZ ) (…) ) C is the first superclass; it is the most specific of the superclasses of designClass. The superclasses of C and their hierarchy are more specific than XX. XX is more specific than ZZ, which is more specific than ZZtop. The least specific are the built-in standardObject and t classes. © Cadence Design Systems, Inc. All rights reserved. 216 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Multiple Slot Inheritance (counter …) Classes sharing slot names (counter…) ZZtop A XX B (counter …) ZZ C h ● All slots are inherited from all the classes. ● Slot @initargs are merged. ● All reader and writer accessors are usable on the appropriate class. designClass ● @initform value from the most specific declaration. 217 © Cadence Design Systems, Inc. All rights reserved. A class inherits the slots from its superclasses. Just like in single inheritance, classes used multiple inheritance may declare the same slot name. The duplicate slots can be set using any of the @initargs for that slot; this is very helpful when writing hierarchical initialization methods. The readers and writers are also usable. The @initform takes the value from the most specific class that specifies it. © Cadence Design Systems, Inc. All rights reserved. 217 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Multiple Slot Inheritance (continued) (counter …) Most Specific designClass C B A XX ZZ ZZtop ZZtop A XX B (counter …) ZZ C h Least Specific designClass (defclass B (A) ((counter @initarg counter @initform 0))) (defclass ZZtop () ((counter @initarg index @initform 1))) 218 © Cadence Design Systems, Inc. All rights reserved. In the example, the counter slot is declared in both class B and class ZZtop. designClass inherits from both classes but only has one slot named counter. It will have the @initargs of ?counter and ?index. The initial form, if not specified when the instance is created, is taken from the most specific @initform declared. In this example, the value is 0; class B is more specific than ZZtop. If the slot definition in class B did not have an @initform, the initial default value would be 1. Note that if you create an instance of class C (or B), only @initarg will counter, and the @initform is 0. If you create an instance of class ZZ, the counter value is independent of any other instance, and the @initform is 1. © Cadence Design Systems, Inc. All rights reserved. 218 This document is for the sole use of Firuz Shomahmadov of Nxp Multiple Inheritance Method Execution (Primary Methods) ZZtop A XX B ZZ C h Method Qualifier Specializer createLib designClass createLib C createLib A createLib XX createLib ZZtop designClass Method execution from most specialized to least specialized. 219 © Cadence Design Systems, Inc. All rights reserved. Multiple inheritance creates a method hierarchy which is often confusing, this is why some languages avoid it completely, but it is very powerful. The general rule is that the methods are evaluated from the most specific specializers to the least specific specializers. In the case of class specializers, the most specific class to the least specific class. In this diagram, the classes with the yellow spots have specialized on a method, myMethod. Executing myMethod specialized on designClass, the callNextMethod evaluates myMethod as specialized by class C. This continues down the class C hierarchy, evaluating myMethod(A). The callNextMethod executed in myMethod( A ) executes myMethod for class, the next most specific class. That method can stop the execution by not using callNextMethod or executing the method specialized on ZZtop using callNextMethod. The last method to execute in the callNextMethod line is the first method for that generic function. A method for a class will only be executed once as the "next method". If the class is a superclass to multiple classes, a method specializing on it will be in the same order as listed in the superclass. @before and @after methods execute based on the same superclass order, the @before methods evaluating from most to least specific and the @after methods evaluating from the least specific to the most specific. © Cadence Design Systems, Inc. All rights reserved. 219 This document is for the sole use of Firuz Shomahmadov of Nxp Multiple Inheritance with @before and @after Methods ZZtop A XX B ZZ C h designClass @before primary @after 220 Method Qualifier Specializer createLib @before designClass createLib @before C createLib @before A createLib @before XX createLib designClass createLib C createLib XX createLib ZZtop createLib @after ZZtop createLib @after ZZ createLib @after B createLib @after C © Cadence Design Systems, Inc. All rights reserved. Although it looks complex, the order of method execution follows the rules for single inheritance. The applicable @before methods are all evaluated, from the most specialized to the least specialized. The primary methods are evaluated from most specialized to least specialized if they all use callNextMethod. The @after methods are ordered from least specialized to most specialized and evaluated in that order. There is an error in this table. Can you spot it? © Cadence Design Systems, Inc. All rights reserved. 220 This document is for the sole use of Firuz Shomahmadov of Nxp Multiple Inheritance and Object-Oriented Pcells Object-oriented Pcells use inheritance to combine capabilities required for PDK-specific devices. Family class PDK class Dummies DFM h Component classes Device class: NMOS Family class: MOS withSymmetricSD withSDconnectivity PDK class: withNdoping withCMOS Component classes: withDummies MOSwithDFM withDFM Device class 221 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 221 This document is for the sole use of Firuz Shomahmadov of Nxp Diamond Class Definitions Perfectly Legal and Useful ● Multiple classes inherit from the same class. ● Multiply inherited classes appear only once in the class hierarchy. ● The hierarchy order is most specific to least specific. baseClass A ZZtop XX B ZZ C superclassesOf( classOf( instTC ) ) (class:designClass class:C class:B class:A class:baseClass class:XX class:ZZ class:ZZtop class:standardObject class:t) h designClass 222 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 222 This document is for the sole use of Firuz Shomahmadov of Nxp Multiple Inheritance Overview ● SKILL++ supports multiple inheritance. ● A class can have more than one direct superclass. ● All the slots in all the inherited classes are merged. ▪ All @initargs are usable. ▪ The most specific @initform determines the default value. ● Primary methods (other than most specific methods) are executed only if callNextMethod is used. ▪ Considering Execution Order: From most specific to least specific methods. ● @before methods execute before any primary methods. ▪ Considering Execution Order: From most specific to least specific methods. ● @after methods execute after primary methods are complete. ▪ Considering Execution Order: From least specific to most specific. 223 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 223 This document is for the sole use of Firuz Shomahmadov of Nxp Lab Lab 18-1 Implementing Multiple Class Inheritance in SKILL++ Code 224 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 224 This document is for the sole use of Firuz Shomahmadov of Nxp Methods (Advanced) Module 19 Revision 2.0 Version IC 6.1.8/ ICADVM 20.1 Estimated time: ● Lecture 30 minutes ● Lab 45 minutes This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 225 This document is for the sole use of Firuz Shomahmadov of Nxp Module Objectives In this module, you ● Use optional arguments to build methods ● Create methods that dispatch on more than one argument ● Create methods that specialize on arguments other than classes ▪ Analyze the usage of the generic specializers for the methods 226 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 226 This document is for the sole use of Firuz Shomahmadov of Nxp Adding Arguments to Methods defgeneric(s_func (s_arg1 [ @rest s_arg2..]) [g_exp..]) => t ● The generic function specifies the name of the method and the required arguments for the methods. ● Some methods may need additional data passed as arguments. ▪ It can be done by adding @optional or @key arguments. ● Generic function should be included with @rest argument to add @optional or @key. ● Methods may only specialize on required arguments. ● Only one method with a particular set of specializers can be defined. ▪ Additional keyed arguments are not additional specializers. ▪ Do not define two methods with the same specializers with different sets of keyed arguments. o Only the last one defined will be used. ● If the generic function declares an @rest variable, all derived methods should declare an @rest variable. 227 © Cadence Design Systems, Inc. All rights reserved. The generic function specifies the name of the method and the required arguments for the methods. The methods can only specialize on the required arguments. Methods for some classes may need additional data passed in as arguments. This can be done by adding the new arguments as @optional or @key arguments to the method. However, to do so, either these arguments are specified on the generic function and applied to all methods derived from that function, or the generic function includes the @rest argument. If the generic function includes @rest, all the derived methods must have an @rest argument defined as well. Including @rest allows methods to define their own @key or @optional arguments independent from other methods. When a method is executed, if some of the additional arguments are not in its argument list, those arguments are assigned to the @rest variable and essentially ignored. It is recommended that the named arguments defined by @key be used instead of the positional arguments defined by @optional. Using @optional arguments makes the methods depend on each other’s positional argument definition. In this class, we will teach using @key and ignore @optional. © Cadence Design Systems, Inc. All rights reserved. 227 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Adding Arguments to Methods (defgeneric pcoDraw (device cvId @rest _ignore)) (defmethod pcoDraw ((device MOS) cvId @rest _ignore )) …) (defmethod pcoDraw ( ( device withHV ) cvId @key termNode finger @rest _ignore ) …) 228 © Cadence Design Systems, Inc. All rights reserved. Methods are defined by their name and their specializers. Adding additional arguments, such as keyed arguments, to a new method will overwrite the definition of a method with the same specializer arguments. © Cadence Design Systems, Inc. All rights reserved. 228 This document is for the sole use of Firuz Shomahmadov of Nxp Using apply and callNextMethod with Methods Changing argument values (especially optional arguments) for callNextMethod. (defmethod genSHparamName (device (shape dbobject) @key (layer shape~>layerName) @rest initargs) (unless shape~>isShape (error "You cannot put a stretch handle on a %s" shape~>objType ) (apply callNextMethod device t ?layer layer initargs)) 229 © Cadence Design Systems, Inc. All rights reserved. Apply is very useful with object-oriented methods. Multiple methods can share the same name; they are specialized by their required arguments. In this example, the method dtlGenSHparamName is evaluated when a second argument is a database object. If the object has a layer, the next method is called with an extra keyed argument ?layer and the value of the shape’s layer. © Cadence Design Systems, Inc. All rights reserved. 229 This document is for the sole use of Firuz Shomahmadov of Nxp Method Rules: Additional Arguments ● The generic function can have the following arguments: ▪ @optional ▪ @key ▪ @rest ● The @rest argument supports creating additional method arguments. ● @optional and @key arguments can be added to any method where the generic method has an @rest argument. ▪ @key arguments are preferred. ● The optional arguments cannot be used to specialize the method. ▪ Specializers only work only on required arguments. ● Any argument not consumed by previous arguments stored in @rest argument. 230 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 230 This document is for the sole use of Firuz Shomahmadov of Nxp What Is Multi-Method Dispatch? With multi-method dispatch, all arguments of a method are treated equally, and the method to be applied is decided at runtime, based on the dynamically-determined types of arguments. ● When you define more than one method with the same name in your code, and when the method call is made, instead of one parameter specializer determining the method to be applied, it is determined by multiple parameter specializers. ● The method is applicable if all required arguments match the corresponding declared specializers. ● The generic function sets the required arguments. ● Any or all those arguments can be used as a specializer. (defmethod add ((x WholeNumber) (y WholeNumber)) (makeInstance 'WholeNumber ?sign (GetSign x) ?digits (addDigits (GetDigits x) (GetDigits y)) ) ) 231 © Cadence Design Systems, Inc. All rights reserved. Methods in SKILL++ can have more than one specializer. The specializers can only be set on the required arguments as defined in the generic function. All of the specialized arguments are tested for a match before the method is executed. Any of the required arguments can have a specializer; unspecialized arguments are not tested to determine if the method is executed. © Cadence Design Systems, Inc. All rights reserved. 231 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Multi-Method Dispatch (defgeneric add ( _arg1 _arg2 @rest _ignore )) Required arguments for this method (potential specializers) (defmethod add ( (arg1 wholeNumber) arg2 @rest _ignore ) … ; Specializes on arg1 being class wholeNumber callNextMethod() ) (defmethod add ( arg1 (arg2 rational) @rest _ignore ) … ; Specializes on arg2 being class rational callNextMethod() ) (defmethod add ( (arg1 wholeNumber) (arg2 rational) @rest _ignore ) … ; arg1 a wholeNumber and arg2 a rational callNextMethod() ) 232 © Cadence Design Systems, Inc. All rights reserved. The generic function defines the potential specializer arguments as required arguments. The methods can then specialize on those arguments, individually or more than one. A method is called when all the specializer arguments match the call. The specializer tests the value of the argument and determines if there is a match. If it matches, that specializer is true. Non-specialized arguments are not tested for matching when the method is chosen for execution. The method with the most matching specialized arguments is the most specific method and is the first primary method executed; then, the order of execution is determined by the position of the matching arguments. © Cadence Design Systems, Inc. All rights reserved. 232 This document is for the sole use of Firuz Shomahmadov of Nxp Multi-Method Dispatch: Method Execution Order add( wholeNumberObject rationalObject ) add( (arg1 wholeNumber) (arg2 rational) ) callNextMethod() add( (wholeNumber A) arg2) callNextMethod() Most specific First argument more specific than second argument add( arg1 (rational B)) callNextMethod() Least specific add( arg1 arg2 ) 233 © Cadence Design Systems, Inc. All rights reserved. The method execution order (for @before and primary methods) is from most specific to least specific. The order is determined by the order of the specializer in the argument list in the method. In this example, add is called with both a wholeNumber object as the first argument and a rational object as the second argument. The first method executed has both matching specializers. Then the method that specializes on argument one is executed with callNextMethod. This is because the specializer is on the first argument, which is more specific than the method that specializes on the second argument. The method with the argument on the second argument is executed next, and finally, the method that does not specialize on any argument is executed. © Cadence Design Systems, Inc. All rights reserved. 233 This document is for the sole use of Firuz Shomahmadov of Nxp Multi-Method Dispatch: Method Rules ● Methods can specialize on more than the first argument. ● Methods can specialize only on required arguments. ● Additional specializers are added to the method. ▪ Execute method only if all the specializer requirements are fulfilled. ● Method becomes more specialized, and the order of specializer declaration determines the method execution order. 234 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 234 This document is for the sole use of Firuz Shomahmadov of Nxp Quick Reference Guide: Method Specialization ● All objects in SKILL® and Virtuoso® have a class. ● Methods can specialize on the SKILL classes. Examples 235 Class Name That Is Returned className(classOf( 5 ) ) fixnum className(classOf(3.4)) flonum className(classOf( "this string" ) string className(classOf( ‘mySymbol )) symbol className(classOf( ‘(nil x 1 y 2 ))) list className(classOf( list( 0:0 8:12))) list className(classOf( nil ))) list className(classOf(makeTable…)) assocTable className(classOf( lambda(…))) funobj © Cadence Design Systems, Inc. All rights reserved. Everything known in SKILL has a class. These classes can be used as specializers on methods, but be aware that all database objects return the class dbobject. © Cadence Design Systems, Inc. All rights reserved. 235 This document is for the sole use of Firuz Shomahmadov of Nxp Generic Specializers ● Generic specializer functions are focused on different objects. ● You can have multiple implementations of the same function by using generic specializer functions. ▪ Makes the code easier to maintain and develop, as it avoids having function calls within the code to switch between different objects. ● Some of the generic specializers are: 236 Generic Specializer Description ilArgMatchesSpecializer Determines whether the arguments passed at runtime match a particular class so that then it knows which method should be called. ilEquivalentSpecializers Defines a method to check if two specializers are equal. This would be required during method redefinition. ilGenerateSpecializer Returns SKILL expression that makes an instance of given specializer class and optionally sets the slots. ilSpecMoreSpecficp Checks if spec1 is more specific than spec2. For this, you need to define all the required ilSpecMoreSpecficp methods. © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 236 This document is for the sole use of Firuz Shomahmadov of Nxp Method Rules: Specializers ● Class – Methods may be specialized on class (by name). ● eqv – Tests the value of argument and must satisfy eqv comparison. 237 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 237 This document is for the sole use of Firuz Shomahmadov of Nxp Labs Lab 19-1 Implementing the Methods by Adding Additional Arguments for Extended Capabilities Lab 19-2 Implementing Equivalence Specializers Lab 19-3 Implementing objType Specializers 238 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 238 This document is for the sole use of Firuz Shomahmadov of Nxp Control Flow (Optional) Module 20 Revision 2.0 Version IC 6.1.8/ ICADVM 20.1 Estimated time: ● Lecture 30 minutes ● Lab NA This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 239 This document is for the sole use of Firuz Shomahmadov of Nxp Module Objective In this module, you ● Analyze the following control flow operators ▪ prog/return ▪ exists/forall ▪ errset ▪ unwindProtect ▪ catch/throw 240 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 240 This document is for the sole use of Firuz Shomahmadov of Nxp Using prog and return prog( localVar ((s_label) expr1) ……) =>g_result/nil ● The prog statement allows local variables bindings and permits abrupt exits on control jumps. ● The argument to prog: localVar List of variables declared to be local within the prog s_label Labels a statement inside the prog expr1 Expressions are executed sequentially unless one control transfer statements like go, or return is encountered ● If no return statement is executed. ▪ It evaluates to the value nil, and control simply falls through the prog after the last expression is executed. ● If a return is executed within a prog. ▪ The prog immediately returns with the value of the argument given to the return statement. ● Unless multiple return points are necessary or you are using the go functions, the let should be used over prog. 241 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 241 This document is for the sole use of Firuz Shomahmadov of Nxp Example: Using prog and return Examples showing the usage of prog and return Example 1 (prog (a) a = (prog () ... (return 42)) ;; a has the value 42 ...) Example 2 x = "hello” => "hello" prog( (x y) ; Declares local variables x and y. x = 5 ; Initialize x to 5. y = 10 ; Initialize y to 10. return( x + y ) ) => 15 x => "hello“ ;The global x keeps its original value. Note: 1. The return and the prog need not be in the same function, but this is considered poor style., and 2. Prog also allows zero or more named variables to be bound to nil. 242 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 242 This document is for the sole use of Firuz Shomahmadov of Nxp Using catch and throw catch(tag form) and throw(tag value) or (catch tag form) and (throw tag value) ● This is similar to prog/return except that throw names the catch tag, which it returns to. ● The second argument of throw indicates the value that the corresponding catch should return. Example (catch 'tag_break (for k 1 100 (catch 'tag_next (when (test1 K) (throw 'tag_next nil)) ;; next K (when (test2 K) (throw 'tag_break K)) ;; break out of the for loop (println K))) 243 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 243 This document is for the sole use of Firuz Shomahmadov of Nxp Using exists and forall exists(varName mylist expr1) forall(varName mylist expr1) => g_result => t/nil ● exists halts iteration when the test condition becomes true. ● forall checks if expr1 evaluates to non-nil for every element in myList. ● Returns the first tail of mylist whose car satisfies a predicate expression. ● Returns t, if expr1 evaluates to non-nil for every element in myList. ● Returns nil, if none of the elements in mylist satisfies the expr1. ● Returns nil, if the above condition does not satisfy. exists(x '(1 2 3 4) (x>1)) forall(x '(1 2 3 4) (x>0)) (2 3 4) t exists(x '(1 2 3 4) (x>4)) forall(x '(1 2 3 4) (x<4)) nil nil These are iteration constructs that halt iteration on particular conditions. 244 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 244 This document is for the sole use of Firuz Shomahmadov of Nxp Using errset errset(expr1) or (errset expr1) =>g_result/nil ● The errset statement encapsulates the execution of an expression in an environment the same as the error mechanism. ● If an error occurs in evaluating the given expression, control always returns to the command, following the errset instead of returning to the nearest top-level. ● If the result is non-nil, error messages are issued; otherwise, they are suppressed. ● In either case, information about the error is placed in the errset property of the errset symbol. ● Programs can therefore access this information with the errset.errset construct after determining that errset returned nil. When working in the CIW, ensure that the errset.errset variable is not modified internally in the Virtuoso® design environment, do not separate errset and errset.errset. For example, see the last example above. 245 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 245 This document is for the sole use of Firuz Shomahmadov of Nxp Examples: Using errset 246 errset(1+2) →(3) errset(sqrt(‘x)) →nil errset(sqrt(‘x)),errset.errset →("sqrt" 0 t nil("*Error* sqrt: can't handle sqrt(x) © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 246 This document is for the sole use of Firuz Shomahmadov of Nxp Using unwindProtect unwindProtect((unsafe)(cleanup)) or (unwindProtect unsafe (cleanup)) =>g_result ● Attempts to evaluate unsafe, which may or may not be complete. ● Evaluates cleanup whether unsafe completed or not. Example (unwindProtect 1/D (printf "attempted to divide by %L\n" D)) ● Returns the value of unsafe if it is completed. ● Invokes the error otherwise. ● Returns the quotient if D is not zero. ● Useful for cleanup of temporary files, etc. ● Prints the message in any case. ● Invokes the error if D is zero. 247 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 247 This document is for the sole use of Firuz Shomahmadov of Nxp Using unwindProtect (continued) unwindProtect can be used in the mode of try/except to execute the except form only if the try form fails. (let ((finished nil)) (unwindProtect (progn (myGenerateLogFile "/tmp/my.log" ) finished = t) (unless finished (deleteFile "/tmp/my.log" )))) ● This code attempts to generate a log file. ● If myGenerateLogFile returns, finished will be set to t. ● If the cleanup form finds the finished as nil yet, it will delete the file. 248 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 248 This document is for the sole use of Firuz Shomahmadov of Nxp Module Summary In this module, you ● Analyzed the following control flow operators ▪ prog/return ▪ exists/forall ▪ errset ▪ unwindProtect ▪ catch/throw 249 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 249 This document is for the sole use of Firuz Shomahmadov of Nxp Next Steps Module 21 Revision 2.0 Version IC 6.1.8 / ICADVM 20.1 Estimated Time: ● Lecture 5 minutes ● Lab NA This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 250 This document is for the sole use of Firuz Shomahmadov of Nxp Learning Maps Cadence® Training Services learning maps provide a comprehensive visual overview of the learning opportunities for Cadence customers. Click here to see all our courses in each technology area and the recommended order in which to take them. 251 © Cadence Design Systems, Inc. All rights reserved. Go here to view the learning maps: http://www.cadence.com/Training/Pages/learning_maps.aspx © Cadence Design Systems, Inc. All rights reserved. 251 This document is for the sole use of Firuz Shomahmadov of Nxp Cadence Learning and Support Cadence Support now includes over 2000 product/language/methodology videos (“Training Bytes”)! 252 © Cadence Design Systems, Inc. All rights reserved. Click here to view the demo of Cadence Learning and Support. © Cadence Design Systems, Inc. All rights reserved. 252 This document is for the sole use of Firuz Shomahmadov of Nxp Wrap Up ● Complete Post Assessment, if provided ● Complete the Course Evaluation ● Get a Certificate of Course Completion Thank you! 253 © Cadence Design Systems, Inc. All rights reserved. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 253 This document is for the sole use of Firuz Shomahmadov of Nxp © Cadence Design Systems, Inc. All rights reserved worldwide. Cadence, the Cadence logo, and the other Cadence marks found at https://www.cadence.com/go/trademarks are trademarks or registered trademarks of Cadence Design Systems, Inc. Accellera and SystemC are trademarks of Accellera Systems Initiative Inc. All Arm products are registered trademarks or trademarks of Arm Limited (or its subsidiaries) in the US and/or elsewhere. All MIPI specifications are registered trademarks or service marks owned by MIPI Alliance. All PCI-SIG specifications are registered trademarks or trademarks of PCI-SIG. All other trademarks are the property of their respective owners. This page does not contain notes. © Cadence Design Systems, Inc. All rights reserved. 254