This directory contains an ACL2 library of register-transfer logic, developed
at AMD from 1995 to 2011, and at Intel from 2012 to the present, in support of 
the mechanical verification of the floating-point arithmetic units designed 
during those periods by the respective companies.

The library's primary author is David Russinoff.  Matt Kaufmann, Eric
Smith, and Hanbing Liu have made significant contributions.  Version
rel11 is a conversion of rel10 to to a new "RTL" package, created as a
collaborative effort by Matt Kaufmann, David Rager, and Ben Selfridge,
with David Russinoff in the loop.

The library's core definitions and lemmas are contained in the subdirectory
"lib".  A parallel subdirectory, "support", contains a superset of these
events, including all sublemmas that were required for the proofs of the
library lemmas.  The "support" directory is organized in such a way as to allow
for the evolution of "lib", as described in the section 'How to Create a New 
Release of "books/rtl"' below.  Users should consider "lib" to be the RTL 
library, and are discouraged from accessing "support" directly.

The book "lib/top" includes those books of "lib" that generally revelant to
floating-point applications.  Other books of "lib", pertaining to more
specialized theories and applications, may be included separately as needed.
There is no guarantee that those specialized books are mutually compatible.  See 
the comments in "lib/top.lisp" for information on each of the other books in 
"lib".

Arithmetic proofs with ACL2 are often cumbersome, but there exist general-purpose 
arithmetic books that make the task more bearable.  The currently recommended 
procedure is to include the book "books/arithmetic-5/top" along with "/books/lib/top".
Unfortunately, there are a number of incompatibilities between the two libraries
that may severely affect efficiency.  These may be (partially) addressed by
the following:

(in-theory (disable |(mod (+ x y) z) where (<= 0 z)| |(mod (+ x (- (mod a b))) y)| 
                    |(mod (mod x y) z)| |(mod (+ x (mod a b)) y)| cancel-mod-+
                    mod-cancel-*-const simplify-products-gather-exponents-equal 
                    cancel-mod-+ reduce-additive-constant-< |(floor x 2)|
                    |(equal x (if a b c))| |(equal (if a b c) x)|))


The library files contain virtually no documentation.  A detailed companion
document is available online as follows, and can also be accessed through
the documentation topic, RTL, in the acl2+books combined manual.

    D.M. Russinoff, A formal theory of register-transfer logic and computer
    arithmetic, 2006.
    http://www.russinoff.com/libman/

Many of the interesting events are formal versions of definitions and lemmas
that are stated and proved in papers that document various applications of 
the library, many of which are available at "http://www.russinoff.com/papers/".


=======================================================================
How to Create a New Release of "books/rtl"
=======================================================================

Any significant revision of the library should result in a new release.  We 
distinguish between a "major" revision, which is likely to involve substantial 
restructuring of the library, and a "minor" revision, consisting, perhaps, of 
a few new lemmas or definitions or changes to old ones.  Thus, we envision a 
sequence of releases,

  ...,
  "rtl/rel<n-1>.0", "rtl/rel<n-1>.1", "rtl/rel<n-1>.2", ..., "rtl/rel<n-1>.k",
  "rtl/reln.0", "rtl/reln.1", ...

If the latest release is "reln.i", then a major revision produces "rel<n+1>.0",
whereas a minor revision instead produces "reln.<i+1>".  

At any time, for given n, only one "rtl/reln.j" exists.  When "rtl/reln.j" is
created, it contains "include-book" references to "rtl/rel<n-1>.k", which
therefore must remain in place.  However, when it is eventually decided that 
"rel<n-1>.k" is no longer needed by any external applications, it may be moved
under the latest "reln.j":

        mv rel<n-1>k reln.j

Every reference to "../rel<n-1>.k" within "reln.j" must then be changed to 
"rel<n-1>.k".  While that release is no longer directly accessible as 
"rtl/rel<n-1>.k", it remains indirectly accessible as "rtl/reln.j/rel<n-1>.k", 
and the current release "rtl/reln.j" is now a self-contained directory.  Thus, 
a release "rtl/reln.j" is forever accessible (directly or indirectly) if j is 
maximal, but is otherwise replaced by "rtl/reln.<j+1>".

The recommended procedures for major and minor revisions are outlined below.


Major revision: Creation of "reln.0" as a modification of "rel<n-1>.k"
-------------------------------------------------------------------

(1.1) Create a new directory "rtl/reln.0" and copy the files "README", "gpl.txt",
      and "license.txt" from "rel<n-1>.k" to "rtl/reln.0".  Create subdirectories 
      "rtl/reln.0/lib", "rtl/reln.0/support", and "rtl/reln.0/support/0".

(1.2) Write the files "reln.0/lib/<book>.lisp" of the new library.  Among these
      should be the file "reln.0/lib/top.lisp", which simply includes all or some
      of the other books of "reln.0/lib/".  Each of the others should begin with
      the events

        (set-enforce-redundancy t)
        (local (include-book "../support/top"))

      where "reln.0/support/top.lisp" is described in Step 1.4 below, and may be 

        (a) a copy of "rel<n-1>.k/lib/<book>.lisp" (modulo local include-books), 

        (b) a modified version of "rel<n-1>.k/lib/<book>.lisp", or 

        (c) an entirely new book.  

(1.3) For each "reln.0/lib/<book>.lisp" that is neither "reln.0/lib/top.lisp" nor a
      copy of "rel<n-1>.k/lib/book.lisp", create the file "reln.0/support/0/book.lisp".
      The first event of this file is typically

        (local (include-book "../../../rel<n-1>.k/lib/top"))

      which allows the subsequent proof script (which may be distributed over 
      several files) to be developed in the context of "rel<n-1>.k/lib/".  The 
      non-local events of this script should precisely coincide with those of 
      "reln.0/lib/<book>.lisp".

(1.4) Create the file "reln.0/support/top.lisp", consisting of an "include-book"
      corresponding to each book "reln.0/lib" other than "reln.0/lib/top".  If 
      "reln.0/lib/book.lisp" is a copy of "rel<n-1>.k/lib/book", then that book 
      should be included:

        (include-book "../../../rel<n-1>.k/lib/book")

      Otherwise, the corresponding book described in Step 1.3 above should be 
      included:

        (include-book "./0/book")


Minor revision: Creation of "reln.j" as a modification of "reln.<j-1>"
-------------------------------------------------------------------

(2.1) Rename "reln.<j-1>" as "reln.j" and create the directory "reln.j/support/j"

        mv "reln.<j-1>" "reln.j"
        mkdir "reln.j/support/j"

(2.2) Revise the existing files "reln.j/lib/book.lisp" and create new ones as desired.
      Modify "reln.j/lib/top.lisp" accordingly.

(2.3) For each "reln.j/lib/book.lisp" other than "reln.j/lib/top.lisp" that has
      been revised or newly created, create the file "reln.j/support/j/book.lisp"
      as in Step 1.3 above.

(1.4) For each "reln.j/support/j/book.lisp", add to "reln.j/support/top.lisp" the
      event

        (include-book "./j/book")

      and unless this is a newly created book, delete the corresponding 
      pre-existing line.

=========================================================================
Hanbing's Hints on Creative Use of Local Include-books
=========================================================================

When revising the library involves renaming or modification of existing 
events, some creativity may be required.  We provide the following illustrative 
example.

Suppose that in a new release "rel8.3" we need to update "lib/round.lisp" by 
strengthening a theorem "foo", and that there is no "rel8.3/support/i/round.lisp" 
for any i < 3.  Then we may create the following books.

    ============================================================
    ; rel8.3/support/3/foo-new.lisp

    ; Here, prove stronger version of foo; but call it foo-new.
    ; We may find that the original version of foo is useful,
    ; We can do something like this:

     (local
      (encapsulate ()
         (local (include-book "../../../rel7.5/lib/round"))
         (defthm foo
                 ....)))   ; extract the original foo theorem.

     (defthm foo-new ...)

    ============================================================
    ; rel8.3/support/3/round-partial.lisp

    (local (include-book "../../../rel7.5/lib/round"))
    (local (include-book "foo-new"))
    <Insert all of round.lisp, except delete foo.>

    ============================================================
    ; rel8.3/support/3/round.lisp

    (local (include-book "round-partial"))
    (local (include-book "foo-new"))
    <Insert all of round.lisp, except delete foo.>
    (local (defthm foo-new ...))
    (defthm foo ... :hints (("Goal" :by foo-new)))
      
    ============================================================
    ; rel8.3/support/top.lisp

    (include-book "../../../rel7.5/lib/round.lisp") ; replace with the following:
    (include-book "3/round")


If there already exists some "rel8.3/support/i/round.lisp", and we feel that
replacing foo with the new version may affect other existing lemmas, then we 
should move to "rel9".


