Skip to content
Snippets Groups Projects
Commit 19ae22d0 authored by Martin Högstedt's avatar Martin Högstedt
Browse files

Merge branch 'tick_break_points' into 'main'

Tick break points

Closes #31

See merge request !9
parents adda43d3 5512bb0a
No related branches found
No related tags found
1 merge request!9Tick break points
Pipeline #131513 failed
...@@ -73,6 +73,13 @@ class CLI: ...@@ -73,6 +73,13 @@ class CLI:
case ["rc"] | ["run_continuously"]: case ["rc"] | ["run_continuously"]:
self.processor.run_continuously() self.processor.run_continuously()
if self.processor.breakpoint_reached:
bp = self.processor.last_breakpoint
print(f"Reached breakpoint: {bp}")
if self.processor.should_halt():
print("The processor halted")
case ["r"] | ["resets"]: case ["r"] | ["resets"]:
# self.processor.load_cycle(0) # self.processor.load_cycle(0)
...@@ -86,6 +93,13 @@ class CLI: ...@@ -86,6 +93,13 @@ class CLI:
try: try:
for _ in range(int(user_input.split()[1])): for _ in range(int(user_input.split()[1])):
self.processor.do_tick() self.processor.do_tick()
if self.processor.is_stopped:
break
if self.processor.breakpoint_reached:
bp = self.processor.last_breakpoint
print(f"Reached breakpoint: {bp}")
if self.processor.should_halt():
print("The processor halted")
except ValueError: except ValueError:
print("Invalid value") print("Invalid value")
......
...@@ -48,8 +48,10 @@ class Processor: ...@@ -48,8 +48,10 @@ class Processor:
def do_tick(self) -> None: def do_tick(self) -> None:
""" """
Does one clock-cycle of the processor by running each modules Simulate one clock cycle of the processor.
tick function, then handels the following updates.
Run each module's tick function, then handle the following updates.
Also check for breakpoints that are reached in this cycle.
""" """
if len(self.module_history) > self.clock - self.removed_cycles: if len(self.module_history) > self.clock - self.removed_cycles:
# If a previous stored cycle has been loaded, discard # If a previous stored cycle has been loaded, discard
...@@ -58,6 +60,7 @@ class Processor: ...@@ -58,6 +60,7 @@ class Processor:
self.module_history = self.module_history[0:self.clock] self.module_history = self.module_history[0:self.clock]
self.signal_history = self.signal_history[0:self.clock] self.signal_history = self.signal_history[0:self.clock]
self.unstop()
self.save_cycle() self.save_cycle()
self.clock += 1 self.clock += 1
...@@ -71,34 +74,51 @@ class Processor: ...@@ -71,34 +74,51 @@ class Processor:
module = self.update_queue.pop(0) module = self.update_queue.pop(0)
module.update_logic() module.update_logic()
self.stop_at_breakpoints()
if self.should_halt():
self.stop()
def run_continuously(self): def run_continuously(self) -> None:
""" """
Runs the processor until it halts. Run the processor until it halts, is stopped or reaches a breakpoint.
""" """
while not self.should_halt() and not self.is_stopped: self.unstop()
while not self.is_stopped:
self.do_tick() self.do_tick()
# Print all reached breakpoints then exit the loop
self.breakpoint_reached = False
for _, bp in self.breakpoints.items():
#TODO: Can make this more efficient by only checking enabled breakpoints
if bp.is_break() and bp.is_enabled:
self.breakpoint_reached = True
self.last_breakpoint = bp
if self.breakpoint_reached:
return
def should_halt(self) -> bool: def should_halt(self) -> bool:
return False return False
def stop(self) -> None: def stop(self) -> None:
"""
Signal to stop the execution of the processor until the processor is
instructed to run continuously or do some ticks again.
"""
self.is_stopped = True self.is_stopped = True
def unstop(self) -> None: def unstop(self) -> None:
"""
Reset the stop execution signal.
"""
self.is_stopped = False self.is_stopped = False
def stop_at_breakpoints(self) -> None:
"""
Stop the execution if any breakpoint has been reached during this cycle.
Also record the breakpoint that was reached.
"""
self.breakpoint_reached = False
for _, bp in self.breakpoints.items():
#TODO: Can make this more efficient by only checking enabled breakpoints
if bp.is_break() and bp.is_enabled:
self.breakpoint_reached = True
self.last_breakpoint = bp
if self.breakpoint_reached:
self.stop()
def reset(self): def reset(self):
""" """
Resets all values in the processor and Resets all values in the processor and
......
...@@ -454,7 +454,6 @@ class GUI(QMainWindow): ...@@ -454,7 +454,6 @@ class GUI(QMainWindow):
steps = self.jump_value_box.value() steps = self.jump_value_box.value()
self.cpu_running = True self.cpu_running = True
self.setDisabledWhenRunning(True) self.setDisabledWhenRunning(True)
self.cpu.unstop()
simulation_thread = RunThread(self.cpu, self.cpu_tick_signal, self.update_delay, False, steps) simulation_thread = RunThread(self.cpu, self.cpu_tick_signal, self.update_delay, False, steps)
self.threadpool.start(simulation_thread) self.threadpool.start(simulation_thread)
...@@ -470,7 +469,6 @@ class GUI(QMainWindow): ...@@ -470,7 +469,6 @@ class GUI(QMainWindow):
# Create own thread for cpu simulation so gui dosent freeze # Create own thread for cpu simulation so gui dosent freeze
self.cpu_running = True self.cpu_running = True
self.setDisabledWhenRunning(True) self.setDisabledWhenRunning(True)
self.cpu.unstop()
simulation_thread = RunThread(self.cpu, self.cpu_tick_signal, self.update_delay) simulation_thread = RunThread(self.cpu, self.cpu_tick_signal, self.update_delay)
self.threadpool.start(simulation_thread) self.threadpool.start(simulation_thread)
...@@ -487,19 +485,6 @@ class GUI(QMainWindow): ...@@ -487,19 +485,6 @@ class GUI(QMainWindow):
if self.update_all_values: if self.update_all_values:
self.updateCpuListeners() self.updateCpuListeners()
# If a breakpoint halted the program, inform the user
# Update other visuals and set the cpu to the correct state (not running)
if self.cpu.breakpoint_reached:
self.messageBox("Reached breakpoint: " + self.cpu.last_breakpoint.__str__())
# When the CPU is done we want to inform the user and update visuals
if self.cpu.should_halt():
# Only show halted message for larger steps that take time
# This is done so a user dosent have to close
# the message box after every small step
if steps > self.HALT_MESSAGE_THRESHOLD:
self.messageBox("The processor halted.")
# A signal of 0 steps signifies end of execution, i.e. the CPU has # A signal of 0 steps signifies end of execution, i.e. the CPU has
# halted or run the specified amount of ticks # halted or run the specified amount of ticks
# => Enable the relevant parts of the GUI again # => Enable the relevant parts of the GUI again
...@@ -508,6 +493,14 @@ class GUI(QMainWindow): ...@@ -508,6 +493,14 @@ class GUI(QMainWindow):
self.setDisabledWhenRunning(False) self.setDisabledWhenRunning(False)
self.updateCpuListeners() self.updateCpuListeners()
# Inform user of reached break point
if self.cpu.breakpoint_reached:
self.messageBox("Reached breakpoint: " + self.cpu.last_breakpoint.__str__())
# Inform user of halt
if self.cpu.should_halt():
self.messageBox("The processor halted.")
def stopToolBarButtonClick(self) -> None: def stopToolBarButtonClick(self) -> None:
""" """
Tells the cpu to stop. It will then stop at an appropriate in its own thread. Tells the cpu to stop. It will then stop at an appropriate in its own thread.
......
...@@ -23,7 +23,8 @@ class RunThread(QRunnable): ...@@ -23,7 +23,8 @@ class RunThread(QRunnable):
def run(self): def run(self):
if self.run_continuously: if self.run_continuously:
while not self.cpu.should_halt() and not self.cpu.is_stopped: self.cpu.unstop()
while not self.cpu.is_stopped:
self.cpu.do_tick() self.cpu.do_tick()
self.signal.emit(1) self.signal.emit(1)
time.sleep(self.delay) time.sleep(self.delay)
...@@ -34,5 +35,8 @@ class RunThread(QRunnable): ...@@ -34,5 +35,8 @@ class RunThread(QRunnable):
self.signal.emit(1) self.signal.emit(1)
time.sleep(self.delay) time.sleep(self.delay)
if self.cpu.is_stopped:
break
# Signal end of execution as having run 0 ticks # Signal end of execution as having run 0 ticks
self.signal.emit(0) self.signal.emit(0)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment