This commit is contained in:
Jaka Furlan 2025-11-30 13:53:18 +01:00
parent 61bb14b9e3
commit ad8728bdf4
19 changed files with 335 additions and 47 deletions

21
ass1/horner.log Normal file
View file

@ -0,0 +1,21 @@
***** Section <default> *****
Stats: size=61 blocks=61 symbols=10 literals=0 relocations=0
Blocks
name start size #ins #dir #sto
<default> 00000 0003D 16 8 1
Symbols
name hex dec scope kind type description
halt 000025 37 local relative code label
poly 000000 0 exported relative code label
rez 00003A 58 local relative data label
start 000000 0 local relative code label
x 000037 55 local relative data label
x0 000034 52 local relative data label
x1 000031 49 local relative data label
x2 00002E 46 local relative data label
x3 00002B 43 local relative data label
x4 000028 40 local relative data label
Literals
label definition
Relocations
address length flag symbol

38
ass1/horner.lst Normal file
View file

@ -0,0 +1,38 @@
00000 poly START 0
00000 772025 start LDT x4
00003 6F2031 LDS x
00006 9845 MULR S,T
00008 032020 LDA x3
0000B 9050 ADDR T,A . do sedaj izračunano (1x + 2)
0000D 77201E LDT x2
00010 9840 MULR S,A
00012 9050 ADDR T,A . do sedaj izračunano ((1x+2)x + 3)
00014 77201A LDT x1
00017 9840 MULR S,A
00019 9050 ADDR T,A . do sedaj izračunano (((1x+2)x + 3)x + 4)
0001B 772016 LDT x0
0001E 9840 MULR S,A
00020 9050 ADDR T,A . do sedaj izračunano (((1x+2)x + 3)x + 4)x + 5
00022 0F2015 STA rez
00025 3F2FFD halt J halt
00028 END start
. polinom
00028 000001 x4 WORD 1
0002B 000002 x3 WORD 2
0002E 000003 x2 WORD 3
00031 000004 x1 WORD 4
00034 000005 x0 WORD 5
. tocka
00037 000002 x WORD 2
. rezultat
0003A 000000 rez RESW 1

4
ass1/horner.obj Normal file
View file

@ -0,0 +1,4 @@
Hpoly 00000000003D
T0000001E7720256F20319845032020905077201E9840905077201A98409050772016
T00001E1C984090500F20153F2FFD000001000002000003000004000005000002
E000000

21
ass1/poly.log Normal file
View file

@ -0,0 +1,21 @@
***** Section <default> *****
Stats: size=70 blocks=70 symbols=10 literals=0 relocations=0
Blocks
name start size #ins #dir #sto
<default> 00000 00046 20 8 1
Symbols
name hex dec scope kind type description
halt 00002E 46 local relative code label
poly 000000 0 exported relative code label
rez 000043 67 local relative data label
start 000000 0 local relative code label
x 000040 64 local relative data label
x0 00003D 61 local relative data label
x1 00003A 58 local relative data label
x2 000037 55 local relative data label
x3 000034 52 local relative data label
x4 000031 49 local relative data label
Literals
label definition
Relocations
address length flag symbol

42
ass1/poly.lst Normal file
View file

@ -0,0 +1,42 @@
00000 poly START 0
00000 03203A start LDA x0 . pristejemo x0 v A
00003 6B203A LDB x
00006 6F2037 LDS x
00009 77202E LDT x1
0000C 9845 MULR S,T
0000E 9050 ADDR T,A . pristejemo x0 * x
00010 772024 LDT x2
00013 9834 MULR B,S . izracunamo x^2
00015 9845 MULR S,T
00017 9050 ADDR T,A
00019 772018 LDT x3
0001C 9834 MULR B,S . izracunamo x^3
0001E 9845 MULR S,T
00020 9050 ADDR T,A
00022 77200C LDT x4
00025 9834 MULR B,S . izracunamo x^4
00027 9845 MULR S,T
00029 9050 ADDR T,A
0002B 0F2015 STA rez
0002E 3F2FFD halt J halt
00031 END start
. polinom
00031 000001 x4 WORD 1
00034 000002 x3 WORD 2
00037 000003 x2 WORD 3
0003A 000004 x1 WORD 4
0003D 000005 x0 WORD 5
. tocka
00040 000002 x WORD 2
. rezultat
00043 000000 rez RESW 1

5
ass1/poly.obj Normal file
View file

@ -0,0 +1,5 @@
Hpoly 000000000046
T0000001E03203A6B203A6F203777202E984590507720249834984590507720189834
T00001E1E9845905077200C9834984590500F20153F2FFD0000010000020000030000
T00003C0704000005000002
E000000

4
ass1/test.asm Normal file
View file

@ -0,0 +1,4 @@
poly START 0
END poly
x1 WORD 1

13
ass1/test.log Normal file
View file

@ -0,0 +1,13 @@
***** Section <default> *****
Stats: size=3 blocks=3 symbols=2 literals=0 relocations=0
Blocks
name start size #ins #dir #sto
<default> 00000 00003 0 3 0
Symbols
name hex dec scope kind type description
poly 000000 0 exported relative code label
x1 000000 0 local relative data label
Literals
label definition
Relocations
address length flag symbol

4
ass1/test.lst Normal file
View file

@ -0,0 +1,4 @@
00000 poly START 0
00000 END poly
00000 000001 x1 WORD 1

3
ass1/test.obj Normal file
View file

@ -0,0 +1,3 @@
Hpoly 000000000003
T00000003000001
E000000

Binary file not shown.

Binary file not shown.

View file

@ -1,4 +1,10 @@
open OpcodeTable open OpcodeTable
open Processor
open IzvajalnikF1
open IzvajalnikF2
open IzvajalnikF3
open IzvajalnikF4
type nixbpe = { type nixbpe = {
n : int; n : int;

51
ass2/SICocaml/loader.ml Normal file
View file

@ -0,0 +1,51 @@
open Processor
open Printf
(* Convert hex string to int *)
let int_of_hex s = int_of_string ("0x" ^ s)
(* Convert two hex digits to a char *)
let char_of_hex s = Char.chr (int_of_hex s)
(* Write a list of bytes (chars) to memory at a given start address *)
let write_bytes state start bytes =
List.iteri (fun i byte -> Bytes.set state.memory (start + i) byte) bytes
(* Parse a T record line like: TAAAAAALL[BYTECODES...] *)
let parse_text_record line =
(* Skip leading 'T' *)
let line = String.sub line 1 (String.length line - 1) in
if String.length line < 8 then failwith "T record too short";
let start_str = String.sub line 0 6 in (*pridobi stolpce 2-7*)
let len_str = String.sub line 6 2 in (*pridobi stolpce 8-9*)
let start_addr = int_of_hex start_str in (*izračunaj star addr*)
let _ = int_of_hex len_str in (*izračunaj dolžino -> v bistvu je nikjer ne rabimo*)
let byte_str = String.sub line 8 (String.length line - 8) in (*pridobi stolpce 10-*)
(* Split the string into pairs of hex digits *)
let bytes =
let rec aux i acc =
if i >= String.length byte_str then List.rev acc (*ko si na koncu še obrni listo, ker si dodajal na začetek *)
else
let hex_pair = String.sub byte_str i 2 in (*pridobi par črk*)
aux (i + 2) (char_of_hex hex_pair :: acc) (*dodaj na začetek nov par*)
in
aux 0 []
in
(start_addr, bytes)
(* Load a SIC/XE object file into memory *)
let load_object_file (state : Processor.state) (filename : string) : unit =
let ic = open_in filename in
try
while true do
let line = input_line ic in
match line.[0] with
| 'T' ->
let addr, bytes = parse_text_record line in
write_bytes state addr bytes
| 'H' -> () (* header: can parse start addr/length if needed *)
| 'E' -> () (* end: can parse entry point if needed *)
| _ -> ()
done
with
| End_of_file -> close_in ic

View file

@ -1,37 +1,19 @@
(* test_execute.ml *) (* test_execute.ml *)
open Processor (* assuming your state, regs, and execute are defined here *) let regs = Processor.{a = 0; x = 0; l = 0; b = 0; s = 0; t = 0; f = 0.0; pc = 0; sw = 0}
let memSize = 1 lsl 20 (*2^20*)
let memory = Bytes.make memSize '\x00' (*mutbale kos pomnilnika velikosti memSize*)
let state = Processor.{regs; memory}
(* Test function *) (* Test function *)
let test_execute () = let test_runner () =
(* Create a dummy state *) let khz = 0.001 in
let mem_size = 1024 in Processor.print_memory state 50;
let memory = Bytes.make mem_size '\000' in Loader.load_object_file state "/mnt/c/Programiranje/SPO/ass1/horner.obj";
let regs = { Processor.print_memory state 50;
a = 0; b = 0; x = 0; l = 0; s = 0; t = 0; f = 0.0; Printf.printf "\n\n---Starting execution!---\n\n";
pc = 0; sw = 0 Pogajalnik.run state khz
} in
let state = { memory; regs } in
(* Example: Write a LDA instruction at address 0*)
Processor.write_instruction3 state 0 '\x01' '\x00' '\x23';
(* Write the operand value at 0x010 *)
Processor.writeMemAddr state 0x010 0x123456;
(* Set PC to 0 *)
state.regs.pc <- 0;
Printf.printf "Before execution:\n";
Processor.print_regs state;
Processor.print_memory state 15;
(* Execute instruction *)
Izvajalnik.execute state;
Printf.printf "After execution:\n";
Processor.print_regs state;
Processor.print_memory state 15
(* Run the test *) (* Run the test *)
let () = test_execute () let () = test_runner ()

View file

@ -1,3 +1,4 @@
(library (library
(name sicxeDune) (name sicxeDune)
(wrapped false)) (wrapped false)
(libraries unix))

View file

@ -1,4 +1,5 @@
open OpcodeTable open OpcodeTable
open Processor
type nixbpe = { type nixbpe = {
n : int; n : int;
@ -12,14 +13,6 @@ type nixbpe = {
let string_of_nixbpe nixbpe = let string_of_nixbpe nixbpe =
Printf.sprintf "n=%d,i=%d,x=%d,b=%d,p=%d,e=%d" Printf.sprintf "n=%d,i=%d,x=%d,b=%d,p=%d,e=%d"
nixbpe.n nixbpe.i nixbpe.x nixbpe.b nixbpe.p nixbpe.e nixbpe.n nixbpe.i nixbpe.x nixbpe.b nixbpe.p nixbpe.e
(*kreiramo začetno stanje -> TODO prestavi v main*)
let regs = Processor.{a = 0; x = 0; l = 0; b = 0; s = 0; t = 0; f = 0.0; pc = 0; sw = 0}
let memSize = 1 lsl 20 (*2^20*)
let memory = Bytes.make memSize '\x00' (*mutbale kos pomnilnika velikosti memSize*)
let state = Processor.{regs; memory}
(*----Funkcije izvajalnika----*) (*----Funkcije izvajalnika----*)
(*TODO - brali bomo vedno relativno od začetka instrukcije, PC bomo na koncu ukaza povečali za pravo velikost!*) (*TODO - brali bomo vedno relativno od začetka instrukcije, PC bomo na koncu ukaza povečali za pravo velikost!*)
@ -56,7 +49,10 @@ let readDisp (state : Processor.state) : int =
let byte2 = Char.code (Processor.readMem state 1) in let byte2 = Char.code (Processor.readMem state 1) in
let byte3 = Char.code (Processor.readMem state 2) in let byte3 = Char.code (Processor.readMem state 2) in
let disp_high = byte2 land 0x0F in let disp_high = byte2 land 0x0F in
let disp = (disp_high lsl 8) lor byte3 in let disp_low = byte3 in
let disp = (disp_high lsl 8) lor disp_low in
let hex_string = Printf.sprintf "%02X%02X" disp_high disp_low in
Printf.printf "[Izvajalnik/readDisp]prebral disp: 0x%s = 0x%04X = %d\n" hex_string disp disp;
disp disp
(*dobi address iz tip ukaza 4*) (*dobi address iz tip ukaza 4*)
@ -72,13 +68,31 @@ let readAddress (state : Processor.state) : int =
address address
(*pridobi operand*) (*pridobi operand*)
let getOperand (state : Processor.state) (nixbpe : nixbpe) (disp : int) : int = let getOperandF3 (state : Processor.state) (nixbpe : nixbpe) (disp : int) : int =
let ea = let ea =
if nixbpe.b = 1 && nixbpe.p = 0 then state.regs.b + disp (*B relativno*) if nixbpe.b = 1 && nixbpe.p = 0 then state.regs.b + disp (*B relativno*)
else if nixbpe.p = 1 && nixbpe.b = 0 then state.regs.pc + disp (*PC relativno*) else if nixbpe.p = 1 && nixbpe.b = 0 then state.regs.pc + disp + 3(*PC relativno, ker PC povečamo šele po klicu te funkcije moramo tu +3*)
else disp (*direktno*) else disp (*direktno*)
in in
let ea = if nixbpe.x = 1 then ea + state.regs.x else ea in (*+ (X) po potrebi*) let ea = if nixbpe.x = 1 then ea + state.regs.x else ea in (*+ (X) po potrebi*)
Printf.printf "[Izvajalnik/getOperand]effective address: 0x%06X = %d\n" ea ea;
(*pridobi operand*)
let value =
if nixbpe.n = 1 && nixbpe.i = 1 then Processor.readMemAddr state ea (*direktno*)
else if nixbpe.n = 0 && nixbpe.i = 1 then disp (* immediate value *)
else if nixbpe.n = 1 && nixbpe.i = 0 then Processor.readMemAddr state (Processor.readMemAddr state ea) (* indirect *)
else failwith "Invalid addressing mode"
in
value
let getOperandF4 (state : Processor.state) (nixbpe : nixbpe) (disp : int) : int =
let ea =
if nixbpe.b = 1 && nixbpe.p = 0 then state.regs.b + disp (*B relativno*)
else if nixbpe.p = 1 && nixbpe.b = 0 then state.regs.pc + disp + 4(*PC relativno, ker PC povečamo šele po klicu te funkcije moramo tu +4*)
else disp (*direktno*)
in
let ea = if nixbpe.x = 1 then ea + state.regs.x else ea in (*+ (X) po potrebi*)
Printf.printf "[Izvajalnik/getOperand]effective address: 0x%06X = %d\n" ea ea;
(*pridobi operand*) (*pridobi operand*)
let value = let value =
if nixbpe.n = 1 && nixbpe.i = 1 then Processor.readMemAddr state ea (*direktno*) if nixbpe.n = 1 && nixbpe.i = 1 then Processor.readMemAddr state ea (*direktno*)
@ -133,7 +147,7 @@ let executeFormat2 (state: Processor.state) (mnemonic : OpcodeTable.mnemonic) :
(*execute Format 3*) (*execute Format 3*)
let executeFormat3 (state : Processor.state) (nixbpe : nixbpe) (mnemonic: OpcodeTable.mnemonic): unit = let executeFormat3 (state : Processor.state) (nixbpe : nixbpe) (mnemonic: OpcodeTable.mnemonic): unit =
let disp = readDisp state in let disp = readDisp state in
let operand = getOperand state nixbpe disp in let operand = getOperandF3 state nixbpe disp in
(*debugging*) (*debugging*)
Printf.printf "[Izvajalnik/executeFormat3] Mnemonic: %s, nixbpe: %s, operand: %d = 0x%02X\n" Printf.printf "[Izvajalnik/executeFormat3] Mnemonic: %s, nixbpe: %s, operand: %d = 0x%02X\n"
(string_of_mnemonic mnemonic) (string_of_nixbpe nixbpe) operand operand; (string_of_mnemonic mnemonic) (string_of_nixbpe nixbpe) operand operand;
@ -188,12 +202,12 @@ let executeFormat3 (state : Processor.state) (nixbpe : nixbpe) (mnemonic: Opcode
let executeFormat4 (state : Processor.state) (nixbpe : nixbpe) (mnemonic: OpcodeTable.mnemonic): unit = let executeFormat4 (state : Processor.state) (nixbpe : nixbpe) (mnemonic: OpcodeTable.mnemonic): unit =
let address = readAddress state in let address = readAddress state in
let operand = getOperand state nixbpe address in let operand = getOperandF4 state nixbpe address in
(*debugging*) (*debugging*)
Printf.printf "[Izvajalnik/executeFormat4] Mnemonic: %s, nixbpe: %s, operand: %d = 0x%02X\n" Printf.printf "[Izvajalnik/executeFormat4] Mnemonic: %s, nixbpe: %s, operand: %d = 0x%02X\n"
(string_of_mnemonic mnemonic) (string_of_nixbpe nixbpe) operand operand; (string_of_mnemonic mnemonic) (string_of_nixbpe nixbpe) operand operand;
Processor.pcIncrement state 3; Processor.pcIncrement state 4;
match mnemonic with match mnemonic with
| ADD -> IzvajalnikF4.add state operand | ADD -> IzvajalnikF4.add state operand
| ADDF -> notImplemented "ADDF3" | ADDF -> notImplemented "ADDF3"

View file

@ -0,0 +1,49 @@
open Processor
(* Convert hex string to int *)
let int_of_hex s = int_of_string ("0x" ^ s)
(* Convert two hex digits to a char *)
let char_of_hex s = Char.chr (int_of_hex s)
(* Write a list of bytes (chars) to memory at a given start address *)
let write_bytes state start bytes =
List.iteri (fun i byte -> Bytes.set state.memory (start + i) byte) bytes
(* Parse a T record line like: TAAAAAALL[BYTECODES...] *)
let parse_text_record line =
(* Skip leading 'T' *)
let line = String.sub line 1 (String.length line - 1) in
if String.length line < 8 then failwith "T record too short";
let start_str = String.sub line 0 6 in (*pridobi stolpce 2-7*)
let len_str = String.sub line 6 2 in (*pridobi stolpce 8-9*)
let start_addr = int_of_hex start_str in (*izračunaj star addr*)
let _ = int_of_hex len_str in (*izračunaj dolžino -> v bistvu je nikjer ne rabimo*)
let byte_str = String.sub line 8 (String.length line - 8) in (*pridobi stolpce 10-*)
(* Split the string into pairs of hex digits *)
let bytes =
let rec aux i acc =
if i >= String.length byte_str then List.rev acc (*ko si na koncu še obrni listo, ker si dodajal na začetek *)
else
let hex_pair = String.sub byte_str i 2 in (*pridobi par črk*)
aux (i + 2) (char_of_hex hex_pair :: acc) (*dodaj na začetek nov par*)
in
aux 0 []
in
(start_addr, bytes)
(* Load a SIC/XE object file into memory *)
let load_object_file (state : Processor.state) (filename : string) : unit =
let ic = open_in filename in
try
while true do
let line = input_line ic in
match line.[0] with
| 'T' ->
let addr, bytes = parse_text_record line in
write_bytes state addr bytes
| 'H' -> () (* header: can parse start addr/length if needed *)
| 'E' -> () (* end: can parse entry point if needed *)
| _ -> ()
done
with
| End_of_file -> close_in ic

View file

@ -0,0 +1,30 @@
(*pogajalnik bo izvajal exekucijo eno za drugo*)
let run (state : Processor.state) (khz : float) : unit =
let perioda_sekunde = 1.0 /. (khz *. 1000.0) in
let rec loop state last_pc count=
(*izvedi ukaz*)
Izvajalnik.execute state;
(*printni stanje*)
Printf.printf "After execution:\n";
Processor.print_regs state;
Processor.print_memory state 50;
flush stdout;
(*spi*)
Unix.sleepf perioda_sekunde;(*mogoče spremeni na time of day approach , da se izogneš driftu*)
(*preveri ali je PC obtičan na istem mestu*)
let current_pc = state.regs.pc in
let count, last_pc =
if current_pc = last_pc then (count + 1, last_pc)
else (1, current_pc)
in
(*Nehaj rekurzijo če je PC 5x na istem mestu*)
if count >= 5 then
Printf.printf "PC stuck at 0x%X 5 times. Ending loop.\n" current_pc
else
loop state last_pc count
in loop state state.regs.pc 0