Something went wrong on our end
Select Git revision
selinux-network.sh
-
Joshua Brindle authored
Signed-off-by:
Joshua Brindle <jbrindle@tresys.com>
Joshua Brindle authoredSigned-off-by:
Joshua Brindle <jbrindle@tresys.com>
bench_input_energy.py 7.57 KiB
#! /usr/bin/env python3
import argparse as ap
import os
import sys
import time
import numpy
import h5py
import numpy as np
import pexpect
import pylab
from time import sleep
from struct import unpack
from multiprocessing import Process, Pipe
from Helper import Benchmark, Log, Result, GenE, MSO
import Backends
from Backends import Patmos, XMC4500
def get_argparser() -> ap.ArgumentParser:
parser = ap.ArgumentParser(prog=sys.argv[0] + " bench_input_energy",
formatter_class=ap.ArgumentDefaultsHelpFormatter,
description='Subfunction bench_input_energy: ' + desc)
parser.add_argument('--samples', metavar='count', type=int, default=1000, help='Number of samples used for benchmarking')
parser.add_argument('--entry', metavar='function', type=str, default='gene_main', help='Entry used for analysis/simulation')
parser.add_argument('--init', metavar='function', type=str, default='gene_init', help='Function used to initialize data for entry')
parser.add_argument('--opt', metavar='opt', type=int, default=0, help='Optimization level')
parser.add_argument('--cache', metavar='file', type=str, default=None, help='Cache file to be used for faster operation')
parser.add_argument('-sr, --shunt-resistance', metavar='ohms', dest='sr', type=float, default=None, required=True, help='Shunt resistance [ohms]')
GenE.add_arguments(parser)
global BACKEND, SUBBACKEND
BACKEND, SUBBACKEND = Backends.add_arguments(parser)
return parser
def decode_data(data_per_channel):
times = []
volts = {}
for ch in data_per_channel.keys():
data, ymult, yzero, yoff, xincr = data_per_channel[ch]
headerlen = 2 + int(data[1])
header = data[:headerlen]
ADC_wave = data[headerlen:-1]
no_samples = len(ADC_wave) / 2
fmt_string = '>%dH' % no_samples
Log.debug("fmt_string: {}".format(fmt_string))
ADC_wave = np.array(unpack(fmt_string, ADC_wave))
volts[ch] = (ADC_wave - yoff) * ymult + yzero
times.append( np.arange(0, xincr * len(volts[ch]), xincr) )
Log.debug("Got {} entries for {}".format(len(volts[ch]), ch))
return (times[0], volts)
def find_benchmark(times, volts, idx):
stime = times[1] - times[0]
Log.debug("Time between 2 Samples: {:.2f}ns -> {:.2f}MHz".format( 1000*1000*1000*stime, 1/stime/1000/1000 ))
# find start of measurement (based on idx)
LIMIT = 1.0
tail = 50 * 10**-6 # 50us
tail_samples = int(tail / stime)
Log.debug("tail_samples = {}".format(tail_samples))
start = 0
end = 0
try:
start = next(i for i, U in enumerate(volts[idx]) if U > LIMIT)
except StopIteration:
Log.fail("Failed to find start")
try:
end = next(start + i for i, U in enumerate(volts[idx][start:]) if U < LIMIT)
except StopIteration:
Log.fail("Failed to find end in {} samples".format(len(volts[idx])))
pylab.plot(times, volts["CH1"], '-r')
pylab.plot(times, volts[idx], '-y')
pylab.axvline(x=times[start])
pylab.show()
assert start < len(times)
assert end < len(times)
assert start < end
end += tail_samples
Log.debug("Measurement in range [{}, {}], {} samples ({:.2f}% of total measurement length: {} samples)".format(start, end, end - start, 100 * (end - start) / len(times), len(times)))
times = times[start:end]
for ch, curr in volts.items():
volts[ch] = curr[start:end]
return (times, volts)
def hdf_store(hdf, dset_name, times, volts):
for curr in volts.values():
assert len(curr) == len(times)
dset = hdf.create_dataset(dset_name, (1 + len(volts), len(times)), dtype='float64', compression="gzip", compression_opts=9)
dset[0] = times
for i, curr in enumerate(volts.values()):
dset[1 + i] = curr
return dset
def calculate_consumption(times, Ushunt, Usys, Rshunt):
stime = times[1] - times[0]
I = Ushunt / Rshunt
P = np.multiply(I, Usys) # [VA] = [W]
Pint = np.trapz(P, dx=stime) # [Ws] = [J]
us = 1000*1000*(times[-1] - times[0]) # us
return (Pint, us)
def gdb_start(binary, remote):
Log.debug("Spawning gdb...")
fout = open('gdb.log','wb')
gdb = pexpect.spawn("arm-none-eabi-gdb --se='{}' -ex 'target remote {}'".format(binary, remote), logfile=fout)
gdb.expect("Remote debugging using .*\r\n")
gdb.expect("0x.* in .*\r\n")
gdb.expect("\(gdb\) ")
Log.debug("Done spawning gdb.")
#gdb.sendline("c")
#gdb.expect("(gdb) ")
return gdb
def gdb_measure(gdb, inp):
gdb.sendline("set variable input = {}".format(inp))
gdb.expect("\(gdb\) ")
gdb.sendline("si")
gdb.expect("\(gdb\) ")
gdb.sendline("c")
gdb.expect("\(gdb\) ")
gdb.sendline("p result")
gdb.expect(r'\$[0-9]+ = ([0-9]+)')
cycles = int(gdb.match.group(1).decode('utf-8'))
sleep(0.1)
return cycles
def analyze_thread(odir, pipe, hdf, Rshunt):
while True:
measurement = pipe.recv()
if measurement is None:
break
inp, cycles, data_per_channel = measurement
times, volts = decode_data(data_per_channel)
times, volts = find_benchmark(times, volts, "CH4")
dset = hdf_store(hdf, "input_{}".format(inp), times, volts)
Pint, us = calculate_consumption(times, volts["CH1"], volts["CH2"] - volts["CH1"], Rshunt)
W = Pint / (times[-1] - times[0])
mJ = Pint * 1000 # mJ
dset.attrs["power_W"] = W
dset.attrs["consumption_mJ"] = mJ
dset.attrs["etime_us"] = us
dset.attrs["cycles"] = cycles
Log.info("Input {}: {:.2f}mJ in {:.2f}us ({}cy, {:.2f}mW)".format(inp, mJ, us, cycles, W * 1000))
hdf.flush()
def run(args):
Log.info("Using backend " + BACKEND.NAME)
config = BACKEND.get_config(args)
gene_rev, gene_mod = GenE.revision()
subcmd = os.path.splitext(os.path.basename(__file__))[0]
odir = Result.get_dirname(subcmd + "_" + args.backend, args.budget, args.seed, args.bits, args.samples, gene_rev, args.suite, args.opt, config.eic, args.ofactor)
if not os.path.exists(odir):
os.makedirs(odir)
Log.set_logfile(odir + '/aladdin.log')
if gene_mod:
Log.warn("Your GenE repo is modified!")
rm, devs = MSO.find_devices()
mso = MSO.MSO(rm, devs[0])
# TODO
gdb = gdb_start("/home/chris/i4/palladium/results/bench_input_xmc4500.plain_budget20000_seed1431655765_bits32_samples10000_opt0_ofactor25_revff42678d10acef590c184a5fa68c5b9b4ded0e63+_suitedevice/bench.axf", ":2331")
inputs = Benchmark.get_input(args.bits, args.seed, args.samples - 1, 1, crafted = False)[0]
hdf = h5py.File('{}/measurement.hdf5'.format(odir), 'w')
hdf.attrs["rshunt_ohm"] = args.sr
# start analysis process
pipe_parent, pipe_child = Pipe()
p = Process(target=analyze_thread, args=(odir, pipe_child, hdf, args.sr))
p.start()
try:
for i, inp in enumerate(inputs):
Log.info("({}/{}) Starting measurement for input {}".format(i, len(inputs), inp))
mso.start()
cycles = gdb_measure(gdb, inp)
while not mso.is_triggered():
Log.warn(" - Repeating Measurement for {}".format(inp))
cycles = gdb_measure(gdb, inp)
data_per_channel = mso.get_values()
pipe_parent.send( (inp, cycles, data_per_channel) )
except Exception as e:
Log.fail("Caught exception during sampling:\n{}".format(e))
pipe_parent.send(None)
p.join()
hdf.close()
desc = "Determine energy consumption via shunt-based measurement"