2012年11月25日 星期日

將sonnet檔轉換到virtuoso上

做高頻電路討厭的就是,頻率太高的情況下,寄生的電容電感會在電路各處藏汙納垢(XD)。
所以在設計的過程,就需要跑很多電磁模擬,把這些寄生的效應一併考慮到模擬之中。
(會吃你一堆電腦的記憶體跟花一堆時間,這也是我為什麼有時間打這篇文章的原因,哈哈)
麻煩就在於,每次在電磁模擬軟體(實驗室用Sonnet)上畫完架構,然後開始跑,確定結果沒錯之後,又要在電路下線的軟體(實驗室用Virtuoso)上畫一遍。
最近學到,該怎麼把sonnet上的檔案匯到virtuoso上面,在這裡記錄一下。

理論上,我們只要把sonnet檔案匯出到GDSII檔,這是IC layout通用格式,幾乎所有的工具都支援;之後再從virtuoso讀入GDSII檔案即可。
遇到的麻煩是,在進行電磁模擬時,我們會在sonnet裡面建好電路一層一層的架構,但Virtuoso的環境卻是依所用的製程而定,它完全看不懂我們是在講什麼?
所以如果直接匯入的話,就會變成有些層virtuoso不知道該對應給誰,變得完全無法編輯,總之會出現各式各樣的問題。
幸好Virtuoso並沒有這麼笨,在匯入檔案的選項中,可以自行指定層與層的Map file,透過這個,理當能「無損的」將sonnet檔案匯入virtuoso中。

1. sonnet to GDSII:
在sonnet中,是將電路板切成一層一層不同的介質,然後可以在每層介質中填入金屬,去摸擬其中的電磁效應,我們要的就是這金屬的pattern。
下面是一個sonnet層數設定的截圖,從最上面的空氣……到最底層的substrate

合理的推斷,GDSII也是將一層一層的資料給記錄下來,但要怎麼知道?
我用的是開源的klayout打開gds下去看,得到如下的畫面:

發現到sonnet轉gds的規則很簡單,原本在sonnet設在第幾層的金屬,就會被轉到gds第幾層;很可惜的,sonnet中層與層間連接的via的資訊全都消失了,不過很多金屬不用重畫還是可以省下很多時間。

 2. GDSII to Virtuoso:
有了上面的資料之後,再來就是編寫map file: 一個map file 的格式如下:
#Cadence layer name  Cadence layer purpose Stream layer number Stream data type
#
TopMetal2 drawing 0-63 0-63

每一行分為四個子資料,分別是:在此製程中的某層的名稱;該層的用途;對應在stream檔中的層數;該層的資料。
像上面這種寫法,會把0-63層的資料都變成TopMetal2。
purpose的部分,大概有drawing, pin, net三種可以選擇,但從sonnet過來的話大概都是要要轉成drawing的。
stream layer number就是方才用klayout看到的layer編號;stream data type這部分則不是很清楚,但sonnet轉出來好像也不會特別去設定。
根據上面的轉出來的資料,可以自行編寫對應的map,data type不清楚就用0-63全部截下來:
#Cadence layer name  Cadence layer purpose Stream layer number Stream data type
#
TopMetal2 drawing 2 0-63
TopMetal1 drawing 3 0-63
MIM drawing 4 0-63
Metal5 drawing 6 0-63
Metal1 drawing 10 0-63
這樣各層就能夠轉換成功了:


不過另一方面,據說從sonnet匯入virtuoso時,有機會發生一些off-grid的問題,這就是一時之間無法解決的問題了。

結論:
這篇介紹了如何將電磁模擬軟體Sonnet上的繪圖,直接轉換到Cadence Virtuoso上面,我很喜歡 「work hard, after you know you are working smart」類似的話
如果可以直接匯入圖形(work smart),就不要花時間重畫(work hard)了。
理論上如果你用的是Sonnect V13以上的話,其實Sonnet已經含有和Virtuoso的介面了。 http://www.sonnetsoftware.com/products/sonnet-suites/ef_translators_cvbridge.html

參考資料:
1. GDSII format description: http://www.buchanan1.net/stream_description.shtml
2. Layermap format description:
http://www-bsac.eecs.berkeley.edu/~cadence/tools/layermap.html
3. open source gds editor, klayout:
http://www.klayout.de/

2012年11月16日 星期五

放大器的級間穩定

做多級的RF的放大器時,除了看一般的stability factor K值外,還需要去測試電路每級放大器的級間穩定。
實驗室一直遵照學長流傳下來的投影片:將電路從中切開,一邊看stability circle,另一邊看ADS裡面的「Map1 circle」跟「Map2 circle」這個東西,然後看看兩個圓有沒有相交在一起,可是這個Map 1/2 circle是啥鬼東西?極間穩定又是什麼?

1. 極間穩定的意義:


先考慮上圖的模型,在一個主動的電晶體兩旁接上matching的電路,stability circle的定義是,在什麼樣的$\Gamma_L$(or $\Gamma_S$)下,會讓$\Gamma_{in}$(out) >1,在$\Gamma_{in}$(out) > 1時,電路幾乎確定會不穩定,將$\Gamma_{in}$(out)=1的邊線畫出來的圓,就是穩定圓(stability circle)。
電路設計完後,一定會看看stability factor K是否全頻帶都大於1,就是要確認電路整體的$\Gamma_{in}$(out)都在穩定的範圍內。
可是若我們把電路切開,這個模型就不適用了,前後接的不是被動的matching電路,這時候我們就要確保,前端的load stability circle,和向後端可能看到任何一點阻抗,都不會相交;否則很不巧的該阻抗出現,電路就不穩定了;這就是極間穩定背後的原理。

所以說map1/2 circle是啥鬼?從上面的定義來看,我認為它所畫的是:當source(load)呈現任何被動阻抗時(也就是實部小於一,落在smith chart上的任何阻抗),會在另一邊load(source)上呈現的阻抗。
實際用複數變換來驗證看看:
$\Gamma_{in} = w = \frac{a \Gamma_L+b}{c\Gamma_L+d}$
改換上式為下式,兩行的abcd並不是相同的:
$\Gamma_L = \frac{a \Gamma_{in}+b}{c \Gamma_{in}+d}$
a=1, b= $-S_{11}$, c= $S_{22}$, d= $-\Delta$
其中 $\Delta = S_{11}S_{22}-S_{12}S_{21}$
這個 $|\Gamma_L|=1$經轉換後會畫出一個圓,其圓心和半徑為:
$C_L = \frac{c^*d-a^*b}{a^2-c^2} = \frac{-S_{11}|S_{22}^2|+S_{12}S_{21}S_{22}^*+S_{11}}{1-|S22|^2} = S_{11}+\frac{S_{12}S_{21}S_{22}^*}{1-|S22|^2}$
$r = \frac{ad-bc}{a^2-c^2} = |\frac{S_{12}S_{21}}{1-|S22|^2}|$
若兩圓相交,就表示有load會讓$\Gamma_L$呈現某阻抗,而該阻抗會落在不穩定圓中,也就使電路在這級不穩定(新細明體:你死了Q_Q)

2. 實際資料:

Linux有問題先查manpage,ADS遇到鬼先問F1 help,結果help裡面解釋是這麼寫的:
Used in Small-signal S-parameter simulations: The function maps the set of terminations with unity magnitude at port 1 to port 2. The circles are defined by the loci of terminations on one port as seen at the other port. A source-mapping circle is created for each value of the swept variable(s). This measurement is supported for 2-port networks only.
大概的意思是一樣的,依著help的註解找到了計算的ael原始碼,下面是map2的原始碼:
defun map2_center_and_radius(sParam, center, radius)
{
    decl S12xS21 = sParam(1,2)*sParam(2,1);
    decl s11MagSq = pow(abs(sParam(1,1)),2);
     *center = sParam(2,2)+S12xS21*conj(sParam(1,1))/(1-s11MagSq);
     *radius = abs(S12xS21)/(1-s11MagSq);
}
可見所做的是以$S_{11}+\frac{S_{12}S_{21}S_{22}^*}{1-|S22|^2}$為圓心,$|\frac{S_{12}S_{21}}{1-|S22|^2}|$為半徑的圓,和我們所計算的結果相符。

附件:

如何在blogger裡面插入方程式?目前找到兩種解決方案
第一種是用這篇文章中所建議的方式:
http://www.codecogs.com/latex/integration/blogger/install.php
照著裡面的步驟做即可,不過它是將LaTeX轉成圖片,再替換掉原本的文字,所以很醜...
而且測試發現Firefox會當掉(媽的連IE都可以了…),原因不明。
第二種是現在的作法:
方法同上,但code是在下面這個blog裡面找到的
http://aishuxue.blogspot.tw/2012/01/latex-blogspot.html

<script src="http://cdn.mathjax.org/mathjax/latest/MathJax.js" type="text/javascript">
MathJax.Hub.Config({
 extensions: ["tex2jax.js","TeX/AMSmath.js","TeX/AMSsymbols.js"],
 jax: ["input/TeX", "output/HTML-CSS"],
 tex2jax: {
     inlineMath: [ ['$','$'], ["\\(","\\)"] ],
     displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
 },
 "HTML-CSS": { availableFonts: ["TeX"] }
});
</script>
這個結果超漂亮的啊!!!,實在太強了!
在chrome跟firefox裡面都可以用,IE我倒不知道,反正懶得理他。

致謝:

本篇文章感謝503實驗室強者我同學曾奕恩,以及強者我學長陳柏翰學長在複數變換方面的指導。

2012年11月13日 星期二

c++ static 修飾詞

最近寫基因演算法的project,有需要使用到C++ class的static variable,因為我之前這個東西怎麼寫都會出錯,這次好不容易在強者陳仕勳(GodGodMouse)的指導下成功寫出可以用的static,在這裡記錄一下怎麼使用C++的Static(是說這些文章也多到滿出來了)。

靜態物件static的標記包括:在主體程式中使用,在函式中使用,和在class中作為靜態資料使用。
總歸三種使用方式,都是要在程式的各處中使用共有的一份資料,下面針對三種使用方式,分別寫明使用方法及使用的時機: 

1. Main程式:

在global 的地方使用static,可以讓該變數由程式的全域變數變成檔案內的全域變數,使用static的全域變數幾乎永遠是好習慣,畢竟其他程式設計師在用你的程式時只想把你的程式當黑箱子,要是哪個全域變數名字相衝……那大概不是一兩個幹字可以解決的問題,例如下文中的debug變數,我每個檔案都想要有debug變數,這時就要加上static。
簡單的例子,我們幾個cpp檔裡面都有一個debug變數(總不能main裡的叫maindebug,gui裡的叫guidebug吧?),如果不加上static
//main.cpp
int debug  = 0; 
//src1.cpp
int debug  = 0; 
這樣在最後編譯的時候,g++ main.o src1.o的階段,就會回傳錯誤,因為debug在這裡被重複定義。 因此,請為全域變數加上static。
Static int debug = 0
或者,與static相對的就是extern,宣告變數是在別的檔案裡有定義,這時候不能再給初始值(因為初始值是從別的檔案來的):
extern char* filename;

2. 在函數裡使用:

在函數裡加上static的變數,不同於一般的變數「在函數執行時起始,於函數終結時清除」,static變數在程式一執行時即被宣告。我想這個已經芭樂到不能再芭樂的地步了,例子也不勝枚舉,如果我們要輸出某函數被call幾次,請愛用static。
Void function(){
 static int i=0;
 cout << ++i << endl;
}

3. 在class裡使用:

在class裡使用,其功用在於,這個class產生的任何一個object(or instance if you like),都可看到static的變數或函數。 比如說我project寫的基因演算法的程式,經由隨機產生了10000個子代,每個子代都要對某一筆測試資料進行處理,看看結果好不好;這時候當然不可能每一個子代都保留一份測試資料的副本(記憶體不用錢也不是這樣花的吧…),就要用static的方式保存資料,讓每個子代都能看到。
在class裡面用會複雜一點,假設現在有一個叫static_test的class,架構如下:
//static_test.h
class static_test { 
public:
    static int static_var;
    static void output();
    int i;
};
所以我們宣告了一個static的integer跟一個static 的function,在.h宣告中,大部分的東西是一樣的。
但在定義式裡,就有些不同,由於static物件在是class共有的一部分,宣告class物件時並不會初始化static的物件,因此在.cpp裡面第一件事就是先初始化static物件:
//static_test.cpp
int static_test::static_var;
要不要給初始值沒什麼關係,但這行指明:static_test中有一個static_var,不寫這行編譯時會出現undefined reference to static_var。 取用static物件時,也要用'::'指明:我要取用static_test的物件,例如:
cout << static_test::static_var << endl;
static_test::static_var = 10;
static function是類似的事情,每一個class都可以取用這個function,但static function裡面,只能用到static的member,因為它並非任何一個object的function,自然不能取用其中的內容,就如文中的output()不能取用 i 這個變數。
據說static member最常用的地方是統計目前程式中生成了幾個object,在contructor中對static member+1,destruct的時候-1,不過作者到目前還是沒遇到相關的場合,所以…就算了吧,能用就好。

 4. 致謝: 

本篇文章,感謝陳仕勳(GodGodMouse)強者的指導。