Commit 4cf9f6ef authored by Quentin Aristote's avatar Quentin Aristote
Browse files

deletion

parent cc07d4e9
(* --------------------------- VARIABLES GLOBALES --------------------------- *)
const ops_nbr_length = 8 (* devrait suffire jusqu'à 256 lignes d'assembleur ;
est aussi la longueur du nombre d'opérations par
seconde *)
(* ---------------------------------- UAL ---------------------------------- *)
zeros<n>() = o:[n] where
if n = 0 then
o = []
else
o = 0.zeros<n-1>()
end if
end where
ones<n>() = o:[n] where
if n = 0 then
o = []
else
o = 1.ones<n-1>()
end if
end where
multi_and<n>(a:[n], b:[n]) = o:[n] where
if n = 0 then
o = []
else
o = (a[0] & b[0]).multi_and<n-1>(a[1..], b[1..])
end if
end where
multi_or<n>(a:[n], b:[n]) = o:[n] where
if n = 0 then
o = [];
else
o = (a[0] + b[0]).multi_or<n-1>(a[1..], b[1..])
end if
end where
multi_xor<n>(a:[n], b:[n]) = o:[n] where
if n = 0 then
o = [];
else
o = (a[0] ^ b[0]).multi_xor<n-1>(a[1..],b[1..])
end if
end where
(* bizzarement le cas n = 0 fait tout bugger *)
multi_not<n>(a:[n]) = o:[n] where
if n = 1 then
o = not(a)
else
o = not(a[0]).multi_not<n-1>(a[1..])
end if
end where
multi_nor<n>(a:[n], b:[n]) = o:[n] where
o = multi_not<n>(multi_or<n>(a, b))
end where
multi_mux<n>(c, a:[n], b:[n]) = o:[n] where
if n = 0 then
o = []
else
o = mux(c, a[0], b[0]).multi_mux<n-1>(c, a[1..n-1], b[1..n-1])
end if
end where
add<n>(a:[n], b:[n], c_in) = (o:[n], c_out) where
if n = 0 then
o = [] ;
c_out = 0
else
(tail, c) = add<n-1>(a[1..], b[1..], c_in) ;
tmp = a[0] ^ b[0] ;
o = (tmp ^ c).tail ;
c_out = (tmp & c) + (a[0] & b[0])
end if
end where
(* a - b *)
sub<n>(a:[n], b:[n]) = o:[n] where
(o, c) = add<n>(a, multi_not<n>(b), 1)
end where
(* a >= 0 *)
gez<n>(a:[n]) = o where
(* a >= 0 ssi son bit de signe est nul *)
o = not(a[0])
end where
(* a = 0 *)
ez<n>(a:[n]) = o where
if n = 0 then
o = 0
else
o = not(a[0]) & ez<n-1>(a[1..])
end if
end where
(* a > O *)
gz<n>(a:[n]) = o where
o = not(a[0] + ez<n>(a))
end where
(* a < 0 *)
lz<n>(a:[n]) = o where
o = a[0]
end where
(* a <= 0 *)
lez<n>(a:[n]) = o where
o = a[0] + ez<n>(a)
end where
(* On fait le shift p fois *)
sll<n, m, p>(a:[n], shamt:[m]) = o:[n] where
if m = 0 then
o = a
else
o = sll<n, m-1, 2*p>(multi_mux<n>(shamt[m-1],
a[..n-(p+1)].zeros<p>(),
a),
shamt[..m-2])
end if
end where
srl<n, m, p>(a:[n], shamt:[m]) = o:[n] where
if m = 0 then
o = a
else
o = srl<n, m-1, 2*p>(multi_mux<n>(shamt[m-1],
zeros<p>().a[p..],
a),
shamt[..m-2])
end if
end where
sra<n, m, p>(a:[n], shamt:[m]) = o:[n] where
if m = 0 then
o = a
else
o = sra<n, m-1, 2*p>(multi_mux<n>(shamt[m-1],
ones<p>().a[p..],
a),
shamt[..m-2])
end if
end where
(* ------------------------------ INSTRUCTIONS ------------------------------ *)
addi(s:[16], imm:[16]) = o:[16] where
(o, c) = add<16>(imm, s, 0)
end where
bltz(s:[16], imm:[16], PC:[16]) = new_PC:[16] where
(tmp_PC, c) = add<16>(PC, imm, 0) ;
new_PC = multi_mux<16>(lz<16>(s), tmp_PC, PC)
end where
beq(s:[16], t:[16], imm:[16], PC:[16]) = new_PC:[16] where
(tmp_PC, c) = add<16>(PC, imm, 0);
e = sub<16>(s, t);
new_PC = multi_mux<16>(ez<16>(s), tmp_PC, PC);
end where
bne(s:[16], t:[16], imm:[16], PC:[16]) = new_PC:[16] where
(tmp_PC, c) = add<16>(PC, imm, 0);
e = sub<16>(s, t);
new_PC = multi_mux<16>(ez<16>(s), PC, tmp_PC);
end where
j(label:[26], PC:[32]) = new_PC:[32] where
new_PC = PC[0..3].label.00
end where
type_i(opcode:[6],
rs:[5],
s:[16],
rt:[5],
t:[16],
imm:[16],
PC:[16]) = (write_enable,
write_address:[5],
write_value:[16],
new_PC:[16]) where
o_addi = addi(s, imm) ;
o_bltz = bltz(s, imm, PC) ;
o_beq = beq(s, t, imm, PC) ;
o_bne = bne(s, t, imm, PC) ;
o_lui = imm ;
new_PC_v1 = multi_mux<16>(opcode[5], o_bne, o_beq) ;
new_PC_v2 = multi_mux<16>(opcode[3], new_PC_v1, o_bltz) ;
write_enable = opcode[2] ;
write_address = multi_mux<5>(opcode[5], rs, rt) ;
write_value = multi_mux<16>(opcode[5], o_lui, o_addi) ;
new_PC = multi_mux<16>(opcode[2], PC, new_PC_v2)
end where
type_r(s:[16],
t:[16],
shamt:[5],
funct:[6]) = write_value:[16] where
o_add = addi(s, t) ;
o_sll = sll<16, 5, 1>(t, shamt) ;
o_srl = srl<16, 5, 1>(t, shamt) ;
write_value_v1 = multi_mux<16>(funct[0], o_add, o_sll) ;
write_value = multi_mux<16>(funct[4], o_srl, write_value_v1)
end where
(* -------------------------------- MÉMOIRE -------------------------------- *)
register_access(rs:[5],
rt:[5],
write_enable,
write_address:[5],
write_word:[16]) = (t0:[16],
t1:[16],
t2:[16],
t3:[16],
t4:[16],
t5:[16],
t6:[16],
t7:[16],
rs_val:[16],
rt_val:[16]) where
t0 = ram<4, 16>(1000, write_enable, write_address[1..], write_word) ;
t1 = ram<4, 16>(1001, write_enable, write_address[1..], write_word) ;
t2 = ram<4, 16>(1010, write_enable, write_address[1..], write_word) ;
t3 = ram<4, 16>(1011, write_enable, write_address[1..], write_word) ;
t4 = ram<4, 16>(1100, write_enable, write_address[1..], write_word) ;
t5 = ram<4, 16>(1101, write_enable, write_address[1..], write_word) ;
t6 = ram<4, 16>(1110, write_enable, write_address[1..], write_word) ;
t7 = ram<4, 16>(1111, write_enable, write_address[1..], write_word) ;
rs_val = multi_mux<16>(ez<5>(rs),
0b0000000000000000,
ram<4, 16>(rs[1..],
write_enable,
write_address[1..],
write_word)) ;
rt_val = multi_mux<16>(ez<5>(rt),
0b0000000000000000,
ram<4, 16>(rt[1..],
write_enable,
write_address[1..],
write_word)) ;
end where
PC_access(new_PC:[32]) = old_PC:[32] where
old_PC = ram<1, 32>(0, 1, 0, new_PC)
end where
ops_to_do() = o:[ops_nbr_length] where
o = 0b11001000 (* 200 *)
end where
ops_done() = o:[ops_nbr_length] where
(o, c) = add<ops_nbr_length>(ram<1, ops_nbr_length>(0, 1, 0, o), 0b00000000, 1)
end where
(* -------------------------- PROGRAMME PRINCIPAL -------------------------- *)
execute_command(command:[32], old_PC:[32]) = (t0:[16],
t1:[16],
t2:[16],
t3:[16],
t4:[16],
t5:[16],
t6:[16],
t7:[16],
new_PC:[32]) where
opcode = command[0..5] ;
rs = command[6..10] ;
rt = command[11..15] ;
rd = command[16..20] ;
shamt = command[21..25] ;
funct = command[26..31] ;
imm = command[16..31] ;
pseudo_address = command[6..31] ;
(* les valeurs des registres renvoyées ne sont pas les résultats de la
commande mais les valeurs utilisées pour calculer ces résultats ;
on est donc décalé mais en pratique ce n'est pas un problème car
l'éxecution d'une commande se fait très rapidement *)
(t0,
t1,
t2,
t3,
t4,
t5,
t6,
t7,
rs_val,
rt_val) = register_access(rs,
rt,
write_enable,
write_address,
write_value) ;
(PC, c) = add<32>(old_PC, 0b00000000000000000000000000000100, 0) ;
(write_enable_I,
write_address_I,
write_value_I,
new_PC_I) = type_i(opcode, rs, rs_val, rt, rt_val, imm, PC[16..]) ;
write_value_R = type_r(rs_val, rt_val, shamt, funct) ;
new_PC_J = j(pseudo_address, PC) ;
J = opcode[4] & not(opcode[5]) ;
I = opcode[2] + opcode[3] + opcode[5] ;
write_enable = mux(J, 0, mux(I, write_enable_I, 1)) ;
write_address = multi_mux<5>(I, write_address_I, rd) ;
write_value = multi_mux<16>(I, write_value_I, write_value_R) ;
new_PC = multi_mux<32>(J + I,
multi_mux<32>(J, new_PC_J, PC[..15].new_PC_I),
PC)
end where
main() = (t0:[16],
t1:[16],
t2:[16],
t3:[16],
t4:[16],
t5:[16],
t6:[16],
t7:[16]) where
PC = PC_access(multi_mux<32>(lz<ops_nbr_length>(
sub<ops_nbr_length>(ops_to_do(),
ops_done())),
zeros<32>(),
new_PC)) ;
command = rom<30, 32>(PC[..29]) ;
(t0, t1, t2, t3, t4, t5, t6, t7, new_PC) = execute_command(command, PC)
end where
open Netlist_ast
let number_steps = ref (-1)
let steps=ref 1
let vars=Hashtbl.create 10
let regs=ref (Hashtbl.create 10)
let bitarray8_of_int i=
let rec aux n e=match e with
|0->[]
|_->(n mod 2)::(aux (n/2) (e-1))
in Array.of_list (List.rev (aux i 8))
let file = open_in_bin "../command.rom"
let rec readRom () =
try let t=input_byte file in (bitarray8_of_int t)::(readRom ())
with
|End_of_file -> []
let rom=Array.concat (readRom ())
let ram=Hashtbl.create 10
let oldram=ref (Hashtbl.create 10)
let saletruc=ref 0
let rec int_of_value v=match v with
|VBit false->0
|VBit true->1
|VBitArray vba->Array.fold_right (fun b n->2*n+int_of_value (VBit b)) vba 0
let bitarray_of_value v=match v with
|VBit vb->Array.make 1 vb
|VBitArray vba->vba
let print_arg a=match a with
|Avar v->print_string v
|Aconst c->print_string "//TODO"
let rec read_input var=
(*On ne vérifie pas que les types sont bons parce que c'est géré bizarrement par
netlist_ast.ml, et ce n'est pas essentiel pour le fonctionnement du simulateur*)
print_string (var^" ? ");
match (read_line ()) with
|"0"->Hashtbl.replace vars var (VBit false)
|"1"->Hashtbl.replace vars var (VBit true)
|s->let vba=Array.make (String.length s) true in
let bon=ref true in
for i=0 to ((String.length s)-1) do
match String.get s i with
|'0'->Array.set vba i false
|'1'->Array.set vba i true
|_->bon:=false
done;
if !bon then Hashtbl.replace vars var (VBitArray vba) else read_input var
let print_bit b=match b with
|true->print_int 1
|false->print_int 0
let print_value v=match v with
|VBit b->print_bit b
|VBitArray vba->Array.iter print_bit vba
let disp_output var=
print_string ("=> "^var^" = ");
print_value (Hashtbl.find vars var);
print_newline ()
(*binop->bool->bool->bool*)
let calc_binop bop vb1 vb2=match bop with
|Or->vb1||vb2
|Xor->(vb1||vb2)&&(not (vb1&&vb2))
|And->vb1&&vb2
|Nand->not (vb1&&vb2)
(*bool->bool->bool->bool*)
let calc_mux mux vb1 vb2=if mux then vb2 else vb1
(*arg->value*)
let calc_arg arg=match arg with
|Avar v->Hashtbl.find vars v
|Aconst c->c
(*exp->value*)
let calc_exp exp=match exp with
|Earg a->calc_arg a
|Ereg x->Hashtbl.find !regs x
|Enot a->let va=calc_arg a in begin
match va with
|VBit vb->VBit (not vb)
|VBitArray vba->VBitArray (Array.map not vba)
end
|Ebinop (bop,a,b)->begin
match calc_arg a,calc_arg b with
|VBit vb1,VBit vb2->VBit (calc_binop bop vb1 vb2)
|VBitArray vba1,VBitArray vba2->VBitArray (Array.map2 (calc_binop bop) vba1 vba2)
|_,_->failwith "Two types don't match"
end
|Emux (mux,a,b)->begin
match calc_arg mux,calc_arg a,calc_arg b with
|VBit vbmux,VBit vb1,VBit vb2->VBit (calc_mux vbmux vb1 vb2)
|VBitArray vbamux,VBitArray vba1,VBitArray vba2->VBitArray Array.(mapi (fun i x->calc_mux x (get vba1 i) (get vba2 i)) vbamux)
|_,_,_->failwith "Two types don't match"
end
|Erom (addr_size,word_size,read_addr)->
let aux i p=
try
match Array.get rom (word_size*(int_of_value (calc_arg read_addr))+i) with
|0->false
|_->true
with
|Invalid_argument a->false
in VBitArray (Array.mapi aux (Array.make word_size 0))
|Eram (addr_size,word_size,read_addr,write_enable,write_addr,data)->saletruc:=!saletruc+1000;
begin if (int_of_value (calc_arg write_enable))=1 then
let aux1 i p=
Hashtbl.add ram (word_size*((int_of_value (calc_arg write_addr)))+i+(!saletruc)) (Array.get (bitarray_of_value (calc_arg data)) i)
in Array.iteri aux1 (bitarray_of_value (calc_arg data)) end;
let aux2 i p=
try
Hashtbl.find !oldram (word_size*((int_of_value (calc_arg read_addr)))+i+(!saletruc))
with
|Not_found->false in
VBitArray (Array.mapi aux2 (Array.make word_size 0))
|Econcat (a,b)->VBitArray (Array.append (bitarray_of_value (calc_arg a)) (bitarray_of_value (calc_arg b)))
|Eslice (i1,i2,a)->begin
match calc_arg a with
|VBitArray vba when (i1<=i2)&&(i2<(Array.length vba))->VBitArray (Array.sub vba i1 (i2-i1+1))
|VBitArray vba->print_int i1;print_int i2;print_arg a;print_int (Array.length vba);failwith "Invalid arguments were given to a slicing instruction"
|_->failwith "Only arrays can be sliced"
end
|Eselect (i,a)->begin
match calc_arg a with
|VBitArray vba when (i<(Array.length vba))->VBit (Array.get vba i)
|VBitArray vba->failwith "Select index out of bounds"
|_->print_arg a;failwith "Selection is only possible in an array"
end
(*eq->unit*)
let process_eq eq=
(*On ne vérifie pas que les types sont bons parce que c'est géré bizarrement par
netlist_ast.ml, et ce n'est pas essentiel pour le fonctionnement du simulateur*)
Hashtbl.replace vars (fst eq) (calc_exp (snd eq))
let execute filename=
try
let p = Netlist.read_file filename in
List.iter (fun x->Hashtbl.add vars x (VBit false)) p.p_inputs;
List.iter (fun x->Hashtbl.add vars (fst x) (match Env.find (fst x) p.p_vars with
|TBit->VBit false
|TBitArray n->VBitArray (Array.make n false))) p.p_eqs;
(*On renverra une erreur si il faut afficher une variable qui n'est jamais assignée*)
while (!number_steps=(-1)) || (!number_steps>=(!steps)) do
print_endline ("Step "^(string_of_int !steps)^":");
saletruc:=0;
List.iter read_input p.p_inputs;
regs:=Hashtbl.copy vars;
oldram:=Hashtbl.copy ram;
List.iter process_eq p.p_eqs;
List.iter disp_output p.p_outputs;
steps:=!steps+1
done;
with
| Netlist.Parse_error s -> Format.eprintf "An error occurred: %s@." s; exit 2
let main () =
Arg.parse
["-n", Arg.Set_int number_steps, "Number of steps to simulate"]
execute
""
;;
main ()
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment