#!
# coding: utf-8
# Copyright (C) 2016 TOPS SYSTEMS
### @file accessAnalyzer.py
### @brief access pattern Analyzer
###
### ISIMのLOGファイルを解析し、アクセスマップを生成するプログラム
### Contact: izumida@topscom.co.jp
###
### @author: M.Izumida
### @date: June 10, 2016
###
## v01r01 2016/06/10 newly created.
## v01r02 2016/06/13 複数リージョンのR/Wに対応できるように.
##
# Written for Python 2.7 (NOT FOR 3.x)
#=======================================================================
# インポート宣言
from __future__ import division
import sys
import re
import argparse
import os
from datetime import datetime
import numpy as np
#=======================================================================
# バージョン文字列
versionSTR = "accessAnalyzer.py v01r02 Tops Systems (pgm by mpi)"
#=======================================================================
# 共通サブルーチン
#-------------------------------------------------------------------
def errPrint(mes):
"""errPrint.
エラー出力へのメッセージ表示
後の始末はその後で別に書くこと
"""
sys.stderr.write(mes)
sys.stderr.write('\n')
#-------------------------------------------------------------------
def stdExceptionHandler(mes):
"""standard Exception Handler.
エラーメッセージを送出し、デバッグのための情報を出力する
"""
errPrint("Exception Captured: " + str(mes))
errPrint("0:" + str(sys.exc_info()[0]))
errPrint("1:" + str(sys.exc_info()[1]))
errPrint("2:" + str(sys.exc_info()[2]))
#-------------------------------------------------------------------
def tryIntParse(st, dval, radix=10):
"""try Parse string to Integer
文字列stをパースして整数化できれば値を返す、できなければデフォルト値dvalを返す
"""
try:
work = int(st, radix)
except:
return dval
return work
#=======================================================================
# Access Checkerクラス
[ドキュメント]class AccessChecker:
"""Access Checker Class.
与えられた行を解釈し、アクセス履歴をnumpy 配列形式で記録するクラス
"""
#--------------------------------------------------------------------
def __init__(self, w, eSize, h, lm1, lm2, sz1, sz2, opt=False):
"""Access Checker Constructor
コンストラクタ
"""
self.dWidth = w
self.eSize = eSize
self.lineWidth = self.dWidth // eSize
self.dHeight = h
self.LowLimit1 = lm1
self.LowLimit2 = lm2
self.HighLimit1 = self.LowLimit1 + sz1
self.HighLimit2 = self.LowLimit2 + sz2
#
self.yMin = [self.dHeight, self.dHeight]
self.xMin = [self.lineWidth, self.lineWidth]
self.yMax = [0, 0]
self.xMax = [0, 0]
#
self.datArray = np.zeros([self.dHeight, self.lineWidth, 2]) #Y, X, region
#高速化のためマッチパターンをコンパイルしておく
if opt:
self.p0match = re.compile('MWR([LDWB]):([0-9A-Fa-f]{8}):([0-9A-Fa-f\&]+)')
else:
self.p0match = re.compile('MRD([LDWB]):([0-9A-Fa-f]{8}):([0-9A-Fa-f\&]+)')
#Access core
self.accessCoreList0 = []
self.accessCoreList1 = []
#デバッグ
self.debug = False
self.verbose = False
#--------------------------------------------------------------------
[ドキュメント] def rLine(self, lin):
"""Read Line method
読み取った1行を処理するメソッド。
①メモリアクセスを探す
②メモリアクセスのアドレスが範囲内かどうか調べる
③範囲内であれば配列にアクセス回数を書き込む(更新する)
継続ならFalseを返す。エラーがあればTrueを返して脱出
"""
elemLis = lin.split()
region = 0
if len(elemLis) > 0:
accessCore = elemLis[0]
for elem in elemLis:
p0 = self.p0match.match(elem)
if p0:
adr = tryIntParse(p0.group(2), 0, 16)
if (self.HighLimit1 > adr ) and (adr >= self.LowLimit1):
region = 0
yAdr = (adr - self.LowLimit1) // self.dWidth
xAdr = ((adr - self.LowLimit1) % self.dWidth) // self.eSize
elif (self.HighLimit2 > adr ) and (adr >= self.LowLimit2):
region = 1
yAdr = (adr - self.LowLimit2) // self.dWidth
xAdr = ((adr - self.LowLimit2) % self.dWidth) // self.eSize
else:
return False
if yAdr < self.yMin[region]:
self.yMin[region] = yAdr
if xAdr < self.xMin[region]:
self.xMin[region] = xAdr
if yAdr > self.yMax[region]:
self.yMax[region] = yAdr
if xAdr > self.xMax[region]:
self.xMax[region] = xAdr
self.datArray[yAdr, xAdr, region] += 1
if region == 0:
if accessCore not in self.accessCoreList0:
self.accessCoreList0.append(accessCore)
else:
if accessCore not in self.accessCoreList1:
self.accessCoreList1.append(accessCore)
return False
#--------------------------------------------------------------------
[ドキュメント] def accessLog(self, region):
"""dump access log
アクセスログを表示する。
"""
if region == 0:
print
print "--- BUF A --- ",
for core in self.accessCoreList0:
print core,
else:
print
print "--- BUF B --- ",
for core in self.accessCoreList1:
print core,
print "yMin=", self.yMin[region], "yMax=", self.yMax[region], "xMin=", self.xMin[region], "xMax=", self.xMax[region]
for yAdr in range(0, self.dHeight):
print "{0:>3d} ".format(yAdr),
for xAdr in range(0, self.lineWidth):
cnt = self.datArray[yAdr, xAdr, region]
if cnt > 9:
pchr = "*"
elif cnt == 0:
pchr = "_"
else:
pchr = str(int(cnt))
print "{0:1}".format(pchr),
print
#=======================================================================
# Direct LOGファイルリーダクラス
[ドキュメント]class DirectLogReader:
"""Direct LOG File Reader Class.
LOGファイル(命令実行ログ形式)を読み取ってAccessCheckerクラスを駆動する
"""
#--------------------------------------------------------------------
def __init__(self, fnam, imageNFlag, blockFlag, dbg, vbs):
"""Direct LOG File Reader Constructor
コンストラクタ
"""
self.logFname = fnam
#
self.imageFlag = not imageNFlag
self.blockFlag = blockFlag
#デバッグ
self.debug = dbg
self.verbose = vbs
#
if self.imageFlag:
self.imageAccess = AccessChecker(640, 32, 350, 0x60000000, 0x6004B000, 640*350, 640*350, False) #Read
self.imageAccess.debug = dbg
self.imageAccess.verbose = vbs
if self.blockFlag:
self.blockAccessR = AccessChecker(64, 2, 25, 0x600FD000, 0x600FD640, 1600, 1600, False) #Read
self.blockAccessR.debug = dbg
self.blockAccessR.verbose = vbs
self.blockAccessW = AccessChecker(64, 32, 25, 0x600FD000, 0x600FD640, 1600, 1600, True) #True
self.blockAccessW.debug = dbg
self.blockAccessW.verbose = vbs
#--------------------------------------------------------------------
[ドキュメント] def read(self):
"""read method
ファイルから行をリードして処理するメソッド
"""
try:
with open(self.logFname, 'r') as f:
for line in f:
if self.rLine(line):
break
except:
stdExceptionHandler("ERROR: in file reading = " + self.logFname)
return False
return True
#--------------------------------------------------------------------
[ドキュメント] def rLine(self, lin):
"""Read Line method
読み取った1行を処理するメソッド
"""
result = False
if self.imageFlag:
result = result or self.imageAccess.rLine(lin)
if self.blockFlag:
result = result or self.blockAccessR.rLine(lin)
result = result or self.blockAccessW.rLine(lin)
return result
#--------------------------------------------------------------------
[ドキュメント] def accessLog(self):
"""dump access log
アクセスログを表示する。
"""
if self.imageFlag:
print
print "IMAGE BUF"
self.imageAccess.accessLog(0)
self.imageAccess.accessLog(1)
if self.blockFlag:
print
print "BLOCK MATCH BUF Write Access"
self.blockAccessW.accessLog(0)
self.blockAccessW.accessLog(1)
print
print "BLOCK MATCH BUF Read Access"
self.blockAccessR.accessLog(0)
self.blockAccessR.accessLog(1)
#=======================================================================
# メインプログラム
def main():
"""main.
メインプログラム
"""
#-----------------------------------------------------------------------
# コマンドラインオプション処理
#
parser = argparse.ArgumentParser(description='accessAnalyzer.')
parser.add_argument('--LOG', nargs=1, help='Specify LOG file name.')
parser.add_argument('-iN', dest='image', help='Image Buffer Read.', action='store_true', default=False)
parser.add_argument('-b', dest='block', help='Block Match Read/Write.', action='store_true', default=False)
parser.add_argument('-d', dest='debug', help='Debug mode, print debug information.', action='store_true', default=False)
parser.add_argument('-v', dest='verbose', help='Verbose mode.', action='store_true', default=False)
parser.add_argument('-V', dest='VERSION', help='Show Version, then exit', action='store_true', default=False)
args = parser.parse_args()
#-----------------------------------------------------------------------
# Version 表示
#
print versionSTR
if args.VERSION:
sys.exit(0)
#-----------------------------------------------------------------------
# ファイル名処理
#
if args.LOG is None:
errPrint('ERROR: NO input LOG file!!!')
sys.exit(1)
else:
logFname = args.LOG[0]
if not os.path.isfile(logFname):
errPrint('ERROR: LOG file, NOT EXIST.')
sys.exit(1)
#-----------------------------------------------------------------------
# パラメータ処理
#-----------------------------------------------------------------------
# 実処理
#
data = DirectLogReader(logFname, args.image, args.block, args.debug, args.verbose)
if data.read():
data.accessLog()
else:
sys.exit(1)
#終了メッセージ
today = datetime.today()
print "-" * 50
print today.strftime("FINISH: %Y/%m/%d %H:%M:%S")
#-----------------------------------------------------------------------
# 正常終了
#
sys.exit(0)
#=======================================================================
# メインプログラムの起動
if __name__ == "__main__":
main()