Indice
DRISC tools
The tools allow to test simple programs written in the DRISC assembler [1]. The tools are written in Ocaml and have been tested on Linux (Ubuntu from 10.04 to 14.10, but other distributions also work).
Federico De Faveri produced an alternative D-RISC intepreter (with a much nicer interface) that runs within a browser page (see this page). The interpreted uses the same syntax defined on this page (including memory location and register contents pseudo instructions).
Install the tools
In order to run the Drisc tools you need to have previously installed Ocaml. Ocaml can be installed from sources (available from the Ocaml web site) or as packages (e.g. through Ubuntu Synaptics).
The tool source can be downloaded from the link below.
In order to use the tools you need:
- uncompress the file
- change directory to the Drisc top level
- make
- insert the Drisc directory in your $PATH, or use commands as /path_to_drisc/Drisc/drisc
Syntax supported
The Drisc tools support the Drisc syntax introduced in [1], with the following limitations/feature
- “symbolic” register names (e.g. Ri or RbaseA) are not supported, only “number” registers are supported (e.g. R0, R63, R17)
- alfanumeric labels are supported
- instruction codes may be lowercase or uppercase
- several pseudo instructions are supported:
- memloc L X defines the contents of memory location L as X
- memlocs L X1 X2 … Xn defines the contents of memory locations starting at L as X1 X2 … Xn
- regval R X defines the initial contents of register R as X
- loc X the following instructions are placed in memory at address X
- start X defines the first instruction of the program (memory location X)
- memloc statements should be used for any location (either read or written) used in the program
- comments or empty lines are not supported
- error handling is really basic. In case you get an error, move an end instruction through the code to identify the instruction killing the parser and then analyze its syntax carefully
Sample code
Here is the code computing inner product:
memloc 1024 3 memloc 1025 2 memloc 1026 1 memloc 2048 4 memloc 2049 5 memloc 2050 6 memloc 4096 0 memloc 4097 0 memloc 4098 0 regval 1 1024 regval 2 2048 regval 3 4096 regval 4 3 start 1024 loc 1024 add R0,R0,R9 clear R10 loop: load R1,R9,R20 load R2,R9,R30 mul R20,R30,R20 add R20,R10,R10 incr R9 if< R9,R4,loop end
The three memloc block define the three areas for input vector A (at mem[1024]), B (at mem[2048]) and the result block (at mem[4096]).
The regval statements initialize the RbaseA (R1) RbaseB (R2) Rresult (R3) and RN (R4) registers. The program is stored starting at memory address 1024 (loc 1024 pseudo instruction) and starts at location 1024 (start 1024 pseudo instruction).
Tool usage
Two programs are compiled from the tools:
parse
parse file
parses the drisc program in file. If parsing succeeds, you should see the whole listing of the program to appear, including pseudo instructions. Otherwise you'll get an error with no output (error handling is not implemented in the parser).
Sample output (correct program):
marcod@marcod-ThinkPad-X220:~/Documents/Didattica/Architetture/Drisc$ ./parse SamplePrograms/ip.drisc 1. Mem[1024]=3 2. Mem[1025]=2 3. Mem[1026]=1 4. Mem[2048]=4 5. Mem[2049]=5 6. Mem[2050]=6 7. Mem[4096]=0 8. Mem[4097]=0 9. Mem[4098]=0 10. R[1]=1024 11. R[2]=2048 12. R[3]=4096 13. R[4]=3 14. START at 1024 15. 1024: 16. ADD R_0 R_0 R_9 17. ADD R_0 R_0 R_10 18. loop: LOAD R_1 R_9 R_20 19. LOAD R_2 R_9 R_30 20. MUL R_20 R_30 R_20 21. ADD R_20 R_10 R_10 22. ADDI R_9 #1 R_9 23. IF< R_9 R_4 loop: 24. END DRisc parser: syntax error Fatal error: exception Parsing.Parse_error marcod@marcod-ThinkPad-X220:~/Documents/Didattica/Architetture/Drisc$
The error at the end is not an error.
Sample output (error):
marcod@marcod-ThinkPad-X220:~/Documents/Didattica/Architetture/Drisc$ ./parse err.drisc DRisc parser: syntax error Fatal error: exception Parsing.Parse_error marcod@marcod-ThinkPad-X220:~/Documents/Didattica/Architetture/Drisc$
drisc
drisc file steps
parses the program in file and executes (up to) steps instructions according to the control flow of the program
Sample output:
Programs$ ../drisc p1.drisc 100 =================== Scanned program source: 1. R[1]=2 2. R[2]=4 3. ADD R_1 R_2 R_3 4. END =================== Relocated program: 0 ADD R_1 R_2 R_3 1 END =================== Final program (labels compiled) 0 ADD R_1 R_2 R_3 1 END =================== Program starting at 0 -------------------------------------------------------------- PC:0 -------------------------------------------------------------- Register dump (10 per line) R0-9 0 2 4 0 0 0 0 0 0 0 R10-19 0 0 0 0 0 0 0 0 0 0 R20-29 0 0 0 0 0 0 0 0 0 0 R30-39 0 0 0 0 0 0 0 0 0 0 R40-49 0 0 0 0 0 0 0 0 0 0 R50-59 0 0 0 0 0 0 0 0 0 0 -------------------------------------------------------------- Memory dump -------------------------------------------------------------- 0 ADD R_1 R_2 R_3 1 END Executing instruction ==> 0: ADD R_1 R_2 R_3 -------------------------------------------------------------- PC:1 -------------------------------------------------------------- Register dump (10 per line) R0-9 0 2 4 6 0 0 0 0 0 0 R10-19 0 0 0 0 0 0 0 0 0 0 R20-29 0 0 0 0 0 0 0 0 0 0 R30-39 0 0 0 0 0 0 0 0 0 0 R40-49 0 0 0 0 0 0 0 0 0 0 R50-59 0 0 0 0 0 0 0 0 0 0 -------------------------------------------------------------- Memory dump -------------------------------------------------------------- Executing instruction ==> 1: END Fatal error: exception Interp.EndOfProgram marcod@marcod-ThinkPad-X220:~/Documents/Didattica/Architetture/Drisc/SamplePrograms$
Internals
The tools are organized in different parts, namely:
- lexer.mll hosts the lex source. In case an opcode is not recognized, look for a line such as
| "div" { DIV }
and in case there is no such line, add it to the file. The returned token (DIV, in this case, should be defined at the beginning of the parser.mly file
- parser.mly hosts the parser (grammar of the recognized drisc instructions). An unrecognized instruction needs a proper entry in the file
- asm.ml defines the internal datatypes, used to return parsed program and to manipulate them
- assembler.ml defines the functions needed to assemble the program from the source
- interp.ml hosts the interpreter of the compiled drisc instructions
As an example, in order to handle a STORE instruction:
- the datatype asm in asm.ml has lines such as
type asm = ... | Load of reg*reg*reg | Loadi of reg*const*reg | ...
* the lexer.mll recognises the load keyword as long as registers with the lines
rule token = parse ... | ['0'-'9']* as num { INT(int_of_string num) } ... | "load" { LOAD } | "LOAD" { LOAD } ... | "R" { REG }
* the parser.mly has productions such as
%token LOAD LOADI STORE STOREI ... main: program { $1 } ; program: END { [Instr(End)] } | anyinstr program { $1::$2 } ; anyinstr: LABEL COLON instr EOL { LabInstr(LabLab($1),$3) } | instr EOL { Instr($1) } | MEMVAL INT INT EOL { Instr(Memloc($2,$3))} | REGVAL INT INT EOL { Instr(Regval($2,$3))} instr: ... | LOAD reg COMMA reg COMMA reg { Load($2,$4,$6)} | LOADI reg COMMA imm COMMA reg { Loadi($2,$4,$6)} ...
* the interp.ml interprets the load as
let step i (Env(pc,m,r)) = match i with ... | Load(Reg(a),Reg(b),Reg(c)) -> let ind = !(r.(a)) + !(r.(b)) in r.(c) := (List.assoc ind !m); pc := !pc + 1 | Loadi(Reg(a),Const(b),Reg(c)) -> let ind = !(r.(a)) + b in r.(c) := (List.assoc ind !m); pc := !pc + 1
Example
This is the first example in Chapter V of [1].
start 1024 memloc 0 123 memloc 1 256 memloc 2 172 memloc 3 190 memloc 10 0 memloc 11 0 memloc 12 0 memloc 13 0 regval 1 0 regval 8 10 regval 2 0 regval 5 150 regval 6 200 regval 7 4 loc 1024 loop: load R1,R2,R3 if>= R3,R6,then2 if<= R3,R5,then1 move R3,R4 goto continua then1: move R5,R4 goto continua then2: move R6,R4 continua:store R8,R2,R4 incr R2 if< R2,R7,loop end
Known problems
There are several instructions not completely managed by the tools. In particular, conditional jumps. In case the tool does not work properly, please send the ASCII version of the drisc program not working with the tools to the professor, by email.
References
[1] M. Vanneschi, Architettura degli elaboratori, Edizioni Plus, 2009 (o seconda edizione 2013)