Strumenti Utente

Strumenti Sito


informatica:ae:file_drisc.ml

drisc.ml

"drisc.ml"
(** DRISC Asm interpreter
		This file contain function for executing DRISC code.
 
    Year 2011
 
    Updated on 27-06-11 by Nicola Corti
*)
 
open Printf;;
 
(** DRISC default register number *)
(* Change this value if you want to change the default number of register *)
let regs = 32;;
 
 
(** DRISC default memory size *)
(* Change this value if you want to change the default memory size *)
let memsize = 128;;
 
 
(** shortcut to maps ... *)
type assoc = Ass of string * int;;
 
 
(** checks whether a key is in a map
		@param k A key to be found into a map
		@return true if k is found, false if not *)
let rec hasKey k = function 
   [] -> false
|  Ass(kk,vv)::rm -> if(kk = k) then true else (hasKey k rm);;
 
 
(** looks up a key in a map
		@param k The key to be found
		@param labs The map containing the key
		@return If the key is found, return his value, else it fail with "key not found"
*)
let rec valueOfKey k labs = 
  match labs with 
    [] -> failwith "key not found"
  | Ass(kk,vv)::rl -> if(kk=k) then vv else (valueOfKey k rl);;
 
 
(** execution environment (the state of the processor + 
    the labels compiled. 
    an environment is:
    pc, reg, mem, labels
 *)
type penv = 
  Penv of int ref * int array * int array * assoc list;;
 
 
(** pretty print the environment *)
let dump penv = 
  match penv with 
     Penv(pc,r,m,a) ->
	printf "PC=%d \n" !pc; 
        printf "%d registers. #MV = %d \n" 
		(Array.length r) (Array.length m);
        pp_reg_set r;
        pp_mem m
;;
 
 
(** Calculate the result of a non-jump instruction without increasing IC
		@param asm the ASM instruction
		@param env the enviroment where execute asm *)
let calculate asm env =
	match env with
		Penv(pc, r, m, labs) ->
	(match asm with
    ADD(Reg(a),Reg(b),Reg(c)) -> r.(c) <- r.(a) + r.(b);
|   SUB(Reg(a),Reg(b),Reg(c)) -> r.(c) <- r.(a) - r.(b);
|   MUL(Reg(a),Reg(b),Reg(c)) -> r.(c) <- r.(a) * r.(b);
|   DIV(Reg(a),Reg(b),Reg(c)) -> r.(c) <- r.(a) / r.(b);
|   ADDI(Reg(a),Const(b),Reg(c)) -> r.(c) <- r.(a) + b;
|   SUBI(Reg(a),Const(b),Reg(c)) -> r.(c) <- r.(a) - b;
|   INC(Reg(a)) -> r.(a) <- r.(a)+1;
|   DEC(Reg(a)) -> r.(a) <- r.(a)-1;
|   LD(Reg(a),Reg(b),Reg(c)) -> 
	let ind = r.(a) + r.(b) in 
	  r.(c) <- m.(ind);
|   LDI(Reg(a),Const(b),Reg(c)) -> 
	let ind = r.(a) + b in 
	  r.(c) <- m.(ind);
|   ST(Reg(a),Reg(b),Reg(c)) -> 
  let ind = r.(a) + r.(b) in
    m.(ind) <- r.(c);
|   STI(Reg(a),Const(b),Reg(c)) -> 
  let ind = r.(a) + b in
    m.(ind) <- r.(c);
|		_ -> printf "UNIMPLEMENTED:"; pp_asm asm
    )
;;
 
 
(** Function for handling the Delayed Branch execution,
		it execute the next instruction and change the value of IC.
		{b If in the Delay Slot there is a Jump, the execution fail}
 
		@param istr The ASM instruction in delay slot
		@param env The enviroment
		@param label The Label to jump to *)
let branch_handler istr env label =
	if (not(is_jump istr)) then
  	(printf "===========> DELAYED_BRANCH: executing";
  	pp_asm istr;
  	calculate istr env;
  	dump env;
  	match env with
	    Penv(pc, r, m, labs) ->
	  (match label with
    		LabLab(lbl) ->  let l = valueOfKey lbl labs in pc := l
    	| LabOff(off) ->  pc := !pc + off
    	| _ -> failwith "Label error"))
  else
  	failwith "Unable to execute a Jump after a Delayed Branch"
;;
 
 
(** execute one instruction within an environment 
    @param pgm the instruction to be executed 
    @param env the initial environment. it is modified via side effects *)
let step pgm env = 
  let apgm = Array.of_list (prog_to_asm pgm) in
  match env with 
    Penv(pc, r, m, labs) ->
  (let i = apgm.(!pc) in 
   if (not(is_jump i)) then
   		(calculate i env; pc:= !pc+1)
   else
   		(match i with 
|   CALL(Reg(f), Reg(ret)) -> 
	r.(ret) <- !pc + 1;
 	pc := r.(f)
|   GOTOR(Reg(l)) ->  pc := r.(l)
|   GOTOL(ll) -> 
		(match ll with 
			LabLab(lbl) ->  let l = valueOfKey lbl labs in pc := l
    | LabOff(off) ->  pc := !pc + off;
    | DelayedBranch(labl) -> 
    	let next = apgm.(!pc + 1) in branch_handler next env labl
    )
|   IFLEQ(Reg(r1),Reg(r2),l) ->
       if(r.(r1) <= r.(r2)) 
       then 
       	(match l with
       	LabOff(l) -> pc := !pc + l 
    |		LabLab(l) -> let lbl = valueOfKey l labs in pc := lbl
    |		DelayedBranch(labl) ->
    		let next = apgm.(!pc + 1) in branch_handler next env labl)
       else pc := !pc + 1
|   IFLE(Reg(r1),Reg(r2),l) ->
       if(r.(r1) < r.(r2)) 
       then 
       	(match l with
       	LabOff(l) -> pc := !pc + l 
    |		LabLab(l) -> let lbl = valueOfKey l labs in pc := lbl
    |		DelayedBranch(labl) ->
				let next = apgm.(!pc + 1) in branch_handler next env labl)
       else pc := !pc + 1
|   IFGEQ(Reg(r1),Reg(r2),l) ->
       if(r.(r1) >= r.(r2)) 
       then 
       	(match l with
       	LabOff(l) -> pc := !pc + l 
    |		LabLab(l) -> let lbl = valueOfKey l labs in pc := lbl
    |		DelayedBranch(labl) ->
				let next = apgm.(!pc + 1) in branch_handler next env labl)
       else pc := !pc + 1
|   IFGE(Reg(r1),Reg(r2),l) ->
       if(r.(r1) > r.(r2)) 
       then 
       	(match l with
       	LabOff(l) -> pc := !pc + l 
    |		LabLab(l) -> let lbl = valueOfKey l labs in pc := lbl
    |		DelayedBranch(labl) ->
				let next = apgm.(!pc + 1) in branch_handler next env labl)
       else pc := !pc + 1
|   IFEQ(Reg(r1),Reg(r2),l) ->
       if(r.(r1) = r.(r2)) 
       then 
       	(match l with
       	LabOff(l) -> pc := !pc + l 
    |		LabLab(l) -> let lbl = valueOfKey l labs in pc := lbl
    |		DelayedBranch(labl) ->
				let next = apgm.(!pc + 1) in branch_handler next env labl)
       else pc := !pc + 1
|   IFNEQ(Reg(r1),Reg(r2),l) ->
       if(not(r.(r1) = r.(r2))) 
       then 
       	(match l with
       	LabOff(l) -> pc := !pc + l 
    |		LabLab(l) -> let lbl = valueOfKey l labs in pc := lbl
    |		DelayedBranch(labl) ->
				let next = apgm.(!pc + 1) in branch_handler next env labl)
       else pc := !pc + 1
|   END -> failwith "Program terminated"
 
		(* Questo caso non e' mai raggiunto *)
| _ -> printf "UNIMPLEMENTED:"; pc := !pc + 1; pp_asm i))
;;
 
(** compile labels. Takes a program with labels and returns 
    a map with the label addresses
    @param pgm the program
    @param addr the initial address of the program  *)
let rec labels pgm addr = 
  match pgm with 
    [] -> []
  | i::ri -> 
      (match i with 
         Instr(i) -> (labels ri (addr+1))
       | LabInstr(LabLab(l),i) -> Ass(l,addr)::(labels ri (addr+1))
       | LabInstr(LabOff(l),i) -> failwith "Label Error, It's impossible to set an offset as an instruction label!"
       | LabInstr(DelayedBranch(l), i) -> failwith "Label Error, It's impossibile to set Delayed Branch as Istruction Label!"
      )
;;
 
(** Create a new set of register
		@param n The size of register set
		@return A new register set of size n *)
let create_regs n = 
  Array.create n 0;; 
 
(** Execute some step of an Instruction List
		@param r The reg set size
		@param m The memory size
		@param ipc The initial value of IC
		@param prg The instruciont list (the program)
		@param steps Number of steps to be executed *)
let stepper r m ipc prg steps = 
  let pc = ref ipc in 
  let reg = create_regs r in 
  let mem = create_regs m in 
  let penv = Penv(pc,reg,mem,(labels prg 0)) in 
  let aprg = Array.of_list prg in
 
  for i=0 to steps do
    printf "===========> STEP %d: executing " i; 
	(pp_instr !pc aprg.(!pc)); printf "\n";
    step prg penv; 
    dump penv;
  done
;;
 
(** Execute an Instruction List till the END instruction
		@param r The reg set size
		@param m The memory size
		@param ipc The initial value of IC
		@param prg The instruciont list (the program) *)
let execute r m ipc prg = 
	let pc = ref ipc in 
	let reg = create_regs r in 
	let mem = create_regs m in 
	let penv = Penv(pc, reg, mem,(labels prg 0)) in
	let aprg = Array.of_list prg in
	let i = (ref 0) in
 
	while (not(delab(aprg.(!pc)) = END)) do
		(
		printf "===========> STEP %d: executing " !i; (pp_instr !pc aprg.(!pc)); printf "\n";
		step prg penv;
		dump penv;
		i := !i + 1;
		)
	done
;;
 
 
(** Execute some step of an Instruction List
		with DRISC default value for reg set and memory
		@param prg The instruciont list (the program)
		@param steps Number of steps to be executed *)
let drisc_stepper prg step = 
	printf "Executing as a D-RISC Cpu \n";
	printf "Number of register: %d\n" regs;
	printf "Memory size: %d\n" memsize;
	printf "Number of steps: %d\n" step;
	stepper regs memsize 0 prg step
;;
 
 
(** Execute an Instruction List till the END instruction
		with DRISC default value for reg set and memory
		@param prg The instruciont list (the program) *)
let drisc_execute prg =
	printf "Executing as a D-RISC Cpu \n";
	printf "Number of register: %d\n" regs;
	printf "Memory size: %d\n" memsize;
	execute regs memsize 0 prg
;;
 
 
(** Calculate the max value between three value
		@param a The first value
		@param b The second value
		@param c The third value
		@return The max of previous value *)
let maxthree a b c =
	if (a > b) then
		(if (a > c) then a else c)
	else 
		(if (b > c) then b else c)
;;
 
 
(** Calculate the max register of a ASM instruction
		@param istr The ASM istruction
		@return The max register of an instruction *)
let maxregistr istr =
	match delab istr with
	 ADD(Reg(a),Reg(b),Reg(c)) -> maxthree a b c
|  SUB(Reg(a),Reg(b),Reg(c)) -> maxthree a b c
|  MUL(Reg(a),Reg(b),Reg(c)) -> maxthree a b c
|  DIV(Reg(a),Reg(b),Reg(c)) -> maxthree a b c
|  ADDI(Reg(a),Const(b),Reg(c)) -> if a < c then c else a
|  SUBI(Reg(a),Const(b),Reg(c)) -> if a < c then c else a
|  INC(Reg(a)) -> a
|  DEC(Reg(a)) -> a
|  LD(Reg(a),Reg(b),Reg(c)) -> maxthree a b c
|  ST(Reg(a),Reg(b),Reg(c)) -> maxthree a b c
|  LDI(Reg(a),Const(b),Reg(c)) -> if a < c then c else a
|  STI(Reg(a),Const(b),Reg(c)) -> if a < c then c else a
|  CALL(Reg(a),Reg(b)) -> if a < b then b else a
|  GOTOR(Reg(a)) -> a
|  IFLEQ(Reg(a), Reg(b), l) -> if a < b then b else a
|  IFLE(Reg(a), Reg(b), l) -> if a < b then b else a
|  IFGEQ(Reg(a), Reg(b), l) -> if a < b then b else a
|  IFGE(Reg(a), Reg(b), l) -> if a < b then b else a
|  IFEQ(Reg(a), Reg(b), l) -> if a < b then b else a
|  IFNEQ(Reg(a), Reg(b), l) -> if a < b then b else a
|  _ -> 0
;;
 
 
(** Calculate the max register of an instruction list
		@param prg The instruction list
		@param a The initial value (it must be set to 0, to let recursion work well)
		@return The max register of an instruction list *)
let rec maxreg prg a =
	match prg with
	[] -> a
	| x::xs -> let found = maxregistr x in 
		if found < a then maxreg xs a else maxreg xs found
;; 
 
 
(** Execute some step of an Instruction List
		with a Register set big enough for executing the instruction list
		@param m The memory size
		@param ipc The initial value of IC
		@param prg The instruciont list (the program)
		@param steps Number of steps to be executed *)
let autostepper m ipc prg steps = stepper (maxreg prg 0) m ipc prg steps
;;
 
 
(** Execute an Instruction List till the END instruction
		with a Register set big enough for executing the instruction list
		@param m The memory size
		@param ipc The initial value of IC
		@param prg The instruciont list (the program) *)
let autoexecute m ipc prg = execute (maxreg prg 0) m ipc prg
;;
informatica/ae/file_drisc.ml.txt · Ultima modifica: 27/06/2011 alle 15:23 (8 anni fa) da Marco Danelutto