(* 
   Figures M. Casu and L. Macchiarulo, 
   "A New Approach to Latency Insensitive Design," DAC 04 
*)

let node relay x = x

(* ----------------------------*)
(* Figure 2                    *)
(* ----------------------------*)
let node ip_A ((x::'a),(y::'a)) = x
let node ip_B x = (x, x)

let node figure_2a (init_A, init_B0, init_B1) = (out_A, out_B1) where
  rec out_A = ip_A (buffer in_A0, buffer in_A1)
  and out_B0, out_B1 = ip_B (buffer in_B)

  and in_R1 = merge 1(0) init_A (delay out_A)
  and out_R1 = relay in_R1
  and in_B = delay out_R1

  and in_R2 = merge 1(0) init_B0 (delay out_B0)
  and out_R2 = relay in_R2
  and in_A0 = delay out_R2

  and in_R3 = merge 1(0) init_B1 (delay out_B1)
  and out_R3 = relay in_R3
  and in_R4 = delay out_R3
  and out_R4 = relay in_R4
  and in_A1 = delay out_R4


(* ----------------------------*)
(* Figure 5                    *)
(* ----------------------------*)
let node ip_A x = (x,x)
let node ip_B x = x
let node ip_C ((x::'a),(y::'a)) = x

let node figure_5 (init_A0, init_A1, init_B, init_C) =
  (out_A0, out_B, out_C) where
  rec out_A0, out_A1 = ip_A (buffer in_A)
  and out_B = ip_B (buffer in_B)
  and out_C = ip_C (buffer in_C0, buffer in_C1)

  and in_B = merge 1(0) init_A0 (delay out_A0)
  and in_C0 = merge 1(0) init_A1 (delay out_A1)

  and in_C1 = merge 1(0) init_B (delay out_B)

  and in_R = merge 1(0) init_C (delay out_C)
  and out_R = relay in_R
  and in_A = delay out_R