diff --git a/src/simudator/core/processor.py b/src/simudator/core/processor.py index 1fc0ee17a7f26ac14474125ecc740b63eb23eda4..405bfbe36c89bf36dec0a4d41177a6d75447dc07 100644 --- a/src/simudator/core/processor.py +++ b/src/simudator/core/processor.py @@ -56,7 +56,8 @@ class Processor: Simulate one clock cycle of the processor. Run each module's tick function, then handle the following updates. - Also check for breakpoints that are reached in this cycle. + Also check for breakpoints that are reached in this cycle, and save + clock cycles when new assemly instructions are started. """ if len(self.module_history) > self.clock - self.removed_cycles: # If a previous stored cycle has been loaded, discard @@ -83,6 +84,15 @@ class Processor: if self.should_halt(): self.stop() + # Set new_instruction and save clock cycle for each + # new assembly instruction + if self.is_new_instruction(): + self.new_instruction = True + self.current_instruction = self.get_current_instrution() + self.assembly_cycles.append(self.get_clock()) + else: + self.new_instruction = False + def get_current_instrution(self) -> str: """ Return the current instruction. Useful for pipeline diagram. @@ -101,13 +111,41 @@ class Processor: def undo_asm_instruction(self, num_instructions = 1) -> None: """ - Undos 'num_instructions' numbers of assembler instructions on the processors. + Undos 'num_instructions' numbers of assembler instructions on the CPU. Default argument is one, but it is possible to specify any number of instructions. - This should be implemented per processor and thus we raise NotImplemented. + Undo assembler instrucion assumes the CPU is always at the end of the list + 'self.assembly_cycles'. + + Undos asm instructions by finding the corresponding clock cycle before + said number of asm intructions started and loading that clock cycle. """ - raise NotImplemented + current_clock_cycle = self.clock + index = len(self.assembly_cycles) + saved_cycle = self.assembly_cycles[index-1] + + # Make sure we are undoing the instruction(s) we are currently on + while saved_cycle >= current_clock_cycle: + index -= 1 + saved_cycle = self.assembly_cycles[index-1] + + index -= num_instructions + + # We cant undo more instructions than we have performed. + if index < 0: + raise IndexError + + clockcycle = self.assembly_cycles[index] + + self.load_cycle(clockcycle) + + # Need +1 here since we save the start state to enable to + # load the start state. This is done since we only append clock + # cycles to the list self.assembly_cycles when we reach a new state + # that has uPC set to 0, which wont happend when we load a new file. + self.assembly_cycles = self.assembly_cycles[:index+1] + def run_continuously(self) -> None: """ @@ -135,9 +173,9 @@ class Processor: def is_new_instruction(self) -> bool: """ - Returns true on the same clock cycle the CPU starts a new instruciton. + Return true on the same clock cycle the CPU starts a new instruciton. - Should be implemented per CPU, returns field new_instruction. It is up to each + Should be implemented per CPU, return field new_instruction. It is up to each processor to set this field to True/False correctly. """ return self.new_instruction @@ -510,7 +548,7 @@ class Processor: def get_most_fields(self, modules: dict[Module: int], ignore_keys=[]) -> int: """ - Returns the most number of a fields a module has. Can optionally + Return the most number of a fields a module has. Can optionally ignore keys. """ fields = 0 diff --git a/src/simudator/gui/gui.py b/src/simudator/gui/gui.py index a03653469d5b0b088ef001b42f447857c24e21b4..88f8a27d084ea39cd1d6e3c769693f0ef165f56f 100644 --- a/src/simudator/gui/gui.py +++ b/src/simudator/gui/gui.py @@ -574,7 +574,7 @@ class GUI(QMainWindow): def folderSaveDialog(self) -> str: """ - Opens a file explorer in a new window. Returns the absolute path to the selected file. + Opens a file explorer in a new window. Return the absolute path to the selected file. """ dialog = QFileDialog() dialog.setFileMode(QFileDialog.AnyFile) @@ -585,7 +585,7 @@ class GUI(QMainWindow): def folderLoadDialog(self) -> str: """ - Opens a file explorer in a new window. Returns the absolute path to the selected file. + Opens a file explorer in a new window. Return the absolute path to the selected file. """ dialog = QFileDialog() dialog.setFileMode(QFileDialog.AnyFile) diff --git a/src/simudator/gui/pipeline.py b/src/simudator/gui/pipeline.py index 75ad99e7ab647d1593e93cac8073ec8b57837283..2c400c06f93411d368b117796136d577687c94f0 100644 --- a/src/simudator/gui/pipeline.py +++ b/src/simudator/gui/pipeline.py @@ -26,7 +26,7 @@ class PipeLine(QTableWidget): def set_instruction(self, instructions: list[str]) -> None: """Give the pipeline the current CPU instructions.""" - self.instrucitons = instructions + self.instructions = instructions def set_height(self, height: int) -> None: """Sets the height of the pipeline.""" diff --git a/src/simudator/processor/mia/mia.py b/src/simudator/processor/mia/mia.py index 8b87db102fa8aa245af13d7e1e991dc62bfbac19..49b996262c1e672ccb1c3a8064ee6d4f8e4bd9f9 100644 --- a/src/simudator/processor/mia/mia.py +++ b/src/simudator/processor/mia/mia.py @@ -283,23 +283,13 @@ class MIA_CPU(Processor): self.lambdas = {} - def do_tick(self) -> None: - """Mia has special assembly related behaviour. - This includes fetching the curret asm instruction, and saving the current clock - cycle in a list to enable stepping back over assembly instructions. - """ - super().do_tick() - if self.get_module("uPC").value == 0: - self.new_instruction = True - self.current_instruction = self.get_current_instrution() - self.assembly_cycles.append(self.get_clock()) - else: - self.new_instruction = False + def is_new_instruction(self) -> bool: + return self.get_module("uPC").value == 0 def get_current_instrution(self) -> str: """ - Returns a string containing the label for the current instruction. + Return a string containing the label for the current instruction. If the label doesnt exist, the string is empty. """ @@ -323,43 +313,6 @@ class MIA_CPU(Processor): self.do_tick() - def undo_asm_instruction(self, num_instructions = 1) -> None: - """ - Undos 'num_instructions' numbers of assembler instructions on Mia. - - Default argument is one, but it is possible to specify any number of instructions. - Undo assembler instrucion assumes the CPU is always at the end of the list - 'self.assembly_cycles'. - - Undos asm instructions by finding the corresponding clock cycle before - said number of asm intructions started and loading that clock cycle. - """ - - current_clock_cycle = self.clock - index = len(self.assembly_cycles) - saved_cycle = self.assembly_cycles[index-1] - - # Make sure we are undoing the instruction(s) we are currently on - while saved_cycle >= current_clock_cycle: - index -= 1 - saved_cycle = self.assembly_cycles[index-1] - - index -= num_instructions - - # We cant undo more instructions than we have performed. - if index < 0: - raise IndexError - - clockcycle = self.assembly_cycles[index] - - self.load_cycle(clockcycle) - - # Need +1 here since we save the start state to enable to - # load the start state. This is done since we only append clock - # cycles to the list self.assembly_cycles when we reach a new state - # that has uPC set to 0, which wont happend when we load a new file. - self.assembly_cycles = self.assembly_cycles[:index+1] - def should_halt(self) -> bool: micro_memory_state = self.micro_memory.get_state()