diff --git a/src/simudator/core/module.py b/src/simudator/core/module.py index d97eb36fb0d061dd33fec136d3a7520dade0a3d0..b7da1ff1246b090aa4e6aa2faa5388eb09bef596 100644 --- a/src/simudator/core/module.py +++ b/src/simudator/core/module.py @@ -64,7 +64,7 @@ class Module: def get_output_signals(self) -> list[Signal]: """ - Returns the modules output signals. Assumes all output signals are + Returns the modules output signals. Assumes all output signals are stored with a key beginning in 'out' in the signals dictionary. """ return [signal for key, signal in self.signals.items() if key[0:3] == "out"] @@ -84,8 +84,9 @@ class Module: def load_from_str(self, state_string): """ - Sets the moudles state according to a string - Each module type will decide how the string should be formated. + Sets the modules state according to a string. + + Each module class will parse and set its own state. """ raise NotImplemented @@ -115,10 +116,25 @@ class Module: """ print(self.name) + def _helper_save_state_to_file(self, file_path: str, content="") -> bool: + """ + Tries to save the content to a given file. + + Returns true on success and false otherwise. + """ + try: + with open(file_path, "a") as file: + file.write(content) + file.close() + except OSError: + return False + return True + def save_state_to_file(self, file_path: str) -> bool: """ - Tries to save the modules state to a given file. - Returns true on success and false if something went wrong. + Tries to save the module state to a given file. + + Returns true on success and false otherwise. """ raise NotImplemented diff --git a/src/simudator/core/modules/demux.py b/src/simudator/core/modules/demux.py index bdd0ff671c96946202aa772f4295fef9bc88c916..d7f47a20dd88a4162bbb29ce7e6210cab9ff0d27 100644 --- a/src/simudator/core/modules/demux.py +++ b/src/simudator/core/modules/demux.py @@ -11,9 +11,15 @@ class Demux(Module): signal 'from_demux_s'. """ - def __init__(self, control: Signal, bit_length: int, - input: Signal, outputs: list[Signal] = [], - name="demux", value=0) -> None: + def __init__( + self, + control: Signal, + bit_length: int, + input: Signal, + outputs: list[Signal] = [], + name="demux", + value=0, + ) -> None: # Signals signals = { @@ -27,7 +33,7 @@ class Demux(Module): # mask and bit_length self.bit_length = bit_length - self.mask = 2**self.bit_length -1 + self.mask = 2**self.bit_length - 1 # Value to be read/written self.value = value @@ -39,7 +45,6 @@ class Demux(Module): input_value = self.signals["in_input"].get_value() self.value = input_value & self.mask - def output_register(self): """ Read which signal to write to from the control signal @@ -66,6 +71,12 @@ class Demux(Module): return state + def save_state_to_file(self, file_path: str) -> bool: + """ + The demux has no state to save. + """ + return True + def set_state(self, state: dict) -> None: """ Sets the name and value of the demux. diff --git a/src/simudator/core/modules/memory.py b/src/simudator/core/modules/memory.py index 775f76f2b3773014e89cf69010ce0e4047117cea..d7fc4dce7a659003abfbaf34cfedce21c87357d1 100644 --- a/src/simudator/core/modules/memory.py +++ b/src/simudator/core/modules/memory.py @@ -119,18 +119,12 @@ class Memory(Module): """ return len(str(len(self.memory))) - def save_state_to_file(self, file_path: str) -> None: - """ - Tries to save the modules state to a given file. - """ - file = open(file_path, "a") - file.write(self.name + ":\n") + def save_state_to_file(self, file_path: str) -> bool: + content = "" + content = self.name + ":\n" for index, value in enumerate(self.memory): - # Write the address in hex and add ': ' to the end - file.write(hex(index)[2:].rjust(self.address_padding, "0") + ": ") - # Write the value in hex - file.write(hex(value)[2:].rjust(self.value_padding, "0")) - file.write("\n") - - file.write("\n") - file.close() + content += str(hex(index)[2:].rjust(self.address_padding, "0")) + ": " + content += str(hex(value)[2:].rjust(self.value_padding, "0")) + content += "\n" + content += "\n" + return super()._helper_save_state_to_file(file_path, content) diff --git a/src/simudator/core/modules/mux.py b/src/simudator/core/modules/mux.py index 0d50b4463323740d3f8d9e7b4d6fb529ea1e06e5..db5a5b40bd777bc11164437729c3943296a27ddb 100644 --- a/src/simudator/core/modules/mux.py +++ b/src/simudator/core/modules/mux.py @@ -11,14 +11,15 @@ class Mux(Module): signal 'to_mux_s'. """ - def __init__(self, - to_mux: Signal, - bit_length: int, - output: Signal, - inputs: list[Signal] = [], - name="mux", - value=0 - ) -> None: + def __init__( + self, + to_mux: Signal, + bit_length: int, + output: Signal, + inputs: list[Signal] = [], + name="mux", + value=0, + ) -> None: # Signals signals = { @@ -33,7 +34,7 @@ class Mux(Module): # mask and bit_length self.bit_length = bit_length - self.mask = 2**self.bit_length -1 + self.mask = 2**self.bit_length - 1 # Value to be read/written self.value = value @@ -71,6 +72,10 @@ class Mux(Module): return state + def save_state_to_file(self, file_path: str) -> bool: + content = self.name + ":\nvalue: " + str(self.value) + "\n\n" + return super()._helper_save_state_to_file(file_path, content) + def set_state(self, state: dict) -> None: """ Sets the name and value of the mux. @@ -81,8 +86,13 @@ class Mux(Module): self.mask = state["mask"] def print_module(self) -> None: - print(self.name, "\n-----", - "\nvalue: ", self.value, - "\nbit length: ", self.bit_length, - "\nmask: ", self.mask, - ) + print( + self.name, + "\n-----", + "\nvalue: ", + self.value, + "\nbit length: ", + self.bit_length, + "\nmask: ", + self.mask, + ) diff --git a/src/simudator/core/modules/register.py b/src/simudator/core/modules/register.py index f76219ce219ce12588744dbbb91708dbbdd6da7c..d729b948a18d1a56b7576837f80e8c3e7cd6d562 100644 --- a/src/simudator/core/modules/register.py +++ b/src/simudator/core/modules/register.py @@ -11,14 +11,18 @@ class Register(Module): A simple module that can store a value. """ - def __init__(self, input_signal: Signal, - output_signal: Signal, - value: Any = 0, name: str = "Register") -> None: + def __init__( + self, + input_signal: Signal, + output_signal: Signal, + value: Any = 0, + name: str = "Register", + ) -> None: # signals signals = { - "in_content": input_signal, - "out_content": output_signal, + "in_content": input_signal, + "out_content": output_signal, } # init the instance @@ -75,20 +79,18 @@ class Register(Module): """ self.value = 0 - def save_state_to_file(self, file_path: str) -> None: - """ - Tries to save the modules state to a given file. - Returns true on success and false if something went wrong. - """ - file = open(file_path, "a") - file.write(self.name + ":\n") - file.write("value: " + str(self.value) + "\n\n") - file.close() + def save_state_to_file(self, file_path: str) -> bool: + content = self.name + ":\nvalue:: " + str(self.value) + "\n\n" + return super()._helper_save_state_to_file(file_path, content) def print_module(self) -> None: - print("", self.name, "\n -----", - "\n value: ", self.value, - ) + print( + "", + self.name, + "\n -----", + "\n value: ", + self.value, + ) class IntegerRegister(Register): @@ -96,8 +98,14 @@ class IntegerRegister(Register): A simple module that can store an integer value with a given bit-length. """ - def __init__(self, input_signal: Signal, output_signal: Signal, - bit_length: int, value: int = 0, name: str | None = None) -> None: + def __init__( + self, + input_signal: Signal, + output_signal: Signal, + bit_length: int, + value: int = 0, + name: str | None = None, + ) -> None: # set the registers name if name is None: @@ -136,20 +144,15 @@ class IntegerRegister(Register): super().set_state(state) if "bit_length" in state: self.bit_length = state["bit_length"] - self.mask = 2**self.bit_length -1 + self.mask = 2**self.bit_length - 1 - def save_state_to_file(self, file_path: str) -> None: - """ - Tries to save the modules state to a given file. - """ - file = open(file_path, "a") - file.write(self.name + ":\n") - file.write("value: " + hex(self.value)[2:] + "\n\n") - file.close() + def save_state_to_file(self, file_path: str) -> bool: + content = self.name + ":\nvalue: " + hex(self.value)[2:] + "\n\n" + return super()._helper_save_state_to_file(file_path, content) def load_from_str(self, state_string): string_pair = state_string.split(": ") - #TODO: Maybe check if it starts with value: ? + # TODO: Maybe check if it starts with value: ? self.value = int(string_pair[1], 16) @@ -159,12 +162,23 @@ class Flag(IntegerRegister): updated during the 'update logic' phase. """ - def __init__(self, input_signal: Signal, output_signal: Signal, - bit_length=1, value=0, name="Flag") -> None: + def __init__( + self, + input_signal: Signal, + output_signal: Signal, + bit_length=1, + value=0, + name="Flag", + ) -> None: # set the flags name - super().__init__(input_signal=input_signal, output_signal=output_signal, - bit_length=bit_length, value=value, name=name) + super().__init__( + input_signal=input_signal, + output_signal=output_signal, + bit_length=bit_length, + value=value, + name=name, + ) def update_logic(self): """ @@ -181,18 +195,19 @@ class Flag(IntegerRegister): state["value"] = self.value return state - def save_state_to_file(self, file_path: str) -> None: - """ - Tries to save the modules state to a given file. - """ - file = open(file_path, "a") - file.write(self.name + ":\n") - file.write("value: " + str(self.value) + "\n\n") - file.close() + def save_state_to_file(self, file_path: str) -> bool: + content = self.name + ":\nvalue: " + str(self.value) + "\n\n" + return super()._helper_save_state_to_file(file_path, content) def print_module(self) -> None: - print("", self.name, "\n -----", - "\n value: ", self.value, - "\n bit length: ", self.bit_length, - "\n mask: ", self.mask, - ) + print( + "", + self.name, + "\n -----", + "\n value: ", + self.value, + "\n bit length: ", + self.bit_length, + "\n mask: ", + self.mask, + ) diff --git a/src/simudator/core/processor.py b/src/simudator/core/processor.py index bb33eb9f836ef8c14247bf4440ce1e1fa7c5be5a..3e253fa407c8e286c706211200c028b9cee022a0 100644 --- a/src/simudator/core/processor.py +++ b/src/simudator/core/processor.py @@ -406,7 +406,6 @@ class Processor: file.close() for module in self.modules.values(): - print(module) module.save_state_to_file(file_path) def pretty_print(self) -> None: diff --git a/src/simudator/processor/mia/modules/alu.py b/src/simudator/processor/mia/modules/alu.py index 47ca0571e49bee3434230e20639cb674f91cab93..edb4eb6e328533db4d16436783191c0a2167b41f 100644 --- a/src/simudator/processor/mia/modules/alu.py +++ b/src/simudator/processor/mia/modules/alu.py @@ -68,7 +68,7 @@ class ALU(Module): def save_state_to_file(self, file_path: str) -> bool: """ - The ali is state-less. + The alu is state-less. """ return True diff --git a/src/simudator/processor/mia/modules/bus.py b/src/simudator/processor/mia/modules/bus.py index 4325b6dbbe5048e14ae14dfad1a2b84647e9a99f..71125ffb384ae3dee8f19727857f5320992e5e17 100644 --- a/src/simudator/processor/mia/modules/bus.py +++ b/src/simudator/processor/mia/modules/bus.py @@ -71,6 +71,6 @@ class Bus(Module): def save_state_to_file(self, file_path: str) -> bool: """ - The ali is state-less. + The bus is state-less. """ return True diff --git a/src/simudator/processor/mia/modules/ir.py b/src/simudator/processor/mia/modules/ir.py index c3224a8adbd1ef68692e604e7f2e897becafba64..57cd353f83cba08b8ade4e2ebdc8ca0cefc0ac56 100644 --- a/src/simudator/processor/mia/modules/ir.py +++ b/src/simudator/processor/mia/modules/ir.py @@ -128,17 +128,15 @@ class IR(Module, MiaBusConnector): bin(self.a), ) - def save_state_to_file(self, file_path: str) -> None: + def save_state_to_file(self, file_path: str) -> bool: """ Tries to save the modules state to a given file. """ - file = open(file_path, "a") - file.write(self.name + ":\n") - file.write("Instruction: " + hex(self.instruction)[2:] + "\n\n") - file.close() + content = self.name + ":\n" + content += "Instruction: " + hex(self.instruction)[2:] + "\n\n" + return super()._helper_save_state_to_file(file_path, content) def load_from_str(self, state_string): string_pair = state_string.split(": ") # TODO: Maybe check if it starts with instruction: ? self.instruction = int(string_pair[1], 16) - diff --git a/src/simudator/processor/mia/modules/lc.py b/src/simudator/processor/mia/modules/lc.py index 15e1598df7c809b62dabda12014548c85df77172..3202506e6e64e1b2486929df94d51b7b8a2f59b7 100644 --- a/src/simudator/processor/mia/modules/lc.py +++ b/src/simudator/processor/mia/modules/lc.py @@ -50,7 +50,6 @@ class LC(Module): Optional bit length of the loop counter. """ - # signals signals = { "in_control": mM_control, @@ -174,12 +173,10 @@ class LC(Module): self.read_from_uADR = False self.decrement_by_one = False - def save_state_to_file(self, file_path: str) -> None: - """Tries to save the modules state to a given file.""" - file = open(file_path, "a") - file.write(self.name + ":\n") - file.write("value: " + hex(self.value)[2:] + "\n\n") - file.close() + def save_state_to_file(self, file_path: str) -> bool: + content = self.name + ":\n" + content += "value: " + hex(self.value)[2:] + "\n\n" + return super()._helper_save_state_to_file(file_path, content) def load_from_str(self, state_string): string_pair = state_string.split(": ") @@ -200,4 +197,3 @@ class LC(Module): "\n read from bus: ", self.read_from_bus, ) - diff --git a/src/simudator/processor/mia/modules/mia_grx.py b/src/simudator/processor/mia/modules/mia_grx.py index 414bcb9aa6f32f25d2c0ca12f2ad4b9919423c21..c139d2cd887929e5b046670916efa90da72e2a91 100644 --- a/src/simudator/processor/mia/modules/mia_grx.py +++ b/src/simudator/processor/mia/modules/mia_grx.py @@ -30,7 +30,6 @@ class GRX(Module, MiaBusConnector): # Set connection to/from bus and bus_id MiaBusConnector.__init__(self, bus_control, bus_id) - # Other signals signals = { "in_input": from_bus, @@ -126,20 +125,15 @@ class GRX(Module, MiaBusConnector): for i in range(len(self.registers)): self.registers[i] = 0 - def save_state_to_file(self, file_path: str) -> None: - """ - Tries to save the modules state to a given file. - Returns true on success and false if something went wrong. - """ - file = open(file_path, "a") - file.write(self.name + ":\n") + def save_state_to_file(self, file_path: str) -> bool: + content = self.name + ":\n" for index, value in enumerate(self.registers): - file.write(hex(index)[2:] + ": ") - file.write(hex(value)[2:]) - file.write("\n") + content += str(hex(index)[2:]) + ": " + content += str(hex(value)[2:]) + content += "\n" - file.write("\n") - file.close() + content += "\n" + return super()._helper_save_state_to_file(file_path, content) def load_from_str(self, state_string) -> None: """ @@ -173,4 +167,3 @@ class GRX(Module, MiaBusConnector): "\n GR3: ", hex(self.registers[3]), ) - diff --git a/src/simudator/processor/mia/modules/micro_memory.py b/src/simudator/processor/mia/modules/micro_memory.py index 8915c5ed2f7ae4d51dd2cd7f5c22400f812fe1af..a6ffb3e41a2886943f3de73cc21699933afa1569 100644 --- a/src/simudator/processor/mia/modules/micro_memory.py +++ b/src/simudator/processor/mia/modules/micro_memory.py @@ -81,7 +81,6 @@ class MicroMemory(Module): None """ - signals = { "in_upc": upc, "in_flag_z": z_flag, @@ -331,19 +330,15 @@ class MicroMemory(Module): value = int(line_data[1], 16) self.memory[address] = value - def save_state_to_file(self, file_path: str) -> None: - """Tries to save the modules state to a given file.""" - file = open(file_path, "a") - file.write(self.name + ":\n") + def save_state_to_file(self, file_path: str) -> bool: + content = self.name + ":\n" for index, value in enumerate(self.memory): - # Write the address in hex and add ': ' to the end - file.write(hex(index)[2:].rjust(self.address_padding, "0") + ": ") - # Write the value in hex - file.write(hex(value)[2:].rjust(self.value_padding, "0")) - file.write("\n") + content += str(hex(index)[2:].rjust(self.address_padding, "0")) + ": " + content += str(hex(value)[2:].rjust(self.value_padding, "0")) + content += "\n" - file.write("\n") - file.close() + content += "\n" + return super()._helper_save_state_to_file(file_path, content) def get_largest_mem_adr(self) -> int: """Helper function for pretty_print that returns the length of @@ -351,11 +346,14 @@ class MicroMemory(Module): """ return len(str(len(self.memory))) - def get_longest_line_len(self, ignore_keys=[]) -> int: + def get_longest_line_len(self, ignore_keys=None) -> int: """Helper function for pretty_print that returns the length of the longest value in the memory to print for a module. """ + if ignore_keys is None: + ignore_keys = [] + longest_memory_line = 0 for value in self.memory: diff --git a/src/simudator/processor/mia/modules/micro_pc.py b/src/simudator/processor/mia/modules/micro_pc.py index 55500e7d68773ca19001f75553d238c0c14c1bf8..38d884c8f746beb40bc0be29b0c934b2916968a7 100644 --- a/src/simudator/processor/mia/modules/micro_pc.py +++ b/src/simudator/processor/mia/modules/micro_pc.py @@ -97,14 +97,10 @@ class MicroPC(Module): """ pass - def save_state_to_file(self, file_path: str) -> None: - """ - Tries to save the modules state to a given file. - """ - file = open(file_path, "a") - file.write(self.name + ":\n") - file.write("value: " + hex(self.value)[2:] + "\n\n") - file.close() + def save_state_to_file(self, file_path: str) -> bool: + content = self.name + ":\n" + content += "value: " + hex(self.value)[2:] + "\n\n" + return super()._helper_save_state_to_file(file_path, content) def load_from_str(self, state_string): string_pair = state_string.split(": ") diff --git a/src/simudator/processor/mia/modules/pc.py b/src/simudator/processor/mia/modules/pc.py index 575c4b65fde008511a6f184836c6e9cd43a4c973..c7ee4df7e7daae2eba2b7bc791903455cac817fc 100644 --- a/src/simudator/processor/mia/modules/pc.py +++ b/src/simudator/processor/mia/modules/pc.py @@ -50,7 +50,7 @@ class PC(Module, MiaBusConnector): self.signals["out_content"].update_value(None) def update_register(self) -> None: - """Updates the value of the PC according to the signals sent by the micro memory. + """Updates the value of the PC according to the signals sent by the micro memory. If the program counter recives 'True' from both signals it should do nothing and wait for the next cycle. @@ -107,12 +107,10 @@ class PC(Module, MiaBusConnector): self.value = 0 self.increase_by_one = False - def save_state_to_file(self, file_path: str) -> None: - """Tries to save the modules state to a given file.""" - file = open(file_path, "a") - file.write(self.name + ":\n") - file.write("value: " + hex(self.value)[2:] + "\n\n") - file.close() + def save_state_to_file(self, file_path: str) -> bool: + content = self.name + ":\n" + content += "value: " + hex(self.value)[2:] + "\n\n" + return super()._helper_save_state_to_file(file_path, content) def load_from_str(self, state_string): string_pair = state_string.split(": ") @@ -121,4 +119,3 @@ class PC(Module, MiaBusConnector): def print_module(self) -> None: print("", self.name, "\n -----", "\n value: ", hex(self.value)) -