1 (* From the SML
/NJ benchmark suite
. *)
8 val testit
: TextIO.outstream
-> unit
14 fun fold f x y
= List.foldr f y x
15 fun revfold f x y
= List.foldl f y x
16 val makestring
= Int.toString
27 (case Char.fromString x
29 | NONE
=> raise NotAChar
)
31 fun ordof(s
, i
) = Char.ord(String.sub(s
, i
))
34 val explode
= (fn x
=> map
Char.toString (explode x
))
35 val implode
= (fn x
=> implode (map fromStr x
))
36 fun ord s
= Char.ord (fromStr s
)
38 val output
= TextIO.output
39 val std_out
= TextIO.stdOut
40 val open_in
= TextIO.openIn
41 val open_out
= TextIO.openOut
42 val close_in
= TextIO.closeIn
43 val close_out
= TextIO.closeOut
46 case TextIO.inputLine ins
of
49 type instream
= TextIO.instream
50 type outstream
= TextIO.outstream
51 fun outputc f x
= TextIO.output(f
, x
)
56 (case Real.fromString s
58 | _
=> raise NotAReal
)
61 (strToReal ((Int.toString x
) ^
".0"))
66 fun wrap (f
: Word.word * Word.word -> Word.word)
67 = (fn (x
: int, y
: int) =>
68 Word.toInt(f(Word.fromInt x
, Word.fromInt y
)))
70 val orb
= wrap
Word.orb
71 val andb
= wrap
Word.andb
72 val xorb
= wrap
Word.xorb
73 val lshift
= wrap
Word.<<
74 val rshift
= wrap
Word.>>
79 val inc
= fn x
=> (x
:= !x
+ 1)
80 val dec
= fn x
=> (x
:= !x
- 1)
88 val new
: unit
-> 'a stringmap
89 val add
: 'a stringmap
-> string * 'a
-> unit
90 val rm
: 'a stringmap
-> string -> unit
91 val map
: 'a stringmap
-> string -> 'a
92 val app
: (string * 'a
-> unit
) -> 'a stringmap
-> unit
93 val isin
: 'a stringmap
-> string -> bool
94 val extract
: 'a stringmap
-> 'a list
97 structure Stringmap
: STRINGMAP
=
99 type 'a stringmap
= (string * 'a
) list array
104 (* a
string hashing function
105 returns a number between
0 and tableSize
-1 *)
106 fun hash(str
: string) : int =
107 let val nchars
= String.size str
111 loop(i
+1,n
,(hashFactor
* r
+ ordof(str
,i
)) mod tableSize
)
115 (* while !i
< nchars
do
116 (n
:= (hashFactor
* !n
+ ordof(str
, !i
)) mod tableSize
;
122 (* create a new stringmap
*)
123 fun new (): 'a stringmap
= array(tableSize
,nil
)
125 (* add a mapping pair s
+-> x to the stringmap a
*)
127 let val index
= hash s
128 in update(a
,index
,(s
,x
)::(a sub index
))
131 (* apply the stringmap a to the index
string s
*)
133 let fun find ((s
',x
)::r
) = if s
=s
' then x
else find r
134 | find nil
= raise Stringmap
135 in find (a
sub (hash s
))
138 (* return
true if the
string is
in the map
, false otherwise
*)
141 handle Stringmap
=> false)
143 (* remove all pairs mapping
string s from stringmap a
*)
144 fun rm a s
= let fun f ((b
as (s
',j
))::r
) =
145 if s
=s
' then f r
else b
:: f r
148 in update(a
,index
, f(a sub index
))
151 (* apply a function f to all mapping pairs
in stringmap a
*)
152 fun app (f
: string * 'a
-> unit
) a
=
154 | zap n
= let val m
= n
-1 in List.app
f (a sub m
); zap m
end
158 (* extract the stringmap items
as a list
*)
161 if n
< Array
.length a
then (a sub n
) :: atol (n
+ 1)
164 fun flatten (a
, b
) = a @ b
165 val fal
= fold flatten al nil
167 val answer
= List.map strip fal
178 val stringListString
: string list
-> string
184 |
sl (h
::nil
) = h ^
"]"
185 |
sl (h
::n
::t
) = h ^
"," ^
sl (n
::t
)
187 fun stringListString l
= "[" ^ sl l
190 signature SortObjSig
=
193 val gt
: obj
* obj
-> bool
196 functor Sort ( objfun
: SortObjSig
) :
199 val sort
: obj list
-> obj list
206 type obj
= objfun
.obj
209 let fun m2 (nil
, b
) = b
211 |
m2 (ha
::ta
, hb
::tb
) =
212 if gt(ha
, hb
) then hb
::(m2(ha
::ta
, tb
))
213 else ha
::(m2(ta
, hb
::tb
))
216 |
ml (h1
::h2
::nil
) = m2(h1
, h2
)
217 |
ml (h1
::h2
::l
) = ml
[m2(h1
, h2
), (ml l
)]
219 ml (map (fn x
=> [x
]) l
)
227 fun gt(a
:obj
, b
:obj
) = a
> b
231 structure INTSort
= Sort ( IntImp
)
239 val makeEQ
: ('a
* 'a
-> bool) -> 'a set
240 val listToSet
: ''a list
-> ''a set
241 val listToSetEQ
: ('a
* 'a
-> bool) * 'a list
-> 'a set
242 val add
: 'a set
* 'a
-> 'a set
243 val union
: 'a set
* 'a set
-> 'a set
244 val listUnion
: 'a set list
-> 'a set
245 val listUnionEQ
: ('a
* 'a
-> bool) * 'a set list
-> 'a set
246 val rm
: 'a set
* 'a
-> 'a set
247 val intersect
: 'a set
* 'a set
-> 'a set
248 val diff
: 'a set
* 'a set
-> 'a set
249 val member
: 'a set
* 'a
-> bool
250 val set
: 'a set
-> 'a list
251 val mag
: 'a set
-> int
252 val empty
: 'a set
-> bool
255 datatype 'a set
= S
of ('a
*'a
->bool) * 'a list
260 fun eqf (x
, y
) = x
= y
262 val make
= S (eqf
, nil
)
264 fun makeEQ eqf
= S (eqf
, nil
)
266 fun set (S (eqf
, a
)) = a
268 fun member (S (eqf
, nil
), e
) = false
269 |
member (S (eqf
, (s
::t
)), e
) = eqf(e
, s
) orelse member(S (eqf
, t
), e
)
271 fun add(st
as (S (eqf
, s
)), e
) = if member(st
, e
) then st
else S(eqf
, e
::s
)
273 fun listToSetEQ (eqf
, l
) =
274 let fun f (nil
, s
) = s
275 |
f (h
::t
, s
) = f(t
, add(s
, h
))
280 fun listToSet l
= listToSetEQ (eqf
, l
)
283 fun union (a
, S (eqf
, nil
)) = a
284 |
union (S (eqf
, nil
), b
) = b
285 |
union (S (eqf
, e
::a
), b
) = union(S (eqf
, a
), add(b
, e
))
287 fun listUnion (h
::t
) = fold union t h
288 | listUnion _
= raise LISTUNION
290 fun listUnionEQ (eqf
, l
) = fold union
l (makeEQ eqf
)
293 fun rm (S (eqf
, nil
), x
) = raise SET
294 |
rm (S (eqf
, s
::t
), x
) =
295 if eqf(s
, x
) then S (eqf
, t
) else S(eqf
, s
:: set(rm(S (eqf
, t
), x
)))
297 fun intersect1 (a
, S (eqf
, nil
), c
) = S (eqf
, c
)
298 |
intersect1 (S (eqf
, nil
), b
, c
) = S (eqf
, c
)
299 |
intersect1 (S (eqf
, a
::t
), b
, c
) =
300 if member(b
, a
) then intersect1(S (eqf
, t
), b
, a
::c
)
301 else intersect1(S (eqf
, t
), b
, c
)
303 fun intersect (a
, b
) = intersect1 (a
, b
, nil
)
305 fun diff (S (eqf
, nil
), b
) = S (eqf
, nil
)
306 |
diff (S (eqf
, a
::t
), b
) = if member(b
, a
) then diff(S (eqf
, t
), b
)
307 else S (eqf
, a
:: set(diff(S (eqf
, t
), b
)))
310 fun mag s
= List.length (set s
)
312 (* fun empty s
= set s
= nil
*)
314 fun empty (S(eqf
, nil
)) = true
315 |
empty (S(eqf
, _
)) = false
318 (* Copyright
1989 by AT
&T Bell Laboratories
*)
319 (* updated by John Danskin at Princeton
*)
322 type reg
= (int*string)
323 type label
= (int*string)
327 | LABVAL
of int * int
329 datatype arithop
= imul | iadd | isub | idiv
330 | orb | andb | xorb | rshift | lshift
331 | fadd | fdiv | fmul | fsub
332 |
real | floor | logb
334 datatype comparison
= ilt | ieq | igt | ile | ige | ine
335 | flt | feq | fgt | fle | fge | fne
336 | inrange | outofrange
338 FETCH
of {immutable
: bool, offset
: int, ptr
: reg
, dst
: reg
}
339 (* dst
:= M
[ptr
+offset
]
340 if immutable
then unaffected by any STORE
341 other than through the allocptr
*)
342 | STORE
of {offset
: int, src
: reg
, ptr
: reg
}
343 (* M
[ptr
+offset
] := src
*)
344 | GETLAB
of {lab
: label
, dst
: reg
}
345 | GETREAL
of {value
: string, dst
: reg
}
346 | ARITH
of {oper
: arithop
, src1
: reg
, src2
: reg
, dst
: reg
}
347 | ARITHI
of {oper
: arithop
, src1
: reg
, src2
: int, dst
: reg
}
348 | MOVE
of {src
: reg
, dst
: reg
}
349 | BRANCH
of {test
: comparison
, src1
: reg
, src2
: reg
, dst
: label
,
351 | JUMP
of {dst
: reg
, live
: reg list
}
352 | LABEL
of {lab
:label
, live
: reg list
}
353 | WORD
of {value
: int}
354 | LABWORD
of {lab
: label
}
356 | BOGUS
of {reads
: reg list
, writes
: reg list
}
358 val opcodeEq
: opcode
* opcode
-> bool = (op =)
362 structure AbsMachImp
:
366 val oeq
: operation
* operation
-> bool
368 val ceq
: comparison
* comparison
-> bool
369 val write_o
: operation
-> reg Set
.set
370 val read_o
: operation
-> reg Set
.set
371 val write_c
: comparison
-> reg Set
.set
372 val read_c
: comparison
-> reg Set
.set
373 val resources_ok
: operation list
* comparison list
-> bool
375 ASSIGNMENT
of operation
376 | LABELREF
of int * operation
377 | COMPARISON
of int * operation
378 | FLOW
of int * operation
379 | TARGET
of int * operation
383 val classify
: operation
-> codetypes
384 val maxreg
: AbsMach
.opcode list
-> int
388 type reg
= int (* register strings will gum up set operations etc
*)
389 type operation
= AbsMach
.opcode
390 type comparison
= AbsMach
.opcode
392 fun oeq (a
, b
) = AbsMach
.opcodeEq(a
, b
)
393 fun ceq (a
, b
) = AbsMach
.opcodeEq(a
, b
)
399 fun srl rl
= Set
.listToSet((map reg
) rl
)
402 val immutableMem
= ~
1
406 (* comparisons are limited to one because
of difficulty writing larger trees
*)
407 fun resources_ok(ops
, c
) = (List.length ops
) <= 4 andalso (List.length c
) <= 1
409 fun allocptr r
= reg r
= 1
415 fn FETCH
{dst
, ...} => sr dst
417 if allocptr ptr
then listToSet
[immutableMem
, mutableMem
]
418 else listToSet
[mutableMem
]
419 | GETLAB
{dst
, ...} => sr dst
420 | GETREAL
{dst
, ...} => sr dst
421 | ARITH
{dst
, ...} => sr dst
422 | ARITHI
{dst
, ...} => sr dst
423 | MOVE
{dst
, ...} => sr dst
424 | JUMP _
=> listToSet
[flowControl
]
425 | BOGUS
{writes
, ...} => srl writes
431 fun write_c c
= Set
.listToSet
[flowControl
]
433 val std_reg_list
= [(1, ""), (2, ""), (3, ""), (4, ""), (5, "")]
439 fn FETCH
{immutable
, ptr
, ...} =>
440 let val mem
= if immutable
then immutableMem
else mutableMem
444 | STORE
{src
, ptr
, ...} => srl
[src
, ptr
]
445 | ARITH
{src1
, src2
, ...} => srl
[src1
, src2
]
446 | ARITHI
{src1
, ...} => sr src1
447 | MOVE
{src
, ...} => sr src
448 | BRANCH
{src1
, src2
, ...} => srl
[src1
, src2
]
449 | JUMP
{dst
, ...} => srl (dst
:: std_reg_list
)
450 | BOGUS
{reads
, ...} => srl reads
456 fun read_o i
= read i
457 fun read_c i
= read i
460 ASSIGNMENT
of operation
461 | LABELREF
of int * operation
462 | COMPARISON
of int * operation
463 | FLOW
of int * operation
464 | TARGET
of int * operation
470 let fun f (a
, b
) = Int.max(a
, b
)
472 (Set
.set (Set
.listUnion((map write_o li
) @
482 fn FETCH _
=> ASSIGNMENT i
483 | STORE _
=> ASSIGNMENT i
484 | GETLAB
{lab
, dst
} => LABELREF(label lab
, i
)
485 | GETREAL _
=> ASSIGNMENT i
486 | ARITH _
=> ASSIGNMENT i
487 | ARITHI _
=> ASSIGNMENT i
489 if reg src
= reg dst
then NERGLE
491 | BRANCH
{test
,src1
,src2
,dst
,live
} =>
492 if test
= ieq
andalso (reg src1
) = (reg src2
)
493 then FLOW (label dst
, i
)
494 else COMPARISON (label dst
, i
)
496 | LABEL
{lab
, ...} => TARGET(label lab
, i
)
498 | LABWORD _
=> JUNK i
500 | BOGUS _
=> ASSIGNMENT i
505 structure ReadAbs
: sig val read
: instream
-> AbsMach
.opcode list
end =
515 fun error s
= (print("Error in line "^makestring i^
": "^s^
"\n");
518 fun b(" "::rest
) = b rest | b rest
= rest
521 fn "i"::"m"::"u"::"l"::l
=> (imul
,l
)
522 |
"i"::"a"::"d"::"d"::l
=> (iadd
,l
)
523 |
"i"::"s"::"u"::"b"::l
=> (isub
,l
)
524 |
"i"::"d"::"i"::"v"::l
=> (idiv
,l
)
525 |
"o"::"r"::"b"::" "::l
=> (orb
,l
)
526 |
"a"::"n"::"d"::"b"::l
=> (andb
,l
)
527 |
"x"::"o"::"r"::"b"::l
=> (xorb
,l
)
528 |
"r"::"s"::"h"::"i"::"f"::"t"::l
=> (rshift
,l
)
529 |
"l"::"s"::"h"::"i"::"f"::"t"::l
=> (lshift
,l
)
530 |
"f"::"a"::"d"::"d"::l
=> (fadd
,l
)
531 |
"f"::"d"::"i"::"v"::l
=> (fdiv
,l
)
532 |
"f"::"m"::"u"::"l"::l
=> (fmul
,l
)
533 |
"f"::"s"::"u"::"b"::l
=> (fsub
,l
)
534 |
"r"::"e"::"a"::"l"::l
=> (real,l
)
535 |
"f"::"l"::"o"::"o"::"r"::l
=> (floor
,l
)
536 |
"l"::"o"::"g"::"b"::l
=> (logb
,l
)
537 | _
=> error
"illegal arithmetic operator"
540 fn "i"::"l"::"t"::l
=> (ilt
,l
)
541 |
"i"::"e"::"q"::l
=> (ieq
,l
)
542 |
"i"::"g"::"t"::l
=> (igt
,l
)
543 |
"i"::"l"::"e"::l
=> (ile
,l
)
544 |
"i"::"g"::"e"::l
=> (ige
,l
)
545 |
"i"::"n"::"e"::l
=> (ine
,l
)
546 |
"f"::"l"::"t"::l
=> (flt
,l
)
547 |
"f"::"e"::"q"::l
=> (feq
,l
)
548 |
"f"::"g"::"t"::l
=> (fgt
,l
)
549 |
"f"::"l"::"e"::l
=> (fle
,l
)
550 |
"f"::"g"::"e"::l
=> (fge
,l
)
551 |
"f"::"n"::"e"::l
=> (fne
,l
)
552 |
"i"::"n"::"r"::"a"::"n"::"g"::"e"::l
=> (inrange
,l
)
553 |
"o"::"u"::"t"::"o"::"f"::"r"::"a"::"n"::"g"::"e"::l
=> (outofrange
,l
)
554 | _
=> error
"illegal comparison operator"
556 fun immut("i"::l
) = (true,l
) |
immut("m"::l
) = (false,l
)
557 | immut _
= error
"i or m required"
561 fun f(n
,l0
as d
::l
) = if d
>="0" andalso d
<="9"
562 then f(n
*10+ord(d
)-z
, l
)
564 | f _
= error
"in readabs.int"
569 let fun f("/"::l
) = (nil
,l
)
570 |
f(a
::l
) = let val (s
,l
') = f l
573 | f _
= error
"name not terminated by \"/\""
579 let val (sign
,s
) = case explode s
of "~"::rest
=> (~
1.0,rest
)
581 fun j(exp
,d
::dl
,mant
) = j(exp
,dl
,mant
* 0.1 + intToReal(d
))
582 |
j(0,nil
,mant
) = mant
*sign
583 |
j(exp
,nil
,mant
) = if exp
>0 then j(exp
-1,nil
,mant
*10.0)
584 else j(exp
+1,nil
,mant
*0.1)
585 fun h(esign
,wholedigits
,diglist
,exp
,nil
) =
586 j(esign
*exp
+wholedigits
-1,diglist
,0.0)
587 |
h(es
,fd
,dl
,exp
,d
::s
) = h(es
,fd
,dl
,exp
*10+(ord d
- ord
"0"),s
)
588 fun g(i
,r
,"E"::"~"::s
)=h(~
1,i
,r
,0,s
)
589 |
g(i
,r
,"E"::s
)=h(1,i
,r
,0,s
)
590 |
g(i
,r
,d
::s
) = if d
>="0" andalso d
<="9" then
591 g(i
, (ord d
- ord
"0")::r
, s
)
593 |
g(i
,r
,nil
) = h(1,i
,r
,0,nil
)
594 fun f(i
,r
,"."::s
)=g(i
,r
,s
)
595 |
f(i
,r
,s
as "E"::_
)=g(i
,r
,s
)
596 |
f(i
,r
,d
::s
) = f(i
+1,(ord(d
)-ord("0"))::r
,s
)
597 | f _
= error
"bad in readdabs"
599 end handle Overflow
=> error ("real constant "^s^
" out of range")
601 fun require((a
:string)::ar
, b
::br
) = if a
=b
then require(ar
,br
)
602 else error(a^
" required")
603 |
require(nil
, br
) = br
604 |
require(a
::_
,_
) = error(a^
" required")
606 fun reg l
= let val (s
,l
) = string l
607 val l
= require(["R"],l
)
611 fun lab l
= let val (s
,l
) = string l
612 val l
= require(["L"],l
)
618 let fun f(")"::_
) = nil
619 | f l
= let val (r
,l
) = reg l
622 in f(b(require(["("],l
)))
626 fn "F"::"E"::"T"::"C"::"H"::l
=>
627 let val (imm
,l
) = immut(b l
)
628 val (dst
,l
) = reg(b l
)
629 val (ptr
,l
) = reg(b(require(["M","["],b(require([":","="],b l
)))))
630 val (offset
,l
) = int(b(require(["+"],b l
)))
631 in require(["]"], b l
);
632 FETCH
{immutable
=imm
,dst
=dst
,ptr
=ptr
,offset
=offset
}
634 |
"S"::"T"::"O"::"R"::"E"::l
=>
635 let val (ptr
,l
) = reg(b(require(["M","["],b l
)))
636 val (offset
,l
) = int(b(require(["+"],b l
)))
637 val (src
,l
) = reg(b(require([":","="],b(require(["]"], b l
)))))
638 in STORE
{src
=src
,ptr
=ptr
,offset
=offset
}
640 |
"G"::"E"::"T"::"L"::"A"::"B"::l
=>
641 let val (dst
,l
) = reg(b l
)
642 val (lab
,l
) = lab(b(require([":","="],b l
)))
643 in GETLAB
{dst
=dst
,lab
=lab
}
645 |
"G"::"E"::"T"::"R"::"E"::"A"::"L"::l
=>
646 let val (dst
,l
) = reg(b l
)
647 val r
= realc(implode(b(require([":","="],b l
))))
648 in GETREAL
{dst
=dst
,value
=Real.toString r
}
650 |
"A"::"R"::"I"::"T"::"H"::"I"::l
=>
651 let val (dst
,l
) = reg(b l
)
652 val (s1
,l
) = reg(b(require([":","="],b l
)))
653 val (oper
,l
) = aop(b l
)
654 val (s2
,l
) = int(b l
)
655 in ARITHI
{oper
=oper
,src1
=s1
,src2
=s2
,dst
=dst
}
657 |
"A"::"R"::"I"::"T"::"H"::l
=>
658 let val (dst
,l
) = reg(b l
)
659 val (s1
,l
) = reg(b(require([":","="],b l
)))
660 val (oper
,l
) = aop(b l
)
661 val (s2
,l
) = reg(b l
)
662 in ARITH
{oper
=oper
,src1
=s1
,src2
=s2
,dst
=dst
}
664 |
"M"::"O"::"V"::"E"::l
=>
665 let val (dst
,l
) = reg(b l
)
666 val (s1
,l
) = reg(b(require([":","="],b l
)))
667 in MOVE
{src
=s1
,dst
=dst
}
669 |
"B"::"R"::"A"::"N"::"C"::"H"::l
=>
670 let val (s1
,l
) = reg(b(require(["I","F"],b l
)))
671 val (test
,l
) = com(b l
)
672 val (s2
,l
) = reg(b l
)
673 val (dst
,l
) = lab(b(require(["G","O","T","O"],b l
)))
675 in BRANCH
{test
=test
,src1
=s1
,src2
=s2
,dst
=dst
,live
=liv
}
677 |
"J"::"U"::"M"::"P"::l
=>
678 let val (dst
,l
) = reg(b l
)
680 in JUMP
{dst
=dst
,live
=live
}
682 |
"L"::"A"::"B"::"E"::"L"::l
=>
683 let val (lab
,l
) = lab(b l
)
684 val live
= live(b(require([":"],l
)))
685 in LABEL
{lab
=lab
,live
=live
}
687 |
"W"::"O"::"R"::"D"::l
=>
688 let val (i
,l
) = int(b l
)
691 |
"L"::"A"::"B"::"W"::"O"::"R"::"D"::l
=>
692 let val (i
,l
) = lab(b l
)
695 |
"N"::"O"::"P"::_
=> NOP
696 | _
=> error
"illegal opcode name"
698 case explode(input_line f
)
700 | l
=> opcode(b l
)::readline(i
+1,f
)
703 fun read f
= readline(0,f
)
709 val show
: outstream
-> AbsMach
.opcode list
-> unit
710 val str
: AbsMach
.opcode list
-> string
721 fun pr s
= outstr
:= !outstr ^ s
754 | inrange
=> "inrange"
755 | outofrange
=> "outofrange"
757 fun bo
true = "t" | bo
false = "f"
759 fun reg(i
,s
) = (pr(s
); pr
"/R"; pr(makestring i
))
760 fun label(i
,s
) = (pr(s
); pr
"/L"; pr(makestring i
))
763 fn FETCH
{immutable
,offset
,ptr
,dst
} =>
765 if immutable
then pr
"i " else pr
"m ";
766 reg dst
; pr
" := M[ "; reg ptr
;
767 pr
" + "; pr (makestring offset
); pr(" ]\n"))
768 | STORE
{offset
,ptr
,src
} =>
771 pr
" + "; pr (makestring offset
); pr(" ] := ");
774 | GETLAB
{lab
, dst
} =>
775 (pr
"GETLAB "; reg dst
;
776 pr
" := "; label lab
;
778 | GETREAL
{value
,dst
} =>
779 (pr
"GETREAL "; reg dst
;
783 | ARITH
{oper
,src1
,src2
,dst
} =>
784 (pr
"ARITH "; reg dst
;
786 pr
" "; pr(aop oper
); pr
" ";
789 | ARITHI
{oper
,src1
,src2
,dst
} =>
790 (pr
"ARITHI "; reg dst
;
792 pr
" "; pr(aop oper
); pr
" ";
796 (pr
"MOVE "; reg dst
;
799 | BRANCH
{test
,src1
,src2
,dst
,live
} =>
802 pr
" "; pr(com test
); pr
" ";
807 List.app (fn r
=> (reg r
; pr
" ")) live
;
810 (pr
"JUMP "; reg dst
;
812 List.app (fn r
=> (reg r
; pr
" ")) live
;
814 | LABEL
{lab
, live
} =>
815 (pr
"LABEL "; label lab
;
817 List.app (fn r
=> (reg r
; pr
" ")) live
;
821 pr (makestring value
);
824 (pr
"LABWORD "; label lab
;
827 | BOGUS
{reads
, writes
} =>
830 List.app (fn r
=> (reg r
; pr
" ")) writes
;
832 List.app (fn r
=> (reg r
; pr
" ")) reads
;
836 in (List.app p prog
; !outstr
)
840 let fun cat (a
, b
) = (xstr
[a
]) ^ b
847 |
f (h
::t
) = (outputc
out (xstr
[h
]);
856 structure HM
= AbsMachImp
857 structure BreakInst
:
859 val breaki
: AbsMach
.opcode list
-> AbsMach
.opcode list
866 val maxreg
= AbsMachImp
.maxreg
868 fun reg(i
:int, s
:string) = i
869 fun rstr(i
:int, s
:string) = s
871 val new_reg_val
= ref
0
872 val new_reg_pairs
:(AbsMach
.reg
* AbsMach
.reg
) list ref
= ref nil
874 fun new_reg_init li
= (new_reg_val
:= maxreg li
;
875 new_reg_pairs
:= nil
)
877 fun new_reg (r
:AbsMach
.reg
) =
879 let val nr
= (new_reg_val
:= !new_reg_val
+ 1; (!new_reg_val
, rstr r
))
881 (new_reg_pairs
:= (r
, nr
) :: !new_reg_pairs
;
884 |
f ((a
, b
)::t
) = if r
= a
then b
else f t
892 fn ARITH
{oper
, src1
, src2
, dst
} =>
893 if reg dst
= reg src1
orelse reg dst
= reg src2
then
894 let val nr
= new_reg(dst
)
896 [ARITH
{oper
=oper
, src1
=src2
, src2
=src2
, dst
=nr
},
897 MOVE
{src
=nr
, dst
=dst
}]
900 | ARITHI
{oper
, src1
, src2
, dst
} =>
901 if reg dst
= reg src1
then
902 let val nr
= new_reg(dst
)
904 [ARITHI
{oper
=oper
, src1
=src1
, src2
=src2
, dst
=nr
},
905 MOVE
{src
=nr
, dst
=dst
}]
908 | FETCH
{immutable
, offset
, ptr
, dst
} =>
909 if reg ptr
= reg dst
then
910 let val nr
= new_reg(dst
)
912 [FETCH
{immutable
=immutable
, offset
=offset
,
914 MOVE
{src
=nr
, dst
=dst
}]
918 if reg src
= reg dst
then nil
924 fun h (a
, b
) = f a @ b
925 val foo
= new_reg_init l
931 structure OutFilter
:
933 val remnops
: AbsMach
.opcode list
-> AbsMach
.opcode list
940 let fun f (NOP
, NOP
::b
) = NOP
::b
949 val init
: AbsMach
.opcode list
-> unit
950 val add_delay
: AbsMach
.opcode list
-> AbsMach
.opcode list
951 val rm_bogus
: AbsMach
.opcode list
-> AbsMach
.opcode list
952 val is_bogus_i
: AbsMach
.opcode
-> bool
953 val is_bogus_reg
: AbsMach
.reg
-> bool
954 val idempotency
: int ref
963 val idempotency
= ref
0
965 fun is_bogus_i (BOGUS _
) = true
966 | is_bogus_i _
= false
968 fun bogus_reg ((i
, s
), which
) = (!maxreg
+ maxdelay
* i
+ which
, s
)
970 fun is_bogus_reg (i
, s
) = i
> !maxreg
972 fun unbogus_reg (i
, s
) = if is_bogus_reg (i
, s
) then (i
div maxdelay
, s
)
975 val max_bog_reg
= ref
0
976 val curr_idem_reg
= ref
0
979 (curr_idem_reg
:= !curr_idem_reg
+ 1;
980 (!curr_idem_reg
, "idem"))
983 maxreg
:= AbsMachImp
.maxreg il
;
984 max_bog_reg
:= (!maxreg
+ 1) * maxdelay
;
985 curr_idem_reg
:= !max_bog_reg
+ 1
991 let fun opdelay oper
=
1013 fn FETCH
{immutable
,offset
,ptr
,dst
} => 2
1014 | STORE
{offset
,ptr
,src
} => 2
1015 | GETLAB
{lab
, dst
} => 2
1016 | GETREAL
{value
,dst
} => 2
1017 | ARITH
{oper
,src1
,src2
,dst
} => opdelay oper
1018 | ARITHI
{oper
,src1
,src2
,dst
} => opdelay oper
1019 | MOVE
{src
,dst
} => 1
1020 | BRANCH
{test
,src1
,src2
,dst
,live
} => 5
1021 | JUMP
{dst
,live
} => 1
1022 | LABEL
{lab
, live
} => 0
1029 fun b_idemx (0, r
, w
) = nil
1030 |
b_idemx (1, r
, w
) = BOGUS
{reads
=r @ w
, writes
= [idem_reg()]} :: nil
1031 |
b_idemx (n
, r
, w
) =
1032 let val ir
= idem_reg()
1034 BOGUS
{reads
=r @ w
, writes
= [ir
]} :: b_idemx(n
-1, r
, [ir
])
1037 fun b_idem (n
, r
, w
) =
1038 let fun fil ((i
, s
), b
) = if i
= 0 then b
else (i
, s
) :: b
1039 val nr
= fold fil r nil
1042 else b_idemx(n
, nr
, w
)
1045 fun b_assx (0, r
) = nil
1046 |
b_assx (1, r
) = BOGUS
{reads
=[bogus_reg(r
, 1)], writes
=[r
]} :: nil
1048 BOGUS
{reads
=[bogus_reg(r
, n
)], writes
=[bogus_reg(r
, n
-1)]} ::
1051 fun b_ass(n
, r
) = BOGUS
{reads
=[r
], writes
=[bogus_reg(r
, n
-1)]} ::
1054 fun b_brxx (0, rl
) = nil
1056 let fun b r
= bogus_reg(r
, 1)
1058 BOGUS
{reads
=rl
, writes
=map b rl
} :: nil
1061 let fun br r
= bogus_reg(r
, n
- 1)
1062 fun bw r
= bogus_reg(r
, n
)
1064 BOGUS
{reads
=map br rl
, writes
=map bw rl
} :: b_brxx (n
- 1, rl
)
1068 let fun br r
= bogus_reg(r
, n
-1)
1070 BOGUS
{reads
=map br rl
, writes
=rl
} :: b_brxx(n
-1, rl
)
1073 fun b_br (b
, n
, rl
) = rev (b
:: b_brx(n
, rl
))
1077 fun f (FLOW _
) = true
1084 let fun idem (r
, w
) = b_idem (!idempotency
, r
, w
)
1088 fn FETCH
{immutable
,offset
,ptr
,dst
} =>
1089 i
:: (idem([ptr
], [dst
]) @
b_ass(d
, dst
))
1090 | STORE
{offset
,ptr
,src
} => [i
]
1091 | GETLAB
{lab
, dst
} => i
:: b_ass(d
, dst
)
1092 | GETREAL
{value
,dst
} => i
:: b_ass(d
, dst
)
1093 | ARITH
{oper
,src1
,src2
,dst
} =>
1094 i
:: (idem([src1
, src2
], [dst
]) @
b_ass(d
, dst
))
1095 | ARITHI
{oper
,src1
,src2
,dst
} =>
1096 i
:: (idem([src1
], [dst
]) @
b_ass(d
, dst
))
1097 | MOVE
{src
,dst
} => i
:: idem([src
], [dst
])
1098 | BRANCH
{test
,src1
,src2
,dst
,live
} =>
1099 if is_flow i
then [i
]
1101 b_br (BRANCH
{test
=test
,
1102 src1
=src1
,src2
=src2
,dst
=dst
,
1109 fun apnd (nil
, b
) = b
1110 |
apnd (a
::t
, b
) = a
:: apnd(t
, b
)
1111 fun fld(a
, b
) = apnd(g a
, b
)
1120 fn FETCH
{immutable
,offset
,ptr
,dst
} =>
1121 FETCH
{immutable
=immutable
, offset
=offset
, ptr
=ptr
,
1122 dst
= unbogus_reg dst
} ::
1124 | STORE
{offset
,ptr
,src
} => i
:: g t
1125 | GETLAB
{lab
, dst
} =>
1126 GETLAB
{lab
=lab
, dst
= unbogus_reg dst
} :: g t
1127 | GETREAL
{value
,dst
} =>
1128 GETREAL
{value
=value
, dst
=unbogus_reg dst
} :: g t
1129 | ARITH
{oper
,src1
,src2
,dst
} =>
1130 ARITH
{oper
=oper
,src1
=src1
,src2
=src2
,dst
=unbogus_reg dst
} ::
1132 | ARITHI
{oper
,src1
,src2
,dst
} =>
1133 ARITHI
{oper
=oper
,src1
=src1
,src2
=src2
,dst
=unbogus_reg dst
} ::
1135 | MOVE
{src
,dst
} => i
:: g t
1136 | BRANCH
{test
,src1
,src2
,dst
,live
} =>
1138 src1
=unbogus_reg src1
,
1139 src2
=unbogus_reg src2
,
1154 val init_names
: unit
-> unit
1155 val new_name
: name
-> name
1156 val prime_name
: name
-> name
1157 val name_prefix_eq
: (name
* name
) -> bool
1159 val teq
: test
* test
-> bool
1162 val aeq
: assignment
* assignment
-> bool
1164 datatype test_or_name
=
1169 val toneq
: test_or_name
* test_or_name
-> bool
1171 datatype test_or_assign
=
1175 val toaeq
: test_or_assign
* test_or_assign
-> bool
1182 type test
= HM
.comparison
1185 type reg
= int*string
1187 type assignment
= HM
.operation
1194 fun init_names () = ct
:= 0
1196 fun nn() = (ct
:= !ct
+ 1; !ct
- 1)
1199 |
pref ("_" :: t
) = nil
1200 |
pref (h
:: t
) = h
:: pref t
1202 val name_prefix
= implode
o pref
o explode
1203 fun name_prefix_eq(a
, b
) = (name_prefix a
) = (name_prefix b
)
1205 fun new_name n
= n ^
"_" ^
(makestring (nn()))
1207 fun new_name n
= name_prefix n ^
"_" ^
(makestring (nn()))
1208 fun prime_name n
= (new_name n
) ^
"'"
1210 datatype test_or_name
=
1215 fun toneq (TEST a
, TEST b
) = teq (a
, b
)
1216 |
toneq (NAME a
, NAME b
) = a
= b
1219 datatype test_or_assign
=
1223 fun toaeq (TST a
, TST b
) = teq (a
, b
)
1224 |
toaeq (ASS a
, ASS b
) = aeq (a
, b
)
1231 exception DAGnotfound
1234 val tests_of
: dag
-> Ntypes
.test Set
.set
1235 val sel_of
: dag
-> ((Ntypes
.test
* bool) -> Ntypes
.test_or_name
)
1236 val root_of
: dag
-> Ntypes
.test_or_name
1237 val succ_of
: dag
-> Ntypes
.name Set
.set
1238 val attach
: Ntypes
.test
* dag
* dag
-> dag
1239 val reach
: dag
* Ntypes
.test_or_name
-> dag
1240 val replace_edge
: dag
* Ntypes
.name list
-> dag
1241 val newdag
: (Ntypes
.test Set
.set
*
1242 ((Ntypes
.test
* bool) -> Ntypes
.test_or_name
) *
1243 Ntypes
.test_or_name
*
1244 Ntypes
.name Set
.set
)
1246 val dagToString
: dag
-> string
1253 exception DAGnotfound
1259 ((test
* bool) -> test_or_name
) *
1263 fun tonToString (TEST t
) = "TEST t"
1264 |
tonToString (NAME n
) = "NAME " ^ n
1265 | tonToString NEITHER
= "NEITHER"
1267 fun sep (a
, b
) = a ^
", " ^ b
1269 fun dagToString (D(t
, sel
, rt
, s
)) =
1270 "D([" ^ PrintAbs
.str (Set
.set t
) ^
"]" ^
1271 "fn, " ^
(tonToString rt
) ^
", " ^
(fold
sep (Set
.set s
) ")")
1273 val make
= D(Set
.makeEQ teq
, fn x
=> raise DAGnotfound
, NEITHER
, Set
.make
)
1277 fun tests_of(D (b
, sel
, r
, h
)) = b
1278 fun sel_of(D (b
, sel
, r
, h
)) = sel
1279 fun root_of(D (b
, sel
, r
, h
)) = r
1280 fun succ_of(D (b
, sel
, r
, h
)) = h
1282 fun attach (t
, D dt
, D df
) =
1284 val (b1
, sel1
, r1
, h1
) = dt
1285 val (b2
, sel2
, r2
, h2
) = df
1287 D(add(union(b1
, b2
), t
),
1289 if teq(x
, t
) then if y
then r1
else r2
1290 else sel1(x
, y
) handle DAGnotfound
=> sel2(x
, y
)),
1296 fun reach (D d
, tn
) =
1298 val (b
, sel
, r
, h
) = d
1300 if not (member(b
, t
)) then raise DAGnotfound
1301 else attach(t
, reach(D d
, sel(t
, true)), reach(D d
, sel(t
, false)))
1303 D(makeEQ teq
, fn x
=> raise DAGnotfound
, NAME n
, listToSet
[n
])
1304 |
f (_
) = raise DAGnotfound
1309 fun replace_edge (D d
, nil
) = D d
1310 |
replace_edge (D d
, old
::new
::tl
) =
1312 val (b
, sel
, r
, h
) = d
1313 val nh
= if member(h
, old
) then add(rm(h
, old
), new
) else h
1314 val nr
= if toneq(r
, NAME old
) then NAME new
else r
1315 val nsel
= fn(x
, y
) =>
1316 let val v
= sel(x
, y
)
1318 if toneq(v
, NAME old
) then NAME new
else v
1323 | replace_edge _
= raise DAG
1346 val delete_debug
: bool ref
1347 val move_op_debug
: bool ref
1348 val move_test_debug
: bool ref
1349 val rw_debug
: bool ref
1350 val ntn_debug
: bool ref
1351 val prog_node_debug
: bool ref
1352 val prog_node_debug_verbose
: bool ref
1353 val closure_progs_debug
: bool ref
1354 val cpsiCheck
: bool ref
1355 val makeProg
: unit
-> program
1357 Ntypes
.name
* Ntypes
.assignment Set
.set
*
1358 Dag
.dag
* Ntypes
.name Set
.set
-> node
1359 val name_of
: node
-> Ntypes
.name
1360 val assignment_of
: node
-> Ntypes
.assignment Set
.set
1361 val dag_of
: node
-> Dag
.dag
1362 val succ
: program
* node
-> Ntypes
.name Set
.set
1363 val prednm
: program
* Ntypes
.name
-> Ntypes
.name Set
.set
1364 val pred
: program
* node
-> Ntypes
.name Set
.set
1365 val succNodes
: program
* node
-> node Set
.set
1366 val predNodes
: program
* node
-> node Set
.set
1367 val readNode
: node
-> int Set
.set
1368 val writeNode
: node
-> int Set
.set
1369 val unreachable
: program
* node
-> bool
1370 val num_ops_node
: node
-> int
1371 val num_tests_node
: node
-> int
1372 val num_things_node
: node
-> int
1373 val replace_edge_node
: node
* string list
-> node
1374 exception NAMETONODE
1375 val nameToNode
: program
* Ntypes
.name
-> node
1376 val nameSetToNodeSet
: program
* Ntypes
.name Set
.set
-> node Set
.set
1377 val eqn
: node
* node
-> bool
1380 val delete
: program
* node
-> program
1382 program
* Ntypes
.assignment
* node Set
.set
* node
-> program
1383 val move_test
: program
* Ntypes
.test
* node
* node
-> program
1384 val nodeToString
: node
-> string
1385 val progToString
: program
-> string
1386 val entries
: program
-> node list
1387 val programs
: program
-> program list
1388 val addPredInfo
: program
-> program
1389 val closure
: program
* node
-> program
1390 val sortNodes
: node list
-> node list
1391 val updateNode
: program
* node
-> program
1392 val addNode
: program
* node
-> program
1393 val rmNode
: program
* node
-> program
1400 datatype node
= N
of name
* assignment Set
.set
* dag
* name Set
.set
1401 type program
= node Stringmap
.stringmap
* node
* node
1403 type debug_fun
= unit
-> string
1404 val delete_debug
= ref
false
1405 val move_op_debug
= ref
false
1406 val dead_set_debug
= ref
false
1407 val move_test_debug
= ref
false
1408 val rw_debug
= ref
false
1409 val prog_node_debug
= ref
false
1410 val prog_node_debug_verbose
= ref
false
1411 val closure_progs_debug
= ref
false
1413 fun name_of(N(n
, a
, d
, prd
)) = n
1414 fun assignment_of(N(n
, a
, d
, prd
)) = a
1415 fun dag_of(N(n
, a
, d
, prd
)) = d
1416 fun pred_of(N(n
, a
, d
, prd
)) = prd
1418 fun eqn(n1
, n2
) = name_of n1
= name_of n2
1420 val start
:name
= "START"
1421 val finish
:name
= "FINISH"
1423 fun printstringlist sl
= stringListString sl
1424 val psl
= printstringlist
1426 fun nodeToString (N(n
, a
, d
, prd
)) =
1427 "\nN(" ^ n ^
", [" ^ PrintAbs
.str (Set
.set a
) ^
"], " ^
1429 "pred(" ^
psl (Set
.set prd
) ^
"))"
1431 fun progToString (ns
, n0
, F
) =
1432 "P (" ^
(psl
o (map nodeToString
) o Stringmap
.extract
) ns ^
",\n" ^
1433 nodeToString n0 ^
",\n" ^
1434 nodeToString F ^
")\n"
1436 fun make (n
, a
, t
, prd
) = N(n
, a
, t
, prd
)
1438 val n00
= make(start
, Set
.makeEQ aeq
, Dag
.make
, Set
.make
)
1439 val fin
= make(finish
, Set
.makeEQ aeq
, Dag
.make
, Set
.make
)
1441 fun makeProg() = (Stringmap
.new():node Stringmap
.stringmap
, n00
, fin
)
1443 fun addPredNode (N(n
, a
, t
, prd
), p
) = (N(n
, a
, t
, Set
.add(prd
, p
)))
1444 fun unionPredNode (N(n
, a
, t
, prd
), ps
) = (N(n
, a
, t
, Set
.union(prd
, ps
)))
1445 fun setPredNode (N(n
, a
, t
, prd
), p
) = (N(n
, a
, t
, p
))
1446 fun rmPredNode (N(n
, a
, t
, prd
), p
) = (N(n
, a
, t
, Set
.rm(prd
, p
)))
1448 fun p_n_debug (f
:debug_fun
) =
1449 if !prog_node_debug
then print ("p_n:" ^
f() ^
"\n")
1453 fun updateNode(P
as (ns
, n0
, F
), new_node
) =
1455 (Stringmap
.rm (ns
:node Stringmap
.stringmap
)
1456 ((name_of new_node
):string);
1457 Stringmap
.add
ns ((name_of new_node
), new_node
);
1458 if name_of new_node
= name_of n0
then (ns
, new_node
, F
)
1459 else if name_of new_node
= name_of F
then (ns
, n0
, new_node
)
1463 ("updateNode n=" ^ nodeToString new_node ^
1465 (if !prog_node_debug_verbose
then progToString answer
1471 fun addNode(P
as (ns
, n0
, F
), new_node
) =
1473 if Stringmap
.isin
ns (name_of new_node
) then updateNode(P
, new_node
)
1474 else (Stringmap
.add
ns ((name_of new_node
), new_node
);
1478 ("addNode n=" ^ nodeToString new_node ^
1480 (if !prog_node_debug_verbose
then progToString answer
1487 fun rmNode(P
as (ns
, n0
, F
), node
) =
1488 let val answer
= (Stringmap
.rm
ns (name_of node
);
1492 ("rmNode n=" ^ nodeToString node ^
1494 (if !prog_node_debug_verbose
then progToString answer
1501 fun succ(p
, n
) = (succ_of
o dag_of
) n
1502 fun pred(p
, n
) = pred_of n
1504 val ntn_debug
= ref
true
1505 fun ntnPrint (f
:debug_fun
) = if !ntn_debug
then print ("ntn:" ^
f() ^
"\n") else ()
1507 exception NAMETONODE
1508 fun nameToNode(P
as (ns
, n0
, F
), nm
) =
1511 (ntnPrint (fn () => ("nameToNode " ^ nm ^
"not found"));
1514 exception NAMESETTONODESET
1515 fun nameSetToNodeSet(P
, ns
) =
1516 Set
.listToSetEQ(eqn
, map (fn x
=> nameToNode(P
, x
)) (Set
.set ns
))
1517 handle NAMETONODE
=> raise NAMESETTONODESET
1519 fun prednm(p
, nm
) = pred(p
, nameToNode(p
, nm
))
1521 fun succNodes (p
, n
) = nameSetToNodeSet(p
, succ(p
, n
))
1522 fun predNodes (p
, n
) = nameSetToNodeSet(p
, pred(p
, n
))
1525 (* a correctness assertion
*)
1527 val cpsiCheck
= ref
false
1528 fun checkPredSuccInfo(from
, P
as (ns
, n0
, F
)) =
1529 let val nl
= Stringmap
.extract ns
1530 val badnode
= ref n0
1531 fun fail s
= (print ("CPSI:" ^ s ^
" failed\nfrom " ^ from ^
1532 "\nbadnode=" ^
nodeToString (!badnode
) ^
1533 "\nprogram=" ^ progToString P ^
"\n");
1535 fun chk (xpred
, xsuccN
, n
) =
1536 let val foo
= badnode
:= n
1537 val s
= Set
.set(xsuccN(P
, n
))
1538 handle NAMESETTONODESET
=>
1539 fail
"NAMESETTONODESET"
1540 fun cs x
= Set
.member(xpred x
, name_of n
)
1541 fun fs (x
, b
) = b
andalso cs x
1545 fun cp (x
, b
) = b
andalso chk(pred_of
, succNodes
, x
)
1546 fun cs (x
, b
) = b
andalso chk((succ_of
o dag_of
), predNodes
, x
)
1548 if not (fold cp nl
true) then fail
"cp"
1549 else if not (fold cs nl
true) then fail
"cs"
1552 fun cpsi x
= if !cpsiCheck
then checkPredSuccInfo x
else ()
1557 empty (assignment_of n
) andalso empty ((tests_of
o dag_of
) n
)
1560 fun unreachable(P
as (ns
, n0
, F
), n
) =
1561 not (eqn (n0
, n
)) andalso Set
.empty (pred(P
, n
))
1563 fun read (TST(t
)) = HM
.read_c t
1564 |
read (ASS(a
)) = HM
.read_o a
1566 fun write (TST(t
)) = HM
.write_c t
1567 |
write (ASS(a
)) = HM
.write_o a
1569 fun read_write_debug (f
:debug_fun
) =
1570 if !rw_debug
then print (f() ^
"\n")
1577 (listUnion (make
::(map (read
o ASS
) ((set
o assignment_of
) n
))),
1578 listUnion (make
::(map
1579 (read
o TST
) ((set
o tests_of
o dag_of
) n
))))
1580 val foo
= read_write_debug
1582 ("readNode " ^ nodeToString n ^
"=>" ^
1583 stringListString (map
makestring (set answer
))))
1592 (listUnion (make
::(map (write
o ASS
) ((set
o assignment_of
) n
))),
1593 listUnion (make
::(map
1594 (write
o TST
) ((set
o tests_of
o dag_of
) n
))))
1595 val foo
= read_write_debug
1597 ("writeNode " ^ nodeToString n ^
"=>" ^
1598 stringListString (map
makestring (set answer
))))
1603 fun no_write_conflict (ta
, n
) =
1605 empty (intersect(writeNode n
, (union(read ta
, write ta
))))
1608 fun no_read_conflict (ta
, n
) =
1610 empty (intersect (write ta
, readNode n
))
1615 (empty
o assignment_of
) n
andalso (empty
o tests_of
o dag_of
) n
1618 fun replace_edge_node(N (n
, a
, d
, p
), nl
) = N(n
, a
, replace_edge(d
, nl
), p
)
1620 fun except_bogus nil
= nil
1621 |
except_bogus (h
::t
) =
1622 if Delay
.is_bogus_i h
then except_bogus t
else h
:: except_bogus t
1624 val num_ops_node
= List.length
o except_bogus
o Set
.set
o assignment_of
1625 val num_tests_node
= List.length
o Set
.set
o tests_of
o dag_of
1626 fun num_things_node n
= (num_ops_node n
) + (num_tests_node n
)
1628 fun dead_debug (f
:debug_fun
) =
1629 if !dead_set_debug
then print ("dead" ^
f() ^
"\n") else ()
1632 fun dead(P
:program
, r
:HM
.reg
, n
:node
, done
: name Set
.set
) =
1634 dead_debug (fn () => "(P, " ^ makestring r ^
", " ^ nodeToString n ^
")")
1635 val new_done
= Set
.add(done
, name_of n
)
1636 fun nfil(a
, b
) = if Set
.member(new_done
, a
) then b
1639 |
drl (h
::t
) = dead(P
, r
, h
, new_done
) andalso drl t
1640 fun ntn n
= nameToNode (P
, n
) handle NAMETONODE
=> raise DEAD
1641 val next
= fold
nfil (Set
.set (succ(P
, n
))) nil
1643 not (Set
.member(readNode n
, r
)) andalso
1644 (Set
.member(writeNode n
, r
) orelse
1647 val foo
= dead_debug(fn () => "=>" ^
Bool.toString answer
)
1652 fun deadset(P
, rs
, n
) =
1653 let val foo
= dead_debug (fn () => "deadset(" ^
1655 (map
makestring (Set
.set rs
)) ^
",\n" ^
1656 nodeToString n ^
")")
1658 |
f (r
::t
) = dead(P
, r
, n
, Set
.make
) andalso f t
1659 val answer
= f (Set
.set rs
)
1660 val foo
= dead_debug(fn () => "deadset=>" ^
Bool.toString answer ^
"\n")
1665 fun del_debug (f
:debug_fun
) =
1666 if !delete_debug
then print ("delete:" ^
f() ^
"\n")
1671 exception DELETE_WIERDSUCC
1672 fun delete (P
as (ns
, n0
, F
), n
) =
1673 let val foo
= cpsi("delete enter", P
)
1675 val un
= unreachable(P
, n
)
1676 fun ntn n
= nameToNode(P
, n
) handle NAMETONODE
=> raise DELETE
1677 val p
= Set
.listToSetEQ(eqn
, (map
ntn (Set
.set (pred(P
, n
)))))
1682 "delete( n=" ^
(name_of n
) ^
"\n" ^
1683 "em=" ^
(Bool.toString em
) ^
"\n" ^
1684 "un=" ^
(Bool.toString un
) ^
"\n" ^
1685 "p =" ^
(psl (map
name_of (Set
.set p
))) ^
"\n" ^
1688 if (em
orelse un
) andalso not (eqn(n
, F
)) then
1691 val foo
= del_debug (fn () => "complex deletion")
1692 val s0
= Set
.set (succ(P
, n
))
1693 val nprime
= if List.length s0
= 1 then hd s0
1694 else (print (Int.toString (List.length s0
));
1695 raise DELETE_WIERDSUCC
)
1697 rmPredNode(unionPredNode(ntn nprime
, pred_of n
),
1700 replace_edge_node(x
, [name_of n
, name_of new_nprime
])
1701 val pprime
= map
ren (set p
)
1702 fun updt(n
, p
) = updateNode(p
, n
)
1703 val Nprime
= fold
updt (new_nprime
:: pprime
) P
1705 val foo
= del_debug (fn () => "nprime=" ^ nprime
)
1708 "pprime=" ^
(psl (map nodeToString pprime
)))
1709 val answer
= rmNode(Nprime
, n
)
1710 val foo
= cpsi("delete leave cd", answer
)
1714 else (del_debug (fn () => "simple_deletion");
1715 let val s
= Set
.set(nameSetToNodeSet(P
, (succ(P
, n
))))
1716 fun updt(s
, p
) = updateNode(p
, rmPredNode(s
, name_of n
))
1717 val np
= rmNode(fold updt s P
, n
)
1718 val foo
= cpsi("delete leave sd", np
)
1722 else (del_debug (fn () => "No deletion");
1724 end handle Hd
=> raise DELETE_HD
1726 fun mop_debug (f
:debug_fun
) =
1727 if !move_op_debug
then
1728 (dead_set_debug
:= true;
1729 print ("mop:" ^
f() ^
"\n"))
1730 else dead_set_debug
:= false
1733 fun can_move_op1(P
as (ns
, n0
, F
), x
, move_set
, m
) =
1735 val foo
= mop_debug (fn () => "can_move_op")
1736 val rok
= HM
.resources_ok(set (add(assignment_of m
, x
)),
1737 set ((tests_of
o dag_of
) m
))
1738 val foo
= mop_debug(fn () => "1")
1739 val p
= diff(nameSetToNodeSet(P
, succ(P
, m
)), move_set
)
1740 val foo
= mop_debug(fn () => "2")
1741 val l
= (write
o ASS
) x
1742 val foo
= mop_debug(fn () => "3")
1744 |
dlpf (pj
::t
) = deadset(P
, l
, pj
) andalso dlpf t
1747 (not
o eqn
)(nj
, F
) andalso
1748 (* no_read_conflict(ASS x
, nj
) andalso *)
1749 (* change ex model so it can run on a sequential machine
*)
1750 no_read_conflict(ASS x
, m
) andalso
1751 no_write_conflict(ASS x
, m
) andalso
1753 val foo
= mop_debug(fn () => "4")
1754 val answer
= rok
andalso cond (set move_set
) andalso dlpf (set p
)
1755 val foo
= mop_debug (fn () => "can_move_op=>" ^
Bool.toString answer
)
1760 fun can_move_op(P
, x
, move_set
, m
) =
1762 val ms
= set move_set
1763 fun pf n
= pred(P
, n
)
1764 val ps
= set(listUnion (map pf ms
))
1765 fun all (x
, b
) = b
andalso can_move_op1(P
, x
, move_set
, m
)
1767 if List.length ps
> 1 then
1768 if List.length ms
> 1 then false
1769 else fold
all ((set
o assignment_of
o hd
) ms
) true
1770 else can_move_op1(P
, x
, move_set
, m
)
1773 fun move_op (P
as (ns
, n0
, F
), x
, move_set
, m
) =
1774 let val foo
= cpsi("move_op enter", P
)
1780 (stringListString (map nodeToString
1781 (Set
.set move_set
))) ^
1782 "\nm=" ^ nodeToString m ^
"\n)\n")
1784 if not (can_move_op(P
, x
, move_set
, m
)) then P
1788 val primed_pairs
= ref nil
1791 let val nn
= prime_name nm
1793 (primed_pairs
:= (nm
, nn
) :: !primed_pairs
;
1796 |
f ((a
, b
)::t
) = if nm
= a
then b
else f t
1797 val answer
= f (!primed_pairs
)
1798 val foo
= mop_debug (fn () => "pnf " ^ nm ^
"=>" ^ answer
)
1802 val foo
= mop_debug(fn () => "1")
1804 |
njp ((N(n
, a
, d
, prd
))::t
) =
1805 N(pnf n
, rm(a
, x
), d
, listToSet
[name_of m
]) :: njp t
1806 fun ojp l
= map (fn x
=> rmPredNode(x
, name_of m
)) l
1807 fun replist nil
= nil
1808 |
replist (h
::t
) = h
:: pnf h
:: replist t
1809 val rlist
= replist (map
name_of (set move_set
))
1810 val foo
= mop_debug(fn () => "2")
1812 let val aprime
= add(assignment_of m
, x
)
1813 val dprime
= replace_edge(dag_of m
, rlist
)
1815 N(name_of m
, aprime
, dprime
, pred_of m
)
1817 val foo
= mop_debug(fn () => "3")
1818 val nj
= njp(set move_set
)
1819 val foo
= mop_debug(fn () =>
1821 stringListString (map name_of nj
))
1822 fun uptd(n
, p
) = updateNode(p
, n
)
1823 val np
= fold
uptd (mprime
:: (ojp (set move_set
))) P
1825 let val s
= set (succNodes(p
, n
))
1826 fun ap x
= addPredNode(x
, name_of n
)
1827 fun updt(x
, p
) = updateNode(p
, ap x
)
1831 fun addn(n
, p
) = addnpi(n
, addNode(p
, n
))
1832 val nnp
= fold addn nj np
1833 val foo
= mop_debug(fn () => "4")
1835 val foo
= mop_debug(fn () => "5")
1836 val foo
= cpsi("move_op leave", answer
)
1838 mop_debug(fn () => "6");
1843 fun updt_sel (d
, nsel
) =
1844 let val tst
= tests_of d
1848 newdag(tst
, nsel
, rt
, s
)
1851 fun mt_debug (f
:debug_fun
) =
1852 if !move_test_debug
then print ("move_test" ^
f() ^
"\n")
1855 fun can_move_test(P
as (ns
, n0
, F
):program
, x
:test
, n
:node
, m
:node
) =
1856 let val foo
= cpsi("move_test enter", P
)
1857 val foo
= mt_debug (fn () => "can_move_test")
1859 no_write_conflict(TST x
, m
) andalso
1861 (* hack because sel can
't distinguish xj
*)
1862 not (Set
.member(tests_of(dag_of m
), x
)) andalso
1864 HM
.resources_ok(Set
.set (assignment_of m
),
1865 Set
.set (Set
.add((tests_of
o dag_of
) m
, x
)))
1866 val foo
= mt_debug (fn () => "can_move_test=>" ^
Bool.toString answer
)
1871 fun move_test (P
as (ns
, n0
, F
):program
, x
:test
, n
:node
, m
:node
) =
1872 if not (can_move_test(P
, x
, n
, m
)) then P
1875 mt_debug (fn () => "move_test" ^ name_of n ^
" " ^ name_of m
)
1878 val sel_n
= sel_of d_n
1879 val rt_n
= root_of d_n
1881 let val newname
= (new_name
o name_of
) n ^
"tt"
1883 let val v
= sel_n(z
, b
) in
1884 if toneq(v
, TEST x
) then sel_n(x
, true)
1888 if TEST x
= rt_n
then
1889 reach(updt_sel(d_n
, nsel
), sel_n(x
, true))
1891 reach(updt_sel(d_n
, nsel
), rt_n
)
1893 N(newname
, assignment_of n
, nC
, listToSet
[name_of m
])
1895 val foo
= mt_debug (fn () => "got nt")
1897 let val newname
= ((new_name
o name_of
) n
) ^
"ff"
1899 let val v
= sel_n(z
, b
) in
1900 if toneq(v
, TEST x
) then sel_n(x
, false)
1904 if TEST x
= rt_n
then
1905 reach(updt_sel(d_n
, nsel
), sel_n(x
, false))
1907 reach(updt_sel(d_n
, nsel
), rt_n
)
1909 N(newname
, assignment_of n
, nC
, listToSet
[name_of m
])
1911 val foo
= mt_debug (fn () => "got nf")
1913 val sel_m
= sel_of d_m
1914 fun nton n
= NAME( name_of n
)
1916 if teq(z
, x
) then if b
then nton nt
else nton nf
1918 let val v
= sel_m(z
, b
) in
1919 if toneq(v
, NAME(name_of n
)) then TEST x
else v
1921 val nb
= add(tests_of d_m
, x
)
1923 add(add(rm(succ_of d_m
, name_of n
), name_of nt
), name_of nf
)
1924 fun new_rt (NAME rt
) = TEST x
1926 val nc
= newdag(nb
, nsel
, (new_rt
o root_of
) d_m
, nh
)
1927 val new_m
= N(name_of m
, assignment_of m
, nc
, pred_of m
)
1928 fun updt_t s
= addPredNode(s
, name_of nt
)
1929 fun updt_f s
= addPredNode(s
, name_of nf
)
1930 val upt
= map
updt_t (set (nameSetToNodeSet(P
, succ(P
, nt
))))
1931 val upf
= map
updt_f (set (nameSetToNodeSet(P
, succ(P
, nf
))))
1932 fun updtl(n
, p
) = updateNode(p
, n
)
1934 fold
updtl ([rmPredNode(n
, name_of m
), new_m
] @ upt @ upf
) P
1936 val foo
= mt_debug (fn () => "mtst done")
1937 val foo
= cpsi("move_test leave", answer
)
1943 fun entries (P
as (ns
, n0
, F
)) =
1944 let val nl
= Stringmap
.extract ns
1945 fun f (a
, b
) = if unreachable(P
, a
) then a
::b
else b
1947 n0
:: (fold f nl nil
)
1950 fun addPredInfo(P
as (ns
, n0
, F
)) =
1951 let fun rmpi n
= setPredNode (n
, Set
.make
)
1952 val nl
= map
rmpi (Stringmap
.extract ns
)
1953 fun updt(n
, p
) = updateNode(p
, n
)
1954 val np
= fold updt nl P
1956 let val s
= Set
.set (succNodes(p
, n
))
1957 fun api(s
, p
) = updateNode(p
, addPredNode(s
, name_of n
))
1965 fun cp_debug (f
:debug_fun
) =
1966 if !closure_progs_debug
then print ("cp:" ^
f() ^
"\n")
1969 fun closure (P
as (ns
, n0
, F
), entry
) =
1973 "closure:entry=" ^ name_of entry ^
"\nprogram=" ^ progToString P
)
1974 val isin
= Stringmap
.isin
1975 fun dfs(p
, parent
, nil
) = p
1976 |
dfs(p
as (ns
, n0
, F
), parent
, cur
::todo
) =
1977 if not (isin
ns (name_of cur
)) then
1978 let val np
= dfs(addNode(p
, cur
), cur
, set(succNodes(P
, cur
)))
1980 dfs(np
, parent
, todo
)
1982 else dfs(p
, parent
, todo
)
1983 val prog
:program
= (Stringmap
.new(), entry
, F
)
1984 val answer
= dfs(addNode(prog
, entry
),
1986 set(succNodes(P
, entry
)))
1989 "\nclosure=>" ^ progToString answer
)
1994 fun programs(P
as (ns
, n0
, F
):program
) =
1995 let val foo
= cp_debug (fn () => "programs")
1996 val l
= entries (addPredInfo P
)
1997 (* make sure preds are
in closure
*)
1998 fun cf e
= addPredInfo(closure(P
, e
))
1999 val answer
= map cf l
2000 val foo
= cp_debug (fn () => "programs done")
2013 if d
>="0" andalso d
<="9" then f(n
*10+ord(d
)-z
, l
)
2020 let val a
= explode(name_of a
)
2021 val b
= explode(name_of b
)
2027 structure sortN
= Sort(ns
)
2029 val sortNodes
= sortN
.sort
2033 structure Compress
:
2035 val compress_debug
: bool ref
2036 val compress
: (int * Node
.program
) -> Node
.program
2037 val move_things_node
:
2038 Node
.program
* Ntypes
.name
* Ntypes
.name Set
.set
-> Node
.program
2039 val do_move_tests
: bool ref
2040 val do_move_ops
: bool ref
2042 val dbg_p
: Node
.program ref
2052 val do_move_tests
= ref
false
2053 val do_move_ops
= ref
true
2057 fun error (s
:string) =
2061 val compress_debug
= ref
false
2063 val dbg_p
= ref (makeProg())
2065 type debug_fun
= unit
-> string
2066 fun debug (f
:debug_fun
) =
2067 if !compress_debug
then print (f() ^
"\n")
2070 exception FILTERSUCC
2072 fun filterSucc(P
, nm
, fence_set
) =
2074 val s
= set(succ(P
, nameToNode(P
, nm
)))
2075 handle NAMETONODE
=> raise FILTERSUCC
2076 fun f (nm
, l
) = if member(fence_set
, nm
) then l
else nm
::l
2083 val finP
= ref makeProg
2084 val foutP
= ref makeProg
2086 fun chinP (p
, from
) =
2087 let val nm
= "11_100'_110tt_119'"
2088 val prd
= prednm(p
, nm
)
2089 val pe
= Set
.empty(prd
)
2092 if pe
then (foutP
:= p
; error ("chinP gone -" ^ from
)) else ()
2095 print ("chinP found it -" ^ from ^
"\n");
2102 exception MOVETHINGSNODE
2103 fun move_things_node(P
, nm
, fence_set
) =
2108 "move_things_node(\n" ^
2109 progToString P ^
",\n" ^
2111 fold (fn (a
, b
) => a ^
", " ^ b
) (set fence_set
) "]" ^
2114 fun ntn (p
, nm
) = ((* chinP (p
, "ntn");*) nameToNode (p
, nm
))
2115 handle NAMETONODE
=> (dbg_p
:= P
; raise MOVETHINGSNODE
)
2116 fun s_nm_list p
= filterSucc(p
, nm
, fence_set
)
2117 fun nd nm
= ntn(P
, nm
) handle MOVETHINGSNODE
=> error
"nd nm"
2118 val au
= listUnionEQ(aeq
, map (assignment_of
o nd
) (s_nm_list P
))
2119 val tu
= listUnionEQ(teq
, map (tests_of
o dag_of
o nd
) (s_nm_list P
))
2122 ((*chinP (p
, "ms"); *)
2123 if member(assignment_of(ntn(p
, nm
)), a
) then nm
::l
2126 handle MOVETHINGSNODE
=> (dbg_p
:= p
; error
"ms")
2128 fold
f (s_nm_list p
) nil
2131 let val msl
= ms (p
, a
)
2132 val ms_set
= nameSetToNodeSet(p
, listToSet msl
)
2133 fun dms(a
, p
) = delete(p
, ntn(p
, a
))
2135 let val foo
= debug (fn () => "mop start " ^ nm
)
2136 val new_p
= move_op(p
, a
, ms_set
, ntn(p
, nm
))
2137 handle MOVETHINGSNODE
=> error
"move_a move_op"
2138 val foo
= debug (fn () => "mop end")
2144 val foo
= chinP(mpa
,
2145 "a_move_a amop " ^ nm ^
2146 StrPak
.stringListString
2147 (map
name_of (set ms_set
)))
2149 val answer
= fold dms msl mpa
2151 val foo
= chinP(answer
, "a_move_a adel")
2156 fun move_a(a
, p
) = if !do_move_ops
then move_a1(a
, p
) else p
2159 ((*chinP (p
, "tset");*)
2160 if member(tests_of(dag_of(ntn(p
, nm
))), t
) then nm
::l
2163 handle MOVETHINGSNODE
=> error
"tset"
2165 fold
f (s_nm_list p
) nil
2168 let val ts
= tset (p
, t
)
2170 if List.length ts
> 0 then
2173 handle MOVETHINGSNODE
=> error
"move_t 1"),
2175 handle MOVETHINGSNODE
=> error
"move_t 2"))
2178 (*val foo
= chinP(answer
, "a_move_t")*)
2182 fun move_t(t
, p
) = if !do_move_tests
then move_t1(t
, p
) else p
2184 debug (fn () => "movethingsnode " ^ nm ^
"\n");
2185 fold
move_t (set tu
) (fold
move_a (set au
) P
)
2188 exception MOVETHINGSWINDOW
2189 fun move_things_window(P
, w
, nm
, fence_set
) =
2192 val foo
= debug (fn () =>
2193 "move_things_window(\n" ^
2194 progToString P ^
",\n" ^
2195 (makestring w
) ^
", " ^
2197 fold (fn (a
, b
) => a ^
", " ^ b
) (set fence_set
) "]" ^
2200 fun ntn (P
, nm
) = (nameToNode (P
, nm
))
2201 handle NAMETONODE
=> raise MOVETHINGSWINDOW
2202 val node
= ntn(P
, nm
)
2203 val things
= num_things_node node
2204 val s_nm_list
= filterSucc(P
, nm
, fence_set
)
2206 move_things_window(p
, w
- things
, nm
, fence_set
)
2207 val child_p
= if w
> things
then fold nxt s_nm_list P
else P
2209 debug (fn () => "movethingswindow " ^ nm ^
"\n");
2210 move_things_node(child_p
, nm
, fence_set
)
2220 fun cpress(window
, P
, fence_set
, everin_fence_set
) =
2222 fun nxt(nm
, p
:program
) =
2224 move_things_window(p
, window
, nm
, fence_set
))
2225 handle MOVETHINGSWINDOW
=> raise CPRESS1
2226 val filled
= fold
nxt (set fence_set
) P
2227 handle CPRESS1
=> raise CPRESS2
2228 fun succf nm
= succ(filled
, nameToNode(filled
, nm
))
2229 handle NAMETONODE
=> raise CPRESS
2230 val nfence_set
= listUnion(make
::(map
succf (set fence_set
)))
2231 fun filt(a
, l
) = if member(everin_fence_set
, a
) then l
else a
::l
2232 val f_fence_set
= listToSet(fold
filt (set nfence_set
) nil
)
2234 fold (fn (a
, s
) => add(s
, a
)) (set f_fence_set
) everin_fence_set
2236 debug (fn () => "cpress: fence_set=" ^
2237 StrPak
.stringListString (set fence_set
) ^
2238 "\n f_fence_set =" ^ StrPak
.stringListString (set f_fence_set
));
2239 if not (empty f_fence_set
)
2240 then cpress(window
, filled
, f_fence_set
, n_everin_fc
)
2241 handle CPRESS
=> raise CPRESS3
2242 handle CPRESS1
=> raise CPRESS4
2243 handle CPRESS2
=> raise CPRESS5
2247 fun clean_up (P
as (ns
, n0
, F
):program
) =
2248 let val foo
= debug (fn () => "cleanup")
2249 val clos
= closure(P
, n0
)
2250 val (ns
, n0
, F
) = clos
2251 val l
= (map
name_of (Stringmap
.extract ns
))
2253 (debug (fn () => "cleanup deleting " ^ n
);
2254 delete(p
, nameToNode(p
, n
)))
2255 val answer
= fold f l clos
2256 val foo
= debug (fn () => "exiting cleanup")
2261 fun compress(window
, P
as (ns
, n0
, F
)) =
2264 val fence_set
= add(make
, name_of n0
)
2265 val everin_fence_set
= add(makeEQ(name_prefix_eq
), name_of n0
)
2266 val uc
= cpress(window
, P
, fence_set
, everin_fence_set
)
2267 val cu
= clean_up uc
2269 debug (fn () => "compress");
2279 HM
.operation list
-> (HM
.operation list
* Node
.program list
)
2282 (HM
.operation list
* Node
.program list
) -> HM
.operation list
2284 val progMap
: Node
.program
-> string
2286 val read_debug
: bool ref
2287 val write_debug
: bool ref
2288 val live_debug
: bool ref
2293 val read_debug
= ref
false
2294 val write_debug
= ref
false
2295 val live_debug
= ref
false
2298 if !read_debug
then print ("readI.read:" ^
f() ^
"\n")
2302 if !write_debug
then print ("writeI.read:" ^
f() ^
"\n")
2305 fun write_dbg_s s
= write_dbg (fn () => s
)
2309 fun btarget (nil
, n
) = (fn x
=> raise BTARGET
)
2310 |
btarget (h
::t
, n
) =
2312 val rf
= btarget(t
, n
+ 1)
2313 fun g lbl x
= if lbl
= x
then n
else rf x
2314 fun f (TARGET(lbl
, inst
)) = (g lbl
)
2321 val programs
= Node
.programs
2328 val t
= btarget(l
, 0)
2329 fun f (nil
, n
) = nil
2333 val nm
= makestring n
2334 val nxtnm
= makestring (n
+ 1)
2335 fun asn i
= Set
.listToSetEQ(aeq
, i
)
2336 val edag
= reach(Dag
.make
, NAME nxtnm
)
2337 fun tgtnm tgt
= makestring (t tgt
)
2338 fun edagt tgt
= reach(Dag
.make
, NAME (tgtnm tgt
))
2339 val finDag
= reach(Dag
.make
, NAME (Node
.name_of Node
.fin
))
2340 fun cdag (tgt
,tst
) = attach(tst
, edagt tgt
, edag
)
2342 fn ASSIGNMENT i
=> Node
.make(nm
, asn
[i
], edag
, Set
.make
)
2343 | NERGLE
=> Node
.make(nm
, asn
[], edag
, Set
.make
)
2344 |
LABELREF (tgt
, i
as GETLAB
{lab
, dst
}) =>
2346 asn
[GETLAB
{lab
=(t tgt
, tgtnm tgt
),
2349 |
COMPARISON (tgt
, tst
) =>
2350 Node
.make(nm
, asn nil
, cdag(tgt
, tst
), Set
.make
)
2352 Node
.make(nm
, asn nil
, edagt tgt
, Set
.make
)
2353 | EXIT i
=> Node
.make(nm
, asn
[i
], finDag
, Set
.make
)
2354 |
TARGET (lbl
, i
) =>
2355 Node
.make(nm
, asn nil
, edag
, Set
.make
)
2358 (g ci
)::Node
.fin
::(f (rest
, n
+ 1))
2360 fun addn(n
, p
) = Node
.addNode(p
, n
)
2361 val prog
= fold
addn (Node
.fin
:: f(l
, 0)) (Node
.makeProg())
2370 fun junkfil (JUNK a
, (junk
, other
)) = (JUNK a
:: junk
, other
)
2371 |
junkfil (x
, (junk
, other
)) = (junk
, x
::other
)
2372 val cl
= map HM
.classify ol
2373 val (junk
, other
) = fold junkfil
cl (nil
, nil
)
2374 fun ntn x
= (Node
.nameToNode x
)
2375 handle NAMETONODE
=> raise READI_NTN
2376 val (ns
, foo
, fin
) = buildNodes other
2377 val nn
= (ns
, ntn((ns
, foo
, fin
), "0"), fin
)
2378 fun unjunk (JUNK i
) = i
2379 | unjunk _
= raise READI
2380 val progs
= programs nn
2382 (fn () => ("progs =>" ^
2383 (StrPak
.stringListString
2384 (map Node
.progToString progs
))))
2386 (map unjunk junk
, progs
)
2392 type obj
= Node
.program
2398 if d
>="0" andalso d
<="9" then f(n
*10+ord(d
)-z
, l
)
2404 fun gt((nsa
, n0a
, Fa
), (nsb
, n0b
, Fb
)) =
2405 let val a
= explode (Node
.name_of n0a
)
2406 val b
= explode (Node
.name_of n0b
)
2412 structure sortP
= Sort (ps
)
2414 fun live_dbg f
= if !live_debug
then print ("live:" ^
f() ^
"\n")
2417 fun build_live_tab(P
as (ns
, n0
, F
): Node
.program
) =
2421 fun fil (a
, b
) = if a
< 0 orelse Delay
.is_bogus_reg (a
, "") then b
2423 fun fil_lset s
= fold
fil (set s
) make
2424 val lt
:(int set
) Stringmap
.stringmap
= Stringmap
.new()
2425 val finset
= listToSet
[0, 1, 2, 3, 4, 5]
2427 if Stringmap
.isin
lt (name_of n
) then Stringmap
.map
lt (name_of n
)
2430 let fun fl n
= flive dfs n
2431 val nm
= name_of cur
2432 val gen
= (fil_lset
o readNode
) cur
2433 val kill
= writeNode cur
2434 val foo
= Stringmap
.add
lt (nm
, gen
)
2435 val children
= succNodes(P
, cur
)
2436 val ch_live
= if empty children
then finset
2437 else listUnion (map
fl (set children
))
2438 val live
= union(diff(ch_live
, kill
), gen
)
2439 val foo
= Stringmap
.rm lt nm
2440 val foo
= Stringmap
.add
lt (nm
, live
)
2447 let val ans
= Stringmap
.map lt nm
2448 val foo
= live_dbg (fn () => nm ^
"=>" ^
2449 StrPak
.stringListString
2450 (map
makestring (set ans
)))
2456 (* live is the union
of live
in successors
*)
2457 fun branch_live (P
, tab
, nm
) =
2459 val s
= Set
.set (succ(P
, nameToNode(P
, nm
)))
2460 val l
:int Set
.set
= Set
.listUnion (map tab s
)
2462 (fn()=>("branch_live " ^ nm ^
" s=" ^
2463 StrPak
.stringListString s ^
" -> " ^
2464 StrPak
.stringListString (map
makestring (Set
.set l
))))
2471 exception WRITEP_NTN
2473 fun writeP (entry_map
, lbl_fun
, P
as (ns
, n0
, F
):Node
.program
) =
2479 val foo
= write_dbg(fn () => "program:" ^ progToString P
)
2480 fun blblmap nil
= (fn x
=> (print ("blblmap_" ^ x
); raise WRITEP
))
2482 let val mp
= blblmap t
2483 val mylab
= lbl_fun()
2485 (fn x
=> if x
= nm
then mylab
else mp x
)
2487 val lblmap
= blblmap(map
name_of (Stringmap
.extract ns
))
2488 val live_tab
= build_live_tab P
2489 fun label_list nm
= map (fn r
=> (r
, "")) (set (live_tab nm
))
2491 map (fn r
=> (r
, "")) (set (branch_live(P
, live_tab
, nm
)))
2492 fun getlab (GETLAB
{lab
=(i
,s
), dst
}) =
2493 GETLAB
{lab
=(entry_map s
, "node" ^ s
), dst
=dst
}
2494 | getlab _
= raise WRITEP1
2495 fun dogetlabs (i
as GETLAB _
, l
) = (getlab i
) :: l
2496 |
dogetlabs (i
, l
) = i
:: l
2497 fun ubranch (frm
, nm
) =
2498 BRANCH
{test
=ieq
, src1
=(0, "zero"), src2
=(0, "zero"),
2499 dst
=(lblmap nm
, "node" ^ nm
), live
=br_list frm
}
2500 fun cbranch (BRANCH
{test
, src1
, src2
, dst
, live
}, frm
, nm
) =
2501 BRANCH
{test
=test
, src1
=src1
, src2
=src2
,
2502 dst
=(lblmap nm
, "node" ^ nm
), live
=br_list frm
}
2503 | cbranch _
= (print
"cbranch"; raise Match
)
2504 fun label nm
= LABEL
{lab
=(lblmap nm
, "node" ^ nm
), live
=label_list nm
}
2505 fun entry_label nm
=
2506 LABEL
{lab
=(entry_map nm
, "entry"), live
=label_list nm
}
2508 fun f (done
, lastnm
, nm
) =
2509 let val foo
= write_dbg
2512 StrPak
.stringListString (set done
) ^
"," ^
2515 if nm
= name_of F
then (write_dbg_s
"fin"; (done
, [NOP
]))
2516 else if member(done
, nm
) then (write_dbg_s
"already";
2517 (done
, [NOP
, ubranch(lastnm
, nm
)]))
2520 val foo
= write_dbg_s
"doing"
2521 val node
= nameToNode(P
, nm
)
2522 handle NAMETONODE
=> raise WRITEP_NTN
2524 let val pd
= set (pred (P
, node
))
2526 (fn () => ("needlabel pd=" ^
2527 StrPak
.stringListString pd
))
2529 |
f ((p
::nil
):Ntypes
.name list
) =
2530 let val pn
= nameToNode(P
, p
:Ntypes
.name
)
2532 (fn () => ("ndlbl: pn=" ^
2537 fun istst (TEST t
) =
2538 (write_dbg_s
"ist true\n";
2541 (write_dbg_s
"ist false\n";
2544 (write_dbg_s
"ist false\n";
2546 fun untst (TEST t
) = t
2547 | untst _
= (print
"needlabel1";
2549 fun unnm (NAME nm
) = nm
2550 | unnm _
= (print
"needlabel2";
2557 unnm(sel(untst rt
, true)) ^
2562 (sel(untst rt
, true) = NAME nm
)
2564 |
f (a
::b
::c
) = true
2567 (fn () => ("needlabel=>" ^
2568 Bool.toString answer
))
2572 val nodelabel
= if needlabel
then [label nm
] else nil
2574 val a
= fold
dogetlabs (set (assignment_of node
)) nil
2578 (* only works for
<= 1 test
*)
2579 fun dag_code NEITHER
= (nil
, nil
)
2580 |
dag_code (NAME n
) = ([n
], nil
)
2581 |
dag_code (TEST t
) =
2582 let fun unnm (NAME x
) = x
2583 | unnm _
= (print
"dag_code"; raise Match
)
2584 val t_n
= unnm(sel(t
, true))
2585 val f_n
= unnm(sel(t
, false))
2587 ([f_n
, t_n
], [cbranch(t
, nm
, t_n
)])
2589 val (nl
, cd
) = dag_code rt
2590 exception DFS_SURPRISE
2591 fun dfs (done
, nil
) = (write_dbg_s
"dfs nil";
2593 |
dfs (done
, h
::nil
) = (write_dbg_s
"dfs 1";
2595 |
dfs (done
, h
::nxt
::nil
) =
2596 let val foo
= write_dbg_s
"dfs 2"
2597 val (dn1
, cd1
) = f(done
, nm
, h
)
2599 if member(dn1
, nxt
) then (dn1
, nil
)
2600 else dfs(dn1
, nxt
::nil
)
2602 if nxt
= name_of F
orelse
2603 member(dn2
, nxt
) then [NOP
]
2604 else [NOP
, label nxt
]
2606 (dn2
, cd1 @ lbl @ cd2
)
2608 | dfs _
= raise DFS_SURPRISE
2609 val (dn
, dcd
) = dfs(add(done
, nm
), nl
)
2611 (dn
, NOP
:: nodelabel @ a @ cd @ dcd
)
2614 val (done
, code
) = f (Set
.make
, "badname", name_of n0
)
2616 (entry_label (name_of n0
)) :: (label (name_of n0
)) :: code
2621 fun progMap(p
as (ns
, n0
, F
)) =
2622 let val l
= Node
.sortNodes (Stringmap
.extract ns
)
2624 fun pr s
= outstr
:= !outstr ^ s
2625 fun ntn n
= Node
.nameToNode(p
, n
)
2626 val n0nm
= Node
.name_of n0
2627 val nFnm
= Node
.name_of F
2629 let val s
= Set
.set (Node
.succ(p
, n
))
2630 val nm
= Node
.name_of n
2631 val pre
= if nm
= n0nm
then "->\t"
2633 val post
= if nm
= nFnm
then "\t->\n"
2637 Node
.name_of n ^
"\t->\t" ^ StrPak
.stringListString s ^
2645 fun writeI(j
:AbsMach
.opcode list
, p
:Node
.program list
) =
2646 let val labelid
= ref
0
2647 fun newlabel () = (labelid
:= !labelid
+ 1; !labelid
- 1)
2648 fun bentrymap nil
= (fn x
=> (print ("bentrymap_" ^ x
); raise WRITEI
))
2649 |
bentrymap ((ns
, n0
, F
)::t
) =
2650 let val mp
= bentrymap t
2651 val mylab
= newlabel()
2653 (fn x
=> if x
= Node
.name_of n0
then mylab
else mp x
)
2655 val entry_map
= bentrymap p
2656 val sp
= sortP
.sort p
2657 fun wp p
= writeP (entry_map
, newlabel
, p
)
2658 fun f(a
, b
) = (wp a
) @ b
2659 val i
= fold f sp nil
2671 exception Data_dependency_checked
2672 exception End_of_Program
2673 exception Simulator_error_1
2674 exception Simulator_error_2
2675 exception illegal_branch_within_branchdelay
2676 exception illegal_jump_within_branchdelay
2677 exception illegal_operator_or_operand
2678 exception negative_label_offset
2679 exception no_address_in_register
2680 exception no_label_in_register
2681 exception no_memory_address_in_register
2682 exception runtime_error_in_labwords
2683 exception runtime_error_in_words_or_labwords
2684 exception type_mismatch_in_comparison
2685 exception wrong_label
2686 val breakptr
: int -> unit
2688 val d_m
: int * int -> unit
2689 val d_ms
: int list
-> unit
2690 val d_pc
: unit
-> unit
2691 val d_r
: unit
-> unit
2692 val d_regs
: int list
-> unit
2693 val init
: AbsMach
.opcode list
-> unit
2694 val mcell
: int -> AbsMach
.values
2695 val pc
: unit
-> AbsMach
.opcode list
2696 val pinit
: int * (AbsMach
.arithop
-> int) * int * AbsMach
.opcode list
2698 val pptr
: unit
-> int
2699 val prun
: unit
-> unit
2700 val pstep
: unit
-> unit
2701 val regc
: int -> AbsMach
.values
2702 val run
: unit
-> unit
2703 val runcount
: int ref
2704 val step
: unit
-> unit
2705 val vinit
: int * AbsMach
.opcode list
-> unit
2706 val vpc
: unit
-> unit
2707 val vrun1
: unit
-> unit
2708 val vrun2
: unit
-> unit
2709 val vrun3
: unit
-> unit
2710 val vstep1
: unit
-> unit
2711 val vstep2
: unit
-> unit
2712 val vstep3
: unit
-> unit
2714 val Memory
: (AbsMach
.values array
) ref
2718 structure SetEnv
: SIMLABS
=
2723 val codes
: (opcode list ref
)=ref nil
;
2725 val RegN
=ref
0 and LabN
=ref
0 and memorysize
=ref
10000;
2726 (*RegN
= (pointer to
) number
of registers needed
;
2727 LabN
= (pointer to
) number
of labels
;
2728 memorysize
=(pointer to
) memory space size
.
2730 val IP
: (opcode list
) ref
=ref nil
;
2731 val inivalue
=(INT
0);
2732 (*IP
= Program Pointer
;
2733 inivalue
= zero
- initial value
of memory
and registers
.
2735 val Reg
=ref (array(0,inivalue
)) and Memory
=ref (array(0,inivalue
))
2736 and Lab_Array
=ref (array(0, (0,IP
) ));
2737 (*Reg
= register array
;
2738 Memory
= memory cell array
;
2739 Lab_Array
= label
-opcode list array
.
2742 fun max(n1
:int,n2
:int)=if (n1
>n2
) then n1
else n2
;
2744 (* hvnop tests whether the instruction is not a
real machine instruction
,
2745 but only useful
in simulation
.
2747 fun hvnop(LABEL
{...})=true |
2748 hvnop(LABWORD
{...})=true |
2749 hvnop(WORD
{...})=true |
2752 (*count_number is used to take into account register references
and label
2753 declarations
, and change RegN or LabN
.
2755 fun count_number(FETCH
{ptr
=(n1
,_
),dst
=(n2
,_
),...})=
2756 (RegN
:=max((!RegN
),max(n1
,n2
)) ) |
2757 count_number(STORE
{src
=(n1
,_
),ptr
=(n2
,_
),...})=
2758 (RegN
:=max((!RegN
),max(n1
,n2
)) ) |
2759 count_number(ARITHI
{src1
=(n1
,_
),dst
=(n2
,_
),...})=
2760 (RegN
:=max((!RegN
),max(n1
,n2
)) ) |
2761 count_number(MOVE
{src
=(n1
,_
),dst
=(n2
,_
)})=
2762 (RegN
:=max((!RegN
),max(n1
,n2
)) ) |
2763 count_number(BRANCH
{src1
=(n1
,_
),src2
=(n2
,_
),...})=
2764 (RegN
:=max((!RegN
),max(n1
,n2
)) ) |
2765 count_number(GETLAB
{dst
=(n
,_
),...})=
2766 (RegN
:=max((!RegN
),n
) ) |
2767 count_number(GETREAL
{dst
=(n
,_
),...})=
2768 (RegN
:=max((!RegN
),n
) ) |
2769 count_number(ARITH
{src1
=(n1
,_
),src2
=(n2
,_
),dst
=(n3
,_
),...})=
2770 (RegN
:=max((!RegN
),max(n1
,max(n2
,n3
)) ) ) |
2771 count_number(LABEL
{...})=
2775 (* scan is used to scan the opcode list for the first time
, to determine
2776 the size
of Reg
and Lab_Array
, i
.e
. number
of registers
and labels
.
2779 scan(h
::t
)=(count_number(h
);scan(t
));
2781 (* setlabels is used to set the label array
, of which each item is a
2782 pair (label
, codep
), codep points to the codes containing the LABEL
2783 statement
and afterwards codes
.
2785 fun setlabels(nil
,_
)= () |
2786 setlabels(codel
as ((LABEL
{lab
=(l
,_
),...})::t
),k
)=
2787 (update((!Lab_Array
),k
,(l
,ref codel
)); setlabels(t
,k
+1) ) |
2788 setlabels(h
::t
,k
)=setlabels(t
,k
) ;
2790 (* initializing the enviroment
of the simulation
.
2792 fun init(l
)=(RegN
:=0; LabN
:=0; IP
:=l
; codes
:=l
;
2793 scan(!IP
); Ref
.inc(RegN
);
2794 Reg
:=array( (!RegN
), inivalue
) ;
2795 Memory
:=array( (!memorysize
), inivalue
) ;
2796 Lab_Array
:=array( (!LabN
), (0,IP
));
2802 exception wrong_label
;
2803 exception runtime_error_in_labwords
;
2804 exception runtime_error_in_words_or_labwords
;
2805 exception negative_label_offset
;
2806 exception no_label_in_register
;
2807 exception illegal_operator_or_operand
;
2808 exception type_mismatch_in_comparison
;
2809 exception no_address_in_register
;
2810 exception no_memory_address_in_register
;
2812 (* getresult gives the results
of arithmtic operations
2814 fun getresult(iadd
,INT (n1
:int),INT (n2
:int))=INT (n1
+n2
) |
2815 getresult(isub
,INT (n1
:int),INT (n2
:int))=INT (n1
-n2
) |
2816 getresult(imul
,INT (n1
:int),INT (n2
:int))=INT (n1
*n2
) |
2817 getresult(idiv
,INT (n1
:int),INT (n2
:int))=INT (n1
div n2
) |
2818 getresult(fadd
,REAL (r1
:real),REAL (r2
:real))=REAL (r1
+r2
) |
2819 getresult(fsub
,REAL (r1
:real),REAL (r2
:real))=REAL (r1
-r2
) |
2820 getresult(fmul
,REAL (r1
:real),REAL (r2
:real))=REAL (r1
*r2
) |
2821 getresult(fdiv
,REAL (r1
:real),REAL (r2
:real))=REAL (r1
/r2
) |
2822 getresult(iadd
,INT (n1
:int),LABVAL (l
,k
))=LABVAL (l
,k
+n1
) |
2823 getresult(iadd
,LABVAL (l
,k
),INT (n1
:int))=LABVAL (l
,k
+n1
) |
2824 getresult(isub
,LABVAL (l
,k
),INT (n1
:int))=LABVAL (l
,k
-n1
) |
2825 getresult(orb
,INT n1
,INT n2
)=INT (Bits
.orb(n1
,n2
)) |
2826 getresult(andb
,INT n1
,INT n2
)=INT (Bits
.andb(n1
,n2
)) |
2827 getresult(xorb
,INT n1
,INT n2
)=INT (Bits
.xorb(n1
,n2
)) |
2828 getresult(rshift
,INT n1
,INT n2
)=INT (Bits
.rshift(n1
,n2
)) |
2829 getresult(lshift
,INT n1
,INT n2
)=INT (Bits
.lshift(n1
,n2
)) |
2830 getresult(real,INT n
,_
)=REAL (intToReal(n
)) |
2831 getresult(floor
,REAL r
,_
)=INT (Real.floor(r
)) |
2832 (* getresult(logb
,REAL r
,_
)=INT (System
.Unsafe
.Assembly
.A
.logb(r
))|
*)
2833 getresult(_
)=raise illegal_operator_or_operand
;
2835 (* compare gives the results
of comparisons
in BRANCH statement
.
2837 fun compare(ilt
,INT n1
,INT n2
)= (n1
<n2
) |
2838 compare(ieq
,INT n1
,INT n2
)= (n1
=n2
) |
2839 compare(igt
,INT n1
,INT n2
)= (n1
>n2
) |
2840 compare(ile
,INT n1
,INT n2
)= (n1
<=n2
) |
2841 compare(ige
,INT n1
,INT n2
)= (n1
>=n2
) |
2842 compare(ine
,INT n1
,INT n2
)= (n1
<>n2
) |
2843 compare(flt
,REAL r1
,REAL r2
)= (r1
<r2
) |
2844 compare(feq
,REAL r1
,REAL r2
)= (realEq(r1
,r2
)) |
2845 compare(fgt
,REAL r1
,REAL r2
)= (r1
>r2
) |
2846 compare(fle
,REAL r1
,REAL r2
)= (r1
<=r2
) |
2847 compare(fge
,REAL r1
,REAL r2
)= (r1
>=r2
) |
2848 compare(fne
,REAL r1
,REAL r2
)= (realNe(r1
,r2
)) |
2849 compare(inrange
,INT a
,INT b
)= (a
>=0) andalso (a
<b
) |
2850 compare(outofrange
,INT a
,INT b
)=(a
<0) orelse (a
>b
) |
2851 compare(inrange
,REAL a
,REAL b
)= (a
>=0.0) andalso (a
<b
) |
2852 compare(outofrange
,REAL a
,REAL b
)=(a
<0.0) orelse (a
>b
) |
2853 compare(_
)=raise type_mismatch_in_comparison
;
2855 (* findjmp_place returns the pointer to the codes corresponding to the
2856 given
label (the codes containing the LABEL statement itself
).
2858 fun findjmp_place lab
=
2859 let val ipp
=ref (ref nil
) and i
=ref
0 and flag
=ref
true;
2860 val none
=(while ( (!i
< !LabN
) andalso (!flag
) ) do
2861 ( let val (l
,p
)=((!Lab_Array
) sub (!i
)) in
2862 if (l
=lab
) then (ipp
:=p
;flag
:=false)
2867 in if (!flag
) then raise wrong_label
2871 (* findjmp_word returns the content
of the k th labword
in a code stream
.
2873 fun findjmp_word(k
,ip
)=if (k
<0) then raise negative_label_offset
2874 else let fun f2(1,LABWORD
{lab
=(herepos
,_
)}::t
)
2876 f2(k
,LABWORD
{...}::t
)=f2(k
-1,t
) |
2877 f2(_
)=raise runtime_error_in_labwords
;
2881 (* inst_word returns the content
of the k
'th
word or labword
in a code
2884 fun inst_word(k
,ip
)=if (k
<0) then raise negative_label_offset
2885 else let fun f(1,LABWORD
{lab
=(herepos
,_
)}::t
)
2886 =LABVAL (herepos
,0) |
2887 f(1,WORD
{value
=n
}::t
)=INT n |
2888 f(k
,LABWORD
{...}::t
)=f(k
-1,t
) |
2889 f(k
,WORD
{...}::t
)=f(k
-1,t
) |
2891 runtime_error_in_words_or_labwords
2896 (* execjmp changes IP
, makes it point to the codes
of the given label
.
2898 fun execjmp(LABVAL (l
,0))= (IP
:= !(findjmp_place l
) ) |
2899 execjmp(LABVAL (l
,k
))= (IP
:=
2901 (findjmp_word(k
,findjmp_place(l
) ) ) )
2903 execjmp(_
) = raise no_label_in_register
;
2905 (* addrplus returns the result
of address
+offset
.
2907 fun addrplus(INT n
,ofst
)= n
+ofst |
2908 addrplus(_
,_
)=raise no_memory_address_in_register
;
2910 (* content gives the content
of the fetched
word.
2912 fun content(INT n
,ofst
)= (!Memory
) sub (n
+ofst
) |
2913 content(LABVAL (l
,k
),ofst
)=inst_word(k
+ofst
,findjmp_place(l
)) |
2914 content(_
,_
)=raise no_address_in_register
;
2916 (* exec executes the given instruction
.
2918 fun exec(FETCH
{immutable
=_
,offset
=ofst
,ptr
=(p
,_
),dst
=(d
,_
)})=
2919 update((!Reg
),d
,content((!Reg
) sub p
,ofst
) ) |
2920 exec(STORE
{offset
=ofst
,src
=(s
,_
),ptr
=(p
,_
)})=
2921 update((!Memory
),addrplus((!Reg
) sub p
,ofst
),(!Reg
) sub s
) |
2922 exec(GETLAB
{lab
=(l
,_
),dst
=(d
,_
)})=
2923 update((!Reg
),d
,(LABVAL (l
,0)) ) |
2924 exec(GETREAL
{value
=v
,dst
=(d
,_
)})=
2925 update((!Reg
),d
,(REAL (strToReal v
))) |
2926 exec(MOVE
{src
=(s
,_
),dst
=(d
,_
)})=
2927 update((!Reg
),d
, (!Reg
) sub s
) |
2930 exec(LABWORD
{...}) =
2934 exec(JUMP
{dst
=(d
,_
),...})=
2935 execjmp((!Reg
) sub d
) |
2936 exec(ARITH
{oper
=opn
,src1
=(s1
,_
),src2
=(s2
,_
),dst
=(d
,_
)})=
2937 update((!Reg
),d
,getresult(opn
,(!Reg
) sub s1
,(!Reg
) sub s2
) ) |
2938 exec(ARITHI
{oper
=opn
,src1
=(s1
,_
),src2
=n1
,dst
=(d
,_
)})=
2939 update((!Reg
),d
,getresult(opn
,(!Reg
) sub s1
,(INT n1
) ) ) |
2940 exec(BRANCH
{test
=comp
,src1
=(s1
,_
),src2
=(s2
,_
),dst
=(labnum
,_
),...})=
2941 if compare(comp
,(!Reg
) sub s1
,(!Reg
) sub s2
)
2942 then (IP
:= !(findjmp_place(labnum
) ) )
2945 exec(BOGUS _
)= raise Match
2951 exception End_of_Program
;
2954 val Instruction
=(hd(!IP
) handle Hd
=> raise End_of_Program
)
2956 (IP
:=tl(!IP
) handle Tl
=>raise End_of_Program
;
2959 fun run () =(step();run() )
2960 handle End_of_Program
=>output(std_out
,"End of program\n");
2962 (* bms
, ims
, rms are simply abbreviations
.
2964 val bms
: bool -> string = Bool.toString
2965 and ims
: int -> string = Int.toString
2966 and rms
: real -> string = Real.toString
2968 (* dispv shows the content
of a register
, dispm shows the content
of a
2971 fun dispv(n
,INT k
)=output(std_out
,"Register "^
ims(n
)^
": "^
2972 "INT "^
ims(k
)^
"\n") |
2973 dispv(n
,REAL r
)=output(std_out
,"Register "^
ims(n
)^
": "^
2974 "REAL "^
rms(r
)^
"\n") |
2975 dispv(n
,LABVAL (l
,0))=output(std_out
,
2976 "Register "^
ims(n
)^
": "^
2977 "LABEL "^
ims(l
)^
"\n") |
2978 dispv(n
,LABVAL (l
,k
))=output(std_out
,
2979 "Register "^
ims(n
)^
": "^
2980 "LABWORD "^
ims(k
)^
" after"^
2981 "LABEL "^
ims(l
)^
"\n") ;
2983 fun dispm(n
,INT k
)=output(std_out
,"Memory "^
ims(n
)^
": "^
2984 "INT "^
ims(k
)^
"\n") |
2985 dispm(n
,REAL r
)=output(std_out
,"Memory "^
ims(n
)^
": "^
2986 "REAL "^
rms(r
)^
"\n") |
2987 dispm(n
,LABVAL (l
,0))=output(std_out
,
2988 "Memory "^
ims(n
)^
": "^
2989 "LABEL "^
ims(l
)^
"\n") |
2990 dispm(n
,LABVAL (l
,k
))=output(std_out
,
2991 "Memory "^
ims(n
)^
": "^
2992 "LABWORD "^
ims(k
)^
" after"^
2993 "LABEL "^
ims(l
)^
"\n") ;
2995 (* oms
and cms give the strings
of the functions
and comparisions
.
2997 fun oms(iadd
)="iadd" |
oms(isub
)="isub" |
2998 oms(imul
)="imul" |
oms(idiv
)="idiv" |
2999 oms(fadd
)="fadd" |
oms(fsub
)="fsub" |
3000 oms(fmul
)="fmul" |
oms(fdiv
)="fdiv" |
3001 oms(real)="real" |
oms(floor
)="floor" |
oms(logb
)="logb" |
3002 oms(orb
)="orb" |
oms(andb
)="andb" |
oms(xorb
)="xorb" |
3003 oms(rshift
)="rshift" |
oms(lshift
)="lshift" ;
3005 fun cms(ilt
)="ilt" |
cms(igt
)="igt" |
cms(ieq
)="ieq" |
3006 cms(ile
)="ile" |
cms(ige
)="ige" |
cms(ine
)="ine" |
3007 cms(flt
)="flt" |
cms(fgt
)="fgt" |
cms(feq
)="feq" |
3008 cms(fle
)="fle" |
cms(fge
)="fge" |
cms(fne
)="fne" |
3009 cms(outofrange
)="outofrange" |
cms(inrange
)="inrange" ;
3011 (* lms gives the
string of the live register list
.
3014 lms((h
,s
)::nil
)="("^
ims(h
)^
","^s^
")" |
3015 lms((h
,s
)::t
)="("^
ims(h
)^
","^s^
"),"^
lms(t
);
3017 (* disp gives the
string for the instruction
.
3019 fun disp(FETCH
{immutable
=b
,offset
=ofst
,ptr
=(p
,s1
),dst
=(d
,s2
)}) =
3020 "FETCH{immutable="^
bms(b
)^
",offset="^
ims(ofst
) ^
",ptr=("^
ims(p
)^
","^s1
3021 ^
"),dst=("^
ims(d
)^
","^s2^
")}\n" |
3023 disp(STORE
{offset
=ofst
,src
=(s
,s1
),ptr
=(p
,s2
)}) =
3024 "STORE{offset="^
ims(ofst
)^
",src=("^
ims(s
)^
","^s1^
"),ptr=("
3025 ^
ims(p
)^
","^s2^
")}\n" |
3027 disp(GETLAB
{lab
=(l
,ls
),dst
=(d
,ds
)}) =
3028 "GETLAB{lab=("^
ims(l
)^
","^ls^
"),dst=("^
ims(d
)^
","^ds^
")}\n" |
3030 disp(GETREAL
{value
=r
,dst
=(d
,ds
)}) =
3031 "GETREAL{value="^r^
",dst=("^
ims(d
)^
","^ds^
")}\n" |
3033 disp(ARITH
{oper
=opn
,src1
=(s1
,ss1
),src2
=(s2
,ss2
),dst
=(d
,ds
)})=
3034 "ARITH{oper="^
oms(opn
)^
",src1=("^
ims(s1
)^
","^ss1^
"),src2=("^
ims(s2
)
3035 ^
","^ss2^
"),dst=("^
ims(d
)^
","^ds^
")}\n" |
3037 disp(ARITHI
{oper
=opn
,src1
=(s1
,ss1
),src2
=n
,dst
=(d
,ds
)})=
3038 "ARITH{oper="^
oms(opn
)^
",src1=("^
ims(s1
)^
","^ss1^
"),src2="^
ims(n
)^
3039 ",dst=("^
ims(d
)^
","^ds^
")}\n" |
3041 disp(MOVE
{src
=(s
,ss
),dst
=(d
,ds
)})=
3042 "MOVE{src=("^
ims(s
)^
","^ss^
"),dst=("^
ims(d
)^
","^ds^
")}\n" |
3044 disp(BRANCH
{test
=comp
,src1
=(s1
,ss1
),src2
=(s2
,ss2
),dst
=(labnum
,ss3
),
3046 "BRANCH{test="^
cms(comp
)^
",src1=("^
ims(s1
)^
","^ss1^
"),src2=("^
ims(s2
)
3047 ^
","^ss2^
"),dst=("^
ims(labnum
)^
","^ss3^
"),live=["^
lms(lt
)^
"]}\n" |
3049 disp(JUMP
{dst
=(d
,ds
),live
=lt
}) =
3050 "JUMP{dst=("^
ims(d
)^
","^ds^
"),live=["^
lms(lt
)^
"]}\n" |
3052 disp(LABWORD
{lab
=(l
,s
)})="LABWORD{lab=("^
ims(l
)^
","^s^
")}\n" |
3054 disp(LABEL
{lab
=(l
,s
),live
=lt
})=
3055 "LABEL{lab=("^
ims(l
)^
","^s^
"),live=["^
lms(lt
)^
"]}\n" |
3057 disp(WORD
{value
=n
})="WORD{value="^
ims(n
)^
"}\n" |
3060 disp(BOGUS _
) = raise Match
3064 fun d_pc () =output(std_out
,disp(hd(!IP
)) handle Hd
=>"No More Instruction\n");
3066 fun pptr () =(List.length(!codes
)-List.length(!IP
))+1;
3067 fun breakptr k
=let fun goon (LABEL
{lab
=(l
,_
),...})=(l
<>k
) |
3069 in while goon(hd(!IP
)) do step()
3071 fun regc n
=((!Reg
) sub n
);
3072 fun d_r () =let val i
=ref
0 in
3073 (while ( !i
< !RegN
) do
3074 (dispv((!i
),(!Reg
) sub (!i
)); Ref
.inc(i
) )
3077 fun d_regs (nil
)=() |
3078 d_regs (h
::t
)=(dispv(h
,(!Reg
) sub h
);d_regs(t
));
3080 fun mcell n
=((!Memory
) sub n
);
3081 fun d_m (n
,m
)=let val i
=ref n
in
3082 while ( !i
<=m
) do (dispm(!i
,(!Memory
) sub
!i
); Ref
.inc(i
) )
3085 d_ms (h
::t
)=(dispm(h
,(!Memory
) sub h
); d_ms(t
) );
3088 (* This part for the VLIW mode execution
. *)
3091 val runcount
=ref
0 and sizen
=ref
0 and flag
=ref
true;
3092 exception Simulator_error_1
;
3093 exception Simulator_error_2
;
3094 exception Data_dependency_checked
;
3096 (* member tests whether element a is
in a list
.
3098 fun member(a
,nil
)=false |
3099 member(a
,h
::t
)=if (a
=h
) then true else member(a
,t
);
3100 (* hvcom tests whether the intersection
of two list isnot nil
.
3102 fun hvcom(nil
,l
)=false |
3103 hvcom(h
::t
,l
)=member(h
,l
) orelse hvcom(t
,l
);
3105 (* gset returns the list
of registers refered
in a instruction
.
3106 gwset returns the list
of the register being written
in a instruction
.
3108 fun gset(FETCH
{ptr
=(p
,_
),dst
=(d
,_
),...})=[p
,d
] |
3109 gset(STORE
{src
=(s
,_
),ptr
=(p
,_
),...})=[s
,p
] |
3110 gset(GETLAB
{dst
=(d
,_
),...})=[d
] |
3111 gset(GETREAL
{dst
=(d
,_
),...})=[d
] |
3112 gset(ARITH
{src1
=(s1
,_
),src2
=(s2
,_
),dst
=(d
,_
),...})=[s1
,s2
,d
] |
3113 gset(ARITHI
{src1
=(s1
,_
),dst
=(d
,_
),...})=[s1
,d
] |
3114 gset(MOVE
{src
=(s
,_
),dst
=(d
,_
)})=[s
,d
] |
3115 gset(BRANCH
{src1
=(s1
,_
),src2
=(s2
,_
),...})=[s1
,s2
] |
3116 gset(JUMP
{dst
=(d
,_
),...})=[d
] |
3118 fun gwset(FETCH
{dst
=(d
,_
),...})=[d
] |
3119 gwset(GETLAB
{dst
=(d
,_
),...})=[d
] |
3120 gwset(GETREAL
{dst
=(d
,_
),...})=[d
] |
3121 gwset(ARITH
{dst
=(d
,_
),...})=[d
] |
3122 gwset(ARITHI
{dst
=(d
,_
),...})=[d
] |
3123 gwset(MOVE
{dst
=(d
,_
),...})=[d
] |
3126 (* fetchcode returns the instruction
word which contains the next k
3127 instruction
. fetchcode3 is used
in version
3 of VLIW mode
, in which
case
3128 labels within instruction words are OK
.
3130 fun fetchcode(0)=nil |
3131 fetchcode(k
)=let val h
=hd(!IP
) in
3134 then (output(std_out
,
3135 "Warning: labels within the instruction word\n");
3138 else h
::fetchcode(k
-1) )
3140 fun fetchcode3(0)=nil |
3141 fetchcode3(k
)=let val h
=hd(!IP
) in
3143 if hvnop(h
) then fetchcode3(k
)
3144 else h
::fetchcode3(k
-1) )
3147 (* allnop tests
if all instructions left mean no operation
.
3149 fun allnop(nil
)=true |
3150 allnop(NOP
::t
)=allnop(t
) |
3153 (* nopcut cut the instruction stream
in a way that the first half are all
3156 fun nopcut(nil
)=(nil
,nil
) |
3157 nopcut(NOP
::t
)=let val (l1
,l2
)=nopcut(t
) in (NOP
::l1
,l2
) end |
3160 (* cmdd tests the data dependency on memory cells
and IP
.
3162 fun cmdd(_
,nil
)=false |
3163 cmdd(wset
,STORE
{ptr
=(p
,_
),offset
=ofst
,...}::t
)=
3164 cmdd(addrplus((!Reg
) sub p
,ofst
)::wset
,t
) |
3165 cmdd(wset
,FETCH
{ptr
=(p
,_
),offset
=ofst
,...}::t
)=
3166 member(addrplus((!Reg
) sub p
,ofst
),wset
) orelse cmdd(wset
,t
) |
3167 cmdd(wset
,BRANCH
{...}::t
)=if allnop(t
) then false else true |
3168 cmdd(wset
,JUMP
{...}::t
)=if allnop(t
) then false else true |
3169 cmdd(wset
,h
::t
)=cmdd(wset
,t
);
3171 (* crdd test the data dependency on registers
.
3173 fun crdd(_
,nil
)=false |
3174 crdd(wset
,h
::t
)=if hvcom(gset(h
),wset
) then true
3175 else crdd(gwset(h
)@wset
,t
) ;
3177 (* check_dd checks whether there is data dependency
in instruction stream l
.
3179 fun check_dd(l
)= crdd(nil
,l
) orelse cmdd(nil
,l
);
3181 (* rddcut seperate the longest part
of the instruction stream that have no
3182 data dependency on registers
, from the left
.
3184 fun rddcut(_
,nil
)= (nil
,nil
) |
3185 rddcut(wset
,l
as (h
::t
))=
3186 if hvcom(gset(h
),wset
) then (nil
,l
)
3187 else let val (l1
,l2
)=rddcut(gwset(h
)@wset
,t
)
3190 (* mddcut seperate the longest part
of the instruction stream that have no data
3191 dependency on memory cells
and IP
, from the left
.
3193 fun mddcut(_
,nil
)= (nil
,nil
) |
3194 mddcut(wset
,(h
as STORE
{ptr
=(p
,_
),offset
=ofst
,...})::t
)=
3195 let val (l1
,l2
)=mddcut(addrplus((!Reg
) sub p
,ofst
)::wset
,t
)
3197 mddcut(wset
,(h
as FETCH
{ptr
=(p
,_
),offset
=ofst
,...})::t
)=
3198 if member(addrplus((!Reg
) sub p
,ofst
),wset
)
3200 else let val (l1
,l2
)=mddcut(wset
,t
) in (h
::l1
,l2
) end |
3201 mddcut(wset
,(h
as BRANCH
{...})::t
)=
3202 let val (l1
,l2
)=nopcut(t
) in (h
::l1
,l2
) end |
3203 mddcut(wset
,(h
as JUMP
{...})::t
)=
3204 let val (l1
,l2
)=nopcut(t
) in (h
::l1
,l2
) end |
3206 let val (l1
,l2
)=mddcut(wset
,t
) in (h
::l1
,l2
) end
3209 (* calcult returns the necessary value list corresponding to a instruction
3210 stream
. And change the IP when necessary
.
3212 fun calcult(nil
)=nil |
3213 calcult(FETCH
{ptr
=(p
,_
),offset
=ofst
,...}::t
)=
3214 content((!Reg
) sub p
,ofst
)::calcult(t
) |
3215 calcult(STORE
{src
=(s
,_
),...}::t
)=((!Reg
) sub s
)::calcult(t
) |
3216 calcult(MOVE
{src
=(s
,_
),...}::t
)=((!Reg
) sub s
)::calcult(t
) |
3217 calcult(ARITH
{oper
=opn
,src1
=(s1
,_
),src2
=(s2
,_
),...}::t
)=
3218 getresult(opn
,(!Reg
) sub s1
,(!Reg
) sub s2
)::calcult(t
) |
3219 calcult(ARITHI
{oper
=opn
,src1
=(s1
,_
),src2
=n1
,...}::t
)=
3220 getresult(opn
,(!Reg
) sub s1
,(INT n1
))::calcult(t
) |
3221 calcult(JUMP
{dst
=(d
,_
),...}::t
)=((!Reg
) sub d
)::calcult(t
) |
3222 calcult(h
::t
)=calcult(t
);
3224 (* dowr does the actual writing operations
.
3226 fun dowr(nil
,nil
)=() |
3227 dowr(nil
,h
::t
)=raise Simulator_error_1 |
3228 dowr(FETCH
{...}::t
,nil
)=raise Simulator_error_2 |
3229 dowr(STORE
{...}::t
,nil
)=raise Simulator_error_2 |
3230 dowr(MOVE
{...}::t
,nil
)=raise Simulator_error_2 |
3231 dowr(ARITH
{...}::t
,nil
)=raise Simulator_error_2 |
3232 dowr(ARITHI
{...}::t
,nil
)=raise Simulator_error_2 |
3233 dowr(JUMP
{...}::t
,nil
)=raise Simulator_error_2 |
3234 dowr(FETCH
{dst
=(d
,_
),...}::t
,vh
::vt
)=(update((!Reg
),d
,vh
);
3236 dowr(STORE
{ptr
=(p
,_
),offset
=ofst
,...}::t
,vh
::vt
)=
3237 (update((!Memory
),addrplus((!Reg
) sub p
,ofst
),vh
); dowr(t
,vt
) ) |
3238 dowr(GETLAB
{lab
=(l
,_
),dst
=(d
,_
)}::t
,vt
)=
3239 (update((!Reg
),d
,(LABVAL (l
,0)) ); dowr(t
,vt
) ) |
3240 dowr(GETREAL
{value
=v
,dst
=(d
,_
)}::t
,vt
)=
3241 (update((!Reg
),d
,(REAL (strToReal v
)) ); dowr(t
,vt
) ) |
3242 dowr(MOVE
{dst
=(d
,_
),...}::t
,vh
::vt
)=
3243 (update((!Reg
),d
,vh
); dowr(t
,vt
) ) |
3244 dowr(ARITH
{dst
=(d
,_
),...}::t
,vh
::vt
)=
3245 (update((!Reg
),d
,vh
); dowr(t
,vt
) ) |
3246 dowr(ARITHI
{dst
=(d
,_
),...}::t
,vh
::vt
)=
3247 (update((!Reg
),d
,vh
); dowr(t
,vt
) ) |
3248 dowr(JUMP
{...}::t
,vh
::vt
)=
3249 (execjmp(vh
); flag
:=false; dowr(t
,vt
) ) |
3250 dowr(BRANCH
{test
=comp
,src1
=(s1
,_
),src2
=(s2
,_
),
3251 dst
=(labnum
,_
),...}::t
,vt
)=
3252 if compare(comp
,(!Reg
) sub s1
,(!Reg
) sub s2
)
3253 then (IP
:= !(findjmp_place(labnum
)); flag
:=false; dowr(t
,vt
) )
3255 dowr(h
::t
,vt
)=dowr(t
,vt
)
3258 (* vv3 executes an instruction
word in version
3 mode
.
3261 vv3(l
)=let val (l1
,l2
)=rddcut(nil
,l
);
3262 val (l3
,l4
)=mddcut(nil
,l1
)
3263 in (flag
:=true; dowr(l3
,calcult(l3
)); Ref
.inc(runcount
);
3264 if (!flag
) then vv3(l4@l2
) else () )
3267 fun vinit(k
,l
)=(init(l
); sizen
:=k
; runcount
:=0 ) ;
3269 fun vstep1()=let val f
=(while hvnop(hd(!IP
)) do IP
:=tl(!IP
))
3270 handle Hd
=>raise End_of_Program
;
3271 val codel
=fetchcode(!sizen
)
3273 (dowr(codel
,calcult(codel
)); Ref
.inc(runcount
) )
3276 fun vstep2()=let val f
=(while hvnop(hd(!IP
)) do IP
:=tl(!IP
))
3277 handle Hd
=>raise End_of_Program
;
3278 val codel
=fetchcode(!sizen
)
3281 then (output(std_out
,"Data dependency checked in:\n");
3283 f(h
::t
)=(output(std_out
,":"^
disp(h
)); f(t
))
3285 raise Data_dependency_checked
3287 else (dowr(codel
,calcult(codel
)); Ref
.inc(runcount
) )
3290 fun vstep3()=let val f
=if (!IP
)=nil
then raise End_of_Program
else ();
3291 val codel
=fetchcode3(!sizen
)
3294 fun vrun1()=(vstep1();vrun1())
3295 handle End_of_Program
=>
3296 output(std_out
,"End of program.\nTotal runtime: "
3297 ^
ims(!runcount
)^
" steps.\n");
3298 fun vrun2()=(vstep2(); vrun2())
3299 handle End_of_Program
=>
3300 output(std_out
,"End of program.\nTotal runtime: "
3301 ^
ims(!runcount
)^
" steps.\n")|
3302 Data_dependency_checked
=>
3303 output(std_out
,"Program halted.\n") ;
3304 fun vrun3()=(vstep3(); vrun3())
3305 handle End_of_Program
=>
3306 output(std_out
,"End of program.\nTotal runtime: "
3307 ^
ims(!runcount
)^
" substeps.\n");
3309 fun vpc()=let val codel
=(!IP
) ;
3312 f (k
,h
::l
)=if k
<=0 then ()
3313 else (output(std_out
,disp(h
) );
3314 if hvnop(h
) then f(k
,l
)
3316 in f((!sizen
),codel
) end;
3319 (* This part for Pipeline mode
*)
3322 exception illegal_jump_within_branchdelay
;
3323 exception illegal_branch_within_branchdelay
;
3324 exception illegal_label_within_branchdelay
;
3325 exception illegal_labword_within_branchdelay
;
3326 exception illegal_word_within_branchdelay
;
3327 (* Rdelay points to the timing array
of registers
.
3329 val Rdelay
=ref ( array(0,0) );
3330 (* clock records run time
. withindelay is a flag used
in BRANCH
and JUMP delays
.
3332 val clock
=ref
0 and withindelay
=ref
false;
3333 val fdelay
=ref
1 and ardelay
: ((arithop
->int) ref
)=ref (fn k
=>1)
3336 (* pexec executes one instruction
, increasing the clock when necessary
, which
3337 corresponding to the holding down
of instruction streams
.
3339 fun pexec(FETCH
{immutable
=_
,offset
=ofst
,ptr
=(p
,_
),dst
=(d
,_
)})=
3340 (let val t
=(!Rdelay
) sub p
in
3341 if (!clock
)<t
then clock
:=t
else ()
3343 update((!Reg
),d
,content((!Reg
) sub p
,ofst
) );
3344 update((!Rdelay
),d
,(!clock
)+(!fdelay
));
3347 pexec(STORE
{offset
=ofst
,src
=(s
,_
),ptr
=(p
,_
)})=
3348 (let val t1
=((!Rdelay
) sub p
) and t2
=((!Rdelay
) sub s
) ;
3349 val t
=Int.max(t1
,t2
) in
3350 if (!clock
)<t
then clock
:=t
else ()
3352 update((!Memory
),addrplus((!Reg
) sub p
,ofst
),(!Reg
) sub s
);
3355 pexec(GETLAB
{lab
=(l
,_
),dst
=(d
,_
)})=
3356 (update((!Reg
),d
,(LABVAL (l
,0)) );
3359 pexec(GETREAL
{value
=v
,dst
=(d
,_
)})=
3360 (update((!Reg
),d
,(REAL (strToReal v
)) );
3363 pexec(MOVE
{src
=(s
,_
),dst
=(d
,_
)})=
3364 (let val t
=(!Rdelay
) sub s
in
3365 if (!clock
)<t
then clock
:=t
else ()
3367 update((!Reg
),d
,(!Reg
) sub s
);
3370 pexec(ARITH
{oper
=opn
,src1
=(s1
,_
),src2
=(s2
,_
),dst
=(d
,_
)})=
3371 (let val t1
=((!Rdelay
) sub s1
) and t2
=((!Rdelay
) sub s2
);
3372 val t
=Int.max(t1
,t2
) in
3373 if (!clock
)<t
then clock
:=t
else ()
3375 update((!Reg
),d
,getresult(opn
,(!Reg
) sub s1
,(!Reg
) sub s2
) );
3376 update((!Rdelay
),d
,((!ardelay
) opn
)+(!clock
) );
3379 pexec(ARITHI
{oper
=opn
,src1
=(s1
,_
),src2
=n1
,dst
=(d
,_
)})=
3380 (let val t
=((!Rdelay
) sub s1
) in
3381 if (!clock
)<t
then clock
:=t
else ()
3383 update((!Reg
),d
,getresult(opn
,(!Reg
) sub s1
,(INT n1
) ) );
3384 update((!Rdelay
),d
,((!ardelay
) opn
)+(!clock
) );
3387 pexec(JUMP
{dst
=(d
,_
),...})=
3388 if (!withindelay
) then raise illegal_jump_within_branchdelay
3390 (let val t
=((!Rdelay
) sub d
) in
3391 if (!clock
)<t
then clock
:=t
else ()
3393 Ref
.inc(clock
); withindelay
:=true;
3395 while ((!i
)<(!jdelay
)) do
3396 (let val h
=hd(!IP
) in
3397 ( pexec(h
); Ref
.inc(i
) )
3398 end handle Hd
=> (i
:=(!jdelay
) ) ;
3399 (IP
:=tl(!IP
)) handle Tl
=>()
3402 execjmp((!Reg
) sub d
)
3404 pexec(BRANCH
{test
=comp
,src1
=(s1
,_
),src2
=(s2
,_
),dst
=(labnum
,_
),...})=
3405 if (!withindelay
) then raise illegal_branch_within_branchdelay
3407 (let val t1
=((!Rdelay
) sub s1
) and t2
=((!Rdelay
) sub s2
);
3408 val t
=Int.max(t1
,t2
) in
3409 if (!clock
)<t
then clock
:=t
else ()
3411 Ref
.inc(clock
); withindelay
:=true;
3413 while ((!i
)<(!jdelay
)) do
3414 (let val h
=hd(!IP
) in
3415 ( pexec(h
); Ref
.inc(i
) )
3416 end handle Hd
=> (i
:=(!jdelay
) ) ;
3417 (IP
:=tl(!IP
)) handle Tl
=>()
3420 if compare(comp
,(!Reg
) sub s1
,(!Reg
) sub s2
)
3421 then (IP
:= !(findjmp_place(labnum
) ) )
3424 pexec(NOP
)=Ref
.inc(clock
) |
3425 pexec(LABEL
{...})=if (!withindelay
)
3426 then raise illegal_label_within_branchdelay
3428 pexec(LABWORD
{...})=if (!withindelay
)
3429 then raise illegal_labword_within_branchdelay
3431 pexec(WORD
{...})=if (!withindelay
)
3432 then raise illegal_word_within_branchdelay
3436 fun pinit(fetchdelay
,arithdelay
,jumpdelay
,l
)=
3438 Rdelay
:=array((!RegN
),0);
3439 clock
:=0; fdelay
:=fetchdelay
;
3440 ardelay
:=arithdelay
; jdelay
:=jumpdelay
);
3444 val Instruction
=(hd(!IP
) handle Hd
=>raise End_of_Program
)
3445 in (IP
:=tl(!IP
) handle Tl
=>raise End_of_Program
;
3446 withindelay
:=false; pexec(Instruction
) )
3449 fun prun()=(pstep(); prun() ) handle End_of_Program
=>
3450 (output(std_out
,"End of program.\n");
3451 output(std_out
,"Total time used: "^
ims(!clock
)^
" cycles.\n") );
3454 structure SimStuff
=
3458 let val if1
= (open_in
"simprelude.s")
3459 val if2
= (open_in file
)
3460 val if3
= (open_in
"simpostlude.s")
3461 val prelude
= ReadAbs
.read if1
3462 val prog
= ReadAbs
.read if2
3463 val postlude
= ReadAbs
.read if3
3468 prelude @ prog @ postlude
3471 fun init file
= SetEnv
.init (read file
)
3473 val runcount
= ref
0
3477 val foo
= runcount
:= 0
3478 fun updc NOP
= runcount
:= !runcount
+ 1
3481 fun f () = (step(); (updc
o hd
o pc
)(); f())
3486 fun srun () = let open SetEnv
in d_pc(); step(); srun() end;
3488 fun memsave () = !SetEnv
.Memory
3491 fun memcmp(a
:AbsMach
.values array
, b
:AbsMach
.values array
) =
3493 fun cmp (INT a
, INT b
) = a
= b
3494 |
cmp (REAL a
, REAL b
) = realEq(a
, b
)
3495 |
cmp (LABVAL _
, LABVAL _
) = true
3498 | f n
= if cmp((a sub n
), (b sub n
)) then f (n
- 1) else n
3499 val al
= Array
.length a
3500 val bl
= Array
.length b
3502 if al
= bl
then f (al
- 1) else (print
"size\n"; 0)
3507 let val la
= Array
.length a
3508 val na
= array(la
, a sub
0)
3509 fun f n
= if n
> 0 then (update(na
, n
, a sub n
) ; f (n
- 1)) else ()
3510 val foo
= f (la
- 1)
3516 exception PROG_NO_END
3520 fun vstring (INT i
) = "INT " ^ makestring i
3521 |
vstring (REAL i
) = "REAL " ^
Real.toString i
3522 |
vstring (LABVAL(i
, j
)) =
3523 "LABVAL(" ^ makestring i ^
", " ^ makestring j ^
")"
3530 handle End_of_Program
=> (print
"eop\n";
3534 fun cmprog(f1
, f2
) =
3536 fun intof (INT i
) = i
3537 fun ptsat p
= SetEnv
.mcell (intof p
)
3539 (* val foo
= print ("cmprog1:" ^ vstring p1 ^
"\n") *)
3543 (* val foo
= print ("cmprog2:" ^ vstring p2 ^
"\n") *)
3548 (f1 ^
" ct " ^ makestring r1 ^
" ptr " ^ vstring p1 ^
3549 " val " ^ vstring v1 ^
3550 f2 ^
" ct " ^ makestring r2 ^
" ptr " ^ vstring p2 ^
3551 " val " ^ vstring v2 ^
"\n")
3557 let (* open System
.Timer
3558 val s
= start_timer() *)
3561 val e
= check_timer s
3562 val foo
= print (str ^
" took " ^ makestring e ^
"sec.usec\n")
3569 fun writeprog(file
, j
, p
) =
3570 let val ot
= (open_out file
)
3571 val prog
= ReadI
.writeI(j
, p
)
3572 val filp
= (Delay
.rm_bogus
o OutFilter
.remnops
) prog
3573 val xxx
= PrintAbs
.show ot filp
3578 fun wp(file
, prog
) =
3579 let val ot
= (open_out file
)
3580 val filp
= Delay
.rm_bogus prog
3581 val xxx
= PrintAbs
.show ot filp
3586 fun dodelay i
= (Delay
.init i
; Delay
.add_delay i
);
3589 Node
.move_test_debug
:= false;
3590 Node
.move_op_debug
:= false;
3591 Node
.rw_debug
:= false;
3592 Node
.delete_debug
:= false;
3593 Node
.ntn_debug
:= true;
3594 Node
.prog_node_debug
:= false;
3595 Node
.prog_node_debug_verbose
:= false;
3596 Node
.closure_progs_debug
:= false;
3597 Node
.cpsiCheck
:= false;
3598 Compress
.compress_debug
:= false;
3599 ReadI
.read_debug
:= false;
3600 ReadI
.write_debug
:= false;
3601 ReadI
.live_debug
:= false
3604 fun pm pl
= print (StrPak
.stringListString (map ReadI
.progMap pl
));
3605 fun pp pl
= print (StrPak
.stringListString (map PrintAbs
.str pl
));
3607 fun ndnm nil
= raise Node
.NAMETONODE
3608 |
ndnm(h
::t
) = (fn (nm
) => Node
.nameToNode(h
, nm
)
3609 handle Node
.NAMETONODE
=> ndnm t nm
);
3613 fun err (s
:string) = (print s
; raise ERROR
);
3615 fun pmem nil
= (err
"oh well")
3616 |
pmem ((ns
, n0
, f
)::t
) =
3617 fn n
=> if Set
.member(ns
, n
) then (ns
, n0
, f
)
3620 structure Main
= struct
3622 fun doitx (ifile
:string, ofile
:string, c_ofile
:string, ws
:int) =
3623 let val foo
= Ntypes
.init_names()
3624 val ins
= open_in ifile
3625 val i
= (dodelay
o BreakInst
.breaki
o ReadAbs
.read
) ins
3626 val _
= close_in ins
3627 val (j
, p
) = time
"Building Nodes" (fn () => ReadI
.readI i
)
3628 val x
= time
"writing unopt" (fn () => writeprog(ofile
, j
, p
))
3629 fun cwin p
= Compress
.compress(ws
, p
)
3630 val cp
= time
"compressing program" (fn () => map cwin p
)
3631 val xx
= time
"writing opt program" (fn () => writeprog(c_ofile
, j
, cp
))
3632 val answer
= "" (* SimStuff
.cmprog(ofile
, c_ofile
) *)
3633 val code_motions
= Ntypes
.new_name
"0"
3635 print (answer ^
"code_motions " ^ code_motions ^
" \n")
3638 fun main(s
:string list
, env
:string list
) =
3639 let val idemp
= ref
0
3641 val ifile
= ref
"/dev/null"
3642 val ofile
= ref
"/dev/null"
3643 val c_ofile
= ref
"/dev/null"
3644 val gotifile
= ref
false
3645 val gotofile
= ref
false
3647 if ord d
>= ord
"0" andalso ord d
<= ord
"9" then ord d
- ord
"0"
3648 else err ("expected digit. got " ^ d
)
3650 fn ("-" :: "i" :: "d" :: "e" :: "m" :: d
:: nil
) =>
3652 |
("-" :: "w" :: "s" :: d
:: nil
) =>
3655 (print ("usage: comp [-ws#] [-idem#]" ^
3656 "input_file temp_file compressed_file\n");
3657 print ("ws is the window size\nidem is the idempotency\n");
3659 | s
=> if !gotofile
then c_ofile
:= implode s
3660 else if !gotifile
then (gotofile
:= true;
3662 else (gotifile
:= true;
3664 val foo
= List.app (parse
o explode
) (tl s
)
3665 val foo
= print ("compressing " ^
!ifile ^
" into (uncompressed)" ^
3667 " and (compressed)" ^
!c_ofile ^
3668 " with idempotency " ^
makestring (!idemp
) ^
3669 " and window size " ^
makestring (!ws
) ^
"\n")
3671 Delay
.idempotency
:= !idemp
;
3672 doitx(!ifile
, !ofile
, !c_ofile
, !ws
)
3675 val s
= OS
.FileSys
.getDir()
3677 fun doit() = main(["foobar", "-ws9",
3678 s^
"/DATA/ndotprod.s",
3685 structure Main
: BMARK
=