https://www.cnblogs.com/yeungchie/
寫個大筆記,低速更新中 ...
Cadence Skill
Cadence 提供二次開發的 SKILL 語言,它是一種基於通用人工智慧語言— Lisp 的互動式高階程式語言 (1)。
SKILL 語言支援一套類似 C 語言的語法,大大降低了初學者學習的難度,同時高水平的程式設計者可以選擇使用類似 Lisp 語言的全部功能。所以 SKILL 語言既可以用作最簡單的工具語言,也可以作為開發任何應用的、強大的程式語言。
SKILL 可以與底層系統互動,也提供了訪問 Cadence 各個工具的豐富介面。使用者可以通過 Skill 語言來訪問,並且可以開發自己的基於 Cadence 平臺的工具。
LISP 即 List Processing-表處理,是最早和最重要的符號處理程式語言之一,它於1958年由美國的 J. McCarthy 提出,LISP 在人工智慧AI方面獲得廣泛應用。
我的環境是 Virtuoso IC618 平臺,可能存在某些特性不適用於舊版本。
如何檢視官方資料
cdsFinder
- 用於模糊查詢 Skill 函式,及檢視簡單介紹。
which cdsFinder
# $CDSHOME/tools/bin/cdsFinder
cdnshelp
- 用於檢視更加詳細的內容,以軟體的使用手冊。
which cdnshelp
# $CDSHOME/tools/bin/cdnshelp
程式碼風格
語法風格
由於 Skill 語言是基於 Lisp ,因此它支援 函式表示法
和 字首表示法
來書寫程式碼。
-
函式表示法
func( arg1 arg2 )
-
字首表示法
( func arg1 arg2 )
以上的兩種表示法可以同時存在,因此在編寫程式碼時候最好注意格式的統一。
推薦統一使用 函式表示法
,並需要注意函式名和括號之間不能有空格。
錯誤寫法 :
func ( arg1 arg2 )
func
後面多了一個空格,這會將arg1
作為函式名
命名風格
其次函式和變數的命名風格,Skill 中一般是使用 駝峰命名法 ( Camel-Case ),函式名中的每一個邏輯斷點(單詞)首字母大寫,開頭第一個單詞全部小寫,一般代表 函式/變數 的類別、作者,像我寫的函式和全域性變數一般都習慣用 yc
開頭。
這也是現在更為流行的一種命名方式,相對於傳統的 下劃線命名法,不會使較長的命名顯得更長,且更加能提高可讀性,當程式碼量上來的時候,滿屏的下劃線看起來會非常蛋疼。
下面是一個對比
-
駝峰命名法
geGetEditCellView() dbOpenCellViewByType(libName cellName viewName nil mode)
-
下劃線命名法 ( 不推薦 )
ge_get_edit_cell_view() db_open_cell_view_by_type(lib_name cell_name view_name nil mode)
最後再注意命名不能過於簡化,例如 a
,b
,c
。命名的目標是至少讓人能一眼看出來這個變數是做什麼用的 ( 一眼不行看兩眼 ),例如上面的 libName
,cellName
,viewName
。
下面介紹語法部分我會使用的一些非常簡化變數命名,因為只是用於演示,命名就會比較隨意了。
基礎語法
hello world
舉例三種 print 寫 hello world,後面會具體講幾種 print 函式的區別。
print( "hello world" )
println( "hello world" )
printf( "%s\n" "hello world" )
註釋
單行註釋
; 這是單行註釋
多行註釋
/*
這是多行註釋
*/
資料型別
可以用函式 type
檢視一個資料的型別標識。
type( 'YEUNGCHIE ) ; symbol
type( "YEUNGCHIE" ) ; string
type( list( "YEUNGCHIE" )) ; list
用 println
列印一個資料的內容,同時也能夠從列印結果觀察到資料型別。
println( 'YEUNGCHIE ) ; YEUNGCHIE
println( "YEUNGCHIE" ) ; "YEUNGCHIE"
println( list( "YEUNGCHIE" )) ; ( YEUNGCHIE )
資料型別標識
官方的教程中一般會用來表明函式需要的輸入資料是什麼型別的( 標在字首 )。也用於限制子函式輸入資料的型別。
字首 | 內部命名 | 資料型別 |
---|---|---|
d | dbobject | id , Cadence 資料物件 |
x | integer | 整數 |
f | flonum | 浮點數 |
n | number | 整數 或者 浮點數 |
g | general | 通用的 , 任何資料型別 |
l | list | 連結串列 |
p | port | I / O 控制程式碼 |
t | string | 字串 |
s | symbol | " 符號 " |
S | stringSymbol | " 符號 " 或者 字串 |
u | function | 函式物件 , 函式名 或者 lambda物件 |
標量
字串
定義方式
字串用雙引號括起來。
"YEUNGCHIE"
; "YEUNGCHIE"
字串連線
strcat
a = "YEUNG"
b = "CHIE"
c = strcat( a b )
println( c )
; "YEUNGCHIE"
字串長度
strlen
下面的 c 沿用上面的變數 c,為了教程不寫得過於繁雜、重複。
println(strlen( c ))
; 9
數字
數字分為 整數 和 浮點數。
整數
18
也可以直接編寫成 二進位制 ( 0b
字首 )、八進位制 ( 0
字首 )、十六進位制 ( 0x
字首 ),但預設會輸出成 十進位制
0b10010 ; 18
024 ; 20
0xFE ; 254
浮點數
3.14
浮點數也可以使用 科學計數法 和 單位字尾 來表示
1e-06 ; 0.000001
1u ; 0.000001
symbol
id
連結串列 list
定義方式
-
list( arg1 arg2 list( arg3 arg4 ) ... )
listA = list( 1 2 ) ; ( 1 2 )
-
'( "value1" sym1 (1 2) ... )
這種表達方式需要注意,它不適用於變數元素,例如上面
sym1
並不會帶入變數值,而是 symbol 型別'sym1
listB = '( 3 4 ) ; ( 3 4 )
-
arg1 : arg2
僅在只有兩個元素時使用,通常用來表達一個座標點
point = 1 : 2 ; ( 1 2 )
連線兩個 list
-
append
listC = append( listA listB ) println( listC ) ; ( 1 2 3 4 )
往 list 追加元素
-
append1
往末尾追加
listD = append1( listC 5 ) println( listD ) ; ( 1 2 3 4 5 )
-
cons
往開頭追加
listE = cons( 0 listD ) println( listE ) ; ( 0 1 2 3 4 5 )
翻轉一個 list
-
reverse
listF = reverse( listE ) println( listF ) ; ( 5 4 3 2 1 0 )
獲取一個 list 元素個數
-
length
length( listF ) ; 6
提取 list 中的元素
-
car 提取第一個元素
car( listF ) ; 5
-
cdr 提取除了第一個元素之後的 list
cdr( listF ) ; ( 4 3 2 1 0 )
-
cadr 及其更多組合
cadr( listF )
其實就是car(cdr( listF ))
的簡寫cadr( listF ) ; 4 caddr( listF ) ; 3
-
nth 根據索引提取
nth( 0 listF ) ; 5 nth( 1 listF ) ; 4 nth( length(listF)-1 listF ) ; 0
陣列 / 向量
陣列 和 向量 不常用,瞭解一下長什麼樣就行。
陣列
-
定義
declare
declare( ARRAY[10] )
-
賦值
ARRAY[2] = 4 ARRAY[3] = 5
-
引用
println( ARRAY[2] * ARRAY[3] ) ; 20 println( ARRAY[0] ) ; unbound println( ARRAY[11] ) ; *Error* arrayref: array index out of bounds - ARRAY[11]
向量
-
定義
makeVector
VECTOR = makeVector( 10 )
-
賦值
VECTOR[2] = 4 VECTOR[3] = 5
-
引用
println( VECTOR[2] * VECTOR[3] ) ; 20 println( VECTOR[0] ) ; unbound println( VECTOR[11] ) ; *Error* arrayref: array index out of bounds - VECTOR[11]
對照表 / 雜湊
某些情況下可能需要用到雜湊來優化程式碼邏輯和速度等等。
定義
makeTable
HASH = makeTable( 'HASH )
賦值
HASH[1] = "ONE"
HASH["2"] = 2
HASH[cvId] = "cellName"
引用
-
檢視一個雜湊的所有 key / value
HASH~>? ; ( "2" 1 db:0x21cfda1a ) HASH~>?? ; ( "2" 2 1 "ONE" db:0x21cfda1a "cellName" )
-
遍歷一個雜湊
foreach( key HASH printf( "key: %A , value: %A\n" key HASH[key] ) ) ; key: db:0x21cfda1a , value: "cellName" ; key: 1 , value: "ONE" ; key: "2" , value: 2