1
2===============================================================================
3== This directory contains Juliano's HOL files modified by MJCG & KXS ==
4== [see end of this file for version history] ==
5===============================================================================
6
7composeScript.sml ......... definition of devices and their composition
8devScript.sml.............. definition and theorems on liveness
9compileScript.sml ......... definitions and theorems to support compiler
10compile.sml ............... convert to combinators and compile to circuits
11vsynth.sml ................ convert a circuit made with MAKE_CIRCUIT to Verilog
12FactScript.sml ............ synthesise naive factorial and dump Verilog
13Fact.ml ................... synthesise and simulate factorial and run gtkwave
14Fact32 .................... directory with word32 examples (including factorial)
15dff ....................... Melham's temporal abstraction theory
16Holmakefile ............... instructions for Holmake
17
18*******************************************************************************
19There are six levels of abstraction:
20
21 S: Source (subset of TFL)
22 I: Intermediate (source combinators Atm, Seq, Par, Ite, Rec)
23 D: Devices (handshake hardware combinators: ATM, SEQ, PAR, ITE, REC)
24 N: Netlist (abstract device predicates: unclocked DEL, DELT, DELT and DFF)
25 C: Circuit (clocked synchronous device predicates: Dtype, Dff)
26 V: Verilog (netlist pretty-printed into Verilog)
27
28The main user-level functions are hwDefine, cirDefine, REFINE_ALL and
29MAKE_NETLIST for creating hardware, refining it and then creating a
30netlist representation, and MAKE_CIRCUIT and MAKE_VERILOG for creating
31Verilog HDL output.
32*******************************************************************************
33
34To make generated hardware devices a bit more readable, the following
35(experimental) infixes are now defined in composeScript.sml
36
37 set_fixity ";;" (Infixl 750); overload_on (";;", ``SEQ``)
38 set_fixity "||" (Infixl 650); overload_on ("||", ``PAR``)
39
40The bus concatenation operator <> is defined by:
41
42 |- !f g. f <> g = (\t. (f t,g t))
43
44Abstract device netlists are generated by MAKE_NETLIST and contain the
45following combinational components:
46
47 |- COMB f (inp,out) = !t. out t = f (inp t)
48 |- CONSTANT c out = !t. out t = c
49 |- MUX (sel,in1,in2,out) = !t. out t = (if sel t then in1 t else in2 t
50 |- AND (in1,in2,out) = !t. out t = in1 t /\ in2 t
51 |- OR (in1,in2,out) = !t. out t = in1 t \/ in2 t
52 |- NOT (inp,out) = !t. out t = ~inp t
53
54and sequential components (registers):
55
56 |- DEL (inp,out) = !t. out(t+1) = inp t
57 |- DELT(inp,out) = (out 0 = T) /\ !t. out(t+1) = inp t
58 |- DELF(inp,out) = (out 0 = F) /\ !t. out(t+1) = inp t
59 |- DFF (d,clk,q) = !t. q(t+1) = if POSEDGE clk (t+1) then d(t+1) else q t
60
61where:
62
63 |- POSEDGE s t = if t=0 then F else ~s(t-1) /\ s t
64
65The sequential components are then implemented in terms of clocked reqisters:
66
67 |- Dtype (ck,d,q) = !t. q (t+1) = (if Rise ck t then d t else q t)
68 |- DtypeT (ck,d,q) = (q 0 = T) /\ Dtype(ck,d,q)
69 |- DtypeF (ck,d,q) = (q 0 = F) /\ Dtype(ck,d,q)
70
71where:
72
73 |- Rise s t = ~(s t) /\ s(t+1)
74
75The implementation of DEL, DELT, DELF, DFF in terms of Dtype, DtypeT
76and DtypeF involves a temporal abstraction, since Dtype and the
77flip-flops are edge-triggered on a clock, but DEL, DELT, DELF, DFF are
78not. The refinement from the unclocked level of abstraction to the
79clocked circuit level is implemented formally using infrastructure
80from Melham's theory of temporal abstraction in the directory dff:
81
82Using Melham's dff theories it is proved in compileScript.sml that:
83
84 |- InfRise clk ==> !d q. Dtype (clk,d,q) ==> DEL (d at clk,q at clk)
85 |- InfRise clk ==> !d q. DtypeT (clk,d,q) ==> DELT (d at clk,q at clk)
86 |- InfRise clk ==> !d q. DtypeF (clk,d,q) ==> DELF (d at clk,q at clk)
87
88Where
89
90 |- Inf sig = !t. ?t'. t < t' /\ sig t' (* sig true infinitely often) *)
91 |- InfRise clk = Inf(Rise clk) (* clk has infinitely many rising edges *)
92 |- s at clk = s when (Rise clk) (* s sampled at rising edges of clk *)
93
94The term ``(s when P) n`` gives the value of s at the time when P is
95true on the n-th occasion (``when`` is defined using the choice
96operator in dff/tempabsScript.sml). Thus ``s at clk`` is ``s`` sampled
97at rising edges of ``clk`` (the sampling being just before the clock rises).
98Note that ``s at clk`` is similar to ``s@clk`` in PSL.
99
100Clocked synchronous circuits using combinational logic and the
101registers Dtype and Dff are synthesised using MAKE_CIRCUIT.
102
103*******************************************************************************
104
105
106hwDefine : term frag list -> thm * thm * thm
107--------------------------------------------
108
109Single entrypoint for definitions where proof of termination will
110succeed. Allows measure function to be indicated in same quotation as
111definition, or not.
112
113 hwDefine lib `(eqns) measuring f`
114
115will use f as the measure function and attempt automatic termination
116proof. If successful, returns (|- eqns, |- ind, |- dev)
117
118NB. the recursion equations must be parenthesized; otherwise, strange
119 parse errors result. Also, the name of the defined function must be
120 alphanumeric.
121
122One can also not mention the measure function, as in Define:
123
124 hwDefine `eqns`
125
126which will accept either non-recursive or recursive specifications. It
127returns a triple (|- eqns, |- ind, |- dev) where the ind theorem
128should be ignored (it will be boolTheory.TRUTH).
129
130The result of a call to hwRefine is added to the front of a global
131reference hwDefineLib, which is accessed by REFINE_ALL.
132
133See FactScript.sml for examples.
134
135REFINE: (term -> thm) -> thm -> thm
136-----------------------------------
137
138The first argument of REFINE is a "refine function", refine say,
139which maps a term representing a circuit, <circuit> say, to a theorem
140
141 |- <circuit'> ===> <circuit>
142
143where ``===>`` is defined by:
144
145 |- P ===> Q = !x. P x ==> Q x.
146
147and <circuit'> is a term representing the result of refining <circuit>
148with the function refine.
149
150Evaluating
151
152 REFINE refine (|- <circuit> ===> Dev f)
153
154applies refine to <circuit> to get
155
156 |- <circuit'> ===> <circuit>
157
158and then uses transitivity of ===> (DEV_IMP_TRANS) to deduce:
159
160 |- <circuit'> ===> Dev f
161
162Two useful refine functions are ATM_REFINE and LIB_REFINE.
163
164
165ATM_REFINE : term -> thm
166------------------------
167
168This maps ``DEV f`` to |- ATM f ===> DEV f
169
170
171LIB_REFINE : thm list -> term -> thm
172------------------------------------
173
174Evaluating
175
176 LIB_REFINE
177 [|- <circuit> ===> DEV f1,
178 |- <circuit> ===> DEV f2
179 ...
180 |- <circuit> ===> DEV fn]
181 ``DEV fi``
182
183returns the first theorem |- <circuit> ===> DEV fi that it finds in
184the supplied list (i.e. the supplied library). Fails if no refinement
185theorem found.
186
187Refinement functions (analogously to conversions and tactics) can be
188combined using combinators THENR, ORELSER, REPEATR, DEPTHR.
189
190
191THENR : (term -> thm) * (term -> thm) -> (term -> thm)
192------------------------------------------------------
193
194Combines refinements sequentially.
195
196
197ORELSER : (term -> thm) * (term -> thm) -> (term -> thm)
198--------------------------------------------------------
199
200Tries first refinement and if that fails tries the second one.
201
202REPEATR : (term -> thm) -> term -> thm
203--------------------------------------
204
205Repeates a refinement until no change. Will fail if the refinement
206being repeated fails.
207
208ALL_REFINE: term -> thm
209-----------------------
210
211ALL_REFINE tm evaluatges to the identity refinement |- tm ===> tm
212
213DEPTHR : (term -> thm) -> (term -> thm)
214---------------------------------------------
215
216Scans through a term representing a circuit applying the supplied
217refinement function to each subterm of the form ``DEV f`` and
218either generating
219
220 |- DEV g ===> DEV f
221
222if the refinement function returns this, or, if the refinement
223function fails:
224
225 |- DEV f ===> DEV f
226
227A refined circuit is then build up using the "monotonicity" theorems:
228
229 SEQ_DEV_IMP =
230 |- !P1 P2 Q1 Q2.
231 P1 ===> Q1 /\ P2 ===> Q2
232 ==>
233 (SEQ P1 P2 ===> SEQ Q1 Q2)
234
235 PAR_DEV_IMP =
236 |- !P1 P2 Q1 Q2.
237 P1 ===> Q1 /\ P2 ===> Q2
238 ==>
239 (PAR P1 P2 ===> PAR Q1 Q2)
240
241 ITE_DEV_IMP =
242 |- !P1 P2 P3 Q1 Q2 Q3.
243 P1 ===> Q1 /\ P2 ===> Q2 /\ P3 ===> Q3
244 ==>
245 (ITE P1 P2 P3 ===> ITE Q1 Q2 Q3)
246
247 REC_DEV_IMP =
248 |- !P1 P2 P3 Q1 Q2 Q3.
249 P1 ===> Q1 /\ P2 ===> Q2 /\ P3 ===> Q3
250 ==>
251 (REC P1 P2 P3 ===> REC Q1 Q2 Q3)
252
253 PRECEDE_DEV_IMP
254 |- !f P Q. P ===> Q ==> PRECEDE f P ===> PRECEDE f Q
255
256Note that "DEPTHR refine" should never fail.
257
258REFINE: thm -> thm
259------------------
260
261Refine using definitions in hwDefineLib and then convert all remaining
262DEVs to ATMs. The definition is:
263
264 fun REFINE_ALL th =
265 REFINE
266 (REPEATR
267 (DEPTHR
268 (LIB_REFINE(map #3 (!hwDefineLib))
269 ORELSER ATM_REFINE
270 ORELSER ALL_REFINE)))
271 th;
272
273
274add_combinational : string list -> unit
275---------------------------------------
276
277Add a list of constant names to the constants that are implemented as
278combinational by the compiler. The definition is:
279
280 fun add_combinational l =
281 (combinational_constants := union l (!combinational_constants));
282
283The initial list of combinational constant names (i.e. the initial
284value of the reference combinational_constants) is:
285
286 ["T","F","/\\","\\/","~",",","o","CURRY","UNCURRY","COND",
287 "FST","SND","=","Seq","Par","Ite","0","NUMERAL","BIT1","BIT2","ZERO",
288 "+","-"];
289
290
291is_combinational : term -> bool
292-------------------------------
293
294Test whether a terms is a combinational function of its free variables
295(i.e. is built up using only combinational constants).
296
297AddUnop : string * (term * string) -> unit
298------------------------------------------
299
300Evaluating
301
302 AddUnop("<component name>", (``<HOL operator>``, "<Verilog operator>"))
303
304defines a HOL component and a corresponding Verilog module and adds
305these to the synthesis engine. Currently only types ``:bool``,
306``:num`` and ``:word<n>`` are supported; ``:num`` is converted to
307Verilog words of width [31:0] (and a warning is issued, since this is
308in general invalid). Example:
309
310 AddUnop ("NOT32", (``$~:word32->word32`` , "~"));
311
312If one doesn't intend to generate Verilog, then just give an arbitrary
313string as the Verilog operator (invoking PRINT_VERILOG will then print
314a module that uses this string, but you will only get an error when
315the Verilog is used, e.g. a simulation is attempted).
316
317
318AddBinop : string * (term * string) -> unit
319-------------------------------------------
320
321Evaluating
322
323 AddBinop
324 ("<component name>",
325 (``<uncurried HOL binary operator>``, "<Verilog operator>"))
326
327defines a HOL component and a corresponding Verilog module and adds
328these to the synthesis engine. Currently only types ``:bool``,
329``:num`` and ``:word<n>`` are supported; ``:num`` is converted to
330Verilog words of width [31:0] (and a warning is issued, since this is
331in general invalid). Examples:
332
333 AddBinop ("ADD", (``UNCURRY $+ : num#num->num``, "+"))
334 AddBinop ("SUB", (``UNCURRY $- : num#num->num``, "-"))
335
336 AddBinop ("ADD32", (``UNCURRY $+ : word32#word32->word32``, "+"));
337 AddBinop ("SUB32", (``UNCURRY $- : word32#word32->word32``, "-"))
338
339 AddBinop ("LESS32", (``UNCURRY $< : word32#word32->bool``, "<"));
340 AddBinop ("EQ32", (``UNCURRY $= : word32#word32->bool``, "=="))
341
342If one doesn't intend to generate Verilog, then just give an arbitrary
343string as the Verilog operator (invoking PRINT_VERILOG will then print
344a module that uses this string, but you will only get an error when
345the Verilog is used, e.g. a simulation is attempted).
346
347
348MAKE_NETLIST : thm -> thm
349-------------------------
350
351Evaluating
352
353 MAKE_NETLIST (|- <device> ===> DEV f)
354
355unfolds <device> using the definitions of ATM, SEQ, PAR, ITE and REC
356and normalises the resulting term into a form, <netlist> say,
357corresponding to a netlist, and returns
358
359 |- <netlist>
360 ==>
361 DEV f (load,(inp1<>...<>inpm),done,(out1<>...<>outn))
362
363
364MAKE_CIRCUIT : thm -> thm
365-------------------------
366
367Evaluating
368
369 MAKE_CIRCUIT (|- <device> ===> DEV f)
370
371unfolds <device> into a netlist, then replaces DFF by an
372implementation in terms of DEL and DELT, and then, using Melham's
373temporal abstraction theory in dff, refines any unclocked DEL, DELT
374and DELF to clocked Dtype and Dff, and returns:
375
376 |- InfClock clk
377 ==>
378 <circuit>
379 ==>
380 DEV f (load at clk,
381 (inp1<>...<>inpm) at clk,
382 done at clk,
383 (out1<>...<>outn) at clk)
384
385See FactScript.sml for examples (e.g. FACT_cir).
386
387
388cirDefine : term frag list -> thm * thm * thm
389--------------------------------------------
390
391Invoke hwDefine and then apply MAKE_CIRCUIT and REFINE_ALL to the device:
392
393fun cirDefine qdef =
394 let val (def,ind,dev) = hwDefine qdef
395 in
396 (def, ind, MAKE_CIRCUIT(REFINE_ALL dev))
397 end;
398
399
400PRINT_VERILOG : thm -> unit
401---------------------------
402
403Evaluating
404
405 PRINT_VERILOG
406 (|- InRise clk
407 ==>
408 (?v0 .... vn. <circuit>)
409 ==>
410 DEV fun (load at clk,
411 (inp1 <> ... <> inpu) at clk,
412 done at clk,
413 (out1 <> ... <> outv) at clk))
414
415creates a module called fun that has the definitions of the modules
416used in <circuit>, and prints it and the definitions it needs to
417fun.vl.
418
419The header is:
420
421 module fun (clk,load,inp1,...,inpu,done,out1,...,outv);
422 input clk,load;
423 input [<size>:0] inp1,inp2;
424 output done;
425 output [<size>:0] out;
426 wire clk,done;
427
428where <size> is the appropriate width computed from the types. The
429internal variables v0, ... ,vn are declared to be wires of appropriate
430widths (computed from their types).
431
432Types ``:num`` are converted to Verilog wires or registers of width
433[31:0], which is not in general valid. When such a conversion occurs,
434a warning like:
435
436 Warning: type of inp is ``:num``, but is compiled to [31:0].
437
438is printed. These warnings can be suppressed by evaluating:
439
440 numWarning := false;
441
442(the ML reference numWarning has a default of true).
443
444
445SIMULATE : thm -> (string * string) list -> unit
446------------------------------------------------
447
448If thm is:
449
450 |- InRise clk
451 ==>
452 (?v0 .... vn. <circuit>)
453 ==>
454 DEV fun (load at clk,
455 (inp1 <> ... <> inpu) at clk,
456 done at clk,
457 (out1 <> ... <> outv) at clk)
458
459the evaluating:
460
461 SIMULATE thm [("inp1","val1"),...,("inpn","valn")]
462
463dumps Verilog using
464
465 PRINT_SIMULATION thm (!period_default) [("inp1","val1"),...,("inpn","valn")]
466
467(see below). It then runs a Verilog simulator on fun.vl and then calls
468a waveform viewer on fun.vcd.
469
470Currently iverilog (Icarus Verilog:
471http://www.icarus.com/eda/verilog/) and cver (GPL Cver:
472http://www.pragmatic-c.com/gpl-cver/) are supported as Verilog
473simulators and gtkwave (GTKWave:
474ftp://ftp.cs.man.ac.uk/pub/amulet/balsa/other-software/gtkwave-2.0.0pre5.tar.gz)
475and dinotrace (which comes with GPS Cver) as waveform viewers.
476
477GPS Cver and dinotrace are particularly easy to install, and are now
478the default. To install them, connect to examples/dev and execute:
479
480 wget http://www.pragmatic-c.com/gpl-cver/downloads/gplcver-2.10c.linux.bin.tar.bz2;
481 bunzip2 gplcver-2.10c.linux.bin.tar.bz2;
482 tar -xf gplcver-2.10c.linux.bin.tar
483
484which should create a directory gplcver-2.10c.linux.bin.
485
486SIMULATE should then just work. Test by evaluating "use Fact.ml;" in hol,
487which should launch dinotrace showing a trace of FACT 4 being computed.
488
489You can change the default clock period, which is held in a reference
490
491 val period_default = ref 5;
492
493To change the default simulator and viewer change the references
494verilog_simulator and waveform_viewer. For example, to change to
495iverilog and gtkwave do:
496
497 val verilog_simulator = ref iverilog;
498 val waveform_viewer = ref gtkwave;
499
500The executables are held in references, which have default values:
501
502 val iverilog_path = ref "/usr/bin/iverilog";
503 val vvp_path = ref "/usr/bin/vvp";
504 val gtkwave_path = ref "/usr/bin/gtkwave -a";
505 val cver_path = ref "./gplcver-2.10c.linux.bin/bin/cver";
506 val dinotrace_path = ref "./gplcver-2.10c.linux.bin/bin/dinotrace";
507
508Note that cver_path and dinotrace_path are correct if the installation
509described above is performed.
510
511
512PRINT_SIMULATION : thm -> int -> (string * string) list -> unit
513---------------------------------------------------------------
514
515Evaluating
516
517 PRINT_SIMULATION thm period stimulus
518
519prints both the Verilog corresponding to thm (see PRINT_VERILOG) and
520then adds a clock and a module Main containing an instance of the
521clock and an instance of the module generated from thm.
522
523The instance of Clock is created with time between edges as specified
524by the parameter period (so really period is 2*period).
525
526The clock line clk and the handshake completion line done are declared
527to be boolean wires.
528
529The input load is declared to be a boolean register and the inputs
530inp1, ... ,inpu are declared to be registers of the appropriate width.
531
532A dumpfile called "file.vcd" is created. If the reference variable
533dump_all_flag is false (the default) then only changes to clk, load,
534and signals inp1, ... ,inpu, done, out1, ... ,outv are declared to
535have their changes dumped to the VCD file. If dump_all_flag is true,
536then changes to all variables are dumped.
537
538The input variables are driven according to the parameter stimulus,
539which is an ML list of tuples of the form:
540
541 [("inp1",val),...,("inpu",val)]
542
543where each input is driven with the supplied value (a string that
544prints to a valid Verilog expression).
545
546I am using Icarus Verilog for simulation
547(http://www.icarus.com/eda/verilog/) and GTKWave
548(http://www.cs.man.ac.uk/apt/tools/gtkwave/) for viewing VCD files.
549Both are public domain and seem to work.
550
551
552*******************************************************************************
553
554Auxiliary functions of interest include the following.
555
556Convert : thm -> thm
557--------------------
558
559Convert (|- f x = e) returns a theorem |- f = p, where p is a
560combinatory expression built from the combinators Seq, Par and Ite.
561
562
563RecConvert: : thm -> thm -> thm
564-------------------------------
565
566RecConvert (|- f x = if f1 x then f2 x else f(f3 x)) (|- TOTAL(f1,f2,f3))
567returns a theorem
568
569 |- f = Rec(p1,p2,p3)
570
571where p1, p2 and p3 are combinatory expressions built from the
572combinators Seq, Par and Ite.
573
574A term PRECEDE f d represents a device d preceded by combinational
575logic and a term FOLLOW d f represents a device d followed by
576combinational logic.
577
578 |- PRECEDE f d =
579 (\(load,inp,done,out). ?v. COMB f (inp,v) /\ d(load,v,done,out))
580
581 |- FOLLOW d f =
582 (\(load,inp,done,out). ?v. d(load,inp,done,v) /\ COMB f (v,out))
583
584The function f representing the combinational logic must only contain
585constants declared combinational by having their names included in the
586ML assignable list "combinational_constants".
587
588Currently PRECEDE and FOLLOW are eliminated when generating netlists,
589but they may appear in the output of the compiler (see the
590CompileConvert example below).
591
592
593CompileProg : thm list -> term -> thm
594-------------------------------------
595
596CompileProg takes a program and a constant defined in the program
597
598 CompileProg : thm list -> term -> thm
599 -------- ----
600 program constant
601
602When the compiler encounters a function f that isn't an application of
603Seq, Par or Ite, then DEV f is generated. It is assumed this
604will subsequently be refined to hardware (see Refine).
605
606Compile : thm -> thm
607--------------------
608
609Compile (|- c = e) = CompileProg [|- c = e] ``c``
610
611
612CompileConvert : thm -> thm
613---------------------------
614
615Converts a non-recursive equation to combinators and then compiles to
616a device implementation.
617
618Example:
619
620 Fact;
621 > val it = |- !n. Fact n = SND (FactIter (n,1)) : thm
622
623 - CompileConvert Fact;
624 > val it =
625 |- FOLLOW (PRECEDE (Par (\n. n) (\n. 1)) (DEV FactIter)) SND
626 ===>
627 DEV Fact : thm
628
629
630RecCompileConvert : thm -> thm -> thm
631-------------------------------------
632
633Converts a recursive equation to combinators and then compiles to a
634device implementation. Needs a totality theorem (user-supplied as third
635argument).
636
637Example:
638
639- val FactIter =
640 |- FactIter (n,acc) =
641 (if n = 0 then (n,acc) else FactIter (n - 1,n * acc))
642
643- val FactIter_TOTAL =
644 |- TOTAL
645 ((\(n,acc). n = 0),(\(n,acc). (n,acc)),(\(n,acc). (n - 1,n * acc)))
646
647 - RecCompileConvert FactIter FactIter_TOTAL;
648 > val it =
649 |- REC(FOLLOW (DEV (\(n,acc). n) || DEV (\(n,acc). 0)) (UNCURRY $=))
650 (DEV (\x. x))
651 (DEV (\x. FST x - 1) || PRECEDE (\x. x) (DEV (UNCURRY $*)))
652 ===>
653 DEV FactIter
654
655
656COMB_SYNTH_CONV : term -> thm
657-----------------------------
658
659One step of conversion of
660
661 ``COMB
662 (\(i1,...,im). (<term1>,...,<termn>)
663 (inp1 <> ... <> inpm, out1 <> .... outn)``
664
665to a netlist.
666
667Example:
668
669- COMB_SYNTH_CONV
670 ``COMB (\(m,n,p). (m-p, SUC(m+n+(p-1)))) (in1<>in2<>in3,out1<>out2)``;
671> val it =
672 |- COMB (\(m,n,p). (m - p,SUC (m + n + (p - 1))))
673 (in1 <> in2 <> in3,out1 <> out2) =
674 COMB (\(m,n,p). m - p) (in1 <> in2 <> in3,out1) /\
675 COMB (\(m,n,p). SUC (m + n + (p - 1))) (in1 <> in2 <> in3,out2) : thm
676
677To completely convert to a netlist COMB_SYNTH_CONV needs to be
678iterated. Example:
679
680- REDEPTH_CONV COMB_SYNTH_CONV
681 ``COMB (\(m,n,p). (m-p, SUC(m+n+(p-1)))) (in1<>in2<>in3,out1<>out2)``;
682> val it =
683 |- COMB (\(m,n,p). (m - p,SUC (m + n + (p - 1))))
684 (in1 <> in2 <> in3,out1 <> out2) =
685 (?v709 v710.
686 (v709 = in1) /\ (v710 = in3) /\
687 COMB (UNCURRY $-) (v709 <> v710,out1)) /\
688 ?v711.
689 (?v712 v713.
690 (?v714 v715.
691 (v714 = in1) /\ (v715 = in2) /\
692 COMB (UNCURRY $+)
693 (v714 <> v715,v712)) /\
694 (?v716 v717.
695 (v716 = in3) /\ CONSTANT 1 v717 /\
696 COMB (UNCURRY $-)
697 (v716 <> v717,v713)) /\
698 COMB (UNCURRY $+)
699 (v712 <> v713,v711)) /\
700 COMB SUC (v711,out2) : thm
701
702Note that the redundant variables are pruned by MAKE_NETLIST and also,
703for readability, the example above uses ``v709`` but COMB_SYNTH_CONV
704actually generates ``%%genvar%%709`.
705
706COMB_SYNTH_CONV may print out some diagnostic stuff if it fails to
707prove certain subgoals (though it may nevertheless still produce
708something reasonable). This output can be switched off by setting the
709ML reference "if_print_flag" to false.
710
711
712===============================================================================
713====== ML definitions and commands to define 32-bit bitwise exclusive-or ======
714===============================================================================
715
716(*****************************************************************************)
717(* The sources have lots of cut-and-paste-and-tweak style repetition for the *)
718(* various combinational components (NOT, AND, OR, MUX, ADD, SUB, LESS, EQ). *)
719(* *)
720(* The functions AddUnop and AddBinop cope with some of the repetition, *)
721(* but what follows might also be useful documentation. *)
722(* *)
723(* Here are the steps currently needed to add a new component, *)
724(* illustrated with the addition of 32-bit bitwise exclusive-or (XOR32). *)
725(* *)
726(* These steps are a manual version of what is done when *)
727(* *)
728(* AddBinop ("XOR32", (``UNCURRY $# : word32#word32->word32``, "^")); *)
729(* *)
730(* is evaluated. *)
731(*****************************************************************************)
732
733(*****************************************************************************)
734(* Step 1 *)
735(* ------ *)
736(* Define the component in HOL *)
737(* (assumes word32Theory loaded and open) *)
738(*****************************************************************************)
739val XOR32_def =
740 Define
741 `XOR32(in1,in2,out) = !t. out t = (in1 t) # (in2 t)`;
742
743(*****************************************************************************)
744(* Step 2 *)
745(* ------ *)
746(* Prove some boilerplate theorems and add to global lists: *)
747(*****************************************************************************)
748val COMB_XOR32 =
749 store_thm
750 ("COMB_XOR32",
751 ``COMB (UNCURRY $#) (in1 <> in2, out) = XOR32(in1,in2,out)``,
752 RW_TAC std_ss [COMB_def,BUS_CONCAT_def,XOR32_def]);
753
754add_combinational_components[COMB_XOR32];
755
756val XOR32_at =
757 store_thm
758 ("XOR32_at",
759 ``XOR32(in1,in2,out)
760 ==>
761 XOR32(in1 at clk,in2 at clk,out at clk)``,
762 RW_TAC std_ss [XOR32_def,at_def,tempabsTheory.when]);
763
764add_temporal_abstractions[XOR32_at];
765
766(*****************************************************************************)
767(* Step 3 *)
768(* ------ *)
769(* Define a Verilog module as an ML string (XOR32vDef), a function to *)
770(* create an instance with a given size as a string (XOR32vInst), an *)
771(* instance counter (XOR32vInst_count -- used to create unique names for *)
772(* instances) and a function to print a HOL term ``XOR32(in1,in2,out)`` as *)
773(* an instance, using the type of ``out`` to compute the word width *)
774(* needed to set parameter "size" in XOR32vDef (termToVerilog_XOR32). *)
775(* These functions are added to a couple of global lists. *)
776(*****************************************************************************)
777val XOR32vDef =
778"// Combinational bitwise XOR32\n\
779\module XOR32 (in1,in2,out);\n\
780\ parameter size = 31;\n\
781\ input [size:0] in1,in2;\n\
782\ output [size:0] out;\n\
783\\n\
784\ assign out = in1 ^ in2;\n\
785\\n\
786\endmodule\n\
787\\n";
788
789val XOR32vInst_count = ref 0;
790fun XOR32vInst (out:string->unit) [("size",size)] [in1_name,in2_name,out_name] =
791 let val count = !XOR32vInst_count
792 val _ = (XOR32vInst_count := count+1);
793 val inst_name = "XOR32" ^ "_" ^ Int.toString count
794 in
795 (out " XOR32 "; out inst_name;
796 out " (";out in1_name;out",";out in2_name;out",";out out_name; out ");\n";
797 out " defparam ";out inst_name; out ".size = "; out size;
798 out ";\n\n")
799 end;
800
801add_module ("XOR32", (XOR32vDef, XOR32vInst));
802
803fun termToVerilog_XOR32 (out:string->unit) tm =
804 if is_comb tm
805 andalso is_const(fst(strip_comb tm))
806 andalso (fst(dest_const(fst(strip_comb tm))) = "XOR32")
807 andalso is_pair(rand tm)
808 andalso (length(strip_pair(rand tm)) = 3)
809 andalso all is_var (strip_pair(rand tm))
810 then XOR32vInst
811 out
812 [("size", var2size(last(strip_pair(rand tm))))]
813 (map (fst o dest_var) (strip_pair(rand tm)))
814 else raise ERR "termToVerilog_XOR32" "bad component term";
815
816termToVerilogLib := (!termToVerilogLib) @ [termToVerilog_XOR32];
817
818===============================================================================
819== This directory contains Juliano's HOL files modified by MJCG & KXS ==
820== [Revised version incorporating Juliano's new treatment of recursion] ==
821== [Revised version incorporating liveness] ==
822== [04.01.05: improved proofs from KXS in composeScript.sml & devScript.sml] ==
823== [09.01.05: MJCG added converter to combinators Seq, Par, Ite, Rec] ==
824== [13.01.05: major tidy and update by MJCG] ==
825== [17.01.05: MJCG installed hwDefine and improved examples from KXS] ==
826== [18.01.05: MJCG added Refine and revised FactScript.sml] ==
827== [19.01.05: MJCG changed to use refinement combinators] ==
828== [20.01.05: MJCG added netlist synthesis] ==
829== [21.01.05: MJCG minor changes and README update] ==
830== [27.01.05: MJCG added hw synthesis improvements] ==
831== [28.01.05: MJCG more optimisations and updated README] ==
832== [29.01.05: MJCG added COMB_SYNTH_CONV removed SEL operators] ==
833== [30.01.05: MJCG added dff: Melham's temporal abstraction theory] ==
834== [01.02.05: MJCG minor tweaks to MAKE_NETLIST and COMB_SYNTH_CONV] ==
835== [06.02.05: MJCG added refinement to clocked dtype registers] ==
836== [08.02.05: MJCG added ?-quantification of internal wires to MAKE_CIRCUIT] ==
837== [10.02.05: MJCG split input and output busses] ==
838== [11.02.05: Holmakefile (thanks to MN) + code improvements (thanks to KXS)]==
839== [14.02.05: MJCG added vsynth (defines MAKE_VERILOG)] ==
840== [15.02.05: MJCG revised MAKE_NETLIST and MAKE_CIRCUIT] ==
841== [18.02.05: MJCG revised MAKE_VERILOG in vsynth; added MAKE_SIMULATION] ==
842== [28.02.05: MJCG revised added SIMULATE to run iverilog and gtkwave] ==
843== [20.04.05: MJCG updated section on adding new components] ==
844== [17.05.05: MJCG added hwDefineLib and REFINE_ALL] ==
845== [30.05.05: MJCG added cirDefine] ==
846===============================================================================
847