forked from mit-plv/koika
-
Notifications
You must be signed in to change notification settings - Fork 0
/
gcd_machine.v
104 lines (89 loc) · 2.75 KB
/
gcd_machine.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
(*! Computing GCDs !*)
Require Import Koika.Frontend.
Require Import Koika.Std.
Module GCDMachine.
Definition ext_fn_t := empty_ext_fn_t.
Inductive reg_t :=
| input_data
| input_valid
| gcd_busy
| gcd_a
| gcd_b
| output_data.
Definition pair_t :=
struct_t {| struct_name := "pair";
struct_fields := [("a", bits_t 16); ("b", bits_t 16)] |}.
Definition R r :=
match r with
| input_data => pair_t
| input_valid => bits_t 1
| gcd_busy => bits_t 1
| gcd_a => bits_t 16
| gcd_b => bits_t 16
| output_data => bits_t 16
end.
Definition init_r idx : R idx :=
match idx with
| input_data => (Bits.zero, (Bits.zero, tt))
| input_valid => Bits.zero
| gcd_busy => Bits.zero
| gcd_a => Bits.zero
| gcd_b => Bits.zero
| output_data => Bits.zero
end.
Definition gcd_start : uaction reg_t ext_fn_t :=
{{
if read0(input_valid) == Ob~1 && !read0(gcd_busy) then
let data := read0(input_data) in
write0(gcd_a, get(data, a));
write0(gcd_b, get(data, b));
write0(gcd_busy, Ob~1);
write0(input_valid, Ob~0)
else
fail
}}.
Definition gcd_compute : uaction reg_t ext_fn_t :=
{{
let a := read0(gcd_a) in
let b := read0(gcd_b) in
if a != |16`d0| then
if a < b then
write0(gcd_b, a);
write0(gcd_a, b)
else
write0(gcd_a, a - b)
else
fail
}}.
Definition gcd_get_result : uaction reg_t ext_fn_t :=
{{
if (read1(gcd_a) == |16`d0|) && read0(gcd_busy) then
write0(gcd_busy, Ob~0);
write0(output_data, read1(gcd_b))
else
fail
}}.
Inductive rule_name_t :=
start | step_compute | get_result.
Definition rules :=
tc_rules R empty_Sigma
(fun rl => match rl with
| start => gcd_start
| step_compute => gcd_compute
| get_result => gcd_get_result end).
Definition bring : scheduler :=
start |> step_compute |> get_result |> done.
Definition package :=
{| ip_koika := {| koika_reg_types := R;
koika_reg_init := init_r;
koika_ext_fn_types := empty_Sigma;
koika_rules := rules;
koika_rule_external _ := false;
koika_scheduler := bring;
koika_module_name := "gcd_machine" |};
ip_sim := {| sp_ext_fn_specs := empty_ext_fn_props;
sp_prelude := None |};
ip_verilog := {| vp_ext_fn_specs := empty_ext_fn_props; |} |}.
End GCDMachine.
Definition prog := Interop.Backends.register GCDMachine.package.
Extraction "gcd_machine.ml" prog.