diff --git a/mia_uppg3.txt b/mia_uppg3.txt index d61dbb62df11c36dc704cb7cd0ed5c2711dc54a6..b752d1a8049af126da4c59eb188d6765e8bb78ee 100644 --- a/mia_uppg3.txt +++ b/mia_uppg3.txt @@ -387,22 +387,22 @@ uM: 7f: 0000000 K1: -00: 0a ADD -01: 0b SUB -02: 0c MULT -03: 0f NOP -04: 12 TEST -05: 15 D -06: 1a R -07: 1d T -08: 1f TT -09: 20 TT -0a: 22 TTT -0b: 27 TTTT -0c: 00 FR -0d: 00 FH -0e: 00 LF -0f: 00 FFF +00: 0a LOAD +01: 0b STORE +02: 0c ADD +03: 0f SUB +04: 12 AND +05: 15 LSR +06: 1a BRA +07: 1d BNE +08: 1f HALT +09: 20 CMP +0a: 22 BGE +0b: 27 BEQ +0c: 00 +0d: 00 +0e: 00 +0f: 00 K2: 00: 03 diff --git a/src/simudator/core/processor.py b/src/simudator/core/processor.py index 91882c7925157c8cfaca04164b8fa2de6f03f894..bb33eb9f836ef8c14247bf4440ce1e1fa7c5be5a 100644 --- a/src/simudator/core/processor.py +++ b/src/simudator/core/processor.py @@ -37,7 +37,13 @@ class Processor: self.line_seperator = "-" self.is_stopped = False self.new_instruction = False - self.current_instructions: list[str] = [] + + # It is the responsibility of the CPU to tell the gui:s pipeline diagram + # what information to be displayed and how to display it. + # Thus each CPU keeps track of its current instructions together with each + # instructions position in the pipeline diagram. + self.current_instructions: list[tuple[str, int, int]] = [] + # TODO: keeping track of what pieces of info not to show # show not be done at the processor level. # Maybe implemenet a 'get_pretty_print_state' at module @@ -93,14 +99,34 @@ class Processor: # new assembly instruction if self.is_new_instruction(): self.new_instruction = True - self.current_instruction = self.get_current_instruction() + self.current_instructions = self.get_current_instructions() self.assembly_cycles.append(self.get_clock()) else: self.new_instruction = False - def get_current_instruction(self) -> str: + def get_current_instructions(self) -> list[tuple[str, int, int]]: + """ + Return a list of the current instructions with their positions. + + Each entry in the list is a tuple of a instruction with its column and row position + for the pipeline diagram. + """ + raise NotImplemented + + def get_pipeline_dimensions(self) -> tuple[int, int]: """ - Return the current instruction. Useful for pipeline diagram. + Return a tuple on the form (x, y) for the processors preffered pipeline display size. + + (x, y) represents the number of columns respective rows the pipeline should have. + """ + raise NotImplemented + + def get_asm_instruction(self) -> str: + """ + Return a string containing the 'code' for the current assembly instruction. + + What 'code' refers to is up to each processor to define, could be a memory address, + an instruction label or something else. """ raise NotImplemented @@ -396,7 +422,7 @@ class Processor: memory_modules = [] other_modules = [] - if ignore_keys == None: + if ignore_keys is None: ignore_keys = [] # TODO: remove isinstance(module, micro_memory) diff --git a/src/simudator/gui/gui.py b/src/simudator/gui/gui.py index 825164f619a955d230c9b401701ba3ab7891ebc8..94e61e82608032f45b76d977261749b13b65120c 100644 --- a/src/simudator/gui/gui.py +++ b/src/simudator/gui/gui.py @@ -132,8 +132,7 @@ class GUI(QMainWindow): self.cpu_running = False self.pipeline = PipeLine() - # Hide pipeline for now since it is not implemented yet - # self.pipeline.show() + self.init_pipeline() # Set Style, THESE ARE TEST AND DONT WORK app = QApplication.instance() @@ -363,14 +362,31 @@ class GUI(QMainWindow): case "CLOCKUPDATE": signal.connect(self.updateCpuClockCycle) + def init_pipeline(self) -> None: + """Initialize the pipeline diagram. + + Sets its height, width and instructions. + """ + size = self.cpu.get_pipeline_dimensions() + + self.pipeline.set_height(size[0]) + self.pipeline.set_width(size[1]) + self.update_pipeline() + + self.pipeline.show() + def updateCpuListeners(self) -> None: """ - Updates the graphics items in the scene and the clock. + Updates the graphics items in the scene, the clock, and the pipeline diagram. Used after the cpu has run or when the user has edited somehting. """ self.cpu_graphics_scene.updateGraphicsItems() self.updateCpuClockCycle() + self.update_pipeline() + + def update_pipeline(self) -> None: + self.pipeline.set_instructions(self.cpu.get_current_instructions()) def updateCpuClockCycle(self) -> None: """ diff --git a/src/simudator/gui/pipeline.py b/src/simudator/gui/pipeline.py index 9023ef17475fa40212b42481e56e0235b0a12bf7..fc9d78012115a011bfc6574414ba6c8a478b6a67 100644 --- a/src/simudator/gui/pipeline.py +++ b/src/simudator/gui/pipeline.py @@ -3,7 +3,6 @@ from typing import Any from qtpy.QtWidgets import QTableWidget, QTableWidgetItem -# TODO: Make the table unediatable class PipeLine(QTableWidget): """ A class showing the current CPU instructions in a seperate window. @@ -14,27 +13,40 @@ class PipeLine(QTableWidget): def __init__(self): super().__init__() - # Values below are temporary test values + + def set_instructions(self, instructions: list[tuple[str, int, int]]) -> None: """ - self.setRowCount(5) - self.setColumnCount(5) - self.instructions = ["Add", "Sub", "Mult", "Fetch", "Nop"] - self.set_item(0, 0, self.instructions[0]) - self.set_item(1, 1, self.instructions[1]) - self.set_item(2, 2, self.instructions[2]) - self.set_item(3, 3, self.instructions[3]) + Give the pipeline the current CPU instructions. + + Parameters + ---------- + instructions: A list of tuples of a string and two ints. + The string containing the current instruction where the two ints + represents the instructions col and row position. + + See Also + -------- + simudator.core.processor.get_current_instructions : + Instructions are set from get_current_instructions() in the Processor class. """ - def set_instruction(self, instructions: list[str]) -> None: - """Give the pipeline the current CPU instructions.""" self.instructions = instructions + for i in range(len(self.instructions)): + instruction = self.instructions[i][0] + col = self.instructions[i][1] + row = self.instructions[i][2] + self.set_item(row, col, instruction) def set_height(self, height: int) -> None: - """Sets the height of the pipeline.""" + """ + Sets the height of the pipeline. + """ self.setColumnCount(height) def set_width(self, width: int) -> None: - """Sets the width of the pipeline.""" + """ + Sets the width of the pipeline. + """ self.setRowCount(width) def set_row_labels(self, labels: list[str]) -> None: @@ -60,7 +72,9 @@ class PipeLine(QTableWidget): raise NotImplemented def set_item(self, row: int, col: int, text: str) -> None: - """Sets the text at position col row to the given text.""" + """ + Sets the text at position col row to the given text. + """ item = QTableWidgetItem(text) self.setItem(row, col, item) diff --git a/src/simudator/processor/mia/mia.py b/src/simudator/processor/mia/mia.py index 724ad94bedb46e5ab898ce607003f193b5a94f93..99f7b7aafa81ee8372ee9ccb27e5cb2456932dc1 100644 --- a/src/simudator/processor/mia/mia.py +++ b/src/simudator/processor/mia/mia.py @@ -1,5 +1,7 @@ import sys +from typing import Any + from simudator.cli.cli import CLI from simudator.core.modules import Flag from simudator.core.modules.register import IntegerRegister @@ -281,9 +283,28 @@ class MIA_CPU(Processor): def is_new_instruction(self) -> bool: return self.get_module("uPC").value == 0 - def get_current_instruction(self) -> str: + def get_current_instructions(self) -> list[tuple[str, int, int]]: + asm_instr = self.get_asm_instruction() + micro_instr = self.get_micro_instruction() + asm = (asm_instr, 1, 0) + micro = (micro_instr, 1, 1) + asm_title = ("Assembler", 0, 0) + micro_title = ("Micro", 0, 1) + return [asm, micro, asm_title, micro_title] + + def get_micro_instruction(self) -> str: + """ + Return a string containing the address for the current micro instruction in hex, e.g. 0a4b. + """ + uM = self.get_module("uM").get_state() + curr_instr = uM["curr_instr"] + memory = uM["memory"] + + return '0x' + format(memory[curr_instr], '07x') + + def get_asm_instruction(self) -> str: """ - Return a string containing the label for the current instruction. + Return a string containing the label for the current assembly instruction. If the label doesnt exist, the string is empty. """ @@ -291,6 +312,14 @@ class MIA_CPU(Processor): op_code = ir.op return self.get_module("K1").get_label(int(op_code)) + def get_pipeline_dimensions(self) -> tuple[int, int]: + """ + Mia should show the current assembly instruction and the current micro instruction. + + One Extra column to specify what the values represent. + """ + return (2, 2) + def run_asm_instruction(self, num_instructions=1) -> None: """ Runs 'num_instructions' assembler instructions on Mia. diff --git a/src/simudator/processor/mia/modules/micro_memory.py b/src/simudator/processor/mia/modules/micro_memory.py index 7eb789584135f1e31dfbf09311bc8bea327da89d..8915c5ed2f7ae4d51dd2cd7f5c22400f812fe1af 100644 --- a/src/simudator/processor/mia/modules/micro_memory.py +++ b/src/simudator/processor/mia/modules/micro_memory.py @@ -274,6 +274,7 @@ class MicroMemory(Module): state = super().get_state() state["memory"] = self.memory[:] state["halt"] = self.halt + state["curr_instr"] = self.curr_instr return state def get_gui_state(self) -> dict[str, Any]: