在 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._vcd
code 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

沒有留言:
張貼留言