diff --git a/src/simudator/core/module.py b/src/simudator/core/module.py index b84284952a8c0177ddf4756f874401a89d745fa4..24cad248e7f16469ce0b0db2b8226ef01902be9d 100644 --- a/src/simudator/core/module.py +++ b/src/simudator/core/module.py @@ -1,5 +1,7 @@ from __future__ import annotations + from os import error +from typing import Any from simudator.core.signal import Signal @@ -60,10 +62,11 @@ class Module: """ Simulate behaviour for sending output using the internal state during a clock tick. Exact behaviour is specified in each module type. + # Internal variables """ raise NotImplementedError - def get_state(self) -> dict: + def get_state(self) -> dict[str, Any]: """ Return the state of the module. @@ -77,6 +80,19 @@ class Module: state_dict["name"] = self.name return state_dict + def get_parameter(self) -> dict[str, Any]: + """ + Return the parameters of the module. + + Returns + ------- + dict[str, Any] + Parameter of the module represented as a dictionary with one key for + each parameter variable. + """ + param_dict = dict() + return param_dict + def get_gui_state(self) -> dict: """ Return the state of the module as should be displayed in a GUI. diff --git a/src/simudator/core/modules/demux.py b/src/simudator/core/modules/demux.py index 2aeb731c2e414cd161b71ec38ea2743d0be6ffbf..70ff14b1de3a4d507b9fa83740cfc2e15a4484dd 100644 --- a/src/simudator/core/modules/demux.py +++ b/src/simudator/core/modules/demux.py @@ -84,19 +84,23 @@ class Demux(Module): def get_state(self) -> dict[str, Any]: state = super().get_state() state["value"] = self._value - state["bit_length"] = self._bit_length return state + def get_parameter(self) -> dict[str, Any]: + parameter = super().get_parameter() + parameter["bit_length"] = self._bit_length + + return parameter + def set_state(self, state: dict[str, Any]) -> None: """Set the name and value of the demux. Parameters ---------- state : dict[str, Any] - The state of the demux to load. Should contain the keys "value" and - "bit_length", both with values of type ``int``. + The state of the demux to load. Should contain the key + "value" of type ``int``. """ super().set_state(state) self._value = state["value"] - self._bit_length = state["bit_length"] diff --git a/src/simudator/core/modules/mux.py b/src/simudator/core/modules/mux.py index cf8e06a9f48366c4dc8a269661dd0825a18e5d5d..851b1b9f28cfc599be3a2b4921d620a2f75d9412 100644 --- a/src/simudator/core/modules/mux.py +++ b/src/simudator/core/modules/mux.py @@ -83,10 +83,15 @@ class Mux(Module): def get_state(self) -> dict[str, Any]: state = super().get_state() state["value"] = self._value - state["bit_length"] = self._bit_length return state + def get_parameter(self) -> dict[str, Any]: + paramter = super().get_state() + paramter["bit_length"] = self._bit_length + + return paramter + 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) @@ -97,13 +102,11 @@ class Mux(Module): Parameters ---------- state : dict[str, Any] - The state of the demux to load. Should contain the keys "name", - "value" and "bit_length" with values of type ``str``, ``int`` and - ``int`` respectively. + The state of the demux to load. Should contain the keys "name" + and "value" with values of type ``str`` and ``int`` respectively. """ super().set_state(state) self._value = state["value"] - self._bit_length = state["bit_length"] def print_module(self) -> None: print( diff --git a/src/simudator/core/modules/register.py b/src/simudator/core/modules/register.py index 723638511324f405f79ab56e456635ed597a2e00..1e735b2904174a89d327804073a6c3ea57bafedc 100644 --- a/src/simudator/core/modules/register.py +++ b/src/simudator/core/modules/register.py @@ -8,18 +8,7 @@ from simudator.core.signal import Signal class Register(Module): """ - A simple module that can store and output a value. - - Parameters - ---------- - input : Signal - Signal from which the value is stored in the register. - output : Signal - Signal onto which the value of the register is outputted. - value : Any - Initial value of the register. - name : str - Name of the register. + A simple module that can store a value. """ __slots__ = "_value" @@ -43,10 +32,9 @@ class Register(Module): self._value = value def update_register(self) -> None: - """Update the internal value of the register with the input signal. - - Any extra bits that do not fit the bit length of the register are - thrown away. + """ + Propagate the input signal to the registers internal state. + Throw away bits larger than the length of the register. """ input_value = self.signals["in_content"].get_value() if input_value is None: @@ -54,46 +42,51 @@ class Register(Module): self._value = input_value def output_register(self) -> None: - """Output the value of the register onto the output signal.""" + """ + Propagate the value of the register to the output signal. + It is the response of the destination to know when it should + read the output. + """ self.signals["out_content"].update_value(self._value) def update_logic(self): - """Do nothing. - + """ The register has no logic. """ pass def get_state(self) -> dict[str, Any]: + """ + Returns a dict of the register state. + These states are changable via set_states. + """ state = super().get_state() state["value"] = self._value return state - def get_gui_state(self) -> dict: + def get_gui_state(self) -> dict[str, Any]: state = self.get_state() return state def set_state(self, state: dict[str, Any]) -> None: """ - Set the state of the register. - - Parameters - ---------- - state : dict[str, Any] - The state of the register to load. Should contain the keys "name" - and "value" with values of type ``str`` and ``int`` respectively. + Sets the register state to one given in dict. """ self.name = state["name"] self._value = state["value"] def reset(self) -> None: """ - Reset the register to 0. + Resets the register to 0. """ self._value = 0 - def save_state_to_file(self, file_path: str) -> bool: - content = self.name + ":\nvalue:: " + str(self._value) + "\n\n" + def save_state_to_file(self, file_path: str) -> True: + """ + Tries to save the modules state to a given file. + Returns true on success and false if something went wrong. + """ + content = self.name + ":\n" + "value: " + str(self._value) + "\n\n" return super()._helper_save_state_to_file(file_path, content) def print_module(self) -> None: @@ -108,65 +101,72 @@ class Register(Module): class IntegerRegister(Register): """ - A register intended to store integers only. - - Parameters - ---------- - input : Signal - Signal from which the value is stored in the register. - output : Signal - Signal onto which the value of the register is outputted. - bit_length : int - Maximum number of bits of the input to store in the register. All extra - bits of the input value are discarded. - value : Any - Initial value of the register. - name : str - Name of the register. + A simple module that can store an integer value with a given bit-length. """ __slots__ = "_bit_length" def __init__( self, - input: Signal, - output: Signal, + input_signal: Signal, + output_signal: Signal, bit_length: int, value: int = 0, name: str | None = None, ) -> None: - # set the name + # set the registers name if name is None: name = f"{bit_length}-bit register" - super().__init__(input, output, value=value, name=name) + super().__init__(input_signal, output_signal, value=value, name=name) # set the bit length of the register self._bit_length = bit_length def update_register(self) -> None: + """ + Propagate the input signal to the registers internal state. + Throw away bits larger than the length of the register. + """ super().update_register() mask = 2**self._bit_length - 1 self._value = self._value & mask def get_state(self) -> dict[str, Any]: + """ + Returns a dict of the register state. + These states are changable via set_states. + """ state = super().get_state() - state["bit_length"] = self._bit_length return state + def get_parameter(self) -> dict[str, Any]: + """ + Returns a dict of the register state. + These states are changable via set_states. + """ + parameter = super().get_parameter() + parameter["bit_length"] = self._bit_length + return parameter + def set_state(self, state: dict[str, Any]) -> None: + """ + Sets the register state to one given in dict. + """ super().set_state(state) - if "bit_length" in state: - self._bit_length = state["bit_length"] - 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 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 load_from_str(self, state_string) -> None: + def load_from_str(self, state_string): string_pair = state_string.split(": ") - # TODO: Maybe check if it starts with value: ? self._value = int(string_pair[1], 16) @@ -187,8 +187,8 @@ class Flag(IntegerRegister): # set the flags name super().__init__( - input=input_signal, - output=output_signal, + input_signal=input_signal, + output_signal=output_signal, bit_length=bit_length, value=value, name=name, @@ -210,9 +210,14 @@ class Flag(IntegerRegister): state["value"] = self._value 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 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 print_module(self) -> None: print( diff --git a/src/simudator/gui/module_graphics_item/register_graphic.py b/src/simudator/gui/module_graphics_item/register_graphic.py index 9cf63a23139d25d20dab120ca039a3e510231e9e..b84f1414e9e1f84384b41ff699b227a9f72be5e3 100644 --- a/src/simudator/gui/module_graphics_item/register_graphic.py +++ b/src/simudator/gui/module_graphics_item/register_graphic.py @@ -50,7 +50,8 @@ class IntegerRegisterGraphicsItem(RegisterGraphicsItem): """ def update(self): + parameter = self.module.get_parameter() + hex_length = math.ceil(parameter["bit_length"] / 4) state = self.module.get_state() - hex_length = math.ceil(state["bit_length"] / 4) full_text = f"{state['name']}: {state['value']:0{hex_length}x}" self.text.setText(full_text) diff --git a/src/simudator/processor/mia/gui/mia_ir_graphic.py b/src/simudator/processor/mia/gui/mia_ir_graphic.py index 2616d856d5e8bd245ac3d92a5c8a445c97e4158c..f39ed53f1af60b3406e59095ef2db96d3b2ab1b8 100644 --- a/src/simudator/processor/mia/gui/mia_ir_graphic.py +++ b/src/simudator/processor/mia/gui/mia_ir_graphic.py @@ -48,7 +48,9 @@ class IrGraphicsItem(ModuleGraphicsItem): def update(self): # Update small text - instr = self.module.instruction + ir_state = self.module.get_state() + + instr = ir_state["value"] self.small_text.setText(f"IR: {instr:04x}") # Update larg text diff --git a/src/simudator/processor/mia/gui/mia_micro_memory_graphic.py b/src/simudator/processor/mia/gui/mia_micro_memory_graphic.py index f23c01bebd3e431836356f72a4371dcfa2ef4e3e..aedf31b56a012561fc5ed1cf0f872c071f142336 100644 --- a/src/simudator/processor/mia/gui/mia_micro_memory_graphic.py +++ b/src/simudator/processor/mia/gui/mia_micro_memory_graphic.py @@ -35,12 +35,10 @@ class MicroMemoryGraphicsItem(MiaMemoryGraphicsItem): def update(self): # get instruction field - current_instr = self.module.curr_instr - instr = self.module.memory[current_instr] + uM_state = self.module.get_state() + + instr = uM_state["curr_instr"] - # TODO: why calculate this from the instruction? - # The module already have this data, maybe wewrite get_state? - # mask out specific fields alu_field = (instr >> 21) & 0b1111 tb_field = (instr >> 18) & 0b111 fb_field = (instr >> 15) & 0b111 diff --git a/src/simudator/processor/mia/mia.py b/src/simudator/processor/mia/mia.py index b90e2f5efdc0b4514ea70a73595531ab1905b540..1e869055b3f9b83fd8f4dffb0c76ff2eb1384759 100644 --- a/src/simudator/processor/mia/mia.py +++ b/src/simudator/processor/mia/mia.py @@ -267,7 +267,7 @@ class MIA_CPU(Processor): self.lambdas = {} def is_new_instruction(self) -> bool: - return self.get_module("uPC").value == 0 + return self.get_module("uPC").get_state()["value"] == 0 def get_current_instructions(self) -> list[tuple[str, int, int]]: asm_instr = self.get_asm_instruction() @@ -294,8 +294,8 @@ class MIA_CPU(Processor): If the label doesnt exist, the string is empty. """ - ir = self.get_module("IR") - op_code = ir.op + ir_state = self.get_module("IR").get_state() + op_code = ir_state["op"] return self.get_module("K1").get_label(int(op_code)) def get_pipeline_dimensions(self) -> tuple[int, int]: diff --git a/src/simudator/processor/mia/modules/hr.py b/src/simudator/processor/mia/modules/hr.py index bd74491b83632dcbe52679eaba363326fece177c..2f8381c9b5f1dcba155b445e86d75e25ec163005 100644 --- a/src/simudator/processor/mia/modules/hr.py +++ b/src/simudator/processor/mia/modules/hr.py @@ -8,7 +8,7 @@ class HR(IntegerRegister, MiaBusConnector): Register for saving large AlU calculations in MIA. """ - # Python does not allow multiple inherintence if more than one of the + # Python does not allow multiple inherintence if more than one of the # parent classes uses __slots__. Thus we also includes the __slots__ # from MiaBusConnector. __slots__ = ("bus_id", "bus_control_s") diff --git a/src/simudator/processor/mia/modules/ir.py b/src/simudator/processor/mia/modules/ir.py index 00ee7de233523a7795616879f8c8ff968071e181..aec64c91a15ddbd5f5b8a42b3c35fc9a5edaf8e3 100644 --- a/src/simudator/processor/mia/modules/ir.py +++ b/src/simudator/processor/mia/modules/ir.py @@ -15,7 +15,7 @@ class IR(Module, MiaBusConnector): # Python does not allow multiple inherintence if more than one of the # parent classes uses __slots__. Thus we also includes the __slots__ # from MiaBusConnector. - __slots__ = ("op", "grx", "m", "a", "bus_id", "instruction", "bus_control_s") + __slots__ = ("_op", "_grx", "_m", "_a", "bus_id", "_instruction", "bus_control_s") def __init__( self, @@ -40,13 +40,12 @@ class IR(Module, MiaBusConnector): Module.__init__(self, signals, name) MiaBusConnector.__init__(self, bus_control, bus_id) - # Internal values - self.op = 0 - self.grx = 0 - self.m = 0 - self.a = 0 + self._op = 0 + self._grx = 0 + self._m = 0 + self._a = 0 + self._instruction = default_value self.bus_id = bus_id - self.instruction = default_value def update_register(self) -> None: """ @@ -54,11 +53,11 @@ class IR(Module, MiaBusConnector): from the bus and bitshift each part of the instruction. """ if self.read_from_bus(): - self.instruction = self.signals["in_input"].get_value() - self.op = self.instruction >> 12 - self.grx = (self.instruction >> 10) & 0b11 - self.m = (self.instruction >> 8) & 0b11 - self.a = self.instruction & (2**8 - 1) + self._instruction = self.signals["in_input"].get_value() + self._op = self._instruction >> 12 + self._grx = (self._instruction >> 10) & 0b11 + self._m = (self._instruction >> 8) & 0b11 + self._a = self._instruction & (2**8 - 1) def output_register(self) -> None: """ @@ -66,12 +65,12 @@ class IR(Module, MiaBusConnector): and m_s, and output its whole instruction to the bus when asked to. """ - self.signals["out_op"].update_value(self.op) - self.signals["out_grx"].update_value(self.grx) - self.signals["out_m"].update_value(self.m) + self.signals["out_op"].update_value(self._op) + self.signals["out_grx"].update_value(self._grx) + self.signals["out_m"].update_value(self._m) if self.write_to_bus(): - self.signals["out_output"].update_value(self.instruction) + self.signals["out_output"].update_value(self._instruction) else: self.signals["out_output"].update_value(None) @@ -81,40 +80,40 @@ class IR(Module, MiaBusConnector): def get_state(self) -> dict[str, Any]: state = { "name": self.name, - "value": self.instruction, - "op": self.op, - "grx": self.grx, - "m": self.m, - "a": self.a, + "value": self._instruction, + "op": self._op, + "grx": self._grx, + "m": self._m, + "a": self._a, } return state def get_gui_state(self) -> dict: state = super().get_gui_state() - state["value"] = self.instruction + state["value"] = self._instruction return state def set_state(self, state: dict) -> None: super().set_state(state) - self.instruction = state["value"] + self._instruction = state["value"] if "op" in state: - self.op = state["op"] + self._op = state["op"] if "grx" in state: - self.grx = state["grx"] + self._grx = state["grx"] if "m" in state: - self.m = state["m"] + self._m = state["m"] if "a" in state: - self.a = state["a"] + self._a = state["a"] def reset(self) -> None: """ Resets the instruction register to 0. """ - self.instruction = 0 - self.op = 0 - self.grx = 0 - self.m = 0 - self.a = 0 + self._instruction = 0 + self._op = 0 + self._grx = 0 + self._m = 0 + self._a = 0 def print_module(self) -> None: print( @@ -122,23 +121,22 @@ class IR(Module, MiaBusConnector): self.name, "\n -----", "\n value: ", - hex(self.instruction), + hex(self._instruction), "\n op: ", - bin(self.op), + bin(self._op), "\n grx: ", - bin(self.grx), + bin(self._grx), "\n m: ", - bin(self.m), + bin(self._m), "\n a: ", - bin(self.a), + bin(self._a), ) def save_state_to_file(self, file_path: str) -> bool: content = self.name + ":\n" - content += "Instruction: " + hex(self.instruction)[2:] + "\n\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) + 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 357e46be5fed5ee27e523a6e2a426f49411a00bc..de59624255c7924f6152ddf0a3bf74d6de96faf0 100644 --- a/src/simudator/processor/mia/modules/lc.py +++ b/src/simudator/processor/mia/modules/lc.py @@ -13,12 +13,11 @@ class LC(Module): """ __slots__ = ( - "value", - "read_from_bus", - "read_from_uADR", - "decrement_by_one", - "bit_length", - "mask", + "_value", + "_read_from_bus", + "_read_from_uADR", + "_decrement_by_one", + "_bit_length", ) def __init__( @@ -70,16 +69,15 @@ class LC(Module): super().__init__(signals, name) # the value of the loop counter - self.value = value + self._value = value # helper variables - self.read_from_bus = False - self.read_from_uADR = False - self.decrement_by_one = False + self._read_from_bus = False + self._read_from_uADR = False + self._decrement_by_one = False # bit length and mask - self.bit_length = bit_length - self.mask = 2**self.bit_length - 1 + self._bit_length = bit_length def update_register(self) -> None: """Reads bit 12 and 13 from the micro memory and updates the @@ -92,39 +90,42 @@ class LC(Module): match self.signals["in_control"].get_value(): case 0b00: # LC is not effected - self.decrement_by_one = False - self.read_from_bus = False - self.read_from_uADR = False + self._decrement_by_one = False + self._read_from_bus = False + self._read_from_uADR = False case 0b01: # Decrement by one - self.decrement_by_one = True - self.read_from_bus = False - self.read_from_uADR = False + self._decrement_by_one = True + self._read_from_bus = False + self._read_from_uADR = False case 0b10: # Load 8 least significant bits from bus - self.decrement_by_one = False - self.read_from_bus = True - self.read_from_uADR = False + self._decrement_by_one = False + self._read_from_bus = True + self._read_from_uADR = False case 0b11: # LCs 7 least significant bits are loaded from uADR - self.decrement_by_one = False - self.read_from_bus = False - self.read_from_uADR = True + self._decrement_by_one = False + self._read_from_bus = False + self._read_from_uADR = True - if self.read_from_bus: + if self._read_from_bus: input_value = self.signals["in_input"].get_value() - self.value = input_value & self.mask + mask = 2**self._bit_length - 1 + self._value = input_value & mask - if self.read_from_uADR: + if self._read_from_uADR: input_value = self.signals["in_address"].get_value() - self.value = input_value & self.mask + mask = 2**self._bit_length - 1 + self._value = input_value & mask - if self.decrement_by_one: - self.value -= 1 + if self._decrement_by_one: + self._value -= 1 - # overflow correctly - if self.value < 0: - self.value = self.mask + # underflow correctly + if self._value < 0: + mask = 2**self._bit_length - 1 + self._value = mask def output_register(self) -> None: """The loop counter will only output to the L flag, this is @@ -136,7 +137,7 @@ class LC(Module): """When the loop counter reaches zero, set the l flag to 1. Otherwise set it to zero. """ - if self.value == 0: + if self._value == 0: self.signals["out_flag_l"].update_value(1) else: self.signals["out_flag_l"].update_value(0) @@ -152,45 +153,52 @@ class LC(Module): """ state = dict() state["name"] = self.name - state["value"] = self.value - state["bit_length"] = self.bit_length - state["mask"] = self.mask - state["read_from_bus"] = self.read_from_bus - state["read_from_uADR"] = self.read_from_uADR - state["decrement_by_one"] = self.decrement_by_one + state["value"] = self._value + state["read_from_bus"] = self._read_from_bus + state["read_from_uADR"] = self._read_from_uADR + state["decrement_by_one"] = self._decrement_by_one return state + def get_parameter(self) -> dict[str, Any]: + """Returns a dict of the loop counter parameter. + + Returns + ------- + dict[str, Any] + The parameter of the loop counter. + """ + parameter = super().get_parameter() + parameter["bit_length"] = self._bit_length + return parameter + def set_state(self, state: dict[str, Any]) -> None: """Sets the loop counter state to one given in dict.""" self.name = state["name"] - self.value = state["value"] + self._value = state["value"] if "bit_length" in state: - self.bit_length = state["bit_length"] - if "mask" in state: - self.mask = state["mask"] + self._bit_length = state["bit_length"] if "read_from_bus" in state: - self.read_from_bus = state["read_from_bus"] + self._read_from_bus = state["read_from_bus"] if "read_from_uADR" in state: - self.read_from_uADR = state["read_from_uADR"] + self._read_from_uADR = state["read_from_uADR"] if "decrement_by_one" in state: - self.decrement_by_one = state["decrement_by_one"] + self._decrement_by_one = state["decrement_by_one"] def reset(self) -> None: """Resets the loop counter to 0.""" - self.value = 0 - self.read_from_bus = False - self.read_from_uADR = False - self.decrement_by_one = False + self._value = 0 + self._read_from_bus = False + self._read_from_uADR = False + self._decrement_by_one = False def save_state_to_file(self, file_path: str) -> bool: content = self.name + ":\n" - content += "value: " + hex(self.value)[2:] + "\n\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(": ") - # TODO: Maybe check if it starts with value: ? - self.value = int(string_pair[1], 16) + self._value = int(string_pair[1], 16) def print_module(self) -> None: print( @@ -198,11 +206,11 @@ class LC(Module): self.name, "\n -----", "\n value: ", - hex(self.value), + hex(self._value), "\n decrement: ", - self.decrement_by_one, + self._decrement_by_one, "\n read from uADR: ", - self.read_from_uADR, + self._read_from_uADR, "\n read from bus: ", - self.read_from_bus, + self._read_from_bus, ) diff --git a/src/simudator/processor/mia/modules/mia_bus_connect.py b/src/simudator/processor/mia/modules/mia_bus_connect.py index e5607b1f82509d93fba475bce0ebcc7b68bd3729..7f1de429b9f175df1db8f2e2a1659ff11e17cd95 100644 --- a/src/simudator/processor/mia/modules/mia_bus_connect.py +++ b/src/simudator/processor/mia/modules/mia_bus_connect.py @@ -9,7 +9,7 @@ class MiaBusConnector: Has logic for controlling when to read and write to bus. """ - # Python does not allow multiple inherintence if more than one of the + # Python does not allow multiple inherintence if more than one of the # parent classes uses __slots__. Since the modules that inherit from MiaBusConnector # also inherits from other classes we leave this class __slots__ empty. __slots__ = () diff --git a/src/simudator/processor/mia/modules/mia_grx.py b/src/simudator/processor/mia/modules/mia_grx.py index 27d40fbe8a6a6ef760e2bebb458d3cdd8e38197e..6530e22241a6ad8418b6af1da906100e716ed127 100644 --- a/src/simudator/processor/mia/modules/mia_grx.py +++ b/src/simudator/processor/mia/modules/mia_grx.py @@ -14,7 +14,7 @@ class GRX(Module, MiaBusConnector): registers should be indexed by the GRx bits or the M bits. """ - # Python does not allow multiple inherintence if more than one of the + # Python does not allow multiple inherintence if more than one of the # parent classes uses __slots__. Thus we also includes the __slots__ # from MiaBusConnector. __slots__ = ( diff --git a/src/simudator/processor/mia/modules/micro_memory.py b/src/simudator/processor/mia/modules/micro_memory.py index 5995909ed6befcdbe0f8e821d4b519216bee40e8..4109d9b7f2d021f745e0c49524e639a1c2fb92c5 100644 --- a/src/simudator/processor/mia/modules/micro_memory.py +++ b/src/simudator/processor/mia/modules/micro_memory.py @@ -18,16 +18,14 @@ class MicroMemory(Module): """ __slots__ = ( - "curr_instr", - "z_flag_val", - "n_flag_val", - "c_flag_val", - "o_flag_val", - "l_flag_val", - "memory", - "halt", - "adress_padding", - "value_padding", + "_curr_instr", + "_z_flag_val", + "_n_flag_val", + "_c_flag_val", + "_o_flag_val", + "_l_flag_val", + "_memory", + "_halt", ) MEMORY_ADDRESS_PADDING = 2 @@ -51,8 +49,6 @@ class MicroMemory(Module): o_flag: Signal, l_flag: Signal, name: str = "uM", - adress_padding: int = 2, - value_padding: int = 7, ) -> None: """ Parameters @@ -117,19 +113,14 @@ class MicroMemory(Module): super().__init__(signals, name) - # Internal variables - self.curr_instr = 0 - self.z_flag_val = 0 - self.n_flag_val = 0 - self.c_flag_val = 0 - self.o_flag_val = 0 - self.l_flag_val = 0 - self.memory = [0 for _ in range(128)] - self.halt = False # Used for signalling a HALT - - # paddings to ensure saving to file has the correct format - self.adress_padding = adress_padding - self.value_padding = value_padding + self._curr_instr = 0 + self._z_flag_val = 0 + self._n_flag_val = 0 + self._c_flag_val = 0 + self._o_flag_val = 0 + self._l_flag_val = 0 + self._memory = [0 for _ in range(128)] + self._halt = False # Used for signalling a HALT def update_logic(self) -> None: """ @@ -143,15 +134,15 @@ class MicroMemory(Module): if instruction is None: return - self.curr_instr = instruction - self.z_flag_val = self.signals["in_flag_z"].get_value() - self.n_flag_val = self.signals["in_flag_n"].get_value() - self.c_flag_val = self.signals["in_flag_c"].get_value() - self.o_flag_val = self.signals["in_flag_o"].get_value() - self.l_flag_val = self.signals["in_flag_l"].get_value() + self._curr_instr = instruction + self._z_flag_val = self.signals["in_flag_z"].get_value() + self._n_flag_val = self.signals["in_flag_n"].get_value() + self._c_flag_val = self.signals["in_flag_c"].get_value() + self._o_flag_val = self.signals["in_flag_o"].get_value() + self._l_flag_val = self.signals["in_flag_l"].get_value() # Extract the different fields of the micro instruction - instr = self.memory[self.curr_instr] + instr = self._memory[self._curr_instr] alu_field = (instr >> 21) & 0b1111 tb_field = (instr >> 18) & 0b111 fb_field = (instr >> 15) & 0b111 @@ -217,7 +208,7 @@ class MicroMemory(Module): case 0b0011: self.signals["out_control_upc"].update_value(0b011) case 0b0100: - self._conditional_jump(self.z_flag_val, 0, uadr_field) + self._conditional_jump(self._z_flag_val, 0, uadr_field) case 0b0101: self.signals["out_control_upc"].update_value(0b100) self.signals["out_upc"].update_value(uadr_field) @@ -227,19 +218,19 @@ class MicroMemory(Module): case 0b0111: self.signals["out_control_upc"].update_value(0b101) case 0b1000: - self._conditional_jump(self.z_flag_val, 1, uadr_field) + self._conditional_jump(self._z_flag_val, 1, uadr_field) case 0b1001: - self._conditional_jump(self.n_flag_val, 1, uadr_field) + self._conditional_jump(self._n_flag_val, 1, uadr_field) case 0b1010: - self._conditional_jump(self.c_flag_val, 1, uadr_field) + self._conditional_jump(self._c_flag_val, 1, uadr_field) case 0b1011: - self._conditional_jump(self.o_flag_val, 1, uadr_field) + self._conditional_jump(self._o_flag_val, 1, uadr_field) case 0b1100: - self._conditional_jump(self.l_flag_val, 1, uadr_field) + self._conditional_jump(self._l_flag_val, 1, uadr_field) case 0b1101: - self._conditional_jump(self.c_flag_val, 0, uadr_field) + self._conditional_jump(self._c_flag_val, 0, uadr_field) case 0b1110: - self._conditional_jump(self.o_flag_val, 0, uadr_field) + self._conditional_jump(self._o_flag_val, 0, uadr_field) case 0b1111: # Halt is handled by update_register self.signals["out_control_upc"].update_value(0b011) @@ -257,11 +248,11 @@ class MicroMemory(Module): were to be done in update_logic, the halt would erroneously be signaled one cycle to early. """ - seq_field = (self.memory[self.curr_instr] >> 7) & 0b1111 + seq_field = (self._memory[self._curr_instr] >> 7) & 0b1111 if seq_field == 0b1111: - self.halt = True + self._halt = True else: - self.halt = False + self._halt = False def _conditional_jump(self, flag, cond_value, uadr): """Helper function for executing a conditional jump to the specified uadr @@ -281,27 +272,27 @@ class MicroMemory(Module): value 0 are not printed. """ print("", self.name, "\n -----\n") - for adress in range(len(self.memory)): - if self.memory[adress] != 0: + for adress in range(len(self._memory)): + if self._memory[adress] != 0: print("", str(adress), "", str(self.memory[adress]), "\n") def get_state(self) -> dict: state = super().get_state() - state["memory"] = self.memory[:] - state["halt"] = self.halt - state["curr_instr"] = self.curr_instr + state["memory"] = self._memory[:] + state["halt"] = self._halt + state["curr_instr"] = self._curr_instr return state def get_gui_state(self) -> dict[str, Any]: state = super().get_state() - state["memory"] = self.memory[:] + state["memory"] = self._memory[:] return state def set_state(self, state: dict) -> None: super().set_state(state) - self.memory = state["memory"] + self._memory = state["memory"] if "halt" in state: - self.halt = state["halt"] + self._halt = state["halt"] def output_register(self): pass @@ -310,14 +301,14 @@ class MicroMemory(Module): return self.signals["in_upc"] def reset(self) -> None: - self.curr_instr = 0 - self.z_flag_val = 0 - self.n_flag_val = 0 - self.c_flag_val = 0 - self.o_flag_val = 0 - self.l_flag_val = 0 - self.memory = [0 for i in range(128)] - self.halt = False # Used for signalling a HALT + self._curr_instr = 0 + self._z_flag_val = 0 + self._n_flag_val = 0 + self._c_flag_val = 0 + self._o_flag_val = 0 + self._l_flag_val = 0 + self._memory = [0 for i in range(128)] + self._halt = False # Used for signalling a HALT def load_from_str(self, state_string) -> None: """Load the contents of the micro memory from a string consisting of a @@ -335,8 +326,8 @@ class MicroMemory(Module): b0: ffff ' """ - for i in range(len(self.memory)): - self.memory[i] = 0 + for i in range(len(self._memory)): + self._memory[i] = 0 lines = state_string.split("\n") for line in lines: @@ -344,11 +335,11 @@ class MicroMemory(Module): line_data = line.split(": ") adress = int(line_data[0], 16) value = int(line_data[1], 16) - self.memory[adress] = value + self._memory[adress] = value def save_state_to_file(self, file_path: str) -> bool: content = self.name + ":\n" - for index, value in enumerate(self.memory): + for index, value in enumerate(self._memory): content += ( str(hex(index)[2:].rjust(self.MEMORY_ADDRESS_PADDING, "0")) + ": " ) @@ -362,7 +353,7 @@ class MicroMemory(Module): """Helper function for pretty_print that returns the length of the largest adress in the memory to print for a module. """ - return len(str(len(self.memory))) + return len(str(len(self._memory))) def get_longest_line_len(self, ignore_keys=None) -> int: """Helper function for pretty_print that returns the length of @@ -374,7 +365,7 @@ class MicroMemory(Module): longest_memory_line = 0 - for value in self.memory: + for value in self._memory: value_len = len(str(value)) if value_len > longest_memory_line: longest_memory_line = value_len diff --git a/src/simudator/processor/mia/modules/micro_pc.py b/src/simudator/processor/mia/modules/micro_pc.py index efaaeb27dc330f321d87efc52e5c299380f3d1d2..7bf10c95d1f79c541ba267571bc24516e9ba9c2d 100644 --- a/src/simudator/processor/mia/modules/micro_pc.py +++ b/src/simudator/processor/mia/modules/micro_pc.py @@ -11,7 +11,7 @@ class MicroPC(Module): to read from or write to. """ - __slots__ = ("value", "bit_length") + __slots__ = ("_value", "_bit_length") def __init__( self, @@ -25,7 +25,7 @@ class MicroPC(Module): name: str = "uPC", ) -> None: - self.value = 0 + self._value = 0 # Signals signals = { @@ -43,50 +43,50 @@ class MicroPC(Module): def update_register(self) -> None: match self.signals["in_control"].get_value(): case 0b000: - self.value += 1 + self._value += 1 # Overflow - if self.value == 128: - self.value = 0 + if self._value == 128: + self._value = 0 case 0b001: - self.value = self.signals["in_k1"].get_value() + self._value = self.signals["in_k1"].get_value() case 0b010: - self.value = self.signals["in_k2"].get_value() + self._value = self.signals["in_k2"].get_value() case 0b011: - self.value = 0 + self._value = 0 case 0b100: - self.value = self.signals["in_um"].get_value() + self._value = self.signals["in_um"].get_value() case 0b101: - self.value = self.signals["in_supc"].get_value() + self._value = self.signals["in_supc"].get_value() case 0b110: - self.signals["out_supc"].update_value(self.value + 1) - self.value = self.signals["in_um"].get_value() + self.signals["out_supc"].update_value(self._value + 1) + self._value = self.signals["in_um"].get_value() def output_register(self) -> None: - self.signals["out_um"].update_value(self.value) + self.signals["out_um"].update_value(self._value) def get_state(self) -> dict: state = super().get_state() - state["value"] = self.value + state["value"] = self._value return state def get_gui_state(self) -> dict: state = { "name": self.name, - "value": self.value, + "value": self._value, } return state def set_state(self, state: dict) -> None: super().set_state(state) - self.value = state["value"] + self._value = state["value"] def reset(self) -> None: """ Resets the micro program counter to 0. """ - self.value = 0 + self._value = 0 def update_logic(self) -> None: """ @@ -96,13 +96,12 @@ class MicroPC(Module): def save_state_to_file(self, file_path: str) -> bool: content = self.name + ":\n" - content += "value: " + hex(self.value)[2:] + "\n\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(": ") - # TODO: Maybe check if it starts with value: ? - self.value = int(string_pair[1], 16) + self._value = int(string_pair[1], 16) def print_module(self) -> None: - print("", self.name, "\n -----", "\n value: ", hex(self.value)) + print("", self.name, "\n -----", "\n value: ", hex(self._value)) diff --git a/src/simudator/processor/mia/modules/pc.py b/src/simudator/processor/mia/modules/pc.py index c80424982e48899236a49592e303cabdcbfcba29..52c6ad1f4d008e878eb43ae52be12d4fdcb5b5ef 100644 --- a/src/simudator/processor/mia/modules/pc.py +++ b/src/simudator/processor/mia/modules/pc.py @@ -17,10 +17,10 @@ class PC(Module, MiaBusConnector): value on the bus. If both are true it does nothing. """ - # Python does not allow multiple inherintence if more than one of the + # Python does not allow multiple inherintence if more than one of the # parent classes uses __slots__. Thus we also includes the __slots__ # from MiaBusConnector. - __slots__ = ("bus_id", "bus_control_s", "value", "increase_by_one") + __slots__ = ("bus_id", "bus_control_s", "_value", "_increase_by_one", "_bit_length") def __init__( self, @@ -41,16 +41,14 @@ class PC(Module, MiaBusConnector): } Module.__init__(self, signals, name) - # internal state - self.value = value - - # help variables - self.increase_by_one = False + self._value = value + self._increase_by_one = False + self._bit_length = 8 def output_register(self) -> None: """Output the value of the program counter to the bus.""" if self.write_to_bus(): - self.signals["out_content"].update_value(self.value) + self.signals["out_content"].update_value(self._value) else: self.signals["out_content"].update_value(None) @@ -61,17 +59,22 @@ class PC(Module, MiaBusConnector): should do nothing and wait for the next cycle. """ - self.increase_by_one = self.signals["in_control"].get_value() + self._increase_by_one = self.signals["in_control"].get_value() - if self.increase_by_one and self.read_from_bus(): + if self._increase_by_one and self.read_from_bus(): return + mask = 2**self._bit_length - 1 if self.read_from_bus(): # Read the 8 lowest bits from the bus - self.value = self.signals["in_input"].get_value() & 0xFF + self._value = self.signals["in_input"].get_value() & mask + + if self._increase_by_one: + self._value += 1 - if self.increase_by_one: - self.value += 1 + # overflow correctly + if self._value > mask: + self._value = 0 def update_logic(self) -> None: self.output_register() @@ -83,44 +86,56 @@ class PC(Module, MiaBusConnector): Returns ------- - dict[Any] + dict[str, Any] The state of the program counter. """ state = dict() state["name"] = self.name - state["value"] = self.value - state["increment"] = self.increase_by_one - state["bit_length"] = 8 + state["value"] = self._value + state["increment"] = self._increase_by_one return state + def get_parameter(self) -> dict[str, Any]: + """Returns a dict of the program counter paramter. + + These states are changable via set_states. + + Returns + ------- + dict[str, Any] + The paramter of the program counter. + """ + paramter = Module.get_parameter(self) + paramter["bit_length"] = self._bit_length + return paramter + def get_gui_state(self) -> dict: state = { "name": self.name, - "value": self.value, + "value": self._value, } return state def set_state(self, state: dict[str, Any]) -> None: """Sets the program counter state to one given in dict.""" self.name = state["name"] - self.value = state["value"] + self._value = state["value"] if "increment" in state: - self.increase_by_one = state["increment"] + self._increase_by_one = state["increment"] def reset(self) -> None: """Reset the program counter to 0.""" - self.value = 0 - self.increase_by_one = False + self._value = 0 + self._increase_by_one = False def save_state_to_file(self, file_path: str) -> bool: content = self.name + ":\n" - content += "value: " + hex(self.value)[2:] + "\n\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(": ") - # TODO: Maybe check if it starts with value: ? - self.value = int(string_pair[1], 16) + self._value = int(string_pair[1], 16) def print_module(self) -> None: - print("", self.name, "\n -----", "\n value: ", hex(self.value)) + print("", self.name, "\n -----", "\n value: ", hex(self._value)) diff --git a/test/test_core/test_breakpoint.py b/test/test_core/test_breakpoint.py index ec961f4ee887db8e5ad28f493c41b38b2e16ca74..a0a353e31973c8c3d2b8d017d32f90fc80a5cbe0 100644 --- a/test/test_core/test_breakpoint.py +++ b/test/test_core/test_breakpoint.py @@ -282,21 +282,21 @@ def test_stop_on_state_breakpoint(): mM_uADR = Signal(cpu) lc = LC(mM_control, bus_input, l_flag, mM_uADR) - lc.value = 10 + lc._value = 10 cpu.add_module(lc) cpu.add_state_breakpoint("LC", "value", 5) cpu.run_continuously() - assert lc.value == 5 + assert lc._value == 5 assert cpu.is_stopped == True cpu.add_state_breakpoint("LC", "value", 2) cpu.run_continuously() - assert lc.value == 2 + assert lc._value == 2 assert cpu.is_stopped == True # 'Reset' loop counter and turn off previous breakpoint - lc.value = 10 + lc._value = 10 cpu.set_enabled_breakpoint(1, False) cpu.set_enabled_breakpoint(2, False) for _ in range(10): diff --git a/test/test_core/test_demux.py b/test/test_core/test_demux.py index e4c59c3d04f7dc5f73d11c131cfabf87b5301120..132b572dd140aeabec61729c25492d8f35af1d67 100644 --- a/test/test_core/test_demux.py +++ b/test/test_core/test_demux.py @@ -37,7 +37,19 @@ def test_get_state(): assert state["name"] == "Demux" assert state["value"] == 7 - assert state["bit_length"] == 5 + + +def test_get_parameter(): + cpu = Processor() + from_demux = Signal(cpu) + input_s = Signal(cpu) + outputs = [] + bit_length = 5 + demux = Demux(from_demux, bit_length, input_s, outputs, "Demux", 7) + + parameter = demux.get_parameter() + + assert parameter["bit_length"] == 5 def test_set_state(): @@ -58,7 +70,6 @@ def test_set_state(): state = demux.get_state() assert state["name"] == "Demux" assert state["value"] == 6 - assert state["bit_length"] == 2 def test_writing_to_output(): diff --git a/test/test_core/test_memory.py b/test/test_core/test_memory.py index 30b0533041f7a2c5da72c543b198e3e0e71dbc7b..4ded14fa5b5df526e33b1ae45cb4bf11463b73c3 100644 --- a/test/test_core/test_memory.py +++ b/test/test_core/test_memory.py @@ -35,3 +35,15 @@ def test_memory(): assert output_s.get_value() == 0 cpu.do_tick() assert output_s.get_value() == 0 + + +def test_get_parameter(): + cpu = Processor() + input_s = Signal(cpu, value=0) + output_s = Signal(cpu, value=0) + control_s = Signal(cpu, value=0) + adress_s = Signal(cpu, value=0) + memory = Memory(input_s, output_s, control_s, adress_s, 2) + + parameter = memory.get_parameter() + assert len(parameter.keys()) == 0 diff --git a/test/test_core/test_mux.py b/test/test_core/test_mux.py index fed767a99b0ebbcd6460ec126adbde0b224e6fa3..18dca41a25c5f8a99ec99107651e67fd20dce53f 100644 --- a/test/test_core/test_mux.py +++ b/test/test_core/test_mux.py @@ -37,7 +37,19 @@ def test_get_state(): assert state["name"] == "Mux" assert state["value"] == 7 - assert state["bit_length"] == 5 + + +def test_get_parameter(): + cpu = Processor() + to_mux = Signal(cpu) + inputs = [] + output_s = Signal(cpu) + bit_length = 5 + mux = Mux(to_mux, bit_length, output_s, inputs, "Mux", 7) + + parameter = mux.get_parameter() + + assert parameter["bit_length"] == 5 def test_set_state(): @@ -58,7 +70,6 @@ def test_set_state(): assert mux.name == "Mux" assert mux._value == 6 - assert mux._bit_length == 2 def test_writing_to_output(): diff --git a/test/test_core/test_register.py b/test/test_core/test_register.py index 1d1d85589a2a2851b7e9cf9710282b2c4eca8180..45f9c3e2797bf5b345bdfd14ffb092b03cb9ccd1 100644 --- a/test/test_core/test_register.py +++ b/test/test_core/test_register.py @@ -39,6 +39,15 @@ def test_get_state(): assert state["value"] == 13 +def test_get_parameter(): + cpu = Processor() + s = Signal(cpu) + register = Register(s, s, 13, "register") + parameter = register.get_parameter() + + assert len(parameter.keys()) == 0 + + def test_signal_propagation(): # Modules needed to run the test cpu = Processor() diff --git a/test/test_core/test_save_state.py b/test/test_core/test_save_state.py index 16199e77a9b1e2795d0563d55ff97a0c0e046ef7..e8715704488a562cf969a6ef7a65aa775324eebc 100644 --- a/test/test_core/test_save_state.py +++ b/test/test_core/test_save_state.py @@ -3,7 +3,6 @@ from unittest.mock import mock_open, patch from simudator.core.module import Module from simudator.core.modules.register import Register from simudator.core.signal import Signal -from simudator.processor.simple.simple import SIMPLE_CPU def test_module_save_state(): @@ -36,7 +35,7 @@ def test_default_register_save_state(): mock_file = mock_open() - content = register.name + ":\nvalue:: " + str(register._value) + "\n\n" + content = register.name + ":\nvalue: " + str(register._value) + "\n\n" with patch("builtins.open", mock_file): register.save_state_to_file(dummy_file_path) mock_file.assert_called_once_with(dummy_file_path, "a") diff --git a/test/test_mia/test_ir.py b/test/test_mia/test_ir.py index ef4a45f2f8611106f18cd71c540ee456475f0f3a..09dff3879d2962d2dd8acda7d933a13d4f9be415 100644 --- a/test/test_mia/test_ir.py +++ b/test/test_mia/test_ir.py @@ -45,7 +45,7 @@ def test_save_state(): mock_file = mock_open() content = ir.name + ":\n" - content += "Instruction: " + hex(ir.instruction)[2:] + "\n\n" + content += "Instruction: " + hex(ir._instruction)[2:] + "\n\n" with patch("builtins.open", mock_file): ir.save_state_to_file(dummy_file_path) mock_file.assert_called_once_with(dummy_file_path, "a") diff --git a/test/test_mia/test_lc.py b/test/test_mia/test_lc.py index 94f05b98a8779ff2fba7352c40883469da8ae3ff..26e1bea3d15d6d8856c2525a2c3e7fa8753e1bbb 100644 --- a/test/test_mia/test_lc.py +++ b/test/test_mia/test_lc.py @@ -34,7 +34,7 @@ def test_read_from_bus(): mM_control_s.update_value(2) cpu.do_tick() - assert lc.value == 10 + assert lc._value == 10 def test_read_from_uADR(): @@ -51,7 +51,7 @@ def test_read_from_uADR(): mM_control_s.update_value(3) cpu.do_tick() - assert lc.value == 10 + assert lc._value == 10 def test_write_to_l_flag(): @@ -131,13 +131,13 @@ def test_lc_do_nothing(): mM_control_s.update_value(0b01) cpu.do_tick() - assert lc.value == 3 + assert lc._value == 3 # tell lc to do nothing mM_control_s.update_value(0b00) cpu.do_tick() - assert lc.value == 3 + assert lc._value == 3 def test_get_state(): @@ -159,8 +159,6 @@ def test_get_state(): state = lc.get_state() assert state["name"] == "LC" assert state["value"] == 255 - assert state["mask"] == 255 - assert state["bit_length"] == 8 assert state["read_from_bus"] is False assert state["read_from_uADR"] is False assert state["decrement_by_one"] is True @@ -171,8 +169,6 @@ def test_get_state(): state = lc.get_state() assert state["name"] == "LC" assert state["value"] == 100 - assert state["mask"] == 255 - assert state["bit_length"] == 8 assert state["read_from_bus"] is True assert state["read_from_uADR"] is False assert state["decrement_by_one"] is False @@ -183,13 +179,24 @@ def test_get_state(): state = lc.get_state() assert state["name"] == "LC" assert state["value"] == 10 - assert state["mask"] == 255 - assert state["bit_length"] == 8 assert state["read_from_bus"] is False assert state["read_from_uADR"] is True assert state["decrement_by_one"] is False +def test_get_parameter(): + # init all the modules + cpu = Processor() + bus_input_s = Signal(cpu) + mM_control_s = Signal(cpu) + mM_uADR_s = Signal(cpu) + l_flag_s = Signal(cpu) + lc = LC(mM_control_s, bus_input_s, l_flag_s, mM_uADR_s) + + parameter = lc.get_parameter() + assert parameter["bit_length"] == 8 + + def test_save_state(): cpu = Processor() s = Signal(cpu) @@ -200,7 +207,7 @@ def test_save_state(): mock_file = mock_open() content = lc.name + ":\n" - content += "value: " + hex(lc.value)[2:] + "\n\n" + content += "value: " + hex(lc._value)[2:] + "\n\n" with patch("builtins.open", mock_file): lc.save_state_to_file(dummy_file_path) mock_file.assert_called_once_with(dummy_file_path, "a") diff --git a/test/test_mia/test_micro_memory.py b/test/test_mia/test_micro_memory.py index 8cfe4206ff751966dfe54cf561dbdd775ebce165..34a9e7c2c476c4ab9592f929a91aa67f8eb9a977 100644 --- a/test/test_mia/test_micro_memory.py +++ b/test/test_mia/test_micro_memory.py @@ -1,7 +1,8 @@ +from unittest.mock import mock_open, patch + from simudator.core.processor import Processor from simudator.core.signal import Signal from simudator.processor.mia.modules.micro_memory import MicroMemory -from unittest.mock import patch, mock_open def test_alu_field(): @@ -395,20 +396,19 @@ def test_seq_field(): assert upc_control_s.get_value() == 0b011 # TODO: Test for some sort of HALT signal + def test_save_state(): cpu = Processor() s = Signal(cpu) - uM = MicroMemory(s,s,s,s,s,s,s,s,s,s,s,s,s,s,s) + uM = MicroMemory(s, s, s, s, s, s, s, s, s, s, s, s, s, s, s) dummy_file_path = "dummy" mock_file = mock_open() content = uM.name + ":\n" - for index, value in enumerate(uM.memory): - content += ( - str(hex(index)[2:].rjust(uM.MEMORY_ADDRESS_PADDING, "0")) + ": " - ) + for index, value in enumerate(uM._memory): + content += str(hex(index)[2:].rjust(uM.MEMORY_ADDRESS_PADDING, "0")) + ": " content += str(hex(value)[2:].rjust(uM.MEMORY_VALUE_PADDING, "0")) content += "\n" diff --git a/test/test_mia/test_micro_pc.py b/test/test_mia/test_micro_pc.py index 91073e409c9da4566227df1ac29c45e329e21153..89835ef4f7b6069e14f00d144cceefffa549fd3d 100644 --- a/test/test_mia/test_micro_pc.py +++ b/test/test_mia/test_micro_pc.py @@ -1,7 +1,8 @@ +from unittest.mock import mock_open, patch + from simudator.core.processor import Processor from simudator.core.signal import Signal from simudator.processor.mia.modules.micro_pc import MicroPC -from unittest.mock import patch, mock_open def test_upc(): @@ -24,64 +25,65 @@ def test_upc(): # Test uPC += 1 with control signal 0b000 cpu.do_tick() - assert upc.value == 1 + assert upc._value == 1 assert t_supc.get_value() == -1 - assert t_um.get_value() == upc.value + assert t_um.get_value() == upc._value # Test uPC = K1 with control signal 0b001 control_signal.update_value(0b001) cpu.do_tick() - assert upc.value == f_k1.get_value() + assert upc._value == f_k1.get_value() assert t_supc.get_value() == -1 - assert t_um.get_value() == upc.value + assert t_um.get_value() == upc._value # Test uPC = K2 with control signal 0b010 control_signal.update_value(0b010) cpu.do_tick() - assert upc.value == f_k2.get_value() + assert upc._value == f_k2.get_value() assert t_supc.get_value() == -1 - assert t_um.get_value() == upc.value + assert t_um.get_value() == upc._value # Test uPC = 0 with control signal 0b011 control_signal.update_value(0b011) cpu.do_tick() - assert upc.value == 0 + assert upc._value == 0 assert t_supc.get_value() == -1 - assert t_um.get_value() == upc.value + assert t_um.get_value() == upc._value # Test uPC = uADR from uM with control signal 0b100 control_signal.update_value(0b100) cpu.do_tick() - assert upc.value == f_um.get_value() + assert upc._value == f_um.get_value() assert t_supc.get_value() == -1 - assert t_um.get_value() == upc.value + assert t_um.get_value() == upc._value # Test uPC = SuPC with control signal 0b101 control_signal.update_value(0b101) cpu.do_tick() - assert upc.value == f_supc.get_value() + assert upc._value == f_supc.get_value() assert t_supc.get_value() == -1 - assert t_um.get_value() == upc.value + assert t_um.get_value() == upc._value # Test SuPC = uPC + 1, uPC = uADR from uM with control signal 0b110 control_signal.update_value(0b110) - temp = upc.value + 1 + temp = upc._value + 1 cpu.do_tick() - assert upc.value == f_um.get_value() + assert upc._value == f_um.get_value() assert t_supc.get_value() == temp - assert t_um.get_value() == upc.value + assert t_um.get_value() == upc._value + def test_save_state(): cpu = Processor() s = Signal(cpu) - upc = MicroPC(s,s,s,s,s,s,s) + upc = MicroPC(s, s, s, s, s, s, s) dummy_file_path = "dummy" mock_file = mock_open() content = upc.name + ":\n" - content += "value: " + hex(upc.value)[2:] + "\n\n" + content += "value: " + hex(upc._value)[2:] + "\n\n" with patch("builtins.open", mock_file): upc.save_state_to_file(dummy_file_path) mock_file.assert_called_once_with(dummy_file_path, "a") diff --git a/test/test_mia/test_pc.py b/test/test_mia/test_pc.py index 5c417e37f034da909c8aa5031851ef3b85fe5073..90084de82241a603de22cd5e70659a9c146c7dfb 100644 --- a/test/test_mia/test_pc.py +++ b/test/test_mia/test_pc.py @@ -1,7 +1,8 @@ +from unittest.mock import mock_open, patch + from simudator.core.processor import Processor from simudator.core.signal import Signal from simudator.processor.mia.modules.pc import PC -from unittest.mock import patch, mock_open def test_default_name(): @@ -43,12 +44,12 @@ def test_pc_increment(): p.update_value(True) cpu.do_tick() - assert pc.value == 1 + assert pc._value == 1 cpu.do_tick() - assert pc.value == 2 + assert pc._value == 2 for _ in range(5): cpu.do_tick() - assert pc.value == 7 + assert pc._value == 7 def test_set_value_from_bus(): @@ -74,11 +75,11 @@ def test_set_value_from_bus(): bus_in.update_value(20) cpu.do_tick() - assert pc.value == 20 + assert pc._value == 20 bus_in.update_value(10) cpu.do_tick() - assert pc.value == 10 + assert pc._value == 10 def test_write_to_bus(): @@ -132,27 +133,27 @@ def test_exception(): # set values that should raise an error p.update_value(True) control.update_value((2, 1)) - assert pc.value == 13 + assert pc._value == 13 # reset one of the signals, the program counter should now read # from the bus p.update_value(False) cpu.do_tick() - assert pc.value == 26 + assert pc._value == 26 # the program counter should do nothing p.update_value(True) - assert pc.value == 26 + assert pc._value == 26 # reset the other signal, the program counter should now increment # the value by one control.update_value((2, 2)) cpu.do_tick() - assert pc.value == 27 + assert pc._value == 27 # the program counter should do nothing control.update_value((2, 1)) - assert pc.value == 27 + assert pc._value == 27 def test_get_state(): @@ -181,6 +182,21 @@ def test_get_state(): assert state["increment"] is True +def test_get_parameter(): + # init all the modules + cpu = Processor() + p = Signal(cpu, "p", False) + bus_in = Signal(cpu, "bus_in", 0) + bus_out = Signal(cpu) + control = Signal(cpu, "bus", (2, 2)) + bus_id = 1 + pc = PC(p, bus_in, bus_out, control, bus_id, "PC", 13) + + parameter = pc.get_parameter() + assert len(parameter.keys()) == 1 + assert parameter["bit_length"] == 8 + + def test_set_state(): # init all the modules cpu = Processor() @@ -197,20 +213,21 @@ def test_set_state(): pc.set_state(state) assert pc.name == "pc" - assert pc.value == 23 - assert pc.increase_by_one is True + assert pc._value == 23 + assert pc._increase_by_one is True + def test_save_state(): cpu = Processor() s = Signal(cpu) - pc = PC(s,s,s,s,0) + pc = PC(s, s, s, s, 0) dummy_file_path = "dummy" mock_file = mock_open() content = pc.name + ":\n" - content += "value: " + hex(pc.value)[2:] + "\n\n" + content += "value: " + hex(pc._value)[2:] + "\n\n" with patch("builtins.open", mock_file): pc.save_state_to_file(dummy_file_path) mock_file.assert_called_once_with(dummy_file_path, "a")