(* 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