aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYann Herklotz <git@yannherklotz.com>2022-03-31 15:41:42 +0100
committerYann Herklotz <git@yannherklotz.com>2022-03-31 15:41:42 +0100
commitdc7eab1a1a7e7a12ff14fb9191c813a405303e4a (patch)
tree6dd781e24a2a260047a8fc9e0a177d1b81bc3b5c
parent505044f22f904a606a1251d72def322512ca4789 (diff)
parent2e232deb0aed4af2448eb9f1031e8084181174b7 (diff)
downloadvericert-dc7eab1a1a7e7a12ff14fb9191c813a405303e4a.tar.gz
vericert-dc7eab1a1a7e7a12ff14fb9191c813a405303e4a.zip
Merge branch 'dev/scheduling'
-rw-r--r--.envrc1
-rw-r--r--.gitignore87
-rw-r--r--.gitmodules3
-rw-r--r--ChangeLog.org (renamed from CHANGELOG.org)0
-rw-r--r--LICENSE6
-rw-r--r--Makefile48
-rw-r--r--README.md12
-rw-r--r--README.org4
-rw-r--r--_CoqProject15
-rw-r--r--benchmarks/polybench-syn-div/exec.csv27
-rw-r--r--benchmarks/polybench-syn-div/poly.csv26
-rwxr-xr-xbenchmarks/polybench-syn-div/run-vericert.sh41
-rwxr-xr-xbenchmarks/polybench-syn-div/setup-syn-vericert.sh24
-rw-r--r--benchmarks/polybench-syn/Makefile24
-rw-r--r--benchmarks/polybench-syn/common.mk7
-rw-r--r--benchmarks/polybench-syn/poly.csv26
-rw-r--r--benchmarks/polybench-syn/quartus_synth.tcl35
-rw-r--r--benchmarks/polybench-syn/script.R29
-rwxr-xr-xbenchmarks/polybench-syn/setup-syn-vericert.sh24
-rw-r--r--benchmarks/polybench-syn/stencils/Makefile1
-rwxr-xr-xbenchmarks/polybench-syn/syn-remote.sh51
-rw-r--r--debug/CoqupTest.ml59
-rw-r--r--debug/dune5
-rw-r--r--default.nix11
-rw-r--r--doc/Makefile24
-rw-r--r--doc/Makefile.extr39
-rw-r--r--doc/README.org7
-rw-r--r--doc/_static/css/custom.css31
-rw-r--r--doc/_static/images/toolflow.pdfbin0 -> 20490 bytes
-rw-r--r--doc/_static/images/toolflow.pngbin0 -> 26864 bytes
-rw-r--r--doc/_static/images/toolflow.svg1250
-rw-r--r--doc/_static/images/vericert-main.svg500
-rw-r--r--doc/common.org15
-rw-r--r--doc/conf.py91
-rw-r--r--doc/documentation.org562
-rw-r--r--doc/docutils.conf2
-rw-r--r--doc/index.rst62
-rw-r--r--doc/make.bat35
-rw-r--r--doc/man.org89
-rw-r--r--doc/res/coqdoc.css867
-rw-r--r--doc/res/fdl.org489
-rw-r--r--doc/res/install-deps.el11
-rw-r--r--doc/res/publish.el23
-rw-r--r--doc/vericert.rst526
m---------docs0
-rw-r--r--driver/VericertDriver.ml11
-rw-r--r--dune2
-rw-r--r--ip/altera.sv (renamed from ip/altera.v)0
-rw-r--r--ip/div_signed.sv (renamed from ip/div_signed.v)0
-rw-r--r--ip/div_unsigned.sv (renamed from ip/div_unsigned.v)0
m---------lib/CompCert0
-rw-r--r--scripts/Makefile25
-rwxr-xr-xscripts/convert.sh14
-rwxr-xr-xscripts/download_artifact.sh8
-rw-r--r--scripts/quartus_synth.tcl (renamed from benchmarks/polybench-syn-div/quartus_synth.tcl)0
-rwxr-xr-x[-rw-r--r--]scripts/run-legup.sh0
-rwxr-xr-xscripts/run-vericert.sh (renamed from benchmarks/polybench-syn/run-vericert.sh)10
-rwxr-xr-xscripts/run-vivado.sh8
-rw-r--r--scripts/script.R (renamed from benchmarks/polybench-syn-div/script.R)0
-rwxr-xr-xscripts/syn-remote.sh (renamed from benchmarks/polybench-syn-div/syn-remote.sh)0
-rwxr-xr-xscripts/synth-ssh.sh28
-rwxr-xr-xscripts/synth.sh32
-rw-r--r--scripts/synth.tcl2
-rw-r--r--scripts/synthesis-results.org44
-rwxr-xr-xscripts/synthesis-results.scm170
-rw-r--r--scripts/verilator_main.cpp (renamed from driver/verilator_main.cpp)4
-rw-r--r--src/Compiler.v248
-rw-r--r--src/VericertClflags.ml1
-rw-r--r--src/bourdoncle/Bourdoncle.v11
-rw-r--r--src/bourdoncle/BourdoncleAux.ml108
-rw-r--r--src/bourdoncle/PrintLoops.ml22
-rw-r--r--src/bourdoncle/README.md3
-rw-r--r--src/bourdoncle/bourdoncleIterator.ml183
-rw-r--r--src/bourdoncle/ptset.ml666
-rw-r--r--src/bourdoncle/ptset.mli125
-rw-r--r--src/common/DecEq.v150
-rw-r--r--src/common/Maps.v8
-rw-r--r--src/common/Show.v30
-rw-r--r--src/common/Vericertlib.v43
-rw-r--r--src/common/ZExtra.v18
-rw-r--r--src/extraction/Extraction.v12
-rw-r--r--src/hls/Abstr.v208
-rw-r--r--src/hls/Array.v5
-rw-r--r--src/hls/AssocMap.v88
-rw-r--r--src/hls/FunctionalUnits.v101
-rw-r--r--src/hls/HTL.v104
-rw-r--r--src/hls/HTLPargen.v245
-rw-r--r--src/hls/HTLgen.v24
-rw-r--r--src/hls/HTLgenproof.v54
-rw-r--r--src/hls/HTLgenspec.v27
-rw-r--r--src/hls/IfConversion.v42
-rw-r--r--src/hls/Memorygen.v8
-rw-r--r--src/hls/Partition.ml14
-rw-r--r--src/hls/Pipeline.v3
-rw-r--r--src/hls/PipelineOp.v193
-rw-r--r--src/hls/Predicate.v628
-rw-r--r--src/hls/PrintAbstr.ml39
-rw-r--r--src/hls/PrintRTLBlockInstr.ml6
-rw-r--r--src/hls/PrintRTLParFU.ml120
-rw-r--r--src/hls/PrintVerilog.ml19
-rw-r--r--src/hls/RICtransf.v87
-rw-r--r--src/hls/RTLBlock.v102
-rw-r--r--src/hls/RTLBlockInstr.v309
-rw-r--r--src/hls/RTLBlockgen.v196
-rw-r--r--src/hls/RTLBlockgenproof.v170
-rw-r--r--src/hls/RTLPar.v53
-rw-r--r--src/hls/RTLParFU.v389
-rw-r--r--src/hls/RTLParFUgen.v177
-rw-r--r--src/hls/RTLPargen.v108
-rw-r--r--src/hls/RTLPargenproof.v32
-rw-r--r--src/hls/Sat.v2
-rw-r--r--src/hls/Schedule.ml104
-rw-r--r--src/hls/ValueInt.v42
-rw-r--r--src/hls/Verilog.v120
-rw-r--r--src/hls/Veriloggen.v32
-rw-r--r--src/hls/Veriloggenproof.v12
-rw-r--r--src/pipelining/LICENSE (renamed from src/SoftwarePipelining/LICENSE)0
-rw-r--r--src/pipelining/SPBase_types.ml (renamed from src/SoftwarePipelining/SPBase_types.ml)0
-rw-r--r--src/pipelining/SPBasic.ml (renamed from src/SoftwarePipelining/SPBasic.ml)0
-rw-r--r--src/pipelining/SPBasic.mli (renamed from src/SoftwarePipelining/SPBasic.mli)0
-rw-r--r--src/pipelining/SPDebug.ml (renamed from src/SoftwarePipelining/SPDebug.ml)0
-rw-r--r--src/pipelining/SPIMS.ml (renamed from src/SoftwarePipelining/SPIMS.ml)0
-rw-r--r--src/pipelining/SPIMS.mli (renamed from src/SoftwarePipelining/SPIMS.mli)0
-rw-r--r--src/pipelining/SPMVE.ml (renamed from src/SoftwarePipelining/SPMVE.ml)0
-rw-r--r--src/pipelining/SPMVE.mli (renamed from src/SoftwarePipelining/SPMVE.mli)0
-rw-r--r--src/pipelining/SPSymbolic_evaluation.ml (renamed from src/SoftwarePipelining/SPSymbolic_evaluation.ml)0
-rw-r--r--src/pipelining/SPTyping.ml (renamed from src/SoftwarePipelining/SPTyping.ml)0
-rw-r--r--src/pipelining/SPTyping.mli (renamed from src/SoftwarePipelining/SPTyping.mli)0
-rw-r--r--src/pipelining/SoftwarePipelining.ml (renamed from src/SoftwarePipelining/SoftwarePipelining.ml)0
-rw-r--r--test/Makefile4
130 files changed, 9403 insertions, 1639 deletions
diff --git a/.envrc b/.envrc
deleted file mode 100644
index 1d953f4..0000000
--- a/.envrc
+++ /dev/null
@@ -1 +0,0 @@
-use nix
diff --git a/.gitignore b/.gitignore
index aaabd2a..5574171 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,7 @@
+/benchmarks/**/*
+!/benchmarks/**/*.*
+!/benchmarks/**/*/
+
.*.aux
*.a
*.cma
@@ -19,17 +23,8 @@
*.vo
*.vok
*.vos
+*.cache
.coq-native/
-.csdp.cache
-.lia.cache
-.nia.cache
-.nlia.cache
-.nra.cache
-csdp.cache
-lia.cache
-nia.cache
-nlia.cache
-nra.cache
Makefile.coq
Makefile.coq.conf
@@ -71,62 +66,6 @@ benchmarks/**/*.v
*.iver
*.dot
-/benchmarks/polybench-syn/stencils/seidel-2d
-/benchmarks/polybench-syn/stencils/jacobi-2d
-/benchmarks/polybench-syn/data-mining/covariance
-/benchmarks/polybench-syn/linear-algebra/blas/gemm
-/benchmarks/polybench-syn/linear-algebra/blas/gemver
-/benchmarks/polybench-syn/linear-algebra/blas/gesummv
-/benchmarks/polybench-syn/linear-algebra/blas/symm
-/benchmarks/polybench-syn/linear-algebra/blas/syr2k
-/benchmarks/polybench-syn/linear-algebra/blas/syrk
-/benchmarks/polybench-syn/linear-algebra/blas/trmm
-/benchmarks/polybench-syn/linear-algebra/kernels/2mm
-/benchmarks/polybench-syn/linear-algebra/kernels/3mm
-/benchmarks/polybench-syn/linear-algebra/kernels/atas
-/benchmarks/polybench-syn/linear-algebra/kernels/bicg
-/benchmarks/polybench-syn/linear-algebra/kernels/doitgen
-/benchmarks/polybench-syn/linear-algebra/kernels/mvt
-/benchmarks/polybench-syn/linear-algebra/solvers/cholesky
-/benchmarks/polybench-syn/linear-algebra/solvers/durbin
-/benchmarks/polybench-syn/linear-algebra/solvers/lu
-/benchmarks/polybench-syn/linear-algebra/solvers/ludcmp
-/benchmarks/polybench-syn/linear-algebra/solvers/trisolv
-/benchmarks/polybench-syn/medley/floyd-warshall
-/benchmarks/polybench-syn/medley/nussinov
-/benchmarks/polybench-syn/stencils/adi
-/benchmarks/polybench-syn/stencils/fdtd-2d
-/benchmarks/polybench-syn/stencils/heat-3d
-/benchmarks/polybench-syn/stencils/jacobi-1d
-
-/benchmarks/polybench-syn-div/stencils/seidel-2d
-/benchmarks/polybench-syn-div/stencils/jacobi-2d
-/benchmarks/polybench-syn-div/data-mining/covariance
-/benchmarks/polybench-syn-div/linear-algebra/blas/gemm
-/benchmarks/polybench-syn-div/linear-algebra/blas/gemver
-/benchmarks/polybench-syn-div/linear-algebra/blas/gesummv
-/benchmarks/polybench-syn-div/linear-algebra/blas/symm
-/benchmarks/polybench-syn-div/linear-algebra/blas/syr2k
-/benchmarks/polybench-syn-div/linear-algebra/blas/syrk
-/benchmarks/polybench-syn-div/linear-algebra/blas/trmm
-/benchmarks/polybench-syn-div/linear-algebra/kernels/2mm
-/benchmarks/polybench-syn-div/linear-algebra/kernels/3mm
-/benchmarks/polybench-syn-div/linear-algebra/kernels/atas
-/benchmarks/polybench-syn-div/linear-algebra/kernels/bicg
-/benchmarks/polybench-syn-div/linear-algebra/kernels/doitgen
-/benchmarks/polybench-syn-div/linear-algebra/kernels/mvt
-/benchmarks/polybench-syn-div/linear-algebra/solvers/cholesky
-/benchmarks/polybench-syn-div/linear-algebra/solvers/durbin
-/benchmarks/polybench-syn-div/linear-algebra/solvers/lu
-/benchmarks/polybench-syn-div/linear-algebra/solvers/ludcmp
-/benchmarks/polybench-syn-div/linear-algebra/solvers/trisolv
-/benchmarks/polybench-syn-div/medley/floyd-warshall
-/benchmarks/polybench-syn-div/medley/nussinov
-/benchmarks/polybench-syn-div/stencils/adi
-/benchmarks/polybench-syn-div/stencils/fdtd-2d
-/benchmarks/polybench-syn-div/stencils/heat-3d
-/benchmarks/polybench-syn-div/stencils/jacobi-1d
-
# Test
*.check
*.txt
@@ -140,3 +79,19 @@ obj_dir/
/*.v
.direnv/
+.envrc
+
+creduce_bug_*/
+
+/doc/src/
+/html/
+
+*~
+*.man
+*.link
+
+/bin
+/share
+/results*
+
+_CoqProject
diff --git a/.gitmodules b/.gitmodules
index 87bab2d..f30817e 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,3 @@
[submodule "lib/CompCert"]
path = lib/CompCert
url = https://github.com/ymherklotz/CompCert.git
-[submodule "docs"]
- path = docs
- url = https://github.com/ymherklotz/vericert-docs
diff --git a/CHANGELOG.org b/ChangeLog.org
index 88c0953..88c0953 100644
--- a/CHANGELOG.org
+++ b/ChangeLog.org
diff --git a/LICENSE b/LICENSE
index b386211..f288702 100644
--- a/LICENSE
+++ b/LICENSE
@@ -631,8 +631,8 @@ to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
- Vericert: Verified high-level synthesis.
- Copyright (C) 2019-2021 Yann Herklotz <yann@yannherklotz.com>
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
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
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
- Vericert Copyright (C) 2019-2021 Yann Herklotz
+ <program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
diff --git a/Makefile b/Makefile
index 0749d1c..3128c23 100644
--- a/Makefile
+++ b/Makefile
@@ -6,12 +6,9 @@ ifeq ($(UNAME_S),Darwin)
ARCH := verilog-macosx
endif
-COMPCERTRECDIRS := lib common verilog backend cfrontend driver exportclight cparser
+COMPCERTRECDIRS := lib common verilog backend cfrontend driver cparser
-COQINCLUDES := -R src/common vericert.common \
- -R src/extraction vericert.extraction \
- -R src/hls vericert.hls \
- -R src vericert \
+COQINCLUDES := -R src vericert \
$(foreach d, $(COMPCERTRECDIRS), -R lib/CompCert/$(d) compcert.$(d)) \
-R lib/CompCert/flocq Flocq \
-R lib/CompCert/MenhirLib MenhirLib
@@ -20,12 +17,15 @@ COQEXEC := $(COQBIN)coqtop $(COQINCLUDES) -batch -load-vernac-source
COQMAKE := $(COQBIN)coq_makefile
COQDOCFLAGS := --no-lib-name -l
+ALECTRYON_OPTS := --no-header --html-minification --long-line-threshold 80 \
+ --coq-driver sertop_noexec $(COQINCLUDES)
-VS := src/Compiler.v src/Simulator.v src/HLSOpts.v $(foreach d, common hls, src/$(d)/*.v)
+VS := src/Compiler.v src/Simulator.v src/HLSOpts.v $(foreach d, common hls bourdoncle, $(wildcard src/$(d)/*.v))
+LIT := docs/basic-block-generation.org docs/scheduler.org docs/scheduler-languages.org
PREFIX ?= .
-.PHONY: all install proof clean extraction test
+.PHONY: all install proof clean extraction test force
all: lib/COMPCERTSTAMP
$(MAKE) proof
@@ -38,18 +38,30 @@ lib/COMPCERTSTAMP: lib/CompCert/Makefile.config
$(MAKE) HAS_RUNTIME_LIB=false CLIGHTGEN=false INSTALL_COQDEV=false -C lib/CompCert
touch $@
-install:
- install -d $(PREFIX)/bin
+install: docs/vericert.1
sed -i'' -e 's/arch=verilog/arch=x86/' _build/default/driver/compcert.ini
- install -C _build/default/driver/compcert.ini $(PREFIX)/bin/.
+ install -d $(PREFIX)/bin
+ install -C -m 644 _build/default/driver/compcert.ini $(PREFIX)/bin
install -C _build/default/driver/VericertDriver.exe $(PREFIX)/bin/vericert
+ install -d $(PREFIX)/share/man/man1
+ install -C -m 644 $< $(PREFIX)/share/man/man1
proof: Makefile.coq
$(MAKE) -f Makefile.coq
@rm -f src/extraction/STAMP
-doc: Makefile.coq
+doc-html: $(patsubst src/%.v,html/%.html,$(VS))
+
+html/%.html: src/%.v
+ @mkdir -p $(dir $@)
+ @echo "ALECTRYON" $@; alectryon $(ALECTRYON_OPTS) $< -o $@
+
+coqdoc: Makefile.coq
$(MAKE) COQDOCFLAGS="$(COQDOCFLAGS)" -f Makefile.coq html
+ cp ./docs/res/coqdoc.css html/.
+
+doc-pdf: Makefile.coq
+ $(MAKE) COQDOCFLAGS="$(COQDOCFLAGS)" -f Makefile.coq all.tex
extraction: src/extraction/STAMP
@@ -67,9 +79,21 @@ src/extraction/STAMP:
@$(COQEXEC) ./src/extraction/Extraction.v
@touch $@
-Makefile.coq:
+Makefile.coq _CoqProject: force
@echo "COQMAKE Makefile.coq"
$(COQBIN)coq_makefile $(COQINCLUDES) $(VS) -o Makefile.coq
+ echo "$(COQINCLUDES)" >_CoqProject
+
+force:
+
+docs/vericert.1:
+ $(MAKE) -C docs vericert.1
+
+detangle-all:
+ emacs --batch --eval "(progn(require 'org)(require 'ob-tangle)\
+ (setq org-src-preserve-indentation t)\
+ $(foreach vs,$(VS),(org-babel-detangle \"$(vs)\"))\
+ (org-save-all-org-buffers))"
clean:: Makefile.coq
$(MAKE) -f Makefile.coq clean
diff --git a/README.md b/README.md
index baebe7a..b45a5ab 100644
--- a/README.md
+++ b/README.md
@@ -4,8 +4,8 @@
- [Setting up Nix](#setting-up-nix)
- [Makefile build](#makefile-build)
- [Running](#running)
- - [Citation](#org741ad34)
- - [License](#orgb089937)
+ - [Citation](#org28fad40)
+ - [License](#org5eb199f)
<a href="https://vericert.ymhg.org"><img src="https://vericert.ymhg.org/vericert-main.svg" width="100%" height="144" /></a>
@@ -109,7 +109,7 @@ To test out `vericert` you can try the following examples which are in the test
```
-<a id="org741ad34"></a>
+<a id="org28fad40"></a>
# Citation
@@ -132,15 +132,15 @@ If you use Vericert in any way, please cite it using our [OOPSLA&rsquo;21 paper]
```
-<a id="orgb089937"></a>
+<a id="org5eb199f"></a>
# License
-This project is licensed under [GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html). The license can be seen in [/LICENSE](file:///LICENSE).
+This project is licensed under [GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html). The license can be seen in [LICENSE](LICENSE).
The following external code and its license is present in this repository:
-- **[/src/pipelining](file:///src/pipelining):** MIT
+- **[src/pipelining](src/pipelining):** MIT
```text
Copyright (c) 2008,2009,2010 Jean-Baptiste Tristan and INRIA
diff --git a/README.org b/README.org
index cf8bd34..1569bfb 100644
--- a/README.org
+++ b/README.org
@@ -133,11 +133,11 @@ If you use Vericert in any way, please cite it using our [[https://yannherklotz.
** License
-This project is licensed under [[https://www.gnu.org/licenses/gpl-3.0.en.html][GPLv3]]. The license can be seen in [[/LICENSE][/LICENSE]].
+This project is licensed under [[https://www.gnu.org/licenses/gpl-3.0.en.html][GPLv3]]. The license can be seen in [[file:LICENSE][LICENSE]].
The following external code and its license is present in this repository:
-- [[/src/SoftwarePipelining][/src/SoftwarePipelining]] :: MIT
+- [[file:src/pipelining][src/pipelining]] :: MIT
#+begin_src text
Copyright (c) 2008,2009,2010 Jean-Baptiste Tristan and INRIA
diff --git a/_CoqProject b/_CoqProject
deleted file mode 100644
index 69d12c1..0000000
--- a/_CoqProject
+++ /dev/null
@@ -1,15 +0,0 @@
--R src/common vericert.common
--R src/extraction vericert.extraction
--R src/hls vericert.hls
--R src vericert
-
--R lib/CompCert/backend compcert.backend
--R lib/CompCert/cfrontend compcert.cfrontend
--R lib/CompCert/common compcert.common
--R lib/CompCert/cparser compcert.cparser
--R lib/CompCert/driver compcert.driver
--R lib/CompCert/exportclight compcert.exportclight
--R lib/CompCert/lib compcert.lib
--R lib/CompCert/verilog compcert.verilog
--R lib/CompCert/flocq Flocq
--R lib/CompCert/MenhirLib MenhirLib
diff --git a/benchmarks/polybench-syn-div/exec.csv b/benchmarks/polybench-syn-div/exec.csv
deleted file mode 100644
index e28109b..0000000
--- a/benchmarks/polybench-syn-div/exec.csv
+++ /dev/null
@@ -1,27 +0,0 @@
-adi,1422354
-heat-3d,580770
-fdtd-2d,901430
-jacobi-1d,19622
-seidel-2d,664780
-jacobi-2d,344072
-nussinov,954402
-floyd-warshall,5373798
-3mm,536114
-2mm,404478
-doitgen,351988
-bicg,53916
-mvt,70204
-atas,58424
-syrk,271816
-gemver,117394
-symm,240172
-gesummv,37700
-gemm,328104
-trmm,144688
-syr2k,436520
-cholesky,2535686
-trisolv,25192
-lu,2853646
-ludcmp,2601382
-durbin,22974
-covariance,288392
diff --git a/benchmarks/polybench-syn-div/poly.csv b/benchmarks/polybench-syn-div/poly.csv
deleted file mode 100644
index fe71983..0000000
--- a/benchmarks/polybench-syn-div/poly.csv
+++ /dev/null
@@ -1,26 +0,0 @@
-benchmark,legupcycles,legupfreqMHz,leguplogicutilisation,legupregs,leguprams,legupdsps,legupcomptime,vericertcycles,vericertfreqMHz,vericertlogicutilisation,vericertregs,vericertrams,vericertdsps,vericertcomptime
-durbin,15106,188.61,2509,4008,0,8,4.77,19852,199.2,3027,6168,0,8,0.077
-lu,482766,244.62,3116,4593,0,10,4.72,2634766,92.97,54806,106037,0,6,0.097
-ludcmp,470843,249.69,3605,5397,0,15,4.87,2401354,83.52,57145,111408,0,10,0.132
-trisolv,35382,213.9,2412,3749,0,3,4.73,33550,112.59,28101,55109,0,2,0.086
-2mm,60088,226.5,1114,1936,0,7,4.80,427098,116.9,32600,63212,0,18,0.136
-3mm,204195,188.96,4210,4801,0,43,4.88,539430,97.13,45073,89719,0,18,0.147
-atas,126288,193.24,3026,3719,0,10,4.80,92000,130.41,28603,56646,0,6,0.069
-bicg,11907,303.4,308,537,0,6,4.78,121134,122.74,30091,58799,0,8,0.097
-mvt,16806,384.47,372,597,0,4,4.79,139194,119.93,30753,60450,0,6,0.130
-doitgen,57199,252.14,909,1402,0,2,5.05,350302,126.18,19898,38461,0,4,0.105
-symm,64903,284.41,2155,3170,0,10,4.63,248930,113.92,27693,54514,0,14,0.115
-syrk,57395,278.01,598,976,0,2,4.73,309018,87.15,76889,57816,0,8,0.094
-syr2k,125705,240.85,3149,3679,0,6,4.85,478040,78.6,120116,82032,0,12,0.116
-trmm,41432,281.61,610,990,0,4,4.71,147528,105.61,64031,40502,0,4,0.089
-gemm,83676,192.68,1029,1544,0,35,4.79,360772,121.61,31853,62126,0,16,0.104
-gemver,28087,303.49,1854,2380,0,8,4.68,175326,107.27,32615,64118,0,14,0.099
-gesummv,6634,310.46,298,504,0,4,4.77,111094,79.97,113876,72908,0,10,0.101
-covariance,109992,245.16,2098,3096,0,5,4.77,297450,110.57,28729,56660,0,4,0.083
-fdtd-2d,214153,262.61,2736,3801,0,2,4.73,831912,108.23,31333,61421,0,6,0.116
-heat-3d,41059,115.54,3132,2910,0,60,4.92,555930,110.42,33915,67273,0,9,0.181
-jacobi-1d,6914,386.25,1355,1885,0,0,4.72,16606,277.93,1636,3305,0,0,0.071
-jacobi-2d,84609,240.79,2347,3185,0,2,4.81,357100,113.53,30393,59782,0,4,0.079
-seidel-2d,345294,232.4,2128,3337,0,2,4.68,875758,127.99,26948,53133,0,2,0.091
-floyd-warshall,1238764,235.52,1869,2367,0,2,4.71,4762766,109.4,59859,118101,0,2,0.094
-nussinov,216467,273.07,1078,1431,0,2,4.79,837958,90.73,60663,119303,0,0,0.080
diff --git a/benchmarks/polybench-syn-div/run-vericert.sh b/benchmarks/polybench-syn-div/run-vericert.sh
deleted file mode 100755
index 6cf4cd9..0000000
--- a/benchmarks/polybench-syn-div/run-vericert.sh
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/env bash
-
-rm exec.csv
-
-top=$(pwd)
- #set up
-while read benchmark ; do
- echo "Running "$benchmark
- ./$benchmark.gcc > $benchmark.clog
- cresult=$(cat $benchmark.clog | cut -d' ' -f2)
- echo "C output: "$cresult
- ./$benchmark.iver > $benchmark.tmp
- veriresult=$(tail -1 $benchmark.tmp | cut -d' ' -f2)
- cycles=$(tail -2 $benchmark.tmp | head -1 | tr -s ' ' | cut -d' ' -f2)
- echo "Verilog output: "$veriresult
-
- #Undefined checks
- if test -z $veriresult
- then
- echo "FAIL: Verilog returned nothing"
- #exit 0
- fi
-
- # Don't care checks
- if [ $veriresult == "x" ]
- then
- echo "FAIL: Verilog returned don't cares"
- #exit 0
- fi
-
- # unequal result check
- if [ $cresult -ne $veriresult ]
- then
- echo "FAIL: Verilog and C output do not match!"
- #exit 0
- else
- echo "PASS"
- fi
- name=$(echo $benchmark | awk -v FS="/" '{print $NF}')
- echo $name","$cycles >> exec.csv
-done < benchmark-list-master
diff --git a/benchmarks/polybench-syn-div/setup-syn-vericert.sh b/benchmarks/polybench-syn-div/setup-syn-vericert.sh
deleted file mode 100755
index 22356f7..0000000
--- a/benchmarks/polybench-syn-div/setup-syn-vericert.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#! /bin/bash
-
-top=$(pwd)
- #set up
- basedir=poly-syn
- sshhost=$1
- ssh $sshhost "cd ~; rm -r $basedir"
- ssh $sshhost "cd ~; mkdir $basedir"
- scp quartus_synth.tcl $sshhost:$basedir
- scp syn-remote.sh $sshhost:$basedir
- rm syn-list
-
- while read benchmark ;
- do
- echo "Copying "$benchmark" over"
- name=$(echo $benchmark | awk -v FS="/" '{print $NF}')
- echo "Name: "$name
- benchdir="~/$basedir/$name"
- scp $benchmark.v $sshhost:~/$basedir
- echo $name >> syn-list
- done < benchmark-list-master
-
- # copy list over
- scp syn-list $sshhost:$basedir
diff --git a/benchmarks/polybench-syn/Makefile b/benchmarks/polybench-syn/Makefile
index 2c20246..7095d94 100644
--- a/benchmarks/polybench-syn/Makefile
+++ b/benchmarks/polybench-syn/Makefile
@@ -1,15 +1,15 @@
all:
- $(MAKE) -C stencils
- $(MAKE) -C medley
- $(MAKE) -C linear-algebra/blas
- $(MAKE) -C linear-algebra/kernels
- $(MAKE) -C linear-algebra/solvers
- $(MAKE) -C data-mining
+ -$(MAKE) -C stencils
+ -$(MAKE) -C medley
+ -$(MAKE) -C linear-algebra/blas
+ -$(MAKE) -C linear-algebra/kernels
+ -$(MAKE) -C linear-algebra/solvers
+ -$(MAKE) -C data-mining
clean:
- $(MAKE) clean -C stencils
- $(MAKE) clean -C medley
- $(MAKE) clean -C linear-algebra/blas
- $(MAKE) clean -C linear-algebra/kernels
- $(MAKE) clean -C linear-algebra/solvers
- $(MAKE) clean -C data-mining
+ -$(MAKE) clean -C stencils
+ -$(MAKE) clean -C medley
+ -$(MAKE) clean -C linear-algebra/blas
+ -$(MAKE) clean -C linear-algebra/kernels
+ -$(MAKE) clean -C linear-algebra/solvers
+ -$(MAKE) clean -C data-mining
diff --git a/benchmarks/polybench-syn/common.mk b/benchmarks/polybench-syn/common.mk
index 4d450e8..0ebc527 100644
--- a/benchmarks/polybench-syn/common.mk
+++ b/benchmarks/polybench-syn/common.mk
@@ -5,11 +5,12 @@ IVERILOG ?= iverilog
IVERILOG_OPTS ?=
VERILATOR ?= verilator
-VERILATOR_OPTS ?= -Wno-fatal --top main --exe /home/ymherklotz/projects/vericert/driver/verilator_main.cpp
+VERILATOR_OPTS ?= -Wno-fatal -Wno-lint -Wno-style -Wno-WIDTH --top main --exe /home/ymherklotz/projects/vericert/scripts/verilator_main.cpp
TARGETS ?=
%.v: %.c
+ @echo -e "\033[0;35mMAKE\033[0m" $<
$(VERICERT) $(VERICERT_OPTS) $< -o $@
%.iver: %.v
@@ -20,7 +21,8 @@ TARGETS ?=
%.verilator: %.v
$(VERILATOR) $(VERILATOR_OPTS) --Mdir $@ --cc $<
- $(MAKE) -C $@ -f Vmain.mk
+ @echo -e $(MAKE) -C $@ -f Vmain.mk
+ @$(MAKE) -C $@ -f Vmain.mk &>/dev/null
%: %.iver %.gcc %.verilator
cp $< $@
@@ -34,6 +36,7 @@ clean:
rm -f *.clog
rm -f *.tmp
rm -f $(TARGETS)
+ rm -rf *.verilator
.PRECIOUS: %.v %.gcc %.iver
.PHONY: all clean
diff --git a/benchmarks/polybench-syn/poly.csv b/benchmarks/polybench-syn/poly.csv
deleted file mode 100644
index fe71983..0000000
--- a/benchmarks/polybench-syn/poly.csv
+++ /dev/null
@@ -1,26 +0,0 @@
-benchmark,legupcycles,legupfreqMHz,leguplogicutilisation,legupregs,leguprams,legupdsps,legupcomptime,vericertcycles,vericertfreqMHz,vericertlogicutilisation,vericertregs,vericertrams,vericertdsps,vericertcomptime
-durbin,15106,188.61,2509,4008,0,8,4.77,19852,199.2,3027,6168,0,8,0.077
-lu,482766,244.62,3116,4593,0,10,4.72,2634766,92.97,54806,106037,0,6,0.097
-ludcmp,470843,249.69,3605,5397,0,15,4.87,2401354,83.52,57145,111408,0,10,0.132
-trisolv,35382,213.9,2412,3749,0,3,4.73,33550,112.59,28101,55109,0,2,0.086
-2mm,60088,226.5,1114,1936,0,7,4.80,427098,116.9,32600,63212,0,18,0.136
-3mm,204195,188.96,4210,4801,0,43,4.88,539430,97.13,45073,89719,0,18,0.147
-atas,126288,193.24,3026,3719,0,10,4.80,92000,130.41,28603,56646,0,6,0.069
-bicg,11907,303.4,308,537,0,6,4.78,121134,122.74,30091,58799,0,8,0.097
-mvt,16806,384.47,372,597,0,4,4.79,139194,119.93,30753,60450,0,6,0.130
-doitgen,57199,252.14,909,1402,0,2,5.05,350302,126.18,19898,38461,0,4,0.105
-symm,64903,284.41,2155,3170,0,10,4.63,248930,113.92,27693,54514,0,14,0.115
-syrk,57395,278.01,598,976,0,2,4.73,309018,87.15,76889,57816,0,8,0.094
-syr2k,125705,240.85,3149,3679,0,6,4.85,478040,78.6,120116,82032,0,12,0.116
-trmm,41432,281.61,610,990,0,4,4.71,147528,105.61,64031,40502,0,4,0.089
-gemm,83676,192.68,1029,1544,0,35,4.79,360772,121.61,31853,62126,0,16,0.104
-gemver,28087,303.49,1854,2380,0,8,4.68,175326,107.27,32615,64118,0,14,0.099
-gesummv,6634,310.46,298,504,0,4,4.77,111094,79.97,113876,72908,0,10,0.101
-covariance,109992,245.16,2098,3096,0,5,4.77,297450,110.57,28729,56660,0,4,0.083
-fdtd-2d,214153,262.61,2736,3801,0,2,4.73,831912,108.23,31333,61421,0,6,0.116
-heat-3d,41059,115.54,3132,2910,0,60,4.92,555930,110.42,33915,67273,0,9,0.181
-jacobi-1d,6914,386.25,1355,1885,0,0,4.72,16606,277.93,1636,3305,0,0,0.071
-jacobi-2d,84609,240.79,2347,3185,0,2,4.81,357100,113.53,30393,59782,0,4,0.079
-seidel-2d,345294,232.4,2128,3337,0,2,4.68,875758,127.99,26948,53133,0,2,0.091
-floyd-warshall,1238764,235.52,1869,2367,0,2,4.71,4762766,109.4,59859,118101,0,2,0.094
-nussinov,216467,273.07,1078,1431,0,2,4.79,837958,90.73,60663,119303,0,0,0.080
diff --git a/benchmarks/polybench-syn/quartus_synth.tcl b/benchmarks/polybench-syn/quartus_synth.tcl
deleted file mode 100644
index 6edbf0c..0000000
--- a/benchmarks/polybench-syn/quartus_synth.tcl
+++ /dev/null
@@ -1,35 +0,0 @@
-# PRiME pre-KAPow kernel flow
-# Performs pre-KAPow run steps for instrumenting arbitrary Verilog for power monitoring
-# James Davis, 2015
-
-load_package flow
-
-project_new -overwrite syn
-set_global_assignment -name FAMILY "Arria 10"
-set_global_assignment -name DEVICE 10AX115H4F34E3LG
-set_global_assignment -name SYSTEMVERILOG_FILE top.v
-set_global_assignment -name TOP_LEVEL_ENTITY main
-#set_global_assignment -name SDC_FILE syn.sdc
-#set_global_assignment -name auto_resource_sharing on
-#set_global_assignment -name enable_state_machine_inference on
-#set_global_assignment -name optimization_technique area
-#set_global_assignment -name synthesis_effort fast
-#set_global_assignment -name AUTO_RAM_RECOGNITION on
-#set_global_assignment -name remove_duplicate_registers on
-#set_instance_assignment -name RAMSTYLE_ATTRIBUTE LOGIC -to ram
-
-execute_module -tool map
-
-execute_module -tool fit
-
-execute_module -tool sta
-
-#execute_module -tool eda -args "--simulation --tool=vcs"
-
-# set_global_assignment -name POWER_OUTPUT_SAF_NAME ${kernel}.asf
-# set_global_assignment -name POWER_DEFAULT_INPUT_IO_TOGGLE_RATE "12.5 %"
-# set_global_assignment -name POWER_REPORT_SIGNAL_ACTIVITY ON
-# set_global_assignment -name POWER_REPORT_POWER_DISSIPATION ON
-# execute_module -tool pow
-
-project_close
diff --git a/benchmarks/polybench-syn/script.R b/benchmarks/polybench-syn/script.R
deleted file mode 100644
index 0be16da..0000000
--- a/benchmarks/polybench-syn/script.R
+++ /dev/null
@@ -1,29 +0,0 @@
-library("psych")
-
-data = read.csv("poly.csv", header=TRUE)
-leguptime = (data$legupcycles/data$legupfreqMHz)
-veritime = data$vericertcycles/data$vericertfreqMHz
-print(lm(veritime ~ leguptime))
-leguputil = data$leguplogicutilisation/427200*100
-veriutil = data$vericertlogicutilisation/427200*100
-print(lm (veriutil ~ leguputil))
-legupct = data$legupcomptime
-verict = data$vericertcomptime
-print(lm ( verict ~ legupct ))
-
-cycleslowdown=data$vericertcycles/data$legupcycles
-
-print("Cycle count slow down")
-print(geometric.mean(cycleslowdown))
-print("Wall clock slow down")
-print(geometric.mean(veritime/leguptime))
-print("Area overhead")
-print(geometric.mean(veriutil/leguputil))
-print("Compilation time speedup")
-print(geometric.mean(legupct/verict))
-print("LegUp RAM use")
-print(geometric.mean(data$legupregs))
-print("Vericert RAM use")
-print(geometric.mean(data$vericertregs))
-print("Area overhead")
-print(geometric.mean(data$vericertregs/data$legupregs))
diff --git a/benchmarks/polybench-syn/setup-syn-vericert.sh b/benchmarks/polybench-syn/setup-syn-vericert.sh
deleted file mode 100755
index 22356f7..0000000
--- a/benchmarks/polybench-syn/setup-syn-vericert.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#! /bin/bash
-
-top=$(pwd)
- #set up
- basedir=poly-syn
- sshhost=$1
- ssh $sshhost "cd ~; rm -r $basedir"
- ssh $sshhost "cd ~; mkdir $basedir"
- scp quartus_synth.tcl $sshhost:$basedir
- scp syn-remote.sh $sshhost:$basedir
- rm syn-list
-
- while read benchmark ;
- do
- echo "Copying "$benchmark" over"
- name=$(echo $benchmark | awk -v FS="/" '{print $NF}')
- echo "Name: "$name
- benchdir="~/$basedir/$name"
- scp $benchmark.v $sshhost:~/$basedir
- echo $name >> syn-list
- done < benchmark-list-master
-
- # copy list over
- scp syn-list $sshhost:$basedir
diff --git a/benchmarks/polybench-syn/stencils/Makefile b/benchmarks/polybench-syn/stencils/Makefile
index d2e1c9b..9b89b0c 100644
--- a/benchmarks/polybench-syn/stencils/Makefile
+++ b/benchmarks/polybench-syn/stencils/Makefile
@@ -3,4 +3,5 @@ TARGETS := adi fdtd-2d heat-3d jacobi-1d jacobi-2d seidel-2d
include ../common.mk
adi.v: adi.c
+ @echo -e "\033[0;35mMAKE\033[0m" $<
$(VERICERT) $(VERICERT_OPTS) -O0 -finline $< -o $@
diff --git a/benchmarks/polybench-syn/syn-remote.sh b/benchmarks/polybench-syn/syn-remote.sh
deleted file mode 100755
index 879db2e..0000000
--- a/benchmarks/polybench-syn/syn-remote.sh
+++ /dev/null
@@ -1,51 +0,0 @@
-#! /bin/bash
-
-#setup
-while read benchmark ;
-do
-echo "Setting up "$benchmark
-rm -r $benchmark
-mkdir $benchmark
-cp $benchmark.v $benchmark/top.v
-
-done < syn-list
-
-#synthesis
-
-count=0
-while read benchmark ;
-
-do
-echo "Synthesising "$benchmark
-cd $benchmark
-quartus_sh -t ../quartus_synth.tcl &
-let "count=count+1"
-cd ..
-
-if [ $count -eq 4 ]
-then
-echo "I am here"
-wait
-count=0
-fi
-
-done < syn-list
-
-if [ $count -lt 4 ]
-then
-wait
-fi
-
-#extract
-while read benchmark ; do
- cd $benchmark
- echo $(pwd)
- freq=$(grep MHz syn.sta.rpt | tail -2 | head -1 | awk '{print $2}')
- lut=$(sed -n -e 8p syn.fit.summary | awk '{print $6}' | sed 's/,//g')
- regs=$(sed -n -e 9p syn.fit.summary | awk '{print $4}')
- bram=$(sed -n -e 13p syn.fit.summary | awk '{print $5}')
- dsp=$(sed -n -e 14p syn.fit.summary | awk '{print $5}')
- cd ..
- echo $benchmark","$freq","$lut","$regs","$bram","$dsp >> results
-done < syn-list
-
diff --git a/debug/CoqupTest.ml b/debug/CoqupTest.ml
deleted file mode 100644
index 2fe1389..0000000
--- a/debug/CoqupTest.ml
+++ /dev/null
@@ -1,59 +0,0 @@
-open Vericert
-
-open Test
-open Camlcoq
-open FMapPositive
-
-let test_function_transf () =
- print_endline "Testing transformation";
- print_endline "TL PROGRAM: ";
- PrintRTL.print_program stdout testinputprogram;
- print_endline "VERILOG PROGRAM: ";
-
- let v = match Veriloggen.transf_program testinputprogram with
- | Errors.OK v -> v
- | Errors.Error _ ->
- raise (Failure "Error") in
- PrintVerilog.print_program stdout v
-
-let cvalue n = Value.natToValue (Nat.of_int 32) (Nat.of_int n)
-
-let test_values () =
- print_endline "Testing values";
- let v1 = cvalue 138 in
- let v2 = cvalue 12 in
- let v3 = Value.natToValue (Nat.of_int 16) (Nat.of_int 21) in
- PrintVerilog.print_value stdout v1;
- print_newline();
- PrintVerilog.print_value stdout v2;
- print_newline();
- PrintVerilog.print_value stdout v3;
- print_newline();
- print_string "Addition: ";
- PrintVerilog.print_value stdout (Value.vplus v1 v2);
- print_newline();
- print_string "Wrong addition: ";
- PrintVerilog.print_value stdout (Value.vplus v1 v3);
- print_newline();
- print_string "Opt addition: ";
- match Value.vplus_opt v1 v2 with
- | Some x -> begin
- PrintVerilog.print_value stdout x;
- print_endline "";
- match Value.vplus_opt v1 v3 with
- | Some x -> PrintVerilog.print_value stdout x; print_newline()
- | None -> print_endline "Correctly failed in addition"
- end
- | None -> raise (Failure "Error")
-
-let simulate_test () =
- print_endline "Simulation test";
- let v =
- match Veriloggen.transf_program testinputprogram with
- | Errors.OK v -> v
- | _ -> raise (Failure "HLS Error") in
- match Verilog.module_run (Nat.of_int 10) v with
- | Errors.OK lst -> PrintVerilog.print_result stdout (PositiveMap.elements lst)
- | _ -> raise (Failure "Simulation error")
-
-let () = test_function_transf ()
diff --git a/debug/dune b/debug/dune
deleted file mode 100644
index feee97c..0000000
--- a/debug/dune
+++ /dev/null
@@ -1,5 +0,0 @@
-(include_subdirs no)
-
-(executable
- (name VericertTest)
- (libraries vericert))
diff --git a/default.nix b/default.nix
index eabd3d3..341c8fc 100644
--- a/default.nix
+++ b/default.nix
@@ -1,7 +1,7 @@
-with import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/1a56d76d718afb6c47dd96602c915b6d23f7c45d.tar.gz") {};
+with import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/00197eff36bb8f7dd7f53a59f730e1fd8e11b1f4.tar.gz") {};
let
- ncoq = coq_8_13;
- ncoqPackages = coqPackages_8_13;
+ ncoq = coq_8_14;
+ ncoqPackages = coqPackages_8_14;
in
stdenv.mkDerivation {
name = "vericert";
@@ -13,10 +13,9 @@ stdenv.mkDerivation {
ncoq.ocamlPackages.menhirLib
ncoqPackages.serapi
- python3 python3Packages.docutils python3Packages.pygments
- python3Packages.dominate
- python3Packages.pelican
+ python3
python3Packages.alectryon
+ python3Packages.sphinx_rtd_theme
];
enableParallelBuilding = true;
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 0000000..8a34845
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,24 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS ?=
+SPHINXBUILD ?= sphinx-build
+SOURCEDIR = .
+BUILDDIR = _build
+SOURCE_DATE_EPOCH = $(shell git log -1 --format=%ct)
+
+VS_DOCS := Compiler.v hls/RTLBlockInstr.v hls/RTLBlockgen.v hls/RTLBlockgenproof.v
+
+# Put it first so that "make" without argument is like "make help".
+help:
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+ $(foreach d,$(VS_DOCS),cp ../src/$(d) src/$(d);)
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/doc/Makefile.extr b/doc/Makefile.extr
new file mode 100644
index 0000000..9d4f361
--- /dev/null
+++ b/doc/Makefile.extr
@@ -0,0 +1,39 @@
+all: manual src man-html
+
+install-deps:
+ emacs --batch --load ./res/install-deps.el
+
+%.man: %.org
+ emacs --batch --file $< --load ./res/publish.el --funcall org-man-export-to-man
+
+%.html: %.org
+ emacs --batch --file $< --load ./res/publish.el --funcall org-html-export-to-html
+
+manual:
+ mkdir -p manual
+ emacs --batch --file documentation.org --load ./res/publish.el --funcall org-texinfo-export-to-texinfo
+ makeinfo --html --number-sections --no-split \
+ --css-ref "https://www.gnu.org/software/emacs/manual.css" \
+ vericert.texi -o ./manual/index.html
+ cp -r images ./manual/.
+
+man-html: man.html
+ mkdir -p man
+ cp man.html ./man/vericert.1.html
+
+vericert.1: man.man
+ cp $< $@
+
+src:
+ $(MAKE) -C .. doc
+ cp -r ../html src
+
+upload:
+ tar caf docs.tar.xz manual man src
+ rsync docs.tar.xz "zk@leika.ymhg.org:~"
+
+.PHONY: all upload manual man src install-deps man-html
+
+clean:
+ rm -rf manual man src
+ rm -f docs.tar.xz
diff --git a/doc/README.org b/doc/README.org
new file mode 100644
index 0000000..4113ed9
--- /dev/null
+++ b/doc/README.org
@@ -0,0 +1,7 @@
+#+title: Vericert Documentation
+
+The documentation for [[https://github.com/ymherklotz/vericert][Vericert]], which is written in the [[/documentation.org][documentation.org]] file.
+
+* How to develop on documentation
+
+The documentation uses =hugo= to generate the website,
diff --git a/doc/_static/css/custom.css b/doc/_static/css/custom.css
new file mode 100644
index 0000000..e899c8f
--- /dev/null
+++ b/doc/_static/css/custom.css
@@ -0,0 +1,31 @@
+.alectryon-coqdoc .doc .code,
+.alectryon-coqdoc .doc .comment,
+.alectryon-coqdoc .doc .inlinecode,
+.alectryon-mref,
+.alectryon-block, .alectryon-io,
+.alectryon-toggle-label, .alectryon-banner, pre, tt, code,
+.rst-content kbd, .rst-content pre, .rst-content samp,
+.rst-content .linenodiv pre, .rst-content div[class^="highlight"] pre, .rst-content pre.literal-block {
+ font-family: 'Iosevka Fixed Slab', 'Iosevka Slab Web', 'Iosevka Web', 'Iosevka Slab',
+ 'Iosevka', 'Fira Code', monospace;
+ font-feature-settings: "COQX" 1 /* Coq ligatures */, "XV00" 1 /* Legacy */, "calt" 1 /* Fallback */;
+ line-height: initial;
+ font-size: 0.9em;
+}
+
+img { width: 100%; }
+a { color: #469369; }
+a:hover { color: #60b386; }
+
+.wy-menu-vertical header, .wy-menu-vertical p.caption {
+ color: #fff5db;
+}
+
+.wy-nav-content, .wy-menu-vertical li.current > a, .wy-menu-vertical li.on a {
+ background-color: #fffbf2;
+ color: #2a3e40;
+}
+
+.wy-side-nav-search .wy-dropdown > a, .wy-side-nav-search > a {
+ color: #2a3e40;
+}
diff --git a/doc/_static/images/toolflow.pdf b/doc/_static/images/toolflow.pdf
new file mode 100644
index 0000000..5fcee67
--- /dev/null
+++ b/doc/_static/images/toolflow.pdf
Binary files differ
diff --git a/doc/_static/images/toolflow.png b/doc/_static/images/toolflow.png
new file mode 100644
index 0000000..601d6be
--- /dev/null
+++ b/doc/_static/images/toolflow.png
Binary files differ
diff --git a/doc/_static/images/toolflow.svg b/doc/_static/images/toolflow.svg
new file mode 100644
index 0000000..0d8f39f
--- /dev/null
+++ b/doc/_static/images/toolflow.svg
@@ -0,0 +1,1250 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ width="308.97266pt"
+ height="124.71875pt"
+ viewBox="0 0 308.97267 124.71875"
+ version="1.2"
+ id="svg466"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs
+ id="defs183">
+ <g
+ id="g172">
+ <symbol
+ overflow="visible"
+ id="glyph0-0">
+ <path
+ style="stroke:none"
+ d=""
+ id="path25" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-1">
+ <path
+ style="stroke:none"
+ d="M 6.625,-2.328125 C 6.625,-2.421875 6.625,-2.5 6.5,-2.5 6.390625,-2.5 6.390625,-2.4375 6.375,-2.328125 6.296875,-0.90625 5.234375,-0.09375 4.140625,-0.09375 c -0.609375,0 -2.5625,-0.328125 -2.5625,-3.3125 0,-2.96875 1.953125,-3.3125 2.5625,-3.3125 1.078125,0 1.96875,0.90625 2.171875,2.359375 C 6.328125,-4.21875 6.328125,-4.1875 6.46875,-4.1875 6.625,-4.1875 6.625,-4.21875 6.625,-4.421875 V -6.78125 c 0,-0.171875 0,-0.25 -0.109375,-0.25 -0.03125,0 -0.078125,0 -0.15625,0.125 l -0.5,0.734375 C 5.5,-6.53125 4.984375,-7.03125 4.03125,-7.03125 c -1.875,0 -3.46875,1.59375 -3.46875,3.625 0,2.0625 1.609375,3.625 3.46875,3.625 1.625,0 2.59375,-1.390625 2.59375,-2.546875 z m 0,0"
+ id="path28" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-2">
+ <path
+ style="stroke:none"
+ d="m 2.546875,0 v -0.3125 c -0.671875,0 -0.78125,0 -0.78125,-0.4375 V -6.921875 L 0.328125,-6.8125 V -6.5 c 0.703125,0 0.78125,0.0625 0.78125,0.5625 V -0.75 c 0,0.4375 -0.109375,0.4375 -0.78125,0.4375 V 0 L 1.4375,-0.03125 Z m 0,0"
+ id="path31" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-3">
+ <path
+ style="stroke:none"
+ d="m 2.46875,0 v -0.3125 c -0.671875,0 -0.703125,-0.046875 -0.703125,-0.4375 V -4.40625 L 0.375,-4.296875 v 0.3125 c 0.640625,0 0.734375,0.0625 0.734375,0.546875 V -0.75 c 0,0.4375 -0.109375,0.4375 -0.78125,0.4375 V 0 l 1.09375,-0.03125 C 1.78125,-0.03125 2.125,-0.015625 2.46875,0 Z m -0.5625,-6.015625 c 0,-0.28125 -0.21875,-0.53125 -0.515625,-0.53125 -0.34375,0 -0.546875,0.28125 -0.546875,0.53125 C 0.84375,-5.75 1.078125,-5.5 1.375,-5.5 c 0.34375,0 0.53125,-0.265625 0.53125,-0.515625 z m 0,0"
+ id="path34" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-4">
+ <path
+ style="stroke:none"
+ d="m 4.828125,-4.03125 c 0,-0.171875 -0.109375,-0.484375 -0.5,-0.484375 -0.203125,0 -0.640625,0.0625 -1.0625,0.46875 C 2.84375,-4.375 2.4375,-4.40625 2.21875,-4.40625 c -0.9375,0 -1.625,0.6875 -1.625,1.453125 0,0.4375 0.21875,0.8125 0.46875,1.03125 -0.125,0.140625 -0.3125,0.46875 -0.3125,0.828125 0,0.3125 0.140625,0.6875 0.453125,0.890625 -0.609375,0.15625 -0.921875,0.59375 -0.921875,0.984375 0,0.71875 0.984375,1.265625 2.203125,1.265625 1.171875,0 2.203125,-0.5 2.203125,-1.28125 0,-0.34375 -0.125,-0.859375 -0.640625,-1.140625 -0.53125,-0.265625 -1.109375,-0.265625 -1.71875,-0.265625 -0.25,0 -0.671875,0 -0.75,-0.015625 C 1.265625,-0.703125 1.0625,-1 1.0625,-1.328125 c 0,-0.03125 0,-0.265625 0.15625,-0.46875 0.390625,0.28125 0.8125,0.3125 1,0.3125 0.921875,0 1.609375,-0.6875 1.609375,-1.453125 0,-0.375 -0.15625,-0.734375 -0.40625,-0.96875 C 3.78125,-4.25 4.140625,-4.296875 4.3125,-4.296875 c 0,0 0.078125,0 0.109375,0.015625 C 4.3125,-4.25 4.25,-4.140625 4.25,-4.015625 c 0,0.171875 0.140625,0.28125 0.296875,0.28125 0.09375,0 0.28125,-0.0625 0.28125,-0.296875 z m -1.75,1.078125 c 0,0.265625 0,0.59375 -0.15625,0.84375 C 2.84375,-2 2.609375,-1.71875 2.21875,-1.71875 c -0.875,0 -0.875,-1 -0.875,-1.21875 0,-0.265625 0.015625,-0.59375 0.15625,-0.84375 0.078125,-0.109375 0.3125,-0.390625 0.71875,-0.390625 0.859375,0 0.859375,0.984375 0.859375,1.21875 z m 1.09375,3.734375 c 0,0.546875 -0.703125,1.046875 -1.671875,1.046875 -1.015625,0 -1.703125,-0.515625 -1.703125,-1.046875 0,-0.453125 0.375,-0.828125 0.8125,-0.84375 h 0.59375 c 0.859375,0 1.96875,0 1.96875,0.84375 z m 0,0"
+ id="path37" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-5">
+ <path
+ style="stroke:none"
+ d="m 5.328125,0 v -0.3125 c -0.515625,0 -0.765625,0 -0.765625,-0.296875 v -1.90625 c 0,-0.859375 0,-1.15625 -0.3125,-1.515625 -0.140625,-0.171875 -0.46875,-0.375 -1.046875,-0.375 -0.84375,0 -1.28125,0.59375 -1.4375,0.953125 H 1.75 v -3.46875 L 0.3125,-6.8125 V -6.5 c 0.703125,0 0.78125,0.0625 0.78125,0.5625 V -0.75 c 0,0.4375 -0.109375,0.4375 -0.78125,0.4375 V 0 L 1.453125,-0.03125 2.5625,0 v -0.3125 c -0.671875,0 -0.78125,0 -0.78125,-0.4375 V -2.59375 C 1.78125,-3.625 2.5,-4.1875 3.125,-4.1875 c 0.640625,0 0.75,0.53125 0.75,1.109375 V -0.75 c 0,0.4375 -0.109375,0.4375 -0.78125,0.4375 V 0 l 1.125,-0.03125 z m 0,0"
+ id="path40" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-6">
+ <path
+ style="stroke:none"
+ d="m 3.3125,-1.234375 v -0.5625 h -0.25 V -1.25 c 0,0.734375 -0.296875,1.109375 -0.671875,1.109375 -0.671875,0 -0.671875,-0.90625 -0.671875,-1.078125 v -2.765625 h 1.4375 v -0.3125 H 1.71875 V -6.125 h -0.25 c 0,0.8125 -0.296875,1.875 -1.28125,1.921875 v 0.21875 h 0.84375 v 2.75 c 0,1.21875 0.9375,1.34375 1.296875,1.34375 0.703125,0 0.984375,-0.703125 0.984375,-1.34375 z m 0,0"
+ id="path43" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-7">
+ <path
+ style="stroke:none"
+ d="m 8.109375,0 v -0.3125 c -0.515625,0 -0.765625,0 -0.78125,-0.296875 v -1.90625 c 0,-0.859375 0,-1.15625 -0.3125,-1.515625 -0.140625,-0.171875 -0.46875,-0.375 -1.046875,-0.375 -0.828125,0 -1.28125,0.59375 -1.4375,0.984375 C 4.390625,-4.296875 3.65625,-4.40625 3.203125,-4.40625 2.46875,-4.40625 2,-3.984375 1.71875,-3.359375 V -4.40625 L 0.3125,-4.296875 v 0.3125 c 0.703125,0 0.78125,0.0625 0.78125,0.5625 V -0.75 c 0,0.4375 -0.109375,0.4375 -0.78125,0.4375 V 0 L 1.453125,-0.03125 2.5625,0 v -0.3125 c -0.671875,0 -0.78125,0 -0.78125,-0.4375 V -2.59375 C 1.78125,-3.625 2.5,-4.1875 3.125,-4.1875 c 0.640625,0 0.75,0.53125 0.75,1.109375 V -0.75 c 0,0.4375 -0.109375,0.4375 -0.78125,0.4375 V 0 L 4.21875,-0.03125 5.328125,0 v -0.3125 c -0.65625,0 -0.765625,0 -0.765625,-0.4375 v -1.84375 c 0,-1.03125 0.703125,-1.59375 1.34375,-1.59375 0.625,0 0.734375,0.53125 0.734375,1.109375 V -0.75 c 0,0.4375 -0.109375,0.4375 -0.78125,0.4375 V 0 l 1.125,-0.03125 z m 0,0"
+ id="path46" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-8">
+ <path
+ style="stroke:none"
+ d="m 5.328125,0 v -0.3125 c -0.515625,0 -0.765625,0 -0.765625,-0.296875 v -1.90625 c 0,-0.859375 0,-1.15625 -0.3125,-1.515625 -0.140625,-0.171875 -0.46875,-0.375 -1.046875,-0.375 C 2.46875,-4.40625 2,-3.984375 1.71875,-3.359375 V -4.40625 L 0.3125,-4.296875 v 0.3125 c 0.703125,0 0.78125,0.0625 0.78125,0.5625 V -0.75 c 0,0.4375 -0.109375,0.4375 -0.78125,0.4375 V 0 L 1.453125,-0.03125 2.5625,0 v -0.3125 c -0.671875,0 -0.78125,0 -0.78125,-0.4375 V -2.59375 C 1.78125,-3.625 2.5,-4.1875 3.125,-4.1875 c 0.640625,0 0.75,0.53125 0.75,1.109375 V -0.75 c 0,0.4375 -0.109375,0.4375 -0.78125,0.4375 V 0 l 1.125,-0.03125 z m 0,0"
+ id="path49" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-9">
+ <path
+ style="stroke:none"
+ d="M 4.6875,-2.140625 C 4.6875,-3.40625 3.703125,-4.46875 2.5,-4.46875 c -1.25,0 -2.21875,1.09375 -2.21875,2.328125 0,1.296875 1.03125,2.25 2.203125,2.25 1.203125,0 2.203125,-0.984375 2.203125,-2.25 z M 3.875,-2.21875 c 0,0.359375 0,0.90625 -0.21875,1.34375 -0.234375,0.453125 -0.671875,0.734375 -1.15625,0.734375 -0.4375,0 -0.875,-0.203125 -1.140625,-0.671875 -0.25,-0.4375 -0.25,-1.046875 -0.25,-1.40625 0,-0.390625 0,-0.921875 0.234375,-1.359375 C 1.609375,-4.03125 2.078125,-4.25 2.484375,-4.25 c 0.4375,0 0.859375,0.21875 1.125,0.65625 0.265625,0.421875 0.265625,1 0.265625,1.375 z m 0,0"
+ id="path52" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-10">
+ <path
+ style="stroke:none"
+ d="m 3.625,-3.796875 c 0,-0.3125 -0.3125,-0.609375 -0.734375,-0.609375 -0.734375,0 -1.09375,0.671875 -1.21875,1.09375 V -4.40625 L 0.28125,-4.296875 v 0.3125 c 0.703125,0 0.78125,0.0625 0.78125,0.5625 V -0.75 c 0,0.4375 -0.109375,0.4375 -0.78125,0.4375 V 0 l 1.140625,-0.03125 c 0.390625,0 0.859375,0 1.265625,0.03125 V -0.3125 H 2.46875 c -0.734375,0 -0.75,-0.109375 -0.75,-0.46875 V -2.3125 c 0,-0.984375 0.421875,-1.875 1.171875,-1.875 0.0625,0 0.09375,0 0.109375,0.015625 -0.03125,0 -0.234375,0.125 -0.234375,0.390625 0,0.265625 0.21875,0.421875 0.4375,0.421875 0.171875,0 0.421875,-0.125 0.421875,-0.4375 z m 0,0"
+ id="path55" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-11">
+ <path
+ style="stroke:none"
+ d="m 4.96875,-1.859375 c 0,-0.984375 -0.65625,-1.8125 -1.484375,-2.015625 l -1.28125,-0.296875 c -0.625,-0.15625 -1,-0.6875 -1,-1.265625 0,-0.703125 0.53125,-1.3125 1.3125,-1.3125 1.65625,0 1.875,1.640625 1.9375,2.078125 0.015625,0.0625 0.015625,0.125 0.125,0.125 0.125,0 0.125,-0.046875 0.125,-0.234375 v -2 c 0,-0.171875 0,-0.25 -0.109375,-0.25 -0.0625,0 -0.078125,0.015625 -0.140625,0.140625 l -0.359375,0.5625 C 3.796875,-6.625 3.390625,-7.03125 2.5,-7.03125 c -1.109375,0 -1.9375,0.875 -1.9375,1.9375 0,0.828125 0.53125,1.5625 1.296875,1.828125 0.109375,0.03125 0.625,0.15625 1.328125,0.328125 0.265625,0.0625 0.5625,0.140625 0.84375,0.5 0.203125,0.265625 0.3125,0.59375 0.3125,0.921875 0,0.703125 -0.5,1.421875 -1.34375,1.421875 -0.28125,0 -1.046875,-0.046875 -1.578125,-0.53125 C 0.84375,-1.171875 0.8125,-1.796875 0.8125,-2.15625 0.796875,-2.265625 0.71875,-2.265625 0.6875,-2.265625 c -0.125,0 -0.125,0.078125 -0.125,0.25 v 2 c 0,0.171875 0,0.234375 0.109375,0.234375 0.0625,0 0.078125,-0.015625 0.140625,-0.125 0,0 0.03125,-0.046875 0.359375,-0.578125 0.3125,0.34375 0.953125,0.703125 1.84375,0.703125 1.15625,0 1.953125,-0.96875 1.953125,-2.078125 z m 0,0"
+ id="path58" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-12">
+ <path
+ style="stroke:none"
+ d="m 4.140625,-1.1875 c 0,-0.09375 -0.078125,-0.125 -0.140625,-0.125 -0.078125,0 -0.109375,0.0625 -0.125,0.140625 -0.34375,1.03125 -1.25,1.03125 -1.34375,1.03125 -0.5,0 -0.890625,-0.296875 -1.125,-0.671875 -0.296875,-0.46875 -0.296875,-1.125 -0.296875,-1.484375 h 2.78125 c 0.21875,0 0.25,0 0.25,-0.21875 0,-0.984375 -0.546875,-1.953125 -1.78125,-1.953125 -1.15625,0 -2.078125,1.03125 -2.078125,2.28125 0,1.328125 1.046875,2.296875 2.1875,2.296875 C 3.6875,0.109375 4.140625,-1 4.140625,-1.1875 Z m -0.65625,-1.328125 h -2.375 C 1.171875,-4 2.015625,-4.25 2.359375,-4.25 c 1.015625,0 1.125,1.34375 1.125,1.734375 z m 0,0"
+ id="path61" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-13">
+ <path
+ style="stroke:none"
+ d="m 4.5625,-1.703125 c 0,-0.8125 -0.640625,-1.59375 -1.671875,-1.8125 0.8125,-0.265625 1.390625,-0.953125 1.390625,-1.75 0,-0.8125 -0.875,-1.375 -1.828125,-1.375 -1,0 -1.765625,0.59375 -1.765625,1.359375 0,0.328125 0.21875,0.515625 0.515625,0.515625 0.296875,0 0.5,-0.21875 0.5,-0.515625 0,-0.484375 -0.46875,-0.484375 -0.609375,-0.484375 0.296875,-0.5 0.953125,-0.625 1.3125,-0.625 0.421875,0 0.96875,0.21875 0.96875,1.109375 0,0.125 -0.03125,0.703125 -0.28125,1.140625 C 2.796875,-3.65625 2.453125,-3.625 2.203125,-3.625 2.125,-3.609375 1.890625,-3.59375 1.8125,-3.59375 c -0.078125,0.015625 -0.140625,0.03125 -0.140625,0.125 0,0.109375 0.0625,0.109375 0.234375,0.109375 h 0.4375 c 0.8125,0 1.1875,0.671875 1.1875,1.65625 0,1.359375 -0.6875,1.640625 -1.125,1.640625 -0.4375,0 -1.1875,-0.171875 -1.53125,-0.75 0.34375,0.046875 0.65625,-0.171875 0.65625,-0.546875 0,-0.359375 -0.265625,-0.5625 -0.546875,-0.5625 -0.25,0 -0.5625,0.140625 -0.5625,0.578125 0,0.90625 0.921875,1.5625 2.015625,1.5625 1.21875,0 2.125,-0.90625 2.125,-1.921875 z m 0,0"
+ id="path64" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-14">
+ <path
+ style="stroke:none"
+ d="M 7.140625,0 V -0.3125 H 6.96875 C 6.375,-0.3125 6.234375,-0.375 6.125,-0.703125 L 3.96875,-6.9375 c -0.046875,-0.125 -0.078125,-0.203125 -0.234375,-0.203125 -0.15625,0 -0.1875,0.0625 -0.234375,0.203125 L 1.4375,-0.984375 C 1.25,-0.46875 0.859375,-0.3125 0.3125,-0.3125 V 0 L 1.328125,-0.03125 2.484375,0 v -0.3125 c -0.5,0 -0.75,-0.25 -0.75,-0.5 0,-0.03125 0.015625,-0.140625 0.015625,-0.15625 L 2.21875,-2.265625 H 4.671875 L 5.203125,-0.75 c 0.015625,0.046875 0.03125,0.109375 0.03125,0.140625 0,0.296875 -0.5625,0.296875 -0.828125,0.296875 V 0 c 0.359375,-0.03125 1.0625,-0.03125 1.4375,-0.03125 z M 4.5625,-2.578125 H 2.328125 l 1.109375,-3.25 z m 0,0"
+ id="path67" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-15">
+ <path
+ style="stroke:none"
+ d="m 5.796875,-2.578125 h -0.25 c -0.109375,1.015625 -0.25,2.265625 -2,2.265625 h -0.8125 C 2.265625,-0.3125 2.25,-0.375 2.25,-0.703125 v -5.3125 C 2.25,-6.359375 2.25,-6.5 3.1875,-6.5 H 3.515625 V -6.8125 C 3.15625,-6.78125 2.25,-6.78125 1.84375,-6.78125 c -0.390625,0 -1.171875,0 -1.515625,-0.03125 V -6.5 H 0.5625 c 0.765625,0 0.796875,0.109375 0.796875,0.46875 v 5.25 c 0,0.359375 -0.03125,0.46875 -0.796875,0.46875 H 0.328125 V 0 h 5.1875 z m 0,0"
+ id="path70" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-16">
+ <path
+ style="stroke:none"
+ d="m 6.828125,-4.5 -0.1875,-2.25 h -6.09375 l -0.1875,2.25 h 0.25 C 0.75,-6.109375 0.890625,-6.4375 2.40625,-6.4375 c 0.171875,0 0.4375,0 0.53125,0.015625 0.21875,0.046875 0.21875,0.15625 0.21875,0.375 v 5.265625 c 0,0.328125 0,0.46875 -1.046875,0.46875 H 1.703125 V 0 C 2.109375,-0.03125 3.125,-0.03125 3.59375,-0.03125 c 0.453125,0 1.484375,0 1.890625,0.03125 v -0.3125 h -0.40625 c -1.046875,0 -1.046875,-0.140625 -1.046875,-0.46875 v -5.265625 c 0,-0.1875 0,-0.328125 0.1875,-0.375 0.109375,-0.015625 0.375,-0.015625 0.5625,-0.015625 1.515625,0 1.65625,0.328125 1.796875,1.9375 z m 0,0"
+ id="path73" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-17">
+ <path
+ style="stroke:none"
+ d="m 4.8125,-0.890625 v -0.5625 h -0.25 v 0.5625 C 4.5625,-0.3125 4.3125,-0.25 4.203125,-0.25 3.875,-0.25 3.84375,-0.703125 3.84375,-0.75 v -1.984375 c 0,-0.421875 0,-0.8125 -0.359375,-1.1875 C 3.09375,-4.3125 2.59375,-4.46875 2.109375,-4.46875 c -0.8125,0 -1.5,0.46875 -1.5,1.125 0,0.296875 0.203125,0.46875 0.453125,0.46875 0.28125,0 0.46875,-0.203125 0.46875,-0.453125 0,-0.125 -0.0625,-0.453125 -0.515625,-0.453125 C 1.28125,-4.140625 1.78125,-4.25 2.09375,-4.25 c 0.484375,0 1.0625,0.390625 1.0625,1.28125 v 0.359375 C 2.640625,-2.578125 1.9375,-2.546875 1.3125,-2.25 c -0.75,0.34375 -1,0.859375 -1,1.296875 0,0.8125 0.96875,1.0625 1.59375,1.0625 0.671875,0 1.125,-0.40625 1.3125,-0.859375 0.046875,0.390625 0.3125,0.8125 0.78125,0.8125 0.203125,0 0.8125,-0.140625 0.8125,-0.953125 z m -1.65625,-0.5 c 0,0.9375 -0.71875,1.28125 -1.171875,1.28125 -0.484375,0 -0.890625,-0.34375 -0.890625,-0.84375 0,-0.546875 0.40625,-1.375 2.0625,-1.4375 z m 0,0"
+ id="path76" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-18">
+ <path
+ style="stroke:none"
+ d="M 4.140625,-1.1875 C 4.140625,-1.28125 4.03125,-1.28125 4,-1.28125 c -0.078125,0 -0.109375,0.03125 -0.125,0.09375 -0.28125,0.921875 -0.9375,1.046875 -1.296875,1.046875 -0.53125,0 -1.40625,-0.421875 -1.40625,-2.03125 0,-1.625 0.8125,-2.046875 1.34375,-2.046875 0.09375,0 0.71875,0.015625 1.0625,0.375 -0.40625,0.03125 -0.46875,0.328125 -0.46875,0.453125 0,0.265625 0.1875,0.453125 0.453125,0.453125 0.265625,0 0.46875,-0.15625 0.46875,-0.46875 0,-0.671875 -0.765625,-1.0625 -1.53125,-1.0625 -1.25,0 -2.15625,1.078125 -2.15625,2.3125 0,1.28125 0.984375,2.265625 2.140625,2.265625 1.328125,0 1.65625,-1.203125 1.65625,-1.296875 z m 0,0"
+ id="path79" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-19">
+ <path
+ style="stroke:none"
+ d="m 4.5625,-2.03125 c 0,-1.265625 -0.890625,-2.21875 -2,-2.21875 -0.671875,0 -1.046875,0.5 -1.25,0.984375 v -0.25 c 0,-2.515625 1.234375,-2.875 1.75,-2.875 0.234375,0 0.65625,0.0625 0.875,0.40625 -0.15625,0 -0.546875,0 -0.546875,0.4375 0,0.3125 0.234375,0.46875 0.453125,0.46875 0.15625,0 0.46875,-0.09375 0.46875,-0.484375 0,-0.59375 -0.4375,-1.078125 -1.265625,-1.078125 -1.28125,0 -2.625,1.28125 -2.625,3.484375 0,2.671875 1.15625,3.375 2.078125,3.375 1.109375,0 2.0625,-0.9375 2.0625,-2.25 z M 3.65625,-2.046875 c 0,0.484375 0,0.984375 -0.171875,1.34375 C 3.1875,-0.109375 2.734375,-0.0625 2.5,-0.0625 c -0.625,0 -0.921875,-0.59375 -0.984375,-0.75 -0.1875,-0.46875 -0.1875,-1.265625 -0.1875,-1.4375 0,-0.78125 0.328125,-1.78125 1.21875,-1.78125 0.171875,0 0.625,0 0.9375,0.625 0.171875,0.359375 0.171875,0.875 0.171875,1.359375 z m 0,0"
+ id="path82" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-20">
+ <path
+ style="stroke:none"
+ d="m 4.6875,-1.640625 v -0.3125 H 3.703125 v -4.53125 c 0,-0.203125 0,-0.265625 -0.171875,-0.265625 -0.078125,0 -0.109375,0 -0.1875,0.125 l -3.0625,4.671875 v 0.3125 H 2.9375 v 0.859375 c 0,0.359375 -0.03125,0.46875 -0.765625,0.46875 H 1.96875 V 0 C 2.375,-0.03125 2.890625,-0.03125 3.3125,-0.03125 c 0.421875,0 0.9375,0 1.359375,0.03125 v -0.3125 h -0.21875 c -0.734375,0 -0.75,-0.109375 -0.75,-0.46875 v -0.859375 z m -1.703125,-0.3125 H 0.5625 l 2.421875,-3.71875 z m 0,0"
+ id="path85" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-21">
+ <path
+ style="stroke:none"
+ d="m 5.140625,0 v -0.3125 c -0.53125,0 -0.71875,-0.015625 -0.9375,-0.3125 L 2.859375,-2.34375 C 3.15625,-2.71875 3.53125,-3.203125 3.78125,-3.46875 4.09375,-3.828125 4.5,-3.984375 4.96875,-3.984375 v -0.3125 c -0.265625,0.015625 -0.5625,0.03125 -0.828125,0.03125 -0.296875,0 -0.828125,-0.015625 -0.953125,-0.03125 v 0.3125 c 0.21875,0.015625 0.296875,0.140625 0.296875,0.3125 0,0.15625 -0.109375,0.28125 -0.15625,0.34375 L 2.71875,-2.546875 1.9375,-3.5625 C 1.84375,-3.65625 1.84375,-3.671875 1.84375,-3.734375 c 0,-0.15625 0.15625,-0.25 0.34375,-0.25 v -0.3125 l -1.078125,0.03125 c -0.203125,0 -0.671875,-0.015625 -0.9375,-0.03125 v 0.3125 c 0.703125,0 0.703125,0 1.171875,0.609375 l 0.984375,1.28125 c -0.46875,0.59375 -0.46875,0.625 -0.9375,1.1875 C 0.921875,-0.328125 0.328125,-0.3125 0.125,-0.3125 V 0 c 0.25,-0.015625 0.5625,-0.03125 0.828125,-0.03125 L 1.890625,0 v -0.3125 c -0.21875,-0.03125 -0.28125,-0.15625 -0.28125,-0.3125 0,-0.21875 0.28125,-0.546875 0.890625,-1.265625 l 0.765625,1 C 3.34375,-0.78125 3.46875,-0.625 3.46875,-0.5625 c 0,0.09375 -0.09375,0.25 -0.359375,0.25 V 0 L 4.1875,-0.03125 c 0.265625,0 0.65625,0.015625 0.953125,0.03125 z m 0,0"
+ id="path88" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-22">
+ <path
+ style="stroke:none"
+ d="m 4.5625,-1.671875 c 0,-0.359375 -0.109375,-0.8125 -0.5,-1.234375 C 3.875,-3.109375 3.71875,-3.203125 3.078125,-3.609375 3.796875,-3.984375 4.28125,-4.5 4.28125,-5.15625 c 0,-0.921875 -0.875,-1.484375 -1.78125,-1.484375 -1,0 -1.8125,0.734375 -1.8125,1.671875 0,0.171875 0.015625,0.625 0.4375,1.09375 0.109375,0.109375 0.484375,0.359375 0.734375,0.53125 C 1.28125,-3.046875 0.421875,-2.5 0.421875,-1.5 c 0,1.046875 1.015625,1.71875 2.0625,1.71875 1.125,0 2.078125,-0.828125 2.078125,-1.890625 z M 3.84375,-5.15625 c 0,0.578125 -0.390625,1.046875 -0.984375,1.390625 L 1.625,-4.5625 c -0.453125,-0.296875 -0.5,-0.625 -0.5,-0.796875 0,-0.609375 0.65625,-1.03125 1.359375,-1.03125 0.71875,0 1.359375,0.515625 1.359375,1.234375 z M 4.0625,-1.3125 c 0,0.734375 -0.75,1.25 -1.5625,1.25 -0.859375,0 -1.578125,-0.609375 -1.578125,-1.4375 0,-0.578125 0.3125,-1.21875 1.15625,-1.6875 L 3.3125,-2.40625 c 0.28125,0.1875 0.75,0.484375 0.75,1.09375 z m 0,0"
+ id="path91" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-23">
+ <path
+ style="stroke:none"
+ d="m 7.140625,0 v -0.3125 h -0.25 c -0.765625,0 -0.78125,-0.109375 -0.78125,-0.46875 v -5.25 C 6.109375,-6.390625 6.125,-6.5 6.890625,-6.5 h 0.25 v -0.3125 c -0.359375,0.03125 -1.09375,0.03125 -1.46875,0.03125 -0.375,0 -1.125,0 -1.46875,-0.03125 V -6.5 H 4.4375 c 0.765625,0 0.78125,0.109375 0.78125,0.46875 v 2.328125 H 2.25 V -6.03125 C 2.25,-6.390625 2.265625,-6.5 3.03125,-6.5 h 0.234375 v -0.3125 c -0.34375,0.03125 -1.078125,0.03125 -1.46875,0.03125 -0.375,0 -1.125,0 -1.46875,-0.03125 V -6.5 H 0.5625 c 0.765625,0 0.796875,0.109375 0.796875,0.46875 v 5.25 c 0,0.359375 -0.03125,0.46875 -0.796875,0.46875 H 0.328125 V 0 c 0.34375,-0.03125 1.09375,-0.03125 1.46875,-0.03125 0.375,0 1.125,0 1.46875,0.03125 V -0.3125 H 3.03125 C 2.265625,-0.3125 2.25,-0.421875 2.25,-0.78125 v -2.609375 h 2.96875 v 2.609375 c 0,0.359375 -0.015625,0.46875 -0.78125,0.46875 H 4.203125 V 0 c 0.34375,-0.03125 1.078125,-0.03125 1.453125,-0.03125 0.390625,0 1.125,0 1.484375,0.03125 z m 0,0"
+ id="path94" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-24">
+ <path
+ style="stroke:none"
+ d="M 7.28125,-6.5 V -6.8125 C 6.96875,-6.78125 6.5625,-6.78125 6.3125,-6.78125 L 5.171875,-6.8125 V -6.5 C 5.6875,-6.484375 5.90625,-6.234375 5.90625,-6 c 0,0.078125 -0.03125,0.140625 -0.046875,0.203125 L 4.03125,-1 2.125,-6.03125 C 2.0625,-6.171875 2.0625,-6.203125 2.0625,-6.203125 2.0625,-6.5 2.625,-6.5 2.875,-6.5 V -6.8125 C 2.515625,-6.78125 1.828125,-6.78125 1.453125,-6.78125 L 0.1875,-6.8125 V -6.5 c 0.65625,0 0.84375,0 0.984375,0.375 L 3.484375,0 c 0.0625,0.1875 0.109375,0.21875 0.25,0.21875 0.15625,0 0.1875,-0.046875 0.234375,-0.1875 L 6.1875,-5.828125 C 6.328125,-6.203125 6.59375,-6.484375 7.28125,-6.5 Z m 0,0"
+ id="path97" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-0">
+ <path
+ style="stroke:none"
+ d=""
+ id="path100" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-1">
+ <path
+ style="stroke:none"
+ d="m 1.90625,-2.5 c 0,-0.28125 -0.234375,-0.515625 -0.515625,-0.515625 -0.296875,0 -0.53125,0.234375 -0.53125,0.515625 0,0.296875 0.234375,0.53125 0.53125,0.53125 0.28125,0 0.515625,-0.234375 0.515625,-0.53125 z m 0,0"
+ id="path103" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-0">
+ <path
+ style="stroke:none"
+ d=""
+ id="path106" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-1">
+ <path
+ style="stroke:none"
+ d="m 7.640625,-2.265625 c 0,-0.203125 -0.078125,-0.203125 -0.25,-0.203125 -0.125,0 -0.21875,0 -0.21875,0.171875 -0.078125,1.328125 -1.28125,1.9375 -2.28125,1.9375 -0.78125,0 -1.625,-0.234375 -2.140625,-0.84375 -0.46875,-0.578125 -0.59375,-1.3125 -0.59375,-2.21875 0,-0.5625 0.03125,-1.625 0.671875,-2.296875 0.640625,-0.65625 1.515625,-0.765625 2.03125,-0.765625 1.078125,0 2.015625,0.765625 2.234375,2.03125 C 7.125,-4.265625 7.140625,-4.25 7.359375,-4.25 c 0.265625,0 0.28125,-0.015625 0.28125,-0.28125 v -2.140625 c 0,-0.1875 0,-0.28125 -0.1875,-0.28125 -0.09375,0 -0.109375,0.03125 -0.1875,0.09375 l -0.65625,0.59375 c -0.625,-0.5 -1.28125,-0.6875 -1.96875,-0.6875 -2.484375,0 -4,1.484375 -4,3.53125 0,2.046875 1.515625,3.53125 4,3.53125 1.875,0 3,-1.21875 3,-2.375 z m 0,0"
+ id="path109" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-2">
+ <path
+ style="stroke:none"
+ d="m 5.40625,-2.171875 c 0,-1.34375 -0.921875,-2.34375 -2.546875,-2.34375 -1.640625,0 -2.546875,1.015625 -2.546875,2.34375 0,1.234375 0.890625,2.234375 2.546875,2.234375 1.671875,0 2.546875,-1.015625 2.546875,-2.234375 z M 4.125,-2.28125 c 0,0.859375 0,1.9375 -1.265625,1.9375 -1.265625,0 -1.265625,-1.078125 -1.265625,-1.9375 0,-0.453125 0,-0.953125 0.171875,-1.296875 0.1875,-0.375 0.609375,-0.578125 1.09375,-0.578125 0.421875,0 0.84375,0.15625 1.0625,0.5 C 4.125,-3.3125 4.125,-2.765625 4.125,-2.28125 Z m 0,0"
+ id="path112" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-3">
+ <path
+ style="stroke:none"
+ d="m 9.328125,0 v -0.46875 h -0.6875 v -2.578125 c 0,-1.03125 -0.515625,-1.4375 -1.546875,-1.4375 -0.90625,0 -1.421875,0.5 -1.6875,0.953125 -0.1875,-0.921875 -1.109375,-0.953125 -1.484375,-0.953125 -0.875,0 -1.4375,0.453125 -1.765625,1.078125 V -4.484375 L 0.453125,-4.40625 v 0.46875 c 0.609375,0 0.6875,0 0.6875,0.390625 v 3.078125 h -0.6875 V 0 l 1.25,-0.03125 1.25,0.03125 v -0.46875 h -0.6875 v -2.078125 c 0,-1.09375 0.875,-1.578125 1.5,-1.578125 0.328125,0 0.546875,0.203125 0.546875,0.96875 v 2.6875 H 3.625 V 0 L 4.890625,-0.03125 6.140625,0 v -0.46875 h -0.6875 V -2.546875 C 5.453125,-3.640625 6.3125,-4.125 6.9375,-4.125 7.28125,-4.125 7.5,-3.921875 7.5,-3.15625 v 2.6875 H 6.8125 V 0 l 1.25,-0.03125 z m 0,0"
+ id="path115" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-4">
+ <path
+ style="stroke:none"
+ d="m 5.984375,-2.21875 c 0,-1.328125 -0.90625,-2.265625 -2.34375,-2.265625 -0.75,0 -1.28125,0.3125 -1.5,0.484375 V -4.484375 L 0.375,-4.40625 v 0.46875 c 0.609375,0 0.6875,0 0.6875,0.375 V 1.46875 H 0.375 V 1.9375 L 1.625,1.90625 2.875,1.9375 V 1.46875 H 2.1875 v -1.859375 c 0.4375,0.34375 0.875,0.453125 1.28125,0.453125 1.5,0 2.515625,-0.90625 2.515625,-2.28125 z m -1.28125,0 c 0,1.40625 -0.703125,1.921875 -1.34375,1.921875 -0.140625,0 -0.609375,0 -1.0625,-0.546875 C 2.1875,-0.96875 2.1875,-0.984375 2.1875,-1.171875 V -3.28125 c 0,-0.1875 0.015625,-0.203125 0.15625,-0.34375 0.390625,-0.40625 0.921875,-0.46875 1.140625,-0.46875 0.65625,0 1.21875,0.609375 1.21875,1.875 z m 0,0"
+ id="path118" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-5">
+ <path
+ style="stroke:none"
+ d="m 4.921875,-1.171875 c 0,-0.171875 -0.1875,-0.171875 -0.234375,-0.171875 -0.171875,0 -0.1875,0.046875 -0.25,0.203125 -0.203125,0.484375 -0.78125,0.796875 -1.421875,0.796875 -1.40625,0 -1.421875,-1.328125 -1.421875,-1.828125 h 3.015625 c 0.21875,0 0.3125,0 0.3125,-0.265625 0,-0.3125 -0.0625,-1.046875 -0.5625,-1.546875 C 4,-4.34375 3.46875,-4.515625 2.78125,-4.515625 c -1.59375,0 -2.46875,1.03125 -2.46875,2.265625 0,1.34375 1,2.3125 2.609375,2.3125 1.578125,0 2,-1.0625 2,-1.234375 z M 3.984375,-2.5 H 1.59375 C 1.609375,-2.890625 1.625,-3.3125 1.828125,-3.640625 2.09375,-4.03125 2.5,-4.15625 2.78125,-4.15625 c 1.171875,0 1.1875,1.3125 1.203125,1.65625 z m 0,0"
+ id="path121" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-6">
+ <path
+ style="stroke:none"
+ d="m 4.40625,-3.671875 c 0,-0.53125 -0.53125,-0.8125 -1.0625,-0.8125 -0.6875,0 -1.09375,0.5 -1.3125,1.125 v -1.125 L 0.375,-4.40625 v 0.46875 c 0.609375,0 0.6875,0 0.6875,0.390625 V -0.46875 H 0.375 V 0 l 1.25,-0.03125 C 2,-0.03125 2.640625,-0.03125 3,0 V -0.46875 H 2.140625 v -1.75 c 0,-0.6875 0.234375,-1.90625 1.234375,-1.90625 0,0 -0.1875,0.171875 -0.1875,0.453125 0,0.40625 0.328125,0.609375 0.609375,0.609375 0.296875,0 0.609375,-0.203125 0.609375,-0.609375 z m 0,0"
+ id="path124" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-7">
+ <path
+ style="stroke:none"
+ d="m 3.8125,-1.234375 v -0.53125 H 3.34375 V -1.25 c 0,0.671875 -0.328125,0.90625 -0.609375,0.90625 -0.578125,0 -0.578125,-0.640625 -0.578125,-0.859375 v -2.75 H 3.625 v -0.46875 H 2.15625 v -1.90625 H 1.6875 c 0,1 -0.484375,1.984375 -1.484375,2.015625 v 0.359375 H 1.03125 v 2.734375 c 0,1.0625 0.859375,1.28125 1.578125,1.28125 0.75,0 1.203125,-0.578125 1.203125,-1.296875 z m 0,0"
+ id="path127" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-8">
+ <path
+ style="stroke:none"
+ d="m 8.390625,-6.375 v -0.46875 l -1.125,0.03125 c -0.390625,0 -0.921875,0 -1.296875,-0.03125 V -6.375 c 0.078125,0 0.875,0 0.875,0.125 0,0.046875 -0.03125,0.09375 -0.046875,0.125 L 4.78125,-1.59375 2.65625,-6.375 h 0.9375 v -0.46875 c -0.375,0.03125 -1.328125,0.03125 -1.765625,0.03125 -0.375,0 -1.21875,0 -1.5625,-0.03125 V -6.375 h 0.90625 l 2.75,6.203125 c 0.078125,0.171875 0.125,0.25 0.40625,0.25 0.15625,0 0.28125,0 0.390625,-0.234375 l 2.65625,-6 C 7.4375,-6.28125 7.484375,-6.375 8.203125,-6.375 Z m 0,0"
+ id="path130" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-9">
+ <path
+ style="stroke:none"
+ d="M 2.84375,0 V -0.46875 H 2.234375 V -4.484375 L 0.5,-4.40625 v 0.46875 c 0.59375,0 0.65625,0 0.65625,0.390625 V -0.46875 H 0.46875 V 0 L 1.6875,-0.03125 Z M 2.375,-6.046875 c 0,-0.4375 -0.34375,-0.78125 -0.78125,-0.78125 -0.421875,0 -0.78125,0.34375 -0.78125,0.78125 0,0.421875 0.359375,0.765625 0.78125,0.765625 0.4375,0 0.78125,-0.34375 0.78125,-0.765625 z m 0,0"
+ id="path133" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-10">
+ <path
+ style="stroke:none"
+ d="M 4.765625,-1.171875 C 4.765625,-1.3125 4.625,-1.3125 4.53125,-1.3125 c -0.1875,0 -0.1875,0.03125 -0.25,0.15625 -0.25,0.625 -0.734375,0.8125 -1.234375,0.8125 -1.390625,0 -1.390625,-1.453125 -1.390625,-1.921875 0,-0.5625 0,-1.84375 1.28125,-1.84375 0.359375,0 0.515625,0.015625 0.65625,0.046875 -0.1875,0.171875 -0.203125,0.375 -0.203125,0.46875 0,0.4375 0.34375,0.625 0.609375,0.625 0.3125,0 0.640625,-0.21875 0.640625,-0.625 0,-0.859375 -1.15625,-0.921875 -1.734375,-0.921875 -1.796875,0 -2.53125,1.140625 -2.53125,2.296875 0,1.328125 0.9375,2.28125 2.46875,2.28125 1.625,0 1.921875,-1.15625 1.921875,-1.234375 z m 0,0"
+ id="path136" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-0">
+ <path
+ style="stroke:none"
+ d=""
+ id="path139" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-1">
+ <path
+ style="stroke:none"
+ d="m 6.203125,-0.71875 c 0,-0.046875 0,-0.15625 -0.125,-0.15625 -0.125,0 -0.125,0.09375 -0.125,0.140625 -0.046875,0.5 -0.3125,0.671875 -0.546875,0.671875 -0.421875,0 -0.46875,-0.359375 -0.609375,-1.375 -0.0625,-0.453125 -0.140625,-1 -1.015625,-1.265625 0.625,-0.171875 1.375,-0.625 1.375,-1.3125 0,-0.78125 -1,-1.421875 -2.1875,-1.421875 H 0.359375 v 0.265625 h 0.1875 c 0.609375,0 0.625,0.078125 0.625,0.375 v 4.15625 c 0,0.296875 -0.015625,0.375 -0.625,0.375 h -0.1875 V 0 L 1.515625,-0.03125 2.6875,0 V -0.265625 H 2.515625 c -0.625,0 -0.640625,-0.078125 -0.640625,-0.375 v -1.96875 h 1.015625 c 0.578125,0 0.84375,0.296875 0.90625,0.359375 0.234375,0.25 0.234375,0.40625 0.234375,0.9375 0,0.5 0,0.84375 0.328125,1.140625 0.34375,0.296875 0.78125,0.34375 1.015625,0.34375 0.671875,0 0.828125,-0.65625 0.828125,-0.890625 z m -1.875,-3.296875 c 0,0.890625 -0.625,1.171875 -1.46875,1.171875 H 1.875 v -2.015625 c 0,-0.203125 0.015625,-0.28125 0.203125,-0.3125 0.078125,0 0.328125,0 0.484375,0 0.71875,0 1.765625,0 1.765625,1.15625 z m 0,0"
+ id="path142" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-2">
+ <path
+ style="stroke:none"
+ d="M 6.046875,0 V -0.265625 H 5.90625 c -0.5,0 -0.578125,-0.0625 -0.671875,-0.328125 L 3.375,-5.515625 C 3.328125,-5.625 3.3125,-5.6875 3.171875,-5.6875 3.03125,-5.6875 3,-5.625 2.96875,-5.515625 l -1.78125,4.6875 c -0.078125,0.21875 -0.25,0.5625 -0.90625,0.5625 V 0 c 0.265625,-0.03125 0.6875,-0.03125 0.828125,-0.03125 0.25,0 0.5,0 0.875,0.03125 v -0.265625 c -0.34375,0 -0.546875,-0.171875 -0.546875,-0.390625 0,-0.0625 0,-0.078125 0.03125,-0.171875 l 0.375,-1 h 2.171875 l 0.453125,1.1875 C 4.5,-0.546875 4.5,-0.5 4.5,-0.5 c 0,0.234375 -0.40625,0.234375 -0.640625,0.234375 V 0 L 5,-0.03125 c 0.4375,0 0.59375,0 1.046875,0.03125 z M 3.90625,-2.09375 H 1.9375 l 1,-2.59375 z m 0,0"
+ id="path145" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-3">
+ <path
+ style="stroke:none"
+ d="M 7.359375,0 V -0.265625 H 7.1875 c -0.625,0 -0.640625,-0.078125 -0.640625,-0.375 v -4.15625 c 0,-0.296875 0.015625,-0.375 0.640625,-0.375 H 7.359375 V -5.4375 h -1.34375 c -0.21875,0 -0.234375,0.015625 -0.296875,0.15625 L 3.875,-0.75 2.03125,-5.265625 C 1.953125,-5.421875 1.953125,-5.4375 1.734375,-5.4375 h -1.34375 v 0.265625 H 0.5625 c 0.609375,0 0.625,0.078125 0.625,0.375 v 3.9375 c 0,0.21875 0,0.59375 -0.796875,0.59375 V 0 C 0.75,-0.03125 1.125,-0.03125 1.328125,-0.03125 c 0.203125,0 0.578125,0 0.9375,0.03125 v -0.265625 c -0.796875,0 -0.796875,-0.375 -0.796875,-0.59375 V -5.09375 L 3.484375,-0.1875 C 3.53125,-0.09375 3.5625,0 3.671875,0 3.78125,0 3.8125,-0.09375 3.859375,-0.1875 l 2.03125,-4.96875 v 4.515625 c 0,0.296875 -0.015625,0.375 -0.625,0.375 H 5.09375 V 0 l 1.125,-0.03125 z m 0,0"
+ id="path148" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-4">
+ <path
+ style="stroke:none"
+ d="m 2.078125,0 v -0.265625 c -0.53125,0 -0.5625,-0.03125 -0.5625,-0.34375 v -2.90625 l -1.15625,0.09375 v 0.265625 c 0.515625,0 0.578125,0.046875 0.578125,0.4375 V -0.625 c 0,0.359375 -0.09375,0.359375 -0.609375,0.359375 V 0 c 0.3125,-0.03125 0.765625,-0.03125 0.890625,-0.03125 0.09375,0 0.578125,0 0.859375,0.03125 z M 1.625,-4.796875 C 1.625,-5.0625 1.40625,-5.25 1.171875,-5.25 c -0.21875,0 -0.4375,0.1875 -0.4375,0.453125 0,0.234375 0.1875,0.4375 0.4375,0.4375 0.25,0 0.453125,-0.203125 0.453125,-0.4375 z m 0,0"
+ id="path151" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-5">
+ <path
+ style="stroke:none"
+ d="m 4.484375,0 v -0.265625 c -0.515625,0 -0.609375,0 -0.609375,-0.359375 v -1.796875 c 0,-0.65625 -0.3125,-1.09375 -1.140625,-1.09375 -0.796875,0 -1.15625,0.578125 -1.25,0.765625 v -0.765625 l -1.15625,0.09375 v 0.265625 c 0.546875,0 0.609375,0.046875 0.609375,0.4375 V -0.625 c 0,0.359375 -0.09375,0.359375 -0.609375,0.359375 V 0 c 0.34375,-0.03125 0.6875,-0.03125 0.90625,-0.03125 0.234375,0 0.5625,0 0.90625,0.03125 v -0.265625 c -0.5,0 -0.609375,0 -0.609375,-0.359375 v -1.4375 c 0,-0.84375 0.640625,-1.234375 1.125,-1.234375 0.484375,0 0.609375,0.34375 0.609375,0.84375 V -0.625 c 0,0.359375 -0.09375,0.359375 -0.609375,0.359375 V 0 C 3,-0.03125 3.359375,-0.03125 3.5625,-0.03125 c 0.234375,0 0.578125,0 0.921875,0.03125 z m 0,0"
+ id="path154" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-6">
+ <path
+ style="stroke:none"
+ d="m 3.046875,-1.03125 c 0,-0.375 -0.21875,-0.9375 -1.171875,-1.109375 -0.0625,-0.015625 -0.515625,-0.09375 -0.546875,-0.09375 -0.25,-0.0625 -0.625,-0.234375 -0.625,-0.546875 0,-0.234375 0.1875,-0.578125 0.9375,-0.578125 0.890625,0 0.9375,0.65625 0.953125,0.875 0,0.0625 0.0625,0.09375 0.109375,0.09375 0.140625,0 0.140625,-0.0625 0.140625,-0.203125 v -0.75 c 0,-0.125 0,-0.203125 -0.109375,-0.203125 -0.046875,0 -0.0625,0 -0.1875,0.125 -0.015625,0 -0.09375,0.078125 -0.109375,0.078125 0,0 -0.03125,0 -0.078125,-0.03125 C 2.234375,-3.46875 2,-3.546875 1.640625,-3.546875 c -1.109375,0 -1.359375,0.59375 -1.359375,0.984375 0,0.390625 0.296875,0.625 0.3125,0.65625 0.328125,0.234375 0.5,0.265625 1.046875,0.359375 0.375,0.078125 0.984375,0.1875 0.984375,0.71875 0,0.3125 -0.203125,0.6875 -0.9375,0.6875 -0.8125,0 -1.046875,-0.625 -1.140625,-1.046875 C 0.515625,-1.296875 0.5,-1.328125 0.40625,-1.328125 c -0.125,0 -0.125,0.0625 -0.125,0.21875 V -0.125 c 0,0.125 0,0.203125 0.09375,0.203125 0.0625,0 0.0625,0 0.203125,-0.15625 C 0.625,-0.125 0.703125,-0.21875 0.75,-0.265625 1.109375,0.0625 1.484375,0.078125 1.6875,0.078125 2.703125,0.078125 3.046875,-0.5 3.046875,-1.03125 Z m 0,0"
+ id="path157" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-7">
+ <path
+ style="stroke:none"
+ d="m 3.515625,-0.953125 c 0,-0.03125 -0.03125,-0.109375 -0.125,-0.109375 -0.09375,0 -0.109375,0.046875 -0.125,0.09375 -0.28125,0.78125 -0.96875,0.796875 -1.109375,0.796875 -0.359375,0 -0.734375,-0.15625 -0.96875,-0.53125 C 0.953125,-1.0625 0.953125,-1.578125 0.953125,-1.8125 h 2.34375 c 0.171875,0 0.21875,0 0.21875,-0.1875 C 3.515625,-2.703125 3.125,-3.546875 2,-3.546875 c -0.984375,0 -1.765625,0.8125 -1.765625,1.796875 0,1.03125 0.859375,1.828125 1.875,1.828125 1,0 1.40625,-0.84375 1.40625,-1.03125 z M 2.96875,-2.03125 H 0.953125 C 1.03125,-3.140625 1.703125,-3.328125 2,-3.328125 c 0.9375,0 0.96875,1.125 0.96875,1.296875 z m 0,0"
+ id="path160" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-8">
+ <path
+ style="stroke:none"
+ d="m 3.0625,-3.015625 c 0,-0.28125 -0.25,-0.5 -0.609375,-0.5 -0.515625,0 -0.875,0.390625 -1.03125,0.84375 H 1.40625 v -0.84375 l -1.125,0.09375 v 0.265625 c 0.546875,0 0.609375,0.046875 0.609375,0.4375 V -0.625 c 0,0.359375 -0.109375,0.359375 -0.609375,0.359375 V 0 c 0.3125,-0.03125 0.75,-0.03125 0.9375,-0.03125 0.46875,0 0.484375,0 1,0.03125 V -0.265625 H 2.0625 c -0.578125,0 -0.59375,-0.078125 -0.59375,-0.375 V -1.8125 c 0,-0.609375 0.25,-1.46875 1.015625,-1.484375 -0.046875,0.03125 -0.140625,0.09375 -0.140625,0.28125 0,0.25 0.203125,0.359375 0.359375,0.359375 0.1875,0 0.359375,-0.125 0.359375,-0.359375 z m 0,0"
+ id="path163" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-9">
+ <path
+ style="stroke:none"
+ d="m 2.8125,-1 v -0.4375 h -0.25 v 0.421875 c 0,0.546875 -0.25,0.84375 -0.546875,0.84375 -0.53125,0 -0.53125,-0.6875 -0.53125,-0.8125 v -2.1875 h 1.1875 V -3.4375 h -1.1875 v -1.46875 h -0.25 c 0,0.734375 -0.328125,1.484375 -1.078125,1.515625 v 0.21875 H 0.875 V -1 c 0,0.9375 0.71875,1.078125 1.078125,1.078125 C 2.5,0.078125 2.8125,-0.390625 2.8125,-1 Z m 0,0"
+ id="path166" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-10">
+ <path
+ style="stroke:none"
+ d="m 3.984375,-1.703125 c 0,-0.984375 -0.828125,-1.84375 -1.875,-1.84375 -1.046875,0 -1.875,0.859375 -1.875,1.84375 0,1 0.859375,1.78125 1.875,1.78125 1.03125,0 1.875,-0.78125 1.875,-1.78125 z m -0.703125,-0.0625 c 0,0.359375 -0.015625,0.796875 -0.25,1.140625 -0.203125,0.3125 -0.5625,0.453125 -0.921875,0.453125 -0.421875,0 -0.765625,-0.203125 -0.9375,-0.484375 -0.203125,-0.328125 -0.21875,-0.71875 -0.21875,-1.109375 0,-0.3125 0,-0.78125 0.234375,-1.125 0.21875,-0.28125 0.546875,-0.4375 0.921875,-0.4375 0.421875,0 0.765625,0.203125 0.9375,0.46875 0.21875,0.34375 0.234375,0.765625 0.234375,1.09375 z m 0,0"
+ id="path169" />
+ </symbol>
+ </g>
+ <clipPath
+ id="clip1">
+ <path
+ d="M 6,0 H 315.60937 V 71 H 6 Z m 0,0"
+ id="path174" />
+ </clipPath>
+ <clipPath
+ id="clip2">
+ <path
+ d="m 6,85 h 309.60937 v 39.71875 H 6 Z m 0,0"
+ id="path177" />
+ </clipPath>
+ <clipPath
+ id="clip3">
+ <path
+ d="m 133,87 h 47 v 37.71875 h -47 z m 0,0"
+ id="path180" />
+ </clipPath>
+ </defs>
+ <g
+ id="surface10254"
+ transform="translate(-6.636719)">
+ <g
+ clip-path="url(#clip1)"
+ clip-rule="nonzero"
+ id="g187">
+ <path
+ style="fill:#bdb8d9;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="M 6.636719,67.875 V 2.984375 c 0,-1.652344 1.335937,-2.98828125 2.988281,-2.98828125 h 303 c 1.65234,0 2.98828,1.33593725 2.98828,2.98828125 V 67.875 c 0,1.648438 -1.33594,2.988281 -2.98828,2.988281 h -303 c -1.652344,0 -2.988281,-1.339843 -2.988281,-2.988281 z m 0,0"
+ id="path185" />
+ </g>
+ <g
+ clip-path="url(#clip2)"
+ clip-rule="nonzero"
+ id="g191">
+ <path
+ style="fill:#8cd1c5;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 6.636719,88.023438 v 33.707032 c 0,1.65234 1.335937,2.99219 2.988281,2.99219 h 303 c 1.65234,0 2.98828,-1.33985 2.98828,-2.99219 V 88.023438 c 0,-1.648438 -1.33594,-2.988282 -2.98828,-2.988282 h -303 c -1.652344,0 -2.988281,1.339844 -2.988281,2.988282 z m 0,0"
+ id="path189" />
+ </g>
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="M 40.234375,46.769531 H 12.722656 c -1.652344,0 -2.988281,1.335938 -2.988281,2.988281 v 13.863282 c 0,1.652344 1.335937,2.988281 2.988281,2.988281 h 27.511719 c 1.652344,0 2.988281,-1.335937 2.988281,-2.988281 V 49.757812 c 0,-1.652343 -1.335937,-2.988281 -2.988281,-2.988281 z m 0,0"
+ id="path193" />
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g205">
+ <use
+ xlink:href="#glyph0-1"
+ x="13.053"
+ y="59.174999"
+ id="use195"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-2"
+ x="20.245996"
+ y="59.174999"
+ id="use197"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-3"
+ x="23.0156"
+ y="59.174999"
+ id="use199"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-4"
+ x="25.785204"
+ y="59.174999"
+ id="use201"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-5"
+ x="30.766502"
+ y="59.174999"
+ id="use203"
+ width="100%"
+ height="100%" />
+ </g>
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g209">
+ <use
+ xlink:href="#glyph0-6"
+ x="36.026756"
+ y="59.174999"
+ id="use207"
+ width="100%"
+ height="100%" />
+ </g>
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g213">
+ <use
+ xlink:href="#glyph1-1"
+ x="57.516998"
+ y="58.903"
+ id="use211"
+ width="100%"
+ height="100%" />
+ </g>
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g217">
+ <use
+ xlink:href="#glyph1-1"
+ x="61.930431"
+ y="58.903"
+ id="use215"
+ width="100%"
+ height="100%" />
+ </g>
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g221">
+ <use
+ xlink:href="#glyph1-1"
+ x="66.353828"
+ y="58.903"
+ id="use219"
+ width="100%"
+ height="100%" />
+ </g>
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="M 134.55859,46.769531 H 88.476562 c -1.652343,0 -2.988281,1.335938 -2.988281,2.988281 v 13.863282 c 0,1.652344 1.335938,2.988281 2.988281,2.988281 h 46.082028 c 1.65235,0 2.99219,-1.335937 2.99219,-2.988281 V 49.757812 c 0,-1.652343 -1.33984,-2.988281 -2.99219,-2.988281 z m 0,0"
+ id="path223" />
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g243">
+ <use
+ xlink:href="#glyph0-1"
+ x="88.807999"
+ y="60.091"
+ id="use225"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-7"
+ x="96.000999"
+ y="60.091"
+ id="use227"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-3"
+ x="104.29984"
+ y="60.091"
+ id="use229"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-8"
+ x="107.06944"
+ y="60.091"
+ id="use231"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-9"
+ x="112.60865"
+ y="60.091"
+ id="use233"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-10"
+ x="117.58995"
+ y="60.091"
+ id="use235"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-11"
+ x="121.49529"
+ y="60.091"
+ id="use237"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-12"
+ x="127.03449"
+ y="60.091"
+ id="use239"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-2"
+ x="131.45789"
+ y="60.091"
+ id="use241"
+ width="100%"
+ height="100%" />
+ </g>
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 178.22656,46.769531 h -20.03125 c -1.64844,0 -2.98828,1.335938 -2.98828,2.988281 v 13.863282 c 0,1.652344 1.33984,2.988281 2.98828,2.988281 h 20.03125 c 1.65235,0 2.98828,-1.335937 2.98828,-2.988281 V 49.757812 c 0,-1.652343 -1.33593,-2.988281 -2.98828,-2.988281 z m 0,0"
+ id="path245" />
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g251">
+ <use
+ xlink:href="#glyph0-13"
+ x="158.528"
+ y="60.146"
+ id="use247"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-14"
+ x="163.50929"
+ y="60.146"
+ id="use249"
+ width="100%"
+ height="100%" />
+ </g>
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g255">
+ <use
+ xlink:href="#glyph0-1"
+ x="170.7023"
+ y="60.146"
+ id="use253"
+ width="100%"
+ height="100%" />
+ </g>
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 220.47266,46.769531 h -19.48047 c -1.65235,0 -2.99219,1.335938 -2.99219,2.988281 v 13.863282 c 0,1.652344 1.33984,2.988281 2.99219,2.988281 h 19.48047 c 1.65234,0 2.98828,-1.335937 2.98828,-2.988281 V 49.757812 c 0,-1.652343 -1.33594,-2.988281 -2.98828,-2.988281 z m 0,0"
+ id="path257" />
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g261">
+ <use
+ xlink:href="#glyph0-15"
+ x="201.32201"
+ y="60.091"
+ id="use259"
+ width="100%"
+ height="100%" />
+ </g>
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g267">
+ <use
+ xlink:href="#glyph0-16"
+ x="206.72173"
+ y="60.091"
+ id="use263"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-15"
+ x="213.91472"
+ y="60.091"
+ id="use265"
+ width="100%"
+ height="100%" />
+ </g>
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 310.46094,46.769531 h -34.17969 c -1.64844,0 -2.98828,1.335938 -2.98828,2.988281 v 13.863282 c 0,1.652344 1.33984,2.988281 2.98828,2.988281 h 34.17969 c 1.65234,0 2.98828,-1.335937 2.98828,-2.988281 V 49.757812 c 0,-1.652343 -1.33594,-2.988281 -2.98828,-2.988281 z m 0,0"
+ id="path269" />
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g279">
+ <use
+ xlink:href="#glyph0-17"
+ x="276.61499"
+ y="60.036999"
+ id="use271"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-17"
+ x="281.59631"
+ y="60.036999"
+ id="use273"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-10"
+ x="286.57761"
+ y="60.036999"
+ id="use275"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-18"
+ x="290.48294"
+ y="60.036999"
+ id="use277"
+ width="100%"
+ height="100%" />
+ </g>
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g287">
+ <use
+ xlink:href="#glyph0-5"
+ x="294.62738"
+ y="60.036999"
+ id="use281"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-19"
+ x="300.1666"
+ y="60.036999"
+ id="use283"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-20"
+ x="305.14789"
+ y="60.036999"
+ id="use285"
+ width="100%"
+ height="100%" />
+ </g>
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 292.16797,24.089844 h -15.88672 c -1.64844,0 -2.98828,1.339844 -2.98828,2.988281 v 13.867187 c 0,1.648438 1.33984,2.988282 2.98828,2.988282 h 15.88672 c 1.65234,0 2.99219,-1.339844 2.99219,-2.988282 V 27.078125 c 0,-1.648437 -1.33985,-2.988281 -2.99219,-2.988281 z m 0,0"
+ id="path289" />
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g297">
+ <use
+ xlink:href="#glyph0-21"
+ x="276.61499"
+ y="37.220001"
+ id="use291"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-22"
+ x="281.87524"
+ y="37.220001"
+ id="use293"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-19"
+ x="286.85657"
+ y="37.220001"
+ id="use295"
+ width="100%"
+ height="100%" />
+ </g>
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g301">
+ <use
+ xlink:href="#glyph1-1"
+ x="276.61499"
+ y="19.218"
+ id="use299"
+ width="100%"
+ height="100%" />
+ </g>
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g305">
+ <use
+ xlink:href="#glyph1-1"
+ x="281.02844"
+ y="19.218"
+ id="use303"
+ width="100%"
+ height="100%" />
+ </g>
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g309">
+ <use
+ xlink:href="#glyph1-1"
+ x="285.45181"
+ y="19.218"
+ id="use307"
+ width="100%"
+ height="100%" />
+ </g>
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g313">
+ <use
+ xlink:href="#glyph1-1"
+ x="236.10201"
+ y="58.903"
+ id="use311"
+ width="100%"
+ height="100%" />
+ </g>
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g317">
+ <use
+ xlink:href="#glyph1-1"
+ x="240.51543"
+ y="58.903"
+ id="use315"
+ width="100%"
+ height="100%" />
+ </g>
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g321">
+ <use
+ xlink:href="#glyph1-1"
+ x="244.93883"
+ y="58.903"
+ id="use319"
+ width="100%"
+ height="100%" />
+ </g>
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 178.98828,89.289062 h -21.55469 c -1.64843,0 -2.98828,1.335938 -2.98828,2.988282 v 13.863286 c 0,1.65234 1.33985,2.98828 2.98828,2.98828 h 21.55469 c 1.65234,0 2.98828,-1.33594 2.98828,-2.98828 V 92.277344 c 0,-1.652344 -1.33594,-2.988282 -2.98828,-2.988282 z m 0,0"
+ id="path323" />
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g331">
+ <use
+ xlink:href="#glyph0-23"
+ x="157.76601"
+ y="102.611"
+ id="use325"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-16"
+ x="165.23795"
+ y="102.611"
+ id="use327"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-15"
+ x="172.43095"
+ y="102.611"
+ id="use329"
+ width="100%"
+ height="100%" />
+ </g>
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 240.47656,89.289062 h -31.14062 c -1.65235,0 -2.98828,1.335938 -2.98828,2.988282 v 13.863286 c 0,1.65234 1.33593,2.98828 2.98828,2.98828 h 31.14062 c 1.64844,0 2.98828,-1.33594 2.98828,-2.98828 V 92.277344 c 0,-1.652344 -1.33984,-2.988282 -2.98828,-2.988282 z m 0,0"
+ id="path333" />
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g337">
+ <use
+ xlink:href="#glyph0-24"
+ x="209.66701"
+ y="101.64"
+ id="use335"
+ width="100%"
+ height="100%" />
+ </g>
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g351">
+ <use
+ xlink:href="#glyph0-12"
+ x="216.31206"
+ y="101.64"
+ id="use339"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-10"
+ x="220.73544"
+ y="101.64"
+ id="use341"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-3"
+ x="224.64079"
+ y="101.64"
+ id="use343"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-2"
+ x="227.41039"
+ y="101.64"
+ id="use345"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-9"
+ x="230.17999"
+ y="101.64"
+ id="use347"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph0-4"
+ x="235.16129"
+ y="101.64"
+ id="use349"
+ width="100%"
+ height="100%" />
+ </g>
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g369">
+ <use
+ xlink:href="#glyph2-1"
+ x="12.99"
+ y="13.84"
+ id="use353"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph2-2"
+ x="21.268921"
+ y="13.84"
+ id="use355"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph2-3"
+ x="26.997416"
+ y="13.84"
+ id="use357"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph2-4"
+ x="36.541588"
+ y="13.84"
+ id="use359"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph2-1"
+ x="42.907688"
+ y="13.84"
+ id="use361"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph2-5"
+ x="51.186607"
+ y="13.84"
+ id="use363"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph2-6"
+ x="56.436897"
+ y="13.84"
+ id="use365"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph2-7"
+ x="61.159172"
+ y="13.84"
+ id="use367"
+ width="100%"
+ height="100%" />
+ </g>
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g373">
+ <use
+ xlink:href="#glyph2-8"
+ x="12.99"
+ y="99.751999"
+ id="use371"
+ width="100%"
+ height="100%" />
+ </g>
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g389">
+ <use
+ xlink:href="#glyph2-5"
+ x="20.69109"
+ y="99.751999"
+ id="use375"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph2-6"
+ x="25.94138"
+ y="99.751999"
+ id="use377"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph2-9"
+ x="30.663652"
+ y="99.751999"
+ id="use379"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph2-10"
+ x="33.841721"
+ y="99.751999"
+ id="use381"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph2-5"
+ x="38.93261"
+ y="99.751999"
+ id="use383"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph2-6"
+ x="44.182899"
+ y="99.751999"
+ id="use385"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph2-7"
+ x="48.905174"
+ y="99.751999"
+ id="use387"
+ width="100%"
+ height="100%" />
+ </g>
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g397">
+ <use
+ xlink:href="#glyph3-1"
+ x="115.526"
+ y="112.701"
+ id="use391"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph3-2"
+ x="121.75862"
+ y="112.701"
+ id="use393"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph3-3"
+ x="128.10281"
+ y="112.701"
+ id="use395"
+ width="100%"
+ height="100%" />
+ </g>
+ <g
+ style="fill:#000000;fill-opacity:1"
+ id="g417">
+ <use
+ xlink:href="#glyph3-4"
+ x="109.676"
+ y="119.675"
+ id="use399"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph3-5"
+ x="112.02718"
+ y="119.675"
+ id="use401"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph3-6"
+ x="116.72954"
+ y="119.675"
+ id="use403"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph3-7"
+ x="120.06901"
+ y="119.675"
+ id="use405"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph3-8"
+ x="123.83089"
+ y="119.675"
+ id="use407"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph3-9"
+ x="127.13052"
+ y="119.675"
+ id="use409"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph3-4"
+ x="130.42216"
+ y="119.675"
+ id="use411"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph3-10"
+ x="132.77335"
+ y="119.675"
+ id="use413"
+ width="100%"
+ height="100%" />
+ <use
+ xlink:href="#glyph3-5"
+ x="137.00548"
+ y="119.675"
+ id="use415"
+ width="100%"
+ height="100%" />
+ </g>
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1"
+ d="m 8.439875,0.0015 h 9.777344"
+ transform="matrix(1,0,0,-1,34.982,56.689)"
+ id="path419" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.79701;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1"
+ d="M -2.552025,3.110875 C -2.083275,1.243687 -1.044213,0.364781 -0.00124375,0.0015 -1.044213,-0.361781 -2.083275,-1.244594 -2.552025,-3.111781"
+ transform="matrix(1,0,0,-1,53.5989,56.689)"
+ id="path421" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1"
+ d="M 37.678156,0.0015 H 49.510188"
+ transform="matrix(1,0,0,-1,34.982,56.689)"
+ id="path423" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.79701;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1"
+ d="M -2.549976,3.110875 C -2.085132,1.243687 -1.04607,0.364781 8.05e-4,0.0015 -1.04607,-0.361781 -2.085132,-1.244594 -2.549976,-3.111781"
+ transform="matrix(1,0,0,-1,84.88982,56.689)"
+ id="path425" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1"
+ d="m 102.768,0.0015 h 16.46094"
+ transform="matrix(1,0,0,-1,34.982,56.689)"
+ id="path427" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.79701;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1"
+ d="M -2.551166,3.110875 C -2.086322,1.243687 -1.04726,0.364781 -3.85e-4,0.0015 -1.04726,-0.361781 -2.086322,-1.244594 -2.551166,-3.111781"
+ transform="matrix(1,0,0,-1,154.60976,56.689)"
+ id="path429" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1"
+ d="m 146.43206,0.0015 h 15.58985"
+ transform="matrix(1,0,0,-1,34.982,56.689)"
+ id="path431" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.79701;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1"
+ d="M -2.552408,3.110875 C -2.083658,1.243687 -1.044595,0.364781 -0.00162625,0.0015 -1.044595,-0.361781 -2.083658,-1.244594 -2.552408,-3.111781"
+ transform="matrix(1,0,0,-1,197.40397,56.689)"
+ id="path433" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1"
+ d="m 188.67816,0.0015 h 8.125"
+ transform="matrix(1,0,0,-1,34.982,56.689)"
+ id="path435" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.79701;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1"
+ d="M -2.551057,3.110875 C -2.086214,1.243687 -1.047151,0.364781 -2.7625e-4,0.0015 -1.047151,-0.361781 -2.086214,-1.244594 -2.551057,-3.111781"
+ transform="matrix(1,0,0,-1,232.18387,56.689)"
+ id="path437" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1"
+ d="m 216.26409,0.0015 h 21.05078"
+ transform="matrix(1,0,0,-1,34.982,56.689)"
+ id="path439" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.79701;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1"
+ d="M -2.551979,3.110875 C -2.083229,1.243687 -1.048072,0.364781 -0.0011975,0.0015 -1.048072,-0.361781 -2.083229,-1.244594 -2.551979,-3.111781"
+ transform="matrix(1,0,0,-1,272.69651,56.689)"
+ id="path441" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1"
+ d="m 216.26409,0.0015 c 12.28516,0 10.30469,18.472656 21.10157,22.402344"
+ transform="matrix(1,0,0,-1,34.982,56.689)"
+ id="path443" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.79701;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1"
+ d="M -2.549132,3.109508 C -2.084774,1.244442 -1.046101,0.363405 -0.00193857,-4.77835e-6 -1.044977,-0.364479 -2.084828,-1.245581 -2.550933,-3.108709"
+ transform="matrix(0.93968,-0.34201,-0.34201,-0.93968,272.72057,34.14777)"
+ id="path445" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1"
+ d="m 216.26409,0.0015 c 17.67578,0 4.44141,36.613281 21.0625,39.546875"
+ transform="matrix(1,0,0,-1,34.982,56.689)"
+ id="path447" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.79701;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1"
+ d="M -2.549055,3.109583 C -2.084879,1.242801 -1.046318,0.361581 3.08915e-4,-0.00144434 -1.047336,-0.364117 -2.083134,-1.244529 -2.550801,-3.109646"
+ transform="matrix(0.9848,-0.17363,-0.17363,-0.9848,272.70257,17.07285)"
+ id="path449" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1"
+ d="M 133.22894,-10.119594 V -31.603969"
+ transform="matrix(1,0,0,-1,34.982,56.689)"
+ id="path451" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.79701;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1"
+ d="m -2.549445,3.112319 c 0.464844,-1.867188 1.503906,-2.75 2.55078125,-3.1132815 C -1.045539,-0.364244 -2.084601,-1.24315 -2.549445,-3.110337"
+ transform="matrix(0,1,1,0,168.2119,88.69007)"
+ id="path453" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1"
+ d="m 147.19378,-42.521938 h 23.17578"
+ transform="matrix(1,0,0,-1,34.982,56.689)"
+ id="path455" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.79701;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1"
+ d="M -2.549931,3.111544 C -2.085087,1.244356 -1.046025,0.361544 8.5e-4,-0.0017375 -1.046025,-0.361113 -2.085087,-1.243925 -2.549931,-3.111113"
+ transform="matrix(1,0,0,-1,205.74915,99.2092)"
+ id="path457" />
+ <g
+ clip-path="url(#clip3)"
+ clip-rule="nonzero"
+ id="g461">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1"
+ d="m 119.26409,-42.521938 c -8.08593,0 -12.8789,-15.800781 -5.875,-19.839843 7.48438,-4.324219 19.83985,1.074218 19.83985,8.925781"
+ transform="matrix(1,0,0,-1,34.982,56.689)"
+ id="path459" />
+ </g>
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.79701;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1"
+ d="M -2.549004,3.110337 C -2.08416,1.24315 -1.045097,0.364244 0.0017775,9.625e-4 -1.045097,-0.362319 -2.08416,-1.245131 -2.549004,-3.112319"
+ transform="matrix(0,-1,-1,0,168.2119,109.72834)"
+ id="path463" />
+ </g>
+</svg>
diff --git a/doc/_static/images/vericert-main.svg b/doc/_static/images/vericert-main.svg
new file mode 100644
index 0000000..2280ec0
--- /dev/null
+++ b/doc/_static/images/vericert-main.svg
@@ -0,0 +1,500 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:i="&amp;ns_ai;"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.1"
+ id="Vrstva_1"
+ x="0px"
+ y="0px"
+ width="260.46588"
+ height="94.647018"
+ viewBox="0 0 260.46587 94.647017"
+ enable-background="new 0 0 618.822 841.89"
+ xml:space="preserve"><metadata
+ id="metadata231"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+ id="defs229"><clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath235"><rect
+ style="opacity:0.33;fill:#cccccc;stroke-width:1.00152"
+ id="rect237"
+ width="260.46588"
+ height="94.647018"
+ x="82.589996"
+ y="165.938" /></clipPath></defs>
+<switch
+ id="switch224"
+ clip-path="url(#clipPath235)"
+ transform="translate(-82.589996,-165.938)">
+ <foreignObject
+ requiredExtensions="http://ns.adobe.com/AdobeIllustrator/10.0/"
+ x="0"
+ y="0"
+ width="1"
+ height="1">
+
+ </foreignObject>
+ <g
+ i:extraneous="self"
+ id="g222">
+ <path
+ fill="#2a3e40"
+ d="m 138.548,46.104 -2.739,2.042 c -2.752,2.045 -5.755,3.74 -8.914,5.057 v -6.786 h -3.464 v 8.054 c -4.161,1.331 -8.523,2.031 -12.901,2.031 -0.226,0 -0.441,0 -0.667,0 -3.9,-0.065 -7.719,-0.654 -11.382,-1.739 v -8.346 h -3.464 v 7.144 C 91.61,52.217 88.367,50.429 85.36,48.207 l -2.769,-2.051 0.069,27.635 v 0.089 c 0.511,9.326 3.818,18.161 9.562,25.563 4.424,5.698 10.187,10.246 16.722,13.27 v 6.539 h 3.465 v -6.406 c 7.5,-3.683 13.894,-9.261 18.522,-16.229 4.712,-7.079 7.412,-15.313 7.834,-23.806 V 72.762 Z M 128.044,94.7 c -4.301,6.469 -10.24,11.682 -17.22,15.087 C 104.61,107 99.143,102.701 94.96,97.31 89.659,90.488 86.606,82.33 86.124,73.73 L 86.065,52.887 c 7.117,4.507 15.255,6.941 23.738,7.068 8.923,0.148 17.818,-2.385 25.338,-7.147 l 0.157,19.879 c -0.392,7.856 -2.905,15.463 -7.254,22.013 z"
+ id="path10" />
+ <path
+ fill="#9acfb2"
+ d="m 135.142,52.809 0.157,19.879 c -0.393,7.854 -2.906,15.462 -7.254,22.012 -4.301,6.469 -10.24,11.682 -17.22,15.087 C 104.61,107 99.143,102.701 94.96,97.31 89.659,90.488 86.606,82.33 86.124,73.73 L 86.065,52.887 c 7.117,4.507 15.255,6.941 23.738,7.068 8.924,0.149 17.819,-2.384 25.339,-7.146 z"
+ id="path12" />
+ <g
+ id="g30">
+ <path
+ fill="#2a3e40"
+ d="m 97.618,69.497 h 6.16 c 0,0 7.858,23.452 7.928,23.899 0.104,-0.447 31,-35.591 31,-35.591 h 6.108 l -35.546,42.546 h -5.137 z"
+ id="path14" />
+ <path
+ fill="#2a3e40"
+ d="m 146.425,100.029 c -0.948,-0.214 -1.831,-0.589 -2.65,-1.119 -0.819,-0.532 -1.508,-1.199 -2.069,-2.007 -0.56,-0.802 -0.948,-1.678 -1.163,-2.626 -0.216,-0.95 -0.324,-1.911 -0.324,-2.888 v -5.604 c 0,-0.977 0.108,-1.94 0.324,-2.886 0.215,-0.951 0.596,-1.826 1.142,-2.63 0.546,-0.803 1.222,-1.481 2.026,-2.026 0.804,-0.546 1.687,-0.919 2.65,-1.121 0.962,-0.198 1.918,-0.301 2.866,-0.301 0.977,0 1.939,0.103 2.888,0.301 0.948,0.202 1.824,0.575 2.628,1.121 0.804,0.545 1.48,1.223 2.026,2.026 0.545,0.804 0.926,1.679 1.142,2.63 0.215,0.946 0.324,1.91 0.324,2.886 v 4.956 h -13.017 v 0.647 c 0,0.573 0.071,1.148 0.216,1.724 0.143,0.574 0.401,1.098 0.775,1.573 0.373,0.474 0.84,0.819 1.4,1.033 0.561,0.218 1.127,0.324 1.702,0.324 0.574,0 1.143,-0.072 1.704,-0.215 0.56,-0.143 1.048,-0.438 1.464,-0.884 0.417,-0.446 0.64,-0.954 0.668,-1.529 h 4.999 c -0.058,1.034 -0.338,2.024 -0.84,2.973 -0.503,0.947 -1.186,1.731 -2.047,2.349 -0.862,0.619 -1.803,1.042 -2.823,1.271 -1.021,0.229 -2.063,0.343 -3.125,0.343 -0.975,0.001 -1.938,-0.106 -2.886,-0.321 z m 6.809,-14.244 c 0,-0.575 -0.065,-1.148 -0.193,-1.724 -0.13,-0.574 -0.374,-1.1 -0.733,-1.574 -0.359,-0.474 -0.819,-0.819 -1.378,-1.035 -0.561,-0.215 -1.128,-0.322 -1.703,-0.322 -0.575,0 -1.135,0.106 -1.681,0.322 -0.546,0.216 -1,0.561 -1.357,1.035 -0.36,0.474 -0.611,1 -0.754,1.574 -0.145,0.576 -0.216,1.148 -0.216,1.724 v 0.645 h 8.016 v -0.645 z"
+ id="path16" />
+ <path
+ fill="#2a3e40"
+ d="m 162.356,77.178 h 5.042 v 5.074 c 0.172,-0.702 0.41,-1.364 0.712,-1.989 0.301,-0.628 0.674,-1.215 1.12,-1.771 0.445,-0.553 0.991,-0.967 1.637,-1.246 0.647,-0.276 1.329,-0.416 2.047,-0.416 0.661,0 1.314,0.125 1.961,0.372 0.647,0.248 1.185,0.635 1.616,1.158 0.432,0.525 0.762,1.115 0.992,1.771 0.23,0.655 0.388,1.317 0.474,1.989 0.086,0.67 0.128,1.356 0.128,2.054 h -4.998 c 0,-0.467 -0.058,-0.934 -0.173,-1.4 -0.115,-0.465 -0.359,-0.842 -0.732,-1.135 -0.375,-0.291 -0.791,-0.437 -1.25,-0.437 -0.576,0 -1.1,0.174 -1.573,0.523 -0.474,0.35 -0.834,0.787 -1.078,1.312 -0.244,0.526 -0.43,1.066 -0.561,1.618 -0.128,0.553 -0.214,1.115 -0.259,1.684 -0.042,0.567 -0.064,1.142 -0.064,1.725 v 12.286 h -5.042 V 77.178 Z"
+ id="path18" />
+ <path
+ fill="#2a3e40"
+ d="m 182.207,95.911 h 5.344 V 81.26 h -4.74 v -4.44 h 9.74 v 19.091 h 4.741 v 4.44 h -15.085 z m 5.753,-23.025 c -0.591,-0.256 -1.013,-0.68 -1.271,-1.269 -0.258,-0.587 -0.388,-1.185 -0.388,-1.789 0,-0.633 0.13,-1.236 0.388,-1.812 0.258,-0.574 0.68,-0.99 1.271,-1.25 0.587,-0.258 1.185,-0.387 1.789,-0.387 0.631,0 1.235,0.128 1.809,0.387 0.575,0.259 0.993,0.676 1.251,1.25 0.258,0.576 0.387,1.179 0.387,1.812 0,0.604 -0.128,1.201 -0.387,1.789 -0.258,0.589 -0.676,1.013 -1.251,1.269 -0.574,0.261 -1.178,0.39 -1.809,0.39 -0.603,-10e-4 -1.201,-0.13 -1.789,-0.39 z"
+ id="path20" />
+ <path
+ fill="#2a3e40"
+ d="m 206.469,100.029 c -0.935,-0.214 -1.804,-0.596 -2.608,-1.142 -0.804,-0.545 -1.471,-1.22 -2.004,-2.026 -0.531,-0.803 -0.904,-1.679 -1.121,-2.629 -0.215,-0.948 -0.323,-1.896 -0.323,-2.843 v -5.604 c 0,-0.949 0.108,-1.897 0.323,-2.845 0.217,-0.949 0.59,-1.824 1.121,-2.629 0.533,-0.804 1.2,-1.48 2.004,-2.026 0.804,-0.546 1.673,-0.924 2.608,-1.144 0.933,-0.213 1.874,-0.322 2.823,-0.322 1.148,0 2.276,0.152 3.383,0.452 1.107,0.302 2.083,0.836 2.931,1.598 0.847,0.76 1.486,1.679 1.918,2.755 0.432,1.079 0.646,2.179 0.646,3.299 v 0.087 h -4.999 v -0.044 c 0,-0.689 -0.158,-1.352 -0.474,-1.984 -0.316,-0.63 -0.791,-1.097 -1.422,-1.399 -0.633,-0.301 -1.292,-0.452 -1.983,-0.452 -0.546,0 -1.092,0.116 -1.638,0.343 -0.546,0.232 -0.992,0.583 -1.337,1.056 -0.345,0.475 -0.58,0.992 -0.71,1.552 -0.13,0.558 -0.194,1.127 -0.194,1.703 v 5.604 c 0,0.573 0.064,1.142 0.194,1.703 0.13,0.56 0.365,1.077 0.71,1.55 0.345,0.474 0.791,0.827 1.337,1.056 0.546,0.231 1.092,0.345 1.638,0.345 0.69,0 1.35,-0.15 1.983,-0.452 0.631,-0.302 1.106,-0.769 1.422,-1.4 0.315,-0.633 0.474,-1.293 0.474,-1.983 v -0.044 h 4.999 v 0.085 c 0,1.123 -0.214,2.221 -0.646,3.298 -0.432,1.078 -1.071,1.999 -1.918,2.758 -0.847,0.764 -1.824,1.292 -2.931,1.595 -1.106,0.301 -2.235,0.452 -3.383,0.452 -0.949,-0.001 -1.89,-0.108 -2.823,-0.323 z"
+ id="path22" />
+ <path
+ fill="#2a3e40"
+ d="m 228.497,100.029 c -0.948,-0.214 -1.832,-0.589 -2.649,-1.119 -0.82,-0.532 -1.51,-1.199 -2.07,-2.007 -0.561,-0.802 -0.949,-1.678 -1.164,-2.626 -0.217,-0.95 -0.323,-1.911 -0.323,-2.888 v -5.604 c 0,-0.977 0.106,-1.94 0.323,-2.886 0.215,-0.951 0.597,-1.826 1.141,-2.63 0.546,-0.803 1.223,-1.481 2.027,-2.026 0.804,-0.546 1.687,-0.919 2.65,-1.121 0.962,-0.198 1.919,-0.301 2.867,-0.301 0.978,0 1.94,0.103 2.887,0.301 0.95,0.202 1.825,0.575 2.629,1.121 0.803,0.545 1.48,1.223 2.027,2.026 0.545,0.804 0.925,1.679 1.141,2.63 0.215,0.946 0.323,1.91 0.323,2.886 v 4.956 h -13.015 v 0.647 c 0,0.573 0.071,1.148 0.214,1.724 0.145,0.574 0.403,1.098 0.776,1.573 0.372,0.474 0.841,0.819 1.4,1.033 0.561,0.218 1.129,0.324 1.704,0.324 0.573,0 1.142,-0.072 1.701,-0.215 0.561,-0.143 1.049,-0.438 1.465,-0.884 0.416,-0.446 0.64,-0.954 0.668,-1.529 h 5 c -0.059,1.034 -0.338,2.024 -0.84,2.973 -0.504,0.947 -1.187,1.731 -2.049,2.349 -0.862,0.619 -1.803,1.042 -2.823,1.271 -1.021,0.229 -2.063,0.343 -3.124,0.343 -0.975,0.001 -1.939,-0.106 -2.886,-0.321 z m 6.811,-14.244 c 0,-0.575 -0.066,-1.148 -0.194,-1.724 -0.129,-0.574 -0.375,-1.1 -0.734,-1.574 -0.358,-0.474 -0.819,-0.819 -1.378,-1.035 -0.561,-0.215 -1.129,-0.322 -1.703,-0.322 -0.575,0 -1.135,0.106 -1.681,0.322 -0.546,0.216 -0.999,0.561 -1.359,1.035 -0.358,0.474 -0.609,1 -0.754,1.574 -0.143,0.576 -0.214,1.148 -0.214,1.724 v 0.645 h 8.017 z"
+ id="path24" />
+ <path
+ fill="#2a3e40"
+ d="m 244.427,77.077 h 5.043 v 5.096 c 0.17,-0.705 0.408,-1.369 0.71,-1.998 0.302,-0.631 0.675,-1.221 1.121,-1.779 0.444,-0.555 0.99,-0.972 1.638,-1.25 0.645,-0.278 1.328,-0.418 2.046,-0.418 0.66,0 1.314,0.126 1.962,0.374 0.645,0.249 1.184,0.638 1.616,1.163 0.43,0.527 0.76,1.12 0.99,1.779 0.23,0.658 0.389,1.323 0.475,1.998 0.086,0.673 0.128,1.362 0.128,2.063 h -4.998 c 0,-0.469 -0.059,-0.938 -0.174,-1.407 -0.115,-0.467 -0.36,-0.846 -0.732,-1.14 -0.376,-0.292 -0.792,-0.439 -1.251,-0.439 -0.575,0 -1.099,0.175 -1.573,0.525 -0.474,0.351 -0.835,0.791 -1.079,1.318 -0.244,0.528 -0.43,1.07 -0.559,1.625 -0.13,0.555 -0.214,1.12 -0.26,1.691 -0.042,0.569 -0.063,1.147 -0.063,1.733 v 12.339 h -5.043 V 77.077 Z"
+ id="path26" />
+ <path
+ fill="#2a3e40"
+ d="m 273.286,99.938 c -0.891,-0.276 -1.666,-0.748 -2.328,-1.419 -0.661,-0.667 -1.185,-1.425 -1.574,-2.271 -0.387,-0.843 -0.653,-1.724 -0.796,-2.64 -0.146,-0.917 -0.214,-1.841 -0.214,-2.774 v -9.605 h -4.095 v -4.367 h 4.095 v -8.949 h 4.997 v 8.949 h 5.992 v 4.367 h -5.992 v 9.605 c 0,0.525 0.029,1.057 0.087,1.595 0.058,0.54 0.164,1.063 0.324,1.573 0.157,0.509 0.431,0.967 0.818,1.374 0.389,0.407 0.854,0.611 1.401,0.611 0.432,0 0.84,-0.138 1.229,-0.414 0.386,-0.276 0.668,-0.625 0.841,-1.048 0.171,-0.423 0.294,-0.853 0.366,-1.29 0.071,-0.435 0.107,-0.887 0.107,-1.352 v -0.22 h 5.042 v 0.48 c 0,1.048 -0.15,2.089 -0.452,3.123 -0.301,1.035 -0.805,1.966 -1.509,2.793 -0.705,0.832 -1.561,1.42 -2.565,1.77 -1.006,0.347 -2.024,0.522 -3.059,0.522 -0.921,0 -1.824,-0.14 -2.715,-0.413 z"
+ id="path28" />
+ </g>
+ <rect
+ x="411.99899"
+ y="43.333"
+ fill="#2a3e40"
+ width="23.02"
+ height="23.02"
+ id="rect32" />
+ <rect
+ x="411.99899"
+ y="98.114998"
+ fill="#99cfb8"
+ width="23.02"
+ height="23.02"
+ id="rect34" />
+ <text
+ transform="translate(456.6675,49.9995)"
+ id="text50"><tspan
+ x="0"
+ y="0"
+ font-family="MyriadPro-Regular"
+ font-size="12px"
+ id="tspan36">CMYK</tspan><tspan
+ x="29.604"
+ y="0"
+ font-family="MyriadPro-Regular"
+ font-size="12px"
+ letter-spacing="3"
+ id="tspan38"> </tspan><tspan
+ x="36"
+ y="0"
+ font-family="MyriadPro-Regular"
+ font-size="12px"
+ id="tspan40">80 / 58 / 52 / 55</tspan><tspan
+ x="0"
+ y="14.4"
+ font-family="MyriadPro-Regular"
+ font-size="12px"
+ id="tspan42">RGB</tspan><tspan
+ x="20.712"
+ y="14.4"
+ font-family="MyriadPro-Regular"
+ font-size="12px"
+ letter-spacing="12"
+ id="tspan44"> </tspan><tspan
+ x="36"
+ y="14.4"
+ font-family="MyriadPro-Regular"
+ font-size="12px"
+ id="tspan46">44 / 60 / 66</tspan><tspan
+ x="0"
+ y="28.799999"
+ font-family="MyriadPro-Regular"
+ font-size="12px"
+ id="tspan48">#2c3c42</tspan></text>
+ <text
+ transform="translate(456.6675,102.4316)"
+ id="text66"><tspan
+ x="0"
+ y="0"
+ font-family="MyriadPro-Regular"
+ font-size="12px"
+ id="tspan52">CMYK</tspan><tspan
+ x="29.604"
+ y="0"
+ font-family="MyriadPro-Regular"
+ font-size="12px"
+ letter-spacing="3"
+ id="tspan54"> </tspan><tspan
+ x="36"
+ y="0"
+ font-family="MyriadPro-Regular"
+ font-size="12px"
+ id="tspan56">45 / 0 / 38 / 0</tspan><tspan
+ x="0"
+ y="14.4"
+ font-family="MyriadPro-Regular"
+ font-size="12px"
+ id="tspan58">RGB</tspan><tspan
+ x="20.712"
+ y="14.4"
+ font-family="MyriadPro-Regular"
+ font-size="12px"
+ letter-spacing="12"
+ id="tspan60"> </tspan><tspan
+ x="36"
+ y="14.4"
+ font-family="MyriadPro-Regular"
+ font-size="12px"
+ id="tspan62">152 / 217 / 182</tspan><tspan
+ x="0"
+ y="28.799999"
+ font-family="MyriadPro-Regular"
+ font-size="12px"
+ id="tspan64">#98d9b6</tspan></text>
+
+ <line
+ fill="none"
+ stroke="#000000"
+ stroke-width="0.25"
+ stroke-miterlimit="10"
+ x1="110.683"
+ y1="144"
+ x2="110.683"
+ y2="124.668"
+ id="line68" />
+ <polyline
+ fill="none"
+ stroke="#000000"
+ stroke-width="0.25"
+ stroke-miterlimit="10"
+ points="74.961,69.341 57,69.341 57,59.956 74.961,59.956 "
+ id="polyline70" />
+ <polyline
+ fill="none"
+ stroke="#000000"
+ stroke-width="0.25"
+ stroke-miterlimit="10"
+ points="74.961,109.819 57,109.819 57,100.434 74.961,100.434 "
+ id="polyline72" />
+
+ <line
+ fill="none"
+ stroke="#000000"
+ stroke-width="0.25"
+ stroke-miterlimit="10"
+ x1="287.66699"
+ y1="100.029"
+ x2="313.66699"
+ y2="100.029"
+ id="line74" />
+
+ <line
+ fill="none"
+ stroke="#000000"
+ stroke-width="0.25"
+ stroke-miterlimit="10"
+ x1="287.66699"
+ y1="77.077003"
+ x2="313.66699"
+ y2="77.077003"
+ id="line76" />
+ <g
+ id="g96">
+ <path
+ fill="#2a3e40"
+ d="m 168.364,181.027 h -7.912 c 0,0 -2.048,2.33 -5.214,5.937 l -0.171,-21.091 -3.548,2.644 c -3.565,2.649 -7.454,4.844 -11.545,6.549 v -8.789 h -4.487 v 10.432 c -5.39,1.723 -11.039,2.63 -16.71,2.63 -0.292,0 -0.572,0 -0.864,0 -5.051,-0.084 -9.998,-0.847 -14.742,-2.253 v -10.809 h -4.487 v 9.252 c -4.413,-1.741 -8.613,-4.057 -12.508,-6.934 l -3.586,-2.657 0.089,35.792 v 0.116 c 0.661,12.079 4.945,23.522 12.384,33.108 5.73,7.38 13.194,13.271 21.659,17.187 v 8.469 h 4.487 v -8.297 c 9.715,-4.771 17.995,-11.995 23.99,-21.021 6.104,-9.168 9.6,-19.834 10.147,-30.833 v -0.063 l -0.03,-3.751 z m -26.902,47.787 c -5.57,8.378 -13.263,15.131 -22.303,19.542 -8.049,-3.61 -15.13,-9.179 -20.547,-16.161 -6.866,-8.835 -10.82,-19.402 -11.444,-30.54 l -0.076,-26.996 c 9.218,5.837 19.759,8.991 30.746,9.155 11.557,0.192 23.078,-3.089 32.818,-9.256 l 0.138,17.472 c -11.852,13.51 -30.401,34.702 -30.492,35.096 -0.09,-0.579 -10.269,-30.954 -10.269,-30.954 h -7.979 l 13.619,39.961 h 6.653 l 28.411,-34.005 c -0.787,9.524 -3.98,18.711 -9.275,26.686 z"
+ id="path78" />
+ <path
+ fill="#2a3e40"
+ d="m 178.667,210.122 c -0.708,-1.04 -1.583,-1.918 -2.625,-2.624 -1.042,-0.708 -2.176,-1.191 -3.404,-1.452 -1.229,-0.257 -2.476,-0.39 -3.741,-0.39 -1.229,0 -2.467,0.133 -3.712,0.39 -1.247,0.261 -2.391,0.745 -3.432,1.452 -1.042,0.706 -1.917,1.583 -2.625,2.624 -0.707,1.042 -1.2,2.175 -1.479,3.407 -0.28,1.226 -0.419,2.474 -0.419,3.738 v 7.258 c 0,1.266 0.14,2.509 0.419,3.74 0.279,1.228 0.781,2.363 1.506,3.402 0.726,1.046 1.618,1.91 2.679,2.6 1.062,0.687 2.206,1.172 3.433,1.45 1.228,0.279 2.475,0.417 3.74,0.417 1.376,0 2.726,-0.147 4.047,-0.444 1.321,-0.298 2.54,-0.845 3.656,-1.647 1.116,-0.8 2,-1.815 2.652,-3.042 0.651,-1.229 1.013,-2.511 1.088,-3.851 h -6.475 c -0.037,0.745 -0.326,1.403 -0.866,1.98 -0.539,0.577 -1.171,0.959 -1.896,1.145 -0.726,0.186 -1.463,0.279 -2.207,0.279 -0.745,0 -1.479,-0.138 -2.205,-0.42 -0.726,-0.278 -1.332,-0.725 -1.814,-1.338 -0.484,-0.615 -0.82,-1.294 -1.004,-2.037 -0.188,-0.746 -0.28,-1.491 -0.28,-2.232 v -0.838 h 16.859 v -6.419 c 0,-1.265 -0.141,-2.512 -0.419,-3.738 -0.277,-1.236 -0.77,-2.369 -1.476,-3.41 z m -4.579,7.98 h -10.383 v -0.835 c 0,-0.745 0.092,-1.487 0.28,-2.232 0.185,-0.743 0.51,-1.425 0.977,-2.038 0.463,-0.613 1.051,-1.061 1.758,-1.34 0.706,-0.279 1.432,-0.417 2.177,-0.417 0.744,0 1.479,0.138 2.206,0.417 0.725,0.28 1.32,0.727 1.786,1.34 0.465,0.613 0.781,1.295 0.949,2.038 0.166,0.746 0.25,1.488 0.25,2.232 z"
+ id="path80" />
+ <path
+ fill="#2a3e40"
+ d="m 205.495,209.945 c -0.298,-0.851 -0.725,-1.614 -1.284,-2.294 -0.559,-0.678 -1.255,-1.18 -2.093,-1.5 -0.837,-0.318 -1.684,-0.481 -2.54,-0.481 -0.93,0 -1.813,0.18 -2.651,0.538 -0.837,0.36 -1.544,0.897 -2.121,1.613 -0.578,0.72 -1.061,1.481 -1.451,2.294 -0.392,0.81 -0.699,1.667 -0.922,2.577 v -6.572 h -6.53 v 30.013 h 6.53 V 220.22 c 0,-0.755 0.028,-1.5 0.083,-2.234 0.058,-0.737 0.169,-1.465 0.335,-2.181 0.169,-0.715 0.41,-1.415 0.726,-2.096 0.316,-0.68 0.782,-1.246 1.396,-1.699 0.613,-0.453 1.292,-0.678 2.038,-0.678 0.595,0 1.134,0.19 1.619,0.566 0.483,0.379 0.8,0.868 0.948,1.47 0.149,0.604 0.224,1.209 0.224,1.813 h 6.474 c 0,-0.904 -0.055,-1.792 -0.167,-2.661 -0.111,-0.869 -0.317,-1.727 -0.614,-2.575 z"
+ id="path82" />
+ <polygon
+ fill="#2a3e40"
+ points="212.395,211.406 218.534,211.406 218.534,230.382 211.613,230.382 211.613,236.132 231.151,236.132 231.151,230.382 225.011,230.382 225.011,205.656 212.395,205.656 "
+ id="polygon84" />
+ <path
+ fill="#2a3e40"
+ d="m 219.065,200.56 c 0.761,0.338 1.535,0.505 2.316,0.505 0.818,0 1.599,-0.167 2.343,-0.505 0.745,-0.332 1.286,-0.881 1.62,-1.644 0.334,-0.761 0.501,-1.535 0.501,-2.316 0,-0.82 -0.167,-1.601 -0.501,-2.346 -0.334,-0.743 -0.875,-1.283 -1.62,-1.619 -0.744,-0.334 -1.525,-0.501 -2.343,-0.501 -0.782,0 -1.556,0.167 -2.316,0.501 -0.766,0.336 -1.313,0.875 -1.647,1.619 -0.334,0.746 -0.503,1.526 -0.503,2.346 0,0.782 0.168,1.556 0.503,2.316 0.335,0.763 0.881,1.313 1.647,1.644 z"
+ id="path86" />
+ <path
+ fill="#2a3e40"
+ d="m 254.871,208.31 c -1.097,-0.987 -2.362,-1.678 -3.796,-2.069 -1.433,-0.389 -2.895,-0.585 -4.381,-0.585 -1.229,0 -2.448,0.141 -3.656,0.417 -1.211,0.284 -2.336,0.774 -3.378,1.481 -1.042,0.708 -1.905,1.583 -2.595,2.624 -0.688,1.043 -1.171,2.176 -1.452,3.405 -0.279,1.227 -0.418,2.456 -0.418,3.684 v 7.258 c 0,1.227 0.14,2.455 0.418,3.683 0.281,1.23 0.764,2.366 1.452,3.406 0.69,1.043 1.554,1.918 2.595,2.624 1.042,0.707 2.167,1.202 3.378,1.479 1.208,0.279 2.427,0.417 3.656,0.417 1.487,0 2.948,-0.195 4.381,-0.585 1.434,-0.391 2.699,-1.076 3.796,-2.065 1.097,-0.983 1.924,-2.175 2.484,-3.572 0.56,-1.395 0.837,-2.817 0.837,-4.271 v -0.11 h -6.475 v 0.057 c 0,0.893 -0.205,1.749 -0.613,2.568 -0.409,0.818 -1.025,1.422 -1.842,1.813 -0.82,0.391 -1.674,0.585 -2.568,0.585 -0.707,0 -1.414,-0.147 -2.121,-0.447 -0.707,-0.297 -1.285,-0.754 -1.732,-1.368 -0.447,-0.612 -0.751,-1.282 -0.919,-2.007 -0.168,-0.726 -0.251,-1.463 -0.251,-2.205 v -7.258 c 0,-0.745 0.083,-1.482 0.251,-2.205 0.168,-0.726 0.473,-1.395 0.919,-2.01 0.447,-0.614 1.025,-1.067 1.732,-1.368 0.707,-0.293 1.414,-0.444 2.121,-0.444 0.894,0 1.749,0.195 2.568,0.585 0.817,0.392 1.433,0.996 1.842,1.812 0.408,0.819 0.613,1.678 0.613,2.57 v 0.057 h 6.475 v -0.113 c 0,-1.451 -0.277,-2.875 -0.837,-4.272 -0.56,-1.396 -1.387,-2.587 -2.484,-3.571 z"
+ id="path88" />
+ <path
+ fill="#2a3e40"
+ d="m 284.967,210.122 c -0.708,-1.04 -1.585,-1.918 -2.625,-2.624 -1.042,-0.708 -2.175,-1.191 -3.405,-1.452 -1.227,-0.257 -2.473,-0.39 -3.74,-0.39 -1.228,0 -2.467,0.133 -3.713,0.39 -1.248,0.261 -2.391,0.745 -3.432,1.452 -1.042,0.706 -1.918,1.583 -2.626,2.624 -0.704,1.042 -1.198,2.175 -1.477,3.407 -0.281,1.226 -0.418,2.474 -0.418,3.738 v 7.258 c 0,1.266 0.138,2.509 0.418,3.74 0.279,1.228 0.782,2.363 1.508,3.402 0.725,1.046 1.618,1.91 2.681,2.6 1.059,0.687 2.204,1.172 3.431,1.45 1.227,0.279 2.475,0.417 3.742,0.417 1.374,0 2.723,-0.147 4.045,-0.444 1.321,-0.298 2.54,-0.845 3.656,-1.647 1.116,-0.8 2,-1.815 2.653,-3.042 0.65,-1.229 1.012,-2.511 1.088,-3.851 h -6.476 c -0.037,0.745 -0.327,1.403 -0.866,1.98 -0.54,0.577 -1.172,0.959 -1.898,1.145 -0.724,0.186 -1.461,0.279 -2.203,0.279 -0.745,0 -1.481,-0.138 -2.207,-0.42 -0.724,-0.278 -1.332,-0.725 -1.814,-1.338 -0.483,-0.615 -0.818,-1.294 -1.005,-2.037 -0.186,-0.746 -0.278,-1.491 -0.278,-2.232 v -0.838 h 16.857 v -6.419 c 0,-1.265 -0.139,-2.512 -0.418,-3.738 -0.279,-1.236 -0.772,-2.369 -1.478,-3.41 z m -4.578,7.98 h -10.383 v -0.835 c 0,-0.745 0.092,-1.487 0.278,-2.232 0.187,-0.743 0.512,-1.425 0.977,-2.038 0.466,-0.613 1.053,-1.061 1.76,-1.34 0.707,-0.279 1.432,-0.417 2.177,-0.417 0.743,0 1.479,0.138 2.206,0.417 0.724,0.28 1.32,0.727 1.785,1.34 0.466,0.613 0.783,1.295 0.951,2.038 0.165,0.746 0.251,1.488 0.251,2.232 v 0.835 z"
+ id="path90" />
+ <path
+ fill="#2a3e40"
+ d="m 311.792,209.832 c -0.298,-0.854 -0.726,-1.622 -1.283,-2.305 -0.56,-0.681 -1.257,-1.185 -2.092,-1.506 -0.839,-0.321 -1.687,-0.484 -2.542,-0.484 -0.931,0 -1.815,0.181 -2.65,0.542 -0.839,0.361 -1.546,0.9 -2.122,1.62 -0.578,0.723 -1.061,1.487 -1.452,2.304 -0.391,0.814 -0.699,1.675 -0.919,2.587 v -6.601 H 292.2 v 30.144 h 6.532 v -15.981 c 0,-0.758 0.027,-1.507 0.081,-2.245 0.059,-0.74 0.168,-1.472 0.336,-2.19 0.167,-0.719 0.409,-1.421 0.724,-2.105 0.315,-0.683 0.784,-1.252 1.397,-1.707 0.613,-0.454 1.292,-0.681 2.037,-0.681 0.594,0 1.133,0.191 1.62,0.568 0.482,0.38 0.799,0.872 0.948,1.476 0.149,0.607 0.226,1.215 0.226,1.822 h 6.473 c 0,-0.909 -0.055,-1.801 -0.167,-2.673 -0.111,-0.873 -0.316,-1.733 -0.615,-2.585 z"
+ id="path92" />
+ <path
+ fill="#2a3e40"
+ d="m 336.389,224.88 v 0.285 c 0,0.602 -0.047,1.187 -0.139,1.75 -0.094,0.565 -0.252,1.123 -0.474,1.67 -0.224,0.547 -0.59,0.999 -1.089,1.357 -0.504,0.358 -1.032,0.537 -1.592,0.537 -0.708,0 -1.311,-0.265 -1.815,-0.792 -0.501,-0.527 -0.856,-1.119 -1.06,-1.779 -0.207,-0.661 -0.345,-1.338 -0.42,-2.037 -0.074,-0.697 -0.112,-1.386 -0.112,-2.065 v -12.441 h 7.76 v -5.657 h -7.76 v -11.591 h -6.472 v 11.591 h -5.304 v 5.657 h 5.304 v 12.441 c 0,1.208 0.089,2.404 0.278,3.593 0.185,1.187 0.529,2.327 1.031,3.419 0.504,1.095 1.183,2.076 2.038,2.94 0.858,0.871 1.861,1.481 3.016,1.839 1.154,0.354 2.324,0.535 3.516,0.535 1.34,0 2.659,-0.227 3.962,-0.676 1.301,-0.453 2.409,-1.214 3.322,-2.292 0.912,-1.071 1.565,-2.277 1.955,-3.618 0.39,-1.338 0.585,-2.687 0.585,-4.044 v -0.622 z"
+ id="path94" />
+ </g>
+ <path
+ fill="#9acfb2"
+ d="m 122.325,236.132 h -6.653 l -13.619,-39.961 h 7.979 c 0,0 10.178,30.375 10.269,30.954 0.091,-0.394 18.641,-21.586 30.492,-35.096 l -0.138,-17.472 c -9.74,6.167 -21.261,9.449 -32.818,9.256 -10.987,-0.164 -21.527,-3.317 -30.746,-9.155 l 0.076,26.996 c 0.624,11.138 4.578,21.705 11.444,30.54 5.417,6.982 12.499,12.551 20.547,16.161 9.041,-4.411 16.733,-11.163 22.303,-19.542 0.629,-0.947 1.223,-1.914 1.792,-2.894 0.042,-0.073 0.087,-0.145 0.13,-0.219 0.54,-0.939 1.047,-1.896 1.532,-2.862 0.058,-0.117 0.119,-0.232 0.177,-0.349 0.466,-0.947 0.902,-1.907 1.314,-2.877 0.059,-0.138 0.119,-0.276 0.177,-0.416 0.401,-0.964 0.773,-1.938 1.12,-2.922 0.052,-0.147 0.103,-0.294 0.154,-0.441 0.339,-0.989 0.652,-1.987 0.936,-2.994 0.04,-0.14 0.077,-0.28 0.116,-0.42 0.28,-1.023 0.535,-2.054 0.757,-3.093 0.025,-0.116 0.047,-0.233 0.072,-0.35 0.222,-1.069 0.417,-2.144 0.578,-3.226 0.011,-0.073 0.019,-0.146 0.03,-0.22 0.163,-1.129 0.295,-2.264 0.39,-3.405 z"
+ id="path98" />
+ <g
+ id="g102">
+ <path
+ fill="#2a3e40"
+ d="m 529.372,181.027 h -7.912 c 0,0 -2.048,2.33 -5.214,5.937 l -0.171,-21.091 -3.548,2.644 c -3.565,2.649 -7.454,4.844 -11.545,6.549 v -8.789 h -4.487 v 10.432 c -5.39,1.723 -11.039,2.63 -16.71,2.63 -0.292,0 -0.572,0 -0.864,0 -5.051,-0.084 -9.998,-0.847 -14.742,-2.253 v -10.809 h -4.487 v 9.252 c -4.413,-1.741 -8.613,-4.057 -12.508,-6.934 l -3.586,-2.657 0.089,35.792 v 0.116 c 0.661,12.079 4.945,23.522 12.384,33.108 5.73,7.38 13.194,13.271 21.659,17.187 v 8.469 h 4.487 v -8.297 c 9.715,-4.771 17.995,-11.995 23.99,-21.021 6.104,-9.168 9.6,-19.834 10.147,-30.833 v -0.063 l -0.03,-3.751 z m -26.902,47.787 c -5.57,8.378 -13.263,15.131 -22.303,19.542 -8.049,-3.61 -15.13,-9.179 -20.547,-16.161 -6.866,-8.835 -10.82,-19.402 -11.444,-30.54 L 448.1,174.659 c 9.218,5.837 19.759,8.991 30.746,9.155 11.557,0.192 23.078,-3.089 32.818,-9.256 l 0.138,17.472 c -11.852,13.51 -30.401,34.702 -30.492,35.096 -0.09,-0.579 -10.269,-30.954 -10.269,-30.954 h -7.979 l 13.619,39.961 h 6.653 l 28.411,-34.005 c -0.787,9.524 -3.981,18.711 -9.275,26.686 z"
+ id="path100" />
+ </g>
+ <path
+ fill="#9acfb2"
+ d="m 483.333,236.132 h -6.653 l -13.619,-39.961 h 7.979 c 0,0 10.178,30.375 10.269,30.954 0.091,-0.394 18.641,-21.586 30.492,-35.096 l -0.138,-17.472 c -9.74,6.167 -21.261,9.449 -32.818,9.256 -10.987,-0.164 -21.527,-3.317 -30.746,-9.155 l 0.076,26.996 c 0.624,11.138 4.578,21.705 11.444,30.54 5.417,6.982 12.499,12.551 20.547,16.161 9.041,-4.411 16.733,-11.163 22.303,-19.542 0.629,-0.947 1.223,-1.914 1.792,-2.894 0.042,-0.073 0.087,-0.145 0.13,-0.219 0.54,-0.939 1.047,-1.896 1.532,-2.862 0.058,-0.117 0.119,-0.232 0.177,-0.349 0.466,-0.947 0.902,-1.907 1.314,-2.877 0.059,-0.138 0.119,-0.276 0.177,-0.416 0.401,-0.964 0.773,-1.938 1.12,-2.922 0.052,-0.147 0.103,-0.294 0.154,-0.441 0.339,-0.989 0.652,-1.987 0.936,-2.994 0.04,-0.14 0.077,-0.28 0.116,-0.42 0.28,-1.023 0.535,-2.054 0.757,-3.093 0.025,-0.116 0.047,-0.233 0.072,-0.35 0.222,-1.069 0.417,-2.144 0.578,-3.226 0.011,-0.073 0.019,-0.146 0.03,-0.22 0.163,-1.129 0.295,-2.264 0.39,-3.405 z"
+ id="path104" />
+ <g
+ id="g124">
+ <path
+ d="m 156.12,356.96 h -6.782 c 0,0 -1.756,1.997 -4.47,5.089 l -0.147,-18.081 -3.042,2.267 c -3.056,2.271 -6.39,4.152 -9.897,5.614 v -7.534 h -3.846 v 8.942 c -4.621,1.477 -9.463,2.255 -14.325,2.255 -0.25,0 -0.49,0 -0.741,0 -4.33,-0.072 -8.57,-0.726 -12.638,-1.931 v -9.266 h -3.847 v 7.931 c -3.783,-1.492 -7.384,-3.478 -10.722,-5.944 l -3.074,-2.278 0.077,30.683 v 0.099 c 0.567,10.354 4.239,20.165 10.616,28.382 4.912,6.327 11.311,11.377 18.567,14.734 v 7.26 h 3.847 v -7.113 c 8.328,-4.089 15.426,-10.283 20.565,-18.02 5.232,-7.86 8.23,-17.003 8.699,-26.432 v -0.054 l -0.026,-3.216 z m -23.061,40.965 c -4.775,7.183 -11.37,12.971 -19.12,16.752 -6.9,-3.094 -12.97,-7.869 -17.614,-13.854 -5.886,-7.574 -9.275,-16.632 -9.81,-26.181 L 86.449,351.5 c 7.902,5.004 16.938,7.708 26.357,7.848 9.907,0.165 19.783,-2.648 28.133,-7.935 l 0.118,14.978 c -10.16,11.582 -26.061,29.749 -26.139,30.086 -0.078,-0.496 -8.803,-26.535 -8.803,-26.535 h -6.84 l 11.675,34.257 h 5.703 l 24.355,-29.151 c -0.673,8.165 -3.411,16.041 -7.949,22.877 z"
+ id="path106" />
+ <path
+ d="m 164.952,381.901 c -0.607,-0.892 -1.357,-1.644 -2.25,-2.249 -0.893,-0.606 -1.866,-1.021 -2.918,-1.245 -1.054,-0.22 -2.122,-0.334 -3.207,-0.334 -1.053,0 -2.115,0.114 -3.183,0.334 -1.069,0.224 -2.05,0.639 -2.942,1.245 -0.894,0.605 -1.644,1.357 -2.25,2.249 -0.605,0.893 -1.028,1.864 -1.267,2.92 -0.24,1.051 -0.36,2.121 -0.36,3.205 v 6.222 c 0,1.085 0.12,2.151 0.36,3.207 0.239,1.053 0.669,2.026 1.291,2.916 0.623,0.897 1.387,1.638 2.297,2.229 0.91,0.589 1.891,1.004 2.943,1.243 1.053,0.239 2.122,0.357 3.207,0.357 1.18,0 2.336,-0.126 3.47,-0.38 1.132,-0.255 2.177,-0.724 3.134,-1.412 0.957,-0.686 1.714,-1.556 2.273,-2.608 0.558,-1.053 0.869,-2.153 0.933,-3.301 h -5.551 c -0.032,0.639 -0.279,1.203 -0.742,1.697 -0.462,0.495 -1.004,0.823 -1.625,0.981 -0.623,0.159 -1.254,0.239 -1.892,0.239 -0.639,0 -1.268,-0.118 -1.89,-0.36 -0.622,-0.238 -1.141,-0.622 -1.555,-1.147 -0.416,-0.527 -0.703,-1.109 -0.861,-1.746 -0.161,-0.639 -0.24,-1.278 -0.24,-1.914 v -0.719 h 14.453 v -5.503 c 0,-1.084 -0.121,-2.153 -0.36,-3.205 -0.24,-1.056 -0.663,-2.028 -1.268,-2.921 z m -3.925,6.842 h -8.901 v -0.716 c 0,-0.638 0.079,-1.274 0.24,-1.914 0.158,-0.637 0.438,-1.222 0.837,-1.747 0.397,-0.526 0.901,-0.909 1.507,-1.149 0.605,-0.239 1.228,-0.357 1.866,-0.357 0.638,0 1.268,0.118 1.891,0.357 0.622,0.24 1.131,0.623 1.531,1.149 0.398,0.525 0.669,1.11 0.813,1.747 0.143,0.639 0.215,1.275 0.215,1.914 v 0.716 z"
+ id="path108" />
+ <path
+ d="m 187.951,381.75 c -0.255,-0.729 -0.622,-1.384 -1.101,-1.967 -0.479,-0.581 -1.076,-1.011 -1.794,-1.286 -0.718,-0.273 -1.443,-0.412 -2.178,-0.412 -0.797,0 -1.555,0.154 -2.273,0.461 -0.718,0.309 -1.324,0.77 -1.818,1.383 -0.496,0.617 -0.909,1.27 -1.243,1.967 -0.336,0.694 -0.599,1.43 -0.791,2.209 v -5.634 h -5.598 V 404.2 h 5.598 v -13.641 c 0,-0.647 0.024,-1.286 0.071,-1.916 0.049,-0.632 0.145,-1.256 0.287,-1.87 0.145,-0.613 0.352,-1.213 0.623,-1.797 0.271,-0.583 0.67,-1.068 1.197,-1.456 0.525,-0.389 1.107,-0.582 1.747,-0.582 0.51,0 0.972,0.163 1.388,0.485 0.414,0.325 0.686,0.744 0.813,1.26 0.128,0.518 0.192,1.036 0.192,1.555 h 5.549 c 0,-0.775 -0.047,-1.536 -0.143,-2.281 -0.095,-0.745 -0.271,-1.479 -0.526,-2.207 z"
+ id="path110" />
+ <polygon
+ points="193.866,383.002 199.128,383.002 199.128,399.27 193.195,399.27 193.195,404.199 209.944,404.199 209.944,399.27 204.681,399.27 204.681,378.073 193.866,378.073 "
+ id="polygon112" />
+ <path
+ d="m 199.584,373.705 c 0.652,0.29 1.315,0.433 1.986,0.433 0.701,0 1.371,-0.144 2.009,-0.433 0.638,-0.284 1.102,-0.755 1.389,-1.409 0.287,-0.652 0.43,-1.316 0.43,-1.986 0,-0.703 -0.143,-1.372 -0.43,-2.011 -0.287,-0.637 -0.75,-1.1 -1.389,-1.388 -0.638,-0.287 -1.308,-0.43 -2.009,-0.43 -0.67,0 -1.333,0.143 -1.986,0.43 -0.657,0.288 -1.125,0.75 -1.412,1.388 -0.287,0.639 -0.431,1.309 -0.431,2.011 0,0.67 0.144,1.333 0.431,1.986 0.287,0.654 0.755,1.124 1.412,1.409 z"
+ id="path114" />
+ <path
+ d="m 230.279,380.349 c -0.941,-0.846 -2.025,-1.439 -3.254,-1.774 -1.229,-0.333 -2.481,-0.501 -3.756,-0.501 -1.054,0 -2.099,0.12 -3.134,0.357 -1.038,0.244 -2.003,0.664 -2.896,1.27 -0.893,0.606 -1.633,1.356 -2.225,2.25 -0.589,0.894 -1.004,1.865 -1.245,2.919 -0.239,1.052 -0.359,2.105 -0.359,3.158 v 6.222 c 0,1.052 0.12,2.104 0.359,3.157 0.241,1.055 0.655,2.028 1.245,2.919 0.592,0.895 1.332,1.644 2.225,2.249 0.893,0.606 1.858,1.03 2.896,1.269 1.036,0.239 2.081,0.357 3.134,0.357 1.274,0 2.527,-0.167 3.756,-0.501 1.229,-0.335 2.313,-0.922 3.254,-1.771 0.94,-0.843 1.649,-1.865 2.129,-3.062 0.48,-1.196 0.718,-2.415 0.718,-3.662 v -0.095 h -5.551 v 0.048 c 0,0.766 -0.176,1.499 -0.525,2.202 -0.351,0.701 -0.879,1.219 -1.58,1.554 -0.703,0.335 -1.435,0.502 -2.202,0.502 -0.606,0 -1.212,-0.126 -1.818,-0.383 -0.606,-0.254 -1.101,-0.646 -1.484,-1.173 -0.383,-0.524 -0.644,-1.099 -0.789,-1.721 -0.144,-0.622 -0.215,-1.254 -0.215,-1.891 v -6.222 c 0,-0.638 0.071,-1.271 0.215,-1.89 0.145,-0.623 0.405,-1.196 0.789,-1.723 0.383,-0.526 0.878,-0.915 1.484,-1.173 0.606,-0.252 1.212,-0.381 1.818,-0.381 0.767,0 1.499,0.167 2.202,0.501 0.701,0.336 1.229,0.854 1.58,1.553 0.35,0.703 0.525,1.438 0.525,2.203 v 0.049 h 5.551 v -0.097 c 0,-1.243 -0.238,-2.465 -0.718,-3.662 -0.48,-1.193 -1.189,-2.214 -2.129,-3.057 z"
+ id="path116" />
+ <path
+ d="m 256.079,381.901 c -0.607,-0.892 -1.359,-1.644 -2.25,-2.249 -0.893,-0.606 -1.865,-1.021 -2.919,-1.245 -1.052,-0.22 -2.12,-0.334 -3.206,-0.334 -1.052,0 -2.114,0.114 -3.183,0.334 -1.069,0.224 -2.05,0.639 -2.942,1.245 -0.893,0.605 -1.645,1.357 -2.251,2.249 -0.603,0.893 -1.027,1.864 -1.266,2.92 -0.241,1.051 -0.359,2.121 -0.359,3.205 v 6.222 c 0,1.085 0.118,2.151 0.359,3.207 0.239,1.053 0.67,2.026 1.292,2.916 0.621,0.897 1.387,1.638 2.298,2.229 0.908,0.589 1.889,1.004 2.941,1.243 1.052,0.239 2.122,0.357 3.208,0.357 1.178,0 2.334,-0.126 3.468,-0.38 1.132,-0.255 2.177,-0.724 3.134,-1.412 0.957,-0.686 1.714,-1.556 2.274,-2.608 0.558,-1.053 0.868,-2.153 0.933,-3.301 h -5.552 c -0.031,0.639 -0.28,1.203 -0.742,1.697 -0.463,0.495 -1.005,0.823 -1.627,0.981 -0.621,0.159 -1.252,0.239 -1.889,0.239 -0.639,0 -1.27,-0.118 -1.892,-0.36 -0.621,-0.238 -1.142,-0.622 -1.555,-1.147 -0.415,-0.527 -0.701,-1.109 -0.861,-1.746 -0.159,-0.639 -0.238,-1.278 -0.238,-1.914 v -0.719 h 14.451 v -5.503 c 0,-1.084 -0.12,-2.153 -0.358,-3.205 -0.241,-1.056 -0.663,-2.028 -1.268,-2.921 z m -3.925,6.842 h -8.901 v -0.716 c 0,-0.638 0.079,-1.274 0.238,-1.914 0.16,-0.637 0.439,-1.222 0.837,-1.747 0.399,-0.526 0.902,-0.909 1.509,-1.149 0.606,-0.239 1.228,-0.357 1.866,-0.357 0.637,0 1.269,0.118 1.891,0.357 0.621,0.24 1.132,0.623 1.53,1.149 0.399,0.525 0.671,1.11 0.815,1.747 0.142,0.639 0.215,1.275 0.215,1.914 z"
+ id="path118" />
+ <path
+ d="m 279.075,381.653 c -0.255,-0.732 -0.623,-1.39 -1.1,-1.976 -0.48,-0.583 -1.078,-1.016 -1.793,-1.292 -0.719,-0.275 -1.446,-0.415 -2.179,-0.415 -0.798,0 -1.556,0.155 -2.272,0.464 -0.719,0.31 -1.325,0.772 -1.818,1.389 -0.496,0.62 -0.909,1.275 -1.245,1.975 -0.335,0.698 -0.599,1.436 -0.788,2.218 v -5.659 h -5.6 v 25.841 h 5.6 v -13.7 c 0,-0.65 0.023,-1.292 0.069,-1.924 0.05,-0.634 0.144,-1.262 0.289,-1.877 0.144,-0.616 0.35,-1.218 0.621,-1.804 0.271,-0.585 0.672,-1.073 1.198,-1.463 0.525,-0.39 1.107,-0.583 1.746,-0.583 0.509,0 0.972,0.164 1.389,0.487 0.413,0.326 0.685,0.748 0.813,1.266 0.128,0.521 0.193,1.042 0.193,1.562 h 5.548 c 0,-0.779 -0.047,-1.543 -0.143,-2.291 -0.096,-0.75 -0.272,-1.487 -0.528,-2.218 z"
+ id="path120" />
+ <path
+ d="m 300.16,394.553 v 0.244 c 0,0.516 -0.041,1.018 -0.119,1.5 -0.081,0.485 -0.216,0.962 -0.406,1.432 -0.192,0.469 -0.506,0.856 -0.934,1.163 -0.432,0.307 -0.885,0.46 -1.365,0.46 -0.607,0 -1.124,-0.228 -1.556,-0.679 -0.43,-0.452 -0.734,-0.959 -0.908,-1.525 -0.178,-0.567 -0.296,-1.147 -0.36,-1.746 -0.064,-0.598 -0.097,-1.188 -0.097,-1.771 v -10.665 h 6.653 v -4.849 h -6.653 v -9.936 h -5.548 v 9.936 h -4.547 v 4.849 h 4.547 v 10.665 c 0,1.036 0.077,2.061 0.238,3.08 0.159,1.018 0.454,1.995 0.884,2.931 0.432,0.939 1.014,1.78 1.747,2.521 0.736,0.746 1.596,1.27 2.585,1.576 0.99,0.304 1.993,0.458 3.014,0.458 1.149,0 2.279,-0.195 3.397,-0.58 1.116,-0.388 2.065,-1.041 2.848,-1.964 0.782,-0.918 1.341,-1.953 1.676,-3.102 0.334,-1.147 0.501,-2.303 0.501,-3.467 v -0.533 h -5.597 z"
+ id="path122" />
+ </g>
+ <path
+ fill="#ffffff"
+ d="M 116.653,404.199 H 110.95 L 99.275,369.942 h 6.84 c 0,0 8.725,26.039 8.803,26.535 0.078,-0.337 15.979,-18.504 26.139,-30.086 l -0.118,-14.978 c -8.35,5.287 -18.226,8.1 -28.133,7.935 -9.418,-0.141 -18.455,-2.844 -26.357,-7.848 l 0.065,23.142 c 0.535,9.548 3.924,18.606 9.81,26.181 4.644,5.985 10.714,10.76 17.614,13.854 7.75,-3.781 14.344,-9.569 19.12,-16.752 0.539,-0.812 1.048,-1.641 1.537,-2.481 0.037,-0.063 0.075,-0.124 0.111,-0.188 0.462,-0.805 0.898,-1.625 1.313,-2.453 0.05,-0.1 0.102,-0.199 0.152,-0.299 0.399,-0.812 0.773,-1.635 1.126,-2.467 0.051,-0.118 0.102,-0.237 0.152,-0.356 0.343,-0.827 0.663,-1.662 0.959,-2.505 0.044,-0.126 0.088,-0.252 0.132,-0.378 0.291,-0.848 0.559,-1.704 0.803,-2.566 0.034,-0.12 0.066,-0.24 0.099,-0.36 0.24,-0.877 0.458,-1.761 0.649,-2.652 0.022,-0.1 0.041,-0.2 0.062,-0.299 0.191,-0.917 0.358,-1.838 0.496,-2.766 0.009,-0.063 0.016,-0.126 0.025,-0.188 0.139,-0.968 0.253,-1.941 0.334,-2.919 z"
+ id="path126" />
+ <g
+ id="g130">
+ <path
+ d="m 465.595,356.96 h -6.782 c 0,0 -1.756,1.997 -4.47,5.089 l -0.147,-18.081 -3.042,2.267 c -3.056,2.271 -6.39,4.152 -9.897,5.614 v -7.534 h -3.846 v 8.942 c -4.62,1.477 -9.463,2.255 -14.325,2.255 -0.25,0 -0.49,0 -0.74,0 -4.331,-0.072 -8.571,-0.726 -12.638,-1.931 v -9.266 h -3.847 v 7.931 c -3.783,-1.492 -7.384,-3.478 -10.722,-5.944 l -3.074,-2.278 0.077,30.683 v 0.099 c 0.567,10.354 4.239,20.165 10.616,28.382 4.912,6.327 11.311,11.377 18.567,14.734 v 7.26 h 3.847 v -7.113 c 8.328,-4.089 15.426,-10.283 20.566,-18.02 5.232,-7.86 8.229,-17.003 8.699,-26.432 v -0.054 l -0.026,-3.216 z m -23.062,40.965 c -4.775,7.183 -11.369,12.971 -19.119,16.752 -6.9,-3.094 -12.971,-7.869 -17.615,-13.854 -5.885,-7.574 -9.275,-16.632 -9.81,-26.181 L 395.924,351.5 c 7.902,5.004 16.938,7.708 26.357,7.848 9.907,0.165 19.783,-2.648 28.133,-7.935 l 0.118,14.978 c -10.16,11.582 -26.062,29.749 -26.14,30.086 -0.078,-0.496 -8.803,-26.535 -8.803,-26.535 h -6.84 l 11.675,34.257 h 5.703 l 24.355,-29.151 c -0.672,8.165 -3.41,16.041 -7.949,22.877 z"
+ id="path128" />
+ </g>
+ <path
+ fill="#ffffff"
+ d="m 426.128,404.199 h -5.703 L 408.75,369.942 h 6.84 c 0,0 8.725,26.039 8.803,26.535 0.078,-0.337 15.979,-18.504 26.14,-30.086 l -0.118,-14.978 c -8.35,5.287 -18.226,8.1 -28.133,7.935 -9.418,-0.141 -18.455,-2.844 -26.357,-7.848 l 0.065,23.142 c 0.535,9.548 3.925,18.606 9.81,26.181 4.644,5.985 10.715,10.76 17.615,13.854 7.75,-3.781 14.344,-9.569 19.119,-16.752 0.539,-0.812 1.049,-1.641 1.537,-2.481 0.037,-0.063 0.075,-0.124 0.111,-0.188 0.463,-0.805 0.898,-1.625 1.313,-2.453 0.05,-0.1 0.103,-0.199 0.152,-0.299 0.4,-0.812 0.773,-1.635 1.127,-2.467 0.05,-0.118 0.102,-0.237 0.151,-0.356 0.344,-0.827 0.663,-1.662 0.96,-2.505 0.044,-0.126 0.088,-0.252 0.132,-0.378 0.291,-0.848 0.559,-1.704 0.802,-2.566 0.034,-0.12 0.066,-0.24 0.099,-0.36 0.24,-0.877 0.458,-1.761 0.649,-2.652 0.021,-0.1 0.041,-0.2 0.062,-0.299 0.19,-0.917 0.358,-1.838 0.495,-2.766 0.009,-0.063 0.016,-0.126 0.025,-0.188 0.14,-0.968 0.253,-1.941 0.334,-2.919 z"
+ id="path132" />
+ <g
+ id="g152">
+ <path
+ fill="#ffffff"
+ d="m 155.445,473.178 h -6.736 c 0,0 -1.744,1.984 -4.44,5.056 l -0.146,-17.96 -3.021,2.252 c -3.036,2.256 -6.347,4.124 -9.831,5.576 v -7.483 h -3.821 v 8.882 c -4.589,1.468 -9.4,2.24 -14.229,2.24 -0.249,0 -0.487,0 -0.735,0 -4.301,-0.071 -8.513,-0.721 -12.553,-1.919 v -9.203 h -3.82 v 7.878 c -3.758,-1.482 -7.335,-3.454 -10.65,-5.904 l -3.054,-2.263 0.076,30.477 v 0.099 c 0.563,10.286 4.211,20.029 10.545,28.191 4.879,6.285 11.234,11.302 18.442,14.636 v 7.211 h 3.821 v -7.066 c 8.272,-4.062 15.323,-10.213 20.427,-17.897 5.198,-7.807 8.175,-16.89 8.641,-26.255 v -0.053 l -0.025,-3.195 z m -22.906,40.69 c -4.743,7.134 -11.293,12.883 -18.991,16.639 -6.853,-3.073 -12.883,-7.814 -17.496,-13.76 -5.846,-7.523 -9.213,-16.521 -9.745,-26.005 l -0.064,-22.986 c 7.849,4.971 16.824,7.655 26.18,7.795 9.841,0.164 19.651,-2.632 27.945,-7.882 l 0.117,14.877 c -10.091,11.504 -25.886,29.549 -25.964,29.885 -0.077,-0.493 -8.744,-26.357 -8.744,-26.357 H 98.984 L 110.58,520.1 h 5.665 l 24.191,-28.955 c -0.67,8.109 -3.39,15.932 -7.897,22.723 z"
+ id="path134" />
+ <path
+ fill="#ffffff"
+ d="m 164.218,497.951 c -0.602,-0.886 -1.348,-1.633 -2.234,-2.233 -0.887,-0.603 -1.853,-1.013 -2.899,-1.236 -1.046,-0.219 -2.107,-0.333 -3.185,-0.333 -1.046,0 -2.1,0.114 -3.161,0.333 -1.062,0.224 -2.036,0.634 -2.922,1.236 -0.888,0.601 -1.633,1.348 -2.235,2.233 -0.602,0.888 -1.021,1.853 -1.259,2.901 -0.238,1.045 -0.357,2.106 -0.357,3.183 v 6.181 c 0,1.078 0.119,2.137 0.357,3.185 0.237,1.046 0.666,2.012 1.282,2.896 0.618,0.891 1.378,1.627 2.282,2.215 0.904,0.584 1.878,0.997 2.923,1.233 1.045,0.238 2.108,0.354 3.186,0.354 1.171,0 2.32,-0.125 3.446,-0.378 1.125,-0.254 2.162,-0.719 3.113,-1.402 0.951,-0.681 1.703,-1.546 2.258,-2.59 0.554,-1.046 0.863,-2.14 0.927,-3.279 h -5.513 c -0.032,0.634 -0.277,1.194 -0.737,1.686 -0.458,0.491 -0.998,0.816 -1.614,0.975 -0.619,0.157 -1.246,0.237 -1.879,0.237 -0.635,0 -1.259,-0.117 -1.878,-0.357 -0.617,-0.236 -1.133,-0.616 -1.544,-1.139 -0.413,-0.524 -0.698,-1.103 -0.855,-1.735 -0.16,-0.636 -0.238,-1.269 -0.238,-1.9 v -0.714 h 14.356 v -5.467 c 0,-1.076 -0.12,-2.138 -0.357,-3.183 -0.242,-1.049 -0.662,-2.014 -1.263,-2.902 z m -3.898,6.797 h -8.841 v -0.713 c 0,-0.633 0.079,-1.265 0.238,-1.9 0.158,-0.633 0.435,-1.214 0.832,-1.735 0.395,-0.521 0.895,-0.903 1.497,-1.142 0.601,-0.236 1.219,-0.354 1.854,-0.354 0.634,0 1.26,0.118 1.878,0.354 0.618,0.238 1.124,0.62 1.521,1.142 0.396,0.521 0.665,1.103 0.809,1.735 0.141,0.636 0.213,1.268 0.213,1.9 v 0.713 z"
+ id="path136" />
+ <path
+ fill="#ffffff"
+ d="m 187.062,497.801 c -0.253,-0.724 -0.617,-1.374 -1.093,-1.954 -0.475,-0.576 -1.068,-1.003 -1.782,-1.277 -0.713,-0.271 -1.434,-0.409 -2.163,-0.409 -0.792,0 -1.544,0.152 -2.257,0.459 -0.713,0.307 -1.315,0.763 -1.806,1.373 -0.492,0.612 -0.903,1.262 -1.235,1.953 -0.333,0.689 -0.595,1.421 -0.785,2.194 v -5.596 H 170.38 V 520.1 h 5.561 v -13.549 c 0,-0.643 0.023,-1.278 0.071,-1.902 0.049,-0.627 0.144,-1.249 0.285,-1.858 0.144,-0.609 0.35,-1.204 0.618,-1.783 0.269,-0.58 0.666,-1.062 1.189,-1.447 0.522,-0.386 1.1,-0.577 1.735,-0.577 0.506,0 0.965,0.162 1.378,0.481 0.411,0.323 0.681,0.739 0.808,1.253 0.127,0.514 0.191,1.029 0.191,1.543 h 5.512 c 0,-0.77 -0.046,-1.525 -0.142,-2.266 -0.096,-0.741 -0.271,-1.471 -0.524,-2.194 z"
+ id="path138" />
+ <polygon
+ fill="#ffffff"
+ points="192.938,499.046 198.165,499.046 198.165,515.203 192.271,515.203 192.271,520.1 208.908,520.1 208.908,515.203 203.68,515.203 203.68,494.148 192.938,494.148 "
+ id="polygon140" />
+ <path
+ fill="#ffffff"
+ d="m 198.617,489.81 c 0.648,0.288 1.307,0.431 1.973,0.431 0.696,0 1.362,-0.143 1.995,-0.431 0.634,-0.281 1.095,-0.75 1.379,-1.399 0.285,-0.647 0.427,-1.307 0.427,-1.972 0,-0.698 -0.142,-1.363 -0.427,-1.998 -0.285,-0.633 -0.745,-1.092 -1.379,-1.378 -0.633,-0.285 -1.299,-0.427 -1.995,-0.427 -0.666,0 -1.325,0.142 -1.973,0.427 -0.652,0.286 -1.117,0.745 -1.402,1.378 -0.285,0.635 -0.428,1.3 -0.428,1.998 0,0.665 0.143,1.324 0.428,1.972 0.285,0.649 0.75,1.117 1.402,1.399 z"
+ id="path142" />
+ <path
+ fill="#ffffff"
+ d="m 229.106,496.409 c -0.934,-0.84 -2.012,-1.43 -3.232,-1.762 -1.22,-0.331 -2.465,-0.499 -3.73,-0.499 -1.046,0 -2.085,0.12 -3.114,0.355 -1.031,0.242 -1.989,0.659 -2.876,1.261 -0.887,0.603 -1.622,1.349 -2.21,2.234 -0.585,0.888 -0.998,1.853 -1.236,2.899 -0.238,1.045 -0.356,2.091 -0.356,3.137 v 6.181 c 0,1.044 0.119,2.09 0.356,3.136 0.239,1.048 0.651,2.016 1.236,2.899 0.588,0.889 1.323,1.634 2.21,2.234 0.887,0.603 1.846,1.023 2.876,1.26 1.029,0.238 2.067,0.354 3.114,0.354 1.266,0 2.51,-0.166 3.73,-0.498 1.221,-0.333 2.298,-0.916 3.232,-1.759 0.934,-0.836 1.638,-1.853 2.115,-3.041 0.477,-1.188 0.713,-2.399 0.713,-3.638 v -0.094 h -5.514 v 0.048 c 0,0.761 -0.174,1.488 -0.521,2.188 -0.349,0.696 -0.873,1.21 -1.569,1.545 -0.698,0.331 -1.426,0.497 -2.187,0.497 -0.603,0 -1.204,-0.125 -1.807,-0.381 -0.602,-0.252 -1.093,-0.642 -1.475,-1.164 -0.38,-0.521 -0.639,-1.093 -0.783,-1.709 -0.143,-0.619 -0.214,-1.246 -0.214,-1.878 v -6.181 c 0,-0.633 0.071,-1.261 0.214,-1.878 0.144,-0.617 0.403,-1.187 0.783,-1.71 0.381,-0.523 0.873,-0.91 1.475,-1.166 0.603,-0.25 1.204,-0.378 1.807,-0.378 0.761,0 1.489,0.166 2.187,0.498 0.696,0.334 1.22,0.848 1.569,1.543 0.347,0.698 0.521,1.429 0.521,2.188 v 0.048 h 5.514 v -0.095 c 0,-1.235 -0.236,-2.449 -0.713,-3.639 -0.477,-1.183 -1.181,-2.197 -2.115,-3.035 z"
+ id="path144" />
+ <path
+ fill="#ffffff"
+ d="m 254.732,497.951 c -0.603,-0.886 -1.35,-1.633 -2.235,-2.233 -0.887,-0.603 -1.852,-1.013 -2.9,-1.236 -1.044,-0.219 -2.105,-0.333 -3.184,-0.333 -1.045,0 -2.101,0.114 -3.162,0.333 -1.063,0.224 -2.036,0.634 -2.922,1.236 -0.887,0.601 -1.633,1.348 -2.236,2.233 -0.599,0.888 -1.021,1.853 -1.258,2.901 -0.239,1.045 -0.356,2.106 -0.356,3.183 v 6.181 c 0,1.078 0.117,2.137 0.356,3.185 0.238,1.046 0.666,2.012 1.284,2.896 0.617,0.891 1.378,1.627 2.282,2.215 0.902,0.584 1.876,0.997 2.922,1.233 1.045,0.238 2.107,0.354 3.186,0.354 1.17,0 2.318,-0.125 3.444,-0.378 1.125,-0.254 2.163,-0.719 3.114,-1.402 0.95,-0.681 1.703,-1.546 2.259,-2.59 0.554,-1.046 0.862,-2.14 0.926,-3.279 h -5.514 c -0.031,0.634 -0.278,1.194 -0.737,1.686 -0.459,0.491 -0.999,0.816 -1.617,0.975 -0.616,0.157 -1.244,0.237 -1.875,0.237 -0.635,0 -1.262,-0.117 -1.879,-0.357 -0.617,-0.236 -1.134,-0.616 -1.545,-1.139 -0.411,-0.524 -0.696,-1.103 -0.855,-1.735 -0.158,-0.636 -0.236,-1.269 -0.236,-1.9 v -0.714 h 14.354 v -5.467 c 0,-1.076 -0.119,-2.138 -0.356,-3.183 -0.239,-1.049 -0.659,-2.014 -1.26,-2.902 z m -3.898,6.797 h -8.841 v -0.713 c 0,-0.633 0.078,-1.265 0.236,-1.9 0.159,-0.633 0.436,-1.214 0.832,-1.735 0.397,-0.521 0.896,-0.903 1.499,-1.142 0.602,-0.236 1.22,-0.354 1.854,-0.354 0.633,0 1.259,0.118 1.878,0.354 0.617,0.238 1.125,0.62 1.52,1.142 0.396,0.521 0.667,1.103 0.81,1.735 0.141,0.636 0.214,1.268 0.214,1.9 v 0.713 z"
+ id="path146" />
+ <path
+ fill="#ffffff"
+ d="m 277.574,497.705 c -0.253,-0.728 -0.618,-1.382 -1.092,-1.963 -0.476,-0.579 -1.07,-1.008 -1.782,-1.282 -0.714,-0.272 -1.436,-0.413 -2.164,-0.413 -0.792,0 -1.545,0.155 -2.257,0.461 -0.714,0.308 -1.316,0.768 -1.807,1.381 -0.492,0.615 -0.903,1.266 -1.236,1.961 -0.333,0.692 -0.595,1.427 -0.783,2.203 v -5.62 h -5.562 V 520.1 h 5.562 v -13.608 c 0,-0.645 0.023,-1.283 0.069,-1.91 0.05,-0.631 0.144,-1.254 0.286,-1.864 0.143,-0.613 0.349,-1.211 0.617,-1.792 0.268,-0.583 0.667,-1.067 1.189,-1.454 0.522,-0.388 1.1,-0.58 1.735,-0.58 0.506,0 0.964,0.162 1.379,0.484 0.41,0.323 0.68,0.742 0.807,1.257 0.127,0.517 0.192,1.035 0.192,1.552 h 5.512 c 0,-0.774 -0.047,-1.534 -0.142,-2.275 -0.094,-0.747 -0.269,-1.479 -0.523,-2.205 z"
+ id="path148" />
+ <path
+ fill="#ffffff"
+ d="m 298.518,510.519 v 0.242 c 0,0.513 -0.041,1.012 -0.118,1.491 -0.08,0.481 -0.215,0.956 -0.404,1.422 -0.19,0.467 -0.501,0.851 -0.927,1.155 -0.429,0.305 -0.879,0.458 -1.355,0.458 -0.603,0 -1.116,-0.227 -1.545,-0.675 -0.426,-0.448 -0.729,-0.954 -0.902,-1.515 -0.176,-0.563 -0.294,-1.141 -0.357,-1.734 -0.063,-0.594 -0.095,-1.182 -0.095,-1.76 V 499.01 h 6.607 v -4.816 h -6.607 v -9.869 h -5.511 v 9.869 h -4.517 v 4.816 h 4.517 v 10.593 c 0,1.029 0.077,2.048 0.237,3.06 0.157,1.011 0.45,1.981 0.877,2.912 0.429,0.932 1.007,1.768 1.735,2.503 0.731,0.742 1.584,1.262 2.567,1.566 0.983,0.302 1.979,0.455 2.994,0.455 1.141,0 2.264,-0.193 3.374,-0.575 1.108,-0.386 2.051,-1.034 2.829,-1.95 0.777,-0.915 1.333,-1.94 1.665,-3.083 0.332,-1.139 0.498,-2.287 0.498,-3.443 v -0.529 z"
+ id="path150" />
+ </g>
+ <path
+ d="m 116.243,520.1 h -5.665 L 98.982,486.074 h 6.793 c 0,0 8.667,25.864 8.744,26.357 0.078,-0.336 15.873,-18.381 25.964,-29.885 l -0.117,-14.877 c -8.294,5.25 -18.104,8.046 -27.945,7.882 -9.355,-0.14 -18.331,-2.824 -26.18,-7.795 l 0.064,22.986 c 0.532,9.483 3.899,18.481 9.745,26.005 4.613,5.945 10.643,10.687 17.496,13.76 7.698,-3.756 14.248,-9.505 18.991,-16.639 0.536,-0.808 1.042,-1.63 1.526,-2.464 0.036,-0.063 0.075,-0.125 0.11,-0.187 0.459,-0.801 0.892,-1.614 1.304,-2.437 0.049,-0.1 0.102,-0.198 0.151,-0.297 0.397,-0.807 0.768,-1.625 1.119,-2.45 0.05,-0.118 0.101,-0.235 0.15,-0.354 0.341,-0.822 0.659,-1.651 0.954,-2.489 0.043,-0.126 0.088,-0.25 0.131,-0.375 0.289,-0.843 0.555,-1.693 0.797,-2.55 0.034,-0.12 0.066,-0.238 0.099,-0.357 0.238,-0.872 0.456,-1.749 0.645,-2.634 0.021,-0.099 0.041,-0.198 0.061,-0.298 0.189,-0.909 0.355,-1.826 0.492,-2.747 0.009,-0.063 0.017,-0.125 0.025,-0.187 0.139,-0.962 0.252,-1.929 0.332,-2.899 z"
+ id="path154" />
+ <g
+ id="g158">
+ <path
+ fill="#ffffff"
+ d="m 462.842,473.178 h -6.737 c 0,0 -1.744,1.984 -4.44,5.056 l -0.146,-17.96 -3.021,2.252 c -3.035,2.256 -6.347,4.124 -9.831,5.576 v -7.483 h -3.82 v 8.882 c -4.589,1.468 -9.4,2.24 -14.229,2.24 -0.248,0 -0.486,0 -0.735,0 -4.301,-0.071 -8.513,-0.721 -12.553,-1.919 v -9.203 h -3.821 v 7.878 c -3.758,-1.482 -7.334,-3.454 -10.65,-5.904 l -3.054,-2.263 0.077,30.477 v 0.099 c 0.563,10.286 4.21,20.029 10.544,28.191 4.879,6.285 11.235,11.302 18.442,14.636 v 7.211 h 3.821 v -7.066 c 8.272,-4.062 15.323,-10.213 20.427,-17.897 5.198,-7.807 8.175,-16.89 8.641,-26.255 v -0.053 l -0.026,-3.195 z m -22.907,40.69 c -4.743,7.134 -11.293,12.883 -18.991,16.639 -6.854,-3.073 -12.884,-7.814 -17.497,-13.76 -5.846,-7.523 -9.212,-16.521 -9.744,-26.005 l -0.065,-22.986 c 7.85,4.971 16.825,7.655 26.18,7.795 9.84,0.164 19.65,-2.632 27.944,-7.882 l 0.117,14.877 c -10.092,11.504 -25.886,29.549 -25.964,29.885 -0.077,-0.493 -8.744,-26.357 -8.744,-26.357 h -6.793 l 11.597,34.026 h 5.665 l 24.191,-28.955 c -0.668,8.109 -3.387,15.932 -7.896,22.723 z"
+ id="path156" />
+ </g>
+ <path
+ d="m 423.64,520.1 h -5.665 l -11.597,-34.026 h 6.793 c 0,0 8.667,25.864 8.744,26.357 0.078,-0.336 15.872,-18.381 25.964,-29.885 l -0.117,-14.877 c -8.294,5.25 -18.104,8.046 -27.944,7.882 -9.355,-0.14 -18.331,-2.824 -26.18,-7.795 l 0.065,22.986 c 0.531,9.483 3.898,18.481 9.744,26.005 4.613,5.945 10.643,10.687 17.497,13.76 7.698,-3.756 14.248,-9.505 18.991,-16.639 0.536,-0.808 1.042,-1.63 1.526,-2.464 0.037,-0.063 0.075,-0.125 0.111,-0.187 0.459,-0.801 0.892,-1.614 1.305,-2.437 0.049,-0.1 0.101,-0.198 0.15,-0.297 0.397,-0.807 0.769,-1.625 1.119,-2.45 0.051,-0.118 0.102,-0.235 0.151,-0.354 0.341,-0.822 0.658,-1.651 0.953,-2.489 0.044,-0.126 0.088,-0.25 0.131,-0.375 0.29,-0.843 0.555,-1.693 0.797,-2.55 0.034,-0.12 0.066,-0.238 0.099,-0.357 0.239,-0.872 0.455,-1.749 0.645,-2.634 0.022,-0.099 0.041,-0.198 0.061,-0.298 0.189,-0.909 0.355,-1.826 0.492,-2.747 0.01,-0.063 0.017,-0.125 0.025,-0.187 0.139,-0.962 0.252,-1.929 0.332,-2.899 z"
+ id="path160" />
+ <g
+ id="g180">
+ <path
+ fill="#ffffff"
+ d="m 155.445,588.192 h -6.736 c 0,0 -1.744,1.984 -4.44,5.056 l -0.146,-17.96 -3.021,2.252 c -3.036,2.256 -6.347,4.124 -9.831,5.576 v -7.483 h -3.821 v 8.882 c -4.589,1.468 -9.4,2.24 -14.229,2.24 -0.249,0 -0.487,0 -0.735,0 -4.301,-0.071 -8.513,-0.721 -12.553,-1.919 v -9.203 h -3.82 v 7.878 c -3.758,-1.482 -7.335,-3.454 -10.65,-5.904 l -3.054,-2.263 0.076,30.477 v 0.099 c 0.563,10.286 4.211,20.029 10.545,28.191 4.879,6.285 11.234,11.302 18.442,14.636 v 7.211 h 3.821 v -7.066 c 8.272,-4.062 15.323,-10.213 20.427,-17.897 5.198,-7.807 8.175,-16.89 8.641,-26.255 v -0.053 l -0.025,-3.195 z m -22.906,40.691 c -4.743,7.134 -11.293,12.883 -18.991,16.639 -6.853,-3.073 -12.883,-7.814 -17.496,-13.76 -5.846,-7.523 -9.213,-16.521 -9.745,-26.005 l -0.064,-22.986 c 7.849,4.971 16.824,7.655 26.18,7.795 9.841,0.164 19.651,-2.632 27.945,-7.882 l 0.117,14.877 c -10.091,11.504 -25.886,29.549 -25.964,29.885 -0.077,-0.493 -8.744,-26.357 -8.744,-26.357 h -6.793 l 11.596,34.026 h 5.665 l 24.191,-28.955 c -0.67,8.109 -3.39,15.932 -7.897,22.723 z"
+ id="path162" />
+ <path
+ fill="#ffffff"
+ d="m 164.218,612.966 c -0.602,-0.886 -1.348,-1.633 -2.234,-2.233 -0.887,-0.603 -1.853,-1.013 -2.899,-1.236 -1.046,-0.219 -2.107,-0.333 -3.185,-0.333 -1.046,0 -2.1,0.114 -3.161,0.333 -1.062,0.224 -2.036,0.634 -2.922,1.236 -0.888,0.601 -1.633,1.348 -2.235,2.233 -0.602,0.888 -1.021,1.853 -1.259,2.901 -0.238,1.045 -0.357,2.106 -0.357,3.183 v 6.181 c 0,1.078 0.119,2.137 0.357,3.185 0.237,1.046 0.666,2.012 1.282,2.896 0.618,0.891 1.378,1.627 2.282,2.215 0.904,0.584 1.878,0.997 2.923,1.233 1.045,0.238 2.108,0.354 3.186,0.354 1.171,0 2.32,-0.125 3.446,-0.378 1.125,-0.254 2.162,-0.719 3.113,-1.402 0.951,-0.681 1.703,-1.546 2.258,-2.59 0.554,-1.046 0.863,-2.14 0.927,-3.279 h -5.513 c -0.032,0.634 -0.277,1.194 -0.737,1.686 -0.458,0.491 -0.998,0.816 -1.614,0.975 -0.619,0.157 -1.246,0.237 -1.879,0.237 -0.635,0 -1.259,-0.117 -1.878,-0.357 -0.617,-0.236 -1.133,-0.616 -1.544,-1.139 -0.413,-0.524 -0.698,-1.103 -0.855,-1.735 -0.16,-0.636 -0.238,-1.269 -0.238,-1.9 v -0.714 h 14.356 v -5.467 c 0,-1.076 -0.12,-2.138 -0.357,-3.183 -0.242,-1.05 -0.662,-2.014 -1.263,-2.902 z m -3.898,6.797 h -8.841 v -0.713 c 0,-0.633 0.079,-1.265 0.238,-1.9 0.158,-0.633 0.435,-1.214 0.832,-1.735 0.395,-0.521 0.895,-0.903 1.497,-1.142 0.601,-0.236 1.219,-0.354 1.854,-0.354 0.634,0 1.26,0.118 1.878,0.354 0.618,0.238 1.124,0.62 1.521,1.142 0.396,0.521 0.665,1.103 0.809,1.735 0.141,0.636 0.213,1.268 0.213,1.9 v 0.713 z"
+ id="path164" />
+ <path
+ fill="#ffffff"
+ d="m 187.062,612.815 c -0.253,-0.724 -0.617,-1.374 -1.093,-1.954 -0.475,-0.576 -1.068,-1.003 -1.782,-1.277 -0.713,-0.271 -1.434,-0.409 -2.163,-0.409 -0.792,0 -1.544,0.152 -2.257,0.459 -0.713,0.307 -1.315,0.763 -1.806,1.373 -0.492,0.612 -0.903,1.262 -1.235,1.953 -0.333,0.689 -0.595,1.421 -0.785,2.194 v -5.596 h -5.561 v 25.556 h 5.561 v -13.549 c 0,-0.643 0.023,-1.278 0.071,-1.902 0.049,-0.627 0.144,-1.249 0.285,-1.858 0.144,-0.609 0.35,-1.204 0.618,-1.783 0.269,-0.58 0.666,-1.062 1.189,-1.447 0.522,-0.386 1.1,-0.577 1.735,-0.577 0.506,0 0.965,0.162 1.378,0.481 0.411,0.323 0.681,0.739 0.808,1.253 0.127,0.514 0.191,1.029 0.191,1.543 h 5.512 c 0,-0.77 -0.046,-1.525 -0.142,-2.266 -0.096,-0.74 -0.271,-1.47 -0.524,-2.194 z"
+ id="path166" />
+ <polygon
+ fill="#ffffff"
+ points="192.938,614.061 198.165,614.061 198.165,630.218 192.271,630.218 192.271,635.114 208.908,635.114 208.908,630.218 203.68,630.218 203.68,609.163 192.938,609.163 "
+ id="polygon168" />
+ <path
+ fill="#ffffff"
+ d="m 198.617,604.824 c 0.648,0.288 1.307,0.431 1.973,0.431 0.696,0 1.362,-0.143 1.995,-0.431 0.634,-0.281 1.095,-0.75 1.379,-1.399 0.285,-0.647 0.427,-1.307 0.427,-1.972 0,-0.698 -0.142,-1.363 -0.427,-1.998 -0.285,-0.633 -0.745,-1.092 -1.379,-1.378 -0.633,-0.285 -1.299,-0.427 -1.995,-0.427 -0.666,0 -1.325,0.142 -1.973,0.427 -0.652,0.286 -1.117,0.745 -1.402,1.378 -0.285,0.635 -0.428,1.3 -0.428,1.998 0,0.665 0.143,1.324 0.428,1.972 0.285,0.649 0.75,1.118 1.402,1.399 z"
+ id="path170" />
+ <path
+ fill="#ffffff"
+ d="m 229.106,611.424 c -0.934,-0.84 -2.012,-1.43 -3.232,-1.762 -1.22,-0.331 -2.465,-0.499 -3.73,-0.499 -1.046,0 -2.085,0.12 -3.114,0.355 -1.031,0.242 -1.989,0.659 -2.876,1.261 -0.887,0.603 -1.622,1.349 -2.21,2.234 -0.585,0.888 -0.998,1.853 -1.236,2.899 -0.238,1.045 -0.356,2.091 -0.356,3.137 v 6.181 c 0,1.044 0.119,2.09 0.356,3.136 0.239,1.048 0.651,2.016 1.236,2.899 0.588,0.889 1.323,1.634 2.21,2.234 0.887,0.603 1.846,1.023 2.876,1.26 1.029,0.238 2.067,0.354 3.114,0.354 1.266,0 2.51,-0.166 3.73,-0.498 1.221,-0.333 2.298,-0.916 3.232,-1.759 0.934,-0.836 1.638,-1.853 2.115,-3.041 0.477,-1.188 0.713,-2.399 0.713,-3.638 v -0.094 h -5.514 v 0.048 c 0,0.761 -0.174,1.488 -0.521,2.188 -0.349,0.696 -0.873,1.21 -1.569,1.545 -0.698,0.331 -1.426,0.497 -2.187,0.497 -0.603,0 -1.204,-0.125 -1.807,-0.381 -0.602,-0.252 -1.093,-0.642 -1.475,-1.164 -0.38,-0.521 -0.639,-1.093 -0.783,-1.709 -0.143,-0.619 -0.214,-1.246 -0.214,-1.878 v -6.181 c 0,-0.633 0.071,-1.261 0.214,-1.878 0.144,-0.617 0.403,-1.187 0.783,-1.71 0.381,-0.523 0.873,-0.91 1.475,-1.166 0.603,-0.25 1.204,-0.378 1.807,-0.378 0.761,0 1.489,0.166 2.187,0.498 0.696,0.334 1.22,0.848 1.569,1.543 0.347,0.698 0.521,1.429 0.521,2.188 v 0.048 h 5.514 v -0.095 c 0,-1.235 -0.236,-2.449 -0.713,-3.639 -0.477,-1.184 -1.181,-2.197 -2.115,-3.035 z"
+ id="path172" />
+ <path
+ fill="#ffffff"
+ d="m 254.732,612.966 c -0.603,-0.886 -1.35,-1.633 -2.235,-2.233 -0.887,-0.603 -1.852,-1.013 -2.9,-1.236 -1.044,-0.219 -2.105,-0.333 -3.184,-0.333 -1.045,0 -2.101,0.114 -3.162,0.333 -1.063,0.224 -2.036,0.634 -2.922,1.236 -0.887,0.601 -1.633,1.348 -2.236,2.233 -0.599,0.888 -1.021,1.853 -1.258,2.901 -0.239,1.045 -0.356,2.106 -0.356,3.183 v 6.181 c 0,1.078 0.117,2.137 0.356,3.185 0.238,1.046 0.666,2.012 1.284,2.896 0.617,0.891 1.378,1.627 2.282,2.215 0.902,0.584 1.876,0.997 2.922,1.233 1.045,0.238 2.107,0.354 3.186,0.354 1.17,0 2.318,-0.125 3.444,-0.378 1.125,-0.254 2.163,-0.719 3.114,-1.402 0.95,-0.681 1.703,-1.546 2.259,-2.59 0.554,-1.046 0.862,-2.14 0.926,-3.279 h -5.514 c -0.031,0.634 -0.278,1.194 -0.737,1.686 -0.459,0.491 -0.999,0.816 -1.617,0.975 -0.616,0.157 -1.244,0.237 -1.875,0.237 -0.635,0 -1.262,-0.117 -1.879,-0.357 -0.617,-0.236 -1.134,-0.616 -1.545,-1.139 -0.411,-0.524 -0.696,-1.103 -0.855,-1.735 -0.158,-0.636 -0.236,-1.269 -0.236,-1.9 v -0.714 h 14.354 v -5.467 c 0,-1.076 -0.119,-2.138 -0.356,-3.183 -0.239,-1.05 -0.659,-2.014 -1.26,-2.902 z m -3.898,6.797 h -8.841 v -0.713 c 0,-0.633 0.078,-1.265 0.236,-1.9 0.159,-0.633 0.436,-1.214 0.832,-1.735 0.397,-0.521 0.896,-0.903 1.499,-1.142 0.602,-0.236 1.22,-0.354 1.854,-0.354 0.633,0 1.259,0.118 1.878,0.354 0.617,0.238 1.125,0.62 1.52,1.142 0.396,0.521 0.667,1.103 0.81,1.735 0.141,0.636 0.214,1.268 0.214,1.9 v 0.713 z"
+ id="path174" />
+ <path
+ fill="#ffffff"
+ d="m 277.574,612.72 c -0.253,-0.728 -0.618,-1.382 -1.092,-1.963 -0.476,-0.579 -1.07,-1.008 -1.782,-1.282 -0.714,-0.272 -1.436,-0.413 -2.164,-0.413 -0.792,0 -1.545,0.155 -2.257,0.461 -0.714,0.308 -1.316,0.768 -1.807,1.381 -0.492,0.615 -0.903,1.266 -1.236,1.961 -0.333,0.692 -0.595,1.427 -0.783,2.203 v -5.62 h -5.562 v 25.667 h 5.562 v -13.608 c 0,-0.645 0.023,-1.283 0.069,-1.91 0.05,-0.631 0.144,-1.254 0.286,-1.864 0.143,-0.613 0.349,-1.211 0.617,-1.792 0.268,-0.583 0.667,-1.067 1.189,-1.454 0.522,-0.388 1.1,-0.58 1.735,-0.58 0.506,0 0.964,0.162 1.379,0.484 0.41,0.323 0.68,0.742 0.807,1.257 0.127,0.517 0.192,1.035 0.192,1.552 h 5.512 c 0,-0.774 -0.047,-1.534 -0.142,-2.275 -0.094,-0.747 -0.269,-1.48 -0.523,-2.205 z"
+ id="path176" />
+ <path
+ fill="#ffffff"
+ d="m 298.518,625.533 v 0.242 c 0,0.513 -0.041,1.012 -0.118,1.491 -0.08,0.481 -0.215,0.956 -0.404,1.422 -0.19,0.467 -0.501,0.851 -0.927,1.155 -0.429,0.305 -0.879,0.458 -1.355,0.458 -0.603,0 -1.116,-0.227 -1.545,-0.675 -0.426,-0.448 -0.729,-0.954 -0.902,-1.515 -0.176,-0.563 -0.294,-1.141 -0.357,-1.734 -0.063,-0.594 -0.095,-1.182 -0.095,-1.76 v -10.593 h 6.607 v -4.816 h -6.607 v -9.869 h -5.511 v 9.869 h -4.517 v 4.816 h 4.517 v 10.593 c 0,1.029 0.077,2.048 0.237,3.06 0.157,1.011 0.45,1.981 0.877,2.912 0.429,0.932 1.007,1.768 1.735,2.503 0.731,0.742 1.584,1.262 2.567,1.566 0.983,0.302 1.979,0.455 2.994,0.455 1.141,0 2.264,-0.193 3.374,-0.575 1.108,-0.386 2.051,-1.034 2.829,-1.95 0.777,-0.915 1.333,-1.94 1.665,-3.083 0.332,-1.139 0.498,-2.287 0.498,-3.443 v -0.529 z"
+ id="path178" />
+ </g>
+ <path
+ fill="#9acfb2"
+ d="m 116.243,635.114 h -5.665 L 98.982,601.088 h 6.793 c 0,0 8.667,25.864 8.744,26.357 0.078,-0.336 15.873,-18.381 25.964,-29.885 l -0.117,-14.877 c -8.294,5.25 -18.104,8.046 -27.945,7.882 -9.355,-0.14 -18.331,-2.824 -26.18,-7.795 l 0.064,22.986 c 0.532,9.483 3.899,18.481 9.745,26.005 4.613,5.945 10.643,10.687 17.496,13.76 7.698,-3.756 14.248,-9.505 18.991,-16.639 0.536,-0.808 1.042,-1.63 1.526,-2.464 0.036,-0.063 0.075,-0.125 0.11,-0.187 0.459,-0.801 0.892,-1.614 1.304,-2.437 0.049,-0.1 0.102,-0.198 0.151,-0.297 0.397,-0.807 0.768,-1.625 1.119,-2.45 0.05,-0.118 0.101,-0.235 0.15,-0.354 0.341,-0.822 0.659,-1.651 0.954,-2.489 0.043,-0.126 0.088,-0.25 0.131,-0.375 0.289,-0.843 0.555,-1.693 0.797,-2.55 0.034,-0.12 0.066,-0.238 0.099,-0.357 0.238,-0.872 0.456,-1.749 0.645,-2.634 0.021,-0.099 0.041,-0.198 0.061,-0.298 0.189,-0.909 0.355,-1.826 0.492,-2.747 0.009,-0.063 0.017,-0.125 0.025,-0.187 0.139,-0.962 0.252,-1.929 0.332,-2.899 z"
+ id="path182" />
+ <g
+ id="g186">
+ <path
+ fill="#ffffff"
+ d="m 462.842,588.192 h -6.737 c 0,0 -1.744,1.984 -4.44,5.056 l -0.146,-17.96 -3.021,2.252 c -3.035,2.256 -6.347,4.124 -9.831,5.576 v -7.483 h -3.82 v 8.882 c -4.589,1.468 -9.4,2.24 -14.229,2.24 -0.248,0 -0.486,0 -0.735,0 -4.301,-0.071 -8.513,-0.721 -12.553,-1.919 v -9.203 h -3.821 v 7.878 c -3.758,-1.482 -7.334,-3.454 -10.65,-5.904 l -3.054,-2.263 0.077,30.477 v 0.099 c 0.563,10.286 4.21,20.029 10.544,28.191 4.879,6.285 11.235,11.302 18.442,14.636 v 7.211 h 3.821 v -7.066 c 8.272,-4.062 15.323,-10.213 20.427,-17.897 5.198,-7.807 8.175,-16.89 8.641,-26.255 v -0.053 l -0.026,-3.195 z m -22.907,40.691 c -4.743,7.134 -11.293,12.883 -18.991,16.639 -6.854,-3.073 -12.884,-7.814 -17.497,-13.76 -5.846,-7.523 -9.212,-16.521 -9.744,-26.005 l -0.065,-22.986 c 7.85,4.971 16.825,7.655 26.18,7.795 9.84,0.164 19.65,-2.632 27.944,-7.882 l 0.117,14.877 c -10.092,11.504 -25.886,29.549 -25.964,29.885 -0.077,-0.493 -8.744,-26.357 -8.744,-26.357 h -6.793 l 11.597,34.026 h 5.665 l 24.191,-28.955 c -0.668,8.109 -3.387,15.932 -7.896,22.723 z"
+ id="path184" />
+ </g>
+ <path
+ fill="#9acfb2"
+ d="m 423.64,635.114 h -5.665 l -11.597,-34.026 h 6.793 c 0,0 8.667,25.864 8.744,26.357 0.078,-0.336 15.872,-18.381 25.964,-29.885 l -0.117,-14.877 c -8.294,5.25 -18.104,8.046 -27.944,7.882 -9.355,-0.14 -18.331,-2.824 -26.18,-7.795 l 0.065,22.986 c 0.531,9.483 3.898,18.481 9.744,26.005 4.613,5.945 10.643,10.687 17.497,13.76 7.698,-3.756 14.248,-9.505 18.991,-16.639 0.536,-0.808 1.042,-1.63 1.526,-2.464 0.037,-0.063 0.075,-0.125 0.111,-0.187 0.459,-0.801 0.892,-1.614 1.305,-2.437 0.049,-0.1 0.101,-0.198 0.15,-0.297 0.397,-0.807 0.769,-1.625 1.119,-2.45 0.051,-0.118 0.102,-0.235 0.151,-0.354 0.341,-0.822 0.658,-1.651 0.953,-2.489 0.044,-0.126 0.088,-0.25 0.131,-0.375 0.29,-0.843 0.555,-1.693 0.797,-2.55 0.034,-0.12 0.066,-0.238 0.099,-0.357 0.239,-0.872 0.455,-1.749 0.645,-2.634 0.022,-0.099 0.041,-0.198 0.061,-0.298 0.189,-0.909 0.355,-1.826 0.492,-2.747 0.01,-0.063 0.017,-0.125 0.025,-0.187 0.139,-0.962 0.252,-1.929 0.332,-2.899 z"
+ id="path188" />
+ <g
+ id="g208">
+ <path
+ fill="#2a3e40"
+ d="m 168.364,746.698 h -7.912 c 0,0 -2.048,2.33 -5.214,5.936 l -0.171,-21.091 -3.548,2.644 c -3.565,2.65 -7.454,4.844 -11.545,6.55 v -8.789 h -4.487 v 10.432 c -5.39,1.724 -11.039,2.63 -16.71,2.63 -0.292,0 -0.572,0 -0.864,0 -5.051,-0.084 -9.998,-0.847 -14.742,-2.252 v -10.81 h -4.487 v 9.252 c -4.413,-1.741 -8.613,-4.057 -12.508,-6.935 l -3.586,-2.656 0.09,35.791 v 0.116 c 0.661,12.078 4.945,23.521 12.384,33.107 5.73,7.381 13.194,13.271 21.659,17.188 v 8.469 h 4.487 v -8.298 c 9.715,-4.77 17.995,-11.995 23.99,-21.021 6.104,-9.168 9.6,-19.834 10.147,-30.833 v -0.063 l -0.03,-3.751 z m -26.902,47.786 c -5.57,8.378 -13.263,15.131 -22.303,19.541 -8.049,-3.609 -15.13,-9.179 -20.547,-16.161 -6.866,-8.835 -10.82,-19.401 -11.444,-30.539 l -0.076,-26.996 c 9.218,5.838 19.759,8.99 30.746,9.154 11.557,0.193 23.078,-3.089 32.818,-9.256 l 0.138,17.473 c -11.852,13.51 -30.401,34.701 -30.492,35.096 -0.09,-0.579 -10.269,-30.954 -10.269,-30.954 h -7.979 l 13.619,39.961 h 6.653 l 28.411,-34.005 c -0.787,9.524 -3.98,18.711 -9.275,26.686 z"
+ id="path190" />
+ <path
+ fill="#2a3e40"
+ d="m 178.667,775.792 c -0.708,-1.04 -1.583,-1.918 -2.625,-2.623 -1.042,-0.708 -2.176,-1.191 -3.404,-1.453 -1.229,-0.256 -2.476,-0.39 -3.741,-0.39 -1.229,0 -2.467,0.134 -3.712,0.39 -1.247,0.262 -2.391,0.745 -3.432,1.453 -1.042,0.705 -1.917,1.583 -2.625,2.623 -0.707,1.041 -1.2,2.175 -1.479,3.406 -0.28,1.227 -0.419,2.475 -0.419,3.738 v 7.258 c 0,1.266 0.14,2.51 0.419,3.74 0.279,1.229 0.781,2.363 1.506,3.402 0.726,1.047 1.618,1.91 2.679,2.6 1.062,0.688 2.206,1.172 3.433,1.449 1.228,0.279 2.475,0.417 3.74,0.417 1.376,0 2.726,-0.147 4.047,-0.444 1.321,-0.297 2.54,-0.844 3.656,-1.646 1.116,-0.801 2,-1.815 2.652,-3.043 0.651,-1.229 1.013,-2.511 1.088,-3.85 h -6.475 c -0.037,0.744 -0.326,1.402 -0.866,1.979 -0.539,0.577 -1.171,0.96 -1.896,1.145 -0.726,0.186 -1.463,0.279 -2.207,0.279 -0.745,0 -1.479,-0.138 -2.205,-0.42 -0.726,-0.278 -1.332,-0.726 -1.814,-1.339 -0.484,-0.615 -0.82,-1.293 -1.004,-2.037 -0.188,-0.745 -0.28,-1.49 -0.28,-2.232 v -0.838 h 16.859 v -6.42 c 0,-1.264 -0.141,-2.512 -0.419,-3.738 -0.277,-1.231 -0.77,-2.365 -1.476,-3.406 z m -4.579,7.98 h -10.383 v -0.836 c 0,-0.744 0.092,-1.486 0.28,-2.232 0.185,-0.742 0.51,-1.424 0.977,-2.037 0.463,-0.613 1.051,-1.061 1.758,-1.341 0.706,-0.278 1.432,-0.417 2.177,-0.417 0.744,0 1.479,0.139 2.206,0.417 0.725,0.28 1.32,0.728 1.786,1.341 0.465,0.613 0.781,1.295 0.949,2.037 0.166,0.746 0.25,1.488 0.25,2.232 z"
+ id="path192" />
+ <path
+ fill="#2a3e40"
+ d="m 205.495,775.615 c -0.298,-0.851 -0.725,-1.614 -1.284,-2.294 -0.559,-0.678 -1.255,-1.18 -2.093,-1.501 -0.837,-0.318 -1.684,-0.481 -2.54,-0.481 -0.93,0 -1.813,0.181 -2.651,0.539 -0.837,0.359 -1.544,0.896 -2.121,1.613 -0.578,0.72 -1.061,1.48 -1.451,2.294 -0.392,0.81 -0.699,1.667 -0.922,2.577 v -6.572 h -6.53 v 30.013 h 6.53 v -15.912 c 0,-0.755 0.028,-1.5 0.083,-2.234 0.058,-0.737 0.169,-1.466 0.335,-2.181 0.169,-0.716 0.41,-1.415 0.726,-2.096 0.316,-0.681 0.782,-1.246 1.396,-1.699 0.613,-0.453 1.292,-0.678 2.038,-0.678 0.595,0 1.134,0.189 1.619,0.565 0.483,0.379 0.8,0.868 0.948,1.47 0.149,0.605 0.224,1.209 0.224,1.814 h 6.474 c 0,-0.904 -0.055,-1.793 -0.167,-2.661 -0.111,-0.87 -0.317,-1.727 -0.614,-2.576 z"
+ id="path194" />
+ <polygon
+ fill="#2a3e40"
+ points="212.395,777.077 218.534,777.077 218.534,796.052 211.613,796.052 211.613,801.803 231.151,801.803 231.151,796.052 225.011,796.052 225.011,771.326 212.395,771.326 "
+ id="polygon196" />
+ <path
+ fill="#2a3e40"
+ d="m 219.065,766.23 c 0.761,0.338 1.535,0.505 2.316,0.505 0.818,0 1.599,-0.167 2.343,-0.505 0.745,-0.331 1.286,-0.881 1.62,-1.644 0.334,-0.761 0.501,-1.535 0.501,-2.316 0,-0.82 -0.167,-1.601 -0.501,-2.346 -0.334,-0.744 -0.875,-1.283 -1.62,-1.619 -0.744,-0.334 -1.525,-0.501 -2.343,-0.501 -0.782,0 -1.556,0.167 -2.316,0.501 -0.766,0.336 -1.313,0.875 -1.647,1.619 -0.334,0.745 -0.503,1.525 -0.503,2.346 0,0.781 0.168,1.556 0.503,2.316 0.335,0.764 0.881,1.313 1.647,1.644 z"
+ id="path198" />
+ <path
+ fill="#2a3e40"
+ d="m 254.871,773.98 c -1.097,-0.987 -2.362,-1.679 -3.796,-2.069 -1.433,-0.389 -2.895,-0.585 -4.381,-0.585 -1.229,0 -2.448,0.141 -3.656,0.417 -1.211,0.283 -2.336,0.773 -3.378,1.48 -1.042,0.707 -1.905,1.582 -2.595,2.624 -0.688,1.043 -1.171,2.177 -1.452,3.405 -0.279,1.227 -0.418,2.455 -0.418,3.684 v 7.258 c 0,1.228 0.14,2.455 0.418,3.684 0.281,1.23 0.764,2.365 1.452,3.405 0.69,1.044 1.554,1.918 2.595,2.624 1.042,0.707 2.167,1.201 3.378,1.479 1.208,0.279 2.427,0.417 3.656,0.417 1.487,0 2.948,-0.194 4.381,-0.585 1.434,-0.391 2.699,-1.076 3.796,-2.065 1.097,-0.983 1.924,-2.175 2.484,-3.571 0.56,-1.396 0.837,-2.818 0.837,-4.271 V 791.2 h -6.475 v 0.057 c 0,0.894 -0.205,1.749 -0.613,2.568 -0.409,0.818 -1.025,1.423 -1.842,1.814 -0.82,0.391 -1.674,0.585 -2.568,0.585 -0.707,0 -1.414,-0.147 -2.121,-0.447 -0.707,-0.297 -1.285,-0.755 -1.732,-1.368 -0.447,-0.611 -0.751,-1.282 -0.919,-2.008 -0.168,-0.725 -0.251,-1.463 -0.251,-2.205 v -7.258 c 0,-0.744 0.083,-1.482 0.251,-2.205 0.168,-0.726 0.473,-1.395 0.919,-2.01 0.447,-0.613 1.025,-1.066 1.732,-1.368 0.707,-0.294 1.414,-0.444 2.121,-0.444 0.894,0 1.749,0.195 2.568,0.586 0.817,0.391 1.433,0.995 1.842,1.812 0.408,0.819 0.613,1.678 0.613,2.569 v 0.058 h 6.475 v -0.112 c 0,-1.451 -0.277,-2.876 -0.837,-4.273 -0.56,-1.396 -1.387,-2.587 -2.484,-3.571 z"
+ id="path200" />
+ <path
+ fill="#2a3e40"
+ d="m 284.967,775.792 c -0.708,-1.04 -1.585,-1.918 -2.625,-2.623 -1.042,-0.708 -2.175,-1.191 -3.405,-1.453 -1.227,-0.256 -2.473,-0.39 -3.74,-0.39 -1.228,0 -2.467,0.134 -3.713,0.39 -1.248,0.262 -2.391,0.745 -3.432,1.453 -1.042,0.705 -1.918,1.583 -2.626,2.623 -0.704,1.041 -1.198,2.175 -1.477,3.406 -0.281,1.227 -0.418,2.475 -0.418,3.738 v 7.258 c 0,1.266 0.138,2.51 0.418,3.74 0.279,1.229 0.782,2.363 1.508,3.402 0.725,1.047 1.618,1.91 2.681,2.6 1.059,0.688 2.204,1.172 3.431,1.449 1.227,0.279 2.475,0.417 3.742,0.417 1.374,0 2.723,-0.147 4.045,-0.444 1.321,-0.297 2.54,-0.844 3.656,-1.646 1.116,-0.801 2,-1.815 2.653,-3.043 0.65,-1.229 1.012,-2.511 1.088,-3.85 h -6.476 c -0.037,0.744 -0.327,1.402 -0.866,1.979 -0.54,0.577 -1.172,0.96 -1.898,1.145 -0.724,0.186 -1.461,0.279 -2.203,0.279 -0.745,0 -1.481,-0.138 -2.207,-0.42 -0.724,-0.278 -1.332,-0.726 -1.814,-1.339 -0.483,-0.615 -0.818,-1.293 -1.005,-2.037 -0.186,-0.745 -0.278,-1.49 -0.278,-2.232 v -0.838 h 16.857 v -6.42 c 0,-1.264 -0.139,-2.512 -0.418,-3.738 -0.279,-1.231 -0.772,-2.365 -1.478,-3.406 z m -4.578,7.98 h -10.383 v -0.836 c 0,-0.744 0.092,-1.486 0.278,-2.232 0.187,-0.742 0.512,-1.424 0.977,-2.037 0.466,-0.613 1.053,-1.061 1.76,-1.341 0.707,-0.278 1.432,-0.417 2.177,-0.417 0.743,0 1.479,0.139 2.206,0.417 0.724,0.28 1.32,0.728 1.785,1.341 0.466,0.613 0.783,1.295 0.951,2.037 0.165,0.746 0.251,1.488 0.251,2.232 v 0.836 z"
+ id="path202" />
+ <path
+ fill="#2a3e40"
+ d="m 311.792,775.502 c -0.298,-0.854 -0.726,-1.622 -1.283,-2.305 -0.56,-0.681 -1.257,-1.185 -2.092,-1.507 -0.839,-0.32 -1.687,-0.483 -2.542,-0.483 -0.931,0 -1.815,0.181 -2.65,0.542 -0.839,0.36 -1.546,0.9 -2.122,1.619 -0.578,0.723 -1.061,1.487 -1.452,2.305 -0.391,0.813 -0.699,1.674 -0.919,2.587 v -6.601 H 292.2 v 30.144 h 6.532 v -15.981 c 0,-0.758 0.027,-1.507 0.081,-2.244 0.059,-0.74 0.168,-1.472 0.336,-2.189 0.167,-0.72 0.409,-1.422 0.724,-2.105 0.315,-0.683 0.784,-1.252 1.397,-1.707 0.613,-0.453 1.292,-0.68 2.037,-0.68 0.594,0 1.133,0.19 1.62,0.568 0.482,0.38 0.799,0.871 0.948,1.476 0.149,0.607 0.226,1.216 0.226,1.822 h 6.473 c 0,-0.909 -0.055,-1.801 -0.167,-2.673 -0.111,-0.875 -0.316,-1.736 -0.615,-2.588 z"
+ id="path204" />
+ <path
+ fill="#2a3e40"
+ d="m 336.389,790.551 v 0.284 c 0,0.603 -0.047,1.188 -0.139,1.751 -0.094,0.565 -0.252,1.122 -0.474,1.671 -0.224,0.547 -0.59,0.998 -1.089,1.356 -0.504,0.358 -1.032,0.536 -1.592,0.536 -0.708,0 -1.311,-0.265 -1.815,-0.791 -0.501,-0.527 -0.856,-1.119 -1.06,-1.779 -0.207,-0.661 -0.345,-1.338 -0.42,-2.037 -0.074,-0.697 -0.112,-1.386 -0.112,-2.065 v -12.44 h 7.76 v -5.657 h -7.76 v -11.591 h -6.472 v 11.591 h -5.304 v 5.657 h 5.304 v 12.44 c 0,1.208 0.089,2.404 0.278,3.593 0.185,1.188 0.529,2.327 1.031,3.42 0.504,1.095 1.183,2.076 2.038,2.939 0.858,0.871 1.861,1.481 3.016,1.84 1.154,0.354 2.324,0.534 3.516,0.534 1.34,0 2.659,-0.228 3.962,-0.676 1.301,-0.453 2.409,-1.214 3.322,-2.292 0.912,-1.071 1.565,-2.277 1.955,-3.618 0.39,-1.338 0.585,-2.687 0.585,-4.044 v -0.622 z"
+ id="path206" />
+ </g>
+ <g
+ id="g212">
+ <path
+ fill="#2a3e40"
+ d="m 529.372,746.698 h -7.912 c 0,0 -2.048,2.33 -5.214,5.936 l -0.171,-21.091 -3.548,2.644 c -3.565,2.65 -7.454,4.844 -11.545,6.55 v -8.789 h -4.487 v 10.432 c -5.39,1.724 -11.039,2.63 -16.71,2.63 -0.292,0 -0.572,0 -0.864,0 -5.051,-0.084 -9.998,-0.847 -14.742,-2.252 v -10.81 h -4.487 v 9.252 c -4.413,-1.741 -8.613,-4.057 -12.508,-6.935 l -3.586,-2.656 0.089,35.792 v 0.116 c 0.661,12.078 4.945,23.521 12.384,33.107 5.73,7.381 13.194,13.271 21.659,17.188 v 8.469 h 4.487 v -8.298 c 9.715,-4.77 17.995,-11.995 23.99,-21.021 6.104,-9.168 9.6,-19.834 10.147,-30.833 v -0.063 l -0.03,-3.751 z m -26.902,47.786 c -5.57,8.378 -13.263,15.131 -22.303,19.541 -8.049,-3.609 -15.13,-9.179 -20.547,-16.161 -6.866,-8.835 -10.82,-19.401 -11.444,-30.539 L 448.1,740.329 c 9.218,5.838 19.759,8.99 30.746,9.154 11.557,0.193 23.078,-3.089 32.818,-9.256 L 511.8,757.7 c -11.852,13.51 -30.401,34.701 -30.492,35.096 -0.09,-0.579 -10.269,-30.954 -10.269,-30.954 h -7.979 l 13.619,39.961 h 6.653 l 28.411,-34.005 c -0.785,9.524 -3.979,18.711 -9.273,26.686 z"
+ id="path210" />
+ </g>
+ <text
+ transform="translate(19.1211,283.5981)"
+ id="text220"><tspan
+ x="0"
+ y="0"
+ font-family="MyriadPro-Regular"
+ font-size="12px"
+ id="tspan214">b/w</tspan><tspan
+ x="0"
+ y="302.39999"
+ font-family="MyriadPro-Regular"
+ font-size="12px"
+ id="tspan216">col/w</tspan><tspan
+ x="0"
+ y="417.60001"
+ font-family="MyriadPro-Regular"
+ font-size="12px"
+ id="tspan218">monochr.</tspan></text>
+ </g>
+</switch>
+
+</svg>
diff --git a/doc/common.org b/doc/common.org
new file mode 100644
index 0000000..aa27264
--- /dev/null
+++ b/doc/common.org
@@ -0,0 +1,15 @@
+#+author: Yann Herklotz
+#+email: git@ymhg.org
+
+#+macro: version 1.2.2
+#+macro: modified 2022-02-24
+
+#+macro: base_url https://vericert.ymhg.org
+
+#+macro: link src_emacs-lisp[:results raw]{(ymhg/link "$1" "$2")}
+
+#+macro: texinfo_head (eval (if (eq org-export-current-backend 'texinfo) "#+exclude_tags: noexport_texinfo" "#+exclude_tags: onlyexport_texinfo"))
+#+macro: latex_head (eval (if (eq org-export-current-backend 'latex) "#+exclude_tags: noexport_latex" "#+exclude_tags: onlyexport_latex"))
+#+macro: hugo_head (eval (if (eq org-export-current-backend 'hugo) "#+exclude_tags: noexport_hugo" "#+exclude_tags: onlyexport_hugo"))
+{{{texinfo_head}}}
+{{{latex_head}}}
diff --git a/doc/conf.py b/doc/conf.py
new file mode 100644
index 0000000..7000f7b
--- /dev/null
+++ b/doc/conf.py
@@ -0,0 +1,91 @@
+# Configuration file for the Sphinx documentation builder.
+#
+# This file only contains a selection of the most common options. For a full
+# list see the documentation:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+
+# -- Path setup --------------------------------------------------------------
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+# import os
+# import sys
+# sys.path.insert(0, os.path.abspath('.'))
+
+
+# -- Project information -----------------------------------------------------
+
+project = 'Vericert'
+copyright = '2022 Yann Herklotz, John Wickerson'
+author = 'Yann Herklotz, John Wickerson'
+
+# The full version, including alpha/beta/rc tags
+release = 'v1.2.2'
+
+
+# -- General configuration ---------------------------------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [ "alectryon.sphinx" ]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This pattern also affects html_static_path and html_extra_path.
+exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+
+pygments_style = "emacs"
+
+
+# -- Options for HTML output -------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+#
+html_theme = 'sphinx_rtd_theme'
+
+html_logo = "_static/images/vericert-main.svg"
+
+html_theme_options = {
+ 'style_nav_header_background': '#fff5db'
+}
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+html_css_files = [
+ 'css/custom.css',
+]
+
+
+# -- LaTeX configuration -----------------------------------------------------
+
+latex_engine = "xelatex"
+
+
+# -- Alectryon configuration -------------------------------------------------
+
+import alectryon.docutils
+alectryon.docutils.CACHE_DIRECTORY = "_build/alectryon/"
+alectryon.docutils.LONG_LINE_THRESHOLD = 80
+
+alectryon.docutils.AlectryonTransform.DRIVER_ARGS["sertop"] = [
+ "-R" "../src,vericert",
+ "-R" "../lib/CompCert/lib,compcert.lib",
+ "-R" "../lib/CompCert/common,compcert.common",
+ "-R" "../lib/CompCert/verilog,compcert.verilog",
+ "-R" "../lib/CompCert/backend,compcert.backend",
+ "-R" "../lib/CompCert/cfrontend,compcert.cfrontend",
+ "-R" "../lib/CompCert/driver,compcert.driver",
+ "-R" "../lib/CompCert/cparser,compcert.cparser",
+ "-R" "../lib/CompCert/flocq,Flocq",
+ "-R" "../lib/CompCert/MenhirLib,MenhirLib"
+]
diff --git a/doc/documentation.org b/doc/documentation.org
new file mode 100644
index 0000000..85bc8fd
--- /dev/null
+++ b/doc/documentation.org
@@ -0,0 +1,562 @@
+#+title: Vericert Manual
+#+subtitle: Release {{{version}}}
+#+author: Yann Herklotz
+#+email: git@ymhg.org
+#+language: en
+
+* Introduction
+:PROPERTIES:
+:EXPORT_FILE_NAME: _index
+:EXPORT_HUGO_SECTION: docs
+:CUSTOM_ID: docs
+:END:
+
+Vericert translates C code into a hardware description language called Verilog, which can then be
+synthesised into hardware, to be placed onto a field-programmable gate array (FPGA) or
+application-specific integrated circuit (ASIC).
+
+#+attr_html: :width "600px"
+#+caption: Current design of Vericert, where HTL is an intermediate language representing a finite state machine with data-path (FSMD) and Verilog is the target language.
+#+name: fig:design
+[[./images/toolflow.png]]
+
+The design shown in Figure [[fig:design]] shows how Vericert leverages an existing verified C compiler
+called [[https://compcert.org/compcert-C.html][CompCert]] to perform this translation.
+
+#+texinfo: @insertcopying
+
+* COPYING
+:PROPERTIES:
+:COPYING: t
+:END:
+
+Copyright (C) 2019-2022 Yann Herklotz.
+
+#+begin_quote
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.3
+or any later version published by the Free Software Foundation;
+with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+Texts. A copy of the license is included in the section entitled ``GNU
+Free Documentation License''.
+#+end_quote
+
+* Building Vericert
+:PROPERTIES:
+:EXPORT_FILE_NAME: building
+:EXPORT_HUGO_SECTION: docs
+:CUSTOM_ID: building
+:END:
+
+#+transclude: [[file:~/projects/vericert/README.org::#building][file:../README.org::#building]] :only-contents :exclude-elements "headline property-drawer"
+#+transclude: [[file:~/projects/vericert/README.org::#downloading-compcert][file:../README.org::#downloading-compcert]] :level 2
+#+transclude: [[file:~/projects/vericert/README.org::#setting-up-nix][file:../README.org::#setting-up-nix]] :level 2
+#+transclude: [[file:~/projects/vericert/README.org::#makefile-build][file:../README.org::#makefile-build]] :level 2
+
+** Testing
+
+To test out ~vericert~ you can try the following examples which are in the test folder using the
+following:
+
+#+begin_src shell
+./bin/vericert test/loop.c -o loop.v
+./bin/vericert test/conditional.c -o conditional.v
+./bin/vericert test/add.c -o add.v
+#+end_src
+
+Or by running the test suite using the following command:
+
+#+begin_src shell
+make test
+#+end_src
+
+* Using Vericert
+:PROPERTIES:
+:CUSTOM_ID: using-vericert
+:END:
+
+Vericert can be used to translate a subset of C into Verilog. As a simple example, consider the
+following C file (~main.c~):
+
+#+begin_src C
+void matrix_multiply(int first[2][2], int second[2][2], int multiply[2][2]) {
+ int sum = 0;
+ for (int c = 0; c < 2; c++) {
+ for (int d = 0; d < 2; d++) {
+ for (int k = 0; k < 2; k++) {
+ sum = sum + first[c][k]*second[k][d];
+ }
+ multiply[c][d] = sum;
+ sum = 0;
+ }
+ }
+}
+
+int main() {
+ int f[2][2] = {{1, 2}, {3, 4}};
+ int s[2][2] = {{5, 6}, {7, 8}};
+ int m[2][2] = {{0, 0}, {0, 0}};
+
+ matrix_multiply(f, s, m);
+ return m[1][1];
+}
+#+end_src
+
+It can be compiled using the following command, assuming that vericert is somewhere on the path.
+
+#+begin_src shell
+vericert main.c -o main.v
+#+end_src
+
+The Verilog file contains a top-level test-bench, which can be given to any Verilog simulator to
+simulate the hardware, which should give the same result as executing the C code. Using [[http://iverilog.icarus.com/][Icarus
+Verilog]] as an example:
+
+#+begin_src shell
+iverilog -o main_v main.v
+#+end_src
+
+When executing, it should therefore print the following:
+
+#+begin_src shell
+$ ./main_v
+finished: 50
+#+end_src
+
+This gives the same result as executing the C in the following way:
+
+#+begin_src shell
+$ gcc -o main_c main.c
+$ ./main_c
+$ echo $?
+50
+#+end_src
+
+** Man pages
+
+#+transclude: [[file:man.org][file:man.org]] :exclude-elements "keyword" :level 3
+
+* Unreleased Features
+:PROPERTIES:
+:EXPORT_FILE_NAME: unreleased
+:EXPORT_HUGO_SECTION: docs
+:CUSTOM_ID: unreleased-features
+:END:
+
+The following are unreleased features in Vericert that are currently being worked on and have not
+been completely proven correct yet. Currently this includes features such as:
+
+- [[#scheduling][scheduling]],
+- [[#operation-chaining][operation chaining]],
+- [[#if-conversion][if-conversion]], and
+- [[#functions][functions]].
+
+This page gives some preliminary information on how the features are implemented and how the proofs
+for the features are being done. Once these features are properly implemented, they will be added
+to the proper documentation.
+
+** Scheduling
+:PROPERTIES:
+:CUSTOM_ID: scheduling
+:END:
+#+cindex: scheduling
+
+Scheduling is an optimisation which is used to run various instructions in parallel that are
+independent to each other.
+
+** Operation Chaining
+:PROPERTIES:
+:CUSTOM_ID: operation-chaining
+:END:
+
+Operation chaining is an optimisation that can be added on to scheduling and allows for the
+sequential execution of instructions in a clock cycle, while executing other instructions in
+parallel in the same clock cycle.
+
+** If-conversion
+:PROPERTIES:
+:CUSTOM_ID: if-conversion
+:END:
+
+If-conversion is an optimisation which can turn code with simple control flow into a single block
+(called a hyper-block), using predicated instructions.
+
+** Functions
+:PROPERTIES:
+:CUSTOM_ID: functions
+:END:
+
+Functions are currently only inlined in Vericert, however, we are working on a proper interface to
+integrate function calls into the hardware.
+
+* Coq Style Guide
+ :PROPERTIES:
+ :CUSTOM_ID: coq-style-guide
+ :EXPORT_FILE_NAME: coq-style-guide
+ :EXPORT_HUGO_SECTION: docs
+ :END:
+
+This style guide was taken from [[https://github.com/project-oak/silveroak][Silveroak]], it outlines code style for Coq code in this
+repository. There are certainly other valid strategies and opinions on Coq code style; this is laid
+out purely in the name of consistency. For a visual example of the style, see the [[#example][example]] at the
+bottom of this file.
+
+** Code organization
+ :PROPERTIES:
+ :CUSTOM_ID: code-organization
+ :END:
+*** Legal banner
+ :PROPERTIES:
+ :CUSTOM_ID: legal-banner
+ :END:
+
+- Files should begin with a copyright/license banner, as shown in the example above.
+
+*** Import statements
+ :PROPERTIES:
+ :CUSTOM_ID: import-statements
+ :END:
+
+- =Require Import= statements should all go at the top of the file, followed by file-wide =Import=
+ statements.
+
+ - =Import=s often contain notations or typeclass instances that might override notations or
+ instances from another library, so it's nice to highlight them separately.
+
+- One =Require Import= statement per line; it's easier to scan that way.
+- =Require Import= statements should use "fully-qualified" names (e.g. =Require Import
+ Coq.ZArith.ZArith= instead of =Require Import ZArith=).
+
+ - Use the =Locate= command to find the fully-qualified name!
+
+- =Require Import='s should go in the following order:
+
+ 1. Standard library dependencies (start with =Coq.=)
+ 2. External dependencies (anything outside the current project)
+ 3. Same-project dependencies
+
+- =Require Import='s with the same root library (the name before the first =.=) should be grouped
+ together. Within each root-library group, they should be in alphabetical order (so =Coq.Lists.List=
+ before =Coq.ZArith.ZArith=).
+
+*** Notations and scopes
+ :PROPERTIES:
+ :CUSTOM_ID: notations-and-scopes
+ :END:
+
+- Any file-wide =Local Open Scope='s should come immediately after the =Import=s (see example).
+
+ - Always use =Local Open Scope=; just =Open Scope= will sneakily open the scope for those who import
+ your file.
+
+- Put notations in their own separate modules or files, so that those who import your file can
+ choose whether or not they want the notations.
+
+ - Conflicting notations can cause a lot of headache, so it comes in very handy to leave this
+ flexibility!
+
+** Formatting
+ :PROPERTIES:
+ :CUSTOM_ID: formatting
+ :END:
+*** Line length
+ :PROPERTIES:
+ :CUSTOM_ID: line-length
+ :END:
+
+- Maximum line length 80 characters.
+
+ - Many Coq IDE setups divide the screen in half vertically and use only half to display source
+ code, so more than 80 characters can be genuinely hard to read on a laptop.
+
+*** Whitespace and indentation
+ :PROPERTIES:
+ :CUSTOM_ID: whitespace-and-indentation
+ :END:
+
+- No trailing whitespace.
+
+- Spaces, not tabs.
+
+- Files should end with a newline.
+
+ - Many editors do this automatically on save.
+
+- Colons may be either "English-spaced", with no space before the colon and one space after (=x: nat=)
+ or "French-spaced", with one space before and after (=x : nat=).
+
+- Default indentation is 2 spaces.
+
+ - Keeping this small prevents complex proofs from being indented ridiculously far, and matches IDE
+ defaults.
+
+- Use 2-space indents if inserting a line break immediately after:
+
+ - =Proof.=
+ - =fun <...> =>=
+ - =forall <...>,=
+ - =exists <....>,=
+
+- The style for indenting arguments in function application depends on where you make a line
+ break. If you make the line break immediately after the function name, use a 2-space
+ indent. However, if you make it after one or more arguments, align the next line with the first
+ argument:
+
+ #+begin_src coq
+ (Z.pow
+ 1 2)
+ (Z.pow 1 2 3
+ 4 5 6)
+ #+end_src
+
+- =Inductive= cases should not be indented. Example:
+
+ #+begin_src coq
+ Inductive Foo : Type :=
+ | FooA : Foo
+ | FooB : Foo
+ .
+ #+end_src
+
+- =match= or =lazymatch= cases should line up with the "m" in =match= or "l" in =lazymatch=, as in the
+ following examples:
+
+ #+begin_src coq
+ match x with
+ | 3 => true
+ | _ => false
+ end.
+
+ lazymatch x with
+ | 3 => idtac
+ | _ => fail "Not equal to 3:" x
+ end.
+
+ repeat match goal with
+ | _ => progress subst
+ | _ => reflexivity
+ end.
+
+ do 2 lazymatch goal with
+ | |- context [eq] => idtac
+ end.
+ #+end_src
+
+** Definitions and Fixpoints
+ :PROPERTIES:
+ :CUSTOM_ID: definitions-and-fixpoints
+ :END:
+
+- It's okay to leave the return type of =Definition='s and =Fixpoint='s implicit (e.g. ~Definition x := 5~
+ instead of ~Definition x : nat := 5~) when the type is very simple or obvious (for instance, the
+ definition is in a file which deals exclusively with operations on =Z=).
+
+** Inductives
+ :PROPERTIES:
+ :CUSTOM_ID: inductives
+ :END:
+
+- The =.= ending an =Inductive= can be either on the same line as the last case or on its own line
+ immediately below. That is, both of the following are acceptable:
+
+ #+begin_src coq
+ Inductive Foo : Type :=
+ | FooA : Foo
+ | FooB : Foo
+ .
+ Inductive Foo : Type :=
+ | FooA : Foo
+ | FooB : Foo.
+ #+end_src
+
+** Lemma/Theorem statements
+ :PROPERTIES:
+ :CUSTOM_ID: lemmatheorem-statements
+ :END:
+
+- Generally, use =Theorem= for the most important, top-level facts you prove and =Lemma= for everything
+ else.
+- Insert a line break after the colon in the lemma statement.
+- Insert a line break after the comma for =forall= or =exist= quantifiers.
+- Implication arrows (=->=) should share a line with the previous hypothesis, not the following one.
+- There is no need to make a line break after every =->=; short preconditions may share a line.
+
+** Proofs and tactics
+ :PROPERTIES:
+ :CUSTOM_ID: proofs-and-tactics
+ :END:
+
+- Use the =Proof= command (lined up vertically with =Lemma= or =Theorem= it corresponds to) to open a
+ proof, and indent the first line after it 2 spaces.
+
+- Very small proofs (where =Proof. <tactics> Qed.= is <= 80 characters) can go all in one line.
+
+- When ending a proof, align the ending statement (=Qed=, =Admitted=, etc.) with =Proof=.
+
+- Avoid referring to autogenerated names (e.g. =H0=, =n0=). It's okay to let Coq generate these names,
+ but you should not explicitly refer to them in your proof. So =intros; my_solver= is fine, but
+ =intros; apply H1; my_solver= is not fine.
+
+ - You can force a non-autogenerated name by either putting the variable before the colon in the
+ lemma statement (=Lemma foo x : ...= instead of =Lemma foo : forall x, ...=), or by passing
+ arguments to =intros= (e.g. =intros ? x= to name the second argument =x=)
+
+- This way, the proof won't break when new hypotheses are added or autogenerated variable names
+ change.
+
+- Use curly braces ={}= for subgoals, instead of bullets.
+
+- /Never write tactics with more than one subgoal focused./ This can make the proof very confusing to
+ step through! If you have more than one subgoal, use curly braces.
+
+- Consider adding a comment after the opening curly brace that explains what case you're in (see
+ example).
+
+ - This is not necessary for small subgoals but can help show the major lines of reasoning in large
+ proofs.
+
+- If invoking a tactic that is expected to return multiple subgoals, use =[ | ... | ]= before the =.= to
+ explicitly specify how many subgoals you expect.
+
+ - Examples: =split; [ | ].= =induction z; [ | | ].=
+ - This helps make code more maintainable, because it fails immediately if your tactic no longer
+ solves as many subgoals as expected (or unexpectedly solves more).
+
+- If invoking a string of tactics (composed by =;=) that will break the goal into multiple subgoals
+ and then solve all but one, still use =[ ]= to enforce that all but one goal is solved.
+
+ - Example: =split; try lia; [ ]=.
+
+- Tactics that consist only of =repeat=-ing a procedure (e.g. =repeat match=, =repeat first=) should
+ factor out a single step of that procedure a separate tactic called =<tactic name>_step=, because
+ the single-step version is much easier to debug. For instance:
+
+ #+begin_src coq
+ Ltac crush_step :=
+ match goal with
+ | _ => progress subst
+ | _ => reflexivity
+ end.
+ Ltac crush := repeat crush_step.
+ #+end_src
+
+** Naming
+ :PROPERTIES:
+ :CUSTOM_ID: naming
+ :END:
+
+- Helper proofs about standard library datatypes should go in a module that is named to match the
+ standard library module (see example).
+
+ - This makes the helper proofs look like standard-library ones, which is helpful for categorizing
+ them if they're genuinely at the standard-library level of abstraction.
+
+- Names of modules should start with capital letters.
+- Names of inductives and their constructors should start with capital letters.
+- Names of other definitions/lemmas should be snake case.
+
+** Example
+ :PROPERTIES:
+ :CUSTOM_ID: example
+ :END:
+A small standalone Coq file that exhibits many of the style points.
+
+#+begin_src coq
+(*
+ * Vericert: Verified high-level synthesis.
+ * Copyright (C) 2021 Name <email@example.com>
+ *
+ * <License...>
+ *)
+
+ Require Import Coq.Lists.List.
+ Require Import Coq.micromega.Lia.
+ Require Import Coq.ZArith.ZArith.
+ Import ListNotations.
+ Local Open Scope Z_scope.
+
+ (* Helper proofs about standard library integers (Z) go within [Module Z] so
+ that they match standard-library Z lemmas when used. *)
+ Module Z.
+ Lemma pow_3_r x : x ^ 3 = x * x * x.
+ Proof. lia. Qed. (* very short proofs can go all on one line *)
+
+ Lemma pow_4_r x : x ^ 4 = x * x * x * x.
+ Proof.
+ change 4 with (Z.succ (Z.succ (Z.succ (Z.succ 0)))).
+ repeat match goal with
+ | _ => rewrite Z.pow_1_r
+ | _ => rewrite Z.pow_succ_r by lia
+ | |- context [x * (?a * ?b)] =>
+ replace (x * (a * b)) with (a * b * x) by lia
+ | _ => reflexivity
+ end.
+ Qed.
+ End Z.
+ (* Now we can access the lemmas above as Z.pow_3_r and Z.pow_4_r, as if they
+ were in the ZArith library! *)
+
+ Definition bar (x y : Z) := x ^ (y + 1).
+
+ (* example with a painfully manual proof to show case formatting *)
+ Lemma bar_upper_bound :
+ forall x y a,
+ 0 <= x <= a -> 0 <= y ->
+ 0 <= bar x y <= a ^ (y + 1).
+ Proof.
+ (* avoid referencing autogenerated names by explicitly naming variables *)
+ intros x y a Hx Hy. revert y Hy x a Hx.
+ (* explicitly indicate # subgoals with [ | ... | ] if > 1 *)
+ cbv [bar]; refine (natlike_ind _ _ _); [ | ].
+ { (* y = 0 *)
+ intros; lia. }
+ { (* y = Z.succ _ *)
+ intros.
+ rewrite Z.add_succ_l, Z.pow_succ_r by lia.
+ split.
+ { (* 0 <= bar x y *)
+ apply Z.mul_nonneg_nonneg; [ lia | ].
+ apply Z.pow_nonneg; lia. }
+ { (* bar x y < a ^ y *)
+ rewrite Z.pow_succ_r by lia.
+ apply Z.mul_le_mono_nonneg; try lia;
+ [ apply Z.pow_nonneg; lia | ].
+ (* For more flexible proofs, use match statements to find hypotheses
+ rather than referring to them by autogenerated names like H0. In this
+ case, we'll take any hypothesis that applies to and then solves the
+ goal. *)
+ match goal with H : _ |- _ => apply H; solve [auto] end. } }
+ Qed.
+
+ (* Put notations in a separate module or file so that importers can
+ decide whether or not to use them. *)
+ Module BarNotations.
+ Infix "#" := bar (at level 40) : Z_scope.
+ Notation "x '##'" := (bar x x) (at level 40) : Z_scope.
+ End BarNotations.
+#+end_src
+
+* Index - Features
+:PROPERTIES:
+:CUSTOM_ID: cindex
+:APPENDIX: t
+:INDEX: cp
+:DESCRIPTION: Key concepts & features
+:END:
+
+* Export Setup :noexport:
+
+#+setupfile: common.org
+
+#+export_file_name: vericert.texi
+
+#+texinfo_dir_category: High-level synthesis tool
+#+texinfo_dir_title: Vericert
+#+texinfo_dir_desc: Formally verified high-level synthesis tool
+
+* GNU Free Documentation License
+:PROPERTIES:
+:appendix: t
+:END:
+
+#+include: res/fdl.org
diff --git a/doc/docutils.conf b/doc/docutils.conf
new file mode 100644
index 0000000..1bf4d83
--- /dev/null
+++ b/doc/docutils.conf
@@ -0,0 +1,2 @@
+[restructuredtext parser]
+syntax_highlight = short
diff --git a/doc/index.rst b/doc/index.rst
new file mode 100644
index 0000000..06aa509
--- /dev/null
+++ b/doc/index.rst
@@ -0,0 +1,62 @@
+.. Vericert documentation master file, created by
+ sphinx-quickstart on Sat Mar 26 18:15:40 2022.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Vericert's Documentation
+========================
+
+A formally verified high-level synthesis (HLS) tool written in Coq, building on top of `CompCert
+<https://github.com/AbsInt/CompCert>`_ This ensures the correctness of the C to Verilog translation
+according to our Verilog semantics and CompCert's C semantics, removing the need to check the
+resulting hardware for behavioural correctness.
+
+Features
+--------
+
+The project is currently a work in progress. Currently, the following C features are supported and
+have all been proven correct, providing a verified translation from C to Verilog:
+
+- all int operations,
+- non-recursive function calls,
+- local arrays and pointers, and
+- control-flow structures such as if-statements, for-loops, etc...
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Content
+
+ vericert
+
+.. toctree::
+ :maxdepth: 1
+ :caption: Sources
+
+ src/Compiler
+ src/hls/RTLBlockInstr
+ src/hls/RTLBlockgen
+ src/hls/RTLBlockgenproof
+
+Publications
+------------
+
+:OOPSLA '21: Yann Herklotz, James D. Pollard, Nadesh Ramanathan, and John Wickerson. Formal
+ Verification of High-Level Synthesis. In *Proc. ACM Program. Lang.* 5, OOPSLA, 2021.
+
+:LATTE '21: Yann Herklotz and John Wickerson. High-level synthesis tools should be proven
+ correct. In *Workshop on Languages, Tools, and Techniques for Accelerator
+ Design*, 2021.
+
+Mailing lists
+-------------
+
+For discussions, you can join the following mailing list: `lists.sr.ht/~ymherklotz/vericert-discuss <https://lists.sr.ht/~ymherklotz/vericert-discuss>`_.
+
+For contributing patches to the `sourcehut <https://sr.ht/~ymherklotz/vericert/>`_ repository:
+`lists.sr.ht/~ymherklotz/vericert-devel <https://lists.sr.ht/~ymherklotz/vericert-devel>`_.
+
+Indices
+=======
+
+* :ref:`genindex`
+* :ref:`search`
diff --git a/doc/make.bat b/doc/make.bat
new file mode 100644
index 0000000..153be5e
--- /dev/null
+++ b/doc/make.bat
@@ -0,0 +1,35 @@
+@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=.
+set BUILDDIR=_build
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.https://www.sphinx-doc.org/
+ exit /b 1
+)
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+
+:end
+popd
diff --git a/doc/man.org b/doc/man.org
new file mode 100644
index 0000000..cb6143f
--- /dev/null
+++ b/doc/man.org
@@ -0,0 +1,89 @@
+#+title: vericert
+#+man_class_options: :section-id "1"
+#+options: toc:nil num:nil
+#+html_head_extra: <style>body{font-family:monospace;max-width:60em}h1{text-align:center}dt{font-weight:700}dd{margin-bottom:1em}</style>
+
+* NAME
+
+vericert - A formally verified high-level synthesis tool.
+
+* SYNOPSYS
+
+*vericert* [ *OPTION* ]... [ *FILE* ]...
+
+* DESCRIPTION
+
+** HLS Options:
+
+- --no-hls :: Do not use HLS and generate standard flow
+- --simulate :: Simulate the result with the Verilog semantics
+- --debug-hls :: Add debug logic to the Verilog
+- --initialise-stack :: initialise the stack to all 0s
+
+** HLS Optimisations:
+
+- -fschedule :: Schedule the resulting hardware [off]
+- -fif-conversion :: If-conversion optimisation [off]
+
+** General options:
+
+- -stdlib <dir> :: Set the path of the Compcert run-time library
+- -v :: Print external commands before invoking them
+- -timings :: Show the time spent in various compiler passes
+- -version :: Print the version string and exit
+- -target <value> :: Generate code for the given target
+- -conf <file> :: Read configuration from file
+- @<file> :: Read command line options from <file>
+
+** Tracing Options:
+
+- -dprepro :: Save C file after preprocessing in <file>.i
+- -dparse :: Save C file after parsing and elaboration in <file>.parsed.c
+- -dc :: Save generated C in <file>.compcert.c
+- -dclight :: Save generated Clight in <file>.light.c
+- -dcminor :: Save generated Cminor in <file>.cm
+- -drtl :: Save RTL at various optimization points in <file>.rtl.<n>
+- -drtlblock :: Save RTLBlock <file>.rtlblock
+- -dhtl :: Save HTL before Verilog generation <file>.htl
+- -dltl :: Save LTL after register allocation in <file>.ltl
+- -dmach :: Save generated Mach code in <file>.mach
+- -dasm :: Save generated assembly in <file>.s
+- -dall :: Save all generated intermediate files in <file>.<ext>
+- -sdump :: Save info for post-linking validation in <file>.json
+- -o <file> :: Generate output in <file>
+
+** Diagnostic options:
+
+- -Wall :: Enable all warnings
+- -W<warning> :: Enable the specific <warning>
+- -Wno-<warning> :: Disable the specific <warning>
+- -Werror :: Make all warnings into errors
+- -Werror=<warning> :: Turn <warning> into an error
+- -Wno-error=<warning> :: Turn <warning> into a warning even if -Werror is specified
+- -Wfatal-errors :: Turn all errors into fatal errors aborting the compilation
+- -fdiagnostics-color :: Turn on colored diagnostics
+- -fno-diagnostics-color :: Turn of colored diagnostics
+- -fmax-errors=<n> :: Maximum number of errors to report
+- -fdiagnostics-show-option :: Print the option name with mappable diagnostics
+- -fno-diagnostics-show-option :: Turn of printing of options with mappable diagnostics
+
+* AUTHOR
+
+Written by Yann Herklotz, Michalis Pardalos, James Pollard, Nadesh Ramanathan and John Wickerson.
+
+* COPYRIGHT
+
+Copyright (C) 2019-2022 Yann Herklotz <yann@yannherklotz.com>
+
+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 <https://www.gnu.org/licenses/>.
diff --git a/doc/res/coqdoc.css b/doc/res/coqdoc.css
new file mode 100644
index 0000000..5572aaa
--- /dev/null
+++ b/doc/res/coqdoc.css
@@ -0,0 +1,867 @@
+body {
+ padding: 0px 0px;
+ margin: 0px 0px;
+ padding-left: 1em;
+ background-color: white;
+ font-family: sans-serif;
+ background-repeat: no-repeat;
+ background-size: 100%;
+}
+
+#page {
+ display: block;
+ padding: 0px;
+ margin: 0px;
+}
+
+#header {
+ min-height: 100px;
+ max-width: 760px;
+ margin: 0 auto;
+ padding-left: 80px;
+ padding-right: 80px;
+ padding-top: 30px;
+}
+
+#header h1 {
+ padding: 0;
+ margin: 0;
+}
+
+/* Menu */
+ul#menu {
+ padding: 0;
+ display: block;
+ margin: auto;
+}
+
+ul#menu li, div.button {
+ display: inline-block;
+ background-color: white;
+ padding: 5px;
+ font-size: .70em;
+ text-transform: uppercase;
+ width: 30%;
+ text-align: center;
+ font-weight: 600;
+}
+
+div.button {
+ margin-top:5px;
+ width: 40%;
+}
+
+#button_block {margin-top:50px;}
+
+ul#menu a.hover li {
+ background-color: red;
+}
+
+/* Contents */
+
+#main, #main_home {
+ display: block;
+ padding: 80px;
+ padding-top: 60px; /* BCP */
+ font-size: 100%;
+ line-height: 100%;
+ max-width: 760px;
+ background-color: #ffffff;
+ margin: 0 auto;
+}
+
+#main_home {
+ background-color: rgba(255, 255, 255, 0.5);
+}
+
+#index_content div.intro p {
+ font-size: 12px;
+}
+
+#main h1 {
+ /* line-height: 80%; */
+ line-height: normal;
+ padding-top: 3px;
+ padding-bottom: 4px;
+ /* Demitri: font-size: 22pt; */
+ font-size: 200%; /* BCP */
+}
+
+/* allow for multi-line headers */
+#main a.idref:visited {color : #416DFF; text-decoration : none; }
+#main a.idref:link {color : #416DFF; text-decoration : none; }
+#main a.idref:hover {text-decoration : none; }
+#main a.idref:active {text-decoration : none; }
+
+#main a.modref:visited {color : #416DFF; text-decoration : none; }
+#main a.modref:link {color : #416DFF; text-decoration : none; }
+#main a.modref:hover {text-decoration : none; }
+#main a.modref:active {text-decoration : none; }
+
+#main .keyword { color : #697f2f }
+#main { color: black }
+
+/* General section class - applies to all .section IDs */
+.section {
+ padding-top: 12px;
+ padding-bottom: 11px;
+ padding-left: 8px;
+ margin-top: 5px;
+ margin-bottom: 3px;
+ margin-top: 18px;
+ font-size : 125%;
+ color: #ffffff;
+}
+
+/* Book title in header */
+.booktitleinheader {
+ color: #000000;
+ text-transform: uppercase;
+ font-weight: 300;
+ letter-spacing: 1px;
+ font-size: 125%;
+ margin-left: 0px;
+ margin-bottom: 22px;
+ }
+
+/* Chapter titles */
+.libtitle {
+ max-width: 860px;
+ text-transform: uppercase;
+ margin: 5px auto;
+ font-weight: 500;
+ padding-bottom: 2px;
+ font-size: 120%;
+ letter-spacing: 3px;
+ }
+
+.subtitle {
+ display: block;
+ padding-top: 10px;
+ font-size: 70%;
+ line-height: normal;
+}
+
+h2.section {
+ color: #2a2c71;
+ background-color: transparent;
+ padding-left: 0px;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ /* margin-top: 0px; */
+ margin-top: 9px; /* BCP 2/20 */
+ font-size : 135%; }
+
+h3.section {
+ /* background-color: rgb(90%,90%,100%); */
+ background-color: white;
+ /* padding-left: 8px; */
+ padding-left: 0px;
+ /* padding-top: 7px; */
+ padding-top: 0px;
+ /* padding-bottom: 0px; */
+ padding-bottom: 0.5em;
+ /* margin-top: 9px; */
+ /* margin-top: 4px; (BCP 2/20) */
+ margin-top: 9px; /* BCP 2/20 */
+ font-size : 115%;
+ color:black;
+}
+
+h4.section {
+ margin-top: .2em;
+ background-color: white;
+ color: #2a2c71;
+ padding-left: 0px;
+ padding-top: 0px;
+ padding-bottom: 0.5em; /* 0px; */
+ font-size : 100%;
+ font-style : bold;
+ text-decoration : underline;
+}
+
+#header p {
+ font-size: 13px;
+}
+
+/* Sets up Main ID and margins */
+
+#main .doc {
+ margin: 0px auto;
+ font-size: 14px;
+ line-height: 22px;
+ /* max-width: 570px; */
+ color: black;
+ /* text-align: justify; */
+ border-style: plain;
+ /* This might work better after changing back to standard coqdoc: */
+ padding-top: 10px;
+ /* padding-top: 18px; */
+}
+
+.quote {
+ margin-left: auto;
+ margin-right: auto;
+ width: 40em;
+ color: darkred;
+}
+
+.loud {
+ color: darkred;
+}
+
+pre {
+ margin-top: 0px;
+ margin-bottom: 0px;
+}
+
+.inlinecode {
+ display: inline;
+ /* font-size: 125%; */
+ color: #444444;
+ font-family: monospace }
+
+.doc .inlinecode {
+ display: inline;
+ font-size: 105%;
+ color: rgb(35%,35%,70%);
+ font-family: monospace }
+
+.doc .inlinecode .id {
+/* I am changing this to white in style below:
+ color: rgb(35%,35%,70%);
+*/
+}
+
+h1 .inlinecode .id, h1.section span.inlinecode {
+ color: #ffffff;
+}
+
+.inlinecodenm {
+ display: inline;
+ /* font-size: 125%; */
+ color: #444444;
+}
+
+.doc .inlinecodenm {
+ display: inline;
+ color: rgb(35%,35%,70%);
+}
+
+.doc .inlinecodenm .id {
+ color: rgb(35%,35%,70%);
+}
+
+.doc .code {
+ display: inline;
+ font-size: 110%;
+ color: rgb(35%,35%,70%);
+ font-family: monospace;
+ padding-left: 0px;
+}
+
+.comment {
+ display: inline;
+ font-family: monospace;
+ color: rgb(50%,50%,80%);
+}
+
+.inlineref {
+ display: inline;
+ /* font-family: monospace; */
+ color: rgb(50%,50%,80%);
+}
+
+.show::before {
+ /* content: "more"; */
+ content: "+";
+}
+
+.show {
+ background-color: rgb(93%,93%,93%);
+ display: inline;
+ font-family: monospace;
+ font-size: 60%;
+ padding-top: 1px;
+ padding-bottom: 2px;
+ padding-left: 4px;
+ padding-right: 4px;
+ color: rgb(60%,60%,60%);
+}
+
+/*
+.show {
+ display: inline;
+ font-family: monospace;
+ font-size: 60%;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ padding-left: 10px;
+ border: 1px;
+ border-style: solid;
+ color: rgb(75%,75%,85%);
+}
+*/
+
+.proofbox {
+ font-size: 90%;
+ color: rgb(75%,75%,75%);
+}
+
+#main .less-space {
+ margin-top: -12px;
+}
+
+/* Inline quizzes */
+.quiz:before {
+ color: rgb(40%,40%,40%);
+ /* content: "- Quick Check -" ; */
+ display: block;
+ text-align: center;
+ margin-bottom: 5px;
+}
+.quiz {
+ border: 4px;
+ border-color: rgb(80%,80%,80%);
+ /*
+ margin-left: 40px;
+ margin-right: 100px;
+ */
+ padding: 5px;
+ padding-left: 8px;
+ padding-right: 8px;
+ margin-top: 10px;
+ margin-bottom: 15px;
+ border-style: solid;
+}
+
+/* For textual ones... */
+.show-old {
+ display: inline;
+ font-family: monospace;
+ font-size: 80%;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ padding-left: 3px;
+ padding-right: 3px;
+ border: 1px;
+ margin-top: 5px; /* doesn't work?! */
+ border-style: solid;
+ color: rgb(75%,75%,85%);
+}
+
+.largebr {
+ margin-top: 10px;
+}
+
+.code {
+ padding-left: 20px;
+ font-size: 14px;
+ font-family: monospace;
+ line-height: 17px;
+ margin-top: 9px;
+}
+
+/* Working:
+.code {
+ display: block;
+ padding-left: 0px;
+ font-size: 110%;
+ font-family: monospace;
+ }
+*/
+
+.code-space {
+ max-width: 50em;
+ margin-top: 0em;
+ /* margin-bottom: -.5em; */
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.code-tight {
+ max-width: 50em;
+ margin-top: .6em;
+ /* margin-bottom: -.7em; */
+ margin-left: auto;
+ margin-right: auto;
+}
+
+hr.doublespaceincode {
+ height: 1pt;
+ visibility: hidden;
+ font-size: 10px;
+}
+
+/*
+code.br {
+ height: 5em;
+}
+*/
+
+#main .citation {
+ color: rgb(70%,0%,0%);
+ text-decoration: underline;
+}
+
+table.infrule {
+ border: 0px;
+ margin-left: 50px;
+ margin-top: .5em;
+ margin-bottom: 1.2em;
+}
+
+td.infrule {
+ font-family: monospace;
+ text-align: center;
+ /* color: rgb(35%,35%,70%); */
+ padding: 0px;
+ line-height: 100%;
+}
+
+tr.infrulemiddle hr {
+ margin: 1px 0 1px 0;
+}
+
+.infrulenamecol {
+ color: rgb(60%,60%,60%);
+ font-size: 80%;
+ padding-left: 1em;
+ padding-bottom: 0.1em
+}
+
+#footer {
+ font-size: 65%;
+ font-family: sans-serif;
+}
+
+.id { display: inline; }
+
+.id[title="constructor"] {
+ color: #697f2f;
+}
+
+.id[title="var"],
+.id[title="variable"] {
+ color: rgb(40%,0%,40%);
+}
+
+.id[title="definition"] {
+ color: rgb(0%,40%,0%);
+}
+
+.id[title="abbreviation"] {
+ color: rgb(0%,40%,0%);
+}
+
+.id[title="lemma"] {
+ color: rgb(0%,40%,0%);
+}
+
+.id[title="instance"] {
+ color: rgb(0%,40%,0%);
+}
+
+.id[title="projection"] {
+ color: rgb(0%,40%,0%);
+}
+
+.id[title="method"] {
+ color: rgb(0%,40%,0%);
+}
+
+.id[title="inductive"] {
+ color: #034764;
+}
+
+.id[title="record"] {
+ color: rgb(0%,0%,80%);
+}
+
+.id[title="class"] {
+ color: rgb(0%,0%,80%);
+}
+
+.id[title="keyword"] {
+ color : #697f2f;
+ /* color: black; */
+}
+
+.inlinecode .id {
+ color: rgb(0%,0%,0%);
+}
+
+.nowrap {
+ white-space: nowrap;
+}
+
+.HIDEFROMHTML {
+ display: none;
+}
+
+/* TOC */
+
+#toc h2 {
+/* padding-top: 13px; */
+ padding-bottom: 13px;
+ padding-left: 8px;
+ margin-top: 5px;
+ margin-top: 20px;
+ /* OLD: padding: 10px;
+ line-height: 120%;
+ background-color: rgb(60%,60%,100%); */
+}
+
+#toc h2.ui-accordion-header {
+ padding: .5em .5em .5em .7em;
+ outline: none;
+}
+
+#toc .ui-accordion .ui-accordion-content {
+ padding: 0.5em 2.5em 0.8em .9em;
+ border-top: 0;
+ margin-bottom: 1em;
+ /* bottom rule */
+ border: none;
+ border-bottom: 1px solid transparent;
+ transition: border-bottom-color 0.25s ease-in;
+ transition-delay: 0.15s;
+}
+
+#toc .ui-accordion .ui-accordion-content-active {
+ border-bottom: 1px solid #9b9b9b;
+ transition-delay: 0s;
+}
+
+#toc h2.ui-accordion-header-active {
+ background: silver !important;
+}
+
+#toc h2:not(.ui-accordion-header-active):hover {
+ background: rgba(0,0,0,0.04) !important;
+}
+
+#toc h2 a:hover {
+ text-decoration: underline;
+}
+
+#toc h2:hover::after {
+ content: "expand ▾";
+ font-size: 80%;
+ float: right;
+ margin-top: 0.2em;
+ color: silver;
+ opacity: 1;
+ transition: opacity .5s ease-in-out;
+}
+
+#toc h2.ui-accordion-header-active:hover::after {
+ opacity: 0;
+}
+
+#toc h2 .select { background-image: url('media/image/arrow_down.jpg'); }
+div#sec1.hide { display: none; }
+
+#toc ul {
+ padding-top: 8px;
+ font-size: 14px;
+ padding-left: 0;
+}
+
+#toc ul ul {
+ margin-bottom: -8px;
+}
+
+#toc li {
+ font-weight: 600;
+ list-style-type: none;
+ padding-top: 12px;
+ padding-bottom: 8px;
+}
+
+#toc li li {
+ font-weight: 300;
+ list-style-type: circle;
+ padding-bottom: 3px;
+ padding-top: 0px;
+ margin-left: 19px;
+}
+
+
+
+
+/* Accordion Overrides */
+
+/* Widget Bar */
+.ui-state-default,
+.ui-widget-content .ui-state-default,
+.ui-widget-header .ui-state-default,
+.ui-button,
+/* We use html here because we need a greater specificity to make sure disabled
+ works properly when clicked or hovered */
+html .ui-button.ui-state-disabled:hover,
+html .ui-button.ui-state-disabled:active {
+ border: none!important;
+ /* BCP 3/17: I like it better without the rules...
+ border-bottom: 1px solid silver!important; */
+ background: white !important;
+ font-weight: normal;
+ color: #454545!important;
+ font-weight: 400!important;
+ margin-top: 0px!important;
+
+}
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-all,
+.ui-corner-top,
+.ui-corner-left,
+.ui-corner-tl {
+ border-top-left-radius: 0px!important;
+}
+
+.ui-corner-all,
+.ui-corner-top,
+.ui-corner-right,
+.ui-corner-tr {
+ border-top-right-radius: 0px!important;
+}
+
+.ui-corner-all,
+.ui-corner-bottom,
+.ui-corner-left,
+.ui-corner-bl {
+ border-bottom-left-radius: 0px!important;
+}
+
+.ui-corner-all,
+.ui-corner-bottom,
+.ui-corner-right,
+.ui-corner-br {
+ border-bottom-right-radius: 0px!important;
+}
+
+html .ui-button.ui-state-disabled:focus {
+ color: red!important;
+}
+
+/* Remove Icon */
+.ui-icon { display: none!important; }
+
+/* Widget */
+.ui-widget-content {
+ border: 1px solid #9e9e9e;
+ border-bottom-color: #b2b2b2;
+}
+
+.ui-widget-content {
+ background: #ffffff;
+ color: #333333;
+}
+
+
+/* Index */
+
+#index {
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ font-style : normal;
+}
+
+#index #frontispiece {
+ margin: auto;
+ padding: 1em;
+ width: 700px;
+}
+
+.booktitle {
+ font-size : 300%; line-height: 100%; font-style:bold;
+ color: white;
+ padding-top: 70px;
+ padding-bottom: 20px; }
+.authors { font-size : 200%;
+ line-height: 115%; }
+.moreauthors { font-size : 170% }
+.buttons { font-size : 170%;
+ margin-left: auto;
+ margin-right: auto;
+ font-style : bold;
+ }
+
+/* Link colors never changes */
+
+A:link, A:visited, A:active, A:hover {
+ text-decoration: none;
+ color: #555555
+}
+
+/* Special color for the chapter header */
+
+.booktitleinheader A:visited, .booktitleinheader A:active, .booktitleinheader A:hover, .booktitleinheader A:link {
+ text-decoration: none;
+ color: black;
+}
+
+#index #entrance {
+ text-align: center;
+}
+
+/* This was removed via CSS but the HTML is still generated */
+#index #footer {
+ display: none;
+}
+
+.paragraph {
+ height: 0.6em;
+}
+
+ul.doclist {
+ margin-top: 0em;
+ margin-bottom: 0em;
+}
+
+/* Index styles */
+
+/* Styles the author box (Intro class) and With (column class) */
+
+.column {
+ float:left;
+ width: 43%;
+ margin:0 10px;
+ text-align: left;
+ font-size: 15px;
+ line-height: 25px;
+ padding-right: 20px;
+ min-height: 340px;
+}
+
+.smallauthors {
+ font-size: 19px;
+ line-height: 25px;
+}
+
+.mediumauthors {
+ font-size: 23px;
+ line-height: 33px;
+}
+
+.largeauthors {
+ font-size: 28px;
+ line-height: 40px;
+}
+
+.intro {
+ width: 35%;
+ font-size: 21px;
+ line-height: 27px;
+ font-weight: 600;
+ padding-right: 20px;
+}
+
+.column.pub {
+ width: 40%;
+ margin-bottom: 20px;
+}
+
+#index_content {
+ width: 100%!important;
+ display: block;
+ min-height: 400px;
+}
+
+div.column.pub table tbody tr td {
+ text-align: center; padding: 10px;
+}
+div.column.pub table tbody tr td p {
+ text-align: left;
+ margin-top: 0;
+ font-weight: 600;
+ font-size: 13px!important;
+ line-height: 18px;
+}
+
+/* Tables */
+
+td.tab {
+ height: 16px;
+ font-weight: 600;
+ padding-left: 5px;
+ text-align: left!important;
+}
+
+/* Styles tables on the index -- body class sf_home is used there */
+
+body.sf_home table {
+ min-height: 450px;
+ vertical-align: top;
+}
+
+body.sf_home table td {
+ vertical-align: top;
+
+}
+body.sf_home table td p {
+ min-height: 100px;
+
+}
+
+table.logical { background-color: rgba(144, 160, 209, 0.5); }
+table.logical tbody tr td.tab { background-color: #91a1d1; }
+
+table.language_found { background-color: rgba(178, 88, 88, 0.5); }
+table.language_found tbody tr td.tab { background-color: #b25959; }
+
+table.algo { background-color: rgba(194, 194, 108, 0.5); }
+table.algo tbody tr td.tab { background-color: #c2c26c; }
+
+table.qc { background-color: rgba(185, 170, 185, 0.5); }
+table.qc tbody tr td.tab { background-color: #8b7d95; }
+
+table.vc { background-color: rgba(159, 125, 140, 0.5); }
+table.vc tbody tr td.tab { background-color: rgb(159, 125, 140); }
+
+table.slf { background-color: rgba(219, 178, 127, 0.5); }
+table.slf tbody tr td.tab { background-color: rgb(219, 178, 127); }
+
+/* Suggested background color for next volume */
+/* #c07d62 */
+
+.ui-draggable, .ui-droppable {
+ background-position: top;
+}
+
+/* Chapter dependencies (SVG) */
+.deps a polygon:hover { opacity: 0.6; stroke-width: 2; }
+.deps a text { pointer-events: none; }
+
+/* A few specific things for the top-level SF landing page */
+
+body.sf_home {background-color: #ededed; background-image: url(../media/image/core_mem_bg.jpg); }
+
+body.sf_home #header {
+ background-image: url(../media/image/core_mem_hdr_bg.jpg);
+ padding-bottom: 20px;
+}
+
+body.sf_home #main_home {
+ background-color: transparent;
+}
+
+/* A partial fix to a coqdoc bug...
+ See https://github.com/DeepSpec/sfdev/issues/236 */
+.inlinecode { white-space: pre; }
+.inlinecode br { display: none; }
+
+#header { background-color: rgba(190, 170, 190, 0.5); }
+
+/* This volume's color */
+.section, ul#menu li.section_name, div.button { background-color: #8b7d95; }
+
+.slide img {
+ border: 2px solid gray;
+ margin: 1em;
+}
diff --git a/doc/res/fdl.org b/doc/res/fdl.org
new file mode 100644
index 0000000..81e2cd9
--- /dev/null
+++ b/doc/res/fdl.org
@@ -0,0 +1,489 @@
+# The GNU Free Documentation License.
+#+begin_center
+Version 1.3, 3 November 2008
+#+end_center
+
+# This file is intended to be included within another document.
+
+#+begin_verse
+Copyright \copy{} 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
+https://fsf.org/
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+#+end_verse
+
+0. [@0] PREAMBLE
+
+ The purpose of this License is to make a manual, textbook, or other
+ functional and useful document @@texinfo:@dfn{@@free@@texinfo:}@@
+ in the sense of freedom: to assure everyone the effective freedom
+ to copy and redistribute it, with or without modifying it, either
+ commercially or noncommercially. Secondarily, this License
+ preserves for the author and publisher a way to get credit for
+ their work, while not being considered responsible for
+ modifications made by others.
+
+ This License is a kind of "copyleft", which means that derivative
+ works of the document must themselves be free in the same sense.
+ It complements the GNU General Public License, which is a copyleft
+ license designed for free software.
+
+ We have designed this License in order to use it for manuals for
+ free software, because free software needs free documentation:
+ a free program should come with manuals providing the same freedoms
+ that the software does. But this License is not limited to
+ software manuals; it can be used for any textual work, regardless
+ of subject matter or whether it is published as a printed book. We
+ recommend this License principally for works whose purpose is
+ instruction or reference.
+
+1. APPLICABILITY AND DEFINITIONS
+
+ This License applies to any manual or other work, in any medium,
+ that contains a notice placed by the copyright holder saying it can
+ be distributed under the terms of this License. Such a notice
+ grants a world-wide, royalty-free license, unlimited in duration,
+ to use that work under the conditions stated herein. The
+ "Document", below, refers to any such manual or work. Any member
+ of the public is a licensee, and is addressed as "you". You accept
+ the license if you copy, modify or distribute the work in a way
+ requiring permission under copyright law.
+
+ A "Modified Version" of the Document means any work containing the
+ Document or a portion of it, either copied verbatim, or with
+ modifications and/or translated into another language.
+
+ A "Secondary Section" is a named appendix or a front-matter section
+ of the Document that deals exclusively with the relationship of the
+ publishers or authors of the Document to the Document's overall
+ subject (or to related matters) and contains nothing that could
+ fall directly within that overall subject. (Thus, if the Document
+ is in part a textbook of mathematics, a Secondary Section may not
+ explain any mathematics.) The relationship could be a matter of
+ historical connection with the subject or with related matters, or
+ of legal, commercial, philosophical, ethical or political position
+ regarding them.
+
+ The "Invariant Sections" are certain Secondary Sections whose
+ titles are designated, as being those of Invariant Sections, in the
+ notice that says that the Document is released under this License.
+ If a section does not fit the above definition of Secondary then it
+ is not allowed to be designated as Invariant. The Document may
+ contain zero Invariant Sections. If the Document does not identify
+ any Invariant Sections then there are none.
+
+ The "Cover Texts" are certain short passages of text that are
+ listed, as Front-Cover Texts or Back-Cover Texts, in the notice
+ that says that the Document is released under this License.
+ A Front-Cover Text may be at most 5 words, and a Back-Cover Text
+ may be at most 25 words.
+
+ A "Transparent" copy of the Document means a machine-readable copy,
+ represented in a format whose specification is available to the
+ general public, that is suitable for revising the document
+ straightforwardly with generic text editors or (for images composed
+ of pixels) generic paint programs or (for drawings) some widely
+ available drawing editor, and that is suitable for input to text
+ formatters or for automatic translation to a variety of formats
+ suitable for input to text formatters. A copy made in an otherwise
+ Transparent file format whose markup, or absence of markup, has
+ been arranged to thwart or discourage subsequent modification by
+ readers is not Transparent. An image format is not Transparent if
+ used for any substantial amount of text. A copy that is not
+ "Transparent" is called "Opaque".
+
+ Examples of suitable formats for Transparent copies include plain
+ ASCII without markup, Texinfo input format, LaTeX input format,
+ SGML or XML using a publicly available DTD, and standard-conforming
+ simple HTML, PostScript or PDF designed for human modification.
+ Examples of transparent image formats include PNG, XCF and JPG.
+ Opaque formats include proprietary formats that can be read and
+ edited only by proprietary word processors, SGML or XML for which
+ the DTD and/or processing tools are not generally available, and
+ the machine-generated HTML, PostScript or PDF produced by some word
+ processors for output purposes only.
+
+ The "Title Page" means, for a printed book, the title page itself,
+ plus such following pages as are needed to hold, legibly, the
+ material this License requires to appear in the title page. For
+ works in formats which do not have any title page as such, "Title
+ Page" means the text near the most prominent appearance of the
+ work's title, preceding the beginning of the body of the text.
+
+ The "publisher" means any person or entity that distributes copies
+ of the Document to the public.
+
+ A section "Entitled XYZ" means a named subunit of the Document
+ whose title either is precisely XYZ or contains XYZ in parentheses
+ following text that translates XYZ in another language. (Here XYZ
+ stands for a specific section name mentioned below, such as
+ "Acknowledgements", "Dedications", "Endorsements", or "History".)
+ To "Preserve the Title" of such a section when you modify the
+ Document means that it remains a section "Entitled XYZ" according
+ to this definition.
+
+ The Document may include Warranty Disclaimers next to the notice
+ which states that this License applies to the Document. These
+ Warranty Disclaimers are considered to be included by reference in
+ this License, but only as regards disclaiming warranties: any other
+ implication that these Warranty Disclaimers may have is void and
+ has no effect on the meaning of this License.
+
+2. VERBATIM COPYING
+
+ You may copy and distribute the Document in any medium, either
+ commercially or noncommercially, provided that this License, the
+ copyright notices, and the license notice saying this License
+ applies to the Document are reproduced in all copies, and that you
+ add no other conditions whatsoever to those of this License. You
+ may not use technical measures to obstruct or control the reading
+ or further copying of the copies you make or distribute. However,
+ you may accept compensation in exchange for copies. If you
+ distribute a large enough number of copies you must also follow the
+ conditions in section 3.
+
+ You may also lend copies, under the same conditions stated above,
+ and you may publicly display copies.
+
+3. COPYING IN QUANTITY
+
+ If you publish printed copies (or copies in media that commonly
+ have printed covers) of the Document, numbering more than 100, and
+ the Document's license notice requires Cover Texts, you must
+ enclose the copies in covers that carry, clearly and legibly, all
+ these Cover Texts: Front-Cover Texts on the front cover, and
+ Back-Cover Texts on the back cover. Both covers must also clearly
+ and legibly identify you as the publisher of these copies. The
+ front cover must present the full title with all words of the title
+ equally prominent and visible. You may add other material on the
+ covers in addition. Copying with changes limited to the covers, as
+ long as they preserve the title of the Document and satisfy these
+ conditions, can be treated as verbatim copying in other respects.
+
+ If the required texts for either cover are too voluminous to fit
+ legibly, you should put the first ones listed (as many as fit
+ reasonably) on the actual cover, and continue the rest onto
+ adjacent pages.
+
+ If you publish or distribute Opaque copies of the Document
+ numbering more than 100, you must either include a machine-readable
+ Transparent copy along with each Opaque copy, or state in or with
+ each Opaque copy a computer-network location from which the general
+ network-using public has access to download using public-standard
+ network protocols a complete Transparent copy of the Document, free
+ of added material. If you use the latter option, you must take
+ reasonably prudent steps, when you begin distribution of Opaque
+ copies in quantity, to ensure that this Transparent copy will
+ remain thus accessible at the stated location until at least one
+ year after the last time you distribute an Opaque copy (directly or
+ through your agents or retailers) of that edition to the public.
+
+ It is requested, but not required, that you contact the authors of
+ the Document well before redistributing any large number of copies,
+ to give them a chance to provide you with an updated version of the
+ Document.
+
+4. MODIFICATIONS
+
+ You may copy and distribute a Modified Version of the Document
+ under the conditions of sections 2 and 3 above, provided that you
+ release the Modified Version under precisely this License, with the
+ Modified Version filling the role of the Document, thus licensing
+ distribution and modification of the Modified Version to whoever
+ possesses a copy of it. In addition, you must do these things in
+ the Modified Version:
+
+ #+attr_texinfo: :enum A
+ 1. Use in the Title Page (and on the covers, if any) a title
+ distinct from that of the Document, and from those of previous
+ versions (which should, if there were any, be listed in the
+ History section of the Document). You may use the same title as
+ a previous version if the original publisher of that version
+ gives permission.
+
+ 2. List on the Title Page, as authors, one or more persons or
+ entities responsible for authorship of the modifications in the
+ Modified Version, together with at least five of the principal
+ authors of the Document (all of its principal authors, if it has
+ fewer than five), unless they release you from this requirement.
+
+ 3. State on the Title page the name of the publisher of the
+ Modified Version, as the publisher.
+
+ 4. Preserve all the copyright notices of the Document.
+
+ 5. Add an appropriate copyright notice for your modifications
+ adjacent to the other copyright notices.
+
+ 6. Include, immediately after the copyright notices, a license
+ notice giving the public permission to use the Modified Version
+ under the terms of this License, in the form shown in the
+ Addendum below.
+
+ 7. Preserve in that license notice the full lists of Invariant
+ Sections and required Cover Texts given in the Document's
+ license notice.
+
+ 8. Include an unaltered copy of this License.
+
+ 9. Preserve the section Entitled "History", Preserve its Title, and
+ add to it an item stating at least the title, year, new authors,
+ and publisher of the Modified Version as given on the Title
+ Page. If there is no section Entitled "History" in the Document,
+ create one stating the title, year, authors, and publisher of
+ the Document as given on its Title Page, then add an item
+ describing the Modified Version as stated in the previous
+ sentence.
+
+ 10. Preserve the network location, if any, given in the Document
+ for public access to a Transparent copy of the Document, and
+ likewise the network locations given in the Document for
+ previous versions it was based on. These may be placed in the
+ "History" section. You may omit a network location for a work
+ that was published at least four years before the Document
+ itself, or if the original publisher of the version it refers
+ to gives permission.
+
+ 11. For any section Entitled "Acknowledgements" or "Dedications",
+ Preserve the Title of the section, and preserve in the section
+ all the substance and tone of each of the contributor
+ acknowledgements and/or dedications given therein.
+
+ 12. Preserve all the Invariant Sections of the Document, unaltered
+ in their text and in their titles. Section numbers or the
+ equivalent are not considered part of the section titles.
+
+ 13. Delete any section Entitled "Endorsements". Such a section may
+ not be included in the Modified Version.
+
+ 14. Do not retitle any existing section to be Entitled
+ "Endorsements" or to conflict in title with any Invariant
+ Section.
+
+ 15. Preserve any Warranty Disclaimers.
+
+ If the Modified Version includes new front-matter sections or
+ appendices that qualify as Secondary Sections and contain no material
+ copied from the Document, you may at your option designate some or all
+ of these sections as invariant. To do this, add their titles to the
+ list of Invariant Sections in the Modified Version's license notice.
+ These titles must be distinct from any other section titles.
+
+ You may add a section Entitled "Endorsements", provided it contains
+ nothing but endorsements of your Modified Version by various
+ parties---for example, statements of peer review or that the text has
+ been approved by an organization as the authoritative definition of a
+ standard.
+
+ You may add a passage of up to five words as a Front-Cover Text, and a
+ passage of up to 25 words as a Back-Cover Text, to the end of the list
+ of Cover Texts in the Modified Version. Only one passage of
+ Front-Cover Text and one of Back-Cover Text may be added by (or
+ through arrangements made by) any one entity. If the Document already
+ includes a cover text for the same cover, previously added by you or
+ by arrangement made by the same entity you are acting on behalf of,
+ you may not add another; but you may replace the old one, on explicit
+ permission from the previous publisher that added the old one.
+
+ The author(s) and publisher(s) of the Document do not by this License
+ give permission to use their names for publicity for or to assert or
+ imply endorsement of any Modified Version.
+
+5. COMBINING DOCUMENTS
+
+ You may combine the Document with other documents released under
+ this License, under the terms defined in section 4 above for
+ modified versions, provided that you include in the combination all
+ of the Invariant Sections of all of the original documents,
+ unmodified, and list them all as Invariant Sections of your
+ combined work in its license notice, and that you preserve all
+ their Warranty Disclaimers.
+
+ The combined work need only contain one copy of this License, and
+ multiple identical Invariant Sections may be replaced with a single
+ copy. If there are multiple Invariant Sections with the same name
+ but different contents, make the title of each such section unique
+ by adding at the end of it, in parentheses, the name of the
+ original author or publisher of that section if known, or else
+ a unique number. Make the same adjustment to the section titles in
+ the list of Invariant Sections in the license notice of the
+ combined work.
+
+ In the combination, you must combine any sections Entitled
+ "History" in the various original documents, forming one section
+ Entitled "History"; likewise combine any sections Entitled
+ "Acknowledgements", and any sections Entitled "Dedications". You
+ must delete all sections Entitled "Endorsements."
+
+6. COLLECTIONS OF DOCUMENTS
+
+ You may make a collection consisting of the Document and other
+ documents released under this License, and replace the individual
+ copies of this License in the various documents with a single copy
+ that is included in the collection, provided that you follow the
+ rules of this License for verbatim copying of each of the documents
+ in all other respects.
+
+ You may extract a single document from such a collection, and
+ distribute it individually under this License, provided you insert
+ a copy of this License into the extracted document, and follow this
+ License in all other respects regarding verbatim copying of that
+ document.
+
+7. AGGREGATION WITH INDEPENDENT WORKS
+
+ A compilation of the Document or its derivatives with other
+ separate and independent documents or works, in or on a volume of
+ a storage or distribution medium, is called an "aggregate" if the
+ copyright resulting from the compilation is not used to limit the
+ legal rights of the compilation's users beyond what the individual
+ works permit. When the Document is included in an aggregate, this
+ License does not apply to the other works in the aggregate which
+ are not themselves derivative works of the Document.
+
+ If the Cover Text requirement of section 3 is applicable to these
+ copies of the Document, then if the Document is less than one half
+ of the entire aggregate, the Document's Cover Texts may be placed
+ on covers that bracket the Document within the aggregate, or the
+ electronic equivalent of covers if the Document is in electronic
+ form. Otherwise they must appear on printed covers that bracket
+ the whole aggregate.
+
+8. TRANSLATION
+
+ Translation is considered a kind of modification, so you may
+ distribute translations of the Document under the terms of
+ section 4. Replacing Invariant Sections with translations requires
+ special permission from their copyright holders, but you may
+ include translations of some or all Invariant Sections in addition
+ to the original versions of these Invariant Sections. You may
+ include a translation of this License, and all the license notices
+ in the Document, and any Warranty Disclaimers, provided that you
+ also include the original English version of this License and the
+ original versions of those notices and disclaimers. In case of
+ a disagreement between the translation and the original version of
+ this License or a notice or disclaimer, the original version will
+ prevail.
+
+ If a section in the Document is Entitled "Acknowledgements",
+ "Dedications", or "History", the requirement (section 4) to
+ Preserve its Title (section 1) will typically require changing the
+ actual title.
+
+9. TERMINATION
+
+ You may not copy, modify, sublicense, or distribute the Document
+ except as expressly provided under this License. Any attempt
+ otherwise to copy, modify, sublicense, or distribute it is void,
+ and will automatically terminate your rights under this License.
+
+ However, if you cease all violation of this License, then your
+ license from a particular copyright holder is reinstated (a)
+ provisionally, unless and until the copyright holder explicitly and
+ finally terminates your license, and (b) permanently, if the
+ copyright holder fails to notify you of the violation by some
+ reasonable means prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+ reinstated permanently if the copyright holder notifies you of the
+ violation by some reasonable means, this is the first time you have
+ received notice of violation of this License (for any work) from
+ that copyright holder, and you cure the violation prior to 30 days
+ after your receipt of the notice.
+
+ Termination of your rights under this section does not terminate
+ the licenses of parties who have received copies or rights from you
+ under this License. If your rights have been terminated and not
+ permanently reinstated, receipt of a copy of some or all of the
+ same material does not give you any rights to use it.
+
+10. FUTURE REVISIONS OF THIS LICENSE
+
+ The Free Software Foundation may publish new, revised versions of
+ the GNU Free Documentation License from time to time. Such new
+ versions will be similar in spirit to the present version, but may
+ differ in detail to address new problems or concerns. See
+ https://www.gnu.org/copyleft/.
+
+ Each version of the License is given a distinguishing version
+ number. If the Document specifies that a particular numbered
+ version of this License "or any later version" applies to it, you
+ have the option of following the terms and conditions either of
+ that specified version or of any later version that has been
+ published (not as a draft) by the Free Software Foundation. If
+ the Document does not specify a version number of this License,
+ you may choose any version ever published (not as a draft) by the
+ Free Software Foundation. If the Document specifies that a proxy
+ can decide which future versions of this License can be used, that
+ proxy's public statement of acceptance of a version permanently
+ authorizes you to choose that version for the Document.
+
+11. RELICENSING
+
+ "Massive Multiauthor Collaboration Site" (or "MMC Site") means any
+ World Wide Web server that publishes copyrightable works and also
+ provides prominent facilities for anybody to edit those works.
+ A public wiki that anybody can edit is an example of such
+ a server. A "Massive Multiauthor Collaboration" (or "MMC")
+ contained in the site means any set of copyrightable works thus
+ published on the MMC site.
+
+ "CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0
+ license published by Creative Commons Corporation,
+ a not-for-profit corporation with a principal place of business in
+ San Francisco, California, as well as future copyleft versions of
+ that license published by that same organization.
+
+ "Incorporate" means to publish or republish a Document, in whole
+ or in part, as part of another Document.
+
+ An MMC is "eligible for relicensing" if it is licensed under this
+ License, and if all works that were first published under this
+ License somewhere other than this MMC, and subsequently
+ incorporated in whole or in part into the MMC, (1) had no cover
+ texts or invariant sections, and (2) were thus incorporated prior
+ to November 1, 2008.
+
+ The operator of an MMC Site may republish an MMC contained in the
+ site under CC-BY-SA on the same site at any time before August 1,
+ 2009, provided the MMC is eligible for relicensing.
+
+#+texinfo: @page
+
+* ADDENDUM: How to use this License for your documents
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+To use this License in a document you have written, include a copy of
+the License in the document and put the following copyright and
+license notices just after the title page:
+
+#+begin_example
+ Copyright (C) YEAR YOUR NAME.
+ Permission is granted to copy, distribute and/or modify this document
+ under the terms of the GNU Free Documentation License, Version 1.3
+ or any later version published by the Free Software Foundation;
+ with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+ Texts. A copy of the license is included in the section entitled ``GNU
+ Free Documentation License''.
+#+end_example
+
+If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
+replace the "with...Texts."\nbsp{}line with this:
+
+#+begin_example
+ with the Invariant Sections being LIST THEIR TITLES, with
+ the Front-Cover Texts being LIST, and with the Back-Cover Texts
+ being LIST.
+#+end_example
+
+If you have Invariant Sections without Cover Texts, or some other
+combination of the three, merge those two alternatives to suit the
+situation.
+
+If your document contains nontrivial examples of program code, we
+recommend releasing these examples in parallel under your choice of
+free software license, such as the GNU General Public License, to
+permit their use in free software.
diff --git a/doc/res/install-deps.el b/doc/res/install-deps.el
new file mode 100644
index 0000000..09cf4ae
--- /dev/null
+++ b/doc/res/install-deps.el
@@ -0,0 +1,11 @@
+(require 'package)
+(package-initialize)
+(add-to-list 'package-archives '("nongnu" . "https://elpa.nongnu.org/nongnu/") t)
+(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
+(add-to-list 'package-archives '("gnu-devel" . "https://elpa.gnu.org/devel/") t)
+(package-refresh-contents)
+
+(package-install 'org)
+(package-install 'org-contrib)
+(package-install 'org-transclusion)
+(package-install 'htmlize)
diff --git a/doc/res/publish.el b/doc/res/publish.el
new file mode 100644
index 0000000..c083eb0
--- /dev/null
+++ b/doc/res/publish.el
@@ -0,0 +1,23 @@
+(require 'package)
+(package-initialize)
+
+(require 'org)
+(require 'org-transclusion)
+(require 'ox)
+(require 'ox-html)
+(require 'htmlize)
+(require 'ox-texinfo)
+(require 'ox-man)
+
+(setq org-transclusion-exclude-elements nil
+ org-html-head-include-default-style nil
+ org-html-head-include-scripts nil
+ org-html-postamble-format '(("en" ""))
+ org-html-postamble t
+ org-html-divs '((preamble "header" "header")
+ (content "article" "content")
+ (postamble "footer" "postamble"))
+ org-html-doctype "html5"
+ org-html-htmlize-output-type 'css)
+
+(org-transclusion-add-all)
diff --git a/doc/vericert.rst b/doc/vericert.rst
new file mode 100644
index 0000000..19ac28f
--- /dev/null
+++ b/doc/vericert.rst
@@ -0,0 +1,526 @@
+===============
+Vericert Manual
+===============
+
+
+Introduction
+------------
+
+Vericert translates C code into a hardware description language called Verilog, which can then be
+synthesised into hardware, to be placed onto a field-programmable gate array (FPGA) or
+application-specific integrated circuit (ASIC).
+
+.. _fig:design:
+
+.. figure:: /_static/images/toolflow.svg
+
+ Current design of Vericert, where HTL is an intermediate language representing a finite state
+ machine with data-path (FSMD) and Verilog is the target language.
+
+The design shown in Figure `fig:design`_ shows how Vericert leverages an existing verified C
+compiler called `CompCert <https://compcert.org/compcert-C.html>`_ to perform this translation.
+
+.. _building:
+
+Building Vericert
+-----------------
+
+
+Testing
+~~~~~~~
+
+To test out ``vericert`` you can try the following examples which are in the test folder using the
+following:
+
+.. code:: shell
+
+ ./bin/vericert test/loop.c -o loop.v
+ ./bin/vericert test/conditional.c -o conditional.v
+ ./bin/vericert test/add.c -o add.v
+
+Or by running the test suite using the following command:
+
+.. code:: shell
+
+ make test
+
+.. _using-vericert:
+
+Using Vericert
+--------------
+
+Vericert can be used to translate a subset of C into Verilog. As a simple example, consider the
+following C file (``main.c``):
+
+.. code:: C
+
+ void matrix_multiply(int first[2][2], int second[2][2], int multiply[2][2]) {
+ int sum = 0;
+ for (int c = 0; c < 2; c++) {
+ for (int d = 0; d < 2; d++) {
+ for (int k = 0; k < 2; k++) {
+ sum = sum + first[c][k]*second[k][d];
+ }
+ multiply[c][d] = sum;
+ sum = 0;
+ }
+ }
+ }
+
+ int main() {
+ int f[2][2] = {{1, 2}, {3, 4}};
+ int s[2][2] = {{5, 6}, {7, 8}};
+ int m[2][2] = {{0, 0}, {0, 0}};
+
+ matrix_multiply(f, s, m);
+ return m[1][1];
+ }
+
+It can be compiled using the following command, assuming that vericert is somewhere on the path.
+
+.. code:: shell
+
+ vericert main.c -o main.v
+
+The Verilog file contains a top-level test-bench, which can be given to any Verilog simulator to
+simulate the hardware, which should give the same result as executing the C code. Using `Icarus
+Verilog <http://iverilog.icarus.com/>`_ as an example:
+
+.. code:: shell
+
+ iverilog -o main_v main.v
+
+When executing, it should therefore print the following:
+
+.. code:: shell
+
+ $ ./main_v
+ finished: 50
+
+This gives the same result as executing the C in the following way:
+
+.. code:: shell
+
+ $ gcc -o main_c main.c
+ $ ./main_c
+ $ echo $?
+ 50
+
+Man pages
+~~~~~~~~~
+
+.. _unreleased-features:
+
+Unreleased Features
+-------------------
+
+The following are unreleased features in Vericert that are currently being worked on and have not
+been completely proven correct yet. Currently this includes features such as:
+
+- `scheduling`_,
+
+- `operation-chaining`_,
+
+- `if-conversion`_, and
+
+- `functions`_.
+
+This page gives some preliminary information on how the features are implemented and how the proofs
+for the features are being done. Once these features are properly implemented, they will be added
+to the proper documentation.
+
+.. _scheduling:
+
+Scheduling
+~~~~~~~~~~
+
+Scheduling is an optimisation which is used to run various instructions in parallel that are
+independent to each other.
+
+.. _operation-chaining:
+
+Operation Chaining
+~~~~~~~~~~~~~~~~~~
+
+Operation chaining is an optimisation that can be added on to scheduling and allows for the
+sequential execution of instructions in a clock cycle, while executing other instructions in
+parallel in the same clock cycle.
+
+.. _if-conversion:
+
+If-conversion
+~~~~~~~~~~~~~
+
+If-conversion is an optimisation which can turn code with simple control flow into a single block
+(called a hyper-block), using predicated instructions.
+
+.. _functions:
+
+Functions
+~~~~~~~~~
+
+Functions are currently only inlined in Vericert, however, we are working on a proper interface to
+integrate function calls into the hardware.
+
+.. _coq-style-guide:
+
+Coq Style Guide
+---------------
+
+This style guide was taken from `Silveroak <https://github.com/project-oak/silveroak>`_, it outlines
+code style for Coq code in this repository. There are certainly other valid strategies and opinions
+on Coq code style; this is laid out purely in the name of consistency. For a visual example of the
+style, see the `example`_ at the bottom of this file.
+
+.. _code-organization:
+
+Code organization
+~~~~~~~~~~~~~~~~~
+
+.. _legal-banner:
+
+Legal banner
+^^^^^^^^^^^^
+
+- Files should begin with a copyright/license banner, as shown in the example above.
+
+.. _import-statements:
+
+Import statements
+^^^^^^^^^^^^^^^^^
+
+- ``Require Import`` statements should all go at the top of the file, followed by file-wide ``Import``
+ statements.
+
+ - =Import=s often contain notations or typeclass instances that might override notations or
+ instances from another library, so it’s nice to highlight them separately.
+
+- One ``Require Import`` statement per line; it’s easier to scan that way.
+
+- ``Require Import`` statements should use “fully-qualified” names (e.g. ``Require Import
+ Coq.ZArith.ZArith`` instead of ``Require Import ZArith``).
+
+ - Use the ``Locate`` command to find the fully-qualified name!
+
+- ``Require Import``’s should go in the following order:
+
+ 1. Standard library dependencies (start with ``Coq.``)
+
+ 2. External dependencies (anything outside the current project)
+
+ 3. Same-project dependencies
+
+- ``Require Import``’s with the same root library (the name before the first ``.``) should be
+ grouped together. Within each root-library group, they should be in alphabetical order (so
+ ``Coq.Lists.List`` before ``Coq.ZArith.ZArith``).
+
+.. _notations-and-scopes:
+
+Notations and scopes
+^^^^^^^^^^^^^^^^^^^^
+
+- Any file-wide ``Local Open Scope``’s should come immediately after the =Import=s (see example).
+
+ - Always use ``Local Open Scope``; just ``Open Scope`` will sneakily open the scope for those who
+ import your file.
+
+- Put notations in their own separate modules or files, so that those who import your file can
+ choose whether or not they want the notations.
+
+ - Conflicting notations can cause a lot of headache, so it comes in very handy to leave this
+ flexibility!
+
+.. _formatting:
+
+Formatting
+~~~~~~~~~~
+
+.. _line-length:
+
+Line length
+^^^^^^^^^^^
+
+- Maximum line length 80 characters.
+
+ - Many Coq IDE setups divide the screen in half vertically and use only half to display source
+ code, so more than 80 characters can be genuinely hard to read on a laptop.
+
+.. _whitespace-and-indentation:
+
+Whitespace and indentation
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- No trailing whitespace.
+
+- Spaces, not tabs.
+
+- Files should end with a newline.
+
+ - Many editors do this automatically on save.
+
+- Colons may be either “English-spaced”, with no space before the colon and one space after (``x:
+ nat``) or “French-spaced”, with one space before and after (``x : nat``).
+
+- Default indentation is 2 spaces.
+
+ - Keeping this small prevents complex proofs from being indented ridiculously far, and matches IDE
+ defaults.
+
+- Use 2-space indents if inserting a line break immediately after:
+
+ - ``Proof.``
+
+ - ``fun <...> =>``
+
+ - ``forall <...>,``
+
+ - ``exists <....>,``
+
+- The style for indenting arguments in function application depends on where you make a line
+ break. If you make the line break immediately after the function name, use a 2-space
+ indent. However, if you make it after one or more arguments, align the next line with the first
+ argument:
+
+ .. code:: coq
+
+ (Z.pow
+ 1 2)
+ (Z.pow 1 2 3
+ 4 5 6)
+
+- ``Inductive`` cases should not be indented. Example:
+
+ .. code:: coq
+
+ Inductive Foo : Type :=
+ | FooA : Foo
+ | FooB : Foo
+ .
+
+- ``match`` or ``lazymatch`` cases should line up with the “m” in ``match`` or “l” in ``lazymatch``,
+ as in the following examples:
+
+ .. code:: coq
+
+ match x with
+ | 3 => true
+ | _ => false
+ end.
+
+ lazymatch x with
+ | 3 => idtac
+ | _ => fail "Not equal to 3:" x
+ end.
+
+ repeat match goal with
+ | _ => progress subst
+ | _ => reflexivity
+ end.
+
+ do 2 lazymatch goal with
+ | |- context [eq] => idtac
+ end.
+
+.. _definitions-and-fixpoints:
+
+Definitions and Fixpoints
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- It’s okay to leave the return type of ``Definition``’s and ``Fixpoint``’s implicit
+ (e.g. ``Definition x := 5`` instead of ``Definition x : nat := 5``) when the type is very simple
+ or obvious (for instance, the definition is in a file which deals exclusively with operations on
+ ``Z``).
+
+.. _inductives:
+
+Inductives
+~~~~~~~~~~
+
+- The ``.`` ending an ``Inductive`` can be either on the same line as the last case or on its own
+ line immediately below. That is, both of the following are acceptable:
+
+ .. code:: coq
+
+ Inductive Foo : Type :=
+ | FooA : Foo
+ | FooB : Foo
+ .
+ Inductive Foo : Type :=
+ | FooA : Foo
+ | FooB : Foo.
+
+.. _lemmatheorem-statements:
+
+Lemma/Theorem statements
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Generally, use ``Theorem`` for the most important, top-level facts you prove and ``Lemma`` for
+ everything else.
+
+- Insert a line break after the colon in the lemma statement.
+
+- Insert a line break after the comma for ``forall`` or ``exist`` quantifiers.
+
+- Implication arrows (``->``) should share a line with the previous hypothesis, not the following
+ one.
+
+- There is no need to make a line break after every ``->``; short preconditions may share a line.
+
+.. _proofs-and-tactics:
+
+Proofs and tactics
+~~~~~~~~~~~~~~~~~~
+
+- Use the ``Proof`` command (lined up vertically with ``Lemma`` or ``Theorem`` it corresponds to) to
+ open a proof, and indent the first line after it 2 spaces.
+
+- Very small proofs (where ``Proof. <tactics> Qed.`` is <= 80 characters) can go all in one line.
+
+- When ending a proof, align the ending statement (``Qed``, ``Admitted``, etc.) with ``Proof``.
+
+- Avoid referring to autogenerated names (e.g. ``H0``, ``n0``). It’s okay to let Coq generate these
+ names, but you should not explicitly refer to them in your proof. So ``intros; my_solver`` is
+ fine, but ``intros; apply H1; my_solver`` is not fine.
+
+ - You can force a non-autogenerated name by either putting the variable before the colon in the
+ lemma statement (``Lemma foo x : ...`` instead of ``Lemma foo : forall x, ...``), or by passing
+ arguments to ``intros`` (e.g. ``intros ? x`` to name the second argument ``x``)
+
+- This way, the proof won’t break when new hypotheses are added or autogenerated variable names
+ change.
+
+- Use curly braces ``{}`` for subgoals, instead of bullets.
+
+- *Never write tactics with more than one subgoal focused.* This can make the proof very confusing
+ to step through! If you have more than one subgoal, use curly braces.
+
+- Consider adding a comment after the opening curly brace that explains what case you’re in (see
+ example).
+
+ - This is not necessary for small subgoals but can help show the major lines of reasoning in large
+ proofs.
+
+- If invoking a tactic that is expected to return multiple subgoals, use ``[ | ... | ]`` before the
+ ``.`` to explicitly specify how many subgoals you expect.
+
+ - Examples: ``split; [ | ].`` ``induction z; [ | | ].``
+
+ - This helps make code more maintainable, because it fails immediately if your tactic no longer
+ solves as many subgoals as expected (or unexpectedly solves more).
+
+- If invoking a string of tactics (composed by ``;``) that will break the goal into multiple
+ subgoals and then solve all but one, still use ``[ ]`` to enforce that all but one goal is solved.
+
+ - Example: ``split; try lia; [ ]``.
+
+- Tactics that consist only of ``repeat``-ing a procedure (e.g. ``repeat match``, ``repeat first``)
+ should factor out a single step of that procedure a separate tactic called ``<tactic name>_step``,
+ because the single-step version is much easier to debug. For instance:
+
+ .. code:: coq
+
+ Ltac crush_step :=
+ match goal with
+ | _ => progress subst
+ | _ => reflexivity
+ end.
+ Ltac crush := repeat crush_step.
+
+.. _naming:
+
+Naming
+~~~~~~
+
+- Helper proofs about standard library datatypes should go in a module that is named to match the
+ standard library module (see example).
+
+ - This makes the helper proofs look like standard-library ones, which is helpful for categorizing
+ them if they’re genuinely at the standard-library level of abstraction.
+
+- Names of modules should start with capital letters.
+
+- Names of inductives and their constructors should start with capital letters.
+
+- Names of other definitions/lemmas should be snake case.
+
+.. _example:
+
+Example
+~~~~~~~
+
+A small standalone Coq file that exhibits many of the style points.
+
+.. coq:: no-out
+
+ (*
+ * Vericert: Verified high-level synthesis.
+ * Copyright (C) 2021 Name <email@example.com>
+ *
+ * <License...>
+ *)
+
+ Require Import Coq.Lists.List.
+ Require Import Coq.micromega.Lia.
+ Require Import Coq.ZArith.ZArith.
+ Import ListNotations.
+ Local Open Scope Z_scope.
+
+ (* Helper proofs about standard library integers (Z) go within [Module Z] so
+ that they match standard-library Z lemmas when used. *)
+ Module Z.
+ Lemma pow_3_r x : x ^ 3 = x * x * x.
+ Proof. lia. Qed. (* very short proofs can go all on one line *)
+
+ Lemma pow_4_r x : x ^ 4 = x * x * x * x.
+ Proof.
+ change 4 with (Z.succ (Z.succ (Z.succ (Z.succ 0)))).
+ repeat match goal with
+ | _ => rewrite Z.pow_1_r
+ | _ => rewrite Z.pow_succ_r by lia
+ | |- context [x * (?a * ?b)] =>
+ replace (x * (a * b)) with (a * b * x) by lia
+ | _ => reflexivity
+ end.
+ Qed.
+ End Z.
+ (* Now we can access the lemmas above as Z.pow_3_r and Z.pow_4_r, as if they
+ were in the ZArith library! *)
+
+ Definition bar (x y : Z) := x ^ (y + 1).
+
+ (* example with a painfully manual proof to show case formatting *)
+ Lemma bar_upper_bound :
+ forall x y a,
+ 0 <= x <= a -> 0 <= y ->
+ 0 <= bar x y <= a ^ (y + 1).
+ Proof.
+ (* avoid referencing autogenerated names by explicitly naming variables *)
+ intros x y a Hx Hy. revert y Hy x a Hx.
+ (* explicitly indicate # subgoals with [ | ... | ] if > 1 *)
+ cbv [bar]; refine (natlike_ind _ _ _); [ | ].
+ { (* y = 0 *)
+ intros; lia. }
+ { (* y = Z.succ _ *)
+ intros.
+ rewrite Z.add_succ_l, Z.pow_succ_r by lia.
+ split.
+ { (* 0 <= bar x y *)
+ apply Z.mul_nonneg_nonneg; [ lia | ].
+ apply Z.pow_nonneg; lia. }
+ { (* bar x y < a ^ y *)
+ rewrite Z.pow_succ_r by lia.
+ apply Z.mul_le_mono_nonneg; try lia;
+ [ apply Z.pow_nonneg; lia | ].
+ (* For more flexible proofs, use match statements to find hypotheses
+ rather than referring to them by autogenerated names like H0. In this
+ case, we'll take any hypothesis that applies to and then solves the
+ goal. *)
+ match goal with H : _ |- _ => apply H; solve [auto] end. } }
+ Qed.
+
+ (* Put notations in a separate module or file so that importers can
+ decide whether or not to use them. *)
+ Module BarNotations.
+ Infix "#" := bar (at level 40) : Z_scope.
+ Notation "x '##'" := (bar x x) (at level 40) : Z_scope.
+ End BarNotations.
diff --git a/docs b/docs
deleted file mode 160000
-Subproject 36abd86820f7521fcebb3b173acbcb6409b148b
diff --git a/driver/VericertDriver.ml b/driver/VericertDriver.ml
index a36f375..e89ff86 100644
--- a/driver/VericertDriver.ml
+++ b/driver/VericertDriver.ml
@@ -67,6 +67,7 @@ let compile_c_file sourcename ifile ofile =
set_dest Vericert.PrintRTL.destination option_drtl ".rtl";
set_dest Vericert.PrintRTLBlock.destination option_drtlblock ".rtlblock";
set_dest Vericert.PrintRTLPar.destination option_drtlpar ".rtlpar";
+ set_dest Vericert.PrintRTLParFU.destination option_drtlparfu ".rtlparfu";
set_dest Vericert.PrintHTL.destination option_dhtl ".htl";
set_dest Vericert.Regalloc.destination_alloctrace option_dalloctrace ".alloctrace";
set_dest Vericert.PrintLTL.destination option_dltl ".ltl";
@@ -393,6 +394,7 @@ let cmdline_actions =
Exact "-drtl", Set option_drtl;
Exact "-drtlblock", Set option_drtlblock;
Exact "-drtlpar", Set option_drtlpar;
+ Exact "-drtlparfu", Set option_drtlparfu;
Exact "-dhtl", Set option_dhtl;
Exact "-dltl", Set option_dltl;
Exact "-dalloctrace", Set option_dalloctrace;
@@ -407,6 +409,7 @@ let cmdline_actions =
option_drtl := true;
option_drtlblock := true;
option_drtlpar := true;
+ option_drtlparfu := true;
option_dhtl := true;
option_dltl := true;
option_dalloctrace := true;
@@ -421,10 +424,10 @@ let cmdline_actions =
warning_options @
(* Vericert.Interpreter mode *)
[ Exact "-interp", Set option_interp;
- Exact "-quiet", Unit (fun () -> Vericert.Interp.trace := 0);
- Exact "-trace", Unit (fun () -> Vericert.Interp.trace := 2);
- Exact "-random", Unit (fun () -> Vericert.Interp.mode := Vericert.Interp.Random);
- Exact "-all", Unit (fun () -> Vericert.Interp.mode := Vericert.Interp.All)
+ Exact "-quiet", Unit (fun () -> Vericert.Interp.trace := 0);
+ Exact "-trace", Unit (fun () -> Vericert.Interp.trace := 2);
+ Exact "-random", Unit (fun () -> Vericert.Interp.mode := Vericert.Interp.Random);
+ Exact "-all", Unit (fun () -> Vericert.Interp.mode := Vericert.Interp.All)
]
(* Optimization options *)
(* -f options: come in -f and -fno- variants *)
diff --git a/dune b/dune
index f58c64e..9bd70aa 100644
--- a/dune
+++ b/dune
@@ -8,4 +8,4 @@
(public_name vericert)
(modules_without_implementation c debugTypes dwarfTypes)
(libraries menhirLib str unix ocamlgraph)
- (flags (:standard -warn-error -A)))
+ (flags (:standard -warn-error -A -w -8-9-16-20-26-27-32..36-39-41-44..45-50-60-67)))
diff --git a/ip/altera.v b/ip/altera.sv
index 3839cbe..3839cbe 100644
--- a/ip/altera.v
+++ b/ip/altera.sv
diff --git a/ip/div_signed.v b/ip/div_signed.sv
index 7aab57c..7aab57c 100644
--- a/ip/div_signed.v
+++ b/ip/div_signed.sv
diff --git a/ip/div_unsigned.v b/ip/div_unsigned.sv
index db70758..db70758 100644
--- a/ip/div_unsigned.v
+++ b/ip/div_unsigned.sv
diff --git a/lib/CompCert b/lib/CompCert
-Subproject 1daf96cdca4d828c333cea5c9a314ef86134298
+Subproject 4f467596f8674f5f4fbf84a793cb8fcfc35a44a
diff --git a/scripts/Makefile b/scripts/Makefile
new file mode 100644
index 0000000..3892723
--- /dev/null
+++ b/scripts/Makefile
@@ -0,0 +1,25 @@
+PREFIX ?= ..
+
+all: synthesis-results
+
+%: %.scm
+ $(eval TMP := $(shell mktemp))
+ echo "(main (command-line-arguments))" >$(TMP)
+ chicken-csc -static -epilogue $(TMP) -output-file $@ $<
+ rm $(TMP)
+
+%.1: %.org
+ emacs --batch --file $< --load ../docs/res/publish.el --funcall org-man-export-to-man
+ mv $(<:.org=.man) $@
+
+install: synthesis-results synthesis-results.1
+ install -d $(PREFIX)/bin
+ install -C synthesis-results $(PREFIX)/bin
+ install -d $(PREFIX)/share/man/man1
+ install -C -m 644 synthesis-results.1 $(PREFIX)/share/man/man1
+
+clean:
+ rm -f synthesis-results synthesis-results.1
+ rm -f *.link
+
+.PHONY: all install
diff --git a/scripts/convert.sh b/scripts/convert.sh
deleted file mode 100755
index c2ef311..0000000
--- a/scripts/convert.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-file=$1
-benchmark=$(echo $1 | sed 's:.*/\([^/]\+\)/encode_report.xml:\1:')
-
-lut_flip_flop=$(sed -n "s/.*XILINX_LUT_FLIP_FLOP_PAIRS_USED.*\"\([0-9.]*\)\".*/\1/p" $file)
-slice=$(sed -n "s/.*XILINX_SLICE\".*\"\([0-9.]*\)\".*/\1/p" $file)
-regs=$(sed -n "s/.*XILINX_SLICE_REGISTERS.*\"\([0-9.]*\)\".*/\1/p" $file)
-luts=$(sed -n "s/.*XILINX_SLICE_LUTS.*\"\([0-9.]*\)\".*/\1/p" $file)
-ramfifo=$(sed -n "s/.*XILINX_BLOCK_RAMFIFO.*\"\([0-9.]*\)\".*/\1/p" $file)
-iopin=$(sed -n "s/.*XILINX_IOPIN.*\"\([0-9.]*\)\".*/\1/p" $file)
-dsps=$(sed -n "s/.*XILINX_DSPS.*\"\([0-9.]*\)\".*/\1/p" $file)
-power=$(sed -n "s/.*XILINX_POWER.*\"\([0-9.]*\)\".*/\1/p" $file)
-delay=$(sed -n "s/.*XILINX_DESIGN_DELAY.*\"\([0-9.]*\)\".*/\1/p" $file)
-
-echo $benchmark,$lut_flip_flop,$slice,$regs,$luts,$ramfifo,$iopin,$dsps,$power,$delay >>synth.csv
diff --git a/scripts/download_artifact.sh b/scripts/download_artifact.sh
deleted file mode 100755
index cac69f6..0000000
--- a/scripts/download_artifact.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-mkdir -p docs/html/proof
-cd docs/html/proof
-curl -v -L -H "Accept: application/vnd.github.v3+json" -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/repos/ymherklotz/vericert/actions/artifacts/26286264/zip -o html-documentation.zip
-unzip html-documentation.zip
-rm html-documentation.zip
-cp ../../css/coqdoc.css .
diff --git a/benchmarks/polybench-syn-div/quartus_synth.tcl b/scripts/quartus_synth.tcl
index 6edbf0c..6edbf0c 100644
--- a/benchmarks/polybench-syn-div/quartus_synth.tcl
+++ b/scripts/quartus_synth.tcl
diff --git a/scripts/run-legup.sh b/scripts/run-legup.sh
index 3b6f60f..3b6f60f 100644..100755
--- a/scripts/run-legup.sh
+++ b/scripts/run-legup.sh
diff --git a/benchmarks/polybench-syn/run-vericert.sh b/scripts/run-vericert.sh
index ef6964f..9deaa10 100755
--- a/benchmarks/polybench-syn/run-vericert.sh
+++ b/scripts/run-vericert.sh
@@ -10,27 +10,31 @@ while read benchmark ; do
cresult=$(cat $benchmark.clog | cut -d' ' -f2)
#echo "C output: "$cresult
#./$benchmark.iver > $benchmark.tmp
+ if [[ ! -f ./$benchmark.verilator/Vmain ]]; then
+ echo -e "\e[0;91mFAIL\e[0m: Verilog failed compilation"
+ continue
+ fi
./$benchmark.verilator/Vmain > $benchmark.tmp
veriresult=$(tail -1 $benchmark.tmp | cut -d' ' -f2)
cycles=$(tail -2 $benchmark.tmp | head -1 | tr -s ' ' | cut -d' ' -f2)
#echo "Verilog output: "$veriresult
#Undefined checks
- if test -z $veriresult
+ if [[ -z "$veriresult" ]]
then
echo "\e[0;91mFAIL\e[0m: Verilog returned nothing"
#exit 0
fi
# Don't care checks
- if [ $veriresult == "x" ]
+ if [[ $veriresult == "x" ]]
then
echo "\e[0;91mFAIL\e[0m: Verilog returned don't cares"
#exit 0
fi
# unequal result check
- if [ $cresult -ne $veriresult ]
+ if [[ $cresult -ne $veriresult ]]
then
echo -e "\e[0;91mFAIL\e[0m: Verilog and C output do not match!"
#exit 0
diff --git a/scripts/run-vivado.sh b/scripts/run-vivado.sh
deleted file mode 100755
index 117054d..0000000
--- a/scripts/run-vivado.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash
-
-benchmark=./$1/$2
-echo $benchmark
-
- cp ./synth.tcl $benchmark/. 2>/dev/null
- cd $benchmark || exit 1
- vivado -mode batch -source synth.tcl >vivado.log 2>&1
diff --git a/benchmarks/polybench-syn-div/script.R b/scripts/script.R
index 0be16da..0be16da 100644
--- a/benchmarks/polybench-syn-div/script.R
+++ b/scripts/script.R
diff --git a/benchmarks/polybench-syn-div/syn-remote.sh b/scripts/syn-remote.sh
index 879db2e..879db2e 100755
--- a/benchmarks/polybench-syn-div/syn-remote.sh
+++ b/scripts/syn-remote.sh
diff --git a/scripts/synth-ssh.sh b/scripts/synth-ssh.sh
new file mode 100755
index 0000000..a6ce349
--- /dev/null
+++ b/scripts/synth-ssh.sh
@@ -0,0 +1,28 @@
+#!/usr/bin/bash
+
+# Assumes that the Verilog is passed on the command line, that the tcl file is in synth.tcl and
+# returns encode_report.xml.
+
+scriptsdir=$(dirname "$(readlink -f "$BASH_SOURCE")")
+
+num=$1
+bench=$2
+output=$3
+machine=ee-beholder${num}.ee.ic.ac.uk
+user=ymh15
+files="$scriptsdir/synth.tcl $output/$bench.v"
+log="$output/${bench}_synth.log"
+
+date >$log
+
+temp=$(ssh $user@$machine "mktemp -d" 2>>$log)
+
+>&2 echo "synthesising $bench $temp"
+rsync $files $user@$machine:$temp/ >>$log 2>&1
+ssh $user@$machine \
+ "bash -lc 'cd $temp && cp $(basename $bench).v main.v && vivado -mode batch -source synth.tcl'" \
+ >>$log 2>&1
+rsync $user@$machine:$temp/encode_report.xml $output/${bench}_report.xml >>$log 2>&1
+ssh $user@$machine "rm -rf '$temp'" >>$log 2>&1
+rm -f main.v >>$log 2>&1
+>&2 echo "done $bench"
diff --git a/scripts/synth.sh b/scripts/synth.sh
new file mode 100755
index 0000000..b1c2696
--- /dev/null
+++ b/scripts/synth.sh
@@ -0,0 +1,32 @@
+#!/usr/bin/bash
+
+set -x
+
+scriptsdir=$(dirname "$(readlink -f "$BASH_SOURCE")")
+
+if [[ -z "$1" ]]; then
+ parallel=1
+else
+ parallel=$1
+fi
+
+if [[ -z "$2" ]]; then
+ output=$(pwd)
+else
+ output=$2
+fi
+
+if [[ -z "$3" ]]; then
+ source=$(pwd)
+else
+ source=$3
+fi
+
+echo "copying directory structure from $source to $output"
+mkdir -p $output
+rsync -am --include '*/' --include '*.v' --exclude '*' $source/ $output/
+
+echo "executing $parallel runs in parallel"
+cat $scriptsdir/../benchmarks/polybench-syn/benchmark-list-master | \
+ xargs --max-procs=$parallel --replace=% \
+ $scriptsdir/synth-ssh.sh 0 % $output
diff --git a/scripts/synth.tcl b/scripts/synth.tcl
index e5151e8..a2fb722 100644
--- a/scripts/synth.tcl
+++ b/scripts/synth.tcl
@@ -76,7 +76,7 @@ proc dump_statistics { } {
}; #END PROC
set outputDir .
create_project -in_memory -part xc7z020clg484-1 -force
-read_verilog main.v
+read_verilog -sv main.v
synth_design -mode out_of_context -no_iobuf -top main -part xc7z020clg484-1
write_checkpoint -force $outputDir/post_synth.dcp
report_timing_summary -file $outputDir/post_synth_timing_summary.rpt
diff --git a/scripts/synthesis-results.org b/scripts/synthesis-results.org
new file mode 100644
index 0000000..602b2ba
--- /dev/null
+++ b/scripts/synthesis-results.org
@@ -0,0 +1,44 @@
+#+title: synthesis-results
+#+man_class_options: :section-id "1"
+#+options: toc:nil num:nil
+#+html_head_extra: <style>body{font-family:monospace;max-width:60em}h1{text-align:center}dt{font-weight:700}dd{margin-bottom:1em}</style>
+
+* NAME
+
+synthesis-results: sends a verilog file to be synthesised and returns results as a CSV file.
+
+* SYNOPSYS
+
+Usage: *synthesis-results* [options...] [files...]
+
+* DESCRIPTION
+
+- -v, --verbose[=LEVEL] :: Debug level [default: 0]
+- -k, --keys=KEY,KEY,... :: Keys to display [default: slice,ramfifo,delay]
+- -o, --output=FILE :: Output file
+- -s, --suppress=TYPE,TYPE,... :: Values to suppress from output [default: none]
+- -x, --xml :: Output raw XML from the synthesis tool
+- -c, --csv :: Output processed CSV
+- -V, --version :: Display version
+- -h, --help :: Display this text
+
+* AUTHOR
+
+Written by Yann Herklotz.
+
+* COPYRIGHT
+
+Copyright (C) 2022 Yann Herklotz <yann@yannherklotz.com>
+
+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 <https://www.gnu.org/licenses/>.
diff --git a/scripts/synthesis-results.scm b/scripts/synthesis-results.scm
new file mode 100755
index 0000000..b1a7349
--- /dev/null
+++ b/scripts/synthesis-results.scm
@@ -0,0 +1,170 @@
+#! /usr/bin/chicken-csi -ss
+;; -*- mode: scheme -*-
+;;
+;; Copyright (C) 2022 Yann Herklotz <yann@yannherklotz.com>
+;;
+;; 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 <https://www.gnu.org/licenses/>.
+
+(import (chicken file)
+ (chicken io)
+ (chicken irregex)
+ (chicken port)
+ (chicken process-context)
+ (chicken sort)
+ (chicken string)
+ args
+ matchable
+ srfi-193
+ ssax)
+
+(define options)
+(define operands)
+
+(define (check-opt b) (cdr (or (assoc b options) `(,b . #f))))
+
+(define opts
+ (list (args:make-option (v verbose) (optional: "LEVEL") "Debug level [default: 0]"
+ (set! arg (or arg "0")))
+ (args:make-option (k keys) (required: "KEY,KEY,...") "Keys to display [default: slice,ramfifo,delay]")
+ (args:make-option (o output) (required: "FILE") "Output file")
+ (args:make-option (default-sort) #:none "Don't the names of the benchmarks")
+ (args:make-option (suppress) (required: "TYPE,TYPE,...") "Values to suppress from output [default: none]")
+ (args:make-option (c csv) #:none "Output processed CSV")
+ (args:make-option (cycle-file) (required: "FILE") "File which contains the cycle counts for the benchmark")
+ (args:make-option (org) #:none "Output processed Org")
+ (args:make-option (V version) #:none "Display version"
+ (print "synthesis-results v0.2.0")
+ (exit))
+ (args:make-option (h help) #:none "Display this text"
+ (usage))))
+
+(: description string)
+(define description
+ "synthesis-results: sends a verilog file to be synthesised and returns results as a CSV file.")
+
+(define (usage)
+ (with-output-to-port (current-error-port)
+ (lambda ()
+ (print description)
+ (newline)
+ (print "Usage: " (program-name) " [options...] [files...]")
+ (newline)
+ (print (args:usage opts))
+ (print "Report bugs to git at yannherklotz dot com.")))
+ (exit 1))
+
+(define (map-names n)
+ (match n
+ ["XILINX_LUT_FLIP_FLOP_PAIRS_USED" "lut_flip_flop"]
+ ["XILINX_SLICE" "slice"]
+ ["XILINX_SLICE_REGISTERS" "regs"]
+ ["XILINX_SLICE_LUTS" "luts"]
+ ["XILINX_BLOCK_RAMFIFO" "ramfifo"]
+ ["XILINX_IOPIN" "iopin"]
+ ["XILINX_DSPS" "dsps"]
+ ["XILINX_POWER" "power"]
+ ["XILINX_DESIGN_DELAY" "delay"]
+ [_ n]))
+
+(define (csv:fmt-row l) (string-intersperse (map ->string l) ","))
+
+(define (org:fmt-row l) (string-append "| " (string-intersperse (map ->string l) " | ") " |"))
+
+(define (csv:fmt-table-string l) (apply string-append (map (lambda (s) (string-append s "\n")) l)))
+
+(define (csv:fmt-table l) (apply string-append (map (lambda (s) (string-append s "\n"))
+ (map csv:fmt-row l))))
+
+(define (xml-matcher xml)
+ (match xml
+ [('*TOP* _ ('document ('application ('section _ . r))))
+ (map (match-lambda
+ [('item ('@ ('value v) ('stringID s))) (cons (map-names s) (string->number v))]) r)]))
+
+(define (parse-xml name file)
+ (with-input-from-file file
+ (lambda ()
+ (cons name (xml-matcher (ssax:xml->sxml (current-input-port) '()))))))
+
+(define (ifn-cons b c l)
+ (if b l (cons c l)))
+
+(define ((to-csv-record fmt-row b head) results)
+ (let ((res (map (lambda (key)
+ (cdr (assoc key (cadr results)))) head)))
+ (fmt-row (ifn-cons b (car results) res))))
+
+(: path-to-name (string -> string))
+(define (path-to-name path)
+ (irregex-replace "^.*?([^/]+)_report\\.xml$" path 1))
+
+(define (order-data d1 d2)
+ (match (list d1 d2)
+ [((n1 . _) (n2 . _)) (string<? n1 n2)]))
+
+(define (convert-files sort? files)
+ ((if sort? (lambda (l) (sort l order-data)) identity)
+ (map (lambda (f) (parse-xml (path-to-name f) f)) files)))
+
+(: split-at-comma (string -> (list-of string)))
+(define (split-at-comma s) (string-split s ","))
+
+(define (parse-cycles f)
+ (if f (with-input-from-file f
+ (lambda () (map (match-lambda [(a b) (cons a b)]) (map split-at-comma (read-lines))))) #f))
+
+(: find-all-xml (string -> (list-of string)))
+(define (find-all-xml dir) (find-files dir #:test ".*\\.xml$"))
+
+(define (get-files-from-op operands)
+ (match operands
+ [(d) (cond [(directory-exists? d) (find-all-xml d)]
+ [else (list d)])]
+ [_ operands]))
+
+(define (with-output thk)
+ (if (check-opt 'output)
+ (with-output-to-file (check-opt 'output) thk)
+ (thk)))
+
+(define (row-fmt)
+ (if (check-opt 'org) org:fmt-row csv:fmt-row))
+
+(define (cycle-file operands)
+ (let ((dir (match operands
+ [(d) (when (directory-exists? d) d)]
+ [_ #f])))
+ (or (check-opt 'cycle-file) (if dir (string-append dir "/exec.csv") #f))))
+
+(define (add-cycles data cycles)
+ (if cycles
+ (map (lambda (f) (list (car f) (cons (cons "cycles" (cdr (assoc (car f) cycles))) (cdr f)))) data)
+ data))
+
+(define (main args)
+ (set!-values (options operands)
+ (args:parse args opts))
+ (let ((head (split-at-comma (or (check-opt 'keys) "slice,ramfifo,delay,cycles")))
+ (suppress (split-at-comma (or (check-opt 'suppress) "none")))
+ (files (get-files-from-op operands)))
+ (let ((data (convert-files (not (check-opt 'default-sort)) files))
+ (header ((row-fmt) (ifn-cons (member "name" suppress) "name" head)))
+ (cycles (parse-cycles (cycle-file operands))))
+ (with-output
+ (lambda ()
+ (display (csv:fmt-table-string
+ (ifn-cons (member "header" suppress) header
+ (map (to-csv-record (row-fmt)
+ (member "name" suppress)
+ head) (add-cycles data cycles))))))))))
diff --git a/driver/verilator_main.cpp b/scripts/verilator_main.cpp
index 4561158..94b6a33 100644
--- a/driver/verilator_main.cpp
+++ b/scripts/verilator_main.cpp
@@ -19,7 +19,7 @@ int main(int argc, char **argv) {
tb->reset = 0;
tb->eval(); tb->clk = 1; tb->eval(); tb->clk = 0; tb->eval();
- int cycles = 1;
+ size_t cycles = 1;
// Tick the clock until we are done
while(!tb->finish) {
@@ -30,6 +30,6 @@ int main(int argc, char **argv) {
cycles++;
}
- printf("cycles: %d\nfinished: %d\n", cycles, (unsigned)tb->return_val);
+ printf("cycles: %lu\nfinished: %u\n", cycles, (unsigned)tb->return_val);
exit(EXIT_SUCCESS);
}
diff --git a/src/Compiler.v b/src/Compiler.v
index ecea2fc..d6d87e2 100644
--- a/src/Compiler.v
+++ b/src/Compiler.v
@@ -1,39 +1,37 @@
(*|
-.. coq:: none
-|*)
+..
+ Vericert: Verified high-level synthesis.
+ Copyright (C) 2019-2022 Yann Herklotz <yann@yannherklotz.com>
-(*
- * Vericert: Verified high-level synthesis.
- * Copyright (C) 2019-2020 Yann Herklotz <yann@yannherklotz.com>
- *
- * 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 <https://www.gnu.org/licenses/>.
- *)
+ 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 <https://www.gnu.org/licenses/>.
-(*|
==============
Compiler Proof
==============
-.. contents:: Table of Contents
- :depth: 2
-
-This is the top-level module of the correctness proof and proves the final backwards simulation correct.
+This is the top-level module of the correctness proof and proves the final
+backwards simulation correct.
Imports
=======
-We first need to import all of the modules that are used in the correctness proof, which includes all of the passes that are performed in Vericert and the CompCert front end.
+
+We first need to import all of the modules that are used in the correctness
+proof, which includes all of the passes that are performed in Vericert and the
+CompCert front end.
+
+.. coq:: none
|*)
Require compcert.backend.Selection.
@@ -65,9 +63,11 @@ Require vericert.hls.HTLgen.
Require vericert.hls.RTLBlock.
Require vericert.hls.RTLBlockgen.
Require vericert.hls.RTLPargen.
+Require vericert.hls.RTLParFUgen.
Require vericert.hls.HTLPargen.
-Require vericert.hls.Pipeline.
+(*Require vericert.hls.Pipeline.*)
Require vericert.hls.IfConversion.
+(*Require vericert.hls.PipelineOp.*)
Require vericert.HLSOpts.
Require vericert.hls.Memorygen.
@@ -77,13 +77,16 @@ Require Import vericert.hls.HTLgenproof.
Declarations
============
-We then need to declare the external OCaml functions used to print out intermediate steps in the compilation, such as ``print_RTL``, ``print_HTL`` and ``print_RTLBlock``.
+We then need to declare the external OCaml functions used to print out
+intermediate steps in the compilation, such as ``print_RTL``, ``print_HTL`` and
+``print_RTLBlock``.
|*)
Parameter print_RTL: Z -> RTL.program -> unit.
Parameter print_HTL: Z -> HTL.program -> unit.
Parameter print_RTLBlock: Z -> RTLBlock.program -> unit.
Parameter print_RTLPar: Z -> RTLPar.program -> unit.
+Parameter print_RTLParFU: Z -> RTLParFU.program -> unit.
Definition print {A: Type} (printer: A -> unit) (prog: A) : A :=
let unused := printer prog in prog.
@@ -96,7 +99,8 @@ Proof.
Qed.
(*|
-We also declare some new notation, which is also used in CompCert to combine the monadic results of each pass.
+We also declare some new notation, which is also used in CompCert to combine the
+monadic results of each pass.
|*)
Notation "a @@@ b" :=
@@ -105,7 +109,8 @@ Notation "a @@ b" :=
(Compiler.apply_total _ _ a b) (at level 50, left associativity).
(*|
-As printing is used in the translation but does not change the output, we need to prove that it has no effect so that it can be removed during the proof.
+As printing is used in the translation but does not change the output, we need
+to prove that it has no effect so that it can be removed during the proof.
|*)
Lemma compose_print_identity:
@@ -116,7 +121,8 @@ Proof.
Qed.
(*|
-Finally, some optimisation passes are only activated by a flag, which is handled by the following functions for partial and total passes.
+Finally, some optimisation passes are only activated by a flag, which is handled
+by the following functions for partial and total passes.
|*)
Definition total_if {A: Type}
@@ -129,24 +135,28 @@ Definition partial_if {A: Type}
Definition time {A B: Type} (name: string) (f: A -> B) : A -> B := f.
-Definition match_if {A: Type} (flag: unit -> bool) (R: A -> A -> Prop): A -> A -> Prop :=
+Definition match_if {A: Type} (flag: unit -> bool) (R: A -> A -> Prop)
+ : A -> A -> Prop :=
if flag tt then R else eq.
Lemma total_if_match:
- forall (A: Type) (flag: unit -> bool) (f: A -> A) (rel: A -> A -> Prop) (prog: A),
- (forall p, rel p (f p)) ->
+ forall (A: Type) (flag: unit -> bool) (f: A -> A)
+ (rel: A -> A -> Prop) (prog: A),
+ (forall p, rel p (f p)) ->
match_if flag rel prog (total_if flag f prog).
Proof.
intros. unfold match_if, total_if. destruct (flag tt); auto.
Qed.
Lemma partial_if_match:
- forall (A: Type) (flag: unit -> bool) (f: A -> res A) (rel: A -> A -> Prop) (prog tprog: A),
+ forall (A: Type) (flag: unit -> bool) (f: A -> res A)
+ (rel: A -> A -> Prop) (prog tprog: A),
(forall p tp, f p = OK tp -> rel p tp) ->
partial_if flag f prog = OK tprog ->
match_if flag rel prog tprog.
Proof.
- intros. unfold match_if, partial_if in *. destruct (flag tt). auto. congruence.
+ intros. unfold match_if, partial_if in *. destruct (flag tt).
+ auto. congruence.
Qed.
Remark forward_simulation_identity:
@@ -160,19 +170,24 @@ Proof.
Qed.
Lemma match_if_simulation:
- forall (A: Type) (sem: A -> semantics) (flag: unit -> bool) (transf: A -> A -> Prop) (prog tprog: A),
+ forall (A: Type) (sem: A -> semantics) (flag: unit -> bool)
+ (transf: A -> A -> Prop) (prog tprog: A),
match_if flag transf prog tprog ->
(forall p tp, transf p tp -> forward_simulation (sem p) (sem tp)) ->
forward_simulation (sem prog) (sem tprog).
Proof.
- intros. unfold match_if in *. destruct (flag tt). eauto. subst. apply forward_simulation_identity.
+ intros. unfold match_if in *. destruct (flag tt). eauto. subst.
+ apply forward_simulation_identity.
Qed.
(*|
Top-level Translation
---------------------
-An optimised transformation function from ``RTL`` to ``Verilog`` can then be defined, which applies the front end compiler optimisations of CompCert to the RTL that is generated and then performs the two Vericert passes from RTL to HTL and then from HTL to Verilog.
+An optimised transformation function from ``RTL`` to ``Verilog`` can then be
+defined, which applies the front end compiler optimisations of CompCert to the
+RTL that is generated and then performs the two Vericert passes from RTL to HTL
+and then from HTL to Verilog.
|*)
Definition transf_backend (r : RTL.program) : res Verilog.program :=
@@ -181,24 +196,28 @@ Definition transf_backend (r : RTL.program) : res Verilog.program :=
@@ print (print_RTL 1)
@@ Renumber.transf_program
@@ print (print_RTL 2)
- @@ total_if Compopts.optim_constprop (time "Constant propagation" Constprop.transf_program)
+ @@ total_if Compopts.optim_constprop
+ (time "Constant propagation" Constprop.transf_program)
@@ print (print_RTL 3)
- @@ total_if Compopts.optim_constprop (time "Renumbering" Renumber.transf_program)
+ @@ total_if Compopts.optim_constprop
+ (time "Renumbering" Renumber.transf_program)
@@ print (print_RTL 4)
@@@ partial_if Compopts.optim_CSE (time "CSE" CSE.transf_program)
@@ print (print_RTL 5)
- @@@ partial_if Compopts.optim_redundancy (time "Redundancy elimination" Deadcode.transf_program)
+ @@@ partial_if Compopts.optim_redundancy
+ (time "Redundancy elimination" Deadcode.transf_program)
@@ print (print_RTL 6)
@@@ time "Unused globals" Unusedglob.transform_program
@@ print (print_RTL 7)
@@@ HTLgen.transl_program
@@ print (print_HTL 0)
- @@ total_if HLSOpts.optim_ram Memorygen.transf_program
- @@ print (print_HTL 1)
+(* @@ total_if HLSOpts.optim_ram Memorygen.transf_program
+ @@ print (print_HTL 1)*)
@@ Veriloggen.transl_program.
(*|
-The transformation functions from RTL to Verilog are then added to the backend of the CompCert transformations from Clight to RTL.
+The transformation functions from RTL to Verilog are then added to the backend
+of the CompCert transformations from Clight to RTL.
|*)
Definition transf_hls (p : Csyntax.program) : res Verilog.program :=
@@ -213,11 +232,9 @@ Definition transf_hls (p : Csyntax.program) : res Verilog.program :=
@@@ transf_backend.
(*|
-.. coq:: none
+This is an unverified version of transf_hls with some experimental additions
+such as scheduling that aren't completed yet.
|*)
-
-(* This is an unverified version of transf_hls with some experimental additions such as scheduling
-that aren't completed yet. *)
Definition transf_hls_temp (p : Csyntax.program) : res Verilog.program :=
OK p
@@@ SimplExpr.transl_program
@@ -230,13 +247,16 @@ Definition transf_hls_temp (p : Csyntax.program) : res Verilog.program :=
@@ print (print_RTL 1)
@@ Renumber.transf_program
@@ print (print_RTL 2)
- @@ total_if Compopts.optim_constprop (time "Constant propagation" Constprop.transf_program)
+ @@ total_if Compopts.optim_constprop
+ (time "Constant propagation" Constprop.transf_program)
@@ print (print_RTL 3)
- @@ total_if Compopts.optim_constprop (time "Renumbering" Renumber.transf_program)
+ @@ total_if Compopts.optim_constprop
+ (time "Renumbering" Renumber.transf_program)
@@ print (print_RTL 4)
@@@ partial_if Compopts.optim_CSE (time "CSE" CSE.transf_program)
@@ print (print_RTL 5)
- @@@ partial_if Compopts.optim_redundancy (time "Redundancy elimination" Deadcode.transf_program)
+ @@@ partial_if Compopts.optim_redundancy
+ (time "Redundancy elimination" Deadcode.transf_program)
@@ print (print_RTL 6)
@@@ time "Unused globals" Unusedglob.transform_program
@@ print (print_RTL 7)
@@ -246,6 +266,8 @@ Definition transf_hls_temp (p : Csyntax.program) : res Verilog.program :=
@@ print (print_RTLBlock 1)
@@@ RTLPargen.transl_program
@@ print (print_RTLPar 0)
+ @@@ RTLParFUgen.transl_program
+ @@ print (print_RTLParFU 0)
@@@ HTLPargen.transl_program
@@ print (print_HTL 0)
@@ Veriloggen.transl_program.
@@ -254,7 +276,8 @@ Definition transf_hls_temp (p : Csyntax.program) : res Verilog.program :=
Correctness Proof
=================
-Finally, the top-level definition for all the passes is defined, which combines the ``match_prog`` predicates of each translation pass from C until Verilog.
+Finally, the top-level definition for all the passes is defined, which combines
+the ``match_prog`` predicates of each translation pass from C until Verilog.
|*)
Local Open Scope linking_scope.
@@ -273,20 +296,23 @@ Definition CompCert's_passes :=
::: mkpass (match_if Compopts.optim_CSE CSEproof.match_prog)
::: mkpass (match_if Compopts.optim_redundancy Deadcodeproof.match_prog)
::: mkpass Unusedglobproof.match_prog
- ::: (@mkpass _ _ HTLgenproof.match_prog (HTLgenproof.TransfHTLLink HTLgen.transl_program))
- ::: mkpass (match_if HLSOpts.optim_ram Memorygen.match_prog)
+ ::: (@mkpass _ _ HTLgenproof.match_prog
+ (HTLgenproof.TransfHTLLink HTLgen.transl_program))
+ (*::: mkpass (match_if HLSOpts.optim_ram Memorygen.match_prog)*)
::: mkpass Veriloggenproof.match_prog
::: pass_nil _.
(*|
-These passes are then composed into a larger, top-level ``match_prog`` predicate which matches a C program directly with a Verilog program.
+These passes are then composed into a larger, top-level ``match_prog`` predicate
+which matches a C program directly with a Verilog program.
|*)
Definition match_prog: Csyntax.program -> Verilog.program -> Prop :=
pass_match (compose_passes CompCert's_passes).
(*|
-We then need to prove that this predicate holds, assuming that the translation is performed using the ``transf_hls`` function declared above.
+We then need to prove that this predicate holds, assuming that the translation
+is performed using the ``transf_hls`` function declared above.
|*)
Theorem transf_hls_match:
@@ -296,24 +322,38 @@ Theorem transf_hls_match:
Proof.
intros p tp T.
unfold transf_hls, time in T. simpl in T.
- destruct (SimplExpr.transl_program p) as [p1|e] eqn:P1; simpl in T; try discriminate.
- destruct (SimplLocals.transf_program p1) as [p2|e] eqn:P2; simpl in T; try discriminate.
- destruct (Cshmgen.transl_program p2) as [p3|e] eqn:P3; simpl in T; try discriminate.
- destruct (Cminorgen.transl_program p3) as [p4|e] eqn:P4; simpl in T; try discriminate.
- destruct (Selection.sel_program p4) as [p5|e] eqn:P5; simpl in T; try discriminate.
+ destruct (SimplExpr.transl_program p) as [p1|e] eqn:P1;
+ simpl in T; try discriminate.
+ destruct (SimplLocals.transf_program p1) as [p2|e] eqn:P2;
+ simpl in T; try discriminate.
+ destruct (Cshmgen.transl_program p2) as [p3|e] eqn:P3;
+ simpl in T; try discriminate.
+ destruct (Cminorgen.transl_program p3) as [p4|e] eqn:P4;
+ simpl in T; try discriminate.
+ destruct (Selection.sel_program p4) as [p5|e] eqn:P5;
+ simpl in T; try discriminate.
+ rewrite ! compose_print_identity in T.
+ destruct (RTLgen.transl_program p5) as [p6|e] eqn:P6;
+ simpl in T; try discriminate.
+ unfold transf_backend, time in T. simpl in T.
rewrite ! compose_print_identity in T.
- destruct (RTLgen.transl_program p5) as [p6|e] eqn:P6; simpl in T; try discriminate.
- unfold transf_backend, time in T. simpl in T. rewrite ! compose_print_identity in T.
- destruct (Inlining.transf_program p6) as [p7|e] eqn:P7; simpl in T; try discriminate.
+ destruct (Inlining.transf_program p6) as [p7|e] eqn:P7;
+ simpl in T; try discriminate.
set (p8 := Renumber.transf_program p7) in *.
- set (p9 := total_if Compopts.optim_constprop Constprop.transf_program p8) in *.
- set (p10 := total_if Compopts.optim_constprop Renumber.transf_program p9) in *.
- destruct (partial_if Compopts.optim_CSE CSE.transf_program p10) as [p11|e] eqn:P11; simpl in T; try discriminate.
- destruct (partial_if Compopts.optim_redundancy Deadcode.transf_program p11) as [p12|e] eqn:P12; simpl in T; try discriminate.
- destruct (Unusedglob.transform_program p12) as [p13|e] eqn:P13; simpl in T; try discriminate.
- destruct (HTLgen.transl_program p13) as [p14|e] eqn:P14; simpl in T; try discriminate.
- set (p15 := total_if HLSOpts.optim_ram Memorygen.transf_program p14) in *.
- set (p16 := Veriloggen.transl_program p15) in *.
+ set (p9 := total_if Compopts.optim_constprop
+ Constprop.transf_program p8) in *.
+ set (p10 := total_if Compopts.optim_constprop
+ Renumber.transf_program p9) in *.
+ destruct (partial_if Compopts.optim_CSE CSE.transf_program p10)
+ as [p11|e] eqn:P11; simpl in T; try discriminate.
+ destruct (partial_if Compopts.optim_redundancy Deadcode.transf_program p11)
+ as [p12|e] eqn:P12; simpl in T; try discriminate.
+ destruct (Unusedglob.transform_program p12) as [p13|e] eqn:P13;
+ simpl in T; try discriminate.
+ destruct (HTLgen.transl_program p13) as [p14|e] eqn:P14;
+ simpl in T; try discriminate.
+ (*set (p15 := total_if HLSOpts.optim_ram Memorygen.transf_program p14) in *.*)
+ set (p15 := Veriloggen.transl_program p14) in *.
unfold match_prog; simpl.
exists p1; split. apply SimplExprproof.transf_program_match; auto.
exists p2; split. apply SimplLocalsproof.match_transf_program; auto.
@@ -323,14 +363,19 @@ Proof.
exists p6; split. apply RTLgenproof.transf_program_match; auto.
exists p7; split. apply Inliningproof.transf_program_match; auto.
exists p8; split. apply Renumberproof.transf_program_match; auto.
- exists p9; split. apply total_if_match. apply Constpropproof.transf_program_match.
- exists p10; split. apply total_if_match. apply Renumberproof.transf_program_match.
- exists p11; split. eapply partial_if_match; eauto. apply CSEproof.transf_program_match.
- exists p12; split. eapply partial_if_match; eauto. apply Deadcodeproof.transf_program_match.
+ exists p9; split. apply total_if_match.
+ apply Constpropproof.transf_program_match.
+ exists p10; split. apply total_if_match.
+ apply Renumberproof.transf_program_match.
+ exists p11; split. eapply partial_if_match; eauto.
+ apply CSEproof.transf_program_match.
+ exists p12; split. eapply partial_if_match; eauto.
+ apply Deadcodeproof.transf_program_match.
exists p13; split. apply Unusedglobproof.transf_program_match; auto.
exists p14; split. apply HTLgenproof.transf_program_match; auto.
- exists p15; split. apply total_if_match. apply Memorygen.transf_program_match; auto.
- exists p16; split. apply Veriloggenproof.transf_program_match; auto.
+ (*exists p15; split. apply total_if_match.
+ apply Memorygen.transf_program_match; auto.*)
+ exists p15; split. apply Veriloggenproof.transf_program_match; auto.
inv T. reflexivity.
Qed.
@@ -338,7 +383,8 @@ Theorem cstrategy_semantic_preservation:
forall p tp,
match_prog p tp ->
forward_simulation (Cstrategy.semantics p) (Verilog.semantics tp)
- /\ backward_simulation (atomic (Cstrategy.semantics p)) (Verilog.semantics tp).
+ /\ backward_simulation (atomic (Cstrategy.semantics p))
+ (Verilog.semantics tp).
Proof.
intros p tp M. unfold match_prog, pass_match in M; simpl in M.
Ltac DestructM :=
@@ -348,7 +394,8 @@ Ltac DestructM :=
destruct H as (p & M & MM); clear H
end.
repeat DestructM. subst tp.
- assert (F: forward_simulation (Cstrategy.semantics p) (Verilog.semantics p16)).
+ assert (F: forward_simulation (Cstrategy.semantics p)
+ (Verilog.semantics p15)).
{
eapply compose_forward_simulations.
eapply SimplExprproof.transl_program_correct; eassumption.
@@ -367,24 +414,30 @@ Ltac DestructM :=
eapply compose_forward_simulations.
eapply Renumberproof.transf_program_correct; eassumption.
eapply compose_forward_simulations.
- eapply match_if_simulation. eassumption. exact Constpropproof.transf_program_correct.
+ eapply match_if_simulation. eassumption.
+ exact Constpropproof.transf_program_correct.
eapply compose_forward_simulations.
- eapply match_if_simulation. eassumption. exact Renumberproof.transf_program_correct.
+ eapply match_if_simulation. eassumption.
+ exact Renumberproof.transf_program_correct.
eapply compose_forward_simulations.
- eapply match_if_simulation. eassumption. exact CSEproof.transf_program_correct.
+ eapply match_if_simulation. eassumption.
+ exact CSEproof.transf_program_correct.
eapply compose_forward_simulations.
- eapply match_if_simulation. eassumption. exact Deadcodeproof.transf_program_correct; eassumption.
+ eapply match_if_simulation. eassumption.
+ exact Deadcodeproof.transf_program_correct; eassumption.
eapply compose_forward_simulations.
eapply Unusedglobproof.transf_program_correct; eassumption.
eapply compose_forward_simulations.
eapply HTLgenproof.transf_program_correct. eassumption.
- eapply compose_forward_simulations.
- eapply match_if_simulation. eassumption. exact Memorygen.transf_program_correct; eassumption.
+ (*eapply compose_forward_simulations.
+ eapply match_if_simulation. eassumption.
+ exact Memorygen.transf_program_correct; eassumption.*)
eapply Veriloggenproof.transf_program_correct; eassumption.
}
split. auto.
apply forward_to_backward_simulation.
- apply factor_forward_simulation. auto. eapply sd_traces. eapply Verilog.semantics_determinate.
+ apply factor_forward_simulation. auto. eapply sd_traces.
+ eapply Verilog.semantics_determinate.
apply atomic_receptive. apply Cstrategy.semantics_strongly_receptive.
apply Verilog.semantics_determinate.
Qed.
@@ -393,7 +446,11 @@ Qed.
Backward Simulation
-------------------
-The following theorem is a *backward simulation* between the C and Verilog, which proves the semantics preservation of the translation. We can assume that the C and Verilog programs match, as we have proven previously in ``transf_hls_match`` that our translation implies that the ``match_prog`` predicate will hold.
+The following theorem is a *backward simulation* between the C and Verilog,
+which proves the semantics preservation of the translation. We can assume that
+the C and Verilog programs match, as we have proven previously in
+``transf_hls_match`` that our translation implies that the ``match_prog``
+predicate will hold.
|*)
Theorem c_semantic_preservation:
@@ -412,7 +469,9 @@ Proof.
Qed.
(*|
-We can then use ``transf_hls_match`` to prove the backward simulation where the assumption is that the translation is performed using the ``transf_hls`` function and that it succeeds.
+We can then use ``transf_hls_match`` to prove the backward simulation where the
+assumption is that the translation is performed using the ``transf_hls``
+function and that it succeeds.
|*)
Theorem transf_c_program_correct:
@@ -424,7 +483,10 @@ Proof.
Qed.
(*|
-The final theorem of the semantic preservation of the translation of separate translation units can also be proven correct, however, this is only because the translation fails if more than one translation unit is passed to Vericert at the moment.
+The final theorem of the semantic preservation of the translation of separate
+translation units can also be proven correct, however, this is only because the
+translation fails if more than one translation unit is passed to Vericert at the
+moment.
|*)
Theorem separate_transf_c_program_correct:
@@ -433,11 +495,13 @@ Theorem separate_transf_c_program_correct:
link_list c_units = Some c_program ->
exists verilog_program,
link_list verilog_units = Some verilog_program
- /\ backward_simulation (Csem.semantics c_program) (Verilog.semantics verilog_program).
+ /\ backward_simulation (Csem.semantics c_program)
+ (Verilog.semantics verilog_program).
Proof.
intros.
assert (nlist_forall2 match_prog c_units verilog_units).
- { eapply nlist_forall2_imply. eauto. simpl; intros. apply transf_hls_match; auto. }
+ { eapply nlist_forall2_imply. eauto. simpl; intros.
+ apply transf_hls_match; auto. }
assert (exists verilog_program, link_list verilog_units = Some verilog_program
/\ match_prog c_program verilog_program).
{ eapply link_list_compose_passes; eauto. }
diff --git a/src/VericertClflags.ml b/src/VericertClflags.ml
index ab3c949..0402d49 100644
--- a/src/VericertClflags.ml
+++ b/src/VericertClflags.ml
@@ -6,6 +6,7 @@ let option_initial = ref false
let option_dhtl = ref false
let option_drtlblock = ref false
let option_drtlpar = ref false
+let option_drtlparfu = ref false
let option_hls_schedule = ref false
let option_fif_conv = ref false
let option_fram = ref true
diff --git a/src/bourdoncle/Bourdoncle.v b/src/bourdoncle/Bourdoncle.v
new file mode 100644
index 0000000..ef1798a
--- /dev/null
+++ b/src/bourdoncle/Bourdoncle.v
@@ -0,0 +1,11 @@
+(*|
+Type of a Bourdoncle component.
+|*)
+
+Require Import List.
+Require Import BinPos.
+Notation node := positive.
+
+Inductive bourdoncle :=
+| I : node -> bourdoncle
+| L : node -> list bourdoncle -> bourdoncle.
diff --git a/src/bourdoncle/BourdoncleAux.ml b/src/bourdoncle/BourdoncleAux.ml
new file mode 100644
index 0000000..a35004e
--- /dev/null
+++ b/src/bourdoncle/BourdoncleAux.ml
@@ -0,0 +1,108 @@
+(* Note: this file is used by SliceToString, so it must not include it *)
+
+open Camlcoq
+open BinNums
+open BinPos
+open Maps
+open RTLBlock
+open RTLBlockInstr
+open BourdoncleIterator
+module B = Bourdoncle
+
+type node = P.t
+
+let int_of_positive p =
+ let i = P.to_int p in
+ i - 1
+
+let positive_of_int n = P.of_int (n+1)
+
+(* Functions copied from SliceToString to avoid mutual inclusion *)
+let nodeToString (p : P.t) : string =
+ Int.to_string (P.to_int p)
+let rec cleanListToString' (aToString: 'a -> string) (l : 'a list) =
+ match l with
+ | [] -> ""
+ | e :: r -> " " ^ (aToString e) ^ (cleanListToString' aToString r)
+let cleanListToString (aToString: 'a -> string) (l : 'a list) =
+ match l with
+ | [] -> "[]"
+ | [e] -> "(" ^ (aToString e) ^ ")"
+ | e :: r -> "(" ^ (aToString e) ^ (cleanListToString' aToString r) ^ ")"
+let rec bourdoncleToString (b : B.bourdoncle) : string =
+ match b with
+ | B.I n -> (nodeToString n)
+ | B.L (h, lb) -> cleanListToString bourdoncleToString ((B.I h) :: lb)
+let bourdoncleListToString (l : B.bourdoncle list) : string =
+ cleanListToString bourdoncleToString l
+
+(* Dummy type to avoid redefining existing functions *)
+type instr = | Inop
+
+let rec get_exits = function
+ | RBgoto j -> [(int_of_positive j, Inop)]
+ | RBcall (_,_,_,dst,j) -> [(int_of_positive j, Inop)]
+ | RBtailcall _ -> []
+ | RBbuiltin (_,_,dst,j) -> [(int_of_positive j, Inop)]
+ | RBcond (c,args,j,k) -> [(int_of_positive j, Inop);(int_of_positive k, Inop)]
+ | RBjumptable (_,tbl) -> List.map (fun j -> (int_of_positive j, Inop)) tbl
+ | RBpred_cf (p, cf1, cf2) -> List.append (get_exits cf1) (get_exits cf2)
+ | RBreturn _ -> []
+
+let build_cfg f =
+ let entry = int_of_positive f.fn_entrypoint in
+ let max = PTree.fold (fun m n _ -> max m (int_of_positive n)) f.fn_code 0 in
+ (* nodes are between 1 and max+1 *)
+ let succ = Array.make (max+1) [] in
+ let _ = PTree.fold (fun () n ins ->
+ succ.(int_of_positive n) <- get_exits ins.bb_exit) f.fn_code () in
+ { entry = entry; succ = succ }
+
+let rec build_bourdoncle' (bl : bourdoncle list) : B.bourdoncle list =
+ match bl with
+ | [] -> []
+ | (I i) :: r -> B.I (positive_of_int i) :: (build_bourdoncle' r)
+ | (L ((I h) :: l, _)) :: r -> B.L (positive_of_int h, build_bourdoncle' l) :: (build_bourdoncle' r)
+ | _ -> failwith "Assertion error: invalid bourdoncle ist"
+
+let build_bourdoncle'' (f : bb coq_function) : B.bourdoncle =
+ let cfg = build_cfg f in
+ match build_bourdoncle' (get_bourdoncle cfg) with
+ | [] -> failwith "assertion error: empty bourdoncle"
+ | l ->
+ begin
+ match l with
+ | B.I h :: r -> B.L (h, r)
+ | B.L (_, _) :: _ ->
+ begin
+ Printf.printf "ASSERTION ERROR: invalid program structure (too many bourdoncles)\n";
+ Printf.printf "Head should be an element, but it is a list\n";
+ Printf.printf "Failed at: %s\n" (bourdoncleListToString l);
+ failwith "assertion error"
+ end
+ | _ -> failwith "assertion error : ???"
+ end
+
+(* Auxiliary function for build_order *)
+let rec linearize (b : B.bourdoncle) : node list =
+ match b with
+ | B.I n -> [n]
+ | B.L (h, l) -> List.fold_left (fun l0 b' -> l0 @ (linearize b')) [h] l
+
+let succ_pos = function
+ | N0 -> Npos Coq_xH
+ | Npos p -> Npos (Pos.succ p)
+
+let rec build_order' (l : node list) (count : coq_N) : coq_N PTree.t =
+ match l with
+ | [] -> PTree.empty
+ | n :: r -> PTree.set n count (build_order' r (succ_pos count))
+
+let build_order (b : B.bourdoncle) : coq_N PMap.t =
+ let bo = build_order' (linearize b) (succ_pos N0) in
+ (succ_pos N0, bo)
+
+let build_bourdoncle (f : bb coq_function) : (B.bourdoncle * coq_N PMap.t) =
+ let b = build_bourdoncle'' f in
+ let bo = build_order b in
+ (b, bo)
diff --git a/src/bourdoncle/PrintLoops.ml b/src/bourdoncle/PrintLoops.ml
new file mode 100644
index 0000000..f70f075
--- /dev/null
+++ b/src/bourdoncle/PrintLoops.ml
@@ -0,0 +1,22 @@
+open Camlcoq
+
+let indent i = String.make (2 * i) ' '
+
+let rec print_bourdoncle i pp =
+ function
+ | Bourdoncle.I n ->
+ Printf.fprintf pp "%sI %d\n" (indent i) (P.to_int n)
+ | Bourdoncle.L (h, b) ->
+ Printf.fprintf pp "%sL %d\n" (indent i) (P.to_int h);
+ List.iter (fun a -> Printf.fprintf pp "%a" (print_bourdoncle (i+1)) a) b
+
+let print_if optdest loop =
+ match !optdest with
+ | None -> ()
+ | Some f ->
+ let oc = open_out f in
+ print_bourdoncle 0 oc loop;
+ close_out oc
+
+let destination_loops : string option ref = ref None
+let print_loops = print_if destination_loops
diff --git a/src/bourdoncle/README.md b/src/bourdoncle/README.md
new file mode 100644
index 0000000..e1d02b9
--- /dev/null
+++ b/src/bourdoncle/README.md
@@ -0,0 +1,3 @@
+# Bourdoncle implementation
+
+This code was taken from WCET analysis in CompCert, which can be found [here](http://www.irisa.fr/celtique/ext/loopbound/).
diff --git a/src/bourdoncle/bourdoncleIterator.ml b/src/bourdoncle/bourdoncleIterator.ml
new file mode 100644
index 0000000..3cf0c78
--- /dev/null
+++ b/src/bourdoncle/bourdoncleIterator.ml
@@ -0,0 +1,183 @@
+type ('ab, 'instr) adom = {
+ order: 'ab -> 'ab -> bool;
+ join: 'ab -> 'ab -> 'ab;
+ widen: 'ab -> 'ab -> 'ab;
+ top: unit -> 'ab;
+ bot: unit -> 'ab;
+ transfer: 'instr -> 'ab -> 'ab;
+ to_string: 'ab -> string
+}
+
+type 'instr cfg = {
+ entry: int;
+ succ: (int * 'instr) list array;
+}
+
+(* Utilities *)
+let rec print_list_sep_rec sep pp = function
+ | [] -> ""
+ | x::q -> sep^(pp x)^(print_list_sep_rec sep pp q)
+
+let rec print_list_sep_list_rec sep pp = function
+ | [] -> []
+ | x::q -> (sep^(pp x))::(print_list_sep_list_rec sep pp q)
+
+let print_list_sep sep pp = function
+ | [] -> ""
+ | x::q -> (pp x)^(print_list_sep_rec sep pp q)
+
+let dot_cfg cfg filename =
+ let f = open_out filename in
+ Printf.fprintf f "digraph {\n";
+ Array.iteri
+ (fun i l ->
+ List.iter (fun (j,_) -> Printf.fprintf f " n%d -> n%d\n" i j) l)
+ cfg.succ;
+ Printf.fprintf f "}\n";
+ close_out f
+
+
+(* Bourdoncle *)
+type bourdoncle = L of (bourdoncle list) * Ptset.t | I of int
+
+let rec string_of_bourdoncle_list l =
+ print_list_sep " " string_of_bourdoncle l
+and string_of_bourdoncle = function
+ | L (l,_) -> "("^(string_of_bourdoncle_list l)^")"
+ | I i -> string_of_int i
+
+(* For efficiency we pre-compute the set of nodes in a cfc *)
+let add_component =
+ List.fold_left
+ (fun s b ->
+ match b with
+ | I i -> Ptset.add i s
+ | L (_,s') -> Ptset.union s s')
+ Ptset.empty
+
+(* Bourdoncle strategy computation *)
+let get_bourdoncle cfg =
+ let date = ref 0 in
+ let debut = Array.map (fun _ -> 0) cfg.succ in
+ let stack = Stack.create () in
+ let rec component i =
+ let partition = ref [] in
+ List.iter
+ (fun (j,_) ->
+ if debut.(j)=0 then ignore (visite j partition))
+ cfg.succ.(i);
+ (I i) :: !partition
+ and visite i partition =
+ incr date;
+ debut.(i) <- !date;
+ let min = ref !date in
+ let loop = ref false in
+ Stack.push i stack;
+ List.iter
+ (fun (j,_) ->
+ let m = if debut.(j)=0 then visite j partition else debut.(j) in
+ if m <= !min then
+ begin
+ min := m;
+ loop := true
+ end)
+ cfg.succ.(i);
+ if !min=debut.(i) then
+ begin
+ debut.(i) <- max_int;
+ let k = ref (Stack.pop stack) in
+ if !loop then begin
+ while (!k<>i) do
+ debut.(!k) <- 0;
+ k := Stack.pop stack;
+ done;
+ let c = component i in
+ partition := (L (c,add_component c)) :: !partition
+ end
+ else partition := (I i) :: !partition
+ end;
+ !min
+ in
+ let partition = ref [] in
+ (* only one entry in the cfg *)
+ ignore (visite cfg.entry partition);
+ Array.iteri (fun i d -> if d=0 then cfg.succ.(i) <- []) debut;
+ !partition
+
+(* predecessors *)
+let get_pred cfg =
+ let pred = Array.make (Array.length cfg.succ) [] in
+ Array.iteri
+ (fun i succs ->
+ List.iter
+ (fun (j,ins) ->
+ pred.(j) <- (i,ins) :: pred.(j))
+ succs
+ )
+ cfg.succ;
+ pred
+
+let check_fixpoint adom cfg res =
+ if not (adom.order (adom.top ()) res.(cfg.entry)) then
+ failwith "res.(ENTRY) should be top !\n";
+ Array.iteri
+ (fun i succs ->
+ List.iter
+ (fun (j,op) ->
+ if not (adom.order (adom.transfer op res.(i)) res.(j)) then
+ begin
+ dot_cfg cfg "debug_bourdoncle.dot";
+ failwith (Printf.sprintf "res.(%d) should be lower than res.(%d) !\n" i j)
+ end)
+ succs)
+ cfg.succ
+
+let option_down_iterations = ref 1
+
+let rec f_list f acc = function
+ [] -> acc
+ | x::q -> f_list f (f acc x) q
+
+let run_with_bourdoncle adom b cfg =
+ let preds = get_pred cfg in
+ let res = Array.init (Array.length preds) (fun _ -> adom.bot ()) in
+ let join_list = f_list adom.join in
+ let _ = res.(cfg.entry) <- adom.top () in
+ let upd j =
+ if j <> cfg.entry then
+ res.(j) <-
+ join_list (adom.bot ())
+ (List.map (fun (i,op) -> adom.transfer op res.(i)) preds.(j)) in
+ let upd_except_cfc j cfc =
+ if j <> cfg.entry then
+ res.(j) <- join_list res.(j)
+ (List.map (fun (i,op) -> adom.transfer op res.(i))
+ (List.filter (fun (i,op) -> not (Ptset.mem i cfc)) preds.(j)))
+ in
+ let nb_down = !option_down_iterations in
+ let rec iter_component down = function
+ | L (I head::rest,cfc) ->
+ let rec aux down = function
+ [] ->
+ let old_ab = res.(head) in
+ let _ = upd head in
+ let new_ab = res.(head) in
+ if down >= nb_down || (new_ab = old_ab) then ()
+ else if not (adom.order new_ab old_ab) then
+ begin
+ res.(head) <- adom.widen old_ab new_ab;
+ aux (-1) rest
+ end
+ else (upd head; aux (down+1) rest)
+ | b::q -> iter_component down b; aux down q in
+ upd_except_cfc head cfc;
+ aux down rest
+ | I i -> upd i
+ | _ -> assert false in
+ List.iter (iter_component (-1)) b;
+ check_fixpoint adom cfg res;
+ res
+
+let run adom cfg =
+ let b = get_bourdoncle cfg in
+ run_with_bourdoncle adom b cfg
diff --git a/src/bourdoncle/ptset.ml b/src/bourdoncle/ptset.ml
new file mode 100644
index 0000000..c94691b
--- /dev/null
+++ b/src/bourdoncle/ptset.ml
@@ -0,0 +1,666 @@
+(*
+ * Copyright (C) 2008 Jean-Christophe Filliatre
+ * Copyright (C) 2008, 2009 Laurent Hubert (CNRS)
+ *
+ * This software is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1, with the special exception on linking described in file
+ * LICENSE.
+
+ * This software 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.
+ *)
+
+
+(*s Sets of integers implemented as Patricia trees, following Chris
+ Okasaki and Andrew Gill's paper {\em Fast Mergeable Integer Maps}
+ ({\tt\small http://www.cs.columbia.edu/\~{}cdo/papers.html\#ml98maps}).
+ Patricia trees provide faster operations than standard library's
+ module [Set], and especially very fast [union], [subset], [inter]
+ and [diff] operations. *)
+
+(*s The idea behind Patricia trees is to build a {\em trie} on the
+ binary digits of the elements, and to compact the representation
+ by branching only one the relevant bits (i.e. the ones for which
+ there is at least on element in each subtree). We implement here
+ {\em little-endian} Patricia trees: bits are processed from
+ least-significant to most-significant. The trie is implemented by
+ the following type [t]. [Empty] stands for the empty trie, and
+ [Leaf k] for the singleton [k]. (Note that [k] is the actual
+ element.) [Branch (m,p,l,r)] represents a branching, where [p] is
+ the prefix (from the root of the trie) and [m] is the branching
+ bit (a power of 2). [l] and [r] contain the subsets for which the
+ branching bit is respectively 0 and 1. Invariant: the trees [l]
+ and [r] are not empty. *)
+
+
+module type S = sig
+ type t
+ type elt = int
+ val empty : t
+ val is_empty : t -> bool
+ val mem : int -> t -> bool
+ val add : int -> t -> t
+ val singleton : int -> t
+ val remove : int -> t -> t
+ val union : t -> t -> t
+ val subset : t -> t -> bool
+ val inter : t -> t -> t
+ val diff : t -> t -> t
+ val equal : t -> t -> bool
+ val compare : t -> t -> int
+ val elements : t -> int list
+ val choose : t -> int
+ val cardinal : t -> int
+ val iter : (int -> unit) -> t -> unit
+ val fold : (int -> 'a -> 'a) -> t -> 'a -> 'a
+ val for_all : (int -> bool) -> t -> bool
+ val exists : (int -> bool) -> t -> bool
+ val filter : (int -> bool) -> t -> t
+ val partition : (int -> bool) -> t -> t * t
+ val split : int -> t -> t * bool * t
+ val min_elt : t -> int
+ val max_elt : t -> int
+ val intersect : t -> t -> bool
+ val choose_and_remove : t -> int*t
+end
+
+
+(*i*)
+type elt = int
+(*i*)
+
+type t =
+ | Empty
+ | Leaf of int
+ | Branch of int * int * t * t
+
+(*s Example: the representation of the set $\{1,4,5\}$ is
+ $$\mathtt{Branch~(0,~1,~Leaf~4,~Branch~(1,~4,~Leaf~1,~Leaf~5))}$$
+ The first branching bit is the bit 0 (and the corresponding prefix
+ is [0b0], not of use here), with $\{4\}$ on the left and $\{1,5\}$ on the
+ right. Then the right subtree branches on bit 2 (and so has a branching
+ value of $2^2 = 4$), with prefix [0b01 = 1]. *)
+
+(*s Empty set and singletons. *)
+
+let empty = Empty
+
+let is_empty = function Empty -> true | _ -> false
+
+let singleton k = Leaf k
+
+(*s Testing the occurrence of a value is similar to the search in a
+ binary search tree, where the branching bit is used to select the
+ appropriate subtree. *)
+
+let zero_bit k m = (k land m) == 0
+
+let rec mem k = function
+ | Empty -> false
+ | Leaf j -> k == j
+ | Branch (_, m, l, r) -> mem k (if zero_bit k m then l else r)
+
+(*s The following operation [join] will be used in both insertion and
+ union. Given two non-empty trees [t0] and [t1] with longest common
+ prefixes [p0] and [p1] respectively, which are supposed to
+ disagree, it creates the union of [t0] and [t1]. For this, it
+ computes the first bit [m] where [p0] and [p1] disagree and create
+ a branching node on that bit. Depending on the value of that bit
+ in [p0], [t0] will be the left subtree and [t1] the right one, or
+ the converse. Computing the first branching bit of [p0] and [p1]
+ uses a nice property of twos-complement representation of integers. *)
+
+let lowest_bit x = x land (-x)
+
+let branching_bit p0 p1 = lowest_bit (p0 lxor p1)
+
+let mask p m = p land (m-1)
+
+let join (p0,t0,p1,t1) =
+ let m = branching_bit p0 p1 in
+ if zero_bit p0 m then
+ Branch (mask p0 m, m, t0, t1)
+ else
+ Branch (mask p0 m, m, t1, t0)
+
+(*s Then the insertion of value [k] in set [t] is easily implemented
+ using [join]. Insertion in a singleton is just the identity or a
+ call to [join], depending on the value of [k]. When inserting in
+ a branching tree, we first check if the value to insert [k]
+ matches the prefix [p]: if not, [join] will take care of creating
+ the above branching; if so, we just insert [k] in the appropriate
+ subtree, depending of the branching bit. *)
+
+let match_prefix k p m = (mask k m) == p
+
+let add k t =
+ let rec ins = function
+ | Empty -> Leaf k
+ | Leaf j as t ->
+ if j == k then t else join (k, Leaf k, j, t)
+ | Branch (p,m,t0,t1) as t ->
+ if match_prefix k p m then
+ if zero_bit k m then
+ Branch (p, m, ins t0, t1)
+ else
+ Branch (p, m, t0, ins t1)
+ else
+ join (k, Leaf k, p, t)
+ in
+ ins t
+
+(*s The code to remove an element is basically similar to the code of
+ insertion. But since we have to maintain the invariant that both
+ subtrees of a [Branch] node are non-empty, we use here the
+ ``smart constructor'' [branch] instead of [Branch]. *)
+
+let branch = function
+ | (_,_,Empty,t) -> t
+ | (_,_,t,Empty) -> t
+ | (p,m,t0,t1) -> Branch (p,m,t0,t1)
+
+let remove k t =
+ let rec rmv = function
+ | Empty -> Empty
+ | Leaf j as t -> if k == j then Empty else t
+ | Branch (p,m,t0,t1) as t ->
+ if match_prefix k p m then
+ if zero_bit k m then
+ branch (p, m, rmv t0, t1)
+ else
+ branch (p, m, t0, rmv t1)
+ else
+ t
+ in
+ rmv t
+
+let rec choose_and_remove = function
+ | Empty -> raise Not_found
+ | Leaf j -> (j,Empty)
+ | Branch (p,m,t0,t1) ->
+ let (j,t0') = choose_and_remove t0
+ in (j, branch (p,m,t0',t1))
+
+(*s One nice property of Patricia trees is to support a fast union
+ operation (and also fast subset, difference and intersection
+ operations). When merging two branching trees we examine the
+ following four cases: (1) the trees have exactly the same
+ prefix; (2/3) one prefix contains the other one; and (4) the
+ prefixes disagree. In cases (1), (2) and (3) the recursion is
+ immediate; in case (4) the function [join] creates the appropriate
+ branching. *)
+
+let rec merge = function
+ | t1,t2 when t1==t2 -> t1
+ | Empty, t -> t
+ | t, Empty -> t
+ | Leaf k, t -> add k t
+ | t, Leaf k -> add k t
+ | (Branch (p,m,s0,s1) as s), (Branch (q,n,t0,t1) as t) ->
+ if m == n && match_prefix q p m then
+ (* The trees have the same prefix. Merge the subtrees. *)
+ Branch (p, m, merge (s0,t0), merge (s1,t1))
+ else if m < n && match_prefix q p m then
+ (* [q] contains [p]. Merge [t] with a subtree of [s]. *)
+ if zero_bit q m then
+ Branch (p, m, merge (s0,t), s1)
+ else
+ Branch (p, m, s0, merge (s1,t))
+ else if m > n && match_prefix p q n then
+ (* [p] contains [q]. Merge [s] with a subtree of [t]. *)
+ if zero_bit p n then
+ Branch (q, n, merge (s,t0), t1)
+ else
+ Branch (q, n, t0, merge (s,t1))
+ else
+ (* The prefixes disagree. *)
+ join (p, s, q, t)
+
+let union s t = merge (s,t)
+
+(*s When checking if [s1] is a subset of [s2] only two of the above
+ four cases are relevant: when the prefixes are the same and when the
+ prefix of [s1] contains the one of [s2], and then the recursion is
+ obvious. In the other two cases, the result is [false]. *)
+
+let rec subset s1 s2 = match (s1,s2) with
+ | Empty, _ -> true
+ | _, Empty -> false
+ | Leaf k1, _ -> mem k1 s2
+ | Branch _, Leaf _ -> false
+ | Branch (p1,m1,l1,r1), Branch (p2,m2,l2,r2) ->
+ if m1 == m2 && p1 == p2 then
+ subset l1 l2 && subset r1 r2
+ else if m1 > m2 && match_prefix p1 p2 m2 then
+ if zero_bit p1 m2 then
+ subset l1 l2 && subset r1 l2
+ else
+ subset l1 r2 && subset r1 r2
+ else
+ false
+
+(*s To compute the intersection and the difference of two sets, we
+ still examine the same four cases as in [merge]. The recursion is
+ then obvious. *)
+
+let rec inter s1 s2 = match (s1,s2) with
+ | t1, t2 when t1==t2 -> t1
+ | Empty, _ -> Empty
+ | _, Empty -> Empty
+ | Leaf k1, _ -> if mem k1 s2 then s1 else Empty
+ | _, Leaf k2 -> if mem k2 s1 then s2 else Empty
+ | Branch (p1,m1,l1,r1), Branch (p2,m2,l2,r2) ->
+ if m1 == m2 && p1 == p2 then
+ merge (inter l1 l2, inter r1 r2)
+ else if m1 < m2 && match_prefix p2 p1 m1 then
+ inter (if zero_bit p2 m1 then l1 else r1) s2
+ else if m1 > m2 && match_prefix p1 p2 m2 then
+ inter s1 (if zero_bit p1 m2 then l2 else r2)
+ else
+ Empty
+
+let rec diff s1 s2 = match (s1,s2) with
+ | Empty, _ -> Empty
+ | _, Empty -> s1
+ | Leaf k1, _ -> if mem k1 s2 then Empty else s1
+ | _, Leaf k2 -> remove k2 s1
+ | Branch (p1,m1,l1,r1), Branch (p2,m2,l2,r2) ->
+ if m1 == m2 && p1 == p2 then
+ merge (diff l1 l2, diff r1 r2)
+ else if m1 < m2 && match_prefix p2 p1 m1 then
+ if zero_bit p2 m1 then
+ merge (diff l1 s2, r1)
+ else
+ merge (l1, diff r1 s2)
+ else if m1 > m2 && match_prefix p1 p2 m2 then
+ if zero_bit p1 m2 then diff s1 l2 else diff s1 r2
+ else
+ s1
+
+(*s All the following operations ([cardinal], [iter], [fold], [for_all],
+ [exists], [filter], [partition], [choose], [elements]) are
+ implemented as for any other kind of binary trees. *)
+
+let rec cardinal = function
+ | Empty -> 0
+ | Leaf _ -> 1
+ | Branch (_,_,t0,t1) -> cardinal t0 + cardinal t1
+
+let rec iter f = function
+ | Empty -> ()
+ | Leaf k -> f k
+ | Branch (_,_,t0,t1) -> iter f t0; iter f t1
+
+let rec fold f s accu = match s with
+ | Empty -> accu
+ | Leaf k -> f k accu
+ | Branch (_,_,t0,t1) -> fold f t0 (fold f t1 accu)
+
+let rec for_all p = function
+ | Empty -> true
+ | Leaf k -> p k
+ | Branch (_,_,t0,t1) -> for_all p t0 && for_all p t1
+
+let rec exists p = function
+ | Empty -> false
+ | Leaf k -> p k
+ | Branch (_,_,t0,t1) -> exists p t0 || exists p t1
+
+let rec filter pr = function
+ | Empty -> Empty
+ | Leaf k as t -> if pr k then t else Empty
+ | Branch (p,m,t0,t1) -> branch (p, m, filter pr t0, filter pr t1)
+
+let partition p s =
+ let rec part (t,f as acc) = function
+ | Empty -> acc
+ | Leaf k -> if p k then (add k t, f) else (t, add k f)
+ | Branch (_,_,t0,t1) -> part (part acc t0) t1
+ in
+ part (Empty, Empty) s
+
+let rec choose = function
+ | Empty -> raise Not_found
+ | Leaf k -> k
+ | Branch (_, _,t0,_) -> choose t0 (* we know that [t0] is non-empty *)
+
+let elements s =
+ let rec elements_aux acc = function
+ | Empty -> acc
+ | Leaf k -> k :: acc
+ | Branch (_,_,l,r) -> elements_aux (elements_aux acc l) r
+ in
+ (* unfortunately there is no easy way to get the elements in ascending
+ order with little-endian Patricia trees *)
+ List.sort Stdlib.compare (elements_aux [] s)
+
+let split x s =
+ let coll k (l, b, r) =
+ if k < x then add k l, b, r
+ else if k > x then l, b, add k r
+ else l, true, r
+ in
+ fold coll s (Empty, false, Empty)
+
+(*s There is no way to give an efficient implementation of [min_elt]
+ and [max_elt], as with binary search trees. The following
+ implementation is a traversal of all elements, barely more
+ efficient than [fold min t (choose t)] (resp. [fold max t (choose
+ t)]). Note that we use the fact that there is no constructor
+ [Empty] under [Branch] and therefore always a minimal
+ (resp. maximal) element there. *)
+
+let rec min_elt = function
+ | Empty -> raise Not_found
+ | Leaf k -> k
+ | Branch (_,_,s,t) -> min (min_elt s) (min_elt t)
+
+let rec max_elt = function
+ | Empty -> raise Not_found
+ | Leaf k -> k
+ | Branch (_,_,s,t) -> max (max_elt s) (max_elt t)
+
+(*s Another nice property of Patricia trees is to be independent of the
+ order of insertion. As a consequence, two Patricia trees have the
+ same elements if and only if they are structurally equal. *)
+
+let equal v1 v2 = 0 == (compare v1 v2)
+
+let compare = compare
+
+(*i*)
+(* let make l = List.fold_right add l empty *)
+(*i*)
+
+(*s Additional functions w.r.t to [Set.S]. *)
+
+let rec intersect s1 s2 = match (s1,s2) with
+ | Empty, _ -> false
+ | _, Empty -> false
+ | Leaf k1, _ -> mem k1 s2
+ | _, Leaf k2 -> mem k2 s1
+ | Branch (p1,m1,l1,r1), Branch (p2,m2,l2,r2) ->
+ if m1 == m2 && p1 == p2 then
+ intersect l1 l2 || intersect r1 r2
+ else if m1 < m2 && match_prefix p2 p1 m1 then
+ intersect (if zero_bit p2 m1 then l1 else r1) s2
+ else if m1 > m2 && match_prefix p1 p2 m2 then
+ intersect s1 (if zero_bit p1 m2 then l2 else r2)
+ else
+ false
+
+
+(*s Big-endian Patricia trees *)
+
+module Big = struct
+
+ type elt = int
+
+ type t_ = t
+ type t = t_
+
+ let empty = Empty
+
+ let is_empty = function Empty -> true | _ -> false
+
+ let singleton k = Leaf k
+
+ let zero_bit k m = (k land m) == 0
+
+ let rec mem k = function
+ | Empty -> false
+ | Leaf j -> k == j
+ | Branch (_, m, l, r) -> mem k (if zero_bit k m then l else r)
+
+ let mask k m = (k lor (m-1)) land (lnot m)
+
+ (* we first write a naive implementation of [highest_bit]
+ only has to work for bytes *)
+ let naive_highest_bit x =
+ assert (x < 256);
+ let rec loop i =
+ if i = 0 then 1 else if x lsr i = 1 then 1 lsl i else loop (i-1)
+ in
+ loop 7
+
+ (* then we build a table giving the highest bit for bytes *)
+ let hbit = Array.init 256 naive_highest_bit
+
+ (* to determine the highest bit of [x] we split it into bytes *)
+ let highest_bit_32 x =
+ let n = x lsr 24 in if n != 0 then hbit.(n) lsl 24
+ else let n = x lsr 16 in if n != 0 then hbit.(n) lsl 16
+ else let n = x lsr 8 in if n != 0 then hbit.(n) lsl 8
+ else hbit.(x)
+
+ let highest_bit_64 x =
+ let n = x lsr 32 in if n != 0 then (highest_bit_32 n) lsl 32
+ else highest_bit_32 x
+
+ let highest_bit = match Sys.word_size with
+ | 32 -> highest_bit_32
+ | 64 -> highest_bit_64
+ | _ -> assert false
+
+ let branching_bit p0 p1 = highest_bit (p0 lxor p1)
+
+ let join (p0,t0,p1,t1) =
+ (*i let m = function Branch (_,m,_,_) -> m | _ -> 0 in i*)
+ let m = branching_bit p0 p1 (*EXP (m t0) (m t1) *) in
+ if zero_bit p0 m then
+ Branch (mask p0 m, m, t0, t1)
+ else
+ Branch (mask p0 m, m, t1, t0)
+
+ let match_prefix k p m = (mask k m) == p
+
+ let add k t =
+ let rec ins = function
+ | Empty -> Leaf k
+ | Leaf j as t ->
+ if j == k then t else join (k, Leaf k, j, t)
+ | Branch (p,m,t0,t1) as t ->
+ if match_prefix k p m then
+ if zero_bit k m then
+ Branch (p, m, ins t0, t1)
+ else
+ Branch (p, m, t0, ins t1)
+ else
+ join (k, Leaf k, p, t)
+ in
+ ins t
+
+ let remove k t =
+ let rec rmv = function
+ | Empty -> Empty
+ | Leaf j as t -> if k == j then Empty else t
+ | Branch (p,m,t0,t1) as t ->
+ if match_prefix k p m then
+ if zero_bit k m then
+ branch (p, m, rmv t0, t1)
+ else
+ branch (p, m, t0, rmv t1)
+ else
+ t
+ in
+ rmv t
+
+ let rec merge = function
+ | Empty, t -> t
+ | t, Empty -> t
+ | Leaf k, t -> add k t
+ | t, Leaf k -> add k t
+ | (Branch (p,m,s0,s1) as s), (Branch (q,n,t0,t1) as t) ->
+ if m == n && match_prefix q p m then
+ (* The trees have the same prefix. Merge the subtrees. *)
+ Branch (p, m, merge (s0,t0), merge (s1,t1))
+ else if m > n && match_prefix q p m then
+ (* [q] contains [p]. Merge [t] with a subtree of [s]. *)
+ if zero_bit q m then
+ Branch (p, m, merge (s0,t), s1)
+ else
+ Branch (p, m, s0, merge (s1,t))
+ else if m < n && match_prefix p q n then
+ (* [p] contains [q]. Merge [s] with a subtree of [t]. *)
+ if zero_bit p n then
+ Branch (q, n, merge (s,t0), t1)
+ else
+ Branch (q, n, t0, merge (s,t1))
+ else
+ (* The prefixes disagree. *)
+ join (p, s, q, t)
+
+ let union s t = merge (s,t)
+
+ let rec subset s1 s2 = match (s1,s2) with
+ | Empty, _ -> true
+ | _, Empty -> false
+ | Leaf k1, _ -> mem k1 s2
+ | Branch _, Leaf _ -> false
+ | Branch (p1,m1,l1,r1), Branch (p2,m2,l2,r2) ->
+ if m1 == m2 && p1 == p2 then
+ subset l1 l2 && subset r1 r2
+ else if m1 < m2 && match_prefix p1 p2 m2 then
+ if zero_bit p1 m2 then
+ subset l1 l2 && subset r1 l2
+ else
+ subset l1 r2 && subset r1 r2
+ else
+ false
+
+ let rec inter s1 s2 = match (s1,s2) with
+ | Empty, _ -> Empty
+ | _, Empty -> Empty
+ | Leaf k1, _ -> if mem k1 s2 then s1 else Empty
+ | _, Leaf k2 -> if mem k2 s1 then s2 else Empty
+ | Branch (p1,m1,l1,r1), Branch (p2,m2,l2,r2) ->
+ if m1 == m2 && p1 == p2 then
+ merge (inter l1 l2, inter r1 r2)
+ else if m1 > m2 && match_prefix p2 p1 m1 then
+ inter (if zero_bit p2 m1 then l1 else r1) s2
+ else if m1 < m2 && match_prefix p1 p2 m2 then
+ inter s1 (if zero_bit p1 m2 then l2 else r2)
+ else
+ Empty
+
+ let rec diff s1 s2 = match (s1,s2) with
+ | Empty, _ -> Empty
+ | _, Empty -> s1
+ | Leaf k1, _ -> if mem k1 s2 then Empty else s1
+ | _, Leaf k2 -> remove k2 s1
+ | Branch (p1,m1,l1,r1), Branch (p2,m2,l2,r2) ->
+ if m1 == m2 && p1 == p2 then
+ merge (diff l1 l2, diff r1 r2)
+ else if m1 > m2 && match_prefix p2 p1 m1 then
+ if zero_bit p2 m1 then
+ merge (diff l1 s2, r1)
+ else
+ merge (l1, diff r1 s2)
+ else if m1 < m2 && match_prefix p1 p2 m2 then
+ if zero_bit p1 m2 then diff s1 l2 else diff s1 r2
+ else
+ s1
+
+ (* same implementation as for little-endian Patricia trees *)
+ let cardinal = cardinal
+ let iter = iter
+ let fold = fold
+ let for_all = for_all
+ let exists = exists
+ let filter = filter
+
+ let partition p s =
+ let rec part (t,f as acc) = function
+ | Empty -> acc
+ | Leaf k -> if p k then (add k t, f) else (t, add k f)
+ | Branch (_,_,t0,t1) -> part (part acc t0) t1
+ in
+ part (Empty, Empty) s
+
+ let choose = choose
+ let choose_and_remove = choose_and_remove
+
+ let elements s =
+ let rec elements_aux acc = function
+ | Empty -> acc
+ | Leaf k -> k :: acc
+ | Branch (_,_,l,r) -> elements_aux (elements_aux acc r) l
+ in
+ (* we still have to sort because of possible negative elements *)
+ List.sort Stdlib.compare (elements_aux [] s)
+
+ let split x s =
+ let coll k (l, b, r) =
+ if k < x then add k l, b, r
+ else if k > x then l, b, add k r
+ else l, true, r
+ in
+ fold coll s (Empty, false, Empty)
+
+ (* could be slightly improved (when we now that a branch contains only
+ positive or only negative integers) *)
+ let min_elt = min_elt
+ let max_elt = max_elt
+
+ let equal = (=)
+
+ let compare = compare
+
+ (* let make l = List.fold_right add l empty *)
+
+ let rec intersect s1 s2 = match (s1,s2) with
+ | Empty, _ -> false
+ | _, Empty -> false
+ | Leaf k1, _ -> mem k1 s2
+ | _, Leaf k2 -> mem k2 s1
+ | Branch (p1,m1,l1,r1), Branch (p2,m2,l2,r2) ->
+ if m1 == m2 && p1 == p2 then
+ intersect l1 l2 || intersect r1 r2
+ else if m1 > m2 && match_prefix p2 p1 m1 then
+ intersect (if zero_bit p2 m1 then l1 else r1) s2
+ else if m1 < m2 && match_prefix p1 p2 m2 then
+ intersect s1 (if zero_bit p1 m2 then l2 else r2)
+ else
+ false
+
+end
+
+(*s Big-endian Patricia trees with non-negative elements only *)
+
+module BigPos = struct
+
+ include Big
+
+ let singleton x = if x < 0 then invalid_arg "BigPos.singleton"; singleton x
+
+ let add x s = if x < 0 then invalid_arg "BigPos.add"; add x s
+
+ (* Patricia trees are now binary search trees! *)
+
+ let rec mem k = function
+ | Empty -> false
+ | Leaf j -> k == j
+ | Branch (p, _, l, r) -> if k <= p then mem k l else mem k r
+
+ let rec min_elt = function
+ | Empty -> raise Not_found
+ | Leaf k -> k
+ | Branch (_,_,s,_) -> min_elt s
+
+ let rec max_elt = function
+ | Empty -> raise Not_found
+ | Leaf k -> k
+ | Branch (_,_,_,t) -> max_elt t
+
+ (* we do not have to sort anymore *)
+ let elements s =
+ let rec elements_aux acc = function
+ | Empty -> acc
+ | Leaf k -> k :: acc
+ | Branch (_,_,l,r) -> elements_aux (elements_aux acc r) l
+ in
+ elements_aux [] s
+
+end
diff --git a/src/bourdoncle/ptset.mli b/src/bourdoncle/ptset.mli
new file mode 100644
index 0000000..88319ea
--- /dev/null
+++ b/src/bourdoncle/ptset.mli
@@ -0,0 +1,125 @@
+(*
+ * Copyright (C) 2008 Jean-Christophe Filliatre
+ * Copyright (C) 2008, 2009 Laurent Hubert (CNRS)
+ *
+ * This software is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1, with the special exception on linking described in file
+ * LICENSE.
+
+ * This software 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.
+ *)
+
+(** Sets of integers implemented as Patricia trees.
+
+ This implementation follows Chris Okasaki and Andrew Gill's paper
+ {e Fast Mergeable Integer Maps}.
+
+ Patricia trees provide faster operations than standard library's
+ module [Set], and especially very fast [union], [subset], [inter]
+ and [diff] operations. *)
+
+(** The idea behind Patricia trees is to build a {e trie} on the
+ binary digits of the elements, and to compact the representation
+ by branching only one the relevant bits (i.e. the ones for which
+ there is at least on element in each subtree). We implement here
+ {e little-endian} Patricia trees: bits are processed from
+ least-significant to most-significant. The trie is implemented by
+ the following type [t]. [Empty] stands for the empty trie, and
+ [Leaf k] for the singleton [k]. (Note that [k] is the actual
+ element.) [Branch (m,p,l,r)] represents a branching, where [p] is
+ the prefix (from the root of the trie) and [m] is the branching
+ bit (a power of 2). [l] and [r] contain the subsets for which the
+ branching bit is respectively 0 and 1. Invariant: the trees [l]
+ and [r] are not empty. *)
+
+(** The docuemntation is given for function that differs from [Set.S
+ with type elt = int]. *)
+
+module type S = sig
+ type t
+
+ type elt = int
+
+ val empty : t
+
+ val is_empty : t -> bool
+
+ val mem : int -> t -> bool
+
+ val add : int -> t -> t
+
+ val singleton : int -> t
+
+ val remove : int -> t -> t
+
+ val union : t -> t -> t
+
+ val subset : t -> t -> bool
+
+ val inter : t -> t -> t
+
+ val diff : t -> t -> t
+
+ val equal : t -> t -> bool
+
+ val compare : t -> t -> int
+
+ val elements : t -> int list
+
+ val choose : t -> int
+
+ val cardinal : t -> int
+
+ val iter : (int -> unit) -> t -> unit
+
+ val fold : (int -> 'a -> 'a) -> t -> 'a -> 'a
+
+ val for_all : (int -> bool) -> t -> bool
+
+ val exists : (int -> bool) -> t -> bool
+
+ val filter : (int -> bool) -> t -> t
+
+ val partition : (int -> bool) -> t -> t * t
+
+ val split : int -> t -> t * bool * t
+
+ (** Warning: [min_elt] and [max_elt] are linear w.r.t. the size of the
+ set. In other words, [min_elt t] is barely more efficient than [fold
+ min t (choose t)]. *)
+
+ val min_elt : t -> int
+ val max_elt : t -> int
+
+ (** Additional functions not appearing in the signature [Set.S] from
+ ocaml standard library. *)
+
+ (** [intersect u v] determines if sets [u] and [v] have a non-empty
+ intersection. *)
+
+ val intersect : t -> t -> bool
+
+ (** [choose_and_remove t] is equivalent (but more efficient) to
+ [(fun t -> let i = choose t in (i,remove i t)) t]
+ @author Laurent Hubert*)
+ val choose_and_remove : t -> int*t
+
+end
+
+include S
+
+(** Big-endian Patricia trees *)
+
+module Big : S
+
+(** Big-endian Patricia trees with non-negative elements. Changes:
+ - [add] and [singleton] raise [Invalid_arg] if a negative element is given
+ - [mem] is slightly faster (the Patricia tree is now a search tree)
+ - [min_elt] and [max_elt] are now O(log(N))
+ - [elements] returns a list with elements in ascending order
+ *)
+
+module BigPos : S
diff --git a/src/common/DecEq.v b/src/common/DecEq.v
new file mode 100644
index 0000000..e9d716f
--- /dev/null
+++ b/src/common/DecEq.v
@@ -0,0 +1,150 @@
+(*|
+..
+ Vericert: Verified high-level synthesis.
+ Copyright (C) 2020-2022 Yann Herklotz <yann@yannherklotz.com>
+
+ 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 <https://www.gnu.org/licenses/>.
+
+====================
+Decidable Equalities
+====================
+|*)
+
+Require compcert.backend.RTL.
+Require Import compcert.common.AST.
+Require Import compcert.lib.Maps.
+Require Import compcert.lib.Integers.
+Require Import compcert.lib.Floats.
+
+Require Import vericert.common.Vericertlib.
+Require Import vericert.hls.RTLBlockInstr.
+Require Import vericert.hls.RTLBlock.
+
+Lemma comparison_eq: forall (x y : comparison), {x = y} + {x <> y}.
+Proof.
+ decide equality.
+Defined.
+
+Lemma condition_eq: forall (x y : Op.condition), {x = y} + {x <> y}.
+Proof.
+ generalize comparison_eq; intro.
+ generalize Int.eq_dec; intro.
+ generalize Int64.eq_dec; intro.
+ decide equality.
+Defined.
+
+Lemma addressing_eq : forall (x y : Op.addressing), {x = y} + {x <> y}.
+Proof.
+ generalize Int.eq_dec; intro.
+ generalize AST.ident_eq; intro.
+ generalize Z.eq_dec; intro.
+ generalize Ptrofs.eq_dec; intro.
+ decide equality.
+Defined.
+
+Lemma typ_eq : forall (x y : AST.typ), {x = y} + {x <> y}.
+Proof.
+ decide equality.
+Defined.
+
+Lemma operation_eq: forall (x y : Op.operation), {x = y} + {x <> y}.
+Proof.
+ generalize Int.eq_dec; intro.
+ generalize Int64.eq_dec; intro.
+ generalize Float.eq_dec; intro.
+ generalize Float32.eq_dec; intro.
+ generalize AST.ident_eq; intro.
+ generalize condition_eq; intro.
+ generalize addressing_eq; intro.
+ generalize typ_eq; intro.
+ decide equality.
+Defined.
+
+Lemma memory_chunk_eq : forall (x y : AST.memory_chunk), {x = y} + {x <> y}.
+Proof.
+ decide equality.
+Defined.
+
+Lemma list_typ_eq: forall (x y : list AST.typ), {x = y} + {x <> y}.
+Proof.
+ generalize typ_eq; intro.
+ decide equality.
+Defined.
+
+Lemma option_typ_eq : forall (x y : option AST.typ), {x = y} + {x <> y}.
+Proof.
+ generalize typ_eq; intro.
+ decide equality.
+Defined.
+
+Lemma signature_eq: forall (x y : AST.signature), {x = y} + {x <> y}.
+Proof.
+ repeat decide equality.
+Defined.
+
+Lemma list_operation_eq : forall (x y : list Op.operation), {x = y} + {x <> y}.
+Proof.
+ generalize operation_eq; intro.
+ decide equality.
+Defined.
+
+Lemma list_pos_eq : forall (x y : list positive), {x = y} + {x <> y}.
+Proof.
+ generalize Pos.eq_dec; intros.
+ decide equality.
+Defined.
+
+Lemma sig_eq : forall (x y : AST.signature), {x = y} + {x <> y}.
+Proof.
+ repeat decide equality.
+Defined.
+
+Lemma instr_eq: forall (x y : instr), {x = y} + {x <> y}.
+Proof.
+ generalize Pos.eq_dec; intro.
+ generalize typ_eq; intro.
+ generalize Int.eq_dec; intro.
+ generalize memory_chunk_eq; intro.
+ generalize addressing_eq; intro.
+ generalize operation_eq; intro.
+ generalize condition_eq; intro.
+ generalize signature_eq; intro.
+ generalize list_operation_eq; intro.
+ generalize list_pos_eq; intro.
+ generalize AST.ident_eq; intro.
+ repeat decide equality.
+Defined.
+
+Lemma cf_instr_eq: forall (x y : cf_instr), {x = y} + {x <> y}.
+Proof.
+ generalize Pos.eq_dec; intro.
+ generalize typ_eq; intro.
+ generalize Int.eq_dec; intro.
+ generalize Int64.eq_dec; intro.
+ generalize Float.eq_dec; intro.
+ generalize Float32.eq_dec; intro.
+ generalize Ptrofs.eq_dec; intro.
+ generalize memory_chunk_eq; intro.
+ generalize addressing_eq; intro.
+ generalize operation_eq; intro.
+ generalize condition_eq; intro.
+ generalize signature_eq; intro.
+ generalize list_operation_eq; intro.
+ generalize list_pos_eq; intro.
+ generalize AST.ident_eq; intro.
+ repeat decide equality.
+Defined.
+
+Definition ceq {A: Type} (eqd: forall a b: A, {a = b} + {a <> b}) (a b: A): bool :=
+ if eqd a b then true else false.
diff --git a/src/common/Maps.v b/src/common/Maps.v
index f0f264d..cb9dc2c 100644
--- a/src/common/Maps.v
+++ b/src/common/Maps.v
@@ -17,7 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*)
-Set Implicit Arguments.
+(*Set Implicit Arguments.
Require Export compcert.lib.Maps.
@@ -29,8 +29,9 @@ Import PTree.
Local Open Scope error_monad_scope.
-(** Instance of traverse for [PTree] and [Errors]. This should maybe be generalised
- in the future. *)
+(*|
+Instance of traverse for ``PTree`` and ``Errors``. This should maybe be generalised in the future.
+|*)
Module PTree.
@@ -62,3 +63,4 @@ Definition traverse (A B : Type) (f : positive -> A -> res B) m := xtraverse f m
Definition traverse1 (A B : Type) (f : A -> res B) := traverse (fun _ => f).
End PTree.
+*)
diff --git a/src/common/Show.v b/src/common/Show.v
index 4c66725..20c07e7 100644
--- a/src/common/Show.v
+++ b/src/common/Show.v
@@ -1,4 +1,4 @@
-(*
+(*
* Vericert: Verified high-level synthesis.
* Copyright (C) 2019-2020 Yann Herklotz <yann@yannherklotz.com>
*
@@ -24,15 +24,11 @@ From Coq Require Import
Local Open Scope string.
-Class Show A : Type :=
- {
- show : A -> string
- }.
+Class Show A : Type := { show : A -> string }.
+#[export]
Instance showBool : Show bool :=
- {
- show := fun b:bool => if b then "true" else "false"
- }.
+ { show := fun b:bool => if b then "true" else "false" }.
Fixpoint string_of_nat_aux (time n : nat) (acc : string) : string :=
let d := match n mod 10 with
@@ -52,17 +48,11 @@ Fixpoint string_of_nat_aux (time n : nat) (acc : string) : string :=
Definition string_of_nat (n : nat) : string :=
string_of_nat_aux n n "".
-Instance showNat : Show nat :=
- {
- show := string_of_nat
- }.
+#[export]
+Instance showNat : Show nat := { show := string_of_nat }.
-Instance showZ : Show Z :=
- {
- show a := show (Z.to_nat a)
- }.
+#[export]
+Instance showZ : Show Z := { show a := show (Z.to_nat a) }.
-Instance showPositive : Show positive :=
- {
- show a := show (Zpos a)
- }.
+#[export]
+Instance showPositive : Show positive := { show a := show (Zpos a) }.
diff --git a/src/common/Vericertlib.v b/src/common/Vericertlib.v
index 389a74f..5540f34 100644
--- a/src/common/Vericertlib.v
+++ b/src/common/Vericertlib.v
@@ -28,6 +28,7 @@ Require Import Coq.micromega.Lia.
Require Export compcert.lib.Coqlib.
Require Import compcert.lib.Integers.
+Require Import compcert.lib.Maps.
Require Import vericert.common.Show.
@@ -243,3 +244,45 @@ Definition debug_show {A B : Type} `{Show A} (a : A) (b : B) : B :=
Definition debug_show_msg {A B : Type} `{Show A} (s : string) (a : A) (b : B) : B :=
let unused := debug_print (s ++ show a) in b.
+
+Definition forall_ptree {A:Type} (f:positive->A->bool) (m:Maps.PTree.t A) : bool :=
+ Maps.PTree.fold (fun (res: bool) (i: positive) (x: A) => res && f i x) m true.
+
+Ltac boolInv :=
+ match goal with
+ | [ H: _ && _ = true |- _ ] =>
+ destruct (andb_prop _ _ H); clear H; boolInv
+ | [ H: proj_sumbool _ = true |- _ ] =>
+ generalize (proj_sumbool_true _ H); clear H;
+ let EQ := fresh in (intro EQ; try subst; boolInv)
+ | _ =>
+ idtac
+ end.
+
+Remark ptree_forall:
+ forall (A: Type) (f: positive -> A -> bool) (m: Maps.PTree.t A),
+ Maps.PTree.fold (fun (res: bool) (i: positive) (x: A) => res && f i x) m true = true ->
+ forall i x, Maps.PTree.get i m = Some x -> f i x = true.
+Proof.
+ intros.
+ set (f' := fun (res: bool) (i: positive) (x: A) => res && f i x).
+ set (P := fun (m: Maps.PTree.t A) (res: bool) =>
+ res = true -> Maps.PTree.get i m = Some x -> f i x = true).
+ assert (P m true).
+ rewrite <- H. fold f'. apply Maps.PTree_Properties.fold_rec.
+ unfold P; intros. rewrite <- H1 in H4. auto.
+ red; intros. now rewrite Maps.PTree.gempty in H2.
+ unfold P; intros. unfold f' in H4. boolInv.
+ rewrite Maps.PTree.gsspec in H5. destruct (peq i k).
+ subst. inv H5. auto.
+ apply H3; auto.
+ red in H1. auto.
+Qed.
+
+Lemma forall_ptree_true:
+ forall (A: Type) (f: positive -> A -> bool) (m: Maps.PTree.t A),
+ forall_ptree f m = true ->
+ forall i x, Maps.PTree.get i m = Some x -> f i x = true.
+Proof.
+ apply ptree_forall.
+Qed.
diff --git a/src/common/ZExtra.v b/src/common/ZExtra.v
index 62ca54d..3a27cc6 100644
--- a/src/common/ZExtra.v
+++ b/src/common/ZExtra.v
@@ -45,12 +45,6 @@ Proof.
- apply Z.mod_divide; assumption.
Qed.
-Lemma mod_0_r: forall (m: Z),
- m mod 0 = 0.
-Proof.
- intros. destruct m; reflexivity.
-Qed.
-
Lemma sub_mod_0: forall (a b m: Z),
a mod m = 0 ->
b mod m = 0 ->
@@ -89,18 +83,6 @@ Proof.
reflexivity.
Qed.
-Lemma mod_pow2_same_cases: forall a n,
- a mod 2 ^ n = a ->
- 2 ^ n = 0 /\ a = 0 \/ 0 <= a < 2 ^ n.
-Proof.
- intros.
- assert (n < 0 \/ 0 <= n) as C by lia. destruct C as [C | C].
- - left. rewrite (Z.pow_neg_r 2 n C) in *. rewrite mod_0_r in H. auto.
- - right.
- rewrite <- H. apply Z.mod_pos_bound.
- apply Z.pow_pos_nonneg; lia.
-Qed.
-
Lemma mod_pow2_same_bounds: forall a n,
a mod 2 ^ n = a ->
0 <= n ->
diff --git a/src/extraction/Extraction.v b/src/extraction/Extraction.v
index 3544f9d..395ec47 100644
--- a/src/extraction/Extraction.v
+++ b/src/extraction/Extraction.v
@@ -24,9 +24,10 @@ From vericert Require
RTLPar
RTLBlockInstr
HTLgen
- Pipeline
+ (*Pipeline*)
HLSOpts
Predicate
+ Bourdoncle
.
From Coq Require DecidableClass.
@@ -145,8 +146,10 @@ Extract Constant Compiler.print_Cminor => "PrintCminor.print_if".
Extract Constant driver.Compiler.print_RTL => "PrintRTL.print_if".
Extract Constant Compiler.print_RTL => "PrintRTL.print_if".
Extract Constant Compiler.print_RTLBlock => "PrintRTLBlock.print_if".
+Extract Constant Compiler.print_RTLPar => "PrintRTLPar.print_if".
Extract Constant Compiler.print_HTL => "PrintHTL.print_if".
Extract Constant Compiler.print_RTLPar => "PrintRTLPar.print_if".
+Extract Constant Compiler.print_RTLParFU => "PrintRTLParFU.print_if".
Extract Constant Compiler.print_LTL => "PrintLTL.print_if".
Extract Constant Compiler.print_Mach => "PrintMach.print_if".
Extract Constant Compiler.print => "fun (f: 'a -> unit) (x: 'a) -> f x; x".
@@ -180,10 +183,13 @@ Extract Inlined Constant Binary.B2R => "fun _ -> assert false".
Extract Inlined Constant Binary.round_mode => "fun _ -> assert false".
Extract Inlined Constant Bracket.inbetween_loc => "fun _ -> assert false".
-Extract Constant Pipeline.pipeline => "SoftwarePipelining.pipeline".
+(*Extract Constant Pipeline.pipeline => "pipelining.pipeline".*)
Extract Constant RTLBlockgen.partition => "Partition.partition".
Extract Constant RTLPargen.schedule => "Schedule.schedule_fn".
+(* Loop normalization *)
+Extract Constant IfConversion.build_bourdoncle => "BourdoncleAux.build_bourdoncle".
+
(* Needed in Coq 8.4 to avoid problems with Function definitions. *)
Set Extraction AccessOpaque.
@@ -193,9 +199,9 @@ Separate Extraction
vericert.Compiler.transf_hls_temp
RTLBlockgen.transl_program RTLBlockInstr.successors_instr
HTLgen.tbl_to_case_expr
- Pipeline.pipeline
Predicate.sat_pred_simple
Verilog.stmnt_to_list
+ Bourdoncle.bourdoncle
Compiler.transf_c_program Compiler.transf_cminor_program
Cexec.do_initial_state Cexec.do_step Cexec.at_final_state
diff --git a/src/hls/Abstr.v b/src/hls/Abstr.v
index abc4181..9d310fb 100644
--- a/src/hls/Abstr.v
+++ b/src/hls/Abstr.v
@@ -42,9 +42,9 @@ Require Import vericert.hls.Predicate.
Schedule Oracle
===============
-This oracle determines if a schedule was valid by performing symbolic execution on the input and
-output and showing that these behave the same. This acts on each basic block separately, as the
-rest of the functions should be equivalent.
+This oracle determines if a schedule was valid by performing symbolic execution
+on the input and output and showing that these behave the same. This acts on
+each basic block separately, as the rest of the functions should be equivalent.
|*)
Definition reg := positive.
@@ -55,8 +55,9 @@ Inductive resource : Set :=
| Mem : resource.
(*|
-The following defines quite a few equality comparisons automatically, however, these can be
-optimised heavily if written manually, as their proofs are not needed.
+The following defines quite a few equality comparisons automatically, however,
+these can be optimised heavily if written manually, as their proofs are not
+needed.
|*)
Lemma resource_eq : forall (r1 r2 : resource), {r1 = r2} + {r1 <> r2}.
@@ -180,9 +181,10 @@ Proof.
Defined.
(*|
-We then create equality lemmas for a resource and a module to index resources uniquely. The
-indexing is done by setting Mem to 1, whereas all other infinitely many registers will all be
-shifted right by 1. This means that they will never overlap.
+We then create equality lemmas for a resource and a module to index resources
+uniquely. The indexing is done by setting Mem to 1, whereas all other
+infinitely many registers will all be shifted right by 1. This means that they
+will never overlap.
|*)
Module R_indexed.
@@ -201,17 +203,19 @@ Module R_indexed.
End R_indexed.
(*|
-We can then create expressions that mimic the expressions defined in RTLBlock and RTLPar, which use
-expressions instead of registers as their inputs and outputs. This means that we can accumulate all
-the results of the operations as general expressions that will be present in those registers.
+We can then create expressions that mimic the expressions defined in RTLBlock
+and RTLPar, which use expressions instead of registers as their inputs and
+outputs. This means that we can accumulate all the results of the operations as
+general expressions that will be present in those registers.
- Ebase: the starting value of the register.
- Eop: Some arithmetic operation on a number of registers.
- Eload: A load from a memory location into a register.
- Estore: A store from a register to a memory location.
-Then, to make recursion over expressions easier, expression_list is also defined in the datatype, as
-that enables mutual recursive definitions over the datatypes.
+Then, to make recursion over expressions easier, expression_list is also defined
+in the datatype, as that enables mutual recursive definitions over the
+datatypes.
|*)
Inductive expression : Type :=
@@ -322,8 +326,8 @@ Definition predicated A := NE.non_empty (pred_op * A).
Definition pred_expr := predicated expression.
(*|
-Using IMap we can create a map from resources to any other type, as resources can be uniquely
-identified as positive numbers.
+Using ``IMap`` we can create a map from resources to any other type, as
+resources can be uniquely identified as positive numbers.
|*)
Module Rtree := ITree(R_indexed).
@@ -357,8 +361,9 @@ Definition eval_predf_opt pr p :=
match p with Some p' => eval_predf pr p' | None => true end.
(*|
-Finally we want to define the semantics of execution for the expressions with symbolic values, so
-the result of executing the expressions will be an expressions.
+Finally we want to define the semantics of execution for the expressions with
+symbolic values, so the result of executing the expressions will be an
+expressions.
|*)
Section SEMANTICS.
@@ -630,15 +635,6 @@ Definition encode_expression max pe h :=
(Pand (Por (Pnot p) (Pvar p')) p'', h'')
end.*)
-Fixpoint max_predicate (p: pred_op) : positive :=
- match p with
- | Plit (b, p) => p
- | Ptrue => 1
- | Pfalse => 1
- | Pand a b => Pos.max (max_predicate a) (max_predicate b)
- | Por a b => Pos.max (max_predicate a) (max_predicate b)
- end.
-
Fixpoint max_pred_expr (pe: pred_expr) : positive :=
match pe with
| NE.singleton (p, e) => max_predicate p
@@ -691,7 +687,7 @@ Inductive similar {A B} : @ctx A -> @ctx B -> Prop :=
Definition beq_pred_expr_once (pe1 pe2: pred_expr) : bool :=
match pe1, pe2 with
- (*| PEsingleton None e1, PEsingleton None e2 => beq_expression e1 e2
+ (* PEsingleton None e1, PEsingleton None e2 => beq_expression e1 e2
| PEsingleton (Some p1) e1, PEsingleton (Some p2) e2 =>
if beq_expression e1 e2
then match sat_pred_simple bound (Por (Pand p1 (Pnot p2)) (Pand p2 (Pnot p1))) with
@@ -714,48 +710,6 @@ Definition beq_pred_expr_once (pe1 pe2: pred_expr) : bool :=
equiv_check p1 p2
end.
-Definition forall_ptree {A:Type} (f:positive->A->bool) (m:Maps.PTree.t A) : bool :=
- Maps.PTree.fold (fun (res: bool) (i: positive) (x: A) => res && f i x) m true.
-
-Ltac boolInv :=
- match goal with
- | [ H: _ && _ = true |- _ ] =>
- destruct (andb_prop _ _ H); clear H; boolInv
- | [ H: proj_sumbool _ = true |- _ ] =>
- generalize (proj_sumbool_true _ H); clear H;
- let EQ := fresh in (intro EQ; try subst; boolInv)
- | _ =>
- idtac
- end.
-
-Remark ptree_forall:
- forall (A: Type) (f: positive -> A -> bool) (m: Maps.PTree.t A),
- Maps.PTree.fold (fun (res: bool) (i: positive) (x: A) => res && f i x) m true = true ->
- forall i x, Maps.PTree.get i m = Some x -> f i x = true.
-Proof.
- intros.
- set (f' := fun (res: bool) (i: positive) (x: A) => res && f i x).
- set (P := fun (m: Maps.PTree.t A) (res: bool) =>
- res = true -> Maps.PTree.get i m = Some x -> f i x = true).
- assert (P m true).
- rewrite <- H. fold f'. apply Maps.PTree_Properties.fold_rec.
- unfold P; intros. rewrite <- H1 in H4. auto.
- red; intros. now rewrite Maps.PTree.gempty in H2.
- unfold P; intros. unfold f' in H4. boolInv.
- rewrite Maps.PTree.gsspec in H5. destruct (peq i k).
- subst. inv H5. auto.
- apply H3; auto.
- red in H1. auto.
-Qed.
-
-Lemma forall_ptree_true:
- forall (A: Type) (f: positive -> A -> bool) (m: Maps.PTree.t A),
- forall_ptree f m = true ->
- forall i x, Maps.PTree.get i m = Some x -> f i x = true.
-Proof.
- apply ptree_forall.
-Qed.
-
Definition tree_equiv_check_el (np2: PTree.t pred_op) (n: positive) (p: pred_op): bool :=
match np2 ! n with
| Some p' => equiv_check p p'
@@ -1386,48 +1340,88 @@ Proof.
end; discriminate.
Qed.
-Fixpoint beq2 {A B : Type} (beqA : A -> B -> bool) (m1 : PTree.t A) (m2 : PTree.t B) {struct m1} : bool :=
- match m1, m2 with
- | PTree.Leaf, _ => PTree.bempty m2
- | _, PTree.Leaf => PTree.bempty m1
- | PTree.Node l1 o1 r1, PTree.Node l2 o2 r2 =>
+Section BOOLEAN_EQUALITY.
+
+ Context {A B: Type}.
+ Context (beqA: A -> B -> bool).
+
+ Fixpoint beq2' (m1: PTree.tree' A) (m2: PTree.tree' B) {struct m1} : bool :=
+ match m1, m2 with
+ | PTree.Node001 r1, PTree.Node001 r2 => beq2' r1 r2
+ | PTree.Node010 x1, PTree.Node010 x2 => beqA x1 x2
+ | PTree.Node011 x1 r1, PTree.Node011 x2 r2 => beqA x1 x2 && beq2' r1 r2
+ | PTree.Node100 l1, PTree.Node100 l2 => beq2' l1 l2
+ | PTree.Node101 l1 r1, PTree.Node101 l2 r2 => beq2' l1 l2 && beq2' r1 r2
+ | PTree.Node110 l1 x1, PTree.Node110 l2 x2 => beqA x1 x2 && beq2' l1 l2
+ | PTree.Node111 l1 x1 r1, PTree.Node111 l2 x2 r2 => beqA x1 x2 && beq2' l1 l2 && beq2' r1 r2
+ | _, _ => false
+ end.
+
+ Definition beq2 (m1: PTree.t A) (m2 : PTree.t B) : bool :=
+ match m1, m2 with
+ | PTree.Empty, PTree.Empty => true
+ | PTree.Nodes m1', PTree.Nodes m2' => beq2' m1' m2'
+ | _, _ => false
+ end.
+
+ Let beq2_optA (o1: option A) (o2: option B) : bool :=
match o1, o2 with
| None, None => true
- | Some y1, Some y2 => beqA y1 y2
+ | Some a1, Some a2 => beqA a1 a2
| _, _ => false
- end
- && beq2 beqA l1 l2 && beq2 beqA r1 r2
- end.
+ end.
-Lemma beq2_correct:
- forall A B beqA m1 m2,
- @beq2 A B beqA m1 m2 = true <->
- (forall (x: PTree.elt),
- match PTree.get x m1, PTree.get x m2 with
- | None, None => True
- | Some y1, Some y2 => beqA y1 y2 = true
- | _, _ => False
- end).
-Proof.
- induction m1; intros.
- - simpl. rewrite PTree.bempty_correct. split; intros.
- rewrite PTree.gleaf. rewrite H. auto.
- generalize (H x). rewrite PTree.gleaf. destruct (PTree.get x m2); tauto.
- - destruct m2.
- + unfold beq2. rewrite PTree.bempty_correct. split; intros.
- rewrite H. rewrite PTree.gleaf. auto.
- generalize (H x). rewrite PTree.gleaf.
- destruct (PTree.get x (PTree.Node m1_1 o m1_2)); tauto.
- + simpl. split; intros.
- * destruct (andb_prop _ _ H). destruct (andb_prop _ _ H0).
- rewrite IHm1_1 in H3. rewrite IHm1_2 in H1.
- destruct x; simpl. apply H1. apply H3.
- destruct o; destruct o0; auto || congruence.
- * apply andb_true_intro. split. apply andb_true_intro. split.
- generalize (H xH); simpl. destruct o; destruct o0; tauto.
- apply IHm1_1. intros; apply (H (xO x)).
- apply IHm1_2. intros; apply (H (xI x)).
-Qed.
+ Lemma beq_correct_bool:
+ forall m1 m2,
+ beq2 m1 m2 = true <-> (forall x, beq2_optA (m1 ! x) (m2 ! x) = true).
+ Proof.
+ Local Transparent PTree.Node.
+ assert (beq_NN: forall l1 o1 r1 l2 o2 r2,
+ PTree.not_trivially_empty l1 o1 r1 ->
+ PTree.not_trivially_empty l2 o2 r2 ->
+ beq2 (PTree.Node l1 o1 r1) (PTree.Node l2 o2 r2) =
+ beq2 l1 l2 && beq2_optA o1 o2 && beq2 r1 r2).
+ { intros.
+ destruct l1, o1, r1; try contradiction; destruct l2, o2, r2; try contradiction;
+ simpl; rewrite ? andb_true_r, ? andb_false_r; auto.
+ rewrite andb_comm; auto.
+ f_equal; rewrite andb_comm; auto. }
+ induction m1 using PTree.tree_ind; [|induction m2 using PTree.tree_ind].
+ - intros. simpl; split; intros.
+ + destruct m2; try discriminate. simpl; auto.
+ + replace m2 with (@PTree.Empty B); auto. apply PTree.extensionality; intros x.
+ specialize (H x). destruct (m2 ! x); simpl; easy.
+ - split; intros.
+ + destruct (PTree.Node l o r); try discriminate. simpl; auto.
+ + replace (PTree.Node l o r) with (@PTree.Empty A); auto. apply PTree.extensionality; intros x.
+ specialize (H0 x). destruct ((PTree.Node l o r) ! x); simpl in *; easy.
+ - rewrite beq_NN by auto. split; intros.
+ + InvBooleans. rewrite ! PTree.gNode. destruct x.
+ * apply IHm0; auto.
+ * apply IHm1; auto.
+ * auto.
+ + apply andb_true_intro; split; [apply andb_true_intro; split|].
+ * apply IHm1. intros. specialize (H1 (xO x)); rewrite ! PTree.gNode in H1; auto.
+ * specialize (H1 xH); rewrite ! PTree.gNode in H1; auto.
+ * apply IHm0. intros. specialize (H1 (xI x)); rewrite ! PTree.gNode in H1; auto.
+ Qed.
+
+ Theorem beq2_correct:
+ forall m1 m2,
+ beq2 m1 m2 = true <->
+ (forall (x: PTree.elt),
+ match m1 ! x, m2 ! x with
+ | None, None => True
+ | Some y1, Some y2 => beqA y1 y2 = true
+ | _, _ => False
+ end).
+ Proof.
+ intros. rewrite beq_correct_bool. unfold beq2_optA. split; intros.
+ - specialize (H x). destruct (m1 ! x), (m2 ! x); intuition congruence.
+ - specialize (H x). destruct (m1 ! x), (m2 ! x); intuition auto.
+ Qed.
+
+End BOOLEAN_EQUALITY.
Lemma map1:
forall w dst dst',
diff --git a/src/hls/Array.v b/src/hls/Array.v
index 0f5ae02..de74611 100644
--- a/src/hls/Array.v
+++ b/src/hls/Array.v
@@ -190,7 +190,10 @@ Proof.
auto using nth_error_nth.
Qed.
-(** Tail recursive version of standard library function. *)
+(*|
+Tail recursive version of standard library function.
+|*)
+
Fixpoint list_repeat' {A : Type} (acc : list A) (a : A) (n : nat) : list A :=
match n with
| O => acc
diff --git a/src/hls/AssocMap.v b/src/hls/AssocMap.v
index 8dbc6b2..ee39e8e 100644
--- a/src/hls/AssocMap.v
+++ b/src/hls/AssocMap.v
@@ -1,6 +1,6 @@
(*
* Vericert: Verified high-level synthesis.
- * Copyright (C) 2020 Yann Herklotz <yann@yannherklotz.com>
+ * Copyright (C) 2020-2022 Yann Herklotz <yann@yannherklotz.com>
* 2020 James Pollard <j@mes.dev>
*
* This program is free software: you can redistribute it and/or modify
@@ -42,63 +42,75 @@ Module AssocMapExt.
| Some v => v
end.
- Fixpoint merge (m1 m2 : t A) : t A :=
- match m1, m2 with
- | Node l1 (Some a) r1, Node l2 _ r2 => Node (merge l1 l2) (Some a) (merge r1 r2)
- | Node l1 None r1, Node l2 o r2 => Node (merge l1 l2) o (merge r1 r2)
- | Leaf, _ => m2
- | _, _ => m1
+ Definition merge_atom (new : option A) (old : option A) : option A :=
+ match new, old with
+ | Some _, _ => new
+ | _, _ => old
end.
+ Definition merge (m1 m2 : t A) : t A :=
+ PTree.combine merge_atom m1 m2.
+
Lemma merge_base_1 :
- forall am,
- merge (empty A) am = am.
- Proof. auto. Qed.
+ forall am x,
+ (merge (empty A) am) ! x = am ! x.
+ Proof using.
+ unfold merge; intros.
+ rewrite PTree.gcombine; eauto.
+ Qed.
Lemma merge_base_2 :
- forall am,
- merge am (empty A) = am.
- Proof.
- unfold merge.
- destruct am; trivial.
- destruct o; trivial.
+ forall am x,
+ (merge am (empty A)) ! x = am ! x.
+ Proof using.
+ unfold merge; intros.
+ rewrite PTree.gcombine; eauto.
+ cbv [merge_atom]. destruct_match; crush.
Qed.
Lemma merge_add_assoc :
- forall r am am' v,
- merge (set r v am) am' = set r v (merge am am').
- Proof.
- induction r; intros; destruct am; destruct am'; try (destruct o); simpl;
- try rewrite IHr; try reflexivity.
+ forall r am am' v x,
+ (merge (set r v am) am') ! x = (set r v (merge am am')) ! x.
+ Proof using.
+ unfold merge. intros; rewrite PTree.gcombine by auto.
+ unfold merge_atom. destruct_match.
+ destruct (peq r x); subst.
+ rewrite PTree.gss in Heqo. inv Heqo. rewrite PTree.gss. auto.
+ rewrite PTree.gso in Heqo by auto. rewrite PTree.gso by auto.
+ rewrite PTree.gcombine by auto. rewrite Heqo. auto.
+ destruct (peq r x); subst.
+ rewrite PTree.gss in Heqo. inv Heqo.
+ rewrite PTree.gso in Heqo by auto. rewrite PTree.gso by auto.
+ rewrite PTree.gcombine by auto. rewrite Heqo. auto.
Qed.
Lemma merge_correct_1 :
forall am bm k v,
- get k am = Some v ->
- get k (merge am bm) = Some v.
- Proof.
- induction am; intros; destruct k; destruct bm; try (destruct o); simpl;
- try rewrite gempty in H; try discriminate; try assumption; auto.
+ am ! k = Some v ->
+ (merge am bm) ! k = Some v.
+ Proof using.
+ unfold merge; intros. rewrite PTree.gcombine by auto.
+ rewrite H; auto.
Qed.
Lemma merge_correct_2 :
forall am bm k v,
- get k am = None ->
- get k bm = Some v ->
- get k (merge am bm) = Some v.
- Proof.
- induction am; intros; destruct k; destruct bm; try (destruct o); simpl;
- try rewrite gempty in H; try discriminate; try assumption; auto.
+ am ! k = None ->
+ bm ! k = Some v ->
+ (merge am bm) ! k = Some v.
+ Proof using.
+ unfold merge; intros. rewrite PTree.gcombine by auto.
+ rewrite H. rewrite H0. auto.
Qed.
Lemma merge_correct_3 :
forall am bm k,
- get k am = None ->
- get k bm = None ->
- get k (merge am bm) = None.
- Proof.
- induction am; intros; destruct k; destruct bm; try (destruct o); simpl;
- try rewrite gempty in H; try discriminate; try assumption; auto.
+ am ! k = None ->
+ bm ! k = None ->
+ (merge am bm) ! k = None.
+ Proof using.
+ unfold merge; intros. rewrite PTree.gcombine by auto.
+ rewrite H. rewrite H0. auto.
Qed.
Definition merge_fold (am bm : t A) : t A :=
diff --git a/src/hls/FunctionalUnits.v b/src/hls/FunctionalUnits.v
index e94b8e8..dcbe22f 100644
--- a/src/hls/FunctionalUnits.v
+++ b/src/hls/FunctionalUnits.v
@@ -52,13 +52,11 @@ Record ram := mk_ram {
ram_wr_en: reg;
ram_d_in: reg;
ram_d_out: reg;
- ram_ordering: (ram_addr < ram_en
- /\ ram_en < ram_d_in
- /\ ram_d_in < ram_d_out
- /\ ram_d_out < ram_wr_en
- /\ ram_wr_en < ram_u_en)
}.
+Definition all_ram_regs r :=
+ ram_mem r::ram_en r::ram_u_en r::ram_addr r::ram_wr_en r::ram_d_in r::ram_d_out r::nil.
+
Inductive funct_unit: Type :=
| SignedDiv: divider true -> funct_unit
| UnsignedDiv: divider false -> funct_unit
@@ -77,6 +75,80 @@ Record resources := mk_resources {
res_arch: arch;
}.
+Definition index_div {b:bool} r (d: divider b) :=
+ match r with
+ | 1 => div_numer d
+ | 2 => div_denom d
+ | 3 => div_quot d
+ | _ => div_rem d
+ end.
+
+Definition index_ram r (d: ram) :=
+ match r with
+ | 1 => ram_mem d
+ | 2 => ram_en d
+ | 3 => ram_u_en d
+ | 4 => ram_addr d
+ | 5 => ram_wr_en d
+ | 6 => ram_d_in d
+ | _ => ram_d_out d
+ end.
+
+Definition index_res u r res :=
+ match PTree.get u res with
+ | Some (SignedDiv d) => Some (index_div r d)
+ | Some (UnsignedDiv d) => Some (index_div r d)
+ | Some (Ram d) => Some (index_ram r d)
+ | None => None
+ end.
+
+Definition get_ram n res: option (positive * ram) :=
+ match nth_error (arch_ram (res_arch res)) n with
+ | Some ri =>
+ match PTree.get ri (res_funct_units res) with
+ | Some (Ram r) => Some (ri, r)
+ | _ => None
+ end
+ | None => None
+ end.
+
+Definition get_div n res :=
+ match nth_error (arch_div (res_arch res)) n with
+ | Some ri =>
+ match PTree.get ri (res_funct_units res) with
+ | Some (UnsignedDiv d) => Some (ri, d)
+ | _ => None
+ end
+ | None => None
+ end.
+
+Definition get_sdiv n res :=
+ match nth_error (arch_sdiv (res_arch res)) n with
+ | Some ri =>
+ match PTree.get ri (res_funct_units res) with
+ | Some (SignedDiv d) => Some (ri, d)
+ | _ => None
+ end
+ | None => None
+ end.
+
+Definition set_res fu res :=
+ let max := ((fold_left Pos.max ((arch_sdiv (res_arch res))
+ ++ (arch_div (res_arch res))
+ ++ (arch_ram (res_arch res))) 1) + 1)%positive in
+ let nt := PTree.set max fu (res_funct_units res) in
+ match fu with
+ | UnsignedDiv _ => mk_resources nt (mk_arch (max :: arch_div (res_arch res))
+ (arch_sdiv (res_arch res))
+ (arch_ram (res_arch res)))
+ | SignedDiv _ => mk_resources nt (mk_arch (arch_div (res_arch res))
+ (max :: arch_sdiv (res_arch res))
+ (arch_ram (res_arch res)))
+ | Ram _ => mk_resources nt (mk_arch (arch_div (res_arch res))
+ (arch_sdiv (res_arch res))
+ (max :: arch_ram (res_arch res)))
+ end.
+
Definition initial_funct_units: funct_units := PTree.empty _.
Definition initial_arch := mk_arch nil nil nil.
@@ -90,3 +162,22 @@ Definition funct_unit_stages (f: funct_unit) : positive :=
| UnsignedDiv d => div_stages d
| _ => 1
end.
+
+Definition max_reg_ram r :=
+ fold_right Pos.max 1 (ram_mem r::ram_en r::ram_u_en r::ram_addr r
+ ::ram_wr_en r::ram_d_in r::ram_d_out r::nil).
+
+Definition max_reg_divider {b: bool} (d: divider b) :=
+ fold_right Pos.max 1 (div_numer d::div_denom d::div_quot d::div_rem d::nil).
+
+Definition max_reg_fu fu :=
+ match fu with
+ | SignedDiv d | UnsignedDiv d => max_reg_divider d
+ | Ram r => max_reg_ram r
+ end.
+
+Definition max_reg_funct_units r :=
+ PTree.fold (fun m _ a => Pos.max m (max_reg_fu a)) r 1.
+
+Definition max_reg_resources r :=
+ max_reg_funct_units r.(res_funct_units).
diff --git a/src/hls/HTL.v b/src/hls/HTL.v
index 8cebbfd..f3af3d8 100644
--- a/src/hls/HTL.v
+++ b/src/hls/HTL.v
@@ -28,18 +28,21 @@ Require Import compcert.lib.Integers.
Require Import compcert.lib.Maps.
Require Import vericert.common.Vericertlib.
-Require Import vericert.hls.ValueInt.
-Require Import vericert.hls.AssocMap.
Require Import vericert.hls.Array.
+Require Import vericert.hls.FunctionalUnits.
Require vericert.hls.Verilog.
+Require Import AssocMap.
+Require Import ValueInt.
Local Open Scope positive.
-(** The purpose of the hardware transfer language (HTL) is to create a more
+(*|
+The purpose of the hardware transfer language (HTL) is to create a more
hardware-like layout that is still similar to the register transfer language
(RTL) that it came from. The main change is that function calls become module
instantiations and that we now describe a state machine instead of a
-control-flow graph. *)
+control-flow graph.
+|*)
Local Open Scope assocmap.
@@ -54,24 +57,6 @@ Definition map_well_formed {A : Type} (m : PTree.t A) : Prop :=
In p0 (map fst (Maps.PTree.elements m)) ->
(Z.pos p0 <= Integers.Int.max_unsigned)%Z.
-Record ram := mk_ram {
- ram_size: nat;
- ram_mem: reg;
- ram_en: reg;
- ram_u_en: reg;
- ram_addr: reg;
- ram_wr_en: reg;
- ram_d_in: reg;
- ram_d_out: reg;
- ram_ordering: (ram_addr < ram_en
- /\ ram_en < ram_d_in
- /\ ram_d_in < ram_d_out
- /\ ram_d_out < ram_wr_en
- /\ ram_wr_en < ram_u_en)
-}.
-
-Definition module_ordering a b c d e f g := a < b < c /\ c < d < e /\ e < f < g.
-
Record module: Type :=
mkmodule {
mod_params : list reg;
@@ -79,8 +64,6 @@ Record module: Type :=
mod_controllogic : controllogic;
mod_entrypoint : node;
mod_st : reg;
- mod_stk : reg;
- mod_stk_len : nat;
mod_finish : reg;
mod_return : reg;
mod_start : reg;
@@ -88,11 +71,7 @@ Record module: Type :=
mod_clk : reg;
mod_scldecls : AssocMap.t (option Verilog.io * Verilog.scl_decl);
mod_arrdecls : AssocMap.t (option Verilog.io * Verilog.arr_decl);
- mod_ram : option ram;
- mod_wf : map_well_formed mod_controllogic /\ map_well_formed mod_datapath;
- mod_ordering_wf : module_ordering mod_st mod_finish mod_return mod_stk mod_start mod_reset mod_clk;
- mod_ram_wf : forall r', mod_ram = Some r' -> mod_clk < ram_addr r';
- mod_params_wf : Forall (Pos.gt mod_st) mod_params;
+ mod_ram : ram;
}.
Definition fundef := AST.fundef module.
@@ -106,9 +85,12 @@ Fixpoint init_regs (vl : list value) (rl : list reg) {struct rl} :=
end.
Definition empty_stack (m : module) : Verilog.assocmap_arr :=
- (AssocMap.set m.(mod_stk) (Array.arr_repeat None m.(mod_stk_len)) (AssocMap.empty Verilog.arr)).
+ (AssocMap.set m.(mod_ram).(ram_mem) (Array.arr_repeat None m.(mod_ram).(ram_size)) (AssocMap.empty Verilog.arr)).
-(** * Operational Semantics *)
+(*|
+Operational Semantics
+=====================
+|*)
Definition genv := Globalenvs.Genv.t fundef unit.
@@ -137,13 +119,13 @@ Inductive state : Type :=
(args : list value), state.
Inductive exec_ram:
- Verilog.reg_associations -> Verilog.arr_associations -> option ram ->
+ Verilog.reg_associations -> Verilog.arr_associations -> ram ->
Verilog.reg_associations -> Verilog.arr_associations -> Prop :=
| exec_ram_Some_idle:
forall ra ar r,
Int.eq (Verilog.assoc_blocking ra)#(ram_en r, 32)
(Verilog.assoc_blocking ra)#(ram_u_en r, 32) = true ->
- exec_ram ra ar (Some r) ra ar
+ exec_ram ra ar r ra ar
| exec_ram_Some_write:
forall ra ar r d_in addr en wr_en u_en,
Int.eq en u_en = false ->
@@ -153,7 +135,7 @@ Inductive exec_ram:
(Verilog.assoc_blocking ra)!(ram_wr_en r) = Some wr_en ->
(Verilog.assoc_blocking ra)!(ram_d_in r) = Some d_in ->
(Verilog.assoc_blocking ra)!(ram_addr r) = Some addr ->
- exec_ram ra ar (Some r) (Verilog.nonblock_reg (ram_en r) ra u_en)
+ exec_ram ra ar r (Verilog.nonblock_reg (ram_en r) ra u_en)
(Verilog.nonblock_arr (ram_mem r) (valueToNat addr) ar d_in)
| exec_ram_Some_read:
forall ra ar r addr v_d_out en u_en,
@@ -164,11 +146,8 @@ Inductive exec_ram:
(Verilog.assoc_blocking ra)!(ram_addr r) = Some addr ->
Verilog.arr_assocmap_lookup (Verilog.assoc_blocking ar)
(ram_mem r) (valueToNat addr) = Some v_d_out ->
- exec_ram ra ar (Some r) (Verilog.nonblock_reg (ram_en r)
- (Verilog.nonblock_reg (ram_d_out r) ra v_d_out) u_en) ar
-| exec_ram_None:
- forall r a,
- exec_ram r a None r a.
+ exec_ram ra ar r (Verilog.nonblock_reg (ram_en r)
+ (Verilog.nonblock_reg (ram_d_out r) ra v_d_out) u_en) ar.
Inductive step : genv -> state -> Events.trace -> state -> Prop :=
| step_module :
@@ -246,6 +225,10 @@ Definition semantics (m : program) :=
Smallstep.Semantics step (initial_state m) final_state
(Globalenvs.Genv.globalenv m).
+Definition all_module_regs m :=
+ all_ram_regs (mod_ram m) ++
+ (mod_st m::mod_finish m::mod_return m::mod_start m::mod_reset m::mod_clk m::nil).
+
Definition max_pc_function (m: module) :=
List.fold_left Pos.max (List.map fst (PTree.elements m.(mod_controllogic))) 1.
@@ -266,17 +249,20 @@ Definition max_reg_ram r :=
(Pos.max (ram_d_out ram) (ram_u_en ram)))))))
end.
-Definition max_reg_module m :=
+Definition max_reg_body m :=
Pos.max (max_list (mod_params m))
- (Pos.max (max_stmnt_tree (mod_datapath m))
- (Pos.max (max_stmnt_tree (mod_controllogic m))
- (Pos.max (mod_st m)
- (Pos.max (mod_stk m)
- (Pos.max (mod_finish m)
- (Pos.max (mod_return m)
- (Pos.max (mod_start m)
- (Pos.max (mod_reset m)
- (Pos.max (mod_clk m) (max_reg_ram (mod_ram m))))))))))).
+ (Pos.max (max_stmnt_tree (mod_datapath m))
+ (max_stmnt_tree (mod_controllogic m))).
+
+Definition max_reg_module m :=
+ Pos.max (max_reg_body m) (max_list (all_module_regs m)).
+
+Record wf_htl_module m :=
+ mk_wf_htl_module {
+ mod_wf : map_well_formed (mod_controllogic m) /\ map_well_formed (mod_datapath m);
+ mod_ordering_wf : list_norepet (all_module_regs m);
+ mod_gt : Forall (Pos.lt (max_reg_body m)) (all_module_regs m);
+ }.
Lemma max_fold_lt :
forall m l n, m <= n -> m <= (fold_left Pos.max l n).
@@ -333,12 +319,16 @@ Proof. intros. apply max_reg_stmnt_le_stmnt_tree in H; lia. Qed.
Lemma max_stmnt_lt_module :
forall m d i,
+ wf_htl_module m ->
(mod_controllogic m) ! i = Some d \/ (mod_datapath m) ! i = Some d ->
Verilog.max_reg_stmnt d < max_reg_module m + 1.
Proof.
- inversion 1 as [ Hv | Hv ]; unfold max_reg_module;
- apply max_reg_stmnt_le_stmnt_tree in Hv; lia.
-Qed.
+ intros. apply mod_gt in H.
+ unfold Pos.lt, max_reg_body, max_reg_module, max_list, all_module_regs, all_ram_regs in *.
+ simplify.
+ repeat match goal with H: Forall _ _ |- _ => inv H end.
+ inversion H0 as [Hv | Hv]; apply max_reg_stmnt_le_stmnt_tree in Hv.
+ Admitted.
Lemma max_list_correct l st : st > max_list l -> Forall (Pos.gt st) l.
Proof. induction l; crush; constructor; [|apply IHl]; lia. Qed.
@@ -352,3 +342,13 @@ Definition max_list_dec (l: list reg) (st: reg) : {Forall (Pos.gt st) l} + {True
); auto.
apply max_list_correct. apply Pos.ltb_lt in e. lia.
Qed.
+
+Variant wf_htl_fundef: fundef -> Prop :=
+ | wf_htl_fundef_external: forall ef,
+ wf_htl_fundef (AST.External ef)
+ | wf_htl_function_internal: forall f,
+ wf_htl_module f ->
+ wf_htl_fundef (AST.Internal f).
+
+Definition wf_htl_program (p: program) : Prop :=
+ forall f id, In (id, AST.Gfun f) (AST.prog_defs p) -> wf_htl_fundef f.
diff --git a/src/hls/HTLPargen.v b/src/hls/HTLPargen.v
index b0815b7..8960ef9 100644
--- a/src/hls/HTLPargen.v
+++ b/src/hls/HTLPargen.v
@@ -1,6 +1,6 @@
(*
* Vericert: Verified high-level synthesis.
- * Copyright (C) 2020 Yann Herklotz <yann@yannherklotz.com>
+ * Copyright (C) 2021 Yann Herklotz <yann@yannherklotz.com>
*
* 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
@@ -27,10 +27,12 @@ Require Import compcert.lib.Maps.
Require Import vericert.common.Statemonad.
Require Import vericert.common.Vericertlib.
Require Import vericert.hls.AssocMap.
+Require Import vericert.hls.FunctionalUnits.
Require Import vericert.hls.HTL.
Require Import vericert.hls.Predicate.
Require Import vericert.hls.RTLBlockInstr.
-Require Import vericert.hls.RTLPar.
+Require Import vericert.hls.RTLParFU.
+Require Import vericert.hls.FunctionalUnits.
Require Import vericert.hls.ValueInt.
Require Import vericert.hls.Verilog.
@@ -143,6 +145,30 @@ Definition declare_reg (i : option io) (r : reg) (sz : nat) : mon unit :=
s.(st_controllogic))
(declare_reg_state_incr i s r sz).
+Lemma declare_arr_state_incr :
+ forall i s r sz ln,
+ st_incr s
+ (mkstate
+ s.(st_st)
+ s.(st_freshreg)
+ s.(st_freshstate)
+ s.(st_scldecls)
+ (AssocMap.set r (i, VArray sz ln) s.(st_arrdecls))
+ s.(st_datapath)
+ s.(st_controllogic)).
+Proof. Admitted.
+
+Definition declare_arr (i : option io) (r : reg) (sz : nat) (ln : nat) : mon unit :=
+ fun s => OK tt (mkstate
+ s.(st_st)
+ s.(st_freshreg)
+ s.(st_freshstate)
+ s.(st_scldecls)
+ (AssocMap.set r (i, VArray sz ln) s.(st_arrdecls))
+ s.(st_datapath)
+ s.(st_controllogic))
+ (declare_arr_state_incr i s r sz ln).
+
Lemma add_instr_state_incr :
forall s n n' st,
(st_controllogic s)!n = None ->
@@ -328,6 +354,30 @@ Definition check_address_parameter_signed (p : Z) : bool :=
Definition check_address_parameter_unsigned (p : Z) : bool :=
Z.leb p Integers.Ptrofs.max_unsigned.
+Lemma create_reg_state_incr:
+ forall s sz i,
+ st_incr s (mkstate
+ s.(st_st)
+ (Pos.succ (st_freshreg s))
+ (st_freshstate s)
+ (AssocMap.set s.(st_freshreg) (i, VScalar sz) s.(st_scldecls))
+ s.(st_arrdecls)
+ (st_datapath s)
+ (st_controllogic s)).
+Proof. constructor; simpl; auto with htlh. Qed.
+
+Definition create_reg (i : option io) (sz : nat) : mon reg :=
+ fun s => let r := s.(st_freshreg) in
+ OK r (mkstate
+ s.(st_st)
+ (Pos.succ r)
+ (st_freshstate s)
+ (AssocMap.set s.(st_freshreg) (i, VScalar sz) s.(st_scldecls))
+ (st_arrdecls s)
+ (st_datapath s)
+ (st_controllogic s))
+ (create_reg_state_incr s sz i).
+
Definition translate_eff_addressing (a: Op.addressing) (args: list reg)
: mon expr :=
match a, args with (* TODO: We should be more methodical here; what are the possibilities?*)
@@ -355,7 +405,10 @@ Definition translate_eff_addressing (a: Op.addressing) (args: list reg)
| _, _ => error (Errors.msg "HTLPargen: translate_eff_addressing unsuported addressing")
end.
-(** Translate an instruction to a statement. FIX mulhs mulhu *)
+(*|
+Translate an instruction to a statement. FIX mulhs mulhu
+|*)
+
Definition translate_instr (op : Op.operation) (args : list reg) : mon expr :=
match op, args with
| Op.Omove, r::nil => ret (Vvar r)
@@ -432,28 +485,6 @@ Definition add_branch_instr (e: expr) (n n1 n2: node) : mon unit :=
| _ => Error (Errors.msg "Htlgen: add_branch_instr")
end.
-Definition translate_arr_access (mem : AST.memory_chunk) (addr : Op.addressing)
- (args : list reg) (stack : reg) : mon expr :=
- match mem, addr, args with (* TODO: We should be more methodical here; what are the possibilities?*)
- | Mint32, Op.Aindexed off, r1::nil =>
- if (check_address_parameter_signed off)
- then ret (Vvari stack (Vbinop Vdivu (boplitz Vadd r1 off) (Vlit (ZToValue 4))))
- else error (Errors.msg "HTLgen: translate_arr_access address out of bounds")
- | Mint32, Op.Aindexed2scaled scale offset, r1::r2::nil => (* Typical for dynamic array addressing *)
- if (check_address_parameter_signed scale) && (check_address_parameter_signed offset)
- then ret (Vvari stack
- (Vbinop Vdivu
- (Vbinop Vadd (boplitz Vadd r1 offset) (boplitz Vmul r2 scale))
- (Vlit (ZToValue 4))))
- else error (Errors.msg "HTLgen: translate_arr_access address out of bounds")
- | Mint32, Op.Ainstack a, nil => (* We need to be sure that the base address is aligned *)
- let a := Integers.Ptrofs.unsigned a in
- if (check_address_parameter_unsigned a)
- then ret (Vvari stack (Vlit (ZToValue (a / 4))))
- else error (Errors.msg "HTLgen: eff_addressing out of bounds stack offset")
- | _, _, _ => error (Errors.msg "HTLgen: translate_arr_access unsuported addressing")
- end.
-
Fixpoint enumerate (i : nat) (ns : list node) {struct ns} : list (nat * node) :=
match ns with
| n :: ns' => (i, n) :: enumerate (i+1) ns'
@@ -469,30 +500,6 @@ Definition tbl_to_case_expr (st : reg) (ns : list node) : list (expr * stmnt) :=
Definition stack_correct (sz : Z) : bool :=
(0 <=? sz) && (sz <? Integers.Ptrofs.modulus) && (Z.modulo sz 4 =? 0).
-Lemma create_reg_state_incr:
- forall s sz i,
- st_incr s (mkstate
- s.(st_st)
- (Pos.succ (st_freshreg s))
- (st_freshstate s)
- (AssocMap.set s.(st_freshreg) (i, VScalar sz) s.(st_scldecls))
- s.(st_arrdecls)
- (st_datapath s)
- (st_controllogic s)).
-Proof. constructor; simpl; auto with htlh. Qed.
-
-Definition create_reg (i : option io) (sz : nat) : mon reg :=
- fun s => let r := s.(st_freshreg) in
- OK r (mkstate
- s.(st_st)
- (Pos.succ r)
- (st_freshstate s)
- (AssocMap.set s.(st_freshreg) (i, VScalar sz) s.(st_scldecls))
- (st_arrdecls s)
- (st_datapath s)
- (st_controllogic s))
- (create_reg_state_incr s sz i).
-
Lemma create_arr_state_incr:
forall s sz ln i,
st_incr s (mkstate
@@ -678,23 +685,18 @@ Definition translate_predicate (a : assignment)
ret (a dst (Vternary (pred_expr preg pos) e dst))
end.
-Definition translate_inst a (fin rtrn stack preg : reg) (n : node) (i : instr)
+Definition translate_inst a (fin rtrn preg : reg) (n : node) (i : instr)
: mon stmnt :=
match i with
- | RBnop =>
+ | FUnop =>
ret Vskip
- | RBop p op args dst =>
+ | FUop p op args dst =>
do instr <- translate_instr op args;
do _ <- declare_reg None dst 32;
translate_predicate a preg p (Vvar dst) instr
- | RBload p chunk addr args dst =>
- do src <- translate_arr_access chunk addr args stack;
- do _ <- declare_reg None dst 32;
- translate_predicate a preg p (Vvar dst) src
- | RBstore p chunk addr args src =>
- do dst <- translate_arr_access chunk addr args stack;
- translate_predicate a preg p dst (Vvar src)
- | RBsetpred _ c args p =>
+ | FUread p1 p2 r => ret Vskip
+ | FUwrite p1 p2 r => ret Vskip
+ | FUsetpred _ c args p =>
do cond <- translate_condition c args;
ret (a (pred_expr preg (Plit (true, p))) cond)
end.
@@ -724,28 +726,28 @@ Definition create_new_state (p: node): mon node :=
s.(st_controllogic))
(create_new_state_state_incr s p).
-Definition translate_inst_list (fin rtrn stack preg: reg) (ni : node * node * list (list instr)) :=
+Definition translate_inst_list (fin rtrn preg: reg) (ni : node * node * list (list instr)) :=
match ni with
| (n, p, li) =>
do _ <- collectlist
(fun l =>
- do stmnt <- translate_inst Vblock fin rtrn stack preg n l;
+ do stmnt <- translate_inst Vblock fin rtrn preg n l;
add_data_instr n stmnt) (concat li);
do st <- get;
add_control_instr n (state_goto st.(st_st) p)
end.
-Fixpoint translate_cfi' (fin rtrn stack preg: reg) (cfi: cf_instr)
+Fixpoint translate_cfi' (fin rtrn preg: reg) (cfi: cf_instr)
: mon (stmnt * stmnt) :=
match cfi with
- | RBgoto n' =>
+ | FUgoto n' =>
do st <- get;
ret (Vskip, state_goto st.(st_st) n')
- | RBcond c args n1 n2 =>
+ | FUcond c args n1 n2 =>
do st <- get;
do e <- translate_condition c args;
ret (Vskip, state_cond st.(st_st) e n1 n2)
- | RBreturn r =>
+ | FUreturn r =>
match r with
| Some r' =>
ret ((Vseq (block fin (Vlit (ZToValue 1%Z))) (block rtrn (Vvar r'))),
@@ -754,41 +756,41 @@ Fixpoint translate_cfi' (fin rtrn stack preg: reg) (cfi: cf_instr)
ret ((Vseq (block fin (Vlit (ZToValue 1%Z))) (block rtrn (Vlit (ZToValue 0%Z)))),
Vskip)
end
- | RBpred_cf p c1 c2 =>
- do (tc1s, tc1c) <- translate_cfi' fin rtrn stack preg c1;
- do (tc2s, tc2c) <- translate_cfi' fin rtrn stack preg c2;
+ | FUpred_cf p c1 c2 =>
+ do (tc1s, tc1c) <- translate_cfi' fin rtrn preg c1;
+ do (tc2s, tc2c) <- translate_cfi' fin rtrn preg c2;
ret ((Vcond (pred_expr preg p) tc1s tc2s), (Vcond (pred_expr preg p) tc1c tc2c))
- | RBjumptable r tbl =>
+ | FUjumptable r tbl =>
do s <- get;
ret (Vskip, Vcase (Vvar r) (list_to_stmnt (tbl_to_case_expr s.(st_st) tbl)) (Some Vskip))
- | RBcall sig ri rl r n =>
+ | FUcall sig ri rl r n =>
error (Errors.msg "HTLPargen: RPcall not supported.")
- | RBtailcall sig ri lr =>
+ | FUtailcall sig ri lr =>
error (Errors.msg "HTLPargen: RPtailcall not supported.")
- | RBbuiltin e lb b n =>
+ | FUbuiltin e lb b n =>
error (Errors.msg "HTLPargen: RPbuildin not supported.")
end.
-Definition translate_cfi (fin rtrn stack preg: reg) (ni: node * cf_instr)
+Definition translate_cfi (fin rtrn preg: reg) (ni: node * cf_instr)
: mon unit :=
let (n, cfi) := ni in
- do (s, c) <- translate_cfi' fin rtrn stack preg cfi;
+ do (s, c) <- translate_cfi' fin rtrn preg cfi;
do _ <- add_control_instr n c;
add_data_instr n s.
-Definition transf_bblock (fin rtrn stack preg: reg) (ni : node * bblock)
+Definition transf_bblock (fin rtrn preg: reg) (ni : node * bblock)
: mon unit :=
let (n, bb) := ni in
do nstate <- create_new_state ((poslength bb.(bb_body)))%positive;
- do _ <- collectlist (translate_inst_list fin rtrn stack preg)
+ do _ <- collectlist (translate_inst_list fin rtrn preg)
(prange n (nstate + poslength bb.(bb_body) - 1)%positive
bb.(bb_body));
match bb.(bb_body) with
- | nil => translate_cfi fin rtrn stack preg (n, bb.(bb_exit))
- | _ => translate_cfi fin rtrn stack preg (nstate, bb.(bb_exit))
+ | nil => translate_cfi fin rtrn preg (n, bb.(bb_exit))
+ | _ => translate_cfi fin rtrn preg (nstate, bb.(bb_exit))
end.
-Definition decide_order a b c d e f g : {module_ordering a b c d e f g} + {True}.
+(*Definition decide_order a b c d e f g : {module_ordering a b c d e f g} + {True}.
refine (match bool_dec ((a <? b) && (b <? c) && (c <? d)
&& (d <? e) && (e <? f) && (f <? g))%positive true with
| left t => left _
@@ -797,56 +799,65 @@ Definition decide_order a b c d e f g : {module_ordering a b c d e f g} + {True}
simplify; repeat match goal with
| H: context[(_ <? _)%positive] |- _ => apply Pos.ltb_lt in H
end; unfold module_ordering; auto.
-Defined.
+Defined.*)
-Definition transf_module (f: function) : mon HTL.module.
- refine (
+Lemma clk_greater :
+ forall ram clk r',
+ Some ram = Some r' -> (clk < ram_addr r')%positive.
+Proof. Admitted.
+
+Definition declare_ram (r: ram) : mon unit :=
+ do _ <- declare_reg None r.(ram_en) 1;
+ do _ <- declare_reg None r.(ram_u_en) 1;
+ do _ <- declare_reg None r.(ram_wr_en) 1;
+ do _ <- declare_reg None r.(ram_addr) 32;
+ do _ <- declare_reg None r.(ram_d_in) 32;
+ do _ <- declare_reg None r.(ram_d_out) 32;
+ do _ <- declare_arr None r.(ram_mem) 32 r.(ram_size);
+ ret tt.
+
+Definition transf_module (f: function) : mon HTL.module :=
if stack_correct f.(fn_stacksize) then
do fin <- create_reg (Some Voutput) 1;
do rtrn <- create_reg (Some Voutput) 32;
- do (stack, stack_len) <- create_arr None 32
- (Z.to_nat (f.(fn_stacksize) / 4));
do preg <- create_reg None 32;
- do _ <- collectlist (transf_bblock fin rtrn stack preg)
+ do _ <- collectlist (transf_bblock fin rtrn preg)
(Maps.PTree.elements f.(fn_code));
do _ <- collectlist (fun r => declare_reg (Some Vinput) r 32)
f.(fn_params);
do start <- create_reg (Some Vinput) 1;
do rst <- create_reg (Some Vinput) 1;
do clk <- create_reg (Some Vinput) 1;
- do current_state <- get;
- match zle (Z.pos (max_pc_map current_state.(st_datapath)))
- Integers.Int.max_unsigned,
+ match get_ram 0 (fn_funct_units f) with
+ | Some (_, r) =>
+ do _ <- declare_ram r;
+ do current_state <- get;
+ match zle (Z.pos (max_pc_map current_state.(st_datapath)))
+ Integers.Int.max_unsigned,
zle (Z.pos (max_pc_map current_state.(st_controllogic)))
Integers.Int.max_unsigned,
- decide_order (st_st current_state) fin rtrn stack start rst clk,
max_list_dec (fn_params f) (st_st current_state)
- with
- | left LEDATA, left LECTRL, left MORD, left WFPARAMS =>
- ret (HTL.mkmodule
- f.(fn_params)
- current_state.(st_datapath)
- current_state.(st_controllogic)
- f.(fn_entrypoint)
- current_state.(st_st)
- stack
- stack_len
- fin
- rtrn
- start
- rst
- clk
- current_state.(st_scldecls)
- current_state.(st_arrdecls)
- None
- (conj (max_pc_wf _ LECTRL) (max_pc_wf _ LEDATA))
- MORD
- _
- WFPARAMS)
- | _, _, _, _ => error (Errors.msg "More than 2^32 states.")
+ with
+ | left LEDATA, left LECTRL, left WFPARAMS =>
+ ret (HTL.mkmodule
+ f.(fn_params)
+ current_state.(st_datapath)
+ current_state.(st_controllogic)
+ f.(fn_entrypoint)
+ current_state.(st_st)
+ fin
+ rtrn
+ start
+ rst
+ clk
+ current_state.(st_scldecls)
+ current_state.(st_arrdecls)
+ r)
+ | _, _, _=> error (Errors.msg "More than 2^32 states.")
+ end
+ | _ => error (Errors.msg "Stack RAM not found.")
end
- else error (Errors.msg "Stack size misalignment.")); discriminate.
-Defined.
+ else error (Errors.msg "Stack size misalignment.").
Definition max_state (f: function) : state :=
let st := Pos.succ (max_reg_function f) in
@@ -863,7 +874,7 @@ Definition transl_module (f : function) : Errors.res HTL.module :=
Definition transl_fundef := transf_partial_fundef transl_module.
-Definition main_is_internal (p : RTLPar.program) : bool :=
+Definition main_is_internal (p : RTLParFU.program) : bool :=
let ge := Globalenvs.Genv.globalenv p in
match Globalenvs.Genv.find_symbol ge p.(AST.prog_main) with
| Some b =>
@@ -874,7 +885,7 @@ Definition main_is_internal (p : RTLPar.program) : bool :=
| _ => false
end.
-Definition transl_program (p : RTLBlockInstr.program) : Errors.res HTL.program :=
+Definition transl_program (p : RTLParFU.program) : Errors.res HTL.program :=
if main_is_internal p
then transform_partial_program transl_fundef p
else Errors.Error (Errors.msg "Main function is not Internal.").
diff --git a/src/hls/HTLgen.v b/src/hls/HTLgen.v
index 3f4e513..c793b1b 100644
--- a/src/hls/HTLgen.v
+++ b/src/hls/HTLgen.v
@@ -32,6 +32,7 @@ Require Import vericert.hls.AssocMap.
Require Import vericert.hls.HTL.
Require Import vericert.hls.ValueInt.
Require Import vericert.hls.Verilog.
+Require Import vericert.hls.FunctionalUnits.
#[local] Hint Resolve AssocMap.gempty : htlh.
#[local] Hint Resolve AssocMap.gso : htlh.
@@ -583,7 +584,7 @@ Proof.
simplify. transitivity (Z.pos (max_pc_map m)); eauto.
Qed.
-Definition decide_order a b c d e f g : {module_ordering a b c d e f g} + {True}.
+(*Definition decide_order a b c d e f g : {module_ordering a b c d e f g} + {True}.
refine (match bool_dec ((a <? b) && (b <? c) && (c <? d)
&& (d <? e) && (e <? f) && (f <? g))%positive true with
| left t => left _
@@ -592,7 +593,7 @@ Definition decide_order a b c d e f g : {module_ordering a b c d e f g} + {True}
simplify; repeat match goal with
| H: context[(_ <? _)%positive] |- _ => apply Pos.ltb_lt in H
end; unfold module_ordering; auto.
-Defined.
+Defined.*)
Definition transf_module (f: function) : mon HTL.module.
refine (
@@ -605,21 +606,24 @@ Definition transf_module (f: function) : mon HTL.module.
do start <- create_reg (Some Vinput) 1;
do rst <- create_reg (Some Vinput) 1;
do clk <- create_reg (Some Vinput) 1;
+ do r_en <- create_reg None 1;
+ do r_u_en <- create_reg None 1;
+ do r_addr <- create_reg None 32;
+ do r_wr_en <- create_reg None 1;
+ do r_d_in <- create_reg None 32;
+ do r_d_out <- create_reg None 32;
do current_state <- get;
match zle (Z.pos (max_pc_map current_state.(st_datapath))) Integers.Int.max_unsigned,
zle (Z.pos (max_pc_map current_state.(st_controllogic))) Integers.Int.max_unsigned,
- decide_order (st_st current_state) fin rtrn stack start rst clk,
max_list_dec (RTL.fn_params f) (st_st current_state)
with
- | left LEDATA, left LECTRL, left MORD, left WFPARAMS =>
+ | left LEDATA, left LECTRL, left WFPARAMS =>
ret (HTL.mkmodule
f.(RTL.fn_params)
current_state.(st_datapath)
current_state.(st_controllogic)
f.(fn_entrypoint)
current_state.(st_st)
- stack
- stack_len
fin
rtrn
start
@@ -627,12 +631,8 @@ Definition transf_module (f: function) : mon HTL.module.
clk
current_state.(st_scldecls)
current_state.(st_arrdecls)
- None
- (conj (max_pc_wf _ LECTRL) (max_pc_wf _ LEDATA))
- MORD
- _
- WFPARAMS)
- | _, _, _, _ => error (Errors.msg "More than 2^32 states.")
+ (mk_ram stack_len stack r_en r_u_en r_addr r_wr_en r_d_in r_d_out))
+ | _, _, _ => error (Errors.msg "More than 2^32 states.")
end
else error (Errors.msg "Stack size misalignment.")); discriminate.
Defined.
diff --git a/src/hls/HTLgenproof.v b/src/hls/HTLgenproof.v
index fc7af6b..bf1ef1c 100644
--- a/src/hls/HTLgenproof.v
+++ b/src/hls/HTLgenproof.v
@@ -34,6 +34,7 @@ Require vericert.hls.HTL.
Require Import vericert.hls.HTLgen.
Require Import vericert.hls.HTLgenspec.
Require Import vericert.hls.ValueInt.
+Require Import vericert.hls.FunctionalUnits.
Require vericert.hls.Verilog.
Require Import Lia.
@@ -62,10 +63,10 @@ Definition state_st_wf (m : HTL.module) (s : HTL.state) :=
Inductive match_arrs (m : HTL.module) (f : RTL.function) (sp : Values.val) (mem : mem) :
Verilog.assocmap_arr -> Prop :=
| match_arr : forall asa stack,
- asa ! (m.(HTL.mod_stk)) = Some stack /\
+ asa ! (m.(HTL.mod_ram).(ram_mem)) = Some stack /\
stack.(arr_length) = Z.to_nat (f.(RTL.fn_stacksize) / 4) /\
(forall ptr,
- 0 <= ptr < Z.of_nat m.(HTL.mod_stk_len) ->
+ 0 <= ptr < Z.of_nat m.(HTL.mod_ram).(ram_size) ->
opt_val_value_lessdef (Mem.loadv AST.Mint32 mem
(Values.Val.offset_ptr sp (Integers.Ptrofs.repr (4 * ptr))))
(Option.default (NToValue 0)
@@ -1003,26 +1004,29 @@ Section CORRECTNESS.
constructor.
Qed.
- (** The proof of semantic preservation for the translation of instructions
- is a simulation argument based on diagrams of the following form:
-<<
- match_states
- code st rs ---------------- State m st assoc
- || |
- || |
- || |
- \/ v
- code st rs' --------------- State m st assoc'
- match_states
->>
- where [tr_code c data control fin rtrn st] is assumed to hold.
-
- The precondition and postcondition is that that should hold is [match_assocmaps rs assoc].
- *)
+(*|
+The proof of semantic preservation for the translation of instructions is a
+simulation argument based on diagrams of the following form:
+
+::
+> match_states
+> code st rs ------------------------- State m st assoc
+> || |
+> || |
+> || |
+> \/ v
+> code st rs' ------------------------ State m st assoc'
+> match_states
+
+where ``tr_code c data control fin rtrn st`` is assumed to hold.
+
+The precondition and postcondition is that that should hold is ``match_assocmaps
+rs assoc``.
+|*)
Definition transl_instr_prop (instr : RTL.instruction) : Prop :=
forall m asr asa fin rtrn st stmt trans res,
- tr_instr fin rtrn st (m.(HTL.mod_stk)) instr stmt trans ->
+ tr_instr fin rtrn st (m.(HTL.mod_ram).(ram_mem)) instr stmt trans ->
exists asr' asa',
HTL.step tge (HTL.State res m st asr asa) Events.E0 (HTL.State res m st asr' asa').
@@ -1090,7 +1094,7 @@ Section CORRECTNESS.
apply Smallstep.plus_one.
eapply HTL.step_module; eauto.
inv CONST; assumption.
- inv CONST; assumption.
+ inv CONST; assumption.
(* processing of state *)
econstructor.
crush.
@@ -1098,9 +1102,9 @@ Section CORRECTNESS.
econstructor.
econstructor.
- all: invert MARR; big_tac.
+ all: invert MARR; big_tac. Abort.
- inv CONST; constructor; simplify; rewrite AssocMap.gso; auto; lia.
+(* inv CONST; constructor; simplify; rewrite AssocMap.gso; auto; lia.
Unshelve. exact tt.
Qed.
@@ -2568,7 +2572,7 @@ Section CORRECTNESS.
Smallstep.plus HTL.step tge R1 Events.E0 R2 /\ match_states (RTL.State s f sp pc' rs m) R2.
Proof.
intros s f sp pc rs m arg tbl n pc' H H0 H1 R1 MSTATE.
-
+
#[local] Hint Resolve transl_ijumptable_correct : htlproof.*)
Lemma transl_ireturn_correct:
@@ -2862,13 +2866,13 @@ Section CORRECTNESS.
Proof.
induction 1; eauto with htlproof; (intros; inv_state).
Qed.
- #[local] Hint Resolve transl_step_correct : htlproof.
+ #[local] Hint Resolve transl_step_correct : htlproof.*)
Theorem transf_program_correct:
Smallstep.forward_simulation (RTL.semantics prog) (HTL.semantics tprog).
Proof.
eapply Smallstep.forward_simulation_plus; eauto with htlproof.
apply senv_preserved.
- Qed.
+ (*Qed.*)Admitted.
End CORRECTNESS.
diff --git a/src/hls/HTLgenspec.v b/src/hls/HTLgenspec.v
index 8746ba2..165fa91 100644
--- a/src/hls/HTLgenspec.v
+++ b/src/hls/HTLgenspec.v
@@ -31,6 +31,7 @@ Require Import vericert.hls.ValueInt.
Require Import vericert.hls.HTL.
Require Import vericert.hls.HTLgen.
Require Import vericert.hls.AssocMap.
+Require Import vericert.hls.FunctionalUnits.
#[local] Hint Resolve Maps.PTree.elements_keys_norepet : htlspec.
#[local] Hint Resolve Maps.PTree.elements_correct : htlspec.
@@ -119,11 +120,15 @@ Ltac monadInv H :=
((progress simpl in H) || unfold F in H); monadInv1 H
end.
-(** * Relational specification of the translation *)
+(*|
+===========================================
+Relational specification of the translation
+===========================================
-(** We now define inductive predicates that characterise the fact that the
+We now define inductive predicates that characterise the fact that the
statemachine that is created by the translation contains the correct
-translations for each of the elements *)
+translations for each of the elements.
+|*)
Inductive tr_instr (fin rtrn st stk : reg) : RTL.instruction -> stmnt -> stmnt -> Prop :=
| tr_instr_Inop :
@@ -159,7 +164,7 @@ Inductive tr_instr (fin rtrn st stk : reg) : RTL.instruction -> stmnt -> stmnt -
translate_arr_access mem addr args stk s = OK c s' i ->
tr_instr fin rtrn st stk (RTL.Istore mem addr args src n) (Vnonblock c (Vvar src))
(state_goto st n).
-(*| tr_instr_Ijumptable :
+(* tr_instr_Ijumptable :
forall cexpr tbl r,
cexpr = tbl_to_case_expr st tbl ->
tr_instr fin rtrn st stk (RTL.Ijumptable r tbl) (Vskip) (Vcase (Vvar r) cexpr (Some Vskip)).*)
@@ -178,12 +183,13 @@ Inductive tr_code (c : RTL.code) (pc : RTL.node) (i : RTL.instruction) (stmnts t
Inductive tr_module (f : RTL.function) : module -> Prop :=
tr_module_intro :
- forall data control fin rtrn st stk stk_len m start rst clk scldecls arrdecls wf1 wf2 wf3 wf4,
+ forall data control fin rtrn st stk stk_len m start rst clk scldecls arrdecls r_en r_u_en r_addr r_wr_en r_d_in r_d_out,
m = (mkmodule f.(RTL.fn_params)
data
control
f.(RTL.fn_entrypoint)
- st stk stk_len fin rtrn start rst clk scldecls arrdecls None wf1 wf2 wf3 wf4) ->
+ st fin rtrn start rst clk scldecls arrdecls
+ (mk_ram stk_len stk r_en r_u_en r_addr r_wr_en r_d_in r_d_out)) ->
(forall pc i, Maps.PTree.get pc f.(RTL.fn_code) = Some i ->
tr_code f.(RTL.fn_code) pc i data control fin rtrn st stk) ->
stk_len = Z.to_nat (f.(RTL.fn_stacksize) / 4) ->
@@ -196,6 +202,12 @@ Inductive tr_module (f : RTL.function) : module -> Prop :=
start = ((RTL.max_reg_function f) + 5)%positive ->
rst = ((RTL.max_reg_function f) + 6)%positive ->
clk = ((RTL.max_reg_function f) + 7)%positive ->
+ r_en = ((RTL.max_reg_function f) + 8)%positive ->
+ r_u_en = ((RTL.max_reg_function f) + 9)%positive ->
+ r_addr = ((RTL.max_reg_function f) + 10)%positive ->
+ r_wr_en = ((RTL.max_reg_function f) + 11)%positive ->
+ r_d_in = ((RTL.max_reg_function f) + 12)%positive ->
+ r_d_out = ((RTL.max_reg_function f) + 13)%positive ->
tr_module f m.
#[local] Hint Constructors tr_module : htlspec.
@@ -644,7 +656,7 @@ Proof.
assert (EQ3D := EQ3).
apply collect_declare_datapath_trans in EQ3.
apply collect_declare_controllogic_trans in EQ3D.
- replace (st_controllogic s10) with (st_controllogic s3) by congruence.
+ (*replace (st_controllogic s10) with (st_controllogic s3) by congruence.
replace (st_datapath s10) with (st_datapath s3) by congruence.
replace (st_st s10) with (st_st s3) by congruence.
eapply iter_expand_instr_spec; eauto with htlspec.
@@ -654,3 +666,4 @@ Proof.
erewrite <- collect_declare_freshreg_trans; try eassumption.
lia.
Qed.
+*)Admitted.
diff --git a/src/hls/IfConversion.v b/src/hls/IfConversion.v
index b397d43..2516109 100644
--- a/src/hls/IfConversion.v
+++ b/src/hls/IfConversion.v
@@ -26,14 +26,17 @@ Require Import vericert.common.Vericertlib.
Require Import vericert.hls.RTLBlockInstr.
Require Import vericert.hls.RTLBlock.
Require Import vericert.hls.Predicate.
+Require Import vericert.bourdoncle.Bourdoncle.
+
+Parameter build_bourdoncle : function -> (bourdoncle * PMap.t N).
(*|
=============
-If conversion
+If-Conversion
=============
-This conversion is a verified conversion from RTLBlock back to itself, which performs if-conversion
-on basic blocks to make basic blocks larger.
+This conversion is a verified conversion from RTLBlock back to itself, which
+performs if-conversion on basic blocks to make basic blocks larger.
|*)
Definition combine_pred (p: pred_op) (optp: option pred_op) :=
@@ -96,11 +99,34 @@ Definition find_all_backedges (c: code) : list node :=
Definition has_backedge (entry: node) (be: list node) :=
any (fun x => Pos.eqb entry x) be.
-Definition find_blocks_with_cond (c: code) : list (node * bblock) :=
+Fixpoint get_loops (b: bourdoncle): list node :=
+ match b with
+ | L h b' => h::(fold_right (fun a b => get_loops a ++ b) nil b')
+ | I h => nil
+ end.
+
+Definition is_loop (b: list node) (n: node) :=
+ any (fun x => Pos.eqb x n) b.
+
+Definition is_flat_cfi (n: cf_instr) :=
+ match n with
+ | RBcond _ _ _ _ => false
+ | RBjumptable _ _ => false
+ | RBpred_cf _ _ _ => false
+ | _ => true
+ end.
+
+Definition is_flat (c: code) (succ: node) :=
+ match c ! succ with
+ | Some bblock => is_flat_cfi bblock.(bb_exit)
+ | None => false
+ end.
+
+Definition find_blocks_with_cond ep (b: list node) (c: code) : list (node * bblock) :=
let backedges := find_all_backedges c in
List.filter (fun x => is_cond_cfi (snd x).(bb_exit) &&
- negb (has_backedge (fst x) backedges) &&
- all (fun x' => negb (has_backedge x' backedges))
+ (negb (is_loop b (fst x)) || Pos.eqb (fst x) ep) &&
+ all (fun x' => is_flat c x')
(successors_instr (snd x).(bb_exit))
) (PTree.elements c).
@@ -109,8 +135,10 @@ Definition if_convert_code (p: nat * code) (nb: node * bblock) :=
(S (fst p), PTree.set (fst nb) nbb (snd p)).
Definition transf_function (f: function) : function :=
+ let (b, _) := build_bourdoncle f in
+ let b' := get_loops b in
let (_, c) := List.fold_left if_convert_code
- (find_blocks_with_cond f.(fn_code))
+ (find_blocks_with_cond f.(fn_entrypoint) b' f.(fn_code))
(1%nat, f.(fn_code)) in
mkfunction f.(fn_sig) f.(fn_params) f.(fn_stacksize) c f.(fn_entrypoint).
diff --git a/src/hls/Memorygen.v b/src/hls/Memorygen.v
index 96c11c3..e28bbc7 100644
--- a/src/hls/Memorygen.v
+++ b/src/hls/Memorygen.v
@@ -35,6 +35,7 @@ Require Import vericert.hls.Verilog.
Require Import vericert.hls.HTL.
Require Import vericert.hls.AssocMap.
Require Import vericert.hls.Array.
+Require Import vericert.hls.FunctionalUnits.
Local Open Scope positive.
Local Open Scope assocmap.
@@ -43,7 +44,7 @@ Local Open Scope assocmap.
#[local] Hint Resolve max_reg_stmnt_lt_stmnt_tree : mgen.
#[local] Hint Resolve max_stmnt_lt_module : mgen.
-Lemma int_eq_not_false : forall x, Int.eq x (Int.not x) = false.
+(*Lemma int_eq_not_false : forall x, Int.eq x (Int.not x) = false.
Proof.
intros. unfold Int.eq.
rewrite Int.unsigned_not.
@@ -459,8 +460,8 @@ Lemma forall_ram_lt :
forall_ram (fun x => x < max_reg_module m + 1) r.
Proof.
assert (X: forall a b c, a < b + 1 -> a < Pos.max c b + 1) by lia.
- unfold forall_ram; simplify; unfold max_reg_module; repeat apply X;
- unfold max_reg_ram; rewrite H; try lia.
+ unfold forall_ram; simplify; unfold HTL.max_reg_module; repeat apply X;
+ unfold HTL.max_reg_ram; rewrite H; try lia.
Qed.
#[local] Hint Resolve forall_ram_lt : mgen.
@@ -3201,3 +3202,4 @@ Section CORRECTNESS.
Qed.
End CORRECTNESS.
+*)
diff --git a/src/hls/Partition.ml b/src/hls/Partition.ml
index 19c6048..545277b 100644
--- a/src/hls/Partition.ml
+++ b/src/hls/Partition.ml
@@ -1,6 +1,6 @@
- (*
+(*
* Vericert: Verified high-level synthesis.
- * Copyright (C) 2020 Yann Herklotz <yann@yannherklotz.com>
+ * Copyright (C) 2020-2022 Yann Herklotz <yann@yannherklotz.com>
*
* 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
@@ -16,6 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*)
+(* [[file:../../docs/basic-block-generation.org::partition-main][partition-main]] *)
open Printf
open Clflags
open Camlcoq
@@ -28,7 +29,7 @@ open Op
open RTLBlockInstr
open RTLBlock
-(* Assuming that the nodes of the CFG [code] are numbered in reverse postorder (cf. pass
+(** Assuming that the nodes of the CFG [code] are numbered in reverse postorder (cf. pass
[Renumber]), an edge from [n] to [s] is a normal edge if [s < n] and a back-edge otherwise. *)
let find_edge i n =
let succ = RTL.successors_instr i in
@@ -65,14 +66,14 @@ let rec next_bblock_from_RTL is_start e (c : RTL.code) s i =
match trans_inst, succ with
| (None, Some i'), _ ->
if List.exists (fun x -> x = s) (snd e) && not is_start then
- Errors.OK { bb_body = []; bb_exit = RBgoto s }
+ Errors.OK { bb_body = [RBnop]; bb_exit = RBgoto s }
else
- Errors.OK { bb_body = []; bb_exit = i' }
+ Errors.OK { bb_body = [RBnop]; bb_exit = i' }
| (Some i', None), (s', Some i_n)::[] ->
if List.exists (fun x -> x = s) (fst e) then
Errors.OK { bb_body = [i']; bb_exit = RBgoto s' }
else if List.exists (fun x -> x = s) (snd e) && not is_start then
- Errors.OK { bb_body = []; bb_exit = RBgoto s }
+ Errors.OK { bb_body = [RBnop]; bb_exit = RBgoto s }
else begin
match next_bblock_from_RTL false e c s' i_n with
| Errors.OK bb ->
@@ -122,3 +123,4 @@ let function_from_RTL f =
}
let partition = function_from_RTL
+(* partition-main ends here *)
diff --git a/src/hls/Pipeline.v b/src/hls/Pipeline.v
index 7f1485a..67ab1f5 100644
--- a/src/hls/Pipeline.v
+++ b/src/hls/Pipeline.v
@@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*)
-Require Import compcert.lib.Maps.
+(*Require Import compcert.lib.Maps.
Require Import compcert.common.AST.
Require Import compcert.backend.RTL.
@@ -26,3 +26,4 @@ Definition transf_fundef := transf_fundef pipeline.
Definition transf_program : program -> program :=
transform_program transf_fundef.
+*)
diff --git a/src/hls/PipelineOp.v b/src/hls/PipelineOp.v
new file mode 100644
index 0000000..bb01ff9
--- /dev/null
+++ b/src/hls/PipelineOp.v
@@ -0,0 +1,193 @@
+(*
+ * Vericert: Verified high-level synthesis.
+ * Copyright (C) 2021 Yann Herklotz <yann@yannherklotz.com>
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ *)
+
+Require Import Coq.Lists.List.
+
+Require Import compcert.backend.Registers.
+Require Import compcert.common.AST.
+Require Import compcert.common.Errors.
+Require Import compcert.common.Globalenvs.
+Require Import compcert.lib.Integers.
+Require Import compcert.lib.Maps.
+Require Import compcert.verilog.Op.
+
+
+Require Import vericert.common.Vericertlib.
+Require Import vericert.hls.RTLBlockInstr.
+Require Import vericert.hls.RTLPar.
+Require Import vericert.hls.FunctionalUnits.
+
+Import Option.Notation.
+
+Local Open Scope positive.
+
+Definition div_pos (il: nat * list nat) x :=
+ let (i, l) := il in
+ match x with
+ | RBop _ Odiv _ _ => (S i, i :: l)
+ | RBop _ Odivu _ _ => (S i, i :: l)
+ | RBop _ Omod _ _ => (S i, i :: l)
+ | RBop _ Omodu _ _ => (S i, i :: l)
+ | _ => (S i, l)
+ end.
+
+Definition div_pos_in_list (il: nat * list (nat * nat)) bb :=
+ let (i, l) := il in
+ let dp := snd (List.fold_left div_pos bb (0%nat, nil)) in
+ (S i, (List.map (fun x => (i, x)) dp) ++ l).
+
+Definition div_pos_in_block (il: nat * list (nat * nat * nat)) bb :=
+ let (i, l) := il in
+ let dp := snd (List.fold_left div_pos_in_list bb (0%nat, nil)) in
+ (S i, (List.map (fun (yx : nat * nat) => let (y, x) := yx in (i, y, x)) dp) ++ l).
+
+Definition find_divs (bb: bblock) :=
+ snd (List.fold_left div_pos_in_block bb.(bb_body) (0%nat, nil)).
+
+Fixpoint mapi' {A B: Type} (n: nat) (f: nat -> A -> B) (l: list A): list B :=
+ match l with
+ | nil => nil
+ | a :: b => f n a :: mapi' (S n) f b
+ end.
+
+Definition mapi {A B: Type} := @mapi' A B 0.
+
+Definition map_at {A: Type} (n: nat) (f: A -> A) (l: list A): list A :=
+ mapi (fun i il =>
+ if Nat.eqb n i
+ then f il
+ else il
+ ) l.
+
+Definition map_at_err {A: Type} (n: nat) (f: A -> A) (l: list A): option (list A) :=
+ if (Datatypes.length l <=? n)%nat
+ then None
+ else Some (map_at n f l).
+
+(*Definition replace_div' sdiv udiv (d: instr) :=
+ match d with
+ | RBop op Odiv args dst => RBpiped op sdiv args
+ | RBop op Odivu args dst => RBpiped op udiv args
+ | RBop op Omod args dst => RBpiped op sdiv args
+ | RBop op Omodu args dst => RBpiped op udiv args
+ | _ => d
+ end.
+
+Definition get_sdiv (fu: funct_unit) : option (reg * reg * reg) :=
+ match fu with
+ | SignedDiv s a b d _ => Some (a, b, d)
+ | _ => None
+ end.
+
+Definition get_udiv (fu: funct_unit) : option (reg * reg * reg) :=
+ match fu with
+ | UnsignedDiv s a b d _ => Some (a, b, d)
+ | _ => None
+ end.
+
+Definition get_smod (fu: funct_unit) : option (reg * reg * reg) :=
+ match fu with
+ | SignedDiv s a b _ d => Some (a, b, d)
+ | _ => None
+ end.
+
+Definition get_umod (fu: funct_unit) : option (reg * reg * reg) :=
+ match fu with
+ | UnsignedDiv s a b _ d => Some (a, b, d)
+ | _ => None
+ end.
+
+Definition bind3 {A B C D: Type}
+ (f: option (A * B * C))
+ (g: A -> B -> C -> option D) : option D :=
+ match f with
+ | Some (a, b, c) => g a b c
+ | None => None
+ end.
+
+Notation "'do' ( X , Y , Z ) <- A ; B" := (bind3 A (fun X Y Z => B))
+ (at level 200, X ident, Y ident, Z ident, A at level 100, B at level 200).
+
+Definition replace_div_error (fu: funct_units) (bb: bb) (loc: nat * nat * nat) :=
+ match loc with
+ | (z, y, x) =>
+ do sdiv <- fu.(avail_sdiv);
+ do udiv <- fu.(avail_udiv);
+ do sfu <- PTree.get sdiv fu.(avail_units);
+ do ufu <- PTree.get udiv fu.(avail_units);
+ do z' <- List.nth_error bb z;
+ do y' <- List.nth_error z' y;
+ do x' <- List.nth_error y' x;
+ let transf := map_at z (map_at y (map_at x (replace_div' sdiv udiv))) bb in
+ match x' with
+ | RBop op Odiv args dst =>
+ do (s1, s2, src) <- get_sdiv sfu;
+ map_at_err (z + 32)%nat (fun x => (RBassign op sdiv src dst :: nil) :: x) transf
+ | RBop op Odivu args dst =>
+ do (s1, s2, src) <- get_udiv ufu;
+ map_at_err (z + 32)%nat (fun x => (RBassign op sdiv src dst :: nil) :: x) transf
+ | RBop op Omod args dst =>
+ do (s1, s2, src) <- get_smod sfu;
+ map_at_err (z + 32)%nat (fun x => (RBassign op sdiv src dst :: nil) :: x) transf
+ | RBop op Omodu args dst =>
+ do (s1, s2, src) <- get_umod ufu;
+ map_at_err (z + 32)%nat (fun x => (RBassign op sdiv src dst :: nil) :: x) transf
+ | _ => None
+ end
+ end.
+
+Definition replace_div (fu: funct_units) (bb: bb) loc :=
+ match replace_div_error fu bb loc with
+ | Some bb' => bb'
+ | _ => bb
+ end.
+
+Definition transf_code (i: code * funct_units) (bbn: node * bblock) :=
+ let (c, fu) := i in
+ let (n, bb) := bbn in
+ let divs := find_divs bb in
+ match divs with
+ | nil => (PTree.set n bb c, fu)
+ | _ =>
+ (PTree.set n (mk_bblock (List.fold_left (replace_div fu) divs bb.(bb_body)) bb.(bb_exit)) c, fu)
+ end.
+
+Definition create_fu (r: reg) :=
+ let fu := PTree.set 2 (UnsignedDiv 32 (r+5) (r+6) (r+7) (r+8))
+ (PTree.set 1 (SignedDiv 32 (r+1) (r+2) (r+3) (r+4)) (PTree.empty _)) in
+ mk_avail_funct_units (Some 1) (Some 2) fu.
+
+Definition transf_function (f: function) : function :=
+ let fu := create_fu (max_reg_function f) in
+ let (c, fu') := List.fold_left transf_code
+ (PTree.elements f.(fn_code))
+ (PTree.empty bblock, fu) in
+ mkfunction
+ f.(fn_sig)
+ f.(fn_params)
+ f.(fn_stacksize)
+ c
+ fu'
+ f.(fn_entrypoint).
+
+Definition transf_fundef (fd: fundef) : fundef :=
+ transf_fundef transf_function fd.
+
+Definition transf_program (p: program) : program :=
+ transform_program transf_fundef p.
+*)
diff --git a/src/hls/Predicate.v b/src/hls/Predicate.v
index a2b5400..b19ae98 100644
--- a/src/hls/Predicate.v
+++ b/src/hls/Predicate.v
@@ -24,6 +24,8 @@ Notation "A ∨ B" := (Por A B) (at level 25) : pred_op.
Notation "⟂" := (Pfalse) : pred_op.
Notation "'T'" := (Ptrue) : pred_op.
+#[local] Open Scope pred_op.
+
Fixpoint sat_predicate (p: pred_op) (a: asgn) : bool :=
match p with
| Plit (b, p') => if b then a (Pos.to_nat p') else negb (a (Pos.to_nat p'))
@@ -33,6 +35,234 @@ Fixpoint sat_predicate (p: pred_op) (a: asgn) : bool :=
| Por p1 p2 => sat_predicate p1 a || sat_predicate p2 a
end.
+Definition sat_equiv p1 p2 := forall c, sat_predicate p1 c = sat_predicate p2 c.
+
+Lemma equiv_symm : forall a b, sat_equiv a b -> sat_equiv b a.
+Proof. crush. Qed.
+
+Lemma equiv_trans : forall a b c, sat_equiv a b -> sat_equiv b c -> sat_equiv a c.
+Proof. crush. Qed.
+
+Lemma equiv_refl : forall a, sat_equiv a a.
+Proof. crush. Qed.
+
+#[global]
+Instance Equivalence_SAT : Equivalence sat_equiv :=
+ { Equivalence_Reflexive := equiv_refl ;
+ Equivalence_Symmetric := equiv_symm ;
+ Equivalence_Transitive := equiv_trans ;
+ }.
+
+#[global]
+Instance SATSetoid : Setoid pred_op :=
+ { equiv := sat_equiv; }.
+
+#[global]
+Instance PandProper : Proper (equiv ==> equiv ==> equiv) Pand.
+Proof.
+ unfold Proper. simplify. unfold "==>".
+ intros.
+ unfold sat_equiv in *. intros.
+ simplify. rewrite H0. rewrite H.
+ auto.
+Qed.
+
+#[global]
+Instance PorProper : Proper (equiv ==> equiv ==> equiv) Por.
+Proof.
+ unfold Proper, "==>". simplify.
+ intros.
+ unfold sat_equiv in *. intros.
+ simplify. rewrite H0. rewrite H.
+ auto.
+Qed.
+
+#[global]
+Instance sat_predicate_Proper : Proper (equiv ==> eq ==> eq) sat_predicate.
+Proof.
+ unfold Proper, "==>". simplify.
+ intros.
+ unfold sat_equiv in *. subst.
+ apply H.
+Qed.
+
+Fixpoint negate (p: pred_op) :=
+ match p with
+ | Plit (b, pr) => Plit (negb b, pr)
+ | T => ⟂
+ | ⟂ => T
+ | A ∧ B => negate A ∨ negate B
+ | A ∨ B => negate A ∧ negate B
+ end.
+
+Notation "¬ A" := (negate A) (at level 15) : pred_op.
+
+Lemma negate_correct :
+ forall h a, sat_predicate (negate h) a = negb (sat_predicate h a).
+Proof.
+ induction h; crush.
+ - repeat destruct_match; subst; crush; symmetry; apply negb_involutive.
+ - rewrite negb_andb; crush.
+ - rewrite negb_orb; crush.
+Qed.
+
+Definition unsat p := forall a, sat_predicate p a = false.
+Definition sat p := exists a, sat_predicate p a = true.
+
+Lemma unsat_correct1 :
+ forall a b c,
+ unsat (Pand a b) ->
+ sat_predicate a c = true ->
+ sat_predicate b c = false.
+Proof.
+ unfold unsat in *. intros.
+ simplify. specialize (H c).
+ apply andb_false_iff in H. inv H. rewrite H0 in H1. discriminate.
+ auto.
+Qed.
+
+Lemma unsat_correct2 :
+ forall a b c,
+ unsat (Pand a b) ->
+ sat_predicate b c = true ->
+ sat_predicate a c = false.
+Proof.
+ unfold unsat in *. intros.
+ simplify. specialize (H c).
+ apply andb_false_iff in H. inv H. auto. rewrite H0 in H1. discriminate.
+Qed.
+
+Lemma unsat_not a: unsat (a ∧ (¬ a)).
+Proof.
+ unfold unsat; simplify.
+ rewrite negate_correct.
+ auto with bool.
+Qed.
+
+Lemma unsat_commut a b: unsat (a ∧ b) -> unsat (b ∧ a).
+Proof. unfold unsat; simplify; eauto with bool. Qed.
+
+Lemma sat_imp_equiv :
+ forall a b,
+ unsat (a ∧ ¬ b ∨ ¬ a ∧ b) -> a == b.
+Proof.
+ simplify; unfold unsat, sat_equiv.
+ intros. specialize (H c); simplify.
+ rewrite negate_correct in *.
+ destruct (sat_predicate b c) eqn:X;
+ destruct (sat_predicate a c) eqn:X2;
+ crush.
+Qed.
+
+Lemma sat_predicate_and :
+ forall a b c,
+ sat_predicate (a ∧ b) c = sat_predicate a c && sat_predicate b c.
+Proof. crush. Qed.
+
+Lemma sat_predicate_or :
+ forall a b c,
+ sat_predicate (a ∨ b) c = sat_predicate a c || sat_predicate b c.
+Proof. crush. Qed.
+
+Lemma sat_equiv2 :
+ forall a b,
+ a == b -> unsat (a ∧ ¬ b ∨ ¬ a ∧ b).
+Proof.
+ unfold unsat, equiv; simplify.
+ repeat rewrite negate_correct.
+ repeat rewrite H.
+ rewrite andb_negb_r.
+ rewrite andb_negb_l. auto.
+Qed.
+
+Lemma sat_equiv3 :
+ forall a b,
+ unsat (a ∧ ¬ b ∨ b ∧ ¬ a) -> a == b.
+Proof.
+ simplify. unfold unsat, sat_equiv in *; intros.
+ specialize (H c); simplify.
+ rewrite negate_correct in *.
+ destruct (sat_predicate b c) eqn:X;
+ destruct (sat_predicate a c) eqn:X2;
+ crush.
+Qed.
+
+Lemma sat_equiv4 :
+ forall a b,
+ a == b -> unsat (a ∧ ¬ b ∨ b ∧ ¬ a).
+Proof.
+ unfold unsat, equiv; simplify.
+ repeat rewrite negate_correct.
+ repeat rewrite H.
+ rewrite andb_negb_r. auto.
+Qed.
+
+Definition simplify' (p: pred_op) :=
+ match p with
+ | (Plit (b1, a)) ∧ (Plit (b2, b)) as p' =>
+ if Pos.eqb a b then
+ if negb (xorb b1 b2) then Plit (b1, a) else ⟂
+ else p'
+ | (Plit (b1, a)) ∨ (Plit (b2, b)) as p' =>
+ if Pos.eqb a b then
+ if negb (xorb b1 b2) then Plit (b1, a) else T
+ else p'
+ | A ∧ T => A
+ | T ∧ A => A
+ | _ ∧ ⟂ => ⟂
+ | ⟂ ∧ _ => ⟂
+ | _ ∨ T => T
+ | T ∨ _ => T
+ | A ∨ ⟂ => A
+ | ⟂ ∨ A => A
+ | A => A
+ end.
+
+Lemma pred_op_dec :
+ forall p1 p2: pred_op,
+ { p1 = p2 } + { p1 <> p2 }.
+Proof. pose proof Pos.eq_dec. repeat decide equality. Qed.
+
+Fixpoint simplify (p: pred_op) :=
+ match p with
+ | A ∧ B =>
+ let A' := simplify A in
+ let B' := simplify B in
+ simplify' (A' ∧ B')
+ | A ∨ B =>
+ let A' := simplify A in
+ let B' := simplify B in
+ simplify' (A' ∨ B')
+ | T => T
+ | ⟂ => ⟂
+ | Plit a => Plit a
+ end.
+
+Lemma simplify'_correct :
+ forall h a,
+ sat_predicate (simplify' h) a = sat_predicate h a.
+Proof.
+ (*destruct h; crush; repeat destruct_match; crush;
+ solve [rewrite andb_true_r; auto | rewrite orb_false_r; auto].
+Qed.*) Admitted.
+
+Lemma simplify_correct :
+ forall h a,
+ sat_predicate (simplify h) a = sat_predicate h a.
+Proof.
+ Local Opaque simplify'.
+ induction h; crush.
+ - replace (sat_predicate h1 a && sat_predicate h2 a)
+ with (sat_predicate (simplify h1) a && sat_predicate (simplify h2) a)
+ by crush.
+ rewrite simplify'_correct. crush.
+ - replace (sat_predicate h1 a || sat_predicate h2 a)
+ with (sat_predicate (simplify h1) a || sat_predicate (simplify h2) a)
+ by crush.
+ rewrite simplify'_correct. crush.
+ Local Transparent simplify'.
+Qed.
+
Fixpoint mult {A: Type} (a b: list (list A)) : list (list A) :=
match a with
| nil => nil
@@ -162,11 +392,143 @@ Fixpoint trans_pred (p: pred_op) :
apply i0 in H0. auto.
Defined.
-Definition sat_pred (p: pred_op) :
+Definition bar (p1: lit): lit := (negb (fst p1), (snd p1)).
+
+Definition stseytin_or (cur p1 p2: lit) : formula :=
+ (bar cur :: p1 :: p2 :: nil)
+ :: (cur :: bar p1 :: nil)
+ :: (cur :: bar p2 :: nil) :: nil.
+
+Definition stseytin_and (cur p1 p2: lit) : formula :=
+ (cur :: bar p1 :: bar p2 :: nil)
+ :: (bar cur :: p1 :: nil)
+ :: (bar cur :: p2 :: nil) :: nil.
+
+Fixpoint xtseytin (next: nat) (p: pred_op) {struct p} : (nat * lit * formula) :=
+ match p with
+ | Plit (b, p') => (next, (b, Pos.to_nat p'), nil)
+ | Ptrue =>
+ ((next+1)%nat, (true, next), ((true, next)::nil)::nil)
+ | Pfalse =>
+ ((next+1)%nat, (true, next), ((false, next)::nil)::nil)
+ | Por p1 p2 =>
+ let '(m1, n1, f1) := xtseytin next p1 in
+ let '(m2, n2, f2) := xtseytin m1 p2 in
+ ((m2+1)%nat, (true, m2), stseytin_or (true, m2) n1 n2 ++ f1 ++ f2)
+ | Pand p1 p2 =>
+ let '(m1, n1, f1) := xtseytin next p1 in
+ let '(m2, n2, f2) := xtseytin m1 p2 in
+ ((m2+1)%nat, (true, m2), stseytin_and (true, m2) n1 n2 ++ f1 ++ f2)
+ end.
+
+Lemma stseytin_and_correct :
+ forall cur p1 p2 fm c,
+ stseytin_and cur p1 p2 = fm ->
+ satLit cur c ->
+ satLit p1 c /\ satLit p2 c ->
+ satFormula fm c.
+Proof.
+ intros.
+ unfold stseytin_and in *. rewrite <- H.
+ unfold satLit in *. destruct p1. destruct p2. destruct cur.
+ simpl in *|-. cbn. unfold satLit. cbn. crush.
+Qed.
+
+Lemma stseytin_and_correct2 :
+ forall cur p1 p2 fm c,
+ stseytin_and cur p1 p2 = fm ->
+ satFormula fm c ->
+ satLit cur c <-> satLit p1 c /\ satLit p2 c.
+Proof.
+ intros. split. intros. inv H1. unfold stseytin_and in *.
+ inv H0; try contradiction. Admitted.
+
+Lemma stseytin_or_correct :
+ forall cur p1 p2 fm c,
+ stseytin_or cur p1 p2 = fm ->
+ satLit cur c ->
+ satLit p1 c \/ satLit p2 c ->
+ satFormula fm c.
+Proof.
+ intros.
+ unfold stseytin_or in *. rewrite <- H. inv H1.
+ unfold satLit in *. destruct p1. destruct p2. destruct cur.
+ simpl in *|-. cbn. unfold satLit. cbn. crush.
+ unfold satLit in *. destruct p1. destruct p2. destruct cur.
+ simpl in *|-. cbn. unfold satLit. cbn. crush.
+Qed.
+
+Lemma stseytin_or_correct2 :
+ forall cur p1 p2 fm c,
+ stseytin_or cur p1 p2 = fm ->
+ satFormula fm c ->
+ satLit cur c <-> satLit p1 c \/ satLit p2 c.
+Proof. Admitted.
+
+Lemma xtseytin_correct :
+ forall p next l n fm c,
+ xtseytin next p = (n, l, fm) ->
+ sat_predicate p c = true <-> satFormula ((l::nil)::fm) c.
+Proof.
+ induction p.
+ - intros. simplify. destruct p.
+ inv H. split.
+ intros. destruct b. split; crush.
+ apply negb_true_iff in H.
+ split; crush.
+ intros. inv H. inv H0; try contradiction.
+ inv H. simplify. rewrite <- H0.
+ destruct b.
+ rewrite -> H0; auto.
+ rewrite -> H0; auto.
+ - admit.
+ - admit.
+ - intros. split. intros. simpl in H0.
+ apply andb_prop in H0. inv H0.
+ cbn in H.
+ repeat destruct_match; try discriminate; []. inv H. eapply IHp1 in Heqp.
+ eapply IHp2 in Heqp1. apply Heqp1 in H2.
+ apply Heqp in H1. inv H1. inv H2.
+ assert
+ (satFormula
+ (((true, n1) :: bar l0 :: bar l1 :: nil)
+ :: (bar (true, n1) :: l0 :: nil)
+ :: (bar (true, n1) :: l1 :: nil) :: nil) c).
+ eapply stseytin_and_correct. unfold stseytin_and. eauto.
+ unfold satLit. simpl. admit.
+ inv H; try contradiction. inv H1; try contradiction. eauto.
+Admitted.
+
+Fixpoint max_predicate (p: pred_op) : positive :=
+ match p with
+ | Plit (b, p) => p
+ | Ptrue => 1
+ | Pfalse => 1
+ | Pand a b => Pos.max (max_predicate a) (max_predicate b)
+ | Por a b => Pos.max (max_predicate a) (max_predicate b)
+ end.
+
+Definition tseytin (p: pred_op) :
+ {fm: formula | forall a,
+ sat_predicate p a = true <-> satFormula fm a}.
+ refine (
+ (match xtseytin (Pos.to_nat (max_predicate p + 1)) p as X
+ return xtseytin (Pos.to_nat (max_predicate p + 1)) p = X ->
+ {fm: formula | forall a, sat_predicate p a = true <-> satFormula fm a}
+ with (m, n, fm) => fun H => exist _ ((n::nil) :: fm) _
+ end) (eq_refl (xtseytin (Pos.to_nat (max_predicate p + 1)) p))).
+ intros. eapply xtseytin_correct; eauto. Defined.
+
+Definition tseytin_simple (p: pred_op) : formula :=
+ let m := Pos.to_nat (max_predicate p + 1) in
+ let '(m, n, fm) := xtseytin m p in
+ (n::nil) :: fm.
+
+Definition sat_pred_tseytin (p: pred_op) :
({al : alist | sat_predicate p (interp_alist al) = true}
+ {forall a : asgn, sat_predicate p a = false}).
refine
- ( match trans_pred p with
+ ( match tseytin p with
| exist _ fm _ =>
match satSolve fm with
| inleft (exist _ a _) => inleft (exist _ a _)
@@ -179,69 +541,33 @@ Definition sat_pred (p: pred_op) :
apply n. apply i. auto. auto.
Defined.
-Definition sat_pred_simple (p: pred_op) :=
- match sat_pred p with
- | inleft (exist _ al _) => Some al
+Definition sat_pred_simple (p: pred_op) : option alist :=
+ match sat_pred_tseytin p with
+ | inleft (exist _ a _) => Some a
| inright _ => None
end.
-#[local] Open Scope pred_op.
-
-Fixpoint negate (p: pred_op) :=
- match p with
- | Plit (b, pr) => Plit (negb b, pr)
- | T => ⟂
- | ⟂ => T
- | A ∧ B => negate A ∨ negate B
- | A ∨ B => negate A ∧ negate B
- end.
-
-Notation "¬ A" := (negate A) (at level 15) : pred_op.
-
-Lemma negate_correct :
- forall h a, sat_predicate (negate h) a = negb (sat_predicate h a).
-Proof.
- induction h; crush.
- - repeat destruct_match; subst; crush; symmetry; apply negb_involutive.
- - rewrite negb_andb; crush.
- - rewrite negb_orb; crush.
-Qed.
-
-Definition unsat p := forall a, sat_predicate p a = false.
-Definition sat p := exists a, sat_predicate p a = true.
-
-Lemma unsat_correct1 :
- forall a b c,
- unsat (Pand a b) ->
- sat_predicate a c = true ->
- sat_predicate b c = false.
-Proof.
- unfold unsat in *. intros.
- simplify. specialize (H c).
- apply andb_false_iff in H. inv H. rewrite H0 in H1. discriminate.
- auto.
-Qed.
-
-Lemma unsat_correct2 :
- forall a b c,
- unsat (Pand a b) ->
- sat_predicate b c = true ->
- sat_predicate a c = false.
-Proof.
- unfold unsat in *. intros.
- simplify. specialize (H c).
- apply andb_false_iff in H. inv H. auto. rewrite H0 in H1. discriminate.
-Qed.
+Definition sat_pred (p: pred_op) :
+ ({al : alist | sat_predicate p (interp_alist al) = true}
+ + {forall a : asgn, sat_predicate p a = false}).
+ refine
+ ( match trans_pred p with
+ | exist _ fm _ =>
+ match satSolve fm with
+ | inleft (exist _ a _) => inleft (exist _ a _)
+ | inright _ => inright _
+ end
+ end ).
+ - apply i in s0. auto.
+ - intros. specialize (n a). specialize (i a).
+ destruct (sat_predicate p a). exfalso.
+ apply n. apply i. auto. auto.
+Defined.
-Lemma unsat_not a: unsat (a ∧ (¬ a)).
-Proof.
- unfold unsat; simplify.
- rewrite negate_correct.
- auto with bool.
-Qed.
+#[local] Open Scope positive.
-Lemma unsat_commut a b: unsat (a ∧ b) -> unsat (b ∧ a).
-Proof. unfold unsat; simplify; eauto with bool. Qed.
+Compute tseytin_simple (Por (negate (Pand (Por (Plit (true, 1)) (Plit (true, 2))) (Plit (true, 3)))) (Plit (false, 4))).
+Compute sat_pred_simple (Por Pfalse (Pand (Plit (true, 1)) (Plit (false, 1)))).
Lemma sat_dec a: {sat a} + {unsat a}.
Proof.
@@ -252,118 +578,14 @@ Proof.
intros. tauto.
Qed.
-Definition sat_equiv p1 p2 := forall c, sat_predicate p1 c = sat_predicate p2 c.
-
-Lemma equiv_symm : forall a b, sat_equiv a b -> sat_equiv b a.
-Proof. crush. Qed.
-
-Lemma equiv_trans : forall a b c, sat_equiv a b -> sat_equiv b c -> sat_equiv a c.
-Proof. crush. Qed.
-
-Lemma equiv_refl : forall a, sat_equiv a a.
-Proof. crush. Qed.
-
-#[global]
-Instance Equivalence_SAT : Equivalence sat_equiv :=
- { Equivalence_Reflexive := equiv_refl ;
- Equivalence_Symmetric := equiv_symm ;
- Equivalence_Transitive := equiv_trans ;
- }.
-
-#[global]
-Instance SATSetoid : Setoid pred_op :=
- { equiv := sat_equiv; }.
-
-#[global]
-Instance PandProper : Proper (equiv ==> equiv ==> equiv) Pand.
-Proof.
- unfold Proper. simplify. unfold "==>".
- intros.
- unfold sat_equiv in *. intros.
- simplify. rewrite H0. rewrite H.
- auto.
-Qed.
-
-#[global]
-Instance PorProper : Proper (equiv ==> equiv ==> equiv) Por.
-Proof.
- unfold Proper, "==>". simplify.
- intros.
- unfold sat_equiv in *. intros.
- simplify. rewrite H0. rewrite H.
- auto.
-Qed.
-
-#[global]
-Instance sat_predicate_Proper : Proper (equiv ==> eq ==> eq) sat_predicate.
-Proof.
- unfold Proper, "==>". simplify.
- intros.
- unfold sat_equiv in *. subst.
- apply H.
-Qed.
-
-Lemma sat_imp_equiv :
- forall a b,
- unsat (a ∧ ¬ b ∨ ¬ a ∧ b) -> a == b.
-Proof.
- simplify; unfold unsat, sat_equiv.
- intros. specialize (H c); simplify.
- rewrite negate_correct in *.
- destruct (sat_predicate b c) eqn:X;
- destruct (sat_predicate a c) eqn:X2;
- crush.
-Qed.
-
-Lemma sat_predicate_and :
- forall a b c,
- sat_predicate (a ∧ b) c = sat_predicate a c && sat_predicate b c.
-Proof. crush. Qed.
-
-Lemma sat_predicate_or :
- forall a b c,
- sat_predicate (a ∨ b) c = sat_predicate a c || sat_predicate b c.
-Proof. crush. Qed.
-
-Lemma sat_equiv2 :
- forall a b,
- a == b -> unsat (a ∧ ¬ b ∨ ¬ a ∧ b).
-Proof.
- unfold unsat, equiv; simplify.
- repeat rewrite negate_correct.
- repeat rewrite H.
- rewrite andb_negb_r.
- rewrite andb_negb_l. auto.
-Qed.
-
-Lemma sat_equiv3 :
- forall a b,
- unsat (a ∧ ¬ b ∨ b ∧ ¬ a) -> a == b.
-Proof.
- simplify. unfold unsat, sat_equiv in *; intros.
- specialize (H c); simplify.
- rewrite negate_correct in *.
- destruct (sat_predicate b c) eqn:X;
- destruct (sat_predicate a c) eqn:X2;
- crush.
-Qed.
-
-Lemma sat_equiv4 :
- forall a b,
- a == b -> unsat (a ∧ ¬ b ∨ b ∧ ¬ a).
-Proof.
- unfold unsat, equiv; simplify.
- repeat rewrite negate_correct.
- repeat rewrite H.
- rewrite andb_negb_r. auto.
-Qed.
-
Definition equiv_check p1 p2 :=
- match sat_pred_simple (p1 ∧ ¬ p2 ∨ p2 ∧ ¬ p1) with
+ match sat_pred_simple (simplify (p1 ∧ ¬ p2 ∨ p2 ∧ ¬ p1)) with
| None => true
| _ => false
end.
+Compute equiv_check Pfalse (Pand (Plit (true, 1%positive)) (Plit (false, 1%positive))).
+
Lemma equiv_check_correct :
forall p1 p2, equiv_check p1 p2 = true -> p1 == p2.
Proof.
@@ -371,16 +593,24 @@ Proof.
destruct_match; try discriminate; [].
destruct_match. destruct_match. discriminate.
eapply sat_equiv3; eauto.
+ unfold unsat; intros.
+ rewrite <- simplify_correct. eauto.
Qed.
+Opaque simplify.
+Opaque simplify'.
+
Lemma equiv_check_correct2 :
forall p1 p2, p1 == p2 -> equiv_check p1 p2 = true.
Proof.
unfold equiv_check, equiv, sat_pred_simple. intros.
- destruct_match; auto. destruct_match; try discriminate. destruct_match.
+ destruct_match; auto. destruct_match; try discriminate.
+ destruct_match.
simplify.
apply sat_equiv4 in H. unfold unsat in H. simplify.
- clear Heqs. rewrite H in e. discriminate.
+ clear Heqs. rewrite simplify_correct in e.
+ specialize (H (interp_alist a)). simplify.
+ rewrite H1 in e. rewrite H0 in e. discriminate.
Qed.
Lemma equiv_check_dec :
@@ -444,60 +674,10 @@ Proof.
auto.
Qed.
-Definition simplify' (p: pred_op) :=
- match p with
- | A ∧ T => A
- | T ∧ A => A
- | _ ∧ ⟂ => ⟂
- | ⟂ ∧ _ => ⟂
- | _ ∨ T => T
- | T ∨ _ => T
- | A ∨ ⟂ => A
- | ⟂ ∨ A => A
- | A => A
- end.
-
-Lemma pred_op_dec :
- forall p1 p2: pred_op,
- { p1 = p2 } + { p1 <> p2 }.
-Proof. pose proof Pos.eq_dec. repeat decide equality. Qed.
-
-Fixpoint simplify (p: pred_op) :=
- match p with
- | A ∧ B =>
- let A' := simplify A in
- let B' := simplify B in
- simplify' (A' ∧ B')
- | A ∨ B =>
- let A' := simplify A in
- let B' := simplify B in
- simplify' (A' ∨ B')
- | T => T
- | ⟂ => ⟂
- | Plit a => Plit a
- end.
-
-Lemma simplify'_correct :
- forall h a,
- sat_predicate (simplify' h) a = sat_predicate h a.
-Proof.
- destruct h; crush; repeat destruct_match; crush;
- solve [rewrite andb_true_r; auto | rewrite orb_false_r; auto].
-Qed.
-
-Lemma simplify_correct :
- forall h a,
- sat_predicate (simplify h) a = sat_predicate h a.
+#[global]
+Instance simplifyProper : Proper (equiv ==> equiv) simplify.
Proof.
- Local Opaque simplify'.
- induction h; crush.
- - replace (sat_predicate h1 a && sat_predicate h2 a)
- with (sat_predicate (simplify h1) a && sat_predicate (simplify h2) a)
- by crush.
- rewrite simplify'_correct. crush.
- - replace (sat_predicate h1 a || sat_predicate h2 a)
- with (sat_predicate (simplify h1) a || sat_predicate (simplify h2) a)
- by crush.
- rewrite simplify'_correct. crush.
- Local Transparent simplify'.
+ unfold Proper, "==>". simplify. unfold "→".
+ intros. unfold sat_equiv; intros.
+ rewrite ! simplify_correct; auto.
Qed.
diff --git a/src/hls/PrintAbstr.ml b/src/hls/PrintAbstr.ml
new file mode 100644
index 0000000..c63fa02
--- /dev/null
+++ b/src/hls/PrintAbstr.ml
@@ -0,0 +1,39 @@
+(**open Camlcoq
+open Datatypes
+open Maps
+open AST
+open Abstr
+open PrintAST
+open Printf
+
+let rec expr_to_list = function
+ | Enil -> []
+ | Econs (e, el) -> e :: expr_to_list el
+
+let res pp = function
+ | Reg r -> fprintf pp "r%d" (P.to_int r)
+ | Pred r -> fprintf pp "p%d" (P.to_int r)
+ | Mem -> fprintf pp "M"
+
+let rec print_expression pp = function
+ | Ebase r -> fprintf pp "%a'" res r
+ | Eop (op, el) -> fprintf pp "(%a)" (PrintOp.print_operation print_expression) (op, expr_to_list el)
+ | Eload (chunk, addr, el, e) ->
+ fprintf pp "(%s[%a][%a])"
+ (name_of_chunk chunk) print_expression e
+ (PrintOp.print_addressing print_expression) (addr, expr_to_list el)
+ | Estore (e, chunk, addr, el, m) ->
+ fprintf pp "(%s[%a][%a] = %a)"
+ (name_of_chunk chunk) print_expression m
+ (PrintOp.print_addressing print_expression) (addr, expr_to_list el)
+ print_expression e
+ | Esetpred (c, el) ->
+ fprintf pp "(%a)" (PrintOp.print_condition print_expression) (c, expr_to_list el)
+
+let rec print_predicated pp = function
+ | NE.Coq_singleton (p, e) ->
+ fprintf pp "%a %a" PrintRTLBlockInstr.print_pred_option p print_expression e
+ | NE.Coq_cons ((p, e), pr) ->
+ fprintf pp "%a %a\n%a" PrintRTLBlockInstr.print_pred_option p print_expression e
+ print_predicated pr
+*)
diff --git a/src/hls/PrintRTLBlockInstr.ml b/src/hls/PrintRTLBlockInstr.ml
index 8e24575..b8e1e2e 100644
--- a/src/hls/PrintRTLBlockInstr.ml
+++ b/src/hls/PrintRTLBlockInstr.ml
@@ -23,9 +23,9 @@ let ros pp = function
| Coq_inr s -> fprintf pp "\"%s\"" (extern_atom s)
let rec print_pred_op pp = function
- | Plit p -> if fst p then pred pp (snd p) else fprintf pp "~ %a" pred (snd p)
- | Pand (p1, p2) -> fprintf pp "(%a & %a)" print_pred_op p1 print_pred_op p2
- | Por (p1, p2) -> fprintf pp "(%a | %a)" print_pred_op p1 print_pred_op p2
+ | Plit p -> if fst p then pred pp (snd p) else fprintf pp "~%a" pred (snd p)
+ | Pand (p1, p2) -> fprintf pp "(%a ∧ %a)" print_pred_op p1 print_pred_op p2
+ | Por (p1, p2) -> fprintf pp "(%a ∨ %a)" print_pred_op p1 print_pred_op p2
| Ptrue -> fprintf pp "T"
| Pfalse -> fprintf pp "⟂"
diff --git a/src/hls/PrintRTLParFU.ml b/src/hls/PrintRTLParFU.ml
new file mode 100644
index 0000000..ec4d851
--- /dev/null
+++ b/src/hls/PrintRTLParFU.ml
@@ -0,0 +1,120 @@
+(* *********************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* Xavier Leroy, INRIA Paris-Rocquencourt *)
+(* *)
+(* Copyright Institut National de Recherche en Informatique et en *)
+(* Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the INRIA Non-Commercial License Agreement. *)
+(* *)
+(* *********************************************************************)
+
+(** Pretty-printers for RTL code *)
+
+open Printf
+open Camlcoq
+open Datatypes
+open Maps
+open AST
+open PrintRTLBlockInstr
+open RTLParFU
+open PrintAST
+
+(* Printing of RTL code *)
+
+let reg pp r =
+ fprintf pp "x%d" (P.to_int r)
+
+let rec regs pp = function
+ | [] -> ()
+ | [r] -> reg pp r
+ | r1::rl -> fprintf pp "%a, %a" reg r1 regs rl
+
+let ros pp = function
+ | Coq_inl r -> reg pp r
+ | Coq_inr s -> fprintf pp "\"%s\"" (extern_atom s)
+
+let print_bblock_body pp i =
+ fprintf pp "\t\t";
+ match i with
+ | FUnop -> fprintf pp "nop\n"
+ | FUop(p, op, ls, dst) ->
+ fprintf pp "%a %a = %a\n"
+ print_pred_option p reg dst (PrintOp.print_operation reg) (op, ls)
+ | FUsetpred (p', c, args, p) ->
+ fprintf pp "%a %a = %a\n"
+ print_pred_option p'
+ pred p
+ (PrintOp.print_condition reg) (c, args)
+ | _ -> assert false
+
+let rec print_bblock_exit pp i =
+ fprintf pp "\t\t";
+ match i with
+ | FUcall(_, fn, args, res, _) ->
+ fprintf pp "%a = %a(%a)\n"
+ reg res ros fn regs args;
+ | FUtailcall(_, fn, args) ->
+ fprintf pp "tailcall %a(%a)\n"
+ ros fn regs args
+ | FUbuiltin(ef, args, res, _) ->
+ fprintf pp "%a = %s(%a)\n"
+ (print_builtin_res reg) res
+ (name_of_external ef)
+ (print_builtin_args reg) args
+ | FUcond(cond, args, s1, s2) ->
+ fprintf pp "if (%a) goto %d else goto %d\n"
+ (PrintOp.print_condition reg) (cond, args)
+ (P.to_int s1) (P.to_int s2)
+ | FUjumptable(arg, tbl) ->
+ let tbl = Array.of_list tbl in
+ fprintf pp "jumptable (%a)\n" reg arg;
+ for i = 0 to Array.length tbl - 1 do
+ fprintf pp "\tcase %d: goto %d\n" i (P.to_int tbl.(i))
+ done
+ | FUreturn None ->
+ fprintf pp "return\n"
+ | FUreturn (Some arg) ->
+ fprintf pp "return %a\n" reg arg
+ | FUgoto n ->
+ fprintf pp "goto %d\n" (P.to_int n)
+ | FUpred_cf (p, c1, c2) ->
+ fprintf pp "if %a then (%a) else (%a)\n" print_pred_op p print_bblock_exit c1 print_bblock_exit c2
+
+let print_bblock pp (pc, i) =
+ fprintf pp "%5d:{\n" pc;
+ List.iter (fun x -> fprintf pp "{\n";
+ List.iter (fun x -> fprintf pp "( "; List.iter (print_bblock_body pp) x; fprintf pp " )") x;
+ fprintf pp "}\n") i.bb_body;
+ print_bblock_exit pp i.bb_exit;
+ fprintf pp "\t}\n\n"
+
+let print_function pp id f =
+ fprintf pp "%s(%a) {\n" (extern_atom id) regs f.fn_params;
+ let instrs =
+ List.sort
+ (fun (pc1, _) (pc2, _) -> compare pc2 pc1)
+ (List.rev_map
+ (fun (pc, i) -> (P.to_int pc, i))
+ (PTree.elements f.fn_code)) in
+ List.iter (print_bblock pp) instrs;
+ fprintf pp "}\n\n"
+
+let print_globdef pp (id, gd) =
+ match gd with
+ | Gfun(Internal f) -> print_function pp id f
+ | _ -> ()
+
+let print_program pp (prog: program) =
+ List.iter (print_globdef pp) prog.prog_defs
+
+let destination : string option ref = ref None
+
+let print_if passno prog =
+ match !destination with
+ | None -> ()
+ | Some f ->
+ let oc = open_out (f ^ "." ^ Z.to_string passno) in
+ print_program oc prog;
+ close_out oc
diff --git a/src/hls/PrintVerilog.ml b/src/hls/PrintVerilog.ml
index fbb26c5..46b001e 100644
--- a/src/hls/PrintVerilog.ml
+++ b/src/hls/PrintVerilog.ml
@@ -28,6 +28,7 @@ open Clflags
open Printf
open VericertClflags
+open FunctionalUnits
module PMap = Map.Make (struct
type t = P.t
@@ -152,9 +153,9 @@ let declarearr (t, _) =
let print_io = function
| Some Vinput -> "input", false
- | Some Voutput -> "output reg", true
+ | Some Voutput -> "output logic", true
| Some Vinout -> "inout", false
- | None -> "reg", true
+ | None -> "logic", true
let decl i = function
| Vdecl (io, r, sz) -> concat [indent i; declare (print_io io) (r, sz)]
@@ -180,6 +181,20 @@ let rec intersperse c = function
let make_io i io r = concat [indent i; io; " "; register r; ";\n"]
+(**let print_funct_units clk = function
+ | SignedDiv (stages, numer, denom, quot, rem) ->
+ sprintf ("div_signed #(.stages(%d)) divs(.clk(%s), " ^^
+ ".clken(1'b1), .numer(%s), .denom(%s), " ^^
+ ".quotient(%s), .remain(%s))\n")
+ (P.to_int stages)
+ (register clk) (register numer) (register denom) (register quot) (register rem)
+ | UnsignedDiv (stages, numer, denom, quot, rem) ->
+ sprintf ("div_unsigned #(.stages(%d)) divs(.clk(%s), " ^^
+ ".clken(1'b1), .numer(%s), .denom(%s), " ^^
+ ".quotient(%s), .remain(%s))\n")
+ (P.to_int stages)
+ (register clk) (register numer) (register denom) (register quot) (register rem)*)
+
let compose f g x = g x |> f
let testbench = "module testbench;
diff --git a/src/hls/RICtransf.v b/src/hls/RICtransf.v
new file mode 100644
index 0000000..3b82b29
--- /dev/null
+++ b/src/hls/RICtransf.v
@@ -0,0 +1,87 @@
+(*
+ * Vericert: Verified high-level synthesis.
+ * Copyright (C) 2022 Yann Herklotz <yann@yannherklotz.com>
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ *)
+
+Require Import compcert.common.AST.
+Require Import compcert.common.Errors.
+Require Import compcert.common.Globalenvs.
+Require Import compcert.lib.Integers.
+Require Import compcert.lib.Maps.
+
+Require Import vericert.common.Vericertlib.
+Require Import vericert.hls.RTLBlockInstr.
+Require Import vericert.hls.RTLPar.
+Require Import vericert.hls.Predicate.
+
+(*|
+=====================
+Reverse If-Conversion
+=====================
+
+This transformation takes a scheduling RTLPar block and removes any predicates
+from it. It can then be trivially transformed into linear code again. It works
+by iteratively selecting a predicate, then creating a branch based on it and
+placing subsequent instructions in one branch or the other.
+|*)
+
+Fixpoint existsb_val {A B} (f: A -> option B) (l : list A) : option B :=
+ match l with
+ | nil => None
+ | a :: l0 =>
+ match f a, existsb_val f l0 with
+ | _, Some v => Some v
+ | Some v, _ => Some v
+ | _, _ => None
+ end
+ end.
+
+Definition includes_setpred (bb: list (list instr)) :=
+ existsb_val (existsb_val (fun x => match x with RBsetpred a _ _ _ => Some a | _ => None end)) bb.
+
+Definition add_bb (should_split: bool) (i: list (list instr))
+ (bbc: list (list (list instr)) * list (list (list instr))) :=
+ match bbc with
+ | (a, b) => if should_split then (a, i::b) else (i::a, b)
+ end.
+
+Fixpoint first_split (saw_pred: bool) (bb: list bb) :=
+ match bb with
+ | a :: b =>
+ match includes_setpred a with
+ | Some v =>
+ let (_, res) := first_split true b in
+ (Some v, add_bb saw_pred a res)
+ | _ =>
+ let (v, res) := first_split saw_pred b in
+ (v, add_bb saw_pred a res)
+ end
+ | nil => (None, (nil, nil))
+ end.
+
+Definition split_bb (fresh: node) (b: list bb) : list bb * list bb * list bb :=
+ match first_split false b with
+ | (Some p, (bb1, bb2)) => (bb1 ++ bb2, nil, nil)
+ | (None, (bb1, bb2)) => (bb1 ++ bb2, nil, nil)
+ end.
+
+Definition transf_function (f: function) : function := f.
+
+Definition transf_fundef (fd: fundef) : fundef :=
+ transf_fundef transf_function fd.
+
+Definition transf_program (p: program) : program :=
+ transform_program transf_fundef p.
diff --git a/src/hls/RTLBlock.v b/src/hls/RTLBlock.v
index bf5c37a..60b6948 100644
--- a/src/hls/RTLBlock.v
+++ b/src/hls/RTLBlock.v
@@ -1,6 +1,6 @@
(*
* Vericert: Verified high-level synthesis.
- * Copyright (C) 2020-2021 Yann Herklotz <yann@yannherklotz.com>
+ * Copyright (C) 2020-2022 Yann Herklotz <yann@yannherklotz.com>
*
* 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
@@ -30,7 +30,13 @@ Require Import compcert.verilog.Op.
Require Import vericert.hls.RTLBlockInstr.
-Definition bb := list instr.
+(*|
+========
+RTLBlock
+========
+|*)
+
+Definition bb := instr.
Definition bblock := @bblock bb.
Definition code := @code bb.
@@ -40,64 +46,92 @@ Definition program := @program bb.
Definition funsig := @funsig bb.
Definition stackframe := @stackframe bb.
Definition state := @state bb.
+
Definition genv := @genv bb.
+(*|
+Semantics
+=========
+
+We first describe the semantics by assuming a global program environment with
+type ~genv~ which was declared earlier.
+|*)
+
Section RELSEM.
Context (ge: genv).
- Inductive step_instr_list: val -> instr_state -> list instr -> instr_state -> Prop :=
- | exec_RBcons:
- forall state i state' state'' instrs sp,
- step_instr ge sp state i state' ->
- step_instr_list sp state' instrs state'' ->
- step_instr_list sp state (i :: instrs) state''
- | exec_RBnil:
- forall state sp,
- step_instr_list sp state nil state.
-
- Inductive step: state -> trace -> state -> Prop :=
+(*|
+Instruction list step
+---------------------
+
+The ``step_instr_list`` definition describes the execution of a list of
+instructions in one big step, inductively traversing the list of instructions
+and applying the ``step_instr``.
+|*)
+
+ Inductive step_instr_list:
+ val -> instr_state -> list instr -> instr_state -> Prop :=
+ | exec_RBcons:
+ forall state i state' state'' instrs sp,
+ step_instr ge sp state i state' ->
+ step_instr_list sp state' instrs state'' ->
+ step_instr_list sp state (i :: instrs) state''
+ | exec_RBnil:
+ forall state sp,
+ step_instr_list sp state nil state.
+
+(*|
+Top-level step
+--------------
+
+The step function itself then uses this big step of the list of instructions to
+then show a transition from basic block to basic block.
+|*)
+
+ Variant step: state -> trace -> state -> Prop :=
| exec_bblock:
forall s f sp pc rs rs' m m' t s' bb pr pr',
f.(fn_code)!pc = Some bb ->
- step_instr_list sp (mk_instr_state rs pr m) bb.(bb_body) (mk_instr_state rs' pr' m') ->
- step_cf_instr ge (State s f sp pc rs' pr' m') bb.(bb_exit) t s' ->
- step (State s f sp pc rs pr m) t s'
+ step_instr_list sp (mk_instr_state rs pr m) bb.(bb_body)
+ (mk_instr_state rs' pr' m') ->
+ step_cf_instr ge (State s f sp pc nil rs' pr' m') bb.(bb_exit) t s' ->
+ step (State s f sp pc nil rs pr m) t s'
| exec_function_internal:
forall s f args m m' stk,
Mem.alloc m 0 f.(fn_stacksize) = (m', stk) ->
step (Callstate s (Internal f) args m)
- E0 (State s
- f
- (Vptr stk Ptrofs.zero)
- f.(fn_entrypoint)
- (init_regs args f.(fn_params))
- (PMap.init false)
- m')
+ E0 (State s f
+ (Vptr stk Ptrofs.zero)
+ f.(fn_entrypoint)
+ nil
+ (init_regs args f.(fn_params))
+ (PMap.init false)
+ m')
| exec_function_external:
forall s ef args res t m m',
external_call ef ge args m t res m' ->
step (Callstate s (External ef) args m)
- t (Returnstate s res m')
+ t (Returnstate s res m')
| exec_return:
forall res f sp pc rs s vres m pr,
step (Returnstate (Stackframe res f sp pc rs pr :: s) vres m)
- E0 (State s f sp pc (rs#res <- vres) pr m).
+ E0 (State s f sp pc nil (rs#res <- vres) pr m).
End RELSEM.
Inductive initial_state (p: program): state -> Prop :=
- | initial_state_intro: forall b f m0,
- let ge := Genv.globalenv p in
- Genv.init_mem p = Some m0 ->
- Genv.find_symbol ge p.(prog_main) = Some b ->
- Genv.find_funct_ptr ge b = Some f ->
- funsig f = signature_main ->
- initial_state p (Callstate nil f nil m0).
+| initial_state_intro: forall b f m0,
+ let ge := Genv.globalenv p in
+ Genv.init_mem p = Some m0 ->
+ Genv.find_symbol ge p.(prog_main) = Some b ->
+ Genv.find_funct_ptr ge b = Some f ->
+ funsig f = signature_main ->
+ initial_state p (Callstate nil f nil m0).
Inductive final_state: state -> int -> Prop :=
- | final_state_intro: forall r m,
- final_state (Returnstate nil (Vint r) m) r.
+| final_state_intro: forall r m,
+ final_state (Returnstate nil (Vint r) m) r.
Definition semantics (p: program) :=
Semantics step (initial_state p) final_state (Genv.globalenv p).
diff --git a/src/hls/RTLBlockInstr.v b/src/hls/RTLBlockInstr.v
index d9f3e74..4631b5a 100644
--- a/src/hls/RTLBlockInstr.v
+++ b/src/hls/RTLBlockInstr.v
@@ -1,20 +1,32 @@
-(*
- * Vericert: Verified high-level synthesis.
- * Copyright (C) 2021 Yann Herklotz <yann@yannherklotz.com>
- *
- * 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 <https://www.gnu.org/licenses/>.
- *)
+(*|
+..
+ Vericert: Verified high-level synthesis.
+ Copyright (C) 2019-2022 Yann Herklotz <yann@yannherklotz.com>
+
+ 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 <https://www.gnu.org/licenses/>.
+
+=============
+RTLBlockInstr
+=============
+
+These instructions are used for ``RTLBlock`` and ``RTLPar``, so that they have
+consistent instructions, which greatly simplifies the proofs, as they will by
+default have the same instruction syntax and semantics. The only changes are
+therefore at the top-level of the instructions.
+
+.. coq:: none
+|*)
Require Import Coq.micromega.Lia.
@@ -31,38 +43,41 @@ Require Import compcert.verilog.Op.
Require Import Predicate.
Require Import Vericertlib.
-(*|
-=====================
-RTLBlock Instructions
-=====================
+Definition node := positive.
-These instructions are used for ``RTLBlock`` and ``RTLPar``, so that they have consistent
-instructions, which greatly simplifies the proofs, as they will by default have the same instruction
-syntax and semantics. The only changes are therefore at the top-level of the instructions.
+(*|
+.. index::
+ triple: definition; RTLBlockInstr; instruction
Instruction Definition
======================
-First, we define the instructions that can be placed into a basic block, meaning they won't branch.
-The main changes to how instructions are defined in ``RTL``, is that these instructions don't have a
-next node, as they will be in a basic block, and they also have an optional predicate (``pred_op``).
+First, we define the instructions that can be placed into a basic block, meaning
+they won't branch. The main changes to how instructions are defined in ``RTL``,
+is that these instructions don't have a next node, as they will be in a basic
+block, and they also have an optional predicate (``pred_op``).
|*)
-Definition node := positive.
-
Inductive instr : Type :=
| RBnop : instr
-| RBop : option pred_op -> operation -> list reg -> reg -> instr
-| RBload : option pred_op -> memory_chunk -> addressing -> list reg -> reg -> instr
-| RBstore : option pred_op -> memory_chunk -> addressing -> list reg -> reg -> instr
-| RBsetpred : option pred_op -> condition -> list reg -> predicate -> instr.
+| RBop :
+ option pred_op -> operation -> list reg -> reg -> instr
+| RBload :
+ option pred_op -> memory_chunk -> addressing -> list reg -> reg -> instr
+| RBstore :
+ option pred_op -> memory_chunk -> addressing -> list reg -> reg -> instr
+| RBsetpred :
+ option pred_op -> condition -> list reg -> predicate -> instr.
(*|
+.. index::
+ triple: definition; RTLBlockInstr; control-flow instruction
+
Control-Flow Instruction Definition
===================================
-These are the instructions that count as control-flow, and will be placed at the end of the basic
-blocks.
+These are the instructions that count as control-flow, and will be placed at the
+end of the basic blocks.
|*)
Inductive cf_instr : Type :=
@@ -77,7 +92,7 @@ Inductive cf_instr : Type :=
| RBpred_cf : pred_op -> cf_instr -> cf_instr -> cf_instr.
(*|
-Helper functions
+Helper Functions
================
|*)
@@ -90,35 +105,36 @@ Fixpoint successors_instr (i : cf_instr) : list node :=
| RBjumptable arg tbl => tbl
| RBreturn optarg => nil
| RBgoto n => n :: nil
- | RBpred_cf p c1 c2 => concat (successors_instr c1 :: successors_instr c2 :: nil)
+ | RBpred_cf p c1 c2 =>
+ concat (successors_instr c1 :: successors_instr c2 :: nil)
end.
Definition max_reg_instr (m: positive) (i: instr) :=
match i with
| RBnop => m
| RBop p op args res =>
- fold_left Pos.max args (Pos.max res m)
+ fold_left Pos.max args (Pos.max res m)
| RBload p chunk addr args dst =>
- fold_left Pos.max args (Pos.max dst m)
+ fold_left Pos.max args (Pos.max dst m)
| RBstore p chunk addr args src =>
- fold_left Pos.max args (Pos.max src m)
+ fold_left Pos.max args (Pos.max src m)
| RBsetpred p' c args p =>
- fold_left Pos.max args m
+ fold_left Pos.max args m
end.
Fixpoint max_reg_cfi (m : positive) (i : cf_instr) :=
match i with
| RBcall sig (inl r) args res s =>
- fold_left Pos.max args (Pos.max r (Pos.max res m))
+ fold_left Pos.max args (Pos.max r (Pos.max res m))
| RBcall sig (inr id) args res s =>
- fold_left Pos.max args (Pos.max res m)
+ fold_left Pos.max args (Pos.max res m)
| RBtailcall sig (inl r) args =>
- fold_left Pos.max args (Pos.max r m)
+ fold_left Pos.max args (Pos.max r m)
| RBtailcall sig (inr id) args =>
- fold_left Pos.max args m
+ fold_left Pos.max args m
| RBbuiltin ef args res s =>
fold_left Pos.max (params_of_builtin_args args)
- (fold_left Pos.max (params_of_builtin_res res) m)
+ (fold_left Pos.max (params_of_builtin_res res) m)
| RBcond cond args ifso ifnot => fold_left Pos.max args m
| RBjumptable arg tbl => Pos.max arg m
| RBreturn None => m
@@ -134,7 +150,7 @@ Definition eval_predf (pr: predset) (p: pred_op) :=
sat_predicate p (fun x => pr !! (Pos.of_nat x)).
#[global]
-Instance eval_predf_Proper : Proper (eq ==> equiv ==> eq) eval_predf.
+ Instance eval_predf_Proper : Proper (eq ==> equiv ==> eq) eval_predf.
Proof.
unfold Proper. simplify. unfold "==>".
intros.
@@ -159,9 +175,10 @@ Lemma eval_predf_pr_equiv :
eval_predf ps p = eval_predf ps' p.
Proof.
induction p; simplify; auto;
- try (unfold eval_predf; simplify; repeat (destruct_match; []); inv Heqp0; rewrite <- H; auto);
- [repeat rewrite eval_predf_Pand|repeat rewrite eval_predf_Por];
- erewrite IHp1; try eassumption; erewrite IHp2; eauto.
+ try (unfold eval_predf; simplify;
+ repeat (destruct_match; []); inv Heqp0; rewrite <- H; auto);
+ [repeat rewrite eval_predf_Pand|repeat rewrite eval_predf_Por];
+ erewrite IHp1; try eassumption; erewrite IHp2; eauto.
Qed.
Fixpoint init_regs (vl: list val) (rl: list reg) {struct rl} : regset :=
@@ -177,16 +194,16 @@ Instruction State
Definition of the instruction state, which contains the following:
:is_rs: This is the current state of the registers.
-:is_ps: This is the current state of the predicate registers, which is in a separate namespace and
- area compared to the standard registers in ``is_rs``.
+:is_ps: This is the current state of the predicate registers, which is in a
+ separate namespace and area compared to the standard registers in [is_rs].
:is_mem: The current state of the memory.
|*)
Record instr_state := mk_instr_state {
- is_rs: regset;
- is_ps: predset;
- is_mem: mem;
-}.
+ is_rs: regset;
+ is_ps: predset;
+ is_mem: mem;
+ }.
(*|
Top-Level Type Definitions
@@ -198,19 +215,19 @@ Section DEFINITION.
Context {bblock_body: Type}.
Record bblock : Type := mk_bblock {
- bb_body: bblock_body;
- bb_exit: cf_instr
- }.
+ bb_body: list bblock_body;
+ bb_exit: cf_instr
+ }.
Definition code: Type := PTree.t bblock.
Record function: Type := mkfunction {
- fn_sig: signature;
- fn_params: list reg;
- fn_stacksize: Z;
- fn_code: code;
- fn_entrypoint: node
- }.
+ fn_sig: signature;
+ fn_params: list reg;
+ fn_stacksize: Z;
+ fn_code: code;
+ fn_entrypoint: node
+ }.
Definition fundef := AST.fundef function.
@@ -224,35 +241,45 @@ Section DEFINITION.
Inductive stackframe : Type :=
| Stackframe:
- forall (res: reg) (**r where to store the result *)
- (f: function) (**r calling function *)
- (sp: val) (**r stack pointer in calling function *)
- (pc: node) (**r program point in calling function *)
- (rs: regset) (**r register state in calling function *)
- (pr: predset), (**r predicate state of the calling function *)
+ forall (res: reg) (**r where to store the result *)
+ (f: function) (**r calling function *)
+ (sp: val) (**r stack pointer in calling function *)
+ (pc: node) (**r program point in calling function *)
+ (rs: regset) (**r register state in calling function *)
+ (pr: predset), (**r predicate state of the calling
+ function *)
stackframe.
- Inductive state : Type :=
- | State:
+(*|
+State Definition
+----------------
+
+Definition of the ``state`` type, which is used by the ``step`` functions.
+|*)
+
+ Variant state : Type :=
+ | State:
forall (stack: list stackframe) (**r call stack *)
(f: function) (**r current function *)
(sp: val) (**r stack pointer *)
(pc: node) (**r current program point in [c] *)
+ (il: list bblock_body) (**r basic block body that is
+ currently executing. *)
(rs: regset) (**r register state *)
(pr: predset) (**r predicate register state *)
(m: mem), (**r memory state *)
- state
- | Callstate:
+ state
+ | Callstate:
forall (stack: list stackframe) (**r call stack *)
(f: fundef) (**r function to call *)
(args: list val) (**r arguments to the call *)
(m: mem), (**r memory state *)
- state
- | Returnstate:
+ state
+ | Returnstate:
forall (stack: list stackframe) (**r call stack *)
(v: val) (**r return value for the call *)
(m: mem), (**r memory state *)
- state.
+ state.
End DEFINITION.
@@ -274,94 +301,122 @@ Section RELSEM.
match ros with
| inl r => Genv.find_funct ge rs#r
| inr symb =>
- match Genv.find_symbol ge symb with
- | None => None
- | Some b => Genv.find_funct_ptr ge b
- end
+ match Genv.find_symbol ge symb with
+ | None => None
+ | Some b => Genv.find_funct_ptr ge b
+ end
end.
- Inductive eval_pred: option pred_op -> instr_state -> instr_state -> instr_state -> Prop :=
+ Inductive eval_pred:
+ option pred_op -> instr_state -> instr_state -> instr_state -> Prop :=
| eval_pred_true:
- forall i i' p,
+ forall i i' p,
eval_predf (is_ps i) p = true ->
eval_pred (Some p) i i' i'
| eval_pred_false:
- forall i i' p,
+ forall i i' p,
eval_predf (is_ps i) p = false ->
eval_pred (Some p) i i' i
| eval_pred_none:
- forall i i', eval_pred None i i' i.
+ forall i i', eval_pred None i i' i.
+
+ (*|
+.. index::
+ triple: semantics; RTLBlockInstr; instruction
+
+Step Instruction
+=============================
+|*)
Inductive step_instr: val -> instr_state -> instr -> instr_state -> Prop :=
| exec_RBnop:
- forall sp ist,
- step_instr sp ist RBnop ist
+ forall sp ist,
+ step_instr sp ist RBnop ist
| exec_RBop:
- forall op v res args rs m sp p ist pr,
- eval_operation ge sp op rs##args m = Some v ->
- eval_pred p (mk_instr_state rs pr m) (mk_instr_state (rs#res <- v) pr m) ist ->
- step_instr sp (mk_instr_state rs pr m) (RBop p op args res) ist
+ forall op v res args rs m sp p ist pr,
+ eval_operation ge sp op rs##args m = Some v ->
+ eval_pred p (mk_instr_state rs pr m)
+ (mk_instr_state (rs#res <- v) pr m) ist ->
+ step_instr sp (mk_instr_state rs pr m) (RBop p op args res) ist
| exec_RBload:
- forall addr rs args a chunk m v dst sp p pr ist,
- eval_addressing ge sp addr rs##args = Some a ->
- Mem.loadv chunk m a = Some v ->
- eval_pred p (mk_instr_state rs pr m) (mk_instr_state (rs#dst <- v) pr m) ist ->
- step_instr sp (mk_instr_state rs pr m) (RBload p chunk addr args dst) ist
+ forall addr rs args a chunk m v dst sp p pr ist,
+ eval_addressing ge sp addr rs##args = Some a ->
+ Mem.loadv chunk m a = Some v ->
+ eval_pred p (mk_instr_state rs pr m)
+ (mk_instr_state (rs#dst <- v) pr m) ist ->
+ step_instr sp (mk_instr_state rs pr m)
+ (RBload p chunk addr args dst) ist
| exec_RBstore:
- forall addr rs args a chunk m src m' sp p pr ist,
- eval_addressing ge sp addr rs##args = Some a ->
- Mem.storev chunk m a rs#src = Some m' ->
- eval_pred p (mk_instr_state rs pr m) (mk_instr_state rs pr m') ist ->
- step_instr sp (mk_instr_state rs pr m) (RBstore p chunk addr args src) ist
+ forall addr rs args a chunk m src m' sp p pr ist,
+ eval_addressing ge sp addr rs##args = Some a ->
+ Mem.storev chunk m a rs#src = Some m' ->
+ eval_pred p (mk_instr_state rs pr m)
+ (mk_instr_state rs pr m') ist ->
+ step_instr sp (mk_instr_state rs pr m)
+ (RBstore p chunk addr args src) ist
| exec_RBsetpred:
- forall sp rs pr m p c b args p' ist,
+ forall sp rs pr m p c b args p' ist,
Op.eval_condition c rs##args m = Some b ->
- eval_pred p' (mk_instr_state rs pr m) (mk_instr_state rs (pr#p <- b) m) ist ->
- step_instr sp (mk_instr_state rs pr m) (RBsetpred p' c args p) ist.
+ eval_pred p' (mk_instr_state rs pr m)
+ (mk_instr_state rs (pr#p <- b) m) ist ->
+ step_instr sp (mk_instr_state rs pr m)
+ (RBsetpred p' c args p) ist.
+
+ (*|
+.. index::
+ triple: semantics; RTLBlockInstr; control-flow instruction
+
+Step Control-Flow Instruction
+=============================
+|*)
Inductive step_cf_instr: state -> cf_instr -> trace -> state -> Prop :=
| exec_RBcall:
forall s f sp rs m res fd ros sig args pc pc' pr,
find_function ros rs = Some fd ->
funsig fd = sig ->
- step_cf_instr (State s f sp pc rs pr m) (RBcall sig ros args res pc')
- E0 (Callstate (Stackframe res f sp pc' rs pr :: s) fd rs##args m)
+ step_cf_instr (State s f sp pc nil rs pr m) (RBcall sig ros args res pc')
+ E0 (Callstate (Stackframe res f sp pc' rs pr :: s) fd rs##args m)
| exec_RBtailcall:
- forall s f stk rs m sig ros args fd m' pc pr,
+ forall s f stk rs m sig ros args fd m' pc pr,
find_function ros rs = Some fd ->
funsig fd = sig ->
Mem.free m stk 0 f.(fn_stacksize) = Some m' ->
- step_cf_instr (State s f (Vptr stk Ptrofs.zero) pc rs pr m) (RBtailcall sig ros args)
- E0 (Callstate s fd rs##args m')
+ step_cf_instr (State s f (Vptr stk Ptrofs.zero) pc nil rs pr m)
+ (RBtailcall sig ros args)
+ E0 (Callstate s fd rs##args m')
| exec_RBbuiltin:
- forall s f sp rs m ef args res pc' vargs t vres m' pc pr,
+ forall s f sp rs m ef args res pc' vargs t vres m' pc pr,
eval_builtin_args ge (fun r => rs#r) sp m args vargs ->
external_call ef ge vargs m t vres m' ->
- step_cf_instr (State s f sp pc rs pr m) (RBbuiltin ef args res pc')
- t (State s f sp pc' (regmap_setres res vres rs) pr m')
+ step_cf_instr (State s f sp pc nil rs pr m) (RBbuiltin ef args res pc')
+ t (State s f sp pc' nil (regmap_setres res vres rs) pr m')
| exec_RBcond:
- forall s f sp rs m cond args ifso ifnot b pc pc' pr,
+ forall s f sp rs m cond args ifso ifnot b pc pc' pr,
eval_condition cond rs##args m = Some b ->
pc' = (if b then ifso else ifnot) ->
- step_cf_instr (State s f sp pc rs pr m) (RBcond cond args ifso ifnot)
- E0 (State s f sp pc' rs pr m)
+ step_cf_instr (State s f sp pc nil rs pr m) (RBcond cond args ifso ifnot)
+ E0 (State s f sp pc' nil rs pr m)
| exec_RBjumptable:
- forall s f sp rs m arg tbl n pc pc' pr,
+ forall s f sp rs m arg tbl n pc pc' pr,
rs#arg = Vint n ->
list_nth_z tbl (Int.unsigned n) = Some pc' ->
- step_cf_instr (State s f sp pc rs pr m) (RBjumptable arg tbl)
- E0 (State s f sp pc' rs pr m)
+ step_cf_instr (State s f sp pc nil rs pr m) (RBjumptable arg tbl)
+ E0 (State s f sp pc' nil rs pr m)
| exec_RBreturn:
- forall s f stk rs m or pc m' pr,
+ forall s f stk rs m or pc m' pr,
Mem.free m stk 0 f.(fn_stacksize) = Some m' ->
- step_cf_instr (State s f (Vptr stk Ptrofs.zero) pc rs pr m) (RBreturn or)
- E0 (Returnstate s (regmap_optget or Vundef rs) m')
+ step_cf_instr (State s f (Vptr stk Ptrofs.zero) pc nil rs pr m) (RBreturn or)
+ E0 (Returnstate s (regmap_optget or Vundef rs) m')
| exec_RBgoto:
- forall s f sp pc rs pr m pc',
- step_cf_instr (State s f sp pc rs pr m) (RBgoto pc') E0 (State s f sp pc' rs pr m)
+ forall s f sp pc rs pr m pc',
+ step_cf_instr (State s f sp pc nil rs pr m) (RBgoto pc') E0
+ (State s f sp pc' nil rs pr m)
| exec_RBpred_cf:
- forall s f sp pc rs pr m cf1 cf2 st' p t,
- step_cf_instr (State s f sp pc rs pr m) (if eval_predf pr p then cf1 else cf2) t st' ->
- step_cf_instr (State s f sp pc rs pr m) (RBpred_cf p cf1 cf2) t st'.
+ forall s f sp pc rs pr m cf1 cf2 st' p t,
+ step_cf_instr (State s f sp pc nil rs pr m)
+ (if eval_predf pr p then cf1 else cf2) t st' ->
+ step_cf_instr (State s f sp pc nil rs pr m)
+ (RBpred_cf p cf1 cf2) t st'.
End RELSEM.
diff --git a/src/hls/RTLBlockgen.v b/src/hls/RTLBlockgen.v
index 889e104..dc65cc2 100644
--- a/src/hls/RTLBlockgen.v
+++ b/src/hls/RTLBlockgen.v
@@ -1,30 +1,190 @@
-(*
- * Vericert: Verified high-level synthesis.
- * Copyright (C) 2020 Yann Herklotz <yann@yannherklotz.com>
- *
- * 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 <https://www.gnu.org/licenses/>.
- *)
+(*|
+..
+ Vericert: Verified high-level synthesis.
+ Copyright (C) 2020-2022 Yann Herklotz <yann@yannherklotz.com>
+
+ 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 <https://www.gnu.org/licenses/>.
+
+===========
+RTLBlockgen
+===========
+
+.. coq:: none
+|*)
Require compcert.backend.RTL.
Require Import compcert.common.AST.
Require Import compcert.lib.Maps.
+Require Import compcert.lib.Integers.
+Require Import compcert.lib.Floats.
+Require Import vericert.common.DecEq.
+Require Import vericert.common.Vericertlib.
+Require Import vericert.hls.RTLBlockInstr.
Require Import vericert.hls.RTLBlock.
+#[local] Open Scope positive.
+
+(*|
+``find_block max nodes index``: Does not need to be sorted, because we use
+filter and the max fold function to find the desired element.
+|*)
+
+Definition find_block (max: positive) (nodes: list positive) (index: positive) : positive :=
+ List.fold_right Pos.min max (List.filter (fun x => (index <=? x)) nodes).
+
+(*Compute find_block 100 (2::94::48::39::19::nil) 40.*)
+
+(*|
+.. index::
+ triple: abstract interpretation; check instruction; RTLBlockgen
+
+Check Instruction
+=================
+
+Check if an instruction is a standard instruction that should be in a basic
+block.
+|*)
+
+Definition check_instr (n: positive) (istr: RTL.instruction) (istr': instr) :=
+ match istr, istr' with
+ | RTL.Inop n', RBnop => (n' + 1 =? n)
+ | RTL.Iop op args dst n', RBop None op' args' dst' =>
+ ceq operation_eq op op' &&
+ ceq list_pos_eq args args' &&
+ ceq peq dst dst' && (n' + 1 =? n)
+ | RTL.Iload chunk addr args dst n', RBload None chunk' addr' args' dst' =>
+ ceq memory_chunk_eq chunk chunk' &&
+ ceq addressing_eq addr addr' &&
+ ceq list_pos_eq args args' &&
+ ceq peq dst dst' &&
+ (n' + 1 =? n)
+ | RTL.Istore chunk addr args src n', RBstore None chunk' addr' args' src' =>
+ ceq memory_chunk_eq chunk chunk' &&
+ ceq addressing_eq addr addr' &&
+ ceq list_pos_eq args args' &&
+ ceq peq src src' &&
+ (n' + 1 =? n)
+ | _, _ => false
+ end.
+
+Definition check_cf_instr_body (istr: RTL.instruction) (istr': instr): bool :=
+ match istr, istr' with
+ | RTL.Iop op args dst _, RBop None op' args' dst' =>
+ ceq operation_eq op op' &&
+ ceq list_pos_eq args args' &&
+ ceq peq dst dst'
+ | RTL.Iload chunk addr args dst _, RBload None chunk' addr' args' dst' =>
+ ceq memory_chunk_eq chunk chunk' &&
+ ceq addressing_eq addr addr' &&
+ ceq list_pos_eq args args' &&
+ ceq peq dst dst'
+ | RTL.Istore chunk addr args src _, RBstore None chunk' addr' args' src' =>
+ ceq memory_chunk_eq chunk chunk' &&
+ ceq addressing_eq addr addr' &&
+ ceq list_pos_eq args args' &&
+ ceq peq src src'
+ | RTL.Inop _, RBnop
+ | RTL.Icall _ _ _ _ _, RBnop
+ | RTL.Itailcall _ _ _, RBnop
+ | RTL.Ibuiltin _ _ _ _, RBnop
+ | RTL.Icond _ _ _ _, RBnop
+ | RTL.Ijumptable _ _, RBnop
+ | RTL.Ireturn _, RBnop => true
+ | _, _ => false
+ end.
+
+Definition check_cf_instr (istr: RTL.instruction) (istr': cf_instr) :=
+ match istr, istr' with
+ | RTL.Inop n, RBgoto n' => (n =? n')
+ | RTL.Iop _ _ _ n, RBgoto n' => (n =? n')
+ | RTL.Iload _ _ _ _ n, RBgoto n' => (n =? n')
+ | RTL.Istore _ _ _ _ n, RBgoto n' => (n =? n')
+ | RTL.Icall sig (inl r) args dst n, RBcall sig' (inl r') args' dst' n' =>
+ ceq signature_eq sig sig' &&
+ ceq peq r r' &&
+ ceq list_pos_eq args args' &&
+ ceq peq dst dst' &&
+ (n =? n')
+ | RTL.Icall sig (inr i) args dst n, RBcall sig' (inr i') args' dst' n' =>
+ ceq signature_eq sig sig' &&
+ ceq peq i i' &&
+ ceq list_pos_eq args args' &&
+ ceq peq dst dst' &&
+ (n =? n')
+ | RTL.Itailcall sig (inl r) args, RBtailcall sig' (inl r') args' =>
+ ceq signature_eq sig sig' &&
+ ceq peq r r' &&
+ ceq list_pos_eq args args'
+ | RTL.Itailcall sig (inr r) args, RBtailcall sig' (inr r') args' =>
+ ceq signature_eq sig sig' &&
+ ceq peq r r' &&
+ ceq list_pos_eq args args'
+ | RTL.Icond cond args n1 n2, RBcond cond' args' n1' n2' =>
+ ceq condition_eq cond cond' &&
+ ceq list_pos_eq args args' &&
+ ceq peq n1 n1' && ceq peq n2 n2'
+ | RTL.Ijumptable r ns, RBjumptable r' ns' =>
+ ceq peq r r' && ceq list_pos_eq ns ns'
+ | RTL.Ireturn (Some r), RBreturn (Some r') =>
+ ceq peq r r'
+ | RTL.Ireturn None, RBreturn None => true
+ | _, _ => false
+ end.
+
+Definition is_cf_instr (n: positive) (i: RTL.instruction) :=
+ match i with
+ | RTL.Inop n' => negb (n' + 1 =? n)
+ | RTL.Iop _ _ _ n' => negb (n' + 1 =? n)
+ | RTL.Iload _ _ _ _ n' => negb (n' + 1 =? n)
+ | RTL.Istore _ _ _ _ n' => negb (n' + 1 =? n)
+ | RTL.Icall _ _ _ _ _ => true
+ | RTL.Itailcall _ _ _ => true
+ | RTL.Ibuiltin _ _ _ _ => true
+ | RTL.Icond _ _ _ _ => true
+ | RTL.Ijumptable _ _ => true
+ | RTL.Ireturn _ => true
+ end.
+
+Definition check_present_blocks (c: code) (n: list positive) (max: positive) (i: positive) (istr: RTL.instruction) :=
+ let blockn := find_block max n i in
+ match c ! blockn with
+ | Some istrs =>
+ match List.nth_error istrs.(bb_body) (Pos.to_nat blockn - Pos.to_nat i)%nat with
+ | Some istr' =>
+ if is_cf_instr i istr
+ then check_cf_instr istr istrs.(bb_exit) && check_cf_instr_body istr istr'
+ else check_instr i istr istr'
+ | None => false
+ end
+ | None => false
+ end.
+
Parameter partition : RTL.function -> Errors.res function.
-Definition transl_fundef := transf_partial_fundef partition.
+Definition transl_function (f: RTL.function) :=
+ match partition f with
+ | Errors.OK f' =>
+ let blockids := map fst (PTree.elements f'.(fn_code)) in
+ if forall_ptree (check_present_blocks f'.(fn_code) blockids (fold_right Pos.max 1 blockids))
+ f.(RTL.fn_code) then
+ Errors.OK f'
+ else Errors.Error (Errors.msg "check_present_blocks failed")
+ | Errors.Error msg => Errors.Error msg
+ end.
+
+Definition transl_fundef := transf_partial_fundef transl_function.
Definition transl_program : RTL.program -> Errors.res program :=
transform_partial_program transl_fundef.
diff --git a/src/hls/RTLBlockgenproof.v b/src/hls/RTLBlockgenproof.v
new file mode 100644
index 0000000..f870278
--- /dev/null
+++ b/src/hls/RTLBlockgenproof.v
@@ -0,0 +1,170 @@
+(*|
+..
+ Vericert: Verified high-level synthesis.
+ Copyright (C) 2020-2022 Yann Herklotz <yann@yannherklotz.com>
+
+ 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 <https://www.gnu.org/licenses/>.
+
+================
+RTLBlockgenproof
+================
+
+.. coq:: none
+|*)
+
+Require compcert.backend.RTL.
+Require Import compcert.common.AST.
+Require Import compcert.common.Errors.
+Require Import compcert.common.Globalenvs.
+Require Import compcert.lib.Maps.
+
+Require Import vericert.common.Vericertlib.
+Require Import vericert.hls.RTLBlockInstr.
+Require Import vericert.hls.RTLBlock.
+Require Import vericert.hls.RTLBlockgen.
+
+#[local] Open Scope positive.
+
+(*|
+Defining a find block specification
+===================================
+
+Basically, it should be able to find the location of the block without using the
+``find_block`` function, so that this is more useful for the proofs. There are
+various different types of options that could come up though:
+
+1. The instruction is a standard instruction present inside of a basic block.
+2. The instruction is a standard instruction which ends with a ``goto``.
+3. The instruction is a control-flow instruction.
+
+For case number 1, there should exist a value in the list of instructions, such
+that the instructions match exactly, and the indices match as well. In the
+original code, this instruction must have been going from the current node to
+the node - 1.
+
+For case number 2, there should be an instruction at the right index again,
+however, this time there will also be a ``goto`` instruction in the control-flow
+part of the basic block.
+
+For case number 3, there should be a ``nop`` instruction in the basic block, and
+then the equivalent control-flow instruction ending the basic block.
+|*)
+
+Parameter find_block_spec : code -> node -> node -> Prop.
+
+Definition find_instr_spec (c: code) (n: node) (i: RTL.instruction)
+ (n': node) (i': instr) :=
+ find_block_spec c n n'
+ /\ exists il,
+ c ! n' = Some il
+ /\ nth_error il.(bb_body) (Pos.to_nat n - Pos.to_nat n')%nat = Some i'.
+
+(*|
+.. index::
+ pair: semantics; transl_code_spec
+
+Translation Specification
+-------------------------
+
+This specification should describe the translation that the unverified
+transformation performs. This should be proven from the validation of the
+transformation.
+|*)
+
+Variant transl_code_spec (c: RTL.code) (tc: code) :=
+| transl_code_standard_bb :
+ forall x x' i i',
+ c ! x = Some i ->
+ find_instr_spec tc x i x' i' ->
+ check_instr x i i' = true ->
+ transl_code_spec c tc
+| transl_code_standard_cf :
+ forall x x' i i' il,
+ c ! x = Some i ->
+ tc ! x' = Some il ->
+ find_instr_spec tc x i x' i' ->
+ check_cf_instr_body i i' = true ->
+ check_cf_instr i il.(bb_exit) = true ->
+ transl_code_spec c tc
+.
+
+Lemma transl_function_correct :
+ forall f tf,
+ transl_function f = OK tf ->
+ transl_code_spec f.(RTL.fn_code) tf.(fn_code).
+Proof. Admitted.
+
+Variant match_stackframe : RTL.stackframe -> stackframe -> Prop :=
+| match_stackframe_init :
+ forall a b,
+ match_stackframe a b.
+
+Variant match_states : RTL.state -> RTLBlock.state -> Prop :=
+| match_state :
+ forall stk stk' f tf sp pc rs m pc' ps
+ (TF: transl_function f = OK tf)
+ (PC: find_block_spec tf.(fn_code) pc pc')
+ (STK: Forall2 match_stackframe stk stk'),
+ match_states (RTL.State stk f sp pc rs m)
+ (State stk' tf sp pc' nil rs ps m).
+
+Definition match_prog (p: RTL.program) (tp: RTLBlock.program) :=
+ Linking.match_program (fun cu f tf => transl_fundef f = Errors.OK tf) eq p tp.
+
+Section CORRECTNESS.
+
+ Context (prog : RTL.program).
+ Context (tprog : RTLBlock.program).
+
+ Context (TRANSL : match_prog prog tprog).
+
+ Let ge : RTL.genv := Globalenvs.Genv.globalenv prog.
+ Let tge : genv := Globalenvs.Genv.globalenv tprog.
+
+ Lemma symbols_preserved:
+ forall (s: AST.ident), Genv.find_symbol tge s = Genv.find_symbol ge s.
+ Proof using TRANSL. intros. eapply (Genv.find_symbol_match TRANSL). Qed.
+
+ Lemma senv_preserved:
+ Senv.equiv (Genv.to_senv ge) (Genv.to_senv tge).
+ Proof using TRANSL. intros; eapply (Genv.senv_transf_partial TRANSL). Qed.
+ #[local] Hint Resolve senv_preserved : rtlgp.
+
+ Lemma transl_initial_states :
+ forall s1 : Smallstep.state (RTL.semantics prog),
+ Smallstep.initial_state (RTL.semantics prog) s1 ->
+ exists s2 : Smallstep.state (semantics tprog),
+ Smallstep.initial_state (semantics tprog) s2 /\ match_states s1 s2.
+ Proof. Admitted.
+
+ Lemma transl_final_states :
+ forall (s1 : Smallstep.state (RTL.semantics prog))
+ (s2 : Smallstep.state (semantics tprog))
+ (r : Integers.Int.int),
+ match_states s1 s2 ->
+ Smallstep.final_state (RTL.semantics prog) s1 r ->
+ Smallstep.final_state (semantics tprog) s2 r.
+ Proof. Admitted.
+
+ Theorem transf_program_correct:
+ Smallstep.forward_simulation (RTL.semantics prog)
+ (RTLBlock.semantics tprog).
+ Proof.
+ eapply Smallstep.forward_simulation_plus.
+ apply senv_preserved.
+ admit.
+ eauto using transl_final_states.
+ Admitted.
+
+End CORRECTNESS.
diff --git a/src/hls/RTLPar.v b/src/hls/RTLPar.v
index 4986cff..7ae563d 100644
--- a/src/hls/RTLPar.v
+++ b/src/hls/RTLPar.v
@@ -1,6 +1,6 @@
(*
* Vericert: Verified high-level synthesis.
- * Copyright (C) 2020-2021 Yann Herklotz <yann@yannherklotz.com>
+ * Copyright (C) 2020-2022 Yann Herklotz <yann@yannherklotz.com>
*
* 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
@@ -30,7 +30,7 @@ Require Import compcert.verilog.Op.
Require Import vericert.hls.RTLBlockInstr.
-Definition bb := list (list (list instr)).
+Definition bb := list (list instr).
Definition bblock := @bblock bb.
Definition code := @code bb.
@@ -46,15 +46,16 @@ Section RELSEM.
Context (ge: genv).
- Inductive step_instr_list: val -> instr_state -> list instr -> instr_state -> Prop :=
- | exec_RBcons:
- forall state i state' state'' instrs sp,
- step_instr ge sp state i state' ->
- step_instr_list sp state' instrs state'' ->
- step_instr_list sp state (i :: instrs) state''
- | exec_RBnil:
- forall state sp,
- step_instr_list sp state nil state.
+ Inductive step_instr_list:
+ val -> instr_state -> list instr -> instr_state -> Prop :=
+ | exec_RBcons:
+ forall state i state' state'' instrs sp,
+ step_instr ge sp state i state' ->
+ step_instr_list sp state' instrs state'' ->
+ step_instr_list sp state (i :: instrs) state''
+ | exec_RBnil:
+ forall state sp,
+ step_instr_list sp state nil state.
Inductive step_instr_seq (sp : val)
: instr_state -> list (list instr) -> instr_state -> Prop :=
@@ -68,7 +69,7 @@ Section RELSEM.
step_instr_seq sp state nil state.
Inductive step_instr_block (sp : val)
- : instr_state -> bb -> instr_state -> Prop :=
+ : instr_state -> list bb -> instr_state -> Prop :=
| exec_instr_block_cons:
forall state i state' state'' instrs,
step_instr_seq sp state i state' ->
@@ -80,11 +81,12 @@ Section RELSEM.
Inductive step: state -> trace -> state -> Prop :=
| exec_bblock:
- forall s f sp pc rs rs' m m' t s' bb pr pr',
+ forall s (f: function) sp pc rs rs' m m' t s' bb pr pr',
f.(fn_code)!pc = Some bb ->
- step_instr_block sp (mk_instr_state rs pr m) bb.(bb_body) (mk_instr_state rs' pr' m') ->
- step_cf_instr ge (State s f sp pc rs' pr' m') bb.(bb_exit) t s' ->
- step (State s f sp pc rs pr m) t s'
+ step_instr_block sp (mk_instr_state rs pr m) bb.(bb_body)
+ (mk_instr_state rs' pr' m') ->
+ step_cf_instr ge (State s f sp pc nil rs' pr' m') bb.(bb_exit) t s' ->
+ step (State s f sp pc nil rs pr m) t s'
| exec_function_internal:
forall s f args m m' stk,
Mem.alloc m 0 f.(fn_stacksize) = (m', stk) ->
@@ -93,6 +95,7 @@ Section RELSEM.
f
(Vptr stk Ptrofs.zero)
f.(fn_entrypoint)
+ nil
(init_regs args f.(fn_params))
(PMap.init false)
m')
@@ -104,7 +107,7 @@ Section RELSEM.
| exec_return:
forall res f sp pc rs s vres m pr,
step (Returnstate (Stackframe res f sp pc rs pr :: s) vres m)
- E0 (State s f sp pc (rs#res <- vres) pr m).
+ E0 (State s f sp pc nil (rs#res <- vres) pr m).
End RELSEM.
@@ -125,7 +128,11 @@ Definition semantics (p: program) :=
Semantics step (initial_state p) final_state (Genv.globalenv p).
Definition max_reg_bblock (m : positive) (pc : node) (bb : bblock) :=
- let max_body := fold_left (fun x l => fold_left (fun x' l' => fold_left max_reg_instr l' x') l x) bb.(bb_body) m in
+ let max_body :=
+ fold_left
+ (fun x l => fold_left (fun x' l' => fold_left max_reg_instr l' x') l x)
+ bb.(bb_body) m
+ in
max_reg_cfi max_body bb.(bb_exit).
Definition max_reg_function (f: function) :=
@@ -134,7 +141,9 @@ Definition max_reg_function (f: function) :=
(fold_left Pos.max f.(fn_params) 1%positive).
Definition max_pc_function (f: function) : positive :=
- PTree.fold (fun m pc i => (Pos.max m
- (pc + match Zlength i.(bb_body)
- with Z.pos p => p | _ => 1 end))%positive)
- f.(fn_code) 1%positive.
+ PTree.fold
+ (fun m pc i =>
+ (Pos.max m
+ (pc + match Zlength i.(bb_body)
+ with Z.pos p => p | _ => 1 end))%positive)
+ f.(fn_code) 1%positive.
diff --git a/src/hls/RTLParFU.v b/src/hls/RTLParFU.v
new file mode 100644
index 0000000..f0ceafd
--- /dev/null
+++ b/src/hls/RTLParFU.v
@@ -0,0 +1,389 @@
+(*
+ * Vericert: Verified high-level synthesis.
+ * Copyright (C) 2020-2021 Yann Herklotz <yann@yannherklotz.com>
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ *)
+
+Require Import compcert.backend.Registers.
+Require Import compcert.common.AST.
+Require Import compcert.common.Events.
+Require Import compcert.common.Globalenvs.
+Require Import compcert.common.Memory.
+Require Import compcert.common.Smallstep.
+Require Import compcert.common.Values.
+Require Import compcert.lib.Coqlib.
+Require Import compcert.lib.Integers.
+Require Import compcert.lib.Maps.
+Require Import compcert.verilog.Op.
+
+Require Import vericert.hls.FunctionalUnits.
+Require Import Predicate.
+Require Import Vericertlib.
+
+Definition node := positive.
+
+Inductive instr : Type :=
+| FUnop : instr
+| FUop : option pred_op -> operation -> list reg -> reg -> instr
+| FUread : positive -> positive -> reg -> instr
+| FUwrite : positive -> positive -> reg -> instr
+| FUsetpred : option pred_op -> condition -> list reg -> predicate -> instr.
+
+Inductive cf_instr : Type :=
+| FUcall : signature -> reg + ident -> list reg -> reg -> node -> cf_instr
+| FUtailcall : signature -> reg + ident -> list reg -> cf_instr
+| FUbuiltin : external_function -> list (builtin_arg reg) ->
+ builtin_res reg -> node -> cf_instr
+| FUcond : condition -> list reg -> node -> node -> cf_instr
+| FUjumptable : reg -> list node -> cf_instr
+| FUreturn : option reg -> cf_instr
+| FUgoto : node -> cf_instr
+| FUpred_cf : pred_op -> cf_instr -> cf_instr -> cf_instr.
+
+Fixpoint successors_instr (i : cf_instr) : list node :=
+ match i with
+ | FUcall sig ros args res s => s :: nil
+ | FUtailcall sig ros args => nil
+ | FUbuiltin ef args res s => s :: nil
+ | FUcond cond args ifso ifnot => ifso :: ifnot :: nil
+ | FUjumptable arg tbl => tbl
+ | FUreturn optarg => nil
+ | FUgoto n => n :: nil
+ | FUpred_cf p c1 c2 => concat (successors_instr c1 :: successors_instr c2 :: nil)
+ end.
+
+Definition max_reg_instr (m: positive) (i: instr) :=
+ match i with
+ | FUnop => m
+ | FUop p op args res =>
+ fold_left Pos.max args (Pos.max res m)
+ | FUread p1 p2 r => Pos.max m r
+ | FUwrite p1 p2 r => Pos.max m r
+ | FUsetpred p' c args p =>
+ fold_left Pos.max args m
+ end.
+
+Fixpoint max_reg_cfi (m : positive) (i : cf_instr) :=
+ match i with
+ | FUcall sig (inl r) args res s =>
+ fold_left Pos.max args (Pos.max r (Pos.max res m))
+ | FUcall sig (inr id) args res s =>
+ fold_left Pos.max args (Pos.max res m)
+ | FUtailcall sig (inl r) args =>
+ fold_left Pos.max args (Pos.max r m)
+ | FUtailcall sig (inr id) args =>
+ fold_left Pos.max args m
+ | FUbuiltin ef args res s =>
+ fold_left Pos.max (params_of_builtin_args args)
+ (fold_left Pos.max (params_of_builtin_res res) m)
+ | FUcond cond args ifso ifnot => fold_left Pos.max args m
+ | FUjumptable arg tbl => Pos.max arg m
+ | FUreturn None => m
+ | FUreturn (Some arg) => Pos.max arg m
+ | FUgoto n => m
+ | FUpred_cf p c1 c2 => Pos.max (max_reg_cfi m c1) (max_reg_cfi m c2)
+ end.
+
+Definition regset := Regmap.t val.
+Definition predset := PMap.t bool.
+
+Definition eval_predf (pr: predset) (p: pred_op) :=
+ sat_predicate p (fun x => pr !! (Pos.of_nat x)).
+
+#[global]
+ Instance eval_predf_Proper : Proper (eq ==> equiv ==> eq) eval_predf.
+Proof.
+ unfold Proper. simplify. unfold "==>".
+ intros.
+ unfold sat_equiv in *. intros. unfold eval_predf. subst. apply H0.
+Qed.
+
+#[local] Open Scope pred_op.
+
+Lemma eval_predf_Pand :
+ forall ps p p',
+ eval_predf ps (p ∧ p') = eval_predf ps p && eval_predf ps p'.
+Proof. unfold eval_predf; split; simplify; auto with bool. Qed.
+
+Lemma eval_predf_Por :
+ forall ps p p',
+ eval_predf ps (p ∨ p') = eval_predf ps p || eval_predf ps p'.
+Proof. unfold eval_predf; split; simplify; auto with bool. Qed.
+
+Lemma eval_predf_pr_equiv :
+ forall p ps ps',
+ (forall x, ps !! x = ps' !! x) ->
+ eval_predf ps p = eval_predf ps' p.
+Proof.
+ induction p; simplify; auto;
+ try (unfold eval_predf; simplify; repeat (destruct_match; []); inv Heqp0; rewrite <- H; auto);
+ [repeat rewrite eval_predf_Pand|repeat rewrite eval_predf_Por];
+ erewrite IHp1; try eassumption; erewrite IHp2; eauto.
+Qed.
+
+Fixpoint init_regs (vl: list val) (rl: list reg) {struct rl} : regset :=
+ match rl, vl with
+ | r1 :: rs, v1 :: vs => Regmap.set r1 v1 (init_regs vs rs)
+ | _, _ => Regmap.init Vundef
+ end.
+
+Definition bblock_body := list (list (list instr)).
+
+Record bblock : Type :=
+ mk_bblock {
+ bb_body: bblock_body;
+ bb_exit: cf_instr
+ }.
+
+Definition code: Type := PTree.t bblock.
+
+Record function: Type :=
+ mkfunction {
+ fn_sig: signature;
+ fn_params: list reg;
+ fn_stacksize: Z;
+ fn_code: code;
+ fn_funct_units: resources;
+ fn_entrypoint: node;
+ }.
+
+Definition fundef := AST.fundef function.
+Definition program := AST.program fundef unit.
+
+Definition funsig (fd: fundef) :=
+ match fd with
+ | Internal f => fn_sig f
+ | External ef => ef_sig ef
+ end.
+
+Inductive stackframe : Type :=
+| Stackframe:
+ forall (res: reg) (**r where to store the result *)
+ (f: function) (**r calling function *)
+ (sp: val) (**r stack pointer in calling function *)
+ (pc: node) (**r program point in calling function *)
+ (rs: regset) (**r register state in calling function *)
+ (pr: predset), (**r predicate state of the calling function *)
+ stackframe.
+
+Inductive state : Type :=
+| State:
+ forall (stack: list stackframe) (**r call stack *)
+ (f: function) (**r current function *)
+ (sp: val) (**r stack pointer *)
+ (pc: node) (**r current program point in [c] *)
+ (rs: regset) (**r register state *)
+ (pr: predset) (**r predicate register state *)
+ (m: mem), (**r memory state *)
+ state
+| Callstate:
+ forall (stack: list stackframe) (**r call stack *)
+ (f: fundef) (**r function to call *)
+ (args: list val) (**r arguments to the call *)
+ (m: mem), (**r memory state *)
+ state
+| Returnstate:
+ forall (stack: list stackframe) (**r call stack *)
+ (v: val) (**r return value for the call *)
+ (m: mem), (**r memory state *)
+ state.
+
+Record instr_state := mk_instr_state {
+ is_rs: regset;
+ is_ps: predset;
+ is_mem: mem;
+ }.
+
+Definition genv := Genv.t fundef unit.
+
+Section RELSEM.
+
+ Context (ge: genv).
+
+ Definition find_function
+ (ros: reg + ident) (rs: regset) : option fundef :=
+ match ros with
+ | inl r => Genv.find_funct ge rs#r
+ | inr symb =>
+ match Genv.find_symbol ge symb with
+ | None => None
+ | Some b => Genv.find_funct_ptr ge b
+ end
+ end.
+
+ Inductive eval_pred: option pred_op -> instr_state -> instr_state -> instr_state -> Prop :=
+ | eval_pred_true:
+ forall i i' p,
+ eval_predf (is_ps i) p = true ->
+ eval_pred (Some p) i i' i'
+ | eval_pred_false:
+ forall i i' p,
+ eval_predf (is_ps i) p = false ->
+ eval_pred (Some p) i i' i
+ | eval_pred_none:
+ forall i i', eval_pred None i i' i.
+
+ Inductive step_instr: val -> instr_state -> instr -> instr_state -> Prop :=
+ | exec_FUnop:
+ forall sp ist,
+ step_instr sp ist FUnop ist
+ | exec_FUop:
+ forall op v res args rs m sp p ist pr,
+ eval_operation ge sp op rs##args m = Some v ->
+ eval_pred p (mk_instr_state rs pr m) (mk_instr_state (rs#res <- v) pr m) ist ->
+ step_instr sp (mk_instr_state rs pr m) (FUop p op args res) ist
+ | exec_FUsetpred:
+ forall sp rs pr m p c b args p' ist,
+ Op.eval_condition c rs##args m = Some b ->
+ eval_pred p' (mk_instr_state rs pr m) (mk_instr_state rs (pr#p <- b) m) ist ->
+ step_instr sp (mk_instr_state rs pr m) (FUsetpred p' c args p) ist.
+
+ Inductive step_instr_list: val -> instr_state -> list instr -> instr_state -> Prop :=
+ | exec_RBcons:
+ forall state i state' state'' instrs sp,
+ step_instr sp state i state' ->
+ step_instr_list sp state' instrs state'' ->
+ step_instr_list sp state (i :: instrs) state''
+ | exec_RBnil:
+ forall state sp,
+ step_instr_list sp state nil state.
+
+ Inductive step_instr_seq (sp : val)
+ : instr_state -> list (list instr) -> instr_state -> Prop :=
+ | exec_instr_seq_cons:
+ forall state i state' state'' instrs,
+ step_instr_list sp state i state' ->
+ step_instr_seq sp state' instrs state'' ->
+ step_instr_seq sp state (i :: instrs) state''
+ | exec_instr_seq_nil:
+ forall state,
+ step_instr_seq sp state nil state.
+
+ Inductive step_instr_block (sp : val)
+ : instr_state -> bblock_body -> instr_state -> Prop :=
+ | exec_instr_block_cons:
+ forall state i state' state'' instrs,
+ step_instr_seq sp state i state' ->
+ step_instr_block sp state' instrs state'' ->
+ step_instr_block sp state (i :: instrs) state''
+ | exec_instr_block_nil:
+ forall state,
+ step_instr_block sp state nil state.
+
+ Inductive step_cf_instr: state -> cf_instr -> trace -> state -> Prop :=
+ | exec_FUcall:
+ forall s f sp rs m res fd ros sig args pc pc' pr,
+ find_function ros rs = Some fd ->
+ funsig fd = sig ->
+ step_cf_instr (State s f sp pc rs pr m) (FUcall sig ros args res pc')
+ E0 (Callstate (Stackframe res f sp pc' rs pr :: s) fd rs##args m)
+ | exec_FUtailcall:
+ forall s f stk rs m sig ros args fd m' pc pr,
+ find_function ros rs = Some fd ->
+ funsig fd = sig ->
+ Mem.free m stk 0 f.(fn_stacksize) = Some m' ->
+ step_cf_instr (State s f (Vptr stk Ptrofs.zero) pc rs pr m) (FUtailcall sig ros args)
+ E0 (Callstate s fd rs##args m')
+ | exec_FUbuiltin:
+ forall s f sp rs m ef args res pc' vargs t vres m' pc pr,
+ eval_builtin_args ge (fun r => rs#r) sp m args vargs ->
+ external_call ef ge vargs m t vres m' ->
+ step_cf_instr (State s f sp pc rs pr m) (FUbuiltin ef args res pc')
+ t (State s f sp pc' (regmap_setres res vres rs) pr m')
+ | exec_FUcond:
+ forall s f sp rs m cond args ifso ifnot b pc pc' pr,
+ eval_condition cond rs##args m = Some b ->
+ pc' = (if b then ifso else ifnot) ->
+ step_cf_instr (State s f sp pc rs pr m) (FUcond cond args ifso ifnot)
+ E0 (State s f sp pc' rs pr m)
+ | exec_FUjumptable:
+ forall s f sp rs m arg tbl n pc pc' pr,
+ rs#arg = Vint n ->
+ list_nth_z tbl (Int.unsigned n) = Some pc' ->
+ step_cf_instr (State s f sp pc rs pr m) (FUjumptable arg tbl)
+ E0 (State s f sp pc' rs pr m)
+ | exec_FUreturn:
+ forall s f stk rs m or pc m' pr,
+ Mem.free m stk 0 f.(fn_stacksize) = Some m' ->
+ step_cf_instr (State s f (Vptr stk Ptrofs.zero) pc rs pr m) (FUreturn or)
+ E0 (Returnstate s (regmap_optget or Vundef rs) m')
+ | exec_FUgoto:
+ forall s f sp pc rs pr m pc',
+ step_cf_instr (State s f sp pc rs pr m) (FUgoto pc') E0 (State s f sp pc' rs pr m)
+ | exec_FUpred_cf:
+ forall s f sp pc rs pr m cf1 cf2 st' p t,
+ step_cf_instr (State s f sp pc rs pr m) (if eval_predf pr p then cf1 else cf2) t st' ->
+ step_cf_instr (State s f sp pc rs pr m) (FUpred_cf p cf1 cf2) t st'.
+
+ Inductive step: state -> trace -> state -> Prop :=
+ | exec_bblock:
+ forall s f sp pc rs rs' m m' t s' bb pr pr',
+ f.(fn_code)!pc = Some bb ->
+ step_instr_block sp (mk_instr_state rs pr m) bb.(bb_body) (mk_instr_state rs' pr' m') ->
+ step_cf_instr (State s f sp pc rs' pr' m') bb.(bb_exit) t s' ->
+ step (State s f sp pc rs pr m) t s'
+ | exec_function_internal:
+ forall s f args m m' stk,
+ Mem.alloc m 0 f.(fn_stacksize) = (m', stk) ->
+ step (Callstate s (Internal f) args m)
+ E0 (State s
+ f
+ (Vptr stk Ptrofs.zero)
+ f.(fn_entrypoint)
+ (init_regs args f.(fn_params))
+ (PMap.init false) m')
+ | exec_function_external:
+ forall s ef args res t m m',
+ external_call ef ge args m t res m' ->
+ step (Callstate s (External ef) args m)
+ t (Returnstate s res m')
+ | exec_return:
+ forall res f sp pc rs s vres m pr,
+ step (Returnstate (Stackframe res f sp pc rs pr :: s) vres m)
+ E0 (State s f sp pc (rs#res <- vres) pr m).
+
+End RELSEM.
+
+Inductive initial_state (p: program): state -> Prop :=
+| initial_state_intro: forall b f m0,
+ let ge := Genv.globalenv p in
+ Genv.init_mem p = Some m0 ->
+ Genv.find_symbol ge p.(prog_main) = Some b ->
+ Genv.find_funct_ptr ge b = Some f ->
+ funsig f = signature_main ->
+ initial_state p (Callstate nil f nil m0).
+
+Inductive final_state: state -> int -> Prop :=
+| final_state_intro: forall r m,
+ final_state (Returnstate nil (Vint r) m) r.
+
+Definition semantics (p: program) :=
+ Semantics step (initial_state p) final_state (Genv.globalenv p).
+
+Definition max_reg_bblock (m : positive) (pc : node) (bb : bblock) :=
+ let max_body := fold_left (fun x l => fold_left (fun x' l' => fold_left max_reg_instr l' x') l x) bb.(bb_body) m in
+ max_reg_cfi max_body bb.(bb_exit).
+
+Definition max_reg_function (f: function) :=
+ Pos.max
+ (PTree.fold max_reg_bblock f.(fn_code) 1%positive)
+ (Pos.max (fold_left Pos.max f.(fn_params) 1%positive)
+ (max_reg_resources f.(fn_funct_units))).
+
+Definition max_pc_function (f: function) : positive :=
+ PTree.fold (fun m pc i => (Pos.max m
+ (pc + match Zlength i.(bb_body)
+ with Z.pos p => p | _ => 1 end))%positive)
+ f.(fn_code) 1%positive.
diff --git a/src/hls/RTLParFUgen.v b/src/hls/RTLParFUgen.v
new file mode 100644
index 0000000..a104056
--- /dev/null
+++ b/src/hls/RTLParFUgen.v
@@ -0,0 +1,177 @@
+(*
+ * Vericert: Verified high-level synthesis.
+ * Copyright (C) 2021 Yann Herklotz <yann@yannherklotz.com>
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ *)
+
+Require Import Coq.micromega.Lia.
+
+Require Import compcert.common.AST.
+Require Import compcert.common.Errors.
+Require compcert.common.Globalenvs.
+Require Import compcert.lib.Integers.
+Require Import compcert.lib.Maps.
+
+Require Import vericert.common.Statemonad.
+Require Import vericert.common.Vericertlib.
+Require Import vericert.hls.AssocMap.
+Require Import vericert.hls.Predicate.
+Require Import vericert.hls.ValueInt.
+Require Import vericert.hls.Verilog.
+Require Import vericert.hls.RTLBlockInstr.
+Require Import vericert.hls.RTLPar.
+Require Import vericert.hls.RTLParFU.
+Require Import vericert.hls.FunctionalUnits.
+
+#[local] Open Scope error_monad_scope.
+
+Definition update {A: Type} (i: positive) (f: option A -> A) (pt: PTree.t A) :=
+ PTree.set i (f (pt ! i)) pt.
+
+Definition add_instr (instr_: instr) x :=
+ match x with Some i => instr_ :: i | None => instr_ :: nil end.
+
+Definition transl_instr (res: resources) (cycle: positive) (i: RTLBlockInstr.instr)
+ (li: Errors.res (list instr * PTree.t (list instr))):
+ Errors.res (list instr * PTree.t (list instr)) :=
+ do (instr_list, d_tree) <- li;
+ match i with
+ | RBnop => Errors.OK (FUnop :: instr_list, d_tree)
+ | RBop po op args d => Errors.OK (FUop po op args d :: instr_list, d_tree)
+ | RBload po chunk addr args d =>
+ match get_ram 0 res with
+ | Some (ri, r) =>
+ Errors.OK (FUop po Op.Onot (ram_u_en r::nil) (ram_u_en r)
+ :: FUop po (Op.Ointconst (Int.repr 0)) nil (ram_wr_en r)
+ :: FUop po (Op.Olea addr) args (ram_addr r)
+ :: FUop po (Op.Oshruimm (Int.repr 2)) ((ram_addr r)::nil) (ram_addr r)
+ :: instr_list, update (Pos.pred cycle)
+ (add_instr (FUop po Op.Omove (ram_d_out r::nil) d))
+ d_tree)
+ | _ => Errors.Error (Errors.msg "Could not find RAM")
+ end
+ | RBstore po chunk addr args d =>
+ match get_ram 0 res with
+ | Some (ri, r) =>
+ Errors.OK (FUop po Op.Onot (ram_u_en r::nil) (ram_u_en r)
+ :: FUop po (Op.Ointconst (Int.repr 1)) nil (ram_wr_en r)
+ :: FUop po Op.Omove (d::nil) (ram_d_in r)
+ :: FUop po (Op.Olea addr) args (ram_addr r)
+ :: FUop po (Op.Oshruimm (Int.repr 2)) ((ram_addr r)::nil) (ram_addr r)
+ :: instr_list, d_tree)
+ | _ => Errors.Error (Errors.msg "Could not find RAM")
+ end
+ | RBsetpred op c args p => Errors.OK (FUsetpred op c args p :: instr_list, d_tree)
+ end.
+
+Fixpoint transl_cf_instr (i: RTLBlockInstr.cf_instr): RTLParFU.cf_instr :=
+ match i with
+ | RBcall sig r args d n => FUcall sig r args d n
+ | RBtailcall sig r args => FUtailcall sig r args
+ | RBbuiltin ef args r n => FUbuiltin ef args r n
+ | RBcond c args n1 n2 => FUcond c args n1 n2
+ | RBjumptable r ns => FUjumptable r ns
+ | RBreturn r => FUreturn r
+ | RBgoto n => FUgoto n
+ | RBpred_cf po c1 c2 => FUpred_cf po (transl_cf_instr c1) (transl_cf_instr c2)
+ end.
+
+Definition list_split {A:Type} (l: list (Z * A)) : (list (Z * A)) * (list (Z * A)) :=
+ (filter (fun x => Z.eqb 0 (fst x)) l,
+ map (fun x => (Z.pred (fst x), snd x)) (filter (fun x => negb (Z.eqb 0 (fst x))) l)).
+
+Fixpoint map_error {A B : Type} (f : A -> res B) (l : list A) {struct l} : res (list B) :=
+ match l with
+ | nil => OK nil
+ | x::xs =>
+ do y <- f x ;
+ do ys <- map_error f xs ;
+ OK (y::ys)
+ end.
+
+Definition transl_op_chain_block (res: resources) (cycle: positive) (instrs: list RTLBlockInstr.instr)
+ (state: Errors.res (list (list instr) * PTree.t (list instr)))
+ : Errors.res (list (list instr) * PTree.t (list instr)) :=
+ do (li, tr) <- state;
+ do (li', tr') <- fold_right (transl_instr res cycle) (OK (nil, tr)) instrs;
+ OK (li' :: li, tr').
+
+(*Compute transl_op_chain_block initial_resources 10%nat (RBop None (Op.Ointconst (Int.repr 1)) nil 1%positive::RBnop::RBnop::RBnop::nil) (OK (nil, PTree.empty _)).*)
+
+Definition transl_par_block (res: resources) (cycle: positive) (instrs: list (list RTLBlockInstr.instr))
+ (state: Errors.res (list (list (list instr)) * PTree.t (list instr)))
+ : Errors.res (list (list (list instr)) * PTree.t (list instr)) :=
+ do (li, tr) <- state;
+ do (li', tr') <- fold_right (transl_op_chain_block res cycle) (OK (nil, tr)) instrs;
+ OK (li' :: li, tr').
+
+(*Compute transl_par_block initial_resources 10%nat ((RBop None (Op.Ointconst (Int.repr 1)) nil 1%positive::RBnop::nil)::(RBop None (Op.Ointconst (Int.repr 2)) nil 2%positive::RBnop::nil)::nil) (OK (((FUnop::nil)::nil)::nil, PTree.empty _)).*)
+
+Definition transl_seq_block (res: resources) (b: list (list RTLBlockInstr.instr))
+ (a: Errors.res (list (list (list instr)) * PTree.t (list instr) * positive)) :=
+ do (litr, n) <- a;
+ let (li, tr) := litr in
+ do (li', tr') <- transl_par_block res n b (OK (li, tr));
+ OK (li', tr', (n+1)%positive).
+
+Definition insert_extra (pt: PTree.t (list instr)) (curr: list (list instr))
+ (cycle_bb: (positive * list (list (list instr)))) :=
+ let (cycle, bb) := cycle_bb in
+ match pt ! cycle with
+ | Some instrs => ((cycle + 1)%positive, (curr ++ (map (fun x => x :: nil) instrs)) :: bb)
+ | None => ((cycle + 1)%positive, curr :: bb)
+ end.
+
+Definition transl_bb (res: resources) (bb: list RTLPar.bb): Errors.res RTLParFU.bblock_body :=
+ do (litr, n) <- fold_right (transl_seq_block res) (OK (nil, PTree.empty _, 1%positive)) bb;
+ let (li, tr) := litr in
+ OK (snd (fold_right (insert_extra tr) (1%positive, nil) li)).
+
+Definition transl_bblock (res: resources) (bb: RTLPar.bblock): Errors.res bblock :=
+ do bb' <- transl_bb res (RTLBlockInstr.bb_body bb);
+ OK (mk_bblock bb' (transl_cf_instr (RTLBlockInstr.bb_exit bb))).
+
+Definition error_map_ptree {A B: Type} (f: positive -> A -> res B) (pt: PTree.t A) :=
+ do ptl' <- map_error (fun x => do x' <- uncurry f x; OK (fst x, x')) (PTree.elements pt);
+ OK (PTree_Properties.of_list ptl').
+
+Definition transl_code (fu: resources) (c: RTLPar.code): res code :=
+ error_map_ptree (fun _ => transl_bblock fu) c.
+
+Definition transl_function (f: RTLPar.function): Errors.res RTLParFU.function :=
+ let max := RTLPar.max_reg_function f in
+ let fu := set_res (Ram (mk_ram
+ (Z.to_nat (RTLBlockInstr.fn_stacksize f))
+ (max+1)%positive
+ (max+3)%positive
+ (max+7)%positive
+ (max+2)%positive
+ (max+6)%positive
+ (max+4)%positive
+ (max+5)%positive
+ )) initial_resources in
+ do c' <- transl_code fu (RTLBlockInstr.fn_code f);
+ Errors.OK (mkfunction (RTLBlockInstr.fn_sig f)
+ (RTLBlockInstr.fn_params f)
+ (RTLBlockInstr.fn_stacksize f)
+ c'
+ fu
+ (RTLBlockInstr.fn_entrypoint f)).
+
+Definition transl_fundef p :=
+ transf_partial_fundef transl_function p.
+
+Definition transl_program (p : RTLPar.program) : Errors.res RTLParFU.program :=
+ transform_partial_program transl_fundef p.
diff --git a/src/hls/RTLPargen.v b/src/hls/RTLPargen.v
index ae4412b..214da6f 100644
--- a/src/hls/RTLPargen.v
+++ b/src/hls/RTLPargen.v
@@ -1,6 +1,6 @@
(*
* Vericert: Verified high-level synthesis.
- * Copyright (C) 2020-2021 Yann Herklotz <yann@yannherklotz.com>
+ * Copyright (C) 2020-2022 Yann Herklotz <yann@yannherklotz.com>
*
* 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
@@ -34,26 +34,25 @@ Require Import vericert.hls.Predicate.
Require Import vericert.hls.Abstr.
Import NE.NonEmptyNotation.
-(*|
-=================
-RTLPar Generation
-=================
-|*)
-
#[local] Open Scope positive.
#[local] Open Scope forest.
#[local] Open Scope pred_op.
(*|
+=========
+RTLPargen
+=========
+
Abstract Computations
=====================
-Define the abstract computation using the ``update`` function, which will set each register to its
-symbolic value. First we need to define a few helper functions to correctly translate the
-predicates.
+Define the abstract computation using the [update] function, which will set each
+register to its symbolic value. First we need to define a few helper functions
+to correctly translate the predicates.
|*)
-Fixpoint list_translation (l : list reg) (f : forest) {struct l} : list pred_expr :=
+Fixpoint list_translation (l : list reg) (f : forest) {struct l}
+ : list pred_expr :=
match l with
| nil => nil
| i :: l => (f # (Reg i)) :: (list_translation l f)
@@ -77,7 +76,8 @@ Definition merge'' x :=
| ((a, e), (b, el)) => (merge''' a b, Econs e el)
end.
-Definition map_pred_op {A B} (pf: option pred_op * (A -> B)) (pa: option pred_op * A): option pred_op * B :=
+Definition map_pred_op {A B} (pf: option pred_op * (A -> B))
+ (pa: option pred_op * A): option pred_op * B :=
match pa, pf with
| (p, a), (p', f) => (merge''' p p', f a)
end.
@@ -86,8 +86,8 @@ Definition predicated_prod {A B: Type} (p1: predicated A) (p2: predicated B) :=
NE.map (fun x => match x with ((a, b), (c, d)) => (Pand a c, (b, d)) end)
(NE.non_empty_prod p1 p2).
-Definition predicated_map {A B: Type} (f: A -> B) (p: predicated A): predicated B :=
- NE.map (fun x => (fst x, f (snd x))) p.
+Definition predicated_map {A B: Type} (f: A -> B) (p: predicated A)
+ : predicated B := NE.map (fun x => (fst x, f (snd x))) p.
(*map (fun x => (fst x, Econs (snd x) Enil)) pel*)
Definition merge' (pel: pred_expr) (tpel: predicated expression_list) :=
@@ -99,16 +99,20 @@ Fixpoint merge (pel: list pred_expr): predicated expression_list :=
| a :: b => merge' a (merge b)
end.
-Definition map_predicated {A B} (pf: predicated (A -> B)) (pa: predicated A): predicated B :=
+Definition map_predicated {A B} (pf: predicated (A -> B)) (pa: predicated A)
+ : predicated B :=
predicated_map (fun x => (fst x) (snd x)) (predicated_prod pf pa).
-Definition predicated_apply1 {A B} (pf: predicated (A -> B)) (pa: A): predicated B :=
+Definition predicated_apply1 {A B} (pf: predicated (A -> B)) (pa: A)
+ : predicated B :=
NE.map (fun x => (fst x, (snd x) pa)) pf.
-Definition predicated_apply2 {A B C} (pf: predicated (A -> B -> C)) (pa: A) (pb: B): predicated C :=
+Definition predicated_apply2 {A B C} (pf: predicated (A -> B -> C)) (pa: A)
+ (pb: B): predicated C :=
NE.map (fun x => (fst x, (snd x) pa pb)) pf.
-Definition predicated_apply3 {A B C D} (pf: predicated (A -> B -> C -> D)) (pa: A) (pb: B) (pc: C): predicated D :=
+Definition predicated_apply3 {A B C D} (pf: predicated (A -> B -> C -> D))
+ (pa: A) (pb: B) (pc: C): predicated D :=
NE.map (fun x => (fst x, (snd x) pa pb pc)) pf.
Definition predicated_from_opt {A: Type} (p: option pred_op) (a: A) :=
@@ -132,23 +136,34 @@ Fixpoint NEapp {A} (l m: NE.non_empty A) :=
| a ::| b => a ::| NEapp b m
end.
-Definition app_predicated {A: Type} (a b: predicated A) :=
+Definition app_predicated' {A: Type} (a b: predicated A) :=
let negation := ¬ (NEfold_left (fun a b => a ∨ (fst b)) b ⟂) in
- NEapp (NE.map (fun x => (negation ∧ (fst x), snd x)) a) b.
+ NEapp (NE.map (fun x => (negation ∧ fst x, snd x)) a) b.
+
+Definition app_predicated {A: Type} (p: option pred_op) (a b: predicated A) :=
+ match p with
+ | Some p' => NEapp (NE.map (fun x => (¬ p' ∧ fst x, snd x)) a)
+ (NE.map (fun x => (p' ∧ fst x, snd x)) b)
+ | None => b
+ end.
+
+Definition pred_ret {A: Type} (a: A) : predicated A :=
+ NE.singleton (T, a).
(*|
Update Function
---------------
-The ``update`` function will generate a new forest given an existing forest and a new instruction,
-so that it can evaluate a symbolic expression by folding over a list of instructions. The main
-problem is that predicates need to be merged as well, so that:
+The ``update`` function will generate a new forest given an existing forest and
+a new instruction, so that it can evaluate a symbolic expression by folding over
+a list of instructions. The main problem is that predicates need to be merged
+as well, so that:
1. The predicates are *independent*.
2. The expression assigned to the register should still be correct.
-This is done by multiplying the predicates together, and assigning the negation of the expression to
-the other predicates.
+This is done by multiplying the predicates together, and assigning the negation
+of the expression to the other predicates.
|*)
Definition update (f : forest) (i : instr) : forest :=
@@ -156,34 +171,38 @@ Definition update (f : forest) (i : instr) : forest :=
| RBnop => f
| RBop p op rl r =>
f # (Reg r) <-
- (app_predicated
+ (app_predicated p
(f # (Reg r))
- (map_predicated (predicated_from_opt p (Eop op)) (merge (list_translation rl f))))
+ (map_predicated (pred_ret (Eop op)) (merge (list_translation rl f))))
| RBload p chunk addr rl r =>
f # (Reg r) <-
- (app_predicated
+ (app_predicated p
(f # (Reg r))
(map_predicated
- (map_predicated (predicated_from_opt p (Eload chunk addr)) (merge (list_translation rl f)))
+ (map_predicated (pred_ret (Eload chunk addr))
+ (merge (list_translation rl f)))
(f # Mem)))
| RBstore p chunk addr rl r =>
f # Mem <-
- (app_predicated
- (f # (Reg r))
+ (app_predicated p
+ (f # Mem)
(map_predicated
(map_predicated
- (predicated_apply2 (map_predicated (predicated_from_opt p Estore) (f # (Reg r))) chunk addr)
+ (predicated_apply2 (map_predicated (pred_ret Estore)
+ (f # (Reg r))) chunk addr)
(merge (list_translation rl f))) (f # Mem)))
| RBsetpred p' c args p =>
f # (Pred p) <-
- (app_predicated
+ (app_predicated p'
(f # (Pred p))
- (map_predicated (predicated_from_opt p' (Esetpred c)) (merge (list_translation args f))))
+ (map_predicated (pred_ret (Esetpred c))
+ (merge (list_translation args f))))
end.
(*|
-Implementing which are necessary to show the correctness of the translation validation by showing
-that there aren't any more effects in the resultant RTLPar code than in the RTLBlock code.
+Implementing which are necessary to show the correctness of the translation
+validation by showing that there aren't any more effects in the resultant RTLPar
+code than in the RTLBlock code.
Get a sequence from the basic block.
|*)
@@ -195,19 +214,20 @@ Fixpoint abstract_sequence (f : forest) (b : list instr) : forest :=
end.
(*|
-Check equivalence of control flow instructions. As none of the basic blocks should have been moved,
-none of the labels should be different, meaning the control-flow instructions should match exactly.
+Check equivalence of control flow instructions. As none of the basic blocks
+should have been moved, none of the labels should be different, meaning the
+control-flow instructions should match exactly.
|*)
Definition check_control_flow_instr (c1 c2: cf_instr) : bool :=
if cf_instr_eq c1 c2 then true else false.
(*|
-We define the top-level oracle that will check if two basic blocks are equivalent after a scheduling
-transformation.
+We define the top-level oracle that will check if two basic blocks are
+equivalent after a scheduling transformation.
|*)
-Definition empty_trees (bb: RTLBlock.bb) (bbt: RTLPar.bb) : bool :=
+Definition empty_trees (bb: list RTLBlock.bb) (bbt: list RTLPar.bb) : bool :=
match bb with
| nil =>
match bbt with
@@ -253,7 +273,8 @@ Top-level Functions
Parameter schedule : RTLBlock.function -> RTLPar.function.
-Definition transl_function (f: RTLBlock.function) : Errors.res RTLPar.function :=
+Definition transl_function (f: RTLBlock.function)
+ : Errors.res RTLPar.function :=
let tfcode := fn_code (schedule f) in
if check_scheduled_trees f.(fn_code) tfcode then
Errors.OK (mkfunction f.(fn_sig)
@@ -262,7 +283,8 @@ Definition transl_function (f: RTLBlock.function) : Errors.res RTLPar.function :
tfcode
f.(fn_entrypoint))
else
- Errors.Error (Errors.msg "RTLPargen: Could not prove the blocks equivalent.").
+ Errors.Error
+ (Errors.msg "RTLPargen: Could not prove the blocks equivalent.").
Definition transl_fundef := transf_partial_fundef transl_function.
diff --git a/src/hls/RTLPargenproof.v b/src/hls/RTLPargenproof.v
index df0615a..215aef5 100644
--- a/src/hls/RTLPargenproof.v
+++ b/src/hls/RTLPargenproof.v
@@ -1,6 +1,6 @@
(*
* Vericert: Verified high-level synthesis.
- * Copyright (C) 2021 Yann Herklotz <yann@yannherklotz.com>
+ * Copyright (C) 2020-2022 Yann Herklotz <yann@yannherklotz.com>
*
* 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
@@ -37,6 +37,17 @@ Require Import vericert.hls.Abstr.
#[local] Open Scope forest.
#[local] Open Scope pred_op.
+(*|
+==============
+RTLPargenproof
+==============
+
+RTLBlock to abstract translation
+================================
+
+Correctness of translation from RTLBlock to the abstract interpretation language.
+|*)
+
(*Definition is_regs i := match i with mk_instr_state rs _ => rs end.
Definition is_mem i := match i with mk_instr_state _ m => m end.
@@ -46,13 +57,6 @@ Inductive state_lessdef : instr_state -> instr_state -> Prop :=
(forall x, rs1 !! x = rs2 !! x) ->
state_lessdef (mk_instr_state rs1 m1) (mk_instr_state rs2 m1).
-(*|
-RTLBlock to abstract translation
---------------------------------
-
-Correctness of translation from RTLBlock to the abstract interpretation language.
-|*)
-
Ltac inv_simp :=
repeat match goal with
| H: exists _, _ |- _ => inv H
@@ -742,7 +746,11 @@ Lemma sem_update :
match_states st' st''' ->
@step_instr A ge sp st''' x st'' ->
exists tst, sem (mk_ctx st sp ge) (update f x) tst /\ match_states st'' tst.
-Proof. Admitted.
+Proof.
+ intros. destruct x.
+ - inv H1. econstructor. simplify. eauto. symmetry; auto.
+ - inv H1. inv H0. econstructor.
+ Admitted.
Lemma rtlblock_trans_correct :
forall bb ge sp st st',
@@ -804,8 +812,8 @@ Inductive match_states: RTLBlock.state -> RTLPar.state -> Prop :=
(STACKS: list_forall2 match_stackframes sf sf')
(REG: forall x, rs !! x = rs' !! x)
(REG: forall x, ps !! x = ps' !! x),
- match_states (State sf f sp pc rs ps m)
- (State sf' tf sp pc rs' ps' m)
+ match_states (State sf f sp pc nil rs ps m)
+ (State sf' tf sp pc nil rs' ps' m)
| match_returnstate:
forall stack stack' v m
(STACKS: list_forall2 match_stackframes stack stack'),
@@ -1092,7 +1100,7 @@ Proof. induction 2; try rewrite H; eauto with barg. Qed.
eauto. eauto. simplify. eauto. eauto. }
{ unfold bind in *. inv TRANSL0. clear Learn. inv H0. destruct_match; crush.
inv H2. unfold transl_function in Heqr. destruct_match; crush.
- inv Heqr.
+ inv Heqr.
repeat econstructor; eauto.
unfold bind in *. destruct_match; crush. }
{ inv TRANSL0. repeat econstructor; eauto using Events.external_call_symbols_preserved, symbols_preserved, senv_preserved, Events.E0_right. }
diff --git a/src/hls/Sat.v b/src/hls/Sat.v
index b7596f6..428c176 100644
--- a/src/hls/Sat.v
+++ b/src/hls/Sat.v
@@ -119,7 +119,6 @@ Lemma satLit_contra : forall s l a cl,
-> satClause cl a.
unfold satLit, upd; simpl; intros.
destruct (eq_nat_dec (snd l) (snd l)); intuition.
- assert False; intuition.
Qed.
#[local] Hint Resolve satLit_contra : core.
@@ -287,6 +286,7 @@ Lemma unitClauseTrue : forall l a fm,
induction fm; intuition.
inversion H.
inversion H; subst; simpl in H0; intuition.
+ apply IHfm; eauto. inv H0. eauto.
Qed.
#[local] Hint Resolve unitClauseTrue : core.
diff --git a/src/hls/Schedule.ml b/src/hls/Schedule.ml
index c5443c7..70395e7 100644
--- a/src/hls/Schedule.ml
+++ b/src/hls/Schedule.ml
@@ -1,6 +1,6 @@
(*
* Vericert: Verified high-level synthesis.
- * Copyright (C) 2020 Yann Herklotz <yann@yannherklotz.com>
+ * Copyright (C) 2020-2022 Yann Herklotz <yann@yannherklotz.com>
*
* 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
@@ -289,6 +289,7 @@ let comb_delay = function
| _ -> 1
let pipeline_stages = function
+ | RBload _ -> 2
| RBop (_, op, _, _) ->
(match op with
| Odiv -> 32
@@ -304,7 +305,7 @@ let add_dep map i tree dfg curr =
| None -> dfg
| Some ip ->
let ipv = (List.nth map ip) in
- DFG.add_edge_e dfg (ipv, comb_delay (snd ipv), List.nth map i)
+ DFG.add_edge_e dfg (ipv, comb_delay (snd (List.nth map i)), List.nth map i)
(** This function calculates the dependencies of each instruction. The nodes correspond to previous
registers that were allocated and show which instruction caused it.
@@ -327,6 +328,7 @@ let accumulate_RAW_deps map dfg curr =
match curr with
| RBop (op, _, rs, dst) -> acc_dep_instruction rs dst
| RBload (op, _mem, _addr, rs, dst) -> acc_dep_instruction rs dst
+ | RBsetpred (_op, _mem, rs, _p) -> acc_dep_instruction_nodst rs
| RBstore (op, _mem, _addr, rs, src) -> acc_dep_instruction_nodst (src :: rs)
| _ -> (i + 1, dst_map, graph)
@@ -407,7 +409,7 @@ let accumulate_WAW_mem_deps instrs dfg curri =
| RBstore (_, _, _, _, _) -> (
match next_store 0 (take i instrs |> List.rev) with
| None -> dfg
- | Some d -> DFG.add_edge dfg (gen_vertex instrs (i - d - 1)) (gen_vertex instrs i) )
+ | Some d -> DFG.add_edge dfg (gen_vertex instrs (i - d - 1)) (gen_vertex instrs i))
| _ -> dfg
(** Predicate dependencies. *)
@@ -424,6 +426,7 @@ let get_predicate = function
| RBop (p, _, _, _) -> p
| RBload (p, _, _, _, _) -> p
| RBstore (p, _, _, _, _) -> p
+ | RBsetpred (p, _, _, _) -> p
| _ -> None
let rec next_setpred p i = function
@@ -447,6 +450,7 @@ let rec next_preduse p i instr=
| RBload (Some p', _, _, _, _) :: rst -> next p' rst
| RBstore (Some p', _, _, _, _) :: rst -> next p' rst
| RBop (Some p', _, _, _) :: rst -> next p' rst
+ | RBsetpred (Some p', _, _, _) :: rst -> next p' rst
| _ :: rst -> next_load (i + 1) rst
let accumulate_RAW_pred_deps instrs dfg curri =
@@ -571,6 +575,18 @@ let gather_bb_constraints debug bb =
let encode_var bbn n i = { sv_type = VarType (bbn, n); sv_num = i }
let encode_bb bbn i = { sv_type = BBType bbn; sv_num = i }
+let add_initial_sv n dfg constr =
+ let add_initial_sv' (i, instr) g =
+ let pipes = pipeline_stages instr in
+ if pipes > 0 then
+ List.init pipes (fun i' -> i')
+ |> List.fold_left (fun g i' ->
+ G.add_edge_e g (encode_var n i i', -1, encode_var n i (i'+1))
+ ) g
+ else g
+ in
+ DFG.fold_vertex add_initial_sv' dfg constr
+
let add_super_nodes n dfg =
DFG.fold_vertex (function v1 -> fun g ->
(if DFG.in_degree dfg v1 = 0
@@ -578,12 +594,14 @@ let add_super_nodes n dfg =
else g) |>
(fun g' ->
if DFG.out_degree dfg v1 = 0
- then G.add_edge_e g' (encode_var n (fst v1) 0, 0, encode_bb n 1)
+ then G.add_edge_e g' (encode_var n (fst v1) (pipeline_stages (snd v1)),
+ 0, encode_bb n 1)
else g')) dfg
let add_data_deps n =
- DFG.fold_edges_e (function ((i1, _), l, (i2, _)) -> fun g ->
- G.add_edge_e g (encode_var n i1 0, 0, encode_var n i2 0)
+ DFG.fold_edges_e (function ((i1, instr1), _, (i2, _)) -> fun g ->
+ let end_sv = pipeline_stages instr1 in
+ G.add_edge_e g (encode_var n i1 end_sv, 0, encode_var n i2 0)
)
let add_ctrl_deps n succs constr =
@@ -607,17 +625,24 @@ let negate_graph constr =
DFG.add_edge_e g (v1, -e, v2)
) constr DFG.empty
-let add_cycle_constr max n dfg constr =
+let add_cycle_constr maxf n dfg constr =
let negated_dfg = negate_graph dfg in
+ let max_initial_del = DFG.fold_vertex (fun v1 g ->
+ if DFG.in_degree dfg v1 = 0
+ then max g (comb_delay (snd v1))
+ else g) dfg 0 in
let longest_path v = BFDFG.all_shortest_paths negated_dfg v
- |> BFDFG.H.to_seq |> List.of_seq in
- let constrained_paths = List.filter (function (v, m) -> - m > max) in
+ |> BFDFG.H.to_seq |> List.of_seq
+ |> List.map (function (x, y) -> (x, y - max_initial_del)) in
+ let constrained_paths = List.filter (function (_, m) -> - m > maxf) in
List.fold_left (fun g -> function (v, v', w) ->
G.add_edge_e g (encode_var n (fst v) 0,
- - (int_of_float (Float.ceil (Float.div (float_of_int w) (float_of_int max))) - 1),
+ - (int_of_float (Float.ceil (Float.div (float_of_int w) (float_of_int maxf))) - 1),
encode_var n (fst v') 0)
) constr (DFG.fold_vertex (fun v l ->
- List.append l (longest_path v |> constrained_paths
+ List.append l (longest_path v (*|> (function l -> List.iter (function (a, x) ->
+ printf "c: %d %d\n" (fst a) x) l; l)*) |> constrained_paths (* |> (function l -> List.iter (function (a, x) ->
+ printf "%d %d\n" (fst a) x) l; l)*)
|> List.map (function (v', w) -> (v, v', - w)))
) dfg [])
@@ -671,6 +696,7 @@ let gather_cfg_constraints c constr curr =
| None -> assert false
| Some { bb_exit = ctrl; _ } ->
add_super_nodes n dfg constr
+ |> add_initial_sv n dfg
|> add_data_deps n dfg
|> add_ctrl_deps n (successors_instr ctrl
|> List.map P.to_int
@@ -703,25 +729,32 @@ let print_lp constr =
let update_schedule v = function Some l -> Some (v :: l) | None -> Some [ v ]
-let parse_soln tree s =
+let parse_soln (tree, bbtree) s =
let r = Str.regexp "var\\([0-9]+\\)n\\([0-9]+\\)_0[ ]+\\([0-9]+\\)" in
- if Str.string_match r s 0 then
- IMap.update
- (Str.matched_group 1 s |> int_of_string)
- (update_schedule
- ( Str.matched_group 2 s |> int_of_string,
- Str.matched_group 3 s |> int_of_string ))
- tree
- else tree
+ let bb = Str.regexp "bb\\([0-9]+\\)_\\([0-9]+\\)[ ]+\\([0-9]+\\)" in
+ let upd s = IMap.update
+ (Str.matched_group 1 s |> int_of_string)
+ (update_schedule
+ ( Str.matched_group 2 s |> int_of_string,
+ Str.matched_group 3 s |> int_of_string ))
+ in
+ if Str.string_match r s 0
+ then (upd s tree, bbtree)
+ else
+ (if Str.string_match bb s 0
+ then (tree, upd s bbtree)
+ else (tree, bbtree))
let solve_constraints constr =
- let oc = open_out "lpsolve.txt" in
+ let (fn, oc) = Filename.open_temp_file "vericert_" "_lp_solve" in
fprintf oc "%s\n" (print_lp constr);
close_out oc;
- Str.split (Str.regexp_string "\n") (read_process "lp_solve lpsolve.txt")
- |> drop 3
- |> List.fold_left parse_soln IMap.empty
+ let res = Str.split (Str.regexp_string "\n") (read_process ("lp_solve " ^ fn))
+ |> drop 3
+ |> List.fold_left parse_soln (IMap.empty, IMap.empty)
+ in
+ (*Sys.remove fn;*) res
let subgraph dfg l =
let dfg' = List.fold_left (fun g v -> DFG.add_vertex g v) DFG.empty l in
@@ -763,20 +796,35 @@ let all_dfs dfg =
if check_in el a then a else
(DFGDfs.fold_component (fun v l -> v :: l) [] dfg' el) :: a) [] roots
+let range s e =
+ List.init (e - s) (fun i -> i)
+ |> List.map (fun x -> x + s)
+
(** Should generate the [RTLPar] code based on the input [RTLBlock] description. *)
-let transf_rtlpar c c' (schedule : (int * int) list IMap.t) =
+let transf_rtlpar c c' schedule =
let f i bb : RTLPar.bblock =
match bb with
| { bb_body = []; bb_exit = c } -> { bb_body = []; bb_exit = c }
| { bb_body = bb_body'; bb_exit = ctrl_flow } ->
let dfg = match PTree.get i c' with None -> assert false | Some x -> x in
- let i_sched = IMap.find (P.to_int i) schedule in
+ let bb_st_e =
+ let m = IMap.find (P.to_int i) (snd schedule) in
+ (List.assq 0 m, List.assq 1 m) in
+ let i_sched = IMap.find (P.to_int i) (fst schedule) in
let i_sched_tree =
List.fold_left combine_bb_schedule IMap.empty i_sched
in
let body = IMap.to_seq i_sched_tree |> List.of_seq |> List.map snd
|> List.map (List.map (fun x -> (x, List.nth bb_body' x)))
in
+ let body2 = List.fold_left (fun x b ->
+ match IMap.find_opt b i_sched_tree with
+ | Some i -> i :: x
+ | None -> [] :: x
+ ) [] (range (fst bb_st_e) (snd bb_st_e + 1))
+ |> List.map (List.map (fun x -> (x, List.nth bb_body' x)))
+ |> List.rev
+ in
(*let final_body = List.map (fun x -> subgraph dfg x |> order_instr) body in*)
let final_body2 = List.map (fun x -> subgraph dfg x
|> (fun x ->
@@ -784,7 +832,9 @@ let transf_rtlpar c c' (schedule : (int * int) list IMap.t) =
|> List.map (subgraph x)
|> List.map (fun y ->
TopoDFG.fold (fun i l -> snd i :: l) y []
- |> List.rev))) body
+ |> List.rev))) body2
+ (*|> (fun x -> TopoDFG.fold (fun i l -> snd i :: l) x [])
+ |> List.rev) body2*)
in
{ bb_body = final_body2;
bb_exit = ctrl_flow
diff --git a/src/hls/ValueInt.v b/src/hls/ValueInt.v
index e434abc..06b5630 100644
--- a/src/hls/ValueInt.v
+++ b/src/hls/ValueInt.v
@@ -22,22 +22,31 @@ From compcert Require Import lib.Integers common.Values.
From vericert Require Import Vericertlib.
(* end hide *)
-(** * Value
+(*|
+=====
+Value
+=====
-A [value] is a bitvector with a specific size. We are using the implementation
+A ``value`` is a bitvector with a specific size. We are using the implementation
of the bitvector by mit-plv/bbv, because it has many theorems that we can reuse.
-However, we need to wrap it with an [Inductive] so that we can specify and match
-on the size of the [value]. This is necessary so that we can easily store
-[value]s of different sizes in a list or in a map.
+However, we need to wrap it with an ``Inductive`` so that we can specify and
+match on the size of the ``value``. This is necessary so that we can easily
+store ``value`` of different sizes in a list or in a map.
-Using the default [word], this would not be possible, as the size is part of the type. *)
+Using the default ``word``, this would not be possible, as the size is part of
+the type.
+|*)
Definition value : Type := int.
-(** ** Value conversions
+(*|
+Value conversions
+=================
-Various conversions to different number types such as [N], [Z], [positive] and
-[int], where the last one is a theory of integers of powers of 2 in CompCert. *)
+Various conversions to different number types such as ``N``, ``Z``, ``positive``
+and ``int``, where the last one is a theory of integers of powers of 2 in
+CompCert.
+|*)
Definition valueToNat (v : value) : nat :=
Z.to_nat (Int.unsigned v).
@@ -83,10 +92,12 @@ Definition valToValue (v : Values.val) : option value :=
| _ => None
end.
-(** Convert a [value] to a [bool], so that choices can be made based on the
-result. This is also because comparison operators will give back [value] instead
-of [bool], so if they are in a condition, they will have to be converted before
-they can be used. *)
+(*|
+Convert a ``value`` to a ``bool``, so that choices can be made based on the
+result. This is also because comparison operators will give back ``value``
+instead of ``bool``, so if they are in a condition, they will have to be
+converted before they can be used.
+|*)
Definition valueToBool (v : value) : bool :=
if Z.eqb (uvalueToZ v) 0 then false else true.
@@ -94,7 +105,10 @@ Definition valueToBool (v : value) : bool :=
Definition boolToValue (b : bool) : value :=
natToValue (if b then 1 else 0).
-(** ** Arithmetic operations *)
+(*|
+Arithmetic operations
+---------------------
+|*)
Inductive val_value_lessdef: val -> value -> Prop :=
| val_value_lessdef_int:
diff --git a/src/hls/Verilog.v b/src/hls/Verilog.v
index cee1d60..72140cd 100644
--- a/src/hls/Verilog.v
+++ b/src/hls/Verilog.v
@@ -142,23 +142,28 @@ Definition nonblock_reg (r : reg) (asr : reg_associations) (v : value) :=
Inductive scl_decl : Type := VScalar (sz : nat).
Inductive arr_decl : Type := VArray (sz : nat) (ln : nat).
-(** * Verilog AST
+(*|
+Verilog AST
+===========
The Verilog AST is defined here, which is the target language of the
compilation.
-** Value
+Value
+-----
-The Verilog [value] is a bitvector containg a size and the actual bitvector. In
-this case, the [Word.word] type is used as many theorems about that bitvector
-have already been proven. *)
+The Verilog ``value`` is a bitvector containg a size and the actual
+bitvector. In this case, the ``Word.word`` type is used as many theorems about
+that bitvector have already been proven.
-(** ** Binary Operators
+Binary Operators
+----------------
These are the binary operations that can be represented in Verilog. Ideally,
multiplication and division would be done by custom modules which could al so be
scheduled properly. However, for now every Verilog operator is assumed to take
-one clock cycle. *)
+one clock cycle.
+|*)
Inductive binop : Type :=
| Vadd : binop (** addition (binary [+]) *)
@@ -184,15 +189,21 @@ Inductive binop : Type :=
| Vshl : binop (** shift left ([<<]) *)
| Vshr : binop (** shift right ([>>>]) *)
| Vshru : binop. (** shift right unsigned ([>>]) *)
-(*| Vror : binop (** shift right unsigned ([>>]) *)*)
+(* Vror : binop (** shift right unsigned ([>>]) *)*)
-(** ** Unary Operators *)
+(*|
+Unary Operators
+---------------
+|*)
Inductive unop : Type :=
| Vneg (** negation ([-]) *)
| Vnot. (** not operation [!] *)
-(** ** Expressions *)
+(*|
+Expressions
+-----------
+|*)
Inductive expr : Type :=
| Vlit : value -> expr
@@ -207,7 +218,10 @@ Inductive expr : Type :=
Definition posToExpr (p : positive) : expr :=
Vlit (posToValue p).
-(** ** Statements *)
+(*|
+Statements
+----------
+|*)
Inductive stmnt : Type :=
| Vskip : stmnt
@@ -220,14 +234,17 @@ with stmnt_expr_list : Type :=
| Stmntnil : stmnt_expr_list
| Stmntcons : expr -> stmnt -> stmnt_expr_list -> stmnt_expr_list.
-(** ** Edges
+(*|
+Edges
+-----
These define when an always block should be triggered, for example if the always
block should be triggered synchronously at the clock edge, or asynchronously for
combinational logic.
-[edge] is not part of [stmnt] in this formalisation because is closer to the
-semantics that are used. *)
+``edge`` is not part of ``stmnt`` in this formalisation because is closer to the
+semantics that are used.
+|*)
Inductive edge : Type :=
| Vposedge : reg -> edge
@@ -235,11 +252,15 @@ Inductive edge : Type :=
| Valledge : edge
| Voredge : edge -> edge -> edge.
-(** ** Module Items
+(*|
+Module Items
+------------
-Module items can either be declarations ([Vdecl]) or always blocks ([Valways]).
-The declarations are always register declarations as combinational logic can be
-done using combinational always block instead of continuous assignments. *)
+Module items can either be declarations (``Vdecl``) or always blocks
+(``Valways``). The declarations are always register declarations as
+combinational logic can be done using combinational always block instead of
+continuous assignments.
+|*)
Inductive io : Type :=
| Vinput : io
@@ -256,16 +277,17 @@ Inductive module_item : Type :=
| Valways_ff : edge -> stmnt -> module_item
| Valways_comb : edge -> stmnt -> module_item.
-(** The main module type containing all the important control signals
+(*|
+The main module type containing all the important control signals
-- [mod_start] If set, starts the computations in the module.
-- [mod_reset] If set, reset the state in the module.
-- [mod_clk] The clock that controls the computation in the module.
-- [mod_args] The arguments to the module.
-- [mod_finish] Bit that is set if the result is ready.
-- [mod_return] The return value that was computed.
-- [mod_body] The body of the module, including the state machine.
-*)
+:mod_start: If set, starts the computations in the module.
+:mod_reset: If set, reset the state in the module.
+:mod_clk: The clock that controls the computation in the module.
+:mod_args: The arguments to the module.
+:mod_finish: Bit that is set if the result is ready.
+:mod_return: The return value that was computed.
+:mod_body: The body of the module, including the state machine.
+|*)
Record module : Type := mkmodule {
mod_start : reg;
@@ -273,7 +295,8 @@ Record module : Type := mkmodule {
mod_clk : reg;
mod_finish : reg;
mod_return : reg;
- mod_st : reg; (**r Variable that defines the current state, it should be internal. *)
+ mod_st : reg; (**r Variable that defines the current state,
+ it should be internal. *)
mod_stk : reg;
mod_stk_len : nat;
mod_args : list reg;
@@ -285,34 +308,39 @@ Definition fundef := AST.fundef module.
Definition program := AST.program fundef unit.
-(** Convert a [positive] to an expression directly, setting it to the right
- size. *)
+(*|
+Convert a ``positive`` to an expression directly, setting it to the right size.
+|*)
+
Definition posToLit (p : positive) : expr :=
Vlit (posToValue p).
Definition fext := unit.
Definition fextclk := nat -> fext.
-(** ** State
+(*|
+State
+-----
+
+The ``state`` contains the following items:
-The [state] contains the following items:
-n
-- Current [module] that is being worked on, so that the state variable can be
-retrieved and set appropriately.
-- Current [module_item] which is being worked on.
-- A contiunation ([cont]) which defines what to do next. The option is to
- either evaluate another module item or go to the next clock cycle. Finally
- it could also end if the finish flag of the module goes high.
+- Current ``module`` that is being worked on, so that the state variable can be
+ retrieved and set appropriately.
+- Current ``module_item`` which is being worked on.
+- A contiunation (``cont``) which defines what to do next. The option is to
+ either evaluate another module item or go to the next clock cycle. Finally it
+ could also end if the finish flag of the module goes high.
- Association list containing the blocking assignments made, or assignments made
in previous clock cycles.
- Nonblocking association list containing all the nonblocking assignments made
in the current module.
- The environment containing values for the input.
-- The program counter which determines the value for the state in this version of
- Verilog, as the Verilog was generated by the RTL, which means that we have to
- make an assumption about how it looks. In this case, that it contains state
- which determines which part of the Verilog is executed. This is then the part
- of the Verilog that should match with the RTL. *)
+- The program counter which determines the value for the state in this version
+ of Verilog, as the Verilog was generated by the RTL, which means that we have
+ to make an assumption about how it looks. In this case, that it contains
+ state which determines which part of the Verilog is executed. This is then
+ the part of the Verilog that should match with the RTL.
+|*)
Inductive stackframe : Type :=
Stackframe :
@@ -432,7 +460,9 @@ Definition handle_def {A : Type} (a : A) (val : option A)
Local Open Scope error_monad_scope.
-(** Return the location of the lhs of an assignment. *)
+(*|
+Return the location of the lhs of an assignment.
+|*)
Inductive location : Type :=
| LocReg (_ : reg)
diff --git a/src/hls/Veriloggen.v b/src/hls/Veriloggen.v
index aba2293..c07e18d 100644
--- a/src/hls/Veriloggen.v
+++ b/src/hls/Veriloggen.v
@@ -25,6 +25,7 @@ Require Import vericert.hls.AssocMap.
Require Import vericert.hls.HTL.
Require Import vericert.hls.ValueInt.
Require Import vericert.hls.Verilog.
+Require Import vericert.hls.FunctionalUnits.
Definition transl_list_fun (a : node * Verilog.stmnt) :=
let (n, stmnt) := a in
@@ -56,9 +57,8 @@ Definition inst_ram clk ram :=
Definition transl_module (m : HTL.module) : Verilog.module :=
let case_el_ctrl := list_to_stmnt (transl_list (PTree.elements m.(mod_controllogic))) in
let case_el_data := list_to_stmnt (transl_list (PTree.elements m.(mod_datapath))) in
- match m.(HTL.mod_ram) with
- | Some ram =>
- let body :=
+ let ram := m.(HTL.mod_ram) in
+ let body :=
Valways (Vposedge m.(HTL.mod_clk)) (Vcond (Vbinop Veq (Vvar m.(HTL.mod_reset)) (Vlit (ZToValue 1)))
(Vnonblock (Vvar m.(HTL.mod_st)) (Vlit (posToValue m.(HTL.mod_entrypoint))))
(Vcase (Vvar m.(HTL.mod_st)) case_el_ctrl (Some Vskip)))
@@ -72,31 +72,11 @@ Definition transl_module (m : HTL.module) : Verilog.module :=
m.(HTL.mod_finish)
m.(HTL.mod_return)
m.(HTL.mod_st)
- m.(HTL.mod_stk)
- m.(HTL.mod_stk_len)
+ m.(HTL.mod_ram).(ram_mem)
+ m.(HTL.mod_ram).(ram_size)
m.(HTL.mod_params)
body
- m.(HTL.mod_entrypoint)
- | None =>
- let body :=
- Valways (Vposedge m.(HTL.mod_clk)) (Vcond (Vbinop Veq (Vvar m.(HTL.mod_reset)) (Vlit (ZToValue 1)))
- (Vnonblock (Vvar m.(HTL.mod_st)) (Vlit (posToValue m.(HTL.mod_entrypoint))))
- (Vcase (Vvar m.(HTL.mod_st)) case_el_ctrl (Some Vskip)))
- :: Valways (Vposedge m.(HTL.mod_clk)) (Vcase (Vvar m.(HTL.mod_st)) case_el_data (Some Vskip))
- :: List.map Vdeclaration (arr_to_Vdeclarr (AssocMap.elements m.(mod_arrdecls))
- ++ scl_to_Vdecl (AssocMap.elements m.(mod_scldecls))) in
- Verilog.mkmodule m.(HTL.mod_start)
- m.(HTL.mod_reset)
- m.(HTL.mod_clk)
- m.(HTL.mod_finish)
- m.(HTL.mod_return)
- m.(HTL.mod_st)
- m.(HTL.mod_stk)
- m.(HTL.mod_stk_len)
- m.(HTL.mod_params)
- body
- m.(HTL.mod_entrypoint)
- end.
+ m.(HTL.mod_entrypoint).
Definition transl_fundef := transf_fundef transl_module.
diff --git a/src/hls/Veriloggenproof.v b/src/hls/Veriloggenproof.v
index d1494ec..90cf4cb 100644
--- a/src/hls/Veriloggenproof.v
+++ b/src/hls/Veriloggenproof.v
@@ -241,7 +241,7 @@ Proof. unfold transl_module; intros; destruct (HTL.mod_ram m) eqn:?; crush. Qed.
Lemma mod_st_equiv m : mod_st (transl_module m) = HTL.mod_st m.
Proof. unfold transl_module; intros; destruct (HTL.mod_ram m) eqn:?; crush. Qed.
-Lemma mod_stk_equiv m : mod_stk (transl_module m) = HTL.mod_stk m.
+(*Lemma mod_stk_equiv m : mod_stk (transl_module m) = HTL.mod_stk m.
Proof. unfold transl_module; intros; destruct (HTL.mod_ram m) eqn:?; crush. Qed.
Lemma mod_stk_len_equiv m : mod_stk_len (transl_module m) = HTL.mod_stk_len m.
@@ -335,7 +335,7 @@ Proof.
Qed.
-Section CORRECTNESS.
+*)Section CORRECTNESS.
Variable prog: HTL.program.
Variable tprog: program.
@@ -345,7 +345,7 @@ Section CORRECTNESS.
Let ge : HTL.genv := Globalenvs.Genv.globalenv prog.
Let tge : genv := Globalenvs.Genv.globalenv tprog.
- Lemma symbols_preserved:
+(* Lemma symbols_preserved:
forall (s: AST.ident), Genv.find_symbol tge s = Genv.find_symbol ge s.
Proof. intros. eapply (Genv.find_symbol_match TRANSL). Qed.
#[local] Hint Resolve symbols_preserved : verilogproof.
@@ -532,13 +532,13 @@ Section CORRECTNESS.
Proof.
intros. inv H0. inv H. inv H3. constructor. reflexivity.
Qed.
- #[local] Hint Resolve transl_final_states : verilogproof.
+ #[local] Hint Resolve transl_final_states : verilogproof.*)
Theorem transf_program_correct:
forward_simulation (HTL.semantics prog) (Verilog.semantics tprog).
Proof.
eapply Smallstep.forward_simulation_plus; eauto with verilogproof.
- apply senv_preserved.
- Qed.
+ (*apply senv_preserved.
+ Qed.*) Admitted.
End CORRECTNESS.
diff --git a/src/SoftwarePipelining/LICENSE b/src/pipelining/LICENSE
index e275fa0..e275fa0 100644
--- a/src/SoftwarePipelining/LICENSE
+++ b/src/pipelining/LICENSE
diff --git a/src/SoftwarePipelining/SPBase_types.ml b/src/pipelining/SPBase_types.ml
index ba92340..ba92340 100644
--- a/src/SoftwarePipelining/SPBase_types.ml
+++ b/src/pipelining/SPBase_types.ml
diff --git a/src/SoftwarePipelining/SPBasic.ml b/src/pipelining/SPBasic.ml
index 32234b8..32234b8 100644
--- a/src/SoftwarePipelining/SPBasic.ml
+++ b/src/pipelining/SPBasic.ml
diff --git a/src/SoftwarePipelining/SPBasic.mli b/src/pipelining/SPBasic.mli
index f16e524..f16e524 100644
--- a/src/SoftwarePipelining/SPBasic.mli
+++ b/src/pipelining/SPBasic.mli
diff --git a/src/SoftwarePipelining/SPDebug.ml b/src/pipelining/SPDebug.ml
index 34d1c0c..34d1c0c 100644
--- a/src/SoftwarePipelining/SPDebug.ml
+++ b/src/pipelining/SPDebug.ml
diff --git a/src/SoftwarePipelining/SPIMS.ml b/src/pipelining/SPIMS.ml
index 0e19dec..0e19dec 100644
--- a/src/SoftwarePipelining/SPIMS.ml
+++ b/src/pipelining/SPIMS.ml
diff --git a/src/SoftwarePipelining/SPIMS.mli b/src/pipelining/SPIMS.mli
index 7c1d9a7..7c1d9a7 100644
--- a/src/SoftwarePipelining/SPIMS.mli
+++ b/src/pipelining/SPIMS.mli
diff --git a/src/SoftwarePipelining/SPMVE.ml b/src/pipelining/SPMVE.ml
index 28381c1..28381c1 100644
--- a/src/SoftwarePipelining/SPMVE.ml
+++ b/src/pipelining/SPMVE.ml
diff --git a/src/SoftwarePipelining/SPMVE.mli b/src/pipelining/SPMVE.mli
index 2da367d..2da367d 100644
--- a/src/SoftwarePipelining/SPMVE.mli
+++ b/src/pipelining/SPMVE.mli
diff --git a/src/SoftwarePipelining/SPSymbolic_evaluation.ml b/src/pipelining/SPSymbolic_evaluation.ml
index c99afc8..c99afc8 100644
--- a/src/SoftwarePipelining/SPSymbolic_evaluation.ml
+++ b/src/pipelining/SPSymbolic_evaluation.ml
diff --git a/src/SoftwarePipelining/SPTyping.ml b/src/pipelining/SPTyping.ml
index 9b9c679..9b9c679 100644
--- a/src/SoftwarePipelining/SPTyping.ml
+++ b/src/pipelining/SPTyping.ml
diff --git a/src/SoftwarePipelining/SPTyping.mli b/src/pipelining/SPTyping.mli
index dd27875..dd27875 100644
--- a/src/SoftwarePipelining/SPTyping.mli
+++ b/src/pipelining/SPTyping.mli
diff --git a/src/SoftwarePipelining/SoftwarePipelining.ml b/src/pipelining/SoftwarePipelining.ml
index 0ba6d9d..0ba6d9d 100644
--- a/src/SoftwarePipelining/SoftwarePipelining.ml
+++ b/src/pipelining/SoftwarePipelining.ml
diff --git a/test/Makefile b/test/Makefile
index 9413c70..aa76e70 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,6 +1,6 @@
CC ?= gcc
VERICERT ?= vericert
-VERICERT_OPTS ?= -fschedule
+VERICERT_OPTS ?= -fschedule -fif-conv
IVERILOG ?= iverilog
IVERILOG_OPTS ?=
@@ -18,7 +18,7 @@ all: $(TESTS)
@$(CC) $(CFLAGS) -o $@ $<
%.v: %.c
- @$(VERICERT) $(VERICERT_OPTS) -o $@ $<
+ $(VERICERT) $(VERICERT_OPTS) -o $@ $<
%.iver: %.v
@$(IVERILOG) $(IVERILOG_OPTS) -o $@ -- $<