summaryrefslogtreecommitdiff
path: root/camlsim/machine.ml
diff options
context:
space:
mode:
Diffstat (limited to 'camlsim/machine.ml')
-rw-r--r--camlsim/machine.ml174
1 files changed, 174 insertions, 0 deletions
diff --git a/camlsim/machine.ml b/camlsim/machine.ml
new file mode 100644
index 0000000..232cb08
--- /dev/null
+++ b/camlsim/machine.ml
@@ -0,0 +1,174 @@
+(*
+ Système Digital, cours de J.Vuillemin, 2013-2013
+ Alex AUVOLAT, ENS INFO 2013
+
+ Circuit Simulator, machine simulator
+
+ ASSUMPTIONS:
+ - Only one ROM chip
+*)
+
+open Netlist_ast
+
+exception Error of string
+exception Is_not_modified
+
+let load_rom filename =
+ () (* TODO *)
+
+
+type ram_prop = int * int (* addr size ; word size *)
+type machine = {
+ p : program;
+ mutable vars : value Env.t;
+ mutable regs : value Env.t;
+ ram_chips : ram_prop array;
+ ram : value array array;
+}
+
+let rec two_to_the = function
+ | 0 -> 1
+ | n -> let k = (two_to_the (n/2)) in
+ if n mod 2 = 1 then 2 * k else k
+
+let create p =
+ let ram_chips = Array.of_list
+ (List.fold_left
+ (fun x (_, v) -> match v with
+ | Eram (a, w, _, _, _, _) ->
+ (a, w)::x
+ | _ -> x)
+ []
+ p.p_eqs) in
+ let vars = Env.fold
+ (fun k v x ->
+ Env.add k
+ (match v with
+ | TBit -> VBit(false)
+ | TBitArray(n) -> VBitArray(Array.make n false))
+ x)
+ p.p_vars
+ Env.empty in
+ {
+ p = p;
+ vars = vars;
+ regs = Env.empty; (* no use putting anything at the moment *)
+ ram_chips = ram_chips;
+ ram = Array.map
+ (fun (a, w) -> Array.make (two_to_the a) (VBitArray (Array.make w false)))
+ ram_chips;
+ }
+
+let read_inputs m f =
+ List.iter
+ (fun n ->
+ m.vars <- Env.add n (f (n, Env.find n m.p.p_vars)) m.vars)
+ m.p.p_inputs
+
+let step m =
+ let get = function
+ | Avar(x) ->
+ begin match Env.find x m.vars with
+ | VBit(x) -> VBit(x)
+ | VBitArray(u) as s ->
+ if Array.length u = 1 then VBit(u.(0)) else s
+ end
+ | Aconst(x) -> x
+ in
+ (* Load register values into dest variables *)
+ Env.iter
+ (fun k v ->
+ m.vars <- Env.add k v m.vars)
+ m.regs;
+ (* Do all the logic *)
+ List.iter
+ (fun (varname, exp) ->
+ let evaluate = function
+ | Earg(k) -> get k
+ | Ereg(_) -> raise Is_not_modified (* do nothing, registers are handled somewhere else *)
+ | Enot(k) ->
+ begin match get k with
+ | VBit(u) -> VBit (not u)
+ | VBitArray(u) -> VBitArray(Array.map (fun x -> not x) u)
+ end
+ | Ebinop(op, k1, k2) ->
+ let f = begin match op with
+ | Or -> (fun x y -> x || y)
+ | Xor -> (fun x y -> (x || y) && (not (x && y)))
+ | And -> (fun x y -> x && y)
+ | Nand -> (fun x y -> not (x && y))
+ end in
+ begin match get k1, get k2 with
+ | VBit(u), VBit(v) -> VBit(f u v)
+ | VBitArray(u), VBitArray(v) when Array.length u = Array.length v ->
+ let r = Array.make (Array.length u) false in
+ for i = 0 to Array.length u - 1 do
+ r.(i) <- (f u.(i) v.(i))
+ done; VBitArray(r)
+ | VBit(u), VBitArray(v) -> VBit(f u v.(0))
+ | VBitArray(u), VBit(v) -> VBit(f u.(0) v)
+ | _ -> raise (Error "Incompatible data types.")
+ end
+ | Emux (control, in0, in1) ->
+ begin match get control, get in0, get in1 with
+ | VBit(u), x, y ->
+ if u then y else x
+ | VBitArray(u), VBitArray(a), VBitArray(b)
+ when Array.length a = Array.length b
+ && Array.length u = Array.length a ->
+ let r = Array.make (Array.length u) false in
+ for i = 0 to Array.length u - 1 do
+ r.(i) <- (if u.(i) then b.(i) else a.(i))
+ done;
+ VBitArray(r)
+ | _ -> raise (Error "Invalid data size in mux")
+ end
+ | Erom(_, w, _) -> VBitArray(Array.make w false) (* TODO *)
+ | Eram(_, _, _,_, _, _) -> raise Is_not_modified (* TODO *)
+ | Econcat(k1, k2) ->
+ let a1 = match get k1 with
+ | VBit(u) -> [|u|]
+ | VBitArray(u) -> u
+ in
+ let a2 = match get k2 with
+ | VBit(u) -> [|u|]
+ | VBitArray(u) -> u
+ in
+ VBitArray(Array.append a1 a2)
+ | Eslice (first, last, k) ->
+ begin match get k with
+ | VBit(u) when first = 0 && last = 0 -> VBit(u)
+ | VBitArray(u) ->
+ let r = Array.make (last - first) false in
+ for i = first to last - 1 do
+ r.(i - first) <- u.(i)
+ done;
+ VBitArray(u)
+ | _ -> raise (Error "Invalid slicing parameters")
+ end
+ | Eselect(id, k) ->
+ begin match get k with
+ | VBit(u) when id = 0 -> VBit(u)
+ | VBitArray(u) -> VBit(u.(id))
+ | _ -> raise (Error "Invalid select parameters")
+ end
+ in
+ try
+ m.vars <- Env.add varname (evaluate exp) m.vars
+ with Is_not_modified -> ())
+ m.p.p_eqs;
+ (* Saves register values *)
+ m.regs <- List.fold_left
+ (fun x (k, v) ->
+ match v with
+ | Ereg(n) -> Env.add k (Env.find n m.vars) x
+ | _ -> x)
+ Env.empty
+ m.p.p_eqs
+
+let print_outputs m f =
+ List.iter
+ (fun n ->
+ f (n, Env.find n m.vars))
+ m.p.p_outputs
+