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

View file

@ -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 ()

View file

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

View file

@ -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"

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