summaryrefslogtreecommitdiff
path: root/FreeRTOS/Test/VeriFast/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS/Test/VeriFast/scripts')
-rwxr-xr-xFreeRTOS/Test/VeriFast/scripts/annotation_overhead.sh3
-rw-r--r--FreeRTOS/Test/VeriFast/scripts/callgraph.md20
-rwxr-xr-xFreeRTOS/Test/VeriFast/scripts/callgraph.py83
-rw-r--r--FreeRTOS/Test/VeriFast/scripts/diff_files.md40
-rwxr-xr-xFreeRTOS/Test/VeriFast/scripts/extract.py73
-rwxr-xr-xFreeRTOS/Test/VeriFast/scripts/generate_diff_files.sh47
6 files changed, 266 insertions, 0 deletions
diff --git a/FreeRTOS/Test/VeriFast/scripts/annotation_overhead.sh b/FreeRTOS/Test/VeriFast/scripts/annotation_overhead.sh
new file mode 100755
index 000000000..3384ea1aa
--- /dev/null
+++ b/FreeRTOS/Test/VeriFast/scripts/annotation_overhead.sh
@@ -0,0 +1,3 @@
+#!/bin/bash -eu
+
+NO_COVERAGE=1 EXTRA_VERIFAST_ARGS=-stats make queue | grep overhead: | sort | uniq
diff --git a/FreeRTOS/Test/VeriFast/scripts/callgraph.md b/FreeRTOS/Test/VeriFast/scripts/callgraph.md
new file mode 100644
index 000000000..5316a6121
--- /dev/null
+++ b/FreeRTOS/Test/VeriFast/scripts/callgraph.md
@@ -0,0 +1,20 @@
+# Generate callgraph
+
+## Requirements
+
+ - python3
+ - pycparser
+ - graphviz/dot
+ - [inconsolata](https://fonts.google.com/specimen/Inconsolata)
+
+## Instructions
+
+```
+cd scripts
+git clone https://github.com/eliben/pycparser.git #< you need this for pycparser's libc headers even if pycparser is installed
+mkdir fake_include
+touch fake_include/threading.h
+gcc -E -I pycparser/utils/fake_libc_include/ -I ../include/ -I fake_include/ ../queue/*.c > out.pp
+./callgraph.py > out.dot
+dot -Nfontname=inconsolata -Tpng -o callgraph.png out.dot
+```
diff --git a/FreeRTOS/Test/VeriFast/scripts/callgraph.py b/FreeRTOS/Test/VeriFast/scripts/callgraph.py
new file mode 100755
index 000000000..ca6fa4ee8
--- /dev/null
+++ b/FreeRTOS/Test/VeriFast/scripts/callgraph.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python3
+
+from __future__ import print_function
+from pycparser import c_parser, c_ast, parse_file
+import sys
+
+ignore_callee = set(['mutex_acquire', 'mutex_release'])
+ignore_caller = set(['caller_reinstates_queue_predicate'])
+proven = [
+ 'prvCopyDataFromQueue',
+ 'prvCopyDataToQueue',
+ 'prvInitialiseNewQueue',
+ 'prvIsQueueEmpty',
+ 'prvIsQueueFull',
+ 'prvLockQueue',
+ 'prvUnlockQueue',
+ 'uxQueueMessagesWaiting',
+ 'uxQueueSpacesAvailable',
+ 'vQueueDelete',
+ 'xQueueGenericCreate',
+ 'xQueueGenericReset',
+ 'xQueueGenericSend',
+ 'xQueueGenericSendFromISR',
+ 'xQueueIsQueueEmptyFromISR',
+ 'xQueueIsQueueFullFromISR',
+ 'xQueuePeek',
+ 'xQueuePeekFromISR',
+ 'xQueueReceive',
+ 'xQueueReceiveFromISR',
+]
+
+modeled = [
+ 'setInterruptMask',
+ 'clearInterruptMask',
+ 'setInterruptMaskFromISR',
+ 'clearInterruptMaskFromISR',
+ 'vTaskSuspendAll',
+ 'xTaskResumeAll',
+]
+
+CALLMAP = set()
+
+
+class FuncCallVisitor(c_ast.NodeVisitor):
+ def __init__(self, caller):
+ self.caller = caller
+
+ def visit_FuncCall(self, node):
+ callee = node.name.name
+ if callee not in ignore_callee:
+ CALLMAP.add((node.name.name, self.caller))
+
+
+class FuncDefVisitor(c_ast.NodeVisitor):
+ def visit_FuncDef(self, node):
+ caller = node.decl.name
+ if caller in ignore_caller:
+ return
+ if caller.startswith('wrapper_'):
+ caller = caller[8:]
+ v = FuncCallVisitor(caller)
+ v.visit(node)
+
+
+def show_func_calls(filename):
+ ast = parse_file(filename, use_cpp=False)
+ v = FuncDefVisitor()
+ v.visit(ast)
+
+
+if __name__ == "__main__":
+ filename = 'out.pp'
+ show_func_calls(filename)
+ print('digraph G {')
+ print(' rankdir=LR;')
+ print(' node [style = filled, colorscheme = set13;];')
+ for f in proven:
+ print(' %s [fillcolor = 3];' % f)
+ for f in modeled:
+ print(' %s [fillcolor = 2];' % f)
+ for (callee, caller) in CALLMAP:
+ print(' %s -> %s;' % (callee, caller))
+ print('}')
diff --git a/FreeRTOS/Test/VeriFast/scripts/diff_files.md b/FreeRTOS/Test/VeriFast/scripts/diff_files.md
new file mode 100644
index 000000000..59f62d364
--- /dev/null
+++ b/FreeRTOS/Test/VeriFast/scripts/diff_files.md
@@ -0,0 +1,40 @@
+# Generate diffs between FreeRTOS source and proofs
+
+## Requirements
+
+ - python3
+ - ctags 5.8
+ - diff 3.4+
+ - [diff2html](https://diff2html.xyz/)
+
+## Instructions
+
+The following will extract per-function files from the original FreeRTOS source
+implementation and the proof directory.
+
+
+```
+cd scripts
+./generate_diff_files.sh
+# will extract to ./FreeRTOS-Kernel/generated and ./queue/generated
+```
+
+Then use `diff` for a side-by-side comparison. Note that the `--color=always`
+flag needs v3.4+:
+
+```
+diff --color=always --width=$COLUMNS --suppress-common-lines --side-by-side FreeRTOS-Kernel/generated queue/generated | less -r
+```
+
+Or generate a html report using `diff2html`:
+
+```
+diff -u FreeRTOS-Kernel/generated queue/generated | diff2html -i stdin
+```
+
+The expectation is that the proofs make minimal changes to the original source
+implementation in the form of:
+
+ - VeriFast annotations `/*@...@*/` and `//*...`
+ - Additional comments explaining the proof `/*...*/`
+ - Flagged changes within `#if[n]def VERIFAST`
diff --git a/FreeRTOS/Test/VeriFast/scripts/extract.py b/FreeRTOS/Test/VeriFast/scripts/extract.py
new file mode 100755
index 000000000..0b74d79a9
--- /dev/null
+++ b/FreeRTOS/Test/VeriFast/scripts/extract.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python3
+from __future__ import print_function
+import sys
+from enum import Enum
+
+
+class Extractor(object):
+ @staticmethod
+ def __parse_ctags(tags_filename):
+ def convert_excmd(excmd):
+ assert excmd.endswith(';"')
+ linenum = excmd[:-2] # remove ';"'
+ return int(linenum)
+ result = {}
+ with open(tags_filename) as f:
+ for line in f:
+ if line.startswith('!'):
+ continue
+ parts = line.split('\t')
+ funcname = parts[0]
+ funcfile = parts[1]
+ linenum = convert_excmd(parts[2])
+ result[funcname] = (funcfile, linenum)
+ return result
+
+ def __init__(self, tags_filename):
+ self.map = Extractor.__parse_ctags(tags_filename)
+
+ class State(Enum):
+ INIT = 0
+ HEAD = 1
+ BODY = 2
+
+ def text_of_funcname(self, funcname):
+ if funcname not in self.map:
+ return []
+ funcfile, linenum = self.map[funcname]
+ result = []
+ state, bracecount = Extractor.State.INIT, 0
+ with open(funcfile) as f:
+ for i, line in enumerate(f, start=1): # ctags counts linenums from 1
+ if state == Extractor.State.INIT and linenum <= i:
+ state = Extractor.State.HEAD
+ if state == Extractor.State.HEAD:
+ result.append(line)
+ lbrace = line.count('{')
+ rbrace = line.count('}')
+ bracecount += lbrace
+ bracecount -= rbrace
+ if '{' in line:
+ state = Extractor.State.BODY
+ continue
+ if state == Extractor.State.BODY:
+ result.append(line)
+ lbrace = line.count('{')
+ rbrace = line.count('}')
+ bracecount += lbrace
+ bracecount -= rbrace
+ if bracecount == 0:
+ break
+ return result
+
+
+if __name__ == "__main__":
+ if len(sys.argv) != 3:
+ print("Usage: %s <tagfile> <funcname>" % sys.argv[0])
+ sys.exit(1)
+ tag_filename = sys.argv[1]
+ funcname = sys.argv[2]
+ extractor = Extractor('tags')
+ result = extractor.text_of_funcname(funcname)
+ print(''.join(result))
+ sys.exit(0)
diff --git a/FreeRTOS/Test/VeriFast/scripts/generate_diff_files.sh b/FreeRTOS/Test/VeriFast/scripts/generate_diff_files.sh
new file mode 100755
index 000000000..55f9cfbd2
--- /dev/null
+++ b/FreeRTOS/Test/VeriFast/scripts/generate_diff_files.sh
@@ -0,0 +1,47 @@
+#!/bin/bash -eu
+
+FUNCS=(
+ prvCopyDataFromQueue
+ prvCopyDataToQueue
+ prvInitialiseNewQueue
+ prvIsQueueEmpty
+ prvIsQueueFull
+ prvUnlockQueue
+ uxQueueMessagesWaiting
+ uxQueueSpacesAvailable
+ vQueueDelete
+ xQueueGenericCreate
+ xQueueGenericReset
+ xQueueGenericSend
+ xQueueGenericSendFromISR
+ xQueueIsQueueEmptyFromISR
+ xQueueIsQueueFullFromISR
+ xQueuePeek
+ xQueuePeekFromISR
+ xQueueReceive
+ xQueueReceiveFromISR
+)
+
+if [ ! -d "FreeRTOS-Kernel" ]; then
+ git clone https://github.com/FreeRTOS/FreeRTOS-Kernel.git
+fi
+pushd FreeRTOS-Kernel > /dev/null
+rm -rf tags generated
+ctags --excmd=number queue.c
+mkdir generated
+for f in ${FUNCS[@]}; do
+ ../extract.py tags $f > generated/$f.c
+done
+popd > /dev/null
+echo "created: FreeRTOS-Kernel/generated"
+
+ln -fs ../queue .
+pushd queue > /dev/null
+rm -rf tags generated
+ctags --excmd=number *.c
+mkdir generated
+for f in ${FUNCS[@]}; do
+ ../scripts/extract.py tags $f > generated/$f.c
+done
+popd > /dev/null
+echo "created: queue/generated"