-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathREADME
116 lines (84 loc) · 4.35 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
= L'assembleur =
Style mips, c'est le plus simple : plein de registres + un registre zero qui contient toujours 0
2 types d'instructions
- [alu rdest r1 r2] pour les operations arith/logiques où alu parcours {add, sub, or, and, ... }
prends aussi en compte move car : move $rdest $r ~ or rdest $r $zero
prends aussi en compte les jump avec move $pc $x
- [load dest addr/store orig addr] qui prends ou mets des trucs dans la RAM à l'addresse $addr
De plus, chaque instruction prends un registre supplementaire $c en argument et ne s'execute que si celui ci est nul (sinon elle devient move $zero $zero ~ nop). Cela permet le branching et on met $zero pour faire le mips usuel.
Encodage : chaque instruction sur 4 mots
[op][arg1][arg2][arg3] (quand l'operation a moins d'arguments on pad avec des 0)
où :
op =
| 00[alu_type] => operation sur l'alu { arg1 = rdest, arg2 = r2, arg3 = r3}, on transmet alu_type
| 10(0*) => load { dest = arg1, addr = arg2 }
| 11(0*) => store { orig = arg3, addr = arg2 }
(le 0* c'est qu'on complète par des zeros, on est indépendant de la taille du mot à la compilation)
= La ROM =
Elle va lire les mots 4 par 4 parceque c'est la taille de nos instructions donc c'est plus simple :
- une entrée read_addr[wordsize]
- une sortie instr[4*wordsize]
= La RAM =
- deux entrée read_addr[wordsize], write_addr[wordsize]
- une entrée write_data[wordsize] et une entrée write[1]
- une sortie read_data[wordsize]
si write est à 1 la RAM écrit write_data à l'addresse write_addr etc.
= Architecture =
Un registre spécial $pc est toujours branché sur le read_addr de la ROM. Il s'incrémente de plus tout seul a chaque tick d'horloge.
Tous les sorties registres sont branchés sur 2 gros selecteurs qui prennent en argument arg2 et arg3 resp.
En gros on a 3 mots qui valent a tout moment $arg2 et $arg3 resp.
De même les entrées sont branchées sur un selecteur qui vaut $arg1$.
Donc a chaque instruction, on écrits TOUJOURS le résultat de quelquechose dans $arg1 et on lit TOUJOURS $arg2 et $arg3
r1_read == | |
r2_read == | SELECT (instr[wordsize:2*wordsize]) |
... | | == arg2
rn_read == | |
pareil pour arg3
Pour alu & load:
arg2 =(read_addr)= [RAM]
||
(read_data)
_____ ||
arg2 =(input1)= | ALU | =(output)= select(op[0:2]) == arg3
arg3 =(input2)= |_____|
Pour brifzero :
zero
|
arg2 == is_zero -- select(op[0:2]) -- pc_overwrite
||
pc_write
= Organisation =
- jop/ : Module camlp4 et runtime pour la compilation ml => netlist.
- circuits/ : Fichiers ml décrivant des netlists.
- netlists/ : Netlists générées et fichiers d'input.
- simulator/ : Simulateur de netlist en java. L'utilisation est expliquée en executant JOP_Simulator.jar sans argument (java -jar JOP_Simulator.jar)
= Comment lancer une demo ? =
Les demos dispos sont (pour l'instant) :
./rundemo.sh full_adder
Teste tout les combinaisons d'entrées sur un full adder décrit dans circuits/full_adder.ml
Sortie espérée : 0 1 1 1 2 2 2 3
./rundemo.sh minus
Fais le moins unaire de l'entrée (ici 100000000...)
Sortie espérée : 11111111111....
./rundemo.sh count <n>
Incrémente un compteur modulo 2^n pendant 32 ticks d'horloge.
Sortie espérée :
- 0 1 2 3 ... ((2^n)-1) 0 1 ... (valeur du compteur)
- 0 0 0 0 ... 1 0 0 ... (bit d'overflow)
./rundemo.sh modn <n>
Même chose que pour count, mais on a ici un compteur modulo n, avec n quelconque.
./rundemo.sh clk2
Effectue une division d'horloge.
Sortie attendue : 110011001100...
(ou la même chose avec un déphasage de 1 pour l'autre sortie)
Le code des circuits n'est pour l'instant pas très beau, ceci étant dût à quelques soucis avec camlp4, work in progress.
= Est-il possible de faire ces démos avec nos propres inputs d'entrée ? =
Bien sûr, il suffit pour cela de modifier le fichier d'extension ".nl.input" correspondant.
Les fichiers input sont concus de telle manière :
Tout d'abord le nombre de cycle d'horloge à simuler,
Puis pour chaque input, le nom de la variable suivie (séparés par des espaces) les valeurs au cours du temps.
Un exemple de fichier pourrait être :
8
a 0 1 0 0 0 1 1 1
b 0 0 1 0 1 0 1 1
ci 0 0 0 1 1 1 0 1