168 lines
5.3 KiB
Python
Executable File
168 lines
5.3 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
# -------------------------------------------------------------------------
|
|
# Import modules
|
|
import csv, sys
|
|
import matplotlib.pyplot as plt
|
|
import numpy as np
|
|
import matplotlib.patches as mpatches
|
|
import matplotlib.pylab as pylab
|
|
|
|
ENTRY_COUNT_PER_LINE = 6
|
|
RESULT_RECT_HEIGHT = 1.0/8
|
|
|
|
# -------------------------------------------------------------------------
|
|
# Basic drawing class
|
|
class Rectangle:
|
|
def __init__(self, x, y, w, h, color):
|
|
# w
|
|
self.xpos = x # |-------------------|
|
|
self.ypos = y # | | h
|
|
self.width = w # | |
|
|
self.height = h # (x,y)---------------|
|
|
self.color = color # fill color
|
|
self.alpha = None # transparency level [0,1]
|
|
def draw(self):
|
|
""" Draw the rectangle. """
|
|
if self.color == (1,1,1):
|
|
return
|
|
tmp = self.xpos, self.ypos,
|
|
p = mpatches.Rectangle(tmp, self.width, self.height, color=self.color, \
|
|
alpha=self.alpha)
|
|
plt.gca().add_patch(p)
|
|
|
|
# -------------------------------------------------------------------------
|
|
# Check provided arguments:
|
|
if len(sys.argv) <= 1:
|
|
print ("ERROR: Not enough arguments provided! See -h for more infos.")
|
|
exit(1)
|
|
if sys.argv[1] == '-h':
|
|
print ("Displays experiment results for the weather-monitor-experiment.")
|
|
print (" CALL-SYNTAX: fsp.plot.py DATA_FILE [USER_TAG_FILE]")
|
|
print ("DATA_FILE is a CSV-file, storing the tab-separated values")
|
|
print ("retrieved by the experiment run. USER_TAG_FILE is an optional")
|
|
print ("CSV-file which can be used to add user-specific marks to the")
|
|
print ("plot.") # TODO: be more precise here
|
|
exit(0)
|
|
|
|
print ("Opening and processing \"" + sys.argv[1] + "\"...")
|
|
file = open(sys.argv[1], "r")
|
|
dialect = csv.Sniffer().sniff(file.read(1024))
|
|
file.seek(0)
|
|
reader = csv.reader(file, dialect)
|
|
next(reader) # Move down a line to skip the header
|
|
|
|
if len(sys.argv) >= 3:
|
|
print ("Opening and processing \"" + sys.argv[2] + "\"...")
|
|
symbolfile = open(sys.argv[2], "r")
|
|
dialect = csv.Sniffer().sniff(symbolfile.read(1024))
|
|
symbolfile.seek(0)
|
|
symbolreader = csv.reader(symbolfile, dialect)
|
|
next(symbolreader) # Move down a line to skip the header
|
|
have_symbols = True
|
|
else:
|
|
have_symbols = False
|
|
|
|
fig = plt.figure()
|
|
|
|
xmin = 99999999
|
|
xmax = 0
|
|
ymin = 0xffffffff
|
|
ymax = 0
|
|
|
|
line_counter = 1
|
|
for row in reader:
|
|
line_counter += 1
|
|
# Check if there are at least ENTRY_COUNT_PER_LINE entries per line:
|
|
if len(row) != ENTRY_COUNT_PER_LINE:
|
|
print ("ERROR: Line " + str(line_counter) + " is invalid (" +\
|
|
str(ENTRY_COUNT_PER_LINE) + " entries expected)")
|
|
sys.exit(1)
|
|
|
|
# Some constants to access the row-entries much easier:
|
|
IDX_INSTR1 = 0; IDX_INSTR2 = 1; IDX_DATA_ADDRESS = 2;
|
|
IDX_BITNR = 3; IDX_BITWIDTH = 4; IDX_COLOR = 5;
|
|
|
|
# Update xmin/xmax/ymin/ymax
|
|
x1 = int(row[IDX_INSTR1])
|
|
x2 = int(row[IDX_INSTR2]) + 1 # inclusive
|
|
width = x2 - x1
|
|
if xmin > x1:
|
|
xmin = x1
|
|
if xmax < x2:
|
|
xmax = x2
|
|
|
|
y1 = float(row[IDX_DATA_ADDRESS]) + float(row[IDX_BITNR]) / 8.0
|
|
height = float(row[IDX_BITWIDTH]) / 8.0
|
|
y2 = y1 + height
|
|
|
|
if ymin > y1:
|
|
ymin = y1
|
|
if ymax < y2:
|
|
ymax = y2
|
|
|
|
Rectangle(x1, y1, width, height, row[IDX_COLOR]).draw()
|
|
if line_counter == 50000: # debug stuff
|
|
pass
|
|
#break
|
|
|
|
# round down to nearest 1000
|
|
#ymin = int(ymin / 1000) * 1000
|
|
|
|
file.close()
|
|
plt.xlim(xmin, xmax)
|
|
plt.ylim(ymin, ymax)
|
|
|
|
plt.ylabel('Data Memory (RAM)')
|
|
plt.xlabel('Time (Cycles)')
|
|
|
|
# show symbols
|
|
if have_symbols:
|
|
# Adding 2nd y-axis for object names
|
|
ax1 = fig.add_subplot(111)
|
|
ax2 = ax1.twinx()
|
|
ax2.set_ylabel('Symbols')
|
|
|
|
# necessary for proper symbol placement
|
|
plt.ylim(ymin, ymax)
|
|
|
|
ticks = []
|
|
symbols = []
|
|
|
|
IDX_SYMBOL_ADDRESS = 0; IDX_SYMBOL_SIZE = 1; IDX_SYMBOL_NAME = 2;
|
|
|
|
for row in symbolreader:
|
|
# TODO: somehow plot size as well
|
|
address = int(row[IDX_SYMBOL_ADDRESS])
|
|
size = int(row[IDX_SYMBOL_SIZE])
|
|
if (address >= ymin) and (address <= ymax):
|
|
ticks.append(address)
|
|
symbols.append(row[IDX_SYMBOL_NAME])
|
|
#print ("symbol: " + str(address) + " " + str(size) + " " + row[IDX_SYMBOL_NAME])
|
|
elif (address < ymin) and (address + size >= ymin):
|
|
ticks.append(ymin)
|
|
symbols.append("(" + row[IDX_SYMBOL_NAME] + ")")
|
|
#print ("partial symbol: " + str(address) + " " + str(size) + " " + row[IDX_SYMBOL_NAME])
|
|
else:
|
|
#print ("skipped symbol: " + str(address) + " " + str(size) + " " + row[IDX_SYMBOL_NAME])
|
|
pass
|
|
|
|
# list of interesting addresses
|
|
ax2.yaxis.set_ticks(ticks)
|
|
ax2.yaxis.grid(b=True, color='gray')
|
|
|
|
# create minor ticks centered between major tick marks
|
|
centered_ticks = []
|
|
major_locator = ax2.yaxis.get_major_locator()
|
|
major_locs = major_locator()
|
|
for i in range(1,len(major_locs)):
|
|
y_last,y = major_locs[i-1],major_locs[i]
|
|
centered_ticks.append(0.5*(y+y_last))
|
|
ax2.yaxis.set_ticks(centered_ticks, minor=True)
|
|
|
|
# list of corresponding symbol names
|
|
ax2.set_yticklabels(symbols, minor=False, rotation=0, rotation_mode='anchor')
|
|
|
|
plt.show()
|
|
#pylab.savefig('baseline.pdf', bbox_inches='tight')
|