informatica:ae:file_asm.ml
Differenze
Queste sono le differenze tra la revisione selezionata e la versione attuale della pagina.
informatica:ae:file_asm.ml [27/06/2011 alle 15:20 (14 anni fa)] – creata Marco Danelutto | informatica:ae:file_asm.ml [27/06/2011 alle 15:22 (14 anni fa)] (versione attuale) – Marco Danelutto | ||
---|---|---|---|
Linea 1: | Linea 1: | ||
===== asm.ml ===== | ===== asm.ml ===== | ||
+ | <code ocaml asm.ml> | ||
+ | (** some support to the analysis of D-RISC code on pipeline processors | ||
+ | This includes the possibility to find dependencies in linear | ||
+ | D-RISC code and to execute D-RISC instructions with a given | ||
+ | configuration of registers and memory (with no cache). | ||
+ | @author Marco Danelutto | ||
+ | Year 2011 | ||
+ | | ||
+ | Updated on 27-06-11 by Nicola Corti | ||
+ | *) | ||
+ | |||
+ | open Printf;; | ||
+ | |||
+ | (** the type modelling registers *) | ||
+ | type reg = Reg of int;; | ||
+ | |||
+ | (** the type modelling labels: either strings or offsets *) | ||
+ | type label = LabOff of int | LabLab of string | DelayedBranch of label;; | ||
+ | |||
+ | (** the type modelling the constants: e.g. #i -> Const(i) *) | ||
+ | type const = Const of int;; | ||
+ | |||
+ | (** the assembler opcodes *) | ||
+ | type asm = | ||
+ | ADD of reg*reg*reg | ||
+ | | SUB of reg*reg*reg | ||
+ | | MUL of reg*reg*reg | ||
+ | | DIV of reg*reg*reg | ||
+ | | ADDI of reg*const*reg | ||
+ | | SUBI of reg*const*reg | ||
+ | | INC of reg | ||
+ | | DEC of reg | ||
+ | | LD of reg*reg*reg | ||
+ | | LDI of reg*const*reg | ||
+ | | ST of reg*reg*reg | ||
+ | | STI of reg*const*reg | ||
+ | | CALL of reg*reg | ||
+ | | GOTOR of reg | ||
+ | | GOTOL of label | ||
+ | | IFLEQ of reg*reg*label | ||
+ | | IFLE of reg*reg*label | ||
+ | | IFGEQ of reg*reg*label | ||
+ | | IFGE of reg*reg*label | ||
+ | | IFEQ of reg*reg*label | ||
+ | | IFNEQ of reg*reg*label | ||
+ | | END | ||
+ | ;; | ||
+ | |||
+ | (** the assembler instruction: | ||
+ | type instruction = | ||
+ | Instr of asm | ||
+ | | LabInstr of label*asm;; | ||
+ | |||
+ | (** returns the domain of an instruction *) | ||
+ | let domain = function | ||
+ | | ||
+ | | SUB(a,b,c) -> [a;b] | ||
+ | | MUL(a,b,c) -> [a;b] | ||
+ | | DIV(a,b,c) -> [a;b] | ||
+ | | ADDI(a,b,c) -> [a] | ||
+ | | SUBI(a,b,c) -> [a] | ||
+ | | INC(a) -> [a] | ||
+ | | DEC(a) -> [a] | ||
+ | | LD(a,b,c) -> [a;b] | ||
+ | | ST(a,b,c) -> [a;b;c] | ||
+ | | LDI(a,b,c) -> [a] | ||
+ | | STI(a,b,c) -> [a;c] | ||
+ | | CALL(a,b) -> [a] | ||
+ | | GOTOR(a) -> [a] | ||
+ | | GOTOL(a) -> [] | ||
+ | | IFLEQ(a, | ||
+ | | IFLE(a,b,c) -> [a;b] | ||
+ | | IFGEQ(a, | ||
+ | | IFGE(a,b,c) -> [a;b] | ||
+ | | IFEQ(a,b,c) -> [a;b] | ||
+ | | IFNEQ(a, | ||
+ | | END -> [] | ||
+ | ;; | ||
+ | | ||
+ | (** returns the range of an instruction *) | ||
+ | let codomain = function | ||
+ | | ||
+ | | SUB(a,b,c) -> [c] | ||
+ | | MUL(a,b,c) -> [c] | ||
+ | | DIV(a,b,c) -> [c] | ||
+ | | ADDI(a,b,c) -> [c] | ||
+ | | SUBI(a,b,c) -> [c] | ||
+ | | INC(a) -> [a] | ||
+ | | DEC(a) -> [a] | ||
+ | | LD(a,b,c) -> [c] | ||
+ | | ST(a,b,c) -> [] | ||
+ | | LDI(a,b,c) -> [c] | ||
+ | | STI(a,b,c) -> [] | ||
+ | | CALL(a,b) -> [] | ||
+ | | GOTOR(a) -> [] | ||
+ | | GOTOL(a) -> [] | ||
+ | | IFLEQ(a, | ||
+ | | IFLE(a,b,c) -> [] | ||
+ | | IFGEQ(a, | ||
+ | | IFGE(a,b,c) -> [] | ||
+ | | IFEQ(a,b,c) -> [] | ||
+ | | IFNEQ(a, | ||
+ | | END -> [] | ||
+ | ;; | ||
+ | |||
+ | (** function computing the intersection of two lists. | ||
+ | This is used to compute Bernstein conditions | ||
+ | @param l1 First list | ||
+ | @param l2 Second list | ||
+ | @return An empty list if no intersection is found, otherwise return the intersection list *) | ||
+ | let intersect l1 l2 = | ||
+ | let a1 = Array.of_list l1 in | ||
+ | let a2 = Array.of_list l2 in | ||
+ | let res = ref [] in | ||
+ | let n1 = Array.length a1 in | ||
+ | let n2 = Array.length a2 in | ||
+ | for i=0 to (n1-1) do | ||
+ | for j=0 to (n2-1) do | ||
+ | if(a1.(i) = a2.(j)) | ||
+ | then res := a2.(j) :: !res | ||
+ | done | ||
+ | done; | ||
+ | !res | ||
+ | ;; | ||
+ | |||
+ | (** checks if an instruction is " | ||
+ | let iu_instruction = function | ||
+ | IFLEQ(a, | ||
+ | | IFLE(a, | ||
+ | | IFGEQ(a, | ||
+ | | IFGE(a, | ||
+ | | IFEQ(a, | ||
+ | | IFNEQ(a, | ||
+ | | LD(a, | ||
+ | | LDI(a, | ||
+ | | ST(a, | ||
+ | | STI(a, | ||
+ | | _ -> false | ||
+ | ;; | ||
+ | |||
+ | |||
+ | (** data dependency: | ||
+ | instructions inducing the data dependencies | ||
+ | interested register(s) | ||
+ | " | ||
+ | " | ||
+ | *) | ||
+ | type datadep = | ||
+ | NoDataDep | ||
+ | | DataDep of int * asm * int * asm * reg list * int * int ;; | ||
+ | |||
+ | (** removes labels from an instruction, | ||
+ | and returns the assembler instruction only *) | ||
+ | let delab = function | ||
+ | LabInstr(l, | ||
+ | | Instr(i) -> i;; | ||
+ | |||
+ | (** check whether there is a data dependency among instructions | ||
+ | @param a1 the address of the first instruction | ||
+ | @param a2 the address of the second instruction | ||
+ | @param li1 the first instruction | ||
+ | @param li2 the second instruction | ||
+ | @param dist the distance between instructions | ||
+ | @param n the N parameter | ||
+ | @return A new datadep instance with the previous parameters | ||
+ | *) | ||
+ | let data_dep_i a1 a2 li1 li2 dist n = | ||
+ | let i1 = delab li1 in | ||
+ | let i2 = delab li2 in | ||
+ | let wrs = codomain(i1) in | ||
+ | let rds = domain(i2) in | ||
+ | let regset = (intersect rds wrs) in | ||
+ | if(iu_instruction i2 && not(regset = [])) | ||
+ | then DataDep(a1, | ||
+ | else NoDataDep;; | ||
+ | |||
+ | (** checks whether there is a load in the sequence | ||
+ | leading to the dependency | ||
+ | @param i1 the starting point of the sequence | ||
+ | @param i2 the ending point of the sequence | ||
+ | @param prog the program with the sequence | ||
+ | @return true if a LD or a LDI is found in the sequence, otherwise return false*) | ||
+ | let loadsinsequence prog i1 i2 = | ||
+ | let aprog = Array.of_list prog in | ||
+ | let bign = ref false in | ||
+ | for i=i1 to (i2-1) do | ||
+ | let asmi = match aprog.(i) with | ||
+ | Instr(ai) -> ai | ||
+ | | ||
+ | bign := match asmi with | ||
+ | LD(a,b,c) -> true | ||
+ | | | ||
+ | | _ -> !bign | ||
+ | done; | ||
+ | !bign | ||
+ | ;; | ||
+ | |||
+ | (** finds all data dependencies in a program | ||
+ | @param prog the program | ||
+ | @return An empty list if no data dependency is found, otherwise return a list of data dependencies *) | ||
+ | let data_deps prog = | ||
+ | let aprog = Array.of_list prog in | ||
+ | let n = Array.length aprog in | ||
+ | let res = ref [] in | ||
+ | let start = ref 0 in | ||
+ | for i=0 to (n-2) do | ||
+ | for j=(i+1) to (n-1) do | ||
+ | let i1 = aprog.(i) in | ||
+ | let i2 = aprog.(j) in | ||
+ | let dd = (data_dep_i i j i1 i2 (j-i) 0) in (* N=0 TODO *) | ||
+ | match dd with | ||
+ | NoDataDep -> () | ||
+ | | DataDep(i, | ||
+ | let hasloads = loadsinsequence prog !start (j-1) in | ||
+ | let bign = if(hasloads) then 2 else 1 in | ||
+ | let dd = DataDep(i, | ||
+ | |||
+ | start := j; | ||
+ | res := (List.append (!res) [dd]) | ||
+ | done | ||
+ | done; | ||
+ | !res | ||
+ | ;; | ||
+ | |||
+ | (** bernstein conditions check *) | ||
+ | let bernstein i1 i2 = | ||
+ | let d1 = domain i1 in | ||
+ | let d2 = domain i2 in | ||
+ | let c1 = codomain i1 in | ||
+ | let c2 = codomain i2 in | ||
+ | let d1c2 = intersect d1 c2 in | ||
+ | let d2c1 = intersect d2 c1 in | ||
+ | if(d1c2 = [] && d2c1 = []) | ||
+ | then true | ||
+ | else false | ||
+ | ;; | ||
+ | |||
+ | (** pretty print a register *) | ||
+ | let pp_reg = function | ||
+ | Reg(x) -> printf " R_%d " x ;; | ||
+ | |||
+ | (** pretty print a list of registers *) | ||
+ | let rec pp_regs = function | ||
+ | [] -> () | ||
+ | | r::rr -> (pp_reg r);(pp_regs rr);; | ||
+ | |||
+ | (** pretty print the register set | ||
+ | Used in pretty print of the | ||
+ | environment of execution of a program | ||
+ | @param r An integer array rappresenting the register set *) | ||
+ | let pp_reg_set r = | ||
+ | let n = Array.length r in | ||
+ | for i=0 to (n-1) do | ||
+ | printf " R%d=%d " i r.(i); | ||
+ | if (i mod 16 == 0 && not(i = 0)) then printf " | ||
+ | done; | ||
+ | printf " | ||
+ | ;; | ||
+ | |||
+ | (** pretty print a memory state. Used in pretty print of the | ||
+ | environment of execution of a program | ||
+ | @param r An integer array rappresenting the memory *) | ||
+ | let pp_mem r = | ||
+ | let n = Array.length r in | ||
+ | for i=0 to (n-1) do | ||
+ | if(i mod 8 == 0 && not (i = 0)) | ||
+ | then printf " | ||
+ | if(i mod 4 == 0) | ||
+ | then printf " | ||
+ | else printf " | ||
+ | done; | ||
+ | printf " | ||
+ | ;; | ||
+ | |||
+ | (** pretty print a label *) | ||
+ | let pp_lab = function | ||
+ | LabLab(s) -> printf " %s " s | ||
+ | | LabOff(o) -> printf "L(%d) " o | ||
+ | | DelayedBranch(LabLab(s)) -> printf " %s , delayed_branch" | ||
+ | | DelayedBranch(LabOff(o)) -> printf " L(%d) , delayed_branch" | ||
+ | | _ -> printf "Label Error" | ||
+ | ;; | ||
+ | |||
+ | (** pretty print a constant *) | ||
+ | let pp_const = function | ||
+ | Const c -> printf " #%d " c;; | ||
+ | |||
+ | (** pretty print a D-RISC instruction *) | ||
+ | let pp_asm = function | ||
+ | ADD(a,b,c) -> printf "ADD "; pp_reg(a); pp_reg(b); pp_reg(c) | ||
+ | | SUB(a,b,c) -> printf "SUB "; pp_reg(a); pp_reg(b); pp_reg(c) | ||
+ | | MUL(a,b,c) -> printf "MUL "; pp_reg(a); pp_reg(b); pp_reg(c) | ||
+ | | DIV(a,b,c) -> printf "DIV "; pp_reg(a); pp_reg(b); pp_reg(c) | ||
+ | | ADDI(a,b,c) -> printf "ADDI "; pp_reg(a); pp_const(b); | ||
+ | | SUBI(a,b,c) -> printf "SUBI "; pp_reg(a); pp_const(b); | ||
+ | | INC(a) -> printf " | ||
+ | | DEC(a) -> printf " | ||
+ | | LD(a,b,c) -> printf "LOAD "; pp_reg(a); pp_reg(b); pp_reg(c) | ||
+ | | LDI(a,b,c) -> printf " | ||
+ | | ST(a,b,c) -> printf "STORE "; pp_reg(a); pp_reg(b); pp_reg(c) | ||
+ | | STI(a,b,c) -> printf " | ||
+ | | CALL(a,b) -> printf "CALL "; pp_reg(a); pp_reg(b) | ||
+ | | GOTOR(a) -> printf " | ||
+ | | GOTOL(l) -> printf " | ||
+ | | IFLE(r1, | ||
+ | | IFLEQ(r1, | ||
+ | | IFGE(r1, | ||
+ | | IFGEQ(r1, | ||
+ | | IFEQ(r1, | ||
+ | | IFNEQ(r1, | ||
+ | | END -> printf "END " | ||
+ | | _ -> printf " | ||
+ | ;; | ||
+ | |||
+ | (** pretty print an instruction, | ||
+ | let pp_instr add = function | ||
+ | Instr(i) -> printf " | ||
+ | | LabInstr(l, | ||
+ | | ||
+ | ;; | ||
+ | |||
+ | (** pretty print a whole program, starting with at a given address *) | ||
+ | let rec pp_prog add = function | ||
+ | [] -> printf " | ||
+ | | i::ri -> (pp_instr add i); (pp_prog (add+1) ri) | ||
+ | ;; | ||
+ | |||
+ | (** pretty print a program, assuming it is allocated from address 0 *) | ||
+ | let pp_program p = (pp_prog 1 p);; | ||
+ | |||
+ | |||
+ | (** pretty print a data dependency *) | ||
+ | let pp_dd = function | ||
+ | NoDataDep -> () | ||
+ | | DataDep(a1, | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | (** pretty print a list of dependencies *) | ||
+ | let rec pp_deps = function | ||
+ | [] -> () | ||
+ | | d::rd -> (pp_dd d);(pp_deps rd);; | ||
+ | |||
+ | (** transforms a list of instructions (with labels) into | ||
+ | a list of assembler instruction (with no labels) *) | ||
+ | let rec prog_to_asm p = | ||
+ | List.map delab p;; | ||
+ | | ||
+ | (* | ||
+ | ============================= | ||
+ | |||
+ | Gestione dei Salti | ||
+ | |||
+ | ============================= | ||
+ | *) | ||
+ | |||
+ | (** Check if an ASM instruction in a jump istruction | ||
+ | @param istr the ASM instruction | ||
+ | @return true if istr is a jump instruction, | ||
+ | let is_jump istr = | ||
+ | match istr with | ||
+ | | ||
+ | | GOTOR(a) -> true | ||
+ | | GOTOL(a) -> true | ||
+ | | IFLEQ(a, b, l) -> true | ||
+ | | IFLE(a, b, l) -> true | ||
+ | | IFGEQ(a, b, l) -> true | ||
+ | | IFGE(a, b, l) -> true | ||
+ | | IFEQ(a, b, l) -> true | ||
+ | | IFNEQ(a, b, l) -> true | ||
+ | | _ -> false | ||
+ | ;; | ||
+ | |||
+ | (** Check if an ASM instruction has Delayed Branch flag | ||
+ | @param istr the ASM instruction | ||
+ | @return true if istr has DelayedBranch, | ||
+ | let has_delayed_branch istr = | ||
+ | match istr with | ||
+ | | ||
+ | | IFLEQ(a, b, DelayedBranch(l)) -> true | ||
+ | | IFLE(a, b, DelayedBranch(l)) -> true | ||
+ | | IFGEQ(a, b, DelayedBranch(l)) -> true | ||
+ | | IFGE(a, b, DelayedBranch(l)) -> true | ||
+ | | IFEQ(a, b, DelayedBranch(l)) -> true | ||
+ | | IFNEQ(a, b, DelayedBranch(l)) -> true | ||
+ | | _ -> false | ||
+ | ;; | ||
+ | |||
+ | |||
+ | (** Jumps: | ||
+ | int: instruction number | ||
+ | asm: the instruction | ||
+ | *) | ||
+ | type jumps = | ||
+ | NoJump | ||
+ | | Jump of int * asm;; | ||
+ | |||
+ | |||
+ | (** finds all jumps in a program | ||
+ | @param prog the program | ||
+ | @return An empty list if no jump is found, otherwise return a list of jumps *) | ||
+ | let jump_find prog = | ||
+ | let asmprog = prog_to_asm prog in | ||
+ | let aprog = Array.of_list asmprog in | ||
+ | let n = Array.length aprog in | ||
+ | let res = ref [] in | ||
+ | for i=0 to n-1 do | ||
+ | let istr = aprog.(i) in | ||
+ | if (is_jump istr && not(has_delayed_branch istr)) then | ||
+ | res := (List.append (!res) [Jump(i, istr)]) | ||
+ | done; | ||
+ | !res | ||
+ | ;; | ||
+ | |||
+ | (** pretty print a jump *) | ||
+ | let pp_jump = function | ||
+ | NoJump -> () | ||
+ | | Jump(i, istr) -> | ||
+ | | ||
+ | | ||
+ | | ||
+ | ;; | ||
+ | |||
+ | (** pretty print a list of jumps *) | ||
+ | let rec pp_jumps = function | ||
+ | [] -> () | ||
+ | | x::xs -> (pp_jump x); | ||
+ | |||
+ | (* | ||
+ | ============================= | ||
+ | *) | ||
+ | </ | ||
+ |
informatica/ae/file_asm.ml.1309188003.txt.gz · Ultima modifica: 27/06/2011 alle 15:20 (14 anni fa) da Marco Danelutto