Skip to content

Commit 433cbb4

Browse files
committed
WIP: Debugging tobytes
1 parent 9f22ece commit 433cbb4

12 files changed

Lines changed: 566 additions & 32 deletions

File tree

libs/lospecs/aig.ml

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,3 +344,143 @@ let deps (r : reg) =
344344
in (r, vs)
345345
)
346346
|> List.sort (fun (r1, _) (r2, _) -> compare r1 r2)
347+
348+
(* -------------------------------------------------------------------- *)
349+
(* SERIALIZATION *)
350+
(* Return map of indice renaming + list of and gates (increasing order) + (max variable index, and gate count, input gate count) *)
351+
let aiger_preprocess ~(input_count: int) (r: reg) : (node -> int) * (node list) * (int * int * int) =
352+
let cache : (int, int) Hashtbl.t = Hashtbl.create 0 in
353+
let count_and = ref 0 in
354+
let and_gates = ref [] in
355+
356+
let rec doit (n: node) : unit =
357+
match Hashtbl.find_option cache (abs n.id) with
358+
| Some v -> ()
359+
| None ->
360+
let value = doit_force n in
361+
Hashtbl.add cache (abs n.id) value
362+
363+
and doit_force (n: node) =
364+
match n.gate with
365+
| False -> 0
366+
| Input (v, i) -> 64*v + i
367+
| And (n1, n2) ->
368+
doit n1; doit n2;
369+
incr count_and;
370+
and_gates := n::(!and_gates);
371+
!count_and
372+
in
373+
374+
List.iter doit r;
375+
let and_cnt = !count_and in
376+
let inp_cnt = input_count in
377+
let id_map =
378+
Hashtbl.to_seq cache |> Map.of_seq
379+
in
380+
let id_map = (function
381+
| { gate = False; id } -> (if 0 < id then 0 else 1)
382+
| { gate = And _; id } -> ((Map.find (abs id) id_map) + inp_cnt) lsl 1 + (if 0 < id then 0 else 1)
383+
| { gate = Input _; id } -> (Map.find (abs id) id_map) lsl 1 + (if 0 < id then 0 else 1)
384+
) in
385+
id_map,
386+
List.sort (fun n1 n2 -> compare (id_map n1) (id_map n2)) !and_gates,
387+
(and_cnt + inp_cnt, and_cnt, inp_cnt)
388+
389+
let aiger_serialize_int (id: int) : string =
390+
assert (id > 0);
391+
let mask = 0x7f in
392+
let rec doit (id: int) : int list =
393+
if id < 0x80 then
394+
[id]
395+
else
396+
((id land mask) lor (0x80))::(doit (id lsr 7))
397+
in
398+
399+
List.fold_left (fun acc id -> (Format.sprintf "%c" (char_of_int id)) ^ acc) "" (List.rev (doit id))
400+
401+
let pp_aiger_int fmt (id: int) : unit =
402+
Format.fprintf fmt "%s" (aiger_serialize_int id)
403+
404+
let pp_aiger_and fmt ((gid, id1, id2): int * int * int) : unit =
405+
if not (gid > id1 && id1 > id2) then Format.eprintf "gid : %d | id1: %d | id2: %d@." gid id1 id2;
406+
assert (gid > id1 && id1 > id2);
407+
let delta0 = gid - id1 in
408+
let delta1 = id1 - id2 in
409+
assert(delta0 > 0 && delta1 > 0);
410+
assert(id1 = gid - delta0);
411+
assert(gid - delta0 - delta1 = id2);
412+
Format.fprintf fmt "%a%a" pp_aiger_int (gid - id1) pp_aiger_int (id1 - id2)
413+
414+
(*
415+
mvi -> Max Variable Index
416+
agc -> And Gate Count
417+
igc -> Input Gate Count
418+
lgc -> Latch Gate Count
419+
ogc -> Output Gate Count
420+
*)
421+
let write_aiger_bin
422+
~(input_count: int)
423+
?(inp_name_map : int -> string = fun (i: int) -> "inp" ^ (string_of_int i))
424+
oc
425+
(r: reg) =
426+
let aiger_id_of_node, and_gates, (mvi, agc, igc) = aiger_preprocess ~input_count r in
427+
428+
let ogc = List.length r in
429+
let lgc = 0 in
430+
Printf.fprintf oc "aig %d %d %d %d %d\n" mvi igc lgc ogc agc;
431+
List.iter (fun n -> Printf.fprintf oc "%d\n" (aiger_id_of_node n)) r;
432+
List.iter (function
433+
| { gate = And (n1, n2); } as n ->
434+
let id = aiger_id_of_node n in
435+
let id1 = aiger_id_of_node n1 in
436+
let id2 = aiger_id_of_node n2 in
437+
let id = id - (id land 1) in
438+
let id1, id2 = if id1 > id2 then id1, id2 else id2, id1 in
439+
Printf.fprintf oc "%s" (Format.asprintf "%a" pp_aiger_and (id, id1, id2))
440+
| _ -> assert false) and_gates;
441+
for i = 0 to igc-1 do
442+
Printf.fprintf oc "i%d %s@\n" i (inp_name_map i)
443+
done
444+
445+
let write_aiger_bin_temp
446+
~(input_count: int)
447+
?(inp_name_map: (int -> string) option)
448+
?(name: string = "circuit")
449+
(r: reg) =
450+
let tf_name, tf_oc = Filename.open_temp_file ~mode:[Open_binary] name ".aig" in
451+
let tf_oc = BatIO.output_channel ~cleanup:true tf_oc in
452+
write_aiger_bin ~input_count ?inp_name_map tf_oc r;
453+
tf_name
454+
455+
(* Assumes inputs are already matched *)
456+
let abc_check_equiv
457+
?(r1_name = "r1")
458+
?(r2_name = "r2")
459+
~(input_count: int)
460+
?(inp_name_map: (int -> string) option)
461+
(r1: reg) (r2: reg) : bool =
462+
463+
let tf1_name, tf1_oc = Filename.open_temp_file ~mode:[Open_binary] r1_name ".aig" in
464+
let tf2_name, tf2_oc = Filename.open_temp_file ~mode:[Open_binary] r2_name ".aig" in
465+
Format.eprintf "Created temp files (%s) (%s)!@." tf1_name tf2_name;
466+
let tf1_oc = BatIO.output_channel ~cleanup:true tf1_oc in
467+
let tf2_oc = BatIO.output_channel ~cleanup:true tf2_oc in
468+
write_aiger_bin ~input_count ?inp_name_map tf1_oc r1;
469+
write_aiger_bin ~input_count ?inp_name_map tf2_oc r2;
470+
Format.eprintf "Wrote aig files!@.";
471+
BatIO.close_out tf1_oc; BatIO.close_out tf2_oc;
472+
let abc_command = Format.sprintf "cec %s %s" tf1_name tf2_name in
473+
Format.eprintf "Abc command: %s@." abc_command;
474+
let abc_output_c, abc_in = Unix.open_process "abc" in
475+
(* let abc_in = BatIO.output_channel ~cleanup:true abc_in in *)
476+
BatIO.write_string abc_in (abc_command ^ "\n");
477+
BatIO.close_out abc_in;
478+
(* let abc_output_c = BatIO.input_channel ~autoclose:true ~cleanup:true abc_output_c in *)
479+
(* FIXME: Get the actual output in all cases from abc *)
480+
let re = Str.regexp {|.*Networks are equivalent.*|} in
481+
Format.eprintf "Before read@.";
482+
let abc_output = BatIO.read_all abc_output_c in
483+
Format.eprintf "====== BEGIN ABC OUTPUT =====@.%s@.======= END ABC OUTPUT =====@." abc_output;
484+
let abc_output = String.replace_chars (function | '\n' -> "|" | c -> String.of_char c) abc_output in
485+
if Str.string_match re abc_output 0 then true else false
486+

libs/lospecs/circuit.ml

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
(* ==================================================================== *)
32
open Aig
43

@@ -40,6 +39,15 @@ let int32_of_bools (bs : bool list) : int32 =
4039
v)
4140
0l bs
4241

42+
let int64_of_bools (bs : bool list) : int64 =
43+
List.fold_lefti
44+
(fun v i b ->
45+
if b then
46+
Int64.(logor (shift_left 1L i) v)
47+
else
48+
v)
49+
0L bs
50+
4351
let ubigint_of_bools (bs: bool list) : Z.t =
4452
List.fold_right
4553
(fun b acc ->
@@ -77,7 +85,15 @@ let bytes_of_bools (bs : bool list) : bytes =
7785
Bytes.of_seq bs
7886

7987
(* -------------------------------------------------------------------- *)
80-
let pp_reg ~(size : int) (fmt : Format.formatter) (r : bool list) =
88+
let bools_of_reg (r: reg) : bool list =
89+
List.map (function
90+
| { gate = False; id } when id > 0 -> false
91+
| { gate = False; id } -> true
92+
| _ -> raise (Invalid_argument "Can't convert non constant reg to bool list")
93+
) r
94+
95+
(* -------------------------------------------------------------------- *)
96+
let pp_reg_ ~(size : int) (fmt : Format.formatter) (r : bool list) =
8197
assert (List.length r mod (size * 4) = 0);
8298

8399
let r = explode ~size:(size * 4) r in
@@ -89,6 +105,10 @@ let pp_reg ~(size : int) (fmt : Format.formatter) (r : bool list) =
89105
(fun fmt -> Format.fprintf fmt "%0.8lx"))
90106
r
91107

108+
let pp_reg ~(size: int) (fmt: Format.formatter) (r: reg) =
109+
assert (size mod 4 = 0);
110+
pp_reg_ ~size:(size / 4) fmt (bools_of_reg r)
111+
92112
(* ==================================================================== *)
93113
let bit ~(position : int) (v : int) : bool =
94114
(v lsr position) land 0b1 <> 0
@@ -125,8 +145,6 @@ let of_bigint ~(size : int) (v : Z.t) : reg =
125145
assert (Z.numbits v <= size);
126146
List.init size (fun i -> constant (Z.testbit v i))
127147

128-
129-
130148
(* -------------------------------------------------------------------- *)
131149
let of_string ~(size : int) (s : string) : reg =
132150
of_bigint ~size (Z.of_string s)
@@ -215,6 +233,10 @@ let sextend ~(size : int) (r : reg) : reg =
215233
else
216234
r
217235

236+
(* -------------------------------------------------------------------- *)
237+
let trunc ~(size: int) (r: reg) : reg =
238+
List.take size r
239+
218240
(* -------------------------------------------------------------------- *)
219241
let mux2 (n1 : node) (n2 : node) (c : node) =
220242
or_ (and_ (neg c) n1) (and_ c n2)
@@ -721,3 +743,14 @@ let of_bigint_all ~(size : int) (v : Z.t) : reg =
721743
let v = Z.rem v mod_ in
722744
let v = if Z.sign v < 0 then Z.add mod_ v else v in
723745
of_bigint ~size v
746+
747+
(* Assumes input is list of 16 bit words *)
748+
let compute ?(input_block_size = 16) ?(output_block_size = 16) (r: reg) (inp: int array) : int array =
749+
assert (input_block_size <= 32);
750+
let m = (1 lsl input_block_size) - 1 in
751+
let inp = Array.map (fun i -> i land m) inp in
752+
let inp = Array.to_list inp |> List.map (of_int ~size:input_block_size) |> List.flatten |> Array.of_list in
753+
maps (function
754+
| (0, i) -> Some (inp.(i))
755+
| _ -> None) r |> bools_of_reg |> explode ~size:output_block_size |> List.map (uint_of_bools) |> Array.of_list
756+

libs/lospecs/circuit.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,5 @@ val smod : reg -> reg -> reg
163163
val popcount : size:int -> reg -> reg
164164

165165
val of_bigint_all : size:int -> Z.t -> reg
166+
167+
val compute : ?input_block_size:int -> ?output_block_size:int -> reg -> int array -> int array

0 commit comments

Comments
 (0)