source: CIVL/doc/tutorial/tutorial.tex@ a054a5b

1.23 2.0 main test-branch
Last change on this file since a054a5b was 802ed671, checked in by Stephen Siegel <siegel@…>, 13 years ago

Continuing work on tutorial

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@313 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 20.4 KB
Line 
1\documentclass[t]{beamer}
2\input{preambular}
3\foot{CIVL Tutorial}
4\date{\today}
5\title{{\huge\bf CIVL}\\
6 Concurrency Intermediate Verification Language\\ \ \\
7 Tutorial}
8
9\begin{document}
10
11\begin{frame}[plain]
12 \titlepage
13\end{frame}
14
15
16\section{CIVL User Tutorial}
17
18\begin{frame}{What is CIVL?}
19 CIVL is \ldots
20 \begin{enumerate}
21 \item \ldots a programming language, \alert{CIVL-C}
22 \begin{itemize}
23 \item based on subset of C
24 \item extensions for concurrency, naming of scopes
25 \end{itemize}
26 \item \ldots a suite of tools for analyzing CIVL-C programs
27 \begin{itemize}
28 \item running + dynamic checking
29 \item model checking
30 \item static analyses (coming)
31 \end{itemize}
32 \item \ldots a set of translators from common programming
33 language/concurrency API combinations to CIVL-C
34 \begin{itemize}
35 \item coming
36 \end{itemize}
37 \end{enumerate}
38\end{frame}
39
40\begin{frame}[containsverbatim]{Example: \code{adder.cvl}}
41
42 \begin{tabular}[t]{l|l}
43 \begin{minipage}[t]{.45\textwidth}\scriptsize
44\begin{verbatim}
45#include <civlc.h>
46
47$input int B;
48$input int N;
49$assume 0<=N && N<=B;
50$input double a[N];
51
52double adderSeq(double *p, int n) {
53 double s = 0.0;
54
55 for (int i = 0; i < n; i++)
56 s += p[i];
57 return s;
58}
59
60double adderPar(double *p, int n) {
61 double s = 0.0;
62 _Bool mutex = 0;
63 $proc workers[n];
64
65 void worker(int i) {
66 double t;
67\end{verbatim}
68 \end{minipage}
69 &
70 \begin{minipage}[t]{.45\textwidth}\scriptsize
71\begin{verbatim}
72 $when (mutex == 0) mutex = 1;
73 t = s;
74 t += p[i];
75 s = t;
76 mutex = 0;
77 }
78
79 for (int j = 0; j < n; j++)
80 workers[j] = $spawn worker(j);
81 for (int j = 0; j < n; j++)
82 $wait workers[j];
83 return s;
84}
85
86void main() {
87 double seq = adderSeq(&a[0], N);
88 double par = adderPar(&a[0], N);
89
90 $assert seq == par;
91}
92\end{verbatim}
93 \end{minipage}
94 \end{tabular}
95\end{frame}
96
97\begin{frame}[containsverbatim]{Verifying \code{adder.cvl}}
98
99\begin{verbatim}
100concurrency$ civl verify -inputB=5 adder.cvl
101CIVL v0.4 of 2013-12-06 -- http://vsl.cis.udel.edu/civl
102=================== Stats ===================
103 validCalls : 23883
104 proverCalls : 29
105 memory (bytes) : 374341632
106 time (s) : 5.35
107 maxProcs : 6
108 statesInstantiated : 28761
109 statesSaved : 3082
110 statesSeen : 3082
111 statesMatched : 1968
112 transitions : 5049
113
114The standard properties hold for all executions.
115concurrency$
116\end{verbatim}
117\end{frame}
118
119\begin{frame}{Download and Installation}
120 \begin{enumerate}
121 \item Get a Java 7 VM.
122 \item Go to \url{http://vsl.cis.udel.edu/civl}
123 \item Navigate to downloads, \emph{latest stable release}.
124 \item Download version corresponding to your platform.
125 \begin{itemize}
126 \item for now, pre-compiled versions for OS X and linux (32- and 64-bit)
127 \item other platforms must build from source
128 \end{itemize}
129 \item Unpack and move resulting directory \texttt{CIVL-\textit{tag}}
130 under \texttt{/opt}.
131 \item Download the VSL dependencies archive.
132 \begin{itemize}
133 \item contains a number of pre-compiled open source libraries used by CIVL
134 \item \url{http://vsl.cis.udel.edu/tools/vsl\_depend}
135 \end{itemize}
136 \item Unpack and move resulting directory \texttt{vsl} under \texttt{/opt}.
137 \item Put \texttt{/opt/CIVL-\textit{tag}/bin/civl} in your path.
138 \begin{itemize}
139 \item however you want: move it, symlink, \ldots
140 \end{itemize}
141 \end{enumerate}
142
143 \alert{Note:} You can put \texttt{vsl} and \texttt{CIVL-\textit{tag}}
144 in any directories (not just \texttt{/opt}). Just edit script \texttt{civl}
145 to use the new paths.
146\end{frame}
147
148\begin{frame}[containsverbatim]{Test your installation}
149
150 From command line \ldots
151
152\begin{verbatim}
153concurrency$ civl
154CIVL v0.4 of 2013-12-06 -- http://vsl.cis.udel.edu/civl
155Missing command
156Type "civl help" for command line syntax.
157
158concurrency$ civl help
159...
160\end{verbatim}
161
162Copy \texttt{/opt/CIVL-\textit{tag}/examples/concurrency/adder.cvl}
163to your working directory and try
164
165\begin{verbatim}
166 civl verify -inputB=5 adder.cvl
167\end{verbatim}
168\end{frame}
169
170\begin{frame}{What features are inherited from C?}
171 \begin{itemize}
172 \item most syntax
173 \item types
174 \begin{itemize}
175 \item \texttt{{\U}Bool} $\ra$ $\{0,1\}$
176 \item \texttt{int}, \texttt{long}, \texttt{short}, \ldots $\ra$ $\Z$
177 \item \texttt{double}, \texttt{float}, \ldots $\ra$ $\R$
178 \item structure, array, pointer, and function types
179 \end{itemize}
180 \item expressions
181 \begin{itemize}
182 \item addition, multiplication, division, subtraction, unary minus (\code{+},
183 \code{*}, \code{/}, \code{-})
184 \item integer division (\code{/}) and modulus (\code{\%})
185 \item pointer dereference (\code{*}), address-of (\code{\&})
186 \item array subscript (\code{[...]})
187 \item structure navigation (\code{.})
188 \item logical and (\code{\&\&}), or (\code{||}), not (\code{!})
189 \item \code{==}, \code{!=}, \code{<}, \code{>}, \code{<=}, \code{>=}
190 \item pointer addition (\code{+}) and subtraction (\code{-})
191 \item \code{++}, \code{--}
192 \item \alert{no bit-wise operations} for now
193 \end{itemize}
194 \end{itemize}
195\end{frame}
196
197\begin{frame}{Inherited from C, cont.}
198 \begin{itemize}
199 \item statements
200 \begin{itemize}
201 \item no-op, labeled-statement, compound-statement
202 \item assignments (\code{=}, \code{+=}, \code{-=}, \ldots)
203 \item function call
204 \item \code{if}\ldots\code{else}
205 \item \code{goto}, \code{while}, \code{do}, \code{for},
206 \code{switch}, \code{break}
207 \end{itemize}
208 \item procedure (function) prototypes and definitions
209 \item \code{typedef}
210 \item preprocessing directives
211 \end{itemize}
212\end{frame}
213
214\begin{frame}{New features}
215 \begin{itemize}
216 \item functions can be declared in any scope
217 \item concurrency primitives
218 \begin{itemize}
219 \item spawning processes: \code{\cproc\ p = \cspawn\ f();}
220 \item waiting for a process to terminate: \code{\cwait\ p;}
221 \item guarded commands: \code{\cwhen (x>0) c=1;}
222 \end{itemize}
223 \item nondeterministic choice: \code{\cchoose ...}
224 \item explicit naming of scopes: \code{\cscope\ s;}
225 \item scope-parameterized pointers \code{double *<s> p;}
226 \item other primitives useful for verification
227 \begin{itemize}
228 \item input qualifier, assert, assume, procedure contracts
229 \end{itemize}
230 \item library-level constructs supporting message-passing, \ldots
231 \end{itemize}
232\end{frame}
233
234\begin{frame}{Some CIVL-C primtives}
235 \begin{tabular}{ll}
236 \cproc & the process type \\
237 \cself & the evaluating process (constant of type \cproc) \\
238 \cscope & the scope type \\
239 \cinput & type qualifier declaring variable to be a program input \\
240 \coutput & type qualifier declaring variable to be a program output \\
241 \cspawn & create a new process running procedure \\
242 \cwait & wait for a process to terminate \\
243 \cassert & check something holds \\
244 \ctrue & boolean value true, used in assertions \\
245 \cfalse & boolean value false, used in assertions \\
246 \cassume & assume something holds \\
247 \cwhen & guarded statement \\
248 \cchoose & nondeterministic choice statement \\
249 \cchooseint & nondeterministic choice of integer
250 \end{tabular}
251\end{frame}
252
253\begin{frame}{CIVL Command line tools}
254 \begin{itemize}
255 \item \code{civl run filename}
256 \begin{itemize}
257 \item run the CIVL program making nondeterministic choices randomly
258 \item \code{-seed=LONG} : use this random seed (reproducible)
259 \end{itemize}
260 \item \code{civl verify filename}
261 \begin{itemize}
262 \item explore reachable state space, checking properties at each state
263 \begin{itemize}
264 \item absence of deadlock, assertion violations, division by $0$,
265 invalid pointer dereference, out of bounds array access, \ldots
266 \end{itemize}
267 \item may specify bounds using \cinput{} variables and command line
268 \begin{itemize}
269 \item \code{-inputX=value}
270 \end{itemize}
271 \item \code{-errorBound=INT} specifies maximum number of errors that
272 will be logged before quitting
273 \end{itemize}
274 \item \code{civl replay}
275 \begin{itemize}
276 \item if a violation was found during \code{verify}, its trace
277 is saved to a file; this will run the trace
278 \item \code{-id=INT} can be used to specify the ID of the trace if more than one
279 \item \code{-trace=tracefile} can be used to specify the exact filename
280 containing trace
281 \end{itemize}
282 \end{itemize}
283\end{frame}
284
285\begin{frame}{Scope-parameterized pointers}
286 \begin{itemize}
287 \item a declaration of the form \code{\cscope\ s;} assigns the name
288 \code{s} to the containing scope
289 \begin{itemize}
290 \item what you can do with \code{s} is very limited
291 \item cannot be assigned, passed as parameter
292 \end{itemize}
293 \item \code{int *<s> p;}
294 \begin{itemize}
295 \item declares \code{p} to have type ``pointer-to-\code{int}-in-\code{s}''
296 \item \code{p} can only hold a pointer to an object in scope \code{s}
297 \end{itemize}
298 \item $s_1\leq s_2$ $\implies$
299 \textit{pointer-to-$T$-in-$s_1$} \alert{is a subtype of}
300 \textit{pointer-to-$T$-in-$s_2$}
301 \item the type \textit{pointer-to-$T$} (\code{T*}) is shorthand for
302 \textit{pointer-to-$T$-in-$s_0$} (\code{T*<\(s_0\)>}), where $s_0$
303 is the \alert{root scope}
304 \item \code{\&x} returns a pointer to the declaration scope of \code{x}
305 \begin{itemize}
306 \item scope of \code{\&a[i]} is the scope of \code{\&a}
307 \item scope of \code{\&r.f} is the scope of \code{\&r}
308 \end{itemize}
309 \end{itemize}
310\end{frame}
311
312\begin{frame}[containsverbatim]{Pointer safety}
313 \begin{itemize}
314 \item for a CIVL-C program to be \alert{statically type-safe},
315 for all assignments, the type of the right-hand side must be a subtype
316 of that of the left-hand side
317 \item static type-safety can be checked statically
318 \end{itemize}
319
320 Example:
321
322 \begin{mycbox}{7cm}
323\begin{verbatim}
324 {
325 $scope s1;
326 double x;
327 {
328 $scope s2;
329 double a[N];
330 double *<s1> p = &x; // OK
331 double *<s2> q = &a[0]; // OK
332
333 p = &a[1]; // OK
334 q = &x; // static type error
335 }
336 }
337\end{verbatim}
338 \end{mycbox}
339\end{frame}
340
341\begin{frame}[containsverbatim]{Scope-parameterized functions}
342
343 A function declaration or definition may be parameterized by any number
344 of \alert{formal scope parameters}. Example:
345
346 \begin{mycbox}{7cm}
347\begin{verbatim}
348 <s> int *<s> f(int *<s> p);
349\end{verbatim}
350 \end{mycbox}
351
352 declares $f$ to be a function which, for any scope $s$, takes a
353 \emph{pointer-to-\texttt{int}-in-$s$} and returns a
354 \emph{pointer-to-\texttt{int}-in-$s$}.
355
356\end{frame}
357
358\begin{frame}{Further ideas}
359 \begin{itemize}
360 \item scope-parameterized \alert{typedefs} and \alert{structs}
361 \item \alert{heap} type (can have ``a heap in every scope'')
362 \begin{itemize}
363 \item \texttt{malloc} and \texttt{free} adjusted to take reference to heap
364 \end{itemize}
365 \item a \alert{bundle type}
366 \begin{itemize}
367 \item wrap up any contiguous region of memory into an object of bundle type
368 \item functions to \alert{pack} and \alert{unpack} bundles
369 \item useful for many abstractions, e.g., messages
370 \end{itemize}
371 \item set of functions and types supporting \alert{message-passing}
372 \item see Trac Wiki and \code{civlc.h}
373 \end{itemize}
374\end{frame}
375
376\begin{frame}[containsverbatim]{Message Passing example: \code{ring.cvl}}
377
378\begin{verbatim}
379/* Create nprocs processes. Have them exchange data
380 * in a cycle. Commandline example:
381 * civl verify -inputNPROCS=3 ring.cvl -simplify=false
382 */
383#include<civlc.h>
384#include "mp_root.cvh"
385
386void MPI_Process (int rank) {
387#include "mp_proc.cvh"
388
389 double x=rank, y;
390
391 send(&x, 1, (rank+1)%NPROCS, 0);
392 recv(&y, 1, (rank+NPROCS-1)%NPROCS, 0);
393 $assert y==(rank+NPROCS-1)%NPROCS;
394}
395\end{verbatim}
396\end{frame}
397
398\begin{frame}[containsverbatim]{File \code{mp{\U}root.cvh}}
399 \scriptsize
400\begin{verbatim}
401$input int NPROCS;
402$proc __procs[NPROCS];
403_Bool __start = 0;
404$comm MPI_COMM_WORLD;
405
406void MPI_Process (int rank);
407
408void init() {
409 for (int i=0; i<NPROCS; i++)
410 __procs[i] = $spawn MPI_Process(i);
411 MPI_COMM_WORLD = $comm_create(NPROCS, __procs);
412 __start=1;
413}
414
415void finalize() {
416 for (int i=0; i<NPROCS; i++)
417 $wait __procs[i];
418}
419
420void main() {
421 init();
422 finalize();
423}
424\end{verbatim}
425\end{frame}
426
427\begin{frame}[containsverbatim]{File \code{mp{\U}proc.cvh}}
428 \scriptsize
429\begin{verbatim}
430 void send(void *buf, int count, int dest, int tag) {
431 $message out = $message_pack(rank, dest, tag, buf, count*sizeof(double));
432 $comm_enqueue(&MPI_COMM_WORLD, out);
433 }
434
435 void recv(void *buf, int count, int source, int tag) {
436 $message in = $comm_dequeue(&MPI_COMM_WORLD, source, rank, tag);
437 $message_unpack(in, buf, count*sizeof(double));
438 }
439
440 $when (__start);
441\end{verbatim}
442\end{frame}
443
444\section{CIVL Developer Tutorial}
445
446\begin{frame}{VSL Projects: Uses Relation}
447
448 \includegraphics{vsl_projects}
449
450 \begin{itemize}
451 \item reusable components
452 \begin{itemize}
453 \item ABC: A Better C compiler? ANTLR-Based C compiler?
454 \item SARL: Symbolic Algebra \& Reasoning Library
455 \item GMC: Generic Model Checking utilities
456 \begin{itemize}
457 \item DFS, command line interface, trace saving/replay, error
458 logging, random simulation
459 \end{itemize}
460 \end{itemize}
461 \item model checking applications
462 \begin{itemize}
463 \item CIVL: Concurrency Intermediate Verification Language
464 \item TASS: Toolkit for Accurate Scientific Software (C+MPI)
465 \item CVT: Chapel Verification Tool
466 \end{itemize}
467 \end{itemize}
468
469\end{frame}
470
471\begin{frame}{Engineering}
472
473 \begin{itemize}
474 \item all of the VSL software is in Java
475 \item try to maintain coding standards
476 \item clear module boundaries with interfaces
477 \end{itemize}
478
479
480 \begin{center}
481 \begin{tabular}{|ll|}
482 \hline
483 Web page & \url{http://vsl.cis.udel.edu/civl}\\
484 Subversion & \url{svn://vsl.cis.udel.edu/civl}\\
485 Trac repository & \url{https://vsl.cis.udel.edu/trac/civl}\\
486 Automated build/test & \url{http://vsl.cis.udel.edu/civl/test}\\
487 \hline
488 \end{tabular}
489 \end{center}
490
491 \begin{itemize}
492 \item replace \texttt{civl} with \texttt{sarl}, \texttt{abc}, \texttt{gmc}, or
493 \texttt{tass}
494 \end{itemize}
495
496 \includegraphics[scale=.3]{civl-trac.pdf}
497
498\end{frame}
499
500\begin{frame}{Civl Test Directory}
501 \includegraphics[scale=.35]{civlTestDir}
502
503 \includegraphics[scale=.35]{civlTestTrunkDir}
504\end{frame}
505
506\begin{frame}{CIVL Test Directory: Latest (unstable) Release}
507 \includegraphics[scale=.35]{civlTestTrunkLatest}
508\end{frame}
509
510
511\begin{frame}{Automated Build \& Test Script}
512
513 \begin{center}
514 \includegraphics[scale=.3]{sarl-junit.pdf}
515 \end{center}
516
517 For each project \ldots
518 \begin{itemize}
519 \item script is run after each commit
520 \item one directory for each \alert{branch} and \alert{trunk}
521 \begin{itemize}
522 \item one subdirectory for each revision, up to some bounded history
523 \end{itemize}
524 \item compiles all code and displays results
525 \item runs JUnit test suite and displays results
526 \item runs Jacoco coverage anaysis and displays results
527 \item generates javadocs
528 \end{itemize}
529\end{frame}
530
531\begin{frame}{Coverage Analysis Results}
532 \includegraphics[scale=.4]{civlCoverage}
533\end{frame}
534
535\begin{frame}{Developer Eclipse Set-up}
536 \begin{enumerate}
537 \item Download vsl dependencies archive from
538 \url{http://vsl.cis.udel.edu/tools/vsl_depend}
539 \item Download and install Eclipse IDE for Java EE Developers
540 \begin{itemize}
541 \item version Kepler or later
542 \end{itemize}
543 \item Install Apache Ant if you don't have it
544 \item Install an Eclipse SVN plugin (such as Subversive)
545 \item Create class path variable \texttt{VSL}:
546 \begin{itemize}
547 \item Preferences$\ra$Java$\ra$Build Path$\ra$ClassPath Variables
548 \item select ``New'' and create a classpath variable \texttt{VSL}
549 \item specify its value to be \texttt{/opt/vsl}
550 \end{itemize}
551 \item Create string variable \texttt{vsl{\U}lib}:
552 \begin{itemize}
553 \item Preferences$\ra$Run/Debug$\ra$String Substitution$\ra$New
554 \item define an entry \texttt{vsl{\U}lib}
555 \item set its value to be \texttt{/opt/vsl/lib}
556 \end{itemize}
557 \end{enumerate}
558\end{frame}
559
560\begin{frame}{Check out and install ABC}
561 \begin{enumerate}
562 \item Check out ABC Eclipse project
563 \begin{itemize}
564 \item ``New Project\ldots from SVN''
565 \item SVN repository: \url{svn://vsl.cis.udel.edu/abc}
566 \item Navigate and select \texttt{trunk} from within archive
567 \item Check out project using all default options
568 \end{itemize}
569 \item Build using Ant
570 \begin{itemize}
571 \item right-click on \texttt{build.xml}
572 \item Choose ``Run as Ant build''
573 \item Clean project
574 \end{itemize}
575 \item test the build
576 \begin{itemize}
577 \item select Run$\ra$Run Configurations\ldots
578 \item ceate a new JUnit 4 configuration called ``ABC Tests''
579 \item select ``Run all tests in the selected project\ldots''
580 \item navigate and select the \texttt{test} folder in the ABC project
581 \item under the Arguments tab, type \texttt{-ea} into the VM arguments field
582 \item click ``Run'' to run the tests
583 \end{itemize}
584 \end{enumerate}
585\end{frame}
586
587\begin{frame}{Check out and install GMC}
588 \begin{enumerate}
589 \item Check out GMC Eclipse project
590 \begin{itemize}
591 \item ``New Project\ldots from SVN''
592 \item SVN repository: \url{svn://vsl.cis.udel.edu/gmc}
593 \item Navigate and select \texttt{trunk} from within archive
594 \item Check out project using all default options
595 \end{itemize}
596 \item test the build
597 \begin{itemize}
598 \item select Run$\ra$Run Configurations\ldots
599 \item ceate a new JUnit 4 configuration called ``GMC Tests''
600 \item select ``Run all tests in the selected project\ldots''
601 \item navigate and select the \texttt{test} folder in the GMC project
602 \item under the Arguments tab, type \texttt{-ea} into the VM arguments field
603 \item click ``Run'' to run the tests
604 \end{itemize}
605 \end{enumerate}
606\end{frame}
607
608\begin{frame}{Check out and install SARL}
609 \begin{enumerate}
610 \item Check out SARL Eclipse project
611 \begin{itemize}
612 \item ``New Project\ldots from SVN''
613 \item SVN repository: \url{svn://vsl.cis.udel.edu/sarl}
614 \item Navigate and select \texttt{trunk} from within archive
615 \item Check out project using all default options
616 \end{itemize}
617 \item test the build
618 \begin{itemize}
619 \item select Run$\ra$Run Configurations\ldots
620 \item ceate a new JUnit 4 configuration called ``SARL Tests''
621 \item select ``Run all tests in the selected project\ldots''
622 \item navigate and select the \texttt{test} folder in the SARL project
623 \item under Arguments tab, type \texttt{-ea} into the VM arguments field
624 \item under Environment tab, create an entry
625 \texttt{DYLD{\U}LIBRARY{\U}PATH} (OS X) or
626 \texttt{LD{\U}LIBRARY{\U}PATH} (linux), specify its value by
627 clicking Variables, choose \texttt{vsl{\U}lib} from the list
628 \item click ``Run'' to run the tests
629 \end{itemize}
630 \end{enumerate}
631\end{frame}
632
633\begin{frame}{Check out and install CIVL}
634 \begin{enumerate}
635 \item Check out CIVL Eclipse project
636 \begin{itemize}
637 \item ``New Project\ldots from SVN''
638 \item SVN repository: \url{svn://vsl.cis.udel.edu/civl}
639 \item Navigate and select \texttt{trunk} from within archive
640 \item Check out project using all default options
641 \end{itemize}
642 \item test the build
643 \begin{itemize}
644 \item select Run$\ra$Run Configurations\ldots
645 \item ceate a new JUnit 4 configuration called ``CIVL Tests''
646 \item select ``Run all tests in the selected project\ldots''
647 \item navigate and select the \texttt{test} folder in the CIVL project
648 \item under Arguments tab, type \texttt{-ea} into the VM arguments field
649 \item under Environment tab, create an entry
650 \texttt{DYLD{\U}LIBRARY{\U}PATH} (OS X) or
651 \texttt{LD{\U}LIBRARY{\U}PATH} (linux), specify its value by
652 clicking Variables, choose \texttt{vsl{\U}lib} from the list
653 \item click ``Run'' to run the tests
654 \end{itemize}
655 \item \alert{optional:} configure to build and run with \texttt{ant}
656 \begin{itemize}
657 \item create file \texttt{build.properties} in root CIVL directory
658 \item base on examples in \texttt{properties} directory
659 \item from command line, type \texttt{ant test}
660 \end{itemize}
661 \end{enumerate}
662\end{frame}
663
664\begin{frame}{CIVL modules}
665 \begin{tabular}{@{}ll@{}}
666 \includegraphics[scale=0.55]{civlModules}
667 &
668 \includegraphics[scale=.3]{civlEclipseModules}
669 \end{tabular}
670\end{frame}
671
672\end{document}
Note: See TracBrowser for help on using the repository browser.