diff --git a/ass1/horner.log b/ass1/horner.log new file mode 100644 index 0000000..7f6c11d --- /dev/null +++ b/ass1/horner.log @@ -0,0 +1,21 @@ +***** Section ***** +Stats: size=61 blocks=61 symbols=10 literals=0 relocations=0 +Blocks + name start size #ins #dir #sto + 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 diff --git a/ass1/horner.lst b/ass1/horner.lst new file mode 100644 index 0000000..4bb467e --- /dev/null +++ b/ass1/horner.lst @@ -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 diff --git a/ass1/horner.obj b/ass1/horner.obj new file mode 100644 index 0000000..5c396f6 --- /dev/null +++ b/ass1/horner.obj @@ -0,0 +1,4 @@ +Hpoly 00000000003D +T0000001E7720256F20319845032020905077201E9840905077201A98409050772016 +T00001E1C984090500F20153F2FFD000001000002000003000004000005000002 +E000000 diff --git a/ass1/poly.log b/ass1/poly.log new file mode 100644 index 0000000..03eea94 --- /dev/null +++ b/ass1/poly.log @@ -0,0 +1,21 @@ +***** Section ***** +Stats: size=70 blocks=70 symbols=10 literals=0 relocations=0 +Blocks + name start size #ins #dir #sto + 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 diff --git a/ass1/poly.lst b/ass1/poly.lst new file mode 100644 index 0000000..3db26df --- /dev/null +++ b/ass1/poly.lst @@ -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 diff --git a/ass1/poly.obj b/ass1/poly.obj new file mode 100644 index 0000000..ab21bac --- /dev/null +++ b/ass1/poly.obj @@ -0,0 +1,5 @@ +Hpoly 000000000046 +T0000001E03203A6B203A6F203777202E984590507720249834984590507720189834 +T00001E1E9845905077200C9834984590500F20153F2FFD0000010000020000030000 +T00003C0704000005000002 +E000000 diff --git a/ass1/test.asm b/ass1/test.asm new file mode 100644 index 0000000..6a588f4 --- /dev/null +++ b/ass1/test.asm @@ -0,0 +1,4 @@ +poly START 0 + END poly + +x1 WORD 1 diff --git a/ass1/test.log b/ass1/test.log new file mode 100644 index 0000000..73e0a7b --- /dev/null +++ b/ass1/test.log @@ -0,0 +1,13 @@ +***** Section ***** +Stats: size=3 blocks=3 symbols=2 literals=0 relocations=0 +Blocks + name start size #ins #dir #sto + 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 diff --git a/ass1/test.lst b/ass1/test.lst new file mode 100644 index 0000000..ad6bbb8 --- /dev/null +++ b/ass1/test.lst @@ -0,0 +1,4 @@ +00000 poly START 0 +00000 END poly + +00000 000001 x1 WORD 1 diff --git a/ass1/test.obj b/ass1/test.obj new file mode 100644 index 0000000..bbd9486 --- /dev/null +++ b/ass1/test.obj @@ -0,0 +1,3 @@ +Hpoly 000000000003 +T00000003000001 +E000000 diff --git a/ass2/SICocaml/izvajalnik.cmi b/ass2/SICocaml/izvajalnik.cmi index 9627cf1..792e3f7 100644 Binary files a/ass2/SICocaml/izvajalnik.cmi and b/ass2/SICocaml/izvajalnik.cmi differ diff --git a/ass2/SICocaml/izvajalnik.cmo b/ass2/SICocaml/izvajalnik.cmo index c0d8363..908611c 100644 Binary files a/ass2/SICocaml/izvajalnik.cmo and b/ass2/SICocaml/izvajalnik.cmo differ diff --git a/ass2/SICocaml/izvajalnik.ml b/ass2/SICocaml/izvajalnik.ml index 1ff702c..ed685f2 100644 --- a/ass2/SICocaml/izvajalnik.ml +++ b/ass2/SICocaml/izvajalnik.ml @@ -1,4 +1,10 @@ -open OpcodeTable +open OpcodeTable +open Processor +open IzvajalnikF1 +open IzvajalnikF2 +open IzvajalnikF3 +open IzvajalnikF4 + type nixbpe = { n : int; diff --git a/ass2/SICocaml/loader.ml b/ass2/SICocaml/loader.ml new file mode 100644 index 0000000..7c3d990 --- /dev/null +++ b/ass2/SICocaml/loader.ml @@ -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 diff --git a/ass2/SICocaml/sicxeDune/bin/main.ml b/ass2/SICocaml/sicxeDune/bin/main.ml index d3231ef..e6e4c5e 100644 --- a/ass2/SICocaml/sicxeDune/bin/main.ml +++ b/ass2/SICocaml/sicxeDune/bin/main.ml @@ -1,37 +1,19 @@ (* 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 *) -let test_execute () = - (* Create a dummy state *) - let mem_size = 1024 in - let memory = Bytes.make mem_size '\000' in - let regs = { - a = 0; b = 0; x = 0; l = 0; s = 0; t = 0; f = 0.0; - pc = 0; sw = 0 - } in - let state = { memory; regs } in +let test_runner () = + let khz = 0.001 in + Processor.print_memory state 50; + Loader.load_object_file state "/mnt/c/Programiranje/SPO/ass1/horner.obj"; + Processor.print_memory state 50; + Printf.printf "\n\n---Starting execution!---\n\n"; + Pogajalnik.run state khz - (* 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 *) -let () = test_execute () +let () = test_runner () \ No newline at end of file diff --git a/ass2/SICocaml/sicxeDune/lib/dune b/ass2/SICocaml/sicxeDune/lib/dune index 2f1c957..039bb16 100644 --- a/ass2/SICocaml/sicxeDune/lib/dune +++ b/ass2/SICocaml/sicxeDune/lib/dune @@ -1,3 +1,4 @@ (library (name sicxeDune) - (wrapped false)) + (wrapped false) + (libraries unix)) diff --git a/ass2/SICocaml/sicxeDune/lib/izvajalnik.ml b/ass2/SICocaml/sicxeDune/lib/izvajalnik.ml index 1ff702c..afef4c1 100644 --- a/ass2/SICocaml/sicxeDune/lib/izvajalnik.ml +++ b/ass2/SICocaml/sicxeDune/lib/izvajalnik.ml @@ -1,4 +1,5 @@ -open OpcodeTable +open OpcodeTable +open Processor type nixbpe = { n : int; @@ -12,14 +13,6 @@ type nixbpe = { let string_of_nixbpe nixbpe = 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 - -(*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----*) (*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 byte3 = Char.code (Processor.readMem state 2) 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 (*dobi address iz tip ukaza 4*) @@ -72,13 +68,31 @@ let readAddress (state : Processor.state) : int = address (*pridobi operand*) -let getOperand (state : Processor.state) (nixbpe : nixbpe) (disp : int) : int = +let getOperandF3 (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 (*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*) 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*) + 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*) let value = 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*) let executeFormat3 (state : Processor.state) (nixbpe : nixbpe) (mnemonic: OpcodeTable.mnemonic): unit = let disp = readDisp state in - let operand = getOperand state nixbpe disp in + let operand = getOperandF3 state nixbpe disp in (*debugging*) Printf.printf "[Izvajalnik/executeFormat3] Mnemonic: %s, nixbpe: %s, operand: %d = 0x%02X\n" (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 address = readAddress state in - let operand = getOperand state nixbpe address in + let operand = getOperandF4 state nixbpe address in (*debugging*) Printf.printf "[Izvajalnik/executeFormat4] Mnemonic: %s, nixbpe: %s, operand: %d = 0x%02X\n" (string_of_mnemonic mnemonic) (string_of_nixbpe nixbpe) operand operand; - Processor.pcIncrement state 3; + Processor.pcIncrement state 4; match mnemonic with | ADD -> IzvajalnikF4.add state operand | ADDF -> notImplemented "ADDF3" diff --git a/ass2/SICocaml/sicxeDune/lib/loader.ml b/ass2/SICocaml/sicxeDune/lib/loader.ml new file mode 100644 index 0000000..0f67c8a --- /dev/null +++ b/ass2/SICocaml/sicxeDune/lib/loader.ml @@ -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 diff --git a/ass2/SICocaml/sicxeDune/lib/pogajalnik.ml b/ass2/SICocaml/sicxeDune/lib/pogajalnik.ml new file mode 100644 index 0000000..d7c493d --- /dev/null +++ b/ass2/SICocaml/sicxeDune/lib/pogajalnik.ml @@ -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 \ No newline at end of file