# HSPICE 入門教學
## Read me
概述hspice一些基礎用法,同學可以大致瀏覽,了解hspice的程式邏輯,不用全部背起來,日後有需要再來查找。
這邊只有少部分的基礎用法,同學若想進一步了解,建議善用google搜尋,或是閱讀==HSPICE使用手冊==,可以得到最完整的答案。
- 簡易指令總覽:
[HSPICE: Quick Reference](https://www.synopsys.com/content/dam/synopsys/verification/hspice-quickrefcard-M-2017-03.pdf)
- 完整手冊:
[HSPICE: User Guide, Simulation and Analysis](https://cseweb.ucsd.edu/classes/wi10/cse241a/assign/hspice_sa.pdf)
[HSPICE: Reference Manual](https://cseweb.ucsd.edu/classes/wi10/cse241a/assign/hspice_cmdref.pdf)
## Circuit file
*如何透過 hspice++描述一個子電路++*
檔案命名: 通常我們會將子電路寫在ooo.cir的檔案中 (ooo可隨意命名)
```haskell=
*** 第一行為註解
.subckt [circuit_name] [pin1] [pin2] [...pinx] [param1=value1] [param2=value2]
*** "m" 代表mos
m1 [drain] [gate] [source] [body] [p_18/n_18] [l=length] [w=width]
*** "c" 代表capacitor
C1 [node1] [node2] [capacitance]
*** "r" 代表resistor
R1 [node3] [node4] [resistance]
.ends
```

:::success
hspice中的 **\*** 或 **\$** 後為註解。
在hspice中,code==沒有==大小寫之分。
**代號**後面緊接著是**命名**。比如我想命名一個叫做 **soonj** 的電晶體,就可以寫成 **msoonj**。
:::
- example 1: inverter.cir
- 
```haskell=
.subckt inv_exp input output vdd gnd
m1 output input vdd vdd p_18 l=0.18u w=0.5u
m2 output input gnd gnd n_18 l=0.18u w=0.25u
.ends
```
- example 2: RC_circuit.cir

```haskell=
.subckt RC_exp vs vc gnd
r1 vs vc 1k
c1 vc gnd 1p
.ends
```
## Testbench file
*如何++測試++我們寫好的電路*
檔案命名:通常我們會將Testbench file寫在ooo.sp的檔案中(ooo可隨意命名)
```haskell=
*** 第一行為註解
.protect
.lib 'cic018.l' TT *** 在此資料夾內使用'cic018.l'此檔案作為library。
.unprotect *** 在.protect與.unprotect之間夾住的檔案,不會顯示在.lis檔案內。
.option post *** "+"代表延續上一個指令(此處為.option指令)
+accurate=1
+ingold=2
+runlvl=6
***以上7行是各位在測電路時幫助收斂以及規定準確度,請各位每次作業這7行都跟這裡一樣。
**************** 宣告testbench中會用到的參數 ****************
.param [parameter_name]=[parameter_value]
******************** 呼叫此資料夾內的檔案 ********************
.include 'inv_exp.cir'
.include 'RC_exp.cir'
****************** 根據呼叫的檔案宣告子電路 ******************
***X[Name] [pin1] [pin2] [...pinx] [param=value] [circuit_name] [m=multiply]
Xinv vin vout vdd gnd inv_exp
XRC vs vc gnd RC_exp
***********************************************************
*** 1.電壓源的設定
***********************************************************
***********************************************************
*** 2.模擬的設定
***********************************************************
***********************************************************
*** 3.量測的設定
***********************************************************
.end
```
:::info
宣告subckt時,可在後面加入 m=[multiply],意即 **並聯** 多少個。
ex: 並聯4個單位的inverter
```haskell=
xinv_a vin vout vdd gnd inv_exp m=4
```
:::
### 1. 電壓源的設定
HSPICE有主要四種電壓源,分別是**DC**, **Pulse**, **Sinusoidal**, 和**Piecewise Linear**。
電壓元的代號是 **V**,後面接著電壓源的名字。
- ==DC==: 宣告一個直流電壓源。
```haskell=
*** [Voltage Source Name] [Node1] [Node2] [DC value]
VVDD VDD GND DC=1.8
```
- ==Pulse==: 宣告一個clock電壓。
```haskell=
*** 宣告一個clock電壓包含幾個要素,首先要訂出低電壓(VL)與高電壓(VH),通常會給GND以及VDD
*** 再來根據clock樣式分別訂出delay、rising time、falling time、pulse width、period
*** 同學可以試著對照下圖來完成自己的clock
VCLK CLK GND PULSE(VL VH delay trise tfall pulse_width period)
```

- ==Sinusoidal==: 宣告一個sin波電壓源。
```haskell=
*** 宣告一個sin波電壓包含幾個要素,首先要訂出中間電壓、震幅與頻率。
*** 再來根據想要的sin樣式去訂出delay
*** 同學可以試著對照下圖來完成自己的sin
VVIN vin gnd sin(Voffset Vamplitude Freq Tdelay)
```

- ==PWL==: 可以自行根據不同時間來給予電壓。
```haskell=
*** PWL內為一個時間搭配一個電壓值
V1 VIN GND PWL(0n 0V 2n 0V 3n 1.8V 8n 1.8V 10n 0V 11n 0V 12n 1.8V 14n 1.8V)
```

### 2. 模擬的設定
HSPICE有主要三種模擬,分別為**AC**, **DC**, 和**Transient**
- ~~==AC==: 交流分析,屬於小訊號分析,分析電路在頻域上的表現,如波德圖。~~ (本課程中不會用到)
- ==DC==: 穩態分析。
```haskell=
*** 設定參數並給定初值
.param L1=0.18u
.param W1=0.5u
*** 假如想看m1電晶體gate電壓在不同大小的情況下,所得到的電流會如何改變
m1 VD VG VS VB n_18 L=L1 W=W1
*** 將VG改變,從0V增加到1.8V,每0.1V為間隔
.dc VG 0 1.8 0.1
*** 再來使用probe的指令,就可以偵測m1電流
.probe id_mos=par(I(m1))
**************************************
*** 透過 "sweep" 指令可以拿來掃不同的參數,像是W或L,同學可以自行摸索
.dc VG 0 1.8 0.1 sweep W1 0.25u 1.25u 0.5u
```
- ==Tran==: 暫態分析,屬於大訊號分析,分析電路在時域上的表現,最貼近真實的電路運作狀況。
```haskell=
****************** Initial condition ******************
*** 有些電路中的節點需要宣告初始值
***.ic V([subckt_name].[node])=[value]
.ic V(Xinv.input)=0.9
*** 先決定模擬總時間要跑多久來設定[run_time]再去設定最小的精細刻度[resolution],
*** [resolution]越小模擬出來的值越準確,但相對地,等待模擬時間也越久。
*** 若同學們有使用到.ic的指令的話,要記得在.tran的後面加上uic,
*** 這樣HSpice才會使用設定的初始值去跑模擬。反之,則不用加uic。
*** .tran [resolution] [run_time] [uic]/[]
.tran 1p 10ns uic
```
### 3. 量測的設定
模擬之後會產生出波形,可以針對產生的波形進行量測,量測有兩種方式:
1. 使用語法進行量測,量測結果儲存於ooo.mx0檔案中 (x取決於跑什麼類型的模擬)
- DC: ooo.ms0
- AC: ooo.ma0
- Tran: ooo.mt0
2. 使用看圖軟體(Waveview)將模擬結果的波形檔案打開,使用Waveview中的tool進行量測。
- DC: ooo.sw0
- AC: ooo.ac0
- Tran: ooo.tr0
:::success
IC Designer通常會兩種方式併用,使用Waveview看波形可以快速確認電路function,使用語法量測則能幫助我們同時量測大量資料,以便後續使用Matlab、Excel等軟體進行分析。以下先針對語法量測說明,Waveview使用會在下一部分介紹。
:::
---
#### 1. meas
有時我們會想要量測電路運作時的一些資訊,可藉由".meas"來進行量測

```haskell=
*** 此堂課的固定設定
.protect
.lib 'cic018.l'
.unprotect
.option post
+ accurate=1
+ ingold=2
+ runlvl=6
*** 電路描述 (通常此部分會寫在.cir檔中,再藉由.include到.sp檔,至於其他測試碼通常也會寫在.sp檔中)
.subckt inv_exp input output vdd gnd
m1 output input vdd vdd p_18 l=0.18u w=0.5u
m2 output input gnd gnd n_18 l=0.18u w=0.25u
.ends
*** 欲測試的子電路
xinv vin vout vdd gnd inv_exp
*** 輸入訊號
Vvin VIN GND PULSE(0 1.8 10n 0.1n 0.1n 20n 40n)
*** 模擬設定
*** .tran [resolution] [run_time]
.tran 1p 200n
*** 量測設定
*** 特定節點在一段時間內的最大、最小電壓值
*** .meas TRAN [data_name] MAX/MIN V([subckt_name].[node]) FROM=[time1] TO=[time2]
.meas TRAN Vmax MAX V(vout) FROM=0n TO=100n *** 一段時間內的電壓最大值,命名為Vmax
.meas TRAN Vmin MIN V(vout) FROM=0n TO=100n *** 一段時間內的電壓最小值,命名為Vmin
*** 設定觸發電壓值以及目標電壓值,量測特定節點從第N次觸發電壓值變化到第M次目標電壓值時的時間長度
*** .meas TRAN [data_name] TRIG V([subckt_name].[node]) VAL=[voltage_value/param] RISE/FALL=[order_of_rise/fall_edge] TARG V([subckt_name].[node]) VAL=[voltage_value/param] RISE/FALL=[order_of_rise/fall_edge]
.meas TRAN Trise TRIG V(vout) VAL='Vmin+0.1*Vmax' RISE=2 *** 量測rising time,此範例為電壓從"第二次達到最大電壓值的1成"上升到"第二次達到最大電壓值的9成"的時間,命名為Trise
+ TARG V(vout) VAL='0.9*Vmax' RISE=2
.meas TRAN Tfall TRIG V(vout) VAL='0.9*Vmax' FALL=2 *** 量測falling time,此範例為電壓從"第二次達到最大電壓值的9成"下降到"第二次達到最大電壓值的1成"的時間,命名為Tfall
+ TARG V(vout) VAL='Vmin+0.1*Vmax' FALL=2
.meas TRAN Tdelay TRIG V(vin) VAL=0.9 FALL=2 *** 量測delay time,此範例為電壓從"輸入電壓第二次達到0.9V"到"輸出電壓第二次達到0.9V"的時間,命名為Tdelay
+ TARG V(vout) VAL=0.9 FALL=2
*** 量測節點電壓值第N次達到指定電壓時的時間長度
*** .meas TRAN [data_name] WHEN V([subckt_name].[node])=[voltage_value] RISE/FALL=[order_of_rise/fall_edge]
.meas TRAN time_second WHEN V(vout)=0.9V RISE=2 *** vout第二次達到0.9V所需的時間長度,命名為time_second
*** 當後面的節點第N次達到指定電壓時,記錄前面節點當下的電壓值
*** .meas TRAN [data_name] FIND V([subckt_name].[node]) WHEN V([subckt_name].[node])=[voltage_value] RISE/FALL=[order_of_rise/fall_edge]
.meas TRAN Vm1 FIND V(vout) WHEN V(vin)=1.2V RISE=1 *** 當vin第一次達到1.2V時,記錄vout的電壓值,命名為Vm1
*** 當到達指定時間時,記錄該節點電壓值
*** .meas TRAN [data_name] FIND V([subckt_name].[node]) AT=[time]
.meas TRAN Vm2 FIND V(vout) AT=50ns *** 當時間到達50ns時,記錄vout電壓值,命名為Vm2
.ends
```
---
#### 2. print
有時我們會自己定義一些參數,可以使用".print"將參數印出在模擬結果波形檔中以便分析
範例:量測VDS電壓變化對NMOS關閉阻抗Roff的曲線

```haskell=
*** 電路描述
MM1 VD VG VS GND n_18 L=0.18u W=0.5u
*** 輸入訊號
VVD VD GND 0
VVG VG GND 0
VVS VS GND ss
*** 模擬設定
.DC ss 0 1.8 0.01
*** 量測設定
.print Roff='V(VS)/abs(I(mm1))'
***
```
## Terminal Command
```haskell=
### run hspice simulation
hspice -i [testbemch_file_name.sp] -o [output_file_name.lis]
### open waveview
wv &
```
:::danger
:warning: 如果跑模擬出現 **hspice job aborted**,請開啟 **[output_file_name].lis** 來debug。
:::
以'print'教學範例為例

## Waveview
以下介紹一些常用的Waveview功能
以'print'教學範例為例






## Appendix
| Element | Symbol |
| -------------- | ------ |
| Resistor | r |
| Capacitor | c |
| Inductor | l |
| MOSFET | m |
| Sub-circuit | x |
| Voltage source | v |
| Current source | i |
| Scale Factor | Symbol |
| ------------ | ------ |
| 1e-15 | f |
| 1e-12 | p |
| 1e-9 | n |
| 1e-6 | u |
| 1e-3 | m |
| 1e3 | k |
| 1e6 | meg |
| 1e9 | g |
| 1e12 | t |