Python的進(jìn)擊(下)--python在IC設(shè)計(jì)里的應(yīng)用點(diǎn)滴
掃描二維碼
隨時(shí)隨地手機(jī)看文章
通過(guò)前兩篇的了解,一起解決了為什么要用python(Why)以及怎么用python(How)的問(wèn)題,在這個(gè)系列的最后一講里,一起再來(lái)看看在IC設(shè)計(jì)的征途中里的案例和一些推薦
案例一:大型文件高速比對(duì)
IC設(shè)計(jì)里邊主要處理的對(duì)象還是以文本為主,但是在某些特殊的情況下,文本文件非常巨大,譬如上G的文件。這個(gè)時(shí)候?qū)ξ募牟轵?yàn)和比較都是比較麻煩的,尤其對(duì)于VIMer而言尤其是困難(由于VIM的設(shè)定,是需要將文件全部讀入到內(nèi)存里邊,大文件的打開(kāi)和覆寫(xiě)操作都很慢)。
文件體量
筆者有兩個(gè)比較大的lib文件,

這兩個(gè)文件的大小很相近,看文件大小的詳情可以有所體會(huì)

但是這里請(qǐng)各位小伙伴注意,同樣字符長(zhǎng)度的lib描述,很有可能只是內(nèi)容不同,但是文件大小可能非常相近,設(shè)置大小完全一致

所以,斷言這兩個(gè)lib的內(nèi)容有多么一致或者不一致從大小上看是比較困難的。如果采用vimdiff或者unix自帶的diff工具,速度會(huì)使非常非常慢(VIM基本30分鐘沒(méi)有結(jié)果~~)
python的高效處理示例
python里邊有很強(qiáng)大的數(shù)據(jù)結(jié)構(gòu)能力,這里使用zip命令可以非常高效的進(jìn)行文件比對(duì)。先說(shuō)結(jié)論,然后慢慢展開(kāi)

從以上截圖可以看到,使用python進(jìn)行文件比對(duì),基本在10秒內(nèi)可以完成兩個(gè)1.6G文件的比對(duì),其中共找到了19K+的不同行,不同之處可以方便的導(dǎo)出到out.rpt里邊??匆幌抡w行數(shù):

平均來(lái)看,基本是2.2M行/秒的比較速度,可以說(shuō)是秒比也不為過(guò)。
核心命令
這個(gè)腳本比較簡(jiǎn)單,其中的核心命令如下:
zip(open(f1), open(f2))
這條命令蘊(yùn)含著下面幾個(gè)加速方法
-
直接對(duì)文件f1/f2進(jìn)行迭代,并不去對(duì)文件對(duì)象使用readlines()的操作。python對(duì)于文件操作的時(shí)候,open()函數(shù)打開(kāi)的對(duì)象就會(huì)被直接轉(zhuǎn)換成可迭代對(duì)象。當(dāng)然,數(shù)據(jù)保留的格式是內(nèi)部數(shù)據(jù)結(jié)構(gòu)
。并非list或者str,這樣可以大大提升處理速度
-
zip函數(shù)可以對(duì)于可迭代對(duì)象進(jìn)行原地打包,并且生成一個(gè)新可迭代對(duì)象,直接被for...in...調(diào)用,效率高出天際。
案例一小結(jié):盡量使用可迭代對(duì)象(Iterable)而非直接的顯式list/str,可以大幅度的提高運(yùn)行效率。
案例二:規(guī)范的腳本開(kāi)發(fā)思路和策略
在IC設(shè)計(jì)里邊,大部分的工作都是短小的腳本處理,目的就是快速和高效。這種開(kāi)發(fā)思路是有優(yōu)勢(shì)的,譬如:數(shù)據(jù)的快速迭代、抽取、解析、分析以及結(jié)果導(dǎo)出。一個(gè)合格的IC工程師,可能每天都要面對(duì)多個(gè)處理和迭代的需求。一周寫(xiě)個(gè)三、五個(gè)腳本是很稀松平常的。這樣的腳本開(kāi)發(fā)是典型的頭疼醫(yī)頭、腳疼醫(yī)腳的短平快的開(kāi)發(fā)方法。高效,所見(jiàn)即所得是其最大的優(yōu)勢(shì)。
常見(jiàn)語(yǔ)言的優(yōu)缺點(diǎn)
在討論腳本開(kāi)發(fā)的思路之前,一起看一下常見(jiàn)語(yǔ)言的優(yōu)缺點(diǎn):
語(yǔ)言各有優(yōu)缺點(diǎn),唯場(chǎng)景以定之?;诠P者的工作經(jīng)驗(yàn)來(lái)看,腳本的開(kāi)發(fā)有以下幾個(gè)階段
-
階段一:TCL統(tǒng)管一切
最開(kāi)始工作的時(shí)候,主要的工作場(chǎng)景都是在EDA工具里邊。TCL確實(shí)好用,和工具的嵌套比較緊密,甚至可以調(diào)用shell或者perl腳本,基本可以在工具里邊完成大部分事情。一些短平快的腳本基本都用TCL開(kāi)發(fā)。但是隨著腳本越來(lái)越多,那些隨意化的腳本非常的散亂,格式也不統(tǒng)一,由于是EDA based的,很多命令只能在特定的EDA工具里邊運(yùn)行,交互起來(lái)缺乏便利性。
結(jié)局:由于以上原因,很多用意類似腳本被反復(fù)書(shū)寫(xiě),效率低下,繼承性低。 -
階段二:shell的支持
shell是直接運(yùn)行在unix下的語(yǔ)言,可以很好的對(duì)unix環(huán)境進(jìn)行調(diào)劑和管控,簡(jiǎn)單編程就可以生成比較好用的膠水工具箱,譬如:R2G流程的聯(lián)動(dòng)(SYN->APR->extraction -> PV -> STA etc.),傳遞參數(shù)運(yùn)行多個(gè)并行的后臺(tái)流程(R2G_run1, R2G_run2 etc.)。但是由于shell語(yǔ)法比較簡(jiǎn)單的原因,對(duì)于結(jié)果的解析通常只能使用awk、sed等unix native命令,需要學(xué)習(xí)獨(dú)立的語(yǔ)法和用法,這些損耗有時(shí)候已經(jīng)超出shell腳本本身。
結(jié)局:shell腳本很多,但是好用的還是比較少,數(shù)據(jù)抽取操作弱,對(duì)于糾錯(cuò)和容錯(cuò)處理相對(duì)困難 -
階段三:perl的介入
這個(gè)時(shí)候,perl的介入就是毋庸置疑了。很多公司的大型仿真、驗(yàn)證環(huán)境都是使用perl語(yǔ)言搭建的。數(shù)據(jù)結(jié)構(gòu)復(fù)雜,文本操作方式多,效率也不差。可以完美取代shell成為更為流程可控、輸出標(biāo)準(zhǔn)的膠水工具。后端也很喜歡用perl,譬如對(duì)timing report進(jìn)行summary和格式化打印,可以方便的對(duì)于每一版本的數(shù)據(jù)進(jìn)行歸一化比對(duì);再譬如,對(duì)于某一個(gè)block的R2G運(yùn)行環(huán)境進(jìn)行遷移的時(shí)候,可以使用異常靈活的perl -pie命令行方式,對(duì)所有的腳本文件中特定字串進(jìn)行高速替換,效率極高??傊?,perl對(duì)實(shí)際常見(jiàn)文本的處理非常高效和方便
結(jié)局:perl文本處理異常強(qiáng)大和高效,但是強(qiáng)大的代價(jià)是松散的上下文決定式(context)的語(yǔ)法體系,這個(gè)對(duì)于后期維護(hù)帶來(lái)了一定的障礙。復(fù)雜數(shù)據(jù)結(jié)構(gòu)的表達(dá)較晦澀(reference/dereference),不易操作 -
階段四:python的出現(xiàn)
上述三個(gè)階段的文本處理、膠水工具、格式化輸出等等復(fù)雜的問(wèn)題。在高級(jí)語(yǔ)言python看起來(lái),都不是問(wèn)題。python和perl都是用C語(yǔ)言編寫(xiě)的初版(perl6以后有使用java編寫(xiě)的可能;python前期的Cpython(使用C編譯),后期的Jpython(Java 編譯,用于JVM環(huán)境)都是一些拓展的話題)。python文本處理沒(méi)有perl直接,也不支持命令行快速操作模式,但是以上種種,都不失為一個(gè)系統(tǒng)化、增量化、可視化、易繼承、易維護(hù)的一個(gè)語(yǔ)言選擇。 - 規(guī)范的語(yǔ)法規(guī)則以及PEP8的加持
- 良好的閱讀性和可維護(hù)性
- 復(fù)雜數(shù)據(jù)結(jié)構(gòu)的支持
- 更類似于高級(jí)語(yǔ)言的編程方法和思路
系統(tǒng)化的解決問(wèn)題的痛點(diǎn)
通常的工作,都是點(diǎn)滴任務(wù)的直接需求,用戶可以把這些簡(jiǎn)單腳本視為一個(gè)一個(gè)的點(diǎn)腳本。為了日后的可擴(kuò)展、可維護(hù)以及可套疊的長(zhǎng)遠(yuǎn)目標(biāo)。需要相對(duì)統(tǒng)一的開(kāi)發(fā)方式進(jìn)行各個(gè)點(diǎn)腳本的開(kāi)發(fā),包括但不限于下列的限制和規(guī)范:- 統(tǒng)一的命名方式:蛇形命名法(snake_case):使用下滑線連接單詞進(jìn)行變量命名:cell_order_reversed
- PEP8 句法 規(guī)則:這里并非真正的語(yǔ)法要求,而是python推薦的代碼書(shū)寫(xiě)風(fēng)格(coding style),譬如:逗號(hào)(‘,’)前邊沒(méi)有空格,后面需要接一個(gè)空格等等。具體細(xì)節(jié),可以點(diǎn)擊查看 PEP8的規(guī)范文檔。(Pycharm里邊默認(rèn)就使能了PEP8的代碼書(shū)寫(xiě)風(fēng)格檢查)
- 局部的、專一的功能盡量使用函數(shù)(def)或者類(class)進(jìn)行描述,減少冗長(zhǎng)的代碼,并且提高代碼維護(hù)性的效率。
- 使用main函數(shù)進(jìn)行主程序的執(zhí)行
- 點(diǎn)腳本的鏈?zhǔn)郊希哼^(guò)往的點(diǎn)腳本,使用模塊的導(dǎo)入(import)的方式進(jìn)行盡可能的重用和構(gòu)建
- 腳本的格式化和規(guī)范化輸出
- 構(gòu)建具有趨勢(shì)性的JSON 作為API接口,以供日后使用
ICer的python腳本模板分享
python的理念相當(dāng)先進(jìn),和專家相比,筆者也是初來(lái)乍到,結(jié)合上述表述,構(gòu)建了一個(gè)簡(jiǎn)單的python 腳本模板,這里分享出來(lái)以饗讀者,也歡迎各位ICer使用和討論:#!/usr/bin/python3.6 -u # use -u to support tee meaage in unix # support Chinese encoding # -*- coding: utf-8 -*- # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # import part # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ import argparse import utils_local as ut # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # Scripts version info # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ver = 'V0.1' ver_date = 'September 13, 2021' ver_des = 'initial version.' ut.ver = ver ut.ver_date = ver_date ut.ver_des = ver_des # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # CLASS part # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ class TextParse def __init__(self, file): self.file = file ...... def get_text_header(self): ...... return XXX # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # FUNCTION part # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ def parse_argu(): ...... return argus def func_1(): ...... return func_1_value def func_2(): ...... return func_2_value def main_run(......): ...... func_1() func_2() ...... return main_run_status # ------------------------------------------------------------ # MAIN part # ------------------------------------------------------------ if __name__ == '__main__': # global variable for main run cell_name = "abc" setup_margin = 0.3 # welcome message include scripts version message from local utils ut.welcome() # args parse args = parse_argu() # Call main run main_run(*args) # bye message from local utils ut.bye()上述示例可以簡(jiǎn)單的提供一個(gè)python的開(kāi)發(fā)模板,按照這種格式化的模板,利用本地工具模塊(utils_local.py)可以方便的進(jìn)行格式化(welcome 、bye message)的輸出打印。就算后期需要調(diào)整打印格式(盡量避免),也可以通過(guò)只改動(dòng)這個(gè)模塊文件進(jìn)行同意刷新(new-face)。
python是強(qiáng)大的高級(jí)語(yǔ)言,使用python可以設(shè)立更大的目標(biāo),如果未來(lái)想實(shí)現(xiàn)更為復(fù)雜、結(jié)構(gòu)化的腳本環(huán)境,建議讀者們可以從現(xiàn)在就向python靠攏。設(shè)想在不遠(yuǎn)的未來(lái),可以將一個(gè)個(gè)簡(jiǎn)單的點(diǎn)腳本串接在一起呈現(xiàn)出系統(tǒng)化、結(jié)構(gòu)化的工具箱式的工具包,提供給各位ICer使用。
本章詞匯
詞匯解釋|
|
|
| 蛇形命名法(snake_case) | 使用下劃線進(jìn)行單詞連接方式的命名法 |





