Source file ocaml_module.ml
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
open! Base
open Stdio
open Printf
module Rebuild_interfaces
(I : Hardcaml.Interface.S)
(O : Hardcaml.Interface.S) (X : sig
val verilog_design : Verilog_design.t
val loaded_design : Verilog_circuit.t
end) =
struct
let verilog_design = X.verilog_design
let t_i, t_o, fn =
( Verilog_circuit.inputs X.loaded_design
, Verilog_circuit.outputs X.loaded_design
, Verilog_circuit.create_fn X.loaded_design )
;;
module I = struct
module T = struct
include I
let port_names_and_widths =
map port_names ~f:(fun n -> n, (Verilog_circuit.Port.find_exn t_i n).value)
;;
end
include T
include Hardcaml.Interface.Make (T)
end
module O = struct
module T = struct
include O
let port_names_and_widths =
map port_names ~f:(fun n -> n, (Verilog_circuit.Port.find_exn t_o n).value)
;;
end
include O
include Hardcaml.Interface.Make (T)
end
let create i =
let i =
I.(
to_list
@@ map2 port_names i ~f:(fun n i -> Verilog_circuit.Port.{ name = n; value = i }))
in
let o = fn i |> Or_error.ok_exn in
O.(map port_names ~f:(fun n -> (Verilog_circuit.Port.find_exn o n).value))
;;
let inst ?(name = Verilog_design.top_name verilog_design) ?instance i =
let module Inst = Hardcaml.Instantiation.With_interface (I) (O) in
Inst.create ?instance ~name i
;;
let hierarchical ?(name = Verilog_design.top_name verilog_design) ?instance scope =
let module Hier = Hardcaml.Hierarchy.In_scope (I) (O) in
Hier.hierarchical ~scope ?instance ~name (fun _scope -> create)
;;
end
let template
~verilog_design
~module_type_params
~module_params
~input_fields
~output_fields
~instantiated_params
=
[%string
{ocaml_module|open Base
let verilog_design =
Hardcaml_of_verilog.Verilog_design.t_of_sexp
(Parsexp.Single.parse_string_exn {|
%{verilog_design}
|})
let name =
Hardcaml_of_verilog.Verilog_design.Module.module_name
(Hardcaml_of_verilog.Verilog_design.top verilog_design)
module type P = sig
%{module_type_params}
end
module P = struct
%{module_params}
end
module I = struct
type 'a t = {
%{input_fields}
}[@@deriving sexp_of, hardcaml]
end
module O = struct
type 'a t = {
%{output_fields}
}[@@deriving sexp_of, hardcaml]
end
module From_verilog(P : P)(X : sig
val verbose : bool
val map_verilog_design
: Hardcaml_of_verilog.Verilog_design.t
-> Hardcaml_of_verilog.Verilog_design.t
end) = struct
let params = [
%{instantiated_params}
]
include Hardcaml_of_verilog.Ocaml_module.Rebuild_interfaces(I)(O)(struct
let verilog_design =
Hardcaml_of_verilog.Verilog_design.override_parameters
(X.map_verilog_design verilog_design) params
let loaded_design =
let create () =
let%bind.Or_error netlist =
Hardcaml_of_verilog.Netlist.create ~verbose:X.verbose verilog_design
in
Hardcaml_of_verilog.Verilog_circuit.create
netlist
~top_name:
(Hardcaml_of_verilog.Verilog_design.Module.module_name
(Hardcaml_of_verilog.Verilog_design.top verilog_design))
in
create () |> Or_error.ok_exn
end)
end
module From_json(X : sig val json : string end) = struct
include Hardcaml_of_verilog.Ocaml_module.Rebuild_interfaces(I)(O)(struct
let verilog_design = verilog_design
let loaded_design =
let create () =
let%bind.Or_error yosys_netlist = Hardcaml_of_verilog.Expert.Yosys_netlist.of_string X.json in
let%bind.Or_error netlist = Hardcaml_of_verilog.Netlist.of_yosys_netlist yosys_netlist in
Hardcaml_of_verilog.Verilog_circuit.create
netlist
~top_name:
(Hardcaml_of_verilog.Verilog_design.Module.module_name
(Hardcaml_of_verilog.Verilog_design.top verilog_design))
in
create () |> Or_error.ok_exn
end)
end
|ocaml_module}]
;;
let to_ocaml verilog_design loaded_design =
let open Verilog_design in
let mapping = [ "match", "match_"; "type", "type_" ] in
let oname n =
let n = String.lowercase n in
match List.Assoc.find ~equal:String.equal mapping n with
| Some n -> n
| None -> n
in
let field (p : _ Verilog_circuit.Port.t) =
sprintf " %s : 'a [@rtlname \"%s\"];" (oname p.name) p.name
in
let param_type p =
let name = Parameter.name p in
match Parameter.value p with
| Int _ -> sprintf " val %s : int" (oname name)
| String _ -> sprintf " val %s : string" (oname name)
| v ->
raise_s [%message "Unsupported parameter type" (v : Hardcaml.Parameter.Value.t)]
in
let param_value p =
let name = Parameter.name p in
match Parameter.value p with
| Int x -> sprintf " let %s = %i" (oname name) x
| String x -> sprintf " let %s = \"%s\"" (oname name) x
| v ->
raise_s [%message "Unsupported parameter type" (v : Hardcaml.Parameter.Value.t)]
in
let param_spec p =
let name = Parameter.name p in
let value = Parameter.value p in
let value =
match value with
| Int _ -> "Int"
| String _ -> "String"
| v ->
raise_s [%message "Unsupported parameter type" (v : Hardcaml.Parameter.Value.t)]
in
String.concat
[ " Hardcaml.Parameter.create"
; " ~name:\""
; name
; "\""
; " ~value:("
; value
; " P."
; oname name
; ");"
]
in
let lines l f = String.concat ~sep:"\n" (List.map ~f l) in
let inputs = Verilog_circuit.inputs loaded_design in
let outputs = Verilog_circuit.outputs loaded_design in
let parameters = Verilog_design.(top verilog_design |> Module.parameters) in
template
~verilog_design:(Sexp.to_string_hum (Verilog_design.sexp_of_t verilog_design))
~module_type_params:(lines parameters param_type)
~module_params:(lines parameters param_value)
~input_fields:(lines inputs field)
~output_fields:(lines outputs field)
~instantiated_params:(lines parameters param_spec)
;;
let save_ocaml verilog_design loaded_design ~file =
Out_channel.write_all file ~data:(to_ocaml verilog_design loaded_design)
;;