Hardware Retiming
Correctness of a Hardware Retiming Transformation
This example applies BOBJ's circular coinductive rewriting algorithm with case
analysis, to a hardware verification example, taken from the thesis of Paul
Miner at Indiana University (1998), written under the direction of
Prof. Steven Johnson; this thesis applies explicit coinduction to many
hardware examples, and inspired us to try our approach on the same domain. A
diagram for the circuit is given below, and the code in the next section is
due to Kai Lin, as is the idea of enhancing circular coinductive rewriting
with case analysis; the syntax was designed by Joseph Goguen.
The problem is to prove that the second circuit has the same behavior as
the first; this means proving correctness of a "retiming transformation," done
to minimize the longest (i.e., critical) path through the first circuit. The
approach in the thesis of Paul Miner was to translate the logic of a hardware
description language named DRS into the higher order logic of the PVS theorem
prover, which then required some rather non-trivial interactions with the user
in order to complete the proof. Our approach here is much more direct,
expressing both the circuit and the proof task in BOBJ, and then applying the
CCRW algorithm with one case analysis and one lemma. Although less than
entirely trivial, these are standard tricks that can be learned from
experience; actually, these Boolean case analyses are entirely standard for
hardware and could be automated, and the cobasis used is also standard.
1. BOBJ Source Code
*** file: /tatami/bobj/examples/mux.bob
*** hardware retiming transformation correctness
bth STREAM is sort Stream .
op _&_ : Bool Stream -> Stream .
op hd : Stream -> Bool .
op tl : Stream -> Stream .
var S : Stream . var B : Bool .
eq hd(B & S) = B .
eq tl(B & S) = S .
end
bth FUN is pr STREAM .
op f : Bool -> Bool .
op mapf : Stream -> Stream .
op mux : Stream Stream Stream -> Stream .
op mux : Bool Bool Bool -> Bool .
op feedback : Stream Stream Bool -> Stream .
vars B B1 B2 : Bool . vars S S1 S2 S3 : Stream .
eq hd(mapf(S)) = f(hd(S)) .
eq tl(mapf(S)) = mapf(tl(S)) .
eq hd(mux(S1, S2, S3)) = hd(S2) if hd(S1) .
eq hd(mux(S1, S2, S3)) = hd(S3) if not hd(S1).
eq tl(mux(S1, S2, S3)) = tl(S2) if hd(S1) .
eq tl(mux(S1, S2, S3)) = tl(S3) if not hd(S1) .
eq mux(true, B1, B2) = B1 .
eq mux(false, B1, B2) = B2 .
eq hd(feedback(S1, S2, B)) = B .
eq tl(feedback(S1, S2, B)) =
feedback(tl(S1), tl(S2), mux(hd(S1), hd(S2), B)) .
end
bth SYSTEM is pr FUN .
ops old new : Stream Stream Bool -> Stream .
vars B B1 B2 : Bool . vars S S1 S2 : Stream .
eq hd(old(S1, S2, B)) = f(B) .
eq tl(old(S1, S2, B)) = mapf(mux(S1, S2, feedback(S1, S2, B))) .
eq hd(new(S1, S2, B)) = B .
eq tl(new(S1, S2, B)) = mux(S1, mapf(S2), feedback(S1, mapf(S2), B)) .
end
cobasis SYSTEM-COBASIS from SYSTEM is
op hd : Stream -> Bool .
op tl : Stream -> Stream .
end
cases MUX-STREAM-CASE-ANALYSE for SYSTEM is
vars S1 S2 S3 : Stream .
context mux(S1, S2, S3) .
case eq hd(S1) = true .
case eq hd(S1) = false .
end
cases MUX-CASE-ANALYSE for SYSTEM is
vars B1 B2 B3 : Bool .
context mux(B1, B2, B3) .
case eq B1 = true .
case eq B1 = false .
end
set cob SYSTEM-COBASIS .
set cred trace on .
***> a lemma
cred with MUX-CASE-ANALYSE
mapf(feedback(S1, S2, B)) == feedback(S1, mapf(S2), f(B)) .
***> main result
open .
eq mapf(feedback(S1, S2, B)) = feedback(S1, mapf(S2), f(B)) .
cred with MUX-STREAM-CASE-ANALYSE
old(S1, S2, B) == new(S1, S2, f(B)) .
close
2. BOBJ Output
awk% bobj
\|||||||||||||||||/
--- Welcome to BOBJ ---
/|||||||||||||||||\
BOBJ version 0.9.196 built: Tue Oct 29 16:43:36 PST 2002
University of California, San Diego
Mon Nov 04 12:15:28 PST 2002
BOBJ> in mux
==========================================
bth STREAM
==========================================
bth FUN
==========================================
bth SYSTEM
==========================================
cases MUX-STREAM-CASE-ANALYSE
==========================================
cases MUX-CASE-ANALYSE
==========================================
set cobasis SYSTEM-COBASIS
==========================================
***> a lemma
==========================================
c-reduce in SYSTEM : mapf(feedback(S1, S2, B)) == feedback(S1,
mapf(S2), f(B))
use: MUX-CASE-ANALYSE
using cobasis SYSTEM-COBASIS for SYSTEM
reduced to: mapf(feedback(S1, S2, B)) == feedback(S1, mapf(S2), f(B))
-----------------------------------------
add rule (C1) : mapf(feedback(S1, S2, B)) = feedback(S1, mapf(S2),
f(B))
-----------------------------------------
target is: mapf(feedback(S1, S2, B)) == feedback(S1, mapf(S2), f(B))
expand by: op hd : Stream -> Bool
reduced to: true
nf: f(B)
-----------------------------------------
target is: mapf(feedback(S1, S2, B)) == feedback(S1, mapf(S2), f(B))
expand by: op tl : Stream -> Stream
deduced using (C1) : feedback(tl(S1), mapf(tl(S2)), f(mux(hd(S1),
hd(S2), B))) == feedback(tl(S1), mapf(tl(S2)), mux(hd(S1),
f(hd(S2)), f(B)))
-------------------------------------------
case analysis by MUX-CASE-ANALYSE
-------------------------------------------
introduce constant(s):
s1 for the variable S1
s for the variable S2
b for the variable B
-------------------------------
case 1 :
assume: hd(s1) = true
reduce: feedback(tl(s1), mapf(tl(s)), f(mux(hd(s1), hd(s), b))) ==
feedback(tl(s1), mapf(tl(s)), mux(hd(s1), f(hd(s)), f(b)))
nf: true
-------------------------------
case 2 :
assume: hd(s1) = false
reduce: feedback(tl(s1), mapf(tl(s)), f(mux(hd(s1), hd(s), b))) ==
feedback(tl(s1), mapf(tl(s)), mux(hd(s1), f(hd(s)), f(b)))
nf: true
-----------------------------------------
result: true
c-rewrite time: 287ms parse time: 8ms
==========================================
***> main result
==========================================
open
==========================================
eq mapf(feedback(S1, S2, B)) = feedback(S1, mapf(S2), f(B))
==========================================
c-reduce in SYSTEM : old(S1, S2, B) == new(S1, S2, f(B))
use: MUX-STREAM-CASE-ANALYSE
using cobasis SYSTEM-COBASIS for SYSTEM
reduced to: old(S1, S2, B) == new(S1, S2, f(B))
-----------------------------------------
add rule (C1) : old(S1, S2, B) = new(S1, S2, f(B))
-----------------------------------------
target is: old(S1, S2, B) == new(S1, S2, f(B))
expand by: op hd : Stream -> Bool
reduced to: true
nf: f(B)
-----------------------------------------
target is: old(S1, S2, B) == new(S1, S2, f(B))
expand by: op tl : Stream -> Stream
reduced to: mapf(mux(S1, S2, feedback(S1, S2, B))) == mux(S1,
mapf(S2), feedback(S1, mapf(S2), f(B)))
-------------------------------------------
case analysis by MUX-STREAM-CASE-ANALYSE
-------------------------------------------
introduce constant(s):
s for the variable S1
s1 for the variable S2
b for the variable B
-------------------------------
case 1 :
assume: hd(s) = true
reduce: mapf(mux(s, s1, feedback(s, s1, b))) == mux(s, mapf(s1),
feedback(s, mapf(s1), f(b)))
nf: mapf(mux(s, s1, feedback(s, s1, b))) == mux(s, mapf(s1),
feedback(s, mapf(s1), f(b)))
-------------------------------
case analysis failed
-----------------------------------------
add rule (C2) : mapf(mux(S1, S2, feedback(S1, S2, B))) = mux(S1,
mapf(S2), feedback(S1, mapf(S2), f(B)))
-----------------------------------------
target is: mapf(mux(S1, S2, feedback(S1, S2, B))) == mux(S1,
mapf(S2), feedback(S1, mapf(S2), f(B)))
expand by: op hd : Stream -> Bool
reduced to: f(hd(mux(S1, S2, feedback(S1, S2, B)))) == hd(mux(S1,
mapf(S2), feedback(S1, mapf(S2), f(B))))
-------------------------------------------
case analysis by MUX-STREAM-CASE-ANALYSE
-------------------------------------------
introduce constant(s):
s for the variable S1
s1 for the variable S2
b for the variable B
-------------------------------
case 1 :
assume: hd(s) = true
reduce: f(hd(mux(s, s1, feedback(s, s1, b)))) == hd(mux(s, mapf(s1),
feedback(s, mapf(s1), f(b))))
nf: true
-------------------------------
case 2 :
assume: hd(s) = false
reduce: f(hd(mux(s, s1, feedback(s, s1, b)))) == hd(mux(s, mapf(s1),
feedback(s, mapf(s1), f(b))))
nf: true
-----------------------------------------
target is: mapf(mux(S1, S2, feedback(S1, S2, B))) == mux(S1,
mapf(S2), feedback(S1, mapf(S2), f(B)))
expand by: op tl : Stream -> Stream
reduced to: mapf(tl(mux(S1, S2, feedback(S1, S2, B)))) == tl(mux(S1,
mapf(S2), feedback(S1, mapf(S2), f(B))))
-------------------------------------------
case analysis by MUX-STREAM-CASE-ANALYSE
-------------------------------------------
introduce constant(s):
s for the variable S1
s1 for the variable S2
b for the variable B
-------------------------------
case 1 :
assume: hd(s) = true
reduce: mapf(tl(mux(s, s1, feedback(s, s1, b)))) == tl(mux(s,
mapf(s1), feedback(s, mapf(s1), f(b))))
nf: true
-------------------------------
case 2 :
assume: hd(s) = false
reduce: mapf(tl(mux(s, s1, feedback(s, s1, b)))) == tl(mux(s,
mapf(s1), feedback(s, mapf(s1), f(b))))
nf: true
-----------------------------------------
result: true
c-rewrite time: 154ms parse time: 7ms
==========================================
close
BOBJ> q
Bye.
awk%
To the BOBJ Examples homepage
To the Tatami project homepage
Maintained by Joseph Goguen
Last modified: Sat Dec 29 11:20:41 PST 2001