利用 Spectre 生成 Gmid 數據庫


學習Murmann《Systematic Design of Analog CMOS Circuits》過程中,需要首先仿真得到關於Gmid參數的數據庫。該數據庫在Matlab環境下生成

我的仿真環境為:CentOS7、Matlab2018a、CadenceIC617。

該數據庫是四維的數據庫,四個維度分別為\(V_{DS}\)\(V_{SB}\)\(V_{GS}\)\(L\)

包含的參數有:

類別 詳細內容
電容信息C CGG,CGS,CSG,CGD,CDG,CGB,CDD,CSS
電流信息I ID,IGD,IGS
跨導信息GM GM,GMB
閾值電壓VT VT
噪聲信息S STH,SFL

利用書中提供的工具箱,利用該數據庫即可完成相應設計。

下載/安裝Matlab相應工具包

我將相應工具包上傳到了這里,請點擊下載。該工具箱包括《Systematic Design of Analog CMOS Circuits》書配套工具箱和Spectre數據讀取工具箱。

  1. 下載Matlab相應工具包;
  2. 將工具包載入Matlab工作目錄即可;

配置仿真.m腳本

仿真使用的腳本有兩個,一個用來配置仿真參數,名字為cortemsweep_config.m;另一個用來執行仿真,名字為cortemsweep_spectre_run.m

腳本中有一些路徑需要修改成為自己電腦中的相應路徑。

需要修改的地方我會寫做“< XXX… > “,修改時請去掉左右尖括號< >。

例如:'< 修改為你模型所在的路徑,例如:/home/allmodel.scs >' 修改為‘/home/allmodel.scs’

cortemsweep_config.m腳本整體如下:

% Harroy  2020.09.02
% 該.m文件用來配置數據庫仿真時的一些參數,注意輸入參數需要輸入相應工藝角和溫度(攝氏度)
function c = cortemsweep_config(corner, temp)
% 仿真模型路徑
c.modelfile = '< 修改為你模型所在的路徑,例如:/home/allmodel.scs >';
c.modelinfo = '< 此處填寫數據庫信息,方便查閱,不對數據庫數據產生影響,例如:180nm CMOS>';
c.corner = corner;
c.temp = temp;
% 模型名字,對應Spectre相應仿真中器件的模型名。
c.modeln = 'nch';
c.modelp = 'pch';
% 數據庫存儲名字和位置
c.savefilen = sprintf("< NMOS數據庫存儲名字和位置,例如:/home/180_nch_%d_%s >",c.temp, c.corner);
c.savefilep = sprintf("< PMOS數據庫存儲名字和位置,例如:/home/180_pch_%d_%s >",c.temp, c.corner);
% 該仿真是通過在matlab中調用spectre的方式實現的,下面是關於調用的命令,配合system函數使用。
c.simcmd = '< Spectre軟件所在路徑,若環境變量已配置好,直接輸入Spectre即可 > -64 < 本.m文件自動生成仿真網表文件的路徑,在本.m文件最后位置更改或查看 > +log < 填寫log文件存在位置,可以查看仿真中遇到的問題,例如:/home/techsweep.out >';
c.outfile = '< 仿真網表文件存放路徑,后面會讀取該文件,建議和數據庫放一起。例如:/home/techsweep.raw >';
c.sweep = 'sweepvds_sweepvgs-sweep';
c.sweep_noise = 'sweepvds_noise_sweepvgs_noise-sweep';
% 掃描仿真的信息,可以自行修改自己為所需數據
c.VGS_step = 100e-3;
c.VDS_step = 100e-3;
c.VSB_step = 0.1;
c.VGS_max = 1.8;
c.VDS_max = 1.8;
c.VSB_max = 1.0;
c.VGS = 0:c.VGS_step:c.VGS_max;
c.VDS = 0:c.VDS_step:c.VDS_max;
c.VSB = 0:c.VSB_step:c.VSB_max;
c.LENGTH = [(0.18:0.02:0.5) (0.6:0.1:2.0)];
c.WIDTH = 4;
c.NFING = 4;
% 變量排布,以便后面讀取數據,不熟悉請不要修改
c.outvars =            {'ID','VT','IGD','IGS','GM','GMB','GDS','CGG','CGS','CSG','CGD','CDG','CGB','CDD','CSS'};
c.n{1}= {'mn:ids','A',   [1    0    0     0     0    0     0     0     0     0     0     0     0     0     0  ]};
c.n{2}= {'mn:vth','V',   [0    1    0     0     0    0     0     0     0     0     0     0     0     0     0  ]};
c.n{3}= {'mn:igd','A',   [0    0    1     0     0    0     0     0     0     0     0     0     0     0     0  ]};
c.n{4}= {'mn:igs','A',   [0    0    0     1     0    0     0     0     0     0     0     0     0     0     0  ]};
c.n{5}= {'mn:gm','S',    [0    0    0     0     1    0     0     0     0     0     0     0     0     0     0  ]};
c.n{6}= {'mn:gmbs','S',  [0    0    0     0     0    1     0     0     0     0     0     0     0     0     0  ]};
c.n{7}= {'mn:gds','S',   [0    0    0     0     0    0     1     0     0     0     0     0     0     0     0  ]};
c.n{8}= {'mn:cgg','F',   [0    0    0     0     0    0     0     1     0     0     0     0     0     0     0  ]};
c.n{9}= {'mn:cgs','F',   [0    0    0     0     0    0     0     0    -1     0     0     0     0     0     0  ]};
c.n{10}={'mn:cgd','F',   [0    0    0     0     0    0     0     0     0     0    -1     0     0     0     0  ]};
c.n{11}={'mn:cgb','F',   [0    0    0     0     0    0     0     0     0     0     0     0    -1     0     0  ]};
c.n{12}={'mn:cdd','F',   [0    0    0     0     0    0     0     0     0     0     0     0     0     1     0  ]};
c.n{13}={'mn:cdg','F',   [0    0    0     0     0    0     0     0     0     0     0    -1     0     0     0  ]};
c.n{14}={'mn:css','F',   [0    0    0     0     0    0     0     0     0     0     0     0     0     0     1  ]};
c.n{15}={'mn:csg','F',   [0    0    0     0     0    0     0     0     0    -1     0     0     0     0     0  ]};
c.n{16}={'mn:cjd','F',   [0    0    0     0     0    0     0     0     0     0     0     0     0     1     0  ]};
c.n{17}={'mn:cjs','F',   [0    0    0     0     0    0     0     0     0     0     0     0     0     0     1  ]};
%
%                      {'ID','VT','IGD','IGS','GM','GMB','GDS','CGG','CGS','CSG','CGD','CDG','CGB','CDD','CSS'};
c.p{1}= {'mp:ids','A',   [-1   0    0     0     0    0     0     0     0     0     0     0     0     0     0  ]};
c.p{2}= {'mp:vth','V',   [0   -1    0     0     0    0     0     0     0     0     0     0     0     0     0  ]};
c.p{3}= {'mp:igd','A',   [0    0   -1     0     0    0     0     0     0     0     0     0     0     0     0  ]};
c.p{4}= {'mp:igs','A',   [0    0    0    -1     0    0     0     0     0     0     0     0     0     0     0  ]};
c.p{5}= {'mp:gm','S',    [0    0    0     0     1    0     0     0     0     0     0     0     0     0     0  ]};
c.p{6}= {'mp:gmbs','S',  [0    0    0     0     0    1     0     0     0     0     0     0     0     0     0  ]};
c.p{7}= {'mp:gds','S',   [0    0    0     0     0    0     1     0     0     0     0     0     0     0     0  ]};
c.p{8}= {'mp:cgg','F',   [0    0    0     0     0    0     0     1     0     0     0     0     0     0     0  ]};
c.p{9}= {'mp:cgs','F',   [0    0    0     0     0    0     0     0    -1     0     0     0     0     0     0  ]};
c.p{10}={'mp:cgd','F',   [0    0    0     0     0    0     0     0     0     0    -1     0     0     0     0  ]};
c.p{11}={'mp:cgb','F',   [0    0    0     0     0    0     0     0     0     0     0     0    -1     0     0  ]};
c.p{12}={'mp:cdd','F',   [0    0    0     0     0    0     0     0     0     0     0     0     0     1     0  ]};
c.p{13}={'mp:cdg','F',   [0    0    0     0     0    0     0     0     0     0     0    -1     0     0     0  ]};
c.p{14}={'mp:css','F',   [0    0    0     0     0    0     0     0     0     0     0     0     0     0     1  ]};
c.p{15}={'mp:csg','F',   [0    0    0     0     0    0     0     0     0    -1     0     0     0     0     0  ]};
c.p{16}={'mp:cjd','F',   [0    0    0     0     0    0     0     0     0     0     0     0     0     1     0  ]};
c.p{17}={'mp:cjs','F',   [0    0    0     0     0    0     0     0     0     0     0     0     0     0     1  ]};
%
c.outvars_noise = {'STH','SFL'};
c.n_noise{1}= {'mn:id', ''};
c.n_noise{2}= {'mn:fn', ''};
%
c.p_noise{1}= {'mp:id', ''};
c.p_noise{2}= {'mp:fn', ''};
% 自動生成Spectre仿真網表,不熟悉請不要修改,注意其中有個路徑需要修改
netlist = sprintf([...
'//techsweep.scs \n'...
'include  "%s" section=%s\n'...
'include "< 仿真執行時的掃描網表位置,注意和另一腳本對應路徑應該相同,例如:/home/techsweep_params.scs >\n'...
'save mn \n'...
'save mp \n'...
'parameters gs=0 ds=0 \n'...
'vnoi     (vx  0)         vsource dc=0  \n'...
'vdsn     (vdn vx)        vsource dc=ds  \n'...
'vgsn     (vgn 0)         vsource dc=gs  \n'...
'vbsn     (vbn 0)         vsource dc=-sb \n'...
'vdsp     (vdp vx)        vsource dc=-ds \n'...
'vgsp     (vgp 0)         vsource dc=-gs \n'...
'vbsp     (vbp 0)         vsource dc=sb  \n'...
'\n'...
'//NOTE: YOUR MODELS SHOULD BE SET UP SUCH THAT THE STRESS PARAMS (SA, SB, etc.) ARE AUTOMATICALLY COMPUTED\n'...
'mn       (vdn vgn 0 vbn) %s  l=length*1e-6 w=%de-6 nf=%d \n'...
'mp       (vdp vgp 0 vbp) %s  l=length*1e-6 w=%de-6 nf=%d \n'...
'\n'...
'simOptions options gmin=1e-13 reltol=1e-4 vabstol=1e-6 iabstol=1e-10 temp=%d tnom=27 rawfmt=psfbin rawfile="%s" \n'...
'sweepvds sweep param=ds start=0 stop=%d step=%d { \n'...
'   sweepvgs dc param=gs start=0 stop=%d step=%d \n'...
'}\n'...
'sweepvds_noise sweep param=ds start=0 stop=%d step=%d { \n'...
'   sweepvgs_noise noise freq=1 oprobe=vnoi param=gs start=0 stop=%d step=%d \n'...
'}\n'...
], c.modelfile, c.corner, ...
c.modeln, c.WIDTH, c.NFING, ...
c.modelp, c.WIDTH, c.NFING, ...
c.temp, c.outfile,...
c.VDS_max, c.VDS_step, ...
c.VGS_max, c.VGS_step, ...
c.VDS_max, c.VDS_step, ...
c.VGS_max, c.VGS_step);
% 將網表寫入文件保存
fid = fopen('<仿真網表文件存放路徑,例如:/home/techsweep.scs' >, 'w');
fprintf(fid, netlist);
fclose(fid);
return

仿真執行腳本cortemsweep_spectre_run.m中也有一個路徑需要修改:

% Harroy @ 2020.09.02
clearvars; 
close all;
% corner表示當前仿真工藝角,temp表示攝氏溫度,自行修改
corner = 'tt';
temp = 27;
% 載入配置腳本
c = cortemsweep_config(corner, temp);
% 載入掃描信息,無需修改
nch.INFO   = c.modelinfo;
nch.CORNER = c.corner;
nch.TEMP   = c.temp;
nch.NFING  = c.NFING;
nch.L      = c.LENGTH';
nch.W      = c.WIDTH;
nch.VGS    = c.VGS';
nch.VDS    = c.VDS';
nch.VSB    = c.VSB';
%
pch.INFO   = c.modelinfo;
pch.CORNER = c.corner;
pch.TEMP   = c.temp;
pch.NFING  = c.NFING;
pch.L      = c.LENGTH';
pch.W      = c.WIDTH;
pch.VGS    = c.VGS';
pch.VDS    = c.VDS';
pch.VSB    = c.VSB';
% 開始仿真
for i = 1:length(c.LENGTH)
    str=sprintf('L = %2.3f', c.LENGTH(i));
    disp(str);
    tic
    for j = 1:length(c.VSB)
        % 寫入掃描參數
        fid=fopen('< 仿真執行時的掃描網表位置,注意和另一腳本對應路徑應該相同,例如:/home/techsweep_params.scs >', 'w');
        fprintf(fid,'parameters length = %d\n', c.LENGTH(i));
        fprintf(fid,'parameters sb = %d\n', c.VSB(j));
        fclose(fid);
        pause(5)
        % 調用Spectre
        [status,result] = system(c.simcmd);
        if(status)
            disp('Simulation did not run properly. Check techsweep.out.')
            return;
        end    
        % 初始化數據庫
        for m = 1:length(c.outvars)
            nch.(c.outvars{m})(i,:,:,j) = zeros(length(c.VGS), length(c.VDS));
            pch.(c.outvars{m})(i,:,:,j) = zeros(length(c.VGS), length(c.VDS));
        end
        % 讀取並存儲常規數據
        for k = 1:length(c.n)
            params_n = c.n{k};
            struct_n = cds_srr(c.outfile, c.sweep, params_n{1});
            values_n = struct_n.(params_n{2});
            params_p = c.p{k};
            struct_p = cds_srr(c.outfile, c.sweep, params_p{1});
            values_p = struct_p.(params_p{2});
            for m = 1:length(c.outvars)
                nch.(c.outvars{m})(i,:,:,j)  = squeeze(nch.(c.outvars{m})(i,:,:,j)) + values_n*params_n{3}(m);
                pch.(c.outvars{m})(i,:,:,j)  = squeeze(pch.(c.outvars{m})(i,:,:,j)) + values_p*params_p{3}(m);
            end
        end
        % 讀取並存儲噪聲數據
        for k = 1:length(c.n_noise)
            params_n = c.n_noise{k};
            % note: using cds_innersrr, since cds_srr is buggy for noise
            struct_n = cds_innersrr(c.outfile, c.sweep_noise, params_n{1},0);
            field_names = fieldnames(struct_n);
            values_n = struct_n.(field_names{4});
            params_p = c.p_noise{k};
            % note: using cds_innersrr, since cds_srr is buggy for noise
            struct_p = cds_innersrr(c.outfile, c.sweep_noise, params_p{1},0);
            field_names = fieldnames(struct_p);
            values_p = struct_p.(field_names{4});
            nch.(c.outvars_noise{k})(i,:,:,j) = squeeze(values_n);
            pch.(c.outvars_noise{k})(i,:,:,j) = squeeze(values_p);
        end
    end
    toc
end
save(c.savefilen, 'nch');
save(c.savefilep, 'pch');

腳本修改完成后,即可執行cortemsweep_spectre_run.m腳本開始仿真。

仿真可能遇到的問題

Matlab輸出

“Simulation did not run properly. Check techsweep.out.“

查看Spectre生成的Log文件發現如下提示

“lmStatus: ERROR (LMC-01902): License call failed. The license server search path is defined as . Can't find license file.“

  • 此處提示沒有正確載入Spectre的Licenses,一般是由於沒有正確載入環境變量導致,從桌面快捷方式打開的Matlab仿真時會出現這種位問題。建議在終端Terminal中輸入matlab執行仿真。

運行時提示缺少“libsrr.so“

  • 由於我的Cadence軟件是直接拷貝過來的,而不是正常的安裝,因此會導致關於Cadence 的動態連接庫無法找到。此時需要將Cadence/Spectre中的動態鏈接庫放入自己系統的環境中。

    # 1. 首先找到libsrr.so所在的位置
    locate libsrr.so
    # 2. 在結果中復制該文件所在文件夾的位置,例如復制/opt/cadence/installs/SPECTRE181/tools.lnx86/lib
    # 3. 進入系統動態連接庫所在位置
    cd /etc/ld.so.conf.d/
    # 4. 新建配置文件或復制配置文件
    sudo cp libiscsi-x86_64.conf spectre.conf
    # 5. 將之前復制的位置/opt/cadence/installs/SPECTRE181/tools.lnx86/lib替換進去
    # 6. 重新配置動態連接庫
    sudo ldconfig
    

    此時動態連接庫配置完成,重啟Matlab仿真即可。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM