Commit b7984c7e authored by Valentin Touzeau's avatar Valentin Touzeau

Merge branch 'dev' into maeva

parents 12ad291f 6ca077fe
......@@ -10,3 +10,6 @@
[submodule "dependencies/lrusecurity"]
path = dependencies/lrusecurity
url = https://gricad-gitlab.univ-grenoble-alpes.fr/touzeauv/lrusecurity.git
[submodule "dependencies/lruexact"]
path = dependencies/lruexact
url = https://gricad-gitlab.univ-grenoble-alpes.fr/touzeauv/lruexact
Subproject commit 5dd7873bfef0da73ca6ad6723525cdaecb34f05a
Subproject commit 86769d53916d77cf705054bd1f2b06fbf2017f2d
Subproject commit 5bbb0600838cd53b97c9f29ec4c8179b4697e8db
Subproject commit 7b92fbd166f30bce318fee605ec8e1ccf44d8611
Subproject commit 62abb982cd4835b7a987cb9651844f1e8962db2e
<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
<otawa-script xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<name>Generic WCET Computation</name>
<info>
This script proposes a generic approach to compute WCET. Mainly, this approach
is based on IPET (Implicit Enumeration Technique) and is composed of:
<ul>
<li>support for L1 instruction cache if any (LRU replacement only),</li>
<li>very basic support for L1 data cache if any (LRU replacement only),</li>
<li>support for branch prediction by category if any,</li>
<li>computation by execution graph of block timing.</li>
</ul>
If no processor configuration is given, a 5-level stage pipeline is considered.
Other hardware components are optional and must be provided by the user expressed
in the OTAWA XML formats.
In addition to the pure WCET time in cycle, the user can request other information
to be provided:
<ul>
<li>time and frequency by block,</li>
<li>output of CFG used by the calculation,</li>
<li>dump in HTML of the produced ILP system of the IPET approach.</li>
</ul>
</info>
<configuration>
<item name="pipeline" type="string" label="pipeline description file">
<help>Select the path of the pipeline description file to use.
If not configured, use a default 5-stage pipeline.</help>
</item>
<item name="cache" type="string" label="cache description file">
<help>Select the path of the cache description file to use.
If none is provided, the hardware is considered without caches.</help>
</item>
<item name="memory" type="string" label="memory description file">
<help>Select the path of the memory description file to use.
If none is provided, the memory is made of only one 32-bits bank with 10-cycles access.</help>
</item>
<item name="cache_analysis" type="string" label="cache analysis to preform">
<help>Select the cache analysis to perform. Can be "none", "classic" or "exact"
If none is provided, no cache analysis is performed.</help>
</item>
<item name="unroll" type="bool" default="false" label="Unroll loops">
<help>Set to true, unroll the first iteration of loops</help>
</item>
<item name="inline" type="bool" default="false" label="Unroll loops">
<help>Set to true, inline function calls</help>
</item>
</configuration>
<script>
<!-- pipeline configuration -->
<xsl:variable name="pipeline_path">
<xsl:if test="$pipeline=''"><xsl:value-of select="$ORIGIN"/>/generic/pipeline.xml</xsl:if>
<xsl:if test="$pipeline!=''"><xsl:value-of select="$pipeline"/></xsl:if>
</xsl:variable>
<config name="otawa::PROCESSOR_PATH" value="{$pipeline_path}"/>
<xsl:if test="$VERBOSE > 0">
<xsl:message> pipeline = <xsl:value-of select="$pipeline_path"/></xsl:message>
</xsl:if>
<!-- cache configuration -->
<xsl:if test="$cache!=''">
<config name="otawa::CACHE_CONFIG_PATH" value="{$cache}"/>
</xsl:if>
<xsl:if test="$VERBOSE > 0">
<xsl:message> cache = <xsl:value-of select="$cache"/></xsl:message>
</xsl:if>
<!-- memory configuration -->
<xsl:if test="$memory!=''">
<config name="otawa::MEMORY_PATH" value="{$memory}"/>
</xsl:if>
<!-- CFG building -->
<xsl:if test="$unroll">
<step require="otawa::UNROLLED_LOOPS_FEATURE"/>
</xsl:if>
<xsl:if test="$inline">
<step processor="otawa::Virtualizer"/>
</xsl:if>
<!-- cache analysis -->
<!-- step require="otawa::ipet::CACHE_SUPPORT_FEATURE"/ -->
<xsl:if test="$cache!=''">
<!--<step require="otawa::icat3::EDGE_EVENTS_FEATURE"/>-->
<xsl:if test="$cache_analysis='precise'">
<!--<step processor="lrupreanalysis::may_must::MayAnalysis"/> -->
<!--<step processor="lrupreanalysis::may_must::MustAnalysis"/> -->
<step processor="lrupreanalysis::may_must::CatBuilder"/>
<step require="lrupreanalysis::eh_em::DU_CATEGORY_FEATURE"/>
<!--<step require="lruexact::REFINEMENT_CATEGORY_FEATURE"/>-->
<step processor="lruzdd::ClassificationBuilder"/>
</xsl:if>
<xsl:if test="$cache_analysis='classic'">
<step processor="lrupreanalysis::may_must::MayAnalysis"/>
<step processor="lrupreanalysis::may_must::MustAnalysis"/>
<!--<step processor="lrupreanalysis::may_must::CatBuilder"/>-->
<step require="lrupreanalysis::may_must::MAY_MUST_CATEGORY_FEATURE"/>
<step processor="lruexact::MayMustClassificationBuilder"/>
</xsl:if>
<step processor="lruexact::EdgeEventBuilder"/>
</xsl:if>
<!-- timing analysis -->
<step require="otawa::etime::EDGE_TIME_FEATURE"/>
<step require="otawa::ipet::WCET_FEATURE"/>
</script>
</otawa-script>
<?xml version="1.0" encoding="UTF-8"?>
<cache-config>
<icache>
<block_bits>4</block_bits>
<way_bits>3</way_bits>
<row_bits>6</row_bits>
</icache>
</cache-config>
<?xml version="1.0" encoding="UTF-8"?>
<cache-config>
<icache>
<block_bits>4</block_bits>
<way_bits>3</way_bits>
<row_bits>0</row_bits>
</icache>
</cache-config>
<?xml version="1.0" encoding="UTF-8" ?>
<memory xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!--
PARAMETERS
processor_model: one of lpc2131, lpc2132, lpc2134, lpc2136 or lpc2138
MAM_fetch_cycle_timing: in range [1, 7]
PROCESSOR CONFIGURATION
MAMCR[MAM_mode_control] =
-->
<banks>
<bank>
<name>ON-CHIP NON-VOLATILE MEMORY</name>
<address>0x00000000</address>
<xsl:choose>
<xsl:when test="$processor_model='lpc2131'"><size>0x8000</size></xsl:when>
<xsl:when test="$processor_model='lpc2132'"><size>0x10000</size></xsl:when>
<xsl:when test="$processor_model='lpc2134'"><size>0x20000</size></xsl:when>
<xsl:when test="$processor_model='lpc2136'"><size>0x40000</size></xsl:when>
<xsl:when test="$processor_model='lpc2138'"><size>0x80000</size></xsl:when>
</xsl:choose>
<type>ROM</type>
<on_chip>true</on_chip>
<!--<latency><xsl:value-of select="$MAM_fetch_cycle_timing"/></latency>-->
<latency>3</latency>
<!-- NOTE: interfaced with the MAM device -->
</bank>
<bank>
<name>ON-CHIP STATIC RAM</name>
<address>0x40000000</address>
<xsl:choose>
<xsl:when test="$processor_model='lpc2131'"><size>0x2000</size></xsl:when>
<xsl:when test="$processor_model='lpc2132'"><size>0x4000</size></xsl:when>
<xsl:when test="$processor_model='lpc2134'"><size>0x4000</size></xsl:when>
<xsl:when test="$processor_model='lpc2136'"><size>0x8000</size></xsl:when>
<xsl:when test="$processor_model='lpc2138'"><size>0x8000</size></xsl:when>
</xsl:choose>
<type>SPM</type>
<on_chip>true</on_chip>
</bank>
<bank>
<name>VPB PERIPHERALS</name>
<address>0xe0000000</address>
<size>0x10000000</size>
<type>IO</type>
</bank>
<bank>
<name>AHB PERIPHERALS</name>
<address>0xf0000000</address>
<size>0x10000000</size>
<type>IO</type>
</bank>
</banks>
</memory>
<?xml version="1.0" encoding="UTF-8" ?>
<memory xmlns:xsl="http://www.w3c.org/XSL/Transform">
<banks>
<bank>
<name>Test</name>
<address>0x00000000</address>
<size>0x40000</size>
<type>DRAM</type>
<on_chip>true</on_chip>
<latency>10</latency>
<cached>true</cached>
</bank>
</banks>
</memory>
<?xml version="1.0" encoding="UTF-8"?>
<processor class="otawa::hard::Processor" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- PARAMETERS
CCLK: frequency in [1, 5]
-->
<!-- TIMING INFORMATION
* fetch delay
B, BX 0
ALU w/ shift, control 1
ALU else 0
LDR w/o control memory latency
LDR w/ control memory latency + 1
LDM w/o control n * memory latency
LDM w/ control n * memory latency + 1
STR memory latency
STM n * memory latency
* execution additional time
B, BX 0
MLA 6 (overestimation)
MUL 4
ALU with shift 1
ALU w/o shift 0
LDR memory latency + 1
STR memory latency
LDM n * memory latency + 1
STM n * memory latency
* support for MAM
ensure that
prefetching instruction time + fetch latency >= prefetched instruction time
if there is any load / store before between prefetching and prefetched
load / store time + fetch latency >= prefetched instruction time
-->
<arch>arm</arch>
<model>lpc2138</model>
<builder>NXP</builder>
<!--<frequency><xsl:value-of select="$CCLK*10000000"/></frequency>-->
<frequency>40000000</frequency>
<stages>
<stage id="FI">
<name>FI</name>
<width>1</width>
<type>FETCH</type>
</stage>
<stage id="DI">
<name>DI</name>
<width>1</width>
<type>LAZY</type>
</stage>
<stage id="EX">
<name>EX</name>
<type>EXEC</type>
<width>1</width>
<ordered>true</ordered>
<fus>
<fu id="ALU">
<name>ALU</name>
<width>1</width>
</fu>
</fus>
<dispatch>
<inst>
<type>IS_LOAD</type>
<fu ref="ALU"/>
</inst>
<inst>
<type>IS_STORE</type>
<fu ref="ALU"/>
</inst>
<inst>
<type>IS_FLOAT</type>
<fu ref="ALU"/>
</inst>
<inst>
<type>IS_MUL</type>
<fu ref="ALU"/>
</inst>
<inst>
<type>IS_DIV</type>
<fu ref="ALU"/>
</inst>
<inst>
<type>IS_INT</type>
<fu ref="ALU"/>
</inst>
<inst>
<type>IS_CONTROL</type>
<fu ref="ALU"/>
</inst>
<inst>
<type>IS_INTERN</type>
<fu ref="ALU"/>
</inst>
</dispatch>
</stage>
<stage id="CM">
<name>CM</name>
<type>COMMIT</type>
<width>1</width>
<latency>0</latency>
</stage>
</stages>
<queues>
<queue>
<name>FQ</name>
<size>0</size>
<input ref="FI"/>
<output ref="DI"/>
</queue>
<queue>
<name>ROB</name>
<size>0</size>
<input ref="DI"/>
<output ref="EX"/>
<intern>
<stage ref="EX"/>
</intern>
</queue>
</queues>
</processor>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE processor SYSTEM "/home/casse/otawa/otawa/data/dtd/pipeline.dtd">
<processor class="otawa::hard::Processor" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<arch></arch>
<model>generic</model>
<builder>OTAWA</builder>
<stages>
<stage id="FE">
<name>FE</name>
<width>1</width>
<type>FETCH</type>
<latency>1</latency>
</stage>
<stage id="DE">
<name>DE</name>
<width>1</width>
<type>LAZY</type>
</stage>
<stage id="EX">
<name>EX</name>
<type>EXEC</type>
<width>1</width>
<ordered>true</ordered>
<fus>
<fu id="ALL">
<name>ALL</name>
<width>1</width>
<mem>true</mem>
</fu>
</fus>
<dispatch>
<inst>
<type/>
<fu ref="ALL"/>
</inst>
</dispatch>
</stage>
<stage id="CM">
<name>CM</name>
<type>COMMIT</type>
<width>1</width>
<latency>0</latency>
</stage>
</stages>
<queues>
<queue>
<name>FQ</name>
<size>2</size>
<input ref="FE"/>
<output ref="DE"/>
</queue>
</queues>
</processor>
#!/bin/bash
BENCH_DIR="bounded-bench"
CACHE="hardware/cache/fully_associative_cache.xml"
if [ ! -d "$BENCH_DIR" ] ; then
echo "Directory \"$BENCH_DIR\" does not exist"
exit
fi
BENCH_LIST=$(find "$BENCH_DIR" -mindepth 2 -maxdepth 2 -type d)
echo "bench,lblocksO0,lblocksO1" > bench_size.csv
while read BENCH_LOCATION ; do
BENCH=$(basename "$BENCH_LOCATION")
LBLOCKS_O0=$(operform --add-prop otawa::CACHE_CONFIG_PATH=$CACHE -o /dev/null --log bb $BENCH_LOCATION/build/$BENCH-O0.elf main require:otawa::icat3::LBLOCKS_FEATURE 2>&1 | grep l-block | tail -n 1 | tr -d '\t' | cut -d ' ' -f 2)
LBLOCKS_O1=$(operform --add-prop otawa::CACHE_CONFIG_PATH=$CACHE -o /dev/null --log bb $BENCH_LOCATION/build/$BENCH-O1.elf main require:otawa::icat3::LBLOCKS_FEATURE 2>&1 | grep l-block | tail -n 1 | tr -d '\t' | cut -d ' ' -f 2)
echo "$BENCH,$LBLOCKS_O0,$LBLOCKS_O1" >> bench_size.csv
done < <(printf '%s\n' "$BENCH_LIST")
exit
#!/bin/bash
RESULTS_DIR="results"
SCRIPT_DIR="$(cd "$(dirname "$0")" ; pwd -P)"
WCET_INFO_SCRIPT="$SCRIPT_DIR/wcet_info.py"
LOG_LIST=$(find "$RESULTS_DIR" -name "*.log")
echo "bench,inline,unroll,analysis,optim,wcet,cache_exec_time,pipeline_exec_time,events,costs,configs"
while read LOG_LOCATION ; do
LOG_FILE="$(basename $LOG_LOCATION)"
#if [[ $LOG_FILE =~ ([^-])-(false|true)-(false|true)-(classic|precise)-(O0|O1).log ]] ; then
if [[ $LOG_FILE =~ ([^-]*)-(false|true)-(false|true)-(classic|precise)-(O0|O1).log ]] ; then
BENCH=${BASH_REMATCH[1]}
INLINE=${BASH_REMATCH[2]}
UNROLL=${BASH_REMATCH[3]}
ANALYSIS=${BASH_REMATCH[4]}
OPTIM=${BASH_REMATCH[5]}
#echo "MATCH ! bench: $BENCH, INLINE: $INLINE, UNROLL: $UNROLL, analysis: $ANALYSIS, optim: $OPTIM"
OUTPUT=$("$WCET_INFO_SCRIPT" --csv-summary "$LOG_LOCATION" /dev/null)
echo "$BENCH,$INLINE,$UNROLL,$ANALYSIS,$OPTIM,$OUTPUT"
else
echo "WARNING ! Pattern $LOG_FILE not recognized"
fi
done < <(printf '%s\n' "$LOG_LIST")
#!/bin/bash
JOBS=16
BENCH_DIR="bounded-bench"
SCRIPT="cache_analysis.osx"
CACHE="hardware/cache/cache.xml"
PIPELINE="hardware/pipeline/toy.xml"
MEMORY="hardware/memory/lpc2138.xml"
check_exists()
{
local FILE="$1"
local ERROR="$2"
if [ ! -f "$FILE" ] ; then
echo "Error: $ERROR"
exit
fi
}
check_exists "$SCRIPT" "No Otawa script found"
check_exists "$CACHE" "No cache config found"
check_exists "$MEMORY" "No memory config found"
check_exists "$PIPELINE" "No pipeline config found"
if [ ! -d "$BENCH_DIR" ] ; then
echo "Directory \"$BENCH_DIR\" does not exist"
exit
fi
BENCH_LIST=$(find "$BENCH_DIR" -mindepth 2 -maxdepth 2 -type d)
echo "optim,unroll,inline,analysis,wcet,cache,pipeline,events,costs,configs" > result.log
while read OPTIM ; do
while read INLINE ; do
while read BENCH_LOCATION ; do
mkdir -p "$BENCH_LOCATION/results"
BENCH=$(basename "$BENCH_LOCATION")
if [[ "$BENCH" != "insertsort" ]] ; then
continue
fi
while read UNROLL ; do
while read ANALYSIS ; do
COMMANDS="owcet --log inst -f $BENCH_LOCATION/bounds/$BENCH-O$OPTIM.ffx -s $SCRIPT -p cache=$CACHE -p pipeline=$PIPELINE -p memory=$MEMORY -p cache_analysis=$ANALYSIS -p unroll=$UNROLL -p inline=$INLINE $BENCH_LOCATION/build/$BENCH-O$OPTIM.elf 2> $BENCH_LOCATION/results/$BENCH-$INLINE-$UNROLL-$ANALYSIS-O$OPTIM.log\n$COMMANDS"
done < <(printf 'classic\nprecise\n')
done < <(printf 'true\nfalse\n')
done < <(printf '%s\n' "$BENCH_LIST")
done < <(printf 'true\nfalse\n')
done < <(printf '0\n1\n')
echo -e "$COMMANDS" | parallel --jobs "$JOBS"
#!/usr/bin/env python
import argparse
import re
import sys
parser = argparse.ArgumentParser(description='Extract useful information from Otawa log.')
parser.add_argument('log_file', metavar='LOG_FILE', help='Otawa log file (instruction log level) to extract data from')
parser.add_argument('csv', metavar='CSV_OUTPUT', help='Location of the output csv file produced')
parser.add_argument('--csv-summary', dest='csv_summary', default=False, action='store_true')
args = parser.parse_args()
if args.log_file == '-':
input_file = sys.stdin
else:
input_file = open(args.log_file)
matching_events = False;
class EdgeInfo:
def __init__(self, cfg, edge):
self.cfg = cfg
self.edge = edge
self.hts = None
self.lts = None
self.events = None
self.cost_configs = 0
def set_events(self, events):
self.events = events
def set_cost_configs(self, cost_configs):
self.cost_configs = cost_configs
def incr_cost_configs(self):
self.cost_configs += 1
def set_time_sets(self, hts, lts):
self.hts = hts
self.lts = lts
def write_to_csv(self, csv_file):
assert (self.hts != None and self.lts != None and self.cost_configs != None and self.events != None)
csv_file.write('{0}|{1}|{2}|{3}|{4}|{5}\n'.format(self.cfg, self.edge, self.events, self.cost_configs, self.hts, self.hts - self.lts))
class ProgramInfo:
def __init__(self, csv_summary):
self.cache_analysis_exec_time = 0
self.edge_time_builder_running_time = 0
self.total_events = 0
self.total_costs = 0
self.total_config = 0
self.wcet = 0
self.analysis = {}
self.csv_summary = csv_summary
def add_cache_analysis_info(self, name, running_time):
self.analysis[name] = running_time
self.cache_analysis_exec_time += running_time
def add_events(self, number_of_events):
self.total_events += number_of_events
self.total_config += 2**number_of_events
def set_edge_time_builder_running_time(self, running_time):
self.edge_time_builder_running_time = running_time
def set_wcet(self, wcet):
self.wcet = wcet
def print_summary(self):
if self.csv_summary:
print '{0},{1},{2},{3},{4},{5}'.format(self.wcet, self.cache_analysis_exec_time, self.edge_time_builder_running_time, self.total_events, self.total_costs, self.total_config)
else:
print 'WCET: {0}s'.format(self.wcet)
print 'Total cache analysis time: {0}s'.format(self.cache_analysis_exec_time)
print 'Total edge event builder running time: {0}s'.format(self.edge_time_builder_running_time)
print 'Total events: {0}\nTotal costs: {1}\nTotal config: {2}'.format(self.total_events, self.total_costs, self.total_config)
class RegexMatcher:
def __init__(self):
self.cfg_expr = re.compile('\s*process CFG (.*)')
self.bb_expr = re.compile('\s*process (entry|BB \d*)\s*')
self.edge_expr = re.compile('\s*(\S.*, .* -> .*, .*\S)\s*')
self.dynamic_event_expr = re.compile('\s*dynamic events = ([0-9]*)\s*')
self.cost_expr = re.compile('\s*cost = ([0-9]*)\s*')
self.config_expr = re.compile('\s*\[\d*\] cost = .*')
self.timesets_expr = re.compile('\s*LTS time = (\d*), HTS time = (\d*) for .*')
self.cache_analysis_expr = re.compile('\s*(May|Must|Exist Hit|Exist Miss|Exact May|Exact Must) Analysis running time: ([0-9]*)\ss\s*')
self.edge_time_builder_running_time_expr = re.compile('\s*Edge Time Builder running time: (\d*) s\s')
self.edge_time_builder_begin_expr = re.compile('Starting otawa::etime::EdgeTimeBuilder (.*)\s*')