在 IP 驗證時, 除了用 synopsys VIP 來驗證 bus 的 protocol 跟 performance 的分析. 但有時候為了 customer design 時, 會把 protocol 作些變形, 這樣就不符合 standard protocol 的方式. 底下就用大家都熟知的 VCD 擋把 bus info 錄出來轉到 data base 讓使用者可以直接用 query 的方式把 performance 跟 dynamic power 算出來. 底下用 vcdparser.py 把 vcd info 讀出來.之後再透過後端的 big data 處理把資料寫到 data base 上.
python db link
""" conn = sqlite3.connect('example.db') c = conn.cursor() c.execute('''CREATE TABLE vcd (version, timeType(s,ns,fs...), time''') c.execute('''CREATE TABLE _scopes_ (scopeDomain, scopeType(fork,module,...), top(scopeNm)''') c.execute('''CREATE TABLE _signals_ (scopeDomain, signalID, signalType(Real,Bit,...), width, name''') c.execute('''CREATE TABLE _signalID_ # _0_ (time , val)''') # ex : # # module top(); # #0 clk =1; # #5 clk =0; ... # endmodule # header create c.execute('''CREATE TABLE _scopes_ (scopeDomain, scopeType, scopeNm''') c.execute('''CREATE TABLE _signals_ (scopeDomain, signalID, signalType, width, name''') c.execute('''CREATE TABLE _signalID_ # _0_ (time , val)''') # body create c.execute("INSERT INTO _scopes_ VALUES (0, 1(module), "top")") c.execute("INSERT INTO _signals_ VALUES (0, 0, 0(bit), "top.clk")") c.execute("INSERT INTO _0_ VALUES (0, 1)") c.execute("INSERT INTO _1_ VALUES (5, 0)") # conn.commit() c.close() """VcdParser.py
from __future__ import with_statement from itertools import dropwhile, takewhile, izip from collections import defaultdict from pprint import pprint as pp from os import * import io from src.vcdDB import * from src.vcdErr import * from src.vcdContext import * class VcdParser(object): """ parser VCD 2 VcdDB """ def __init__(self,vcd=None): self._vfile = None try: if not isinstance(vcd,VcdDB): raise VcdParserError("vcdDB ptr is None") except VcdDBError, e: print e._msg self._vcd = vcd def parse_error(self,tokeniser, keyword): raise "Don't understand keyword: " + keyword def do_drop_declaration(self,tokeniser, keyword): dropwhile(lambda x: x != "$end", tokeniser).next() def do_vcd_date(self,tokeniser, keyword): """ parser vcd date and set 2 VcdDB::date """ date = ' '.join(takewhile(lambda x: x != "$end", tokeniser)) self._vcd.set_date(date) def do_vcd_timescale(self,tokeniser, keyword): """ parser vcd timescale and set 2 VcdDB::timescale """ val, scale = tuple(takewhile(lambda x: x!= "$end", tokeniser)) self._vcd.set_timescale(scale,val) def do_vcd_version(self,tokeniser, keyword): """ parser vcd version and set 2 VcdDB::version """ version = ' '.join(takewhile(lambda x: x!= "$end", tokeniser)) self._vcd.set_version(version) def do_vcd_enddefinitions(self,tokeniser, keyword): """ parser vcd enddefinitions """ self.do_drop_declaration(tokeniser, keyword) self._vcd.set_enddefinition(1) def do_vcd_scope(self,tokeniser, keyword): """ parser vcd scope and set 2 VcdDB::scope """ scope, name = tuple(takewhile(lambda x: x != "$end", tokeniser)) self._vcd.set_scope(self._vcd,scope,name) def do_vcd_upscope(self,tokeniser, keyword): """ parser vcd upscope """ tokeniser.next() def do_vcd_var(self,tokeniser, keyword): """ parser vcd signalInfo and set 2 vcdDB::nameMap """ varTyp, width, uniqNm, refNm = tuple(takewhile(lambda x: x != "$end", tokeniser)) scope = self._vcd.get_end_scope() maptb = self._vcd.get_mapTb() scope.set_signals(scope,varTyp,refNm,width) signal = scope.get_signal(refNm) maptb.set_tb(uniqNm,signal) def do_vcd_dumpall(tokeniser, keyword): pass def do_vcd_dumpoff(tokeniser, keyword): pass def do_vcd_dumpon(tokeniser, keyword): pass def do_vcd_dumpvars(tokeniser, keyword): pass def do_vcd_end(tokeniser, keyword): pass def vcd_2_VcdDB(self,vcdfile=None): """ parser vcd file 2 VcdDB format """ # define key 2 proc keyword2handler = { # declaration_keyword ::= "$comment": self.do_drop_declaration, "$date": self.do_vcd_date, "$enddefinitions": self.do_vcd_enddefinitions, "$scope": self.do_vcd_scope, "$timescale": self.do_vcd_timescale, "$upscope": self.do_vcd_upscope, "$var": self.do_vcd_var, "$version": self.do_vcd_version, # simulation_keyword ::= "$dumpall": self.do_vcd_dumpall, "$dumpoff": self.do_vcd_dumpoff, "$dumpon": self.do_vcd_dumpon, "$dumpvars": self.do_vcd_dumpvars, "$end": self.do_vcd_end, } keyword2handler = defaultdict(self.parse_error, keyword2handler) f = io.open(vcdfile,"r") tokeniser = (word for line in f for word in line.split() if word) time = 0 for count,token in enumerate(tokeniser): if self._vcd.get_enddefinition() != 1: keyword2handler[token](tokeniser, token) else: c, rest = token[0], token[1:] if c == '$': # skip $dump* tokens and $end tokens in sim section continue # time info elif c == '#': time = rest # (1)bit info elif c in '01xXzZ': uniqNm = rest val = c maptb = self._vcd.get_mapTb() signal = maptb.get_tb(uniqNm) signal.set_NodeInfoList(signal,time,"bit",val) # binary info elif c in 'bB': uniqNm = tokeniser.next() val = rest maptb = self._vcd.get_mapTb() signal = maptb.get_tb(uniqNm) signal.set_NodeInfoList(signal,time,"binary",val) # real info elif c in 'rR': uniqNm = tokeniser.next() val = rest maptb = self._vcd.get_mapTb() signal = maptb.get_tb(uniqNm) signal.set_NodeInfoList(signal,time,"real",val) else: raise "Don't understand: %s After %i words" % (token, count) f.close() return self._vcdcode download 主要改寫 writing-vcd-to-toggle-count-generator 成我們要跟底層溝通的api
Refs:
http://www.semiwiki.com/forum/content/753-what-changes-expect-verification-ip-landscape-after-synopsys-acquisition-nsys.html
VMM performance user guide
http://vmmcentral.org/pdfs/perf_user_guide.pdf
http://i.cmpnet.com/eetimes/news/online/2010/09/Whitepaper_Mediatek_2010.pdf
沒有留言:
張貼留言