summaryrefslogtreecommitdiff
path: root/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'cpu')
-rw-r--r--cpu/netlist_gen.ml102
1 files changed, 58 insertions, 44 deletions
diff --git a/cpu/netlist_gen.ml b/cpu/netlist_gen.ml
index 956de91..bb7e4e4 100644
--- a/cpu/netlist_gen.ml
+++ b/cpu/netlist_gen.ml
@@ -1,5 +1,9 @@
open Netlist_ast
+exception Size_error of string
+let ty_assert f s = if not f then raise (Size_error s)
+let ty_error s = raise (Size_error s)
+
type t = program -> (arg * program)
let id =
@@ -13,16 +17,16 @@ let get_size p arg = match arg with
| Aconst(k) -> Array.length k
let add p id eq size =
- assert (not (Env.mem id p.p_vars)
- || (Env.find id p.p_vars = size));
- assert (not (List.mem_assoc id p.p_eqs));
+ ty_assert (not (Env.mem id p.p_vars)
+ || (Env.find id p.p_vars = size)) "Adding a variable with bad size.";
+ ty_assert (not (List.mem_assoc id p.p_eqs)) "Adding an equation that is already there";
{ p with
p_eqs = (id, eq)::p.p_eqs;
p_vars = Env.add id size p.p_vars }
let get id =
fun p ->
- assert (Env.mem id p.p_vars);
+ ty_assert (Env.mem id p.p_vars) ("Trying to get " ^ id ^ ", which does not exist.");
(Avar id, p)
let loop s =
@@ -73,7 +77,8 @@ let ( ^| ) v1 v2 =
let x1, p = v1 p in
let x2, p = v2 p in
let sz = get_size p x1 in
- assert (sz = get_size p x2);
+ let sz2 = get_size p x2 in
+ ty_assert (sz = sz2) (Format.sprintf "Incompatible sizes for Or: %d/%d" sz sz2);
(Avar i), add p i (Ebinop (Or, x1, x2)) sz
let ( ^^ ) v1 v2 =
@@ -83,7 +88,8 @@ let ( ^^ ) v1 v2 =
let x1, p = v1 p in
let x2, p = v2 p in
let sz = get_size p x1 in
- assert (sz = get_size p x2);
+ let sz2 = get_size p x2 in
+ ty_assert (sz = sz2) (Format.sprintf "Incompatible sizes for Xor: %d/%d" sz sz2);
(Avar i), add p i (Ebinop (Xor, x1, x2)) sz
let ( ^& ) v1 v2 =
@@ -93,7 +99,8 @@ let ( ^& ) v1 v2 =
let x1, p = v1 p in
let x2, p = v2 p in
let sz = get_size p x1 in
- assert (sz = get_size p x2);
+ let sz2 = get_size p x2 in
+ ty_assert (sz = sz2) (Format.sprintf "Incompatible sizes for And: %d/%d" sz sz2);
(Avar i), add p i (Ebinop (And, x1, x2)) sz
let ( ^$ ) v1 v2 =
@@ -103,7 +110,8 @@ let ( ^$ ) v1 v2 =
let x1, p = v1 p in
let x2, p = v2 p in
let sz = get_size p x1 in
- assert (sz = get_size p x2);
+ let sz2 = get_size p x2 in
+ ty_assert (sz = sz2) (Format.sprintf "Incompatible sizes for Nand: %d/%d" sz sz2);
(Avar i), add p i (Ebinop (Nand, x1, x2)) sz
let not v1 =
@@ -120,9 +128,11 @@ let mux v1 v2 v3 =
let x1, p = v1 p in
let x2, p = v2 p in
let x3, p = v3 p in
+ let sz0 = get_size p x1 in
let sz = get_size p x2 in
- assert (get_size p x3 = sz);
- assert (get_size p x1 = 1);
+ let sz2 = get_size p x3 in
+ ty_assert (sz = sz2) (Format.sprintf "Mux'ed values have different sizes: %d/%d" sz sz2);
+ ty_assert (sz0 = 1) (Format.sprintf "Mux control has size %d and not 1" sz0);
(Avar i), add p i (Emux (x1, x2, x3)) sz
let ( ** ) v s =
@@ -131,7 +141,7 @@ let ( ** ) v s =
if List.mem_assoc i p.p_eqs then Avar i, p else
let x, p = v p in
let sz = get_size p x in
- assert (s >= 0 && s < sz);
+ ty_assert (s >= 0 && s < sz) (Format.sprintf "Trying to select %d in [0, %d[" s sz);
(Avar i), add p i (Eselect (s, x)) 1
let ( % ) v (s1, s2) =
@@ -140,7 +150,7 @@ let ( % ) v (s1, s2) =
if List.mem_assoc i p.p_eqs then Avar i, p else
let x, p = v p in
let sz = get_size p x in
- assert (s1 >= 0 && s2 >= s1 && sz > s2);
+ ty_assert (s1 >= 0 && s2 >= s1 && sz > s2) (Format.sprintf "Trying to slice [%d, %d] in [0, %d[" s1 s2 sz);
(Avar i), add p i (Eslice (s1, s2, x)) (s2 - s1 + 1)
let rom i a_s w_s ra =
@@ -148,21 +158,22 @@ let rom i a_s w_s ra =
fun p ->
if List.mem_assoc i p.p_eqs then Avar i, p else
let ra, p = ra p in
- assert ((get_size p ra) = a_s);
+ let rasz = get_size p ra in
+ ty_assert (rasz = a_s) (Format.sprintf "(ROM) RA does not have size %d (addr_size) but %d" a_s rasz);
(Avar i), add p i (Erom (a_s, w_s, ra)) w_s
let ram a_s w_s ra we wa d =
let i = id "" in
fun p ->
if List.mem_assoc i p.p_eqs then Avar i, p else
- let ra, p = ra p in
- let we, p = we p in
- let wa, p = wa p in
- let d, p = d p in
- assert ((get_size p ra) = a_s);
- assert ((get_size p wa) = a_s);
- assert ((get_size p we) = 1);
- assert ((get_size p d) = w_s);
+ let ra, p = ra p in let rasz = get_size p ra in
+ let we, p = we p in let wesz = get_size p we in
+ let wa, p = wa p in let wasz = get_size p wa in
+ let d, p = d p in let dsz = get_size p d in
+ ty_assert (rasz = a_s) (Format.sprintf "(RAM) RA does not have size %d (addr_size) but %d" a_s rasz);
+ ty_assert (wasz = a_s) (Format.sprintf "(RAM) WA does not have size %d (addr_size) but %d" a_s wasz);
+ ty_assert (wesz = 1) (Format.sprintf "(RAM) WE does not have size 1 but %d" wesz);
+ ty_assert (dsz = w_s) (Format.sprintf "(RAM) D does not have size %d (word_size) but %d" w_s dsz);
(Avar i), add p i (Eram (a_s, w_s, ra, we, wa, d)) w_s
@@ -170,8 +181,8 @@ let reg n v =
let i = id "" in
fun p ->
if List.mem_assoc i p.p_eqs then Avar i, p else
- let v, p = v p in
- assert (get_size p v = n);
+ let v, p = v p in let sz = get_size p v in
+ ty_assert (sz = n) (Format.sprintf "Reg %d is given argument of size %d" n sz);
match v with
| Avar j ->
(Avar i), add p i (Ereg j) n
@@ -180,26 +191,29 @@ let reg n v =
let program entries outputs =
- let p =
- { p_eqs = [];
- p_inputs = (List.map fst entries);
- p_outputs = [];
- p_vars = List.fold_left
- (fun k (e, s) -> Env.add e s k) Env.empty entries }
- in
- let p, outputs = List.fold_left
- (fun (p, outputs) (name, size, x) ->
- let x, p = x p in
- assert (get_size p x = size);
- if x = Avar(name) then
- p, name::outputs
- else if name <> "" then
- add p name (Earg x) size, name::outputs
- else
- p, outputs)
- (p, []) outputs
- in
- { p with
- p_outputs = List.rev outputs }
+ try
+ let p =
+ { p_eqs = [];
+ p_inputs = (List.map fst entries);
+ p_outputs = [];
+ p_vars = List.fold_left
+ (fun k (e, s) -> Env.add e s k) Env.empty entries }
+ in
+ let p, outputs = List.fold_left
+ (fun (p, outputs) (name, size, x) ->
+ let x, p = x p in
+ assert (get_size p x = size);
+ if x = Avar(name) then
+ p, name::outputs
+ else if name <> "" then
+ add p name (Earg x) size, name::outputs
+ else
+ p, outputs)
+ (p, []) outputs
+ in
+ { p with
+ p_outputs = List.rev outputs }
+ with
+ | Size_error m -> Format.eprintf "\nSize error:\t%s\n\n%!" m; assert false