diff --git a/src/simudator/core/module.py b/src/simudator/core/module.py index b4eaec3b21680f7fe7e1e81a01e602cf50c9581e..37591ab587661a85cb415ecf2755e4c49b1c953c 100644 --- a/src/simudator/core/module.py +++ b/src/simudator/core/module.py @@ -1,6 +1,7 @@ from __future__ import annotations from os import error +from typing import Any from simudator.core.signal import Signal @@ -64,7 +65,7 @@ class Module: """ raise NotImplementedError - def get_state(self) -> dict: + def get_state(self) -> dict[str, Any]: """ Return the state of the module. @@ -78,6 +79,23 @@ class Module: state_dict["name"] = self.name return state_dict + def get_parameter(self) -> dict[str, Any]: + """ + Return the parameters of the module. + + Parameters are immutable attributes of modules that affect how they operate, + such as the bit length of internal registers. They are set once during the initialization + of the modules and assumed to be constant throughout the execution of the program. + + Returns + ------- + dict[str, Any] + Parameters 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..bb193b69404f4a86a301f8afcac71be786d363d8 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]: + parameter = super().get_state() + parameter["bit_length"] = self._bit_length + + return parameter + 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..748c0c25e1a6909fc90f7ffef06b91d34b93ff79 100644 --- a/src/simudator/core/modules/register.py +++ b/src/simudator/core/modules/register.py @@ -26,16 +26,16 @@ class Register(Module): def __init__( self, - input_signal: Signal, - output_signal: Signal, + input: Signal, + output: Signal, value: Any = 0, name: str = "Register", ) -> None: # signals signals = { - "in_content": input_signal, - "out_content": output_signal, + "in_content": input, + "out_content": output, } # init the instance @@ -58,7 +58,8 @@ class Register(Module): self.signals["out_content"].update_value(self._value) def update_logic(self): - """Do nothing. + """ + Do nothing. The register has no logic. """ @@ -69,7 +70,7 @@ class Register(Module): 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 @@ -93,7 +94,7 @@ class Register(Module): self._value = 0 def save_state_to_file(self, file_path: str) -> bool: - content = self.name + ":\nvalue:: " + str(self._value) + "\n\n" + 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: @@ -136,7 +137,7 @@ class IntegerRegister(Register): name: str | None = None, ) -> None: - # set the name + # set the register name if name is None: name = f"{bit_length}-bit register" @@ -152,21 +153,27 @@ class IntegerRegister(Register): def get_state(self) -> dict[str, Any]: state = super().get_state() - state["bit_length"] = self._bit_length return state + def get_parameter(self) -> dict[str, Any]: + """ + Return a dict of the register parameter, i.e. its bit length. + """ + parameter = super().get_parameter() + parameter["bit_length"] = self._bit_length + return parameter + def set_state(self, state: dict[str, Any]) -> None: 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: + 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) @@ -178,8 +185,8 @@ class Flag(IntegerRegister): def __init__( self, - input_signal: Signal, - output_signal: Signal, + input: Signal, + output: Signal, bit_length=1, value=0, name="Flag", @@ -187,8 +194,8 @@ class Flag(IntegerRegister): # set the flags name super().__init__( - input=input_signal, - output=output_signal, + input=input, + output=output, bit_length=bit_length, value=value, name=name, @@ -210,9 +217,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/integer_memory_graphic.py b/src/simudator/gui/module_graphics_item/integer_memory_graphic.py index 262d7a5766208c33f7306c9876e380539c046155..e461468dc1f98e396f654acee953ab001bcc4a2f 100644 --- a/src/simudator/gui/module_graphics_item/integer_memory_graphic.py +++ b/src/simudator/gui/module_graphics_item/integer_memory_graphic.py @@ -44,7 +44,10 @@ class IntegerMemoryWindow(MemoryWindow): An integer specifying the number of bits of each address. """ - def __init__(self, memory_module: Memory, bit_length: int): + def __init__( + self, + memory_module: Memory, + ): # Do not let parent create edit/view buttons super().__init__(memory_module, False) @@ -53,7 +56,7 @@ class IntegerMemoryWindow(MemoryWindow): self.layout.removeWidget(self._memory_table) # Add our own - self._memory_table = IntegerMemoryTable(memory_module, bit_length) + self._memory_table = IntegerMemoryTable(memory_module) self.layout.addWidget(self._memory_table) # Create base buttons, they are exclusive by default @@ -140,14 +143,11 @@ class IntegerMemoryTable(MemoryTable): """ - def __init__(self, memory_module: Memory, bit_length: int, column_size=-1): + def __init__(self, memory_module: Memory, column_size=-1): self._base = Base.DECIMAL_UNSIGNED - self._bit_length = bit_length + self._bit_length = memory_module.get_parameter()["bit_length"] super().__init__(memory_module, column_size) - print(traceback.format_exc()) - print(memory_module) - print(memory_module.get_parameter()) - raise ValueError + self.update() # Signal used to detect when the user has edited a cell # This code can only be called after the initial self.update(). @@ -215,9 +215,6 @@ class IntegerMemoryTable(MemoryTable): # and format each value is in try: - print(value) - print(min_value) - print(max_value) if self._base == Base.BINARY: value = int(value, 2) elif self._base == Base.HEXADECIMAL: 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_memory_graphic.py b/src/simudator/processor/mia/gui/mia_memory_graphic.py index 21d61b027d8bc3386cf0ff66eb3809969b47ce0d..a65eb30bbf6fdb55b69b5be989c8dd738c62f65f 100644 --- a/src/simudator/processor/mia/gui/mia_memory_graphic.py +++ b/src/simudator/processor/mia/gui/mia_memory_graphic.py @@ -68,8 +68,7 @@ class MiaMemoryGraphicsItem(MemoryGraphicsItem): Create and show a MemoryWindow that displays the contents of the memory module associated with this graphics item. """ - bit_length = 16 - self.memory_window = IntegerMemoryWindow(self.module, bit_length) + self.memory_window = IntegerMemoryWindow(self.module) self.memory_window.show() def memoryBreakpointDialog(self) -> None: 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 39087f65727b12c8ddfc8318aa01f86c92b9bafc..5fbd52a3ec7c0ba8339f2d338868427a9f420956 100644 --- a/src/simudator/processor/mia/mia.py +++ b/src/simudator/processor/mia/mia.py @@ -155,6 +155,7 @@ class MIA_CPU(Processor): pm_size, pm_bus_id, name="PM", + bit_length=16, ) # GRX specific @@ -173,6 +174,7 @@ class MIA_CPU(Processor): k1_size, always_write_id, name="K1", + bit_length=7, ) # K2 specific @@ -185,6 +187,7 @@ class MIA_CPU(Processor): k2_size, always_write_id, name="K2", + bit_length=7, ) # IR specific @@ -276,7 +279,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() @@ -303,8 +306,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..9380ae688e14165de2968910e593131938b10ef1 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,53 @@ 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]: + """Return a dictionary of the parameters of the loop counter, + i.e. the bit length of the counter. + + 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 +207,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/mia_memory.py b/src/simudator/processor/mia/modules/mia_memory.py index 4b2ca42c137f718c4260e5ab9064f2a5a8b2d573..2def97845d5bcd15502825501504e182b316f4aa 100644 --- a/src/simudator/processor/mia/modules/mia_memory.py +++ b/src/simudator/processor/mia/modules/mia_memory.py @@ -1,3 +1,5 @@ +from typing import Any + from simudator.core.modules.memory import Memory from simudator.core.signal import Signal from simudator.processor.mia.modules.mia_bus_connect import MiaBusConnector @@ -7,14 +9,14 @@ class MiaMemory(MiaBusConnector, Memory): """ A MIA specific memory, functionality from the general memory and the MiaBusConnector is inherited. The module can be of - arbitrary size and supports opperations that read and write + arbitrary size and supports operations that read and write to/from the mia bus. """ # 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__ = ("label_adress_mapping", "bus_id", "bus_control_s") + __slots__ = ("label_address_mapping", "bus_id", "bus_control_s", "_bit_length") def __init__( self, @@ -25,6 +27,7 @@ class MiaMemory(MiaBusConnector, Memory): size: int = 1, bus_id: int = 0, name: str = "PM", + bit_length: int = 16, ) -> None: MiaBusConnector.__init__(self, bus_control_s, bus_id) Memory.__init__( @@ -38,7 +41,8 @@ class MiaMemory(MiaBusConnector, Memory): ) self.bus_control_s.add_destination(self) - self.label_adress_mapping = {} + self.label_address_mapping = {} + self._bit_length = bit_length def update_register(self) -> None: """ @@ -77,6 +81,11 @@ class MiaMemory(MiaBusConnector, Memory): size = len(self._memory) self._memory = [0 for _ in range(size)] + def get_parameter(self) -> dict[str, Any]: + parameter = super().get_parameter() + parameter["bit_length"] = self._bit_length + return parameter + def load_from_str(self, state_string) -> None: """ Loads the module from a string, used when loading state from @@ -90,20 +99,20 @@ class MiaMemory(MiaBusConnector, Memory): line_data = line.split() value = int(line_data[1], 16) - # Last character of the adress is a semicolon - adress = int(line_data[0][:-1], 16) + # Last character of the address is a semicolon + address = int(line_data[0][:-1], 16) - self._memory[adress] = value + self._memory[address] = value # There is an asm instruction label if len(line_data) == 3: instr = line_data[2] - self.label_adress_mapping[adress] = instr + self.label_address_mapping[address] = instr - def get_label(self, adress: int) -> str: + def get_label(self, address: int) -> str: """Return the label at the given memory address if it exists, else an empty string""" - if adress in self.label_adress_mapping.keys(): - return self.label_adress_mapping[adress] + if address in self.label_address_mapping.keys(): + return self.label_address_mapping[address] return "" diff --git a/src/simudator/processor/mia/modules/micro_memory.py b/src/simudator/processor/mia/modules/micro_memory.py index e9aa9e464a92e5e06a84832815ca0892bb00ea20..5ff0fb694e752f8f8f68bcf990b439a4f7462b54 100644 --- a/src/simudator/processor/mia/modules/micro_memory.py +++ b/src/simudator/processor/mia/modules/micro_memory.py @@ -18,14 +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", + "_curr_instr", + "_z_flag_val", + "_n_flag_val", + "_c_flag_val", + "_o_flag_val", + "_l_flag_val", + "_memory", + "_halt", ) MEMORY_ADDRESS_PADDING = 2 @@ -113,15 +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 + 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: """ @@ -135,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 @@ -209,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) @@ -219,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) @@ -249,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 @@ -273,20 +272,20 @@ 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 get_parameter(self) -> dict: @@ -301,9 +300,9 @@ class MicroMemory(Module): 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 @@ -312,14 +311,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 _ 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 _ 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 @@ -337,8 +336,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: @@ -346,11 +345,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")) + ": " ) @@ -364,7 +363,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 @@ -376,7 +375,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..54f71b1d1885c922b069b5f1b12d032bee021bef 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,55 @@ 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]: + """Return a dictionary of the parameters of the program counter, + i.e. the bit length of the counter. + + 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 e2e600c6f039db5560fcf3dd4de33dac65372ce2..37992bfb0010ebe54ef7c69cbab4f2bcf062905e 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")