#!/usr/bin/env python
#
# This file is part of the pebil project.
#
# Copyright (c) 2010, University of California Regents
# All rights reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

# Counter for a folder
# /pmaclabs/icepic/ti10_round1_icepic_large_0256/processed_trace

# Executable:
# AvgCacheCalc.py
#

# This will calculate the Average of Cache hits for a series of processed metasim files.
# 
# 
# Usage:
# 
# A number of arguments are needed. The arguments determine how to select the set of files to process
# and whether to compute the average across all files or not.
# 
#  Either sysid or taskid is required
# sysid - calculates a single average for all files with the same sysid
#    - use with --sysid option to speciy which sysid to use.
#    - for file icepic_large_0256_0127.sysid44, the sysid is 44
# 
# taskid - prints an average for each file with the same task id (ie 1 set of averages for for each sysid found)
#        - use with --taskid option to specify the task id
#        - for file icepic_large_0256_0127.sysid44, the taskid is 0127
# 
# 
# app		icepic,hycom,..."
# dataset	large, standard..."
# cpu_count	256,1024,... input will be padded with 0s to 4 digits

# Optional:
# dir	- current dir is used if these argument is not given	



# As an example take the folder:
# /pmaclabs/ti10/ti10_round1_icepic_large_0256/processed_trace
# 
# 
# SysID mode:
#mattl@trebek[21]$ ./AvgCacheCalc.py --app icepic --dataset large --cpu_count 1024 --sysid 99 --dir /pmaclabs/ti10/ti10_round1_icepic_large_1024/processed_trace/ 
# # 
# Reading files from:  /pmaclabs/ti10/ti10_round1_icepic_large_1024/processed_trace/
# Averaging for all files like icepic_large_1024*.sysid99
# Number of files:  1024
# Cache 1 average %= 98.365459015 incl(98.365459015)
# Cache 2 average %= 0.000974823792366 incl(98.3654743948)
# Cache 3 average %= 0.0 incl(98.3654743948)
# 
# 
# TaskID:
# mattl@trebek[20]$ ./AvgCacheCalc.py --app icepic --dataset large --cpu_count 1024 --taskid 125 --dir /pmaclabs/ti10/ti10_round1_icepic_large_1024/processed_trace/
# 
# Reading files from:  /pmaclabs/ti10/ti10_round1_icepic_large_1024/processed_trace/
# Averaging for all files like icepic_large_1024_0125*
# Number of files:  32
#   sysid0 99.5021899287 
#   sysid3 98.3544410843 98.4873748354 
#   sysid4 99.0521953314 99.0939555641 
#  sysid21 98.2867244765 98.496093132 
#  sysid22 98.8836107446 99.0731860899 99.5543906444 
#  sysid23 98.086753753 98.4952485239 
#  sysid44 98.8836107446 99.0772427056 99.5790751053 
#  sysid54 96.785672042 99.0781143074 
#  sysid64 98.3544410843 98.4789295449 98.4817196019 
#  sysid67 74.5078816751 
#  sysid68 23.7552154266 
#  sysid69 30.5848561276 
#  sysid70 33.5335710304 
#  sysid71 37.710498373 
#  sysid72 98.2910942185 98.2910942244 98.2910942244 
#  sysid73 98.3544410843 98.4789295449 98.49290069 
#  sysid74 98.3544410843 98.4789295449 98.4887431283 
#  sysid75 98.9182843857 99.0849451175 99.5487031836 
#  sysid77 98.086753753 98.4769519456 98.4956922971 
#  sysid78 98.9182843857 99.0849451175 99.1358601016 
#  sysid81 98.2910942185 98.2910942244 98.2910942244 
#  sysid82 98.2910942185 98.2910942244 98.2910942244 
#  sysid96 98.3544410843 98.4789295449 98.4928364694 
#  sysid97 98.3544410843 98.4789295449 98.492618417 
#  sysid98 98.2910942185 98.2910942244 98.2910942244 
#  sysid99 98.2910942185 98.2910942244 98.2910942244 
# sysid100 98.3544410843 98.4789295449 98.4884141107 
# sysid101 98.3544410843 98.4789295449 98.4884425654 
# sysid102 98.2910942185 98.2910942244 98.2910942244 
# sysid103 98.2910942185 98.2910942244 98.2910942244 
# sysid104 98.086753753 98.4769519456 98.5007917366 
# sysid105 98.086753753 98.4769519456 98.4966562518


import sys, os, glob, re

# function for getting average for a single file
# used by sysid argument
def getAvgSingle(fileNameGetAvg):
	"""calcuates the average cache hits for a file"""
	#print "TESTING:: file:", fileNameGetAvg
	#this part is from counter_mikey.py
	try:
		traceFile = open(fileNameGetAvg, 'r')
		fileLines = traceFile.readlines()
		traceFile.close()
		
	except IOError:
		print "Warning: file" + traceFile, "not found"
		exit()


	#Process file
	#count the lines, track each line in a list
	everyLine = []
	totalMisses = []
	totalAccesses = []
	
	
	myLine = fileLines[0].split()
	cLevel = len(myLine)-3
	#print "TESTING:: cLevel=", cLevel

	for i in range(0,cLevel,1):
		totalMisses.append(0)
		totalAccesses.app
end(0)
	
	if cLevel < 1 or cLevel > 
3:
		print "FATAL: Expected 1, 2 or 3 cache levels"	
		exit()

	idx = 1
	for myLine in fileLines:
		# tokenize the line and verify that we get the correct number of tokens
        	myLine = myLine.split()
        	if cLevel != len(myLine)-3:
               		print "FATAL: expected " + cLevel + " hit rates on line " + str(idx)
			exit()
		# ascribe each token to an aptly-named variable
        	#blockid = long(myLine[0]) ###ASK MIKEY - needed?###
       		#fpCount = long(myLine[1]) ###ASK MIKEY - needed?###
        	memCount = long(myLine[2])
        	inclRate = []
        	for i in range(0,len(totalMisses),1):
			inclRate.append(float(myLine[i+3]))
			#print "myLine[", i+3, "]= ", myLine[i+3]

		# convert each inclusive hit rate to an exclusive rate
		exclRate = [inclRate[0]]
		for i in range(1,len(inclRate),1):
			thisRate = float(inclRate[i])
			prevRate = float(inclRate[i-1])
			if prevRate < 100.0:
                        	exclRate.append(100.0*float(thisRate - prevRate)/(100.0 - prevRate))
                	else:
                       		exclRate.append(float(0.0))

		blockAccesses = []
		blockMisses = []
		blockAccesses.append(memCount)
		## blockHits[n] stores the number of memory accesses that make it to cache level N
       		for i in range(0,len(totalMisses)-1,1):
                	blockMisses.append((blockAccesses[i]*(float(100.0)-exclRate[i]))/float(100.0))
#                	print "block L" + str(i+1) + " misses: " + str(blockMisses[i])
                	blockAccesses.append(blockMisses[i])
#               	print "block L" + str(i+2) + " accesses: " + str(blockAccesses[i+1])

        	blockMisses.append(blockAccesses[cLevel-1]*((100.0-exclRate[cLevel-1])/100.0))
#        	print "block L" + str(cLevel) + " misses: " + str(blockMisses[cLevel-1])

        	for i in range(0,len(totalMisses),1):
                	totalMisses[i] += blockMisses[i]
                	totalAccesses[i] += blockAccesses[i]

	totalHits = 0

	cacheValues = []
	for i in range(0,len(totalMisses),1):
	        levelHits = (totalAccesses[i] - totalMisses[i])
	        totalHits += levelHits
		
		#assign values to tuple and return
		cacheValues.append((levelHits)/(totalAccesses[i])*100)
		cacheValues.append(100*totalHits/totalAccesses[0])
	        #print "Cache " + str(i+1) + " average %= " + str((levelHits)/(totalAccesses[i])*100) + " incl(" + str(100*totalHits/totalAccesses[0]) + ")"
	#print "cacheValues:", cacheValues

	return cacheValues













# function for getting average for a single file
# used by taskid argument
# printType: 1 = taskid prints ex: taskid0001
# printType: 2 = sysid pritns sysid72
def printAvgSingle(fileNamepAvg, printType):
	#print "Avg for file:", fileNamepAvg
	
	fileidx = fileNamepAvg.rfind("/")
	shortfileName = fileNamepAvg[fileidx+1:]
	#print "TESTING: FileName:", shortfileName

	# get the sysid# for printing later
	try:
		sysidname = shortfileName[shortfileName.index('.')+1:]
		taskidname = shortfileName[shortfileName.index('.')-4:shortfileName.index('.')]
		#print "TESTING: sysidname=", sysidname
	except ValueError:
		print "ERROR: Invalid filename n