diff options
Diffstat (limited to 'camlsim/machine.ml')
-rw-r--r-- | camlsim/machine.ml | 174 |
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 + |