Skip to content
Snippets Groups Projects
Commit 968dd133 authored by Johannes Kung's avatar Johannes Kung
Browse files

Merge branch '11-count-clock-cycles' into 'main'

Resolve "Count clock cycles"

Closes #29 and #11

See merge request !6
parents 58f2a69c c6d3f374
No related branches found
No related tags found
1 merge request!6Resolve "Count clock cycles"
Pipeline #131475 failed
......@@ -2,6 +2,7 @@ import ast
import json
import sys
from json import JSONDecodeError
from threading import Thread
from qtpy import QtCore, QtWidgets
from qtpy.QtCore import QPointF
......@@ -89,7 +90,7 @@ class GUI(QMainWindow):
and added individually.
"""
halted_signal = pyqtSignal(int)
cpu_tick_signal = pyqtSignal(int)
HALT_MESSAGE_THRESHOLD = 100
def __init__(self, cpu: Processor):
......@@ -113,7 +114,7 @@ class GUI(QMainWindow):
self.threadpool = QtCore.QThreadPool()
# Signal to tell gui when cpu has halted
self.halted_signal.connect(self.cpuHaltedFunction)
self.cpu_tick_signal.connect(self.handleCpuTick)
# Used to lock some actions in ui when cpu is running in another thread
# Using the cpu's internal status directly could case problems
......@@ -284,13 +285,24 @@ class GUI(QMainWindow):
signal.connect(self.addLambdaBreakpoint)
case "UPDATE":
signal.connect(self.updateCpuListeners)
case "CLOCKUPDATE":
signal.connect(self.updateCpuClockCycle)
def updateCpuListeners(self) -> None:
"""
Updates the graphics items in the scene and the clock.
Used after the cpu has run or when the user has edited somehting.
"""
self.cpu_graphics_scene.updateGraphicsItems()
self.updateCpuClockCycle()
def updateCpuClockCycle(self) -> None:
"""
Update the clock cycle counter.
Used while the program is running to show the user nothing has crashed.
"""
self.clock_label.setText("Clockcycle: " + str(self.cpu.get_clock()))
def lambdaBreakpointDialog(self) -> None:
......@@ -422,9 +434,9 @@ class GUI(QMainWindow):
self.cpu_running = True
self.setDisabledWhenRunning(True)
self.cpu.unstop()
simultaion_thread = RunThread(self.cpu, self.halted_signal, False, steps)
self.threadpool.start(simultaion_thread)
self.updateCpuListeners()
simulation_thread = RunThread(self.cpu, self.cpu_tick_signal, False, steps)
self.threadpool.start(simulation_thread)
# self.updateCpuListeners()
def runToolBarButtonClick(self) -> None:
"""
......@@ -439,27 +451,41 @@ class GUI(QMainWindow):
self.cpu_running = True
self.setDisabledWhenRunning(True)
self.cpu.unstop()
simultaion_thread = RunThread(self.cpu, self.halted_signal)
self.threadpool.start(simultaion_thread)
simulation_thread = RunThread(self.cpu, self.cpu_tick_signal)
self.threadpool.start(simulation_thread)
self.updateCpuListeners()
@Slot(int)
def cpuHaltedFunction(self, steps: int) -> None:
def handleCpuTick(self, steps: int) -> None:
"""
Called from other thread when cpu has halted.
Called from other thread after every cpu tick.
Will inform the user and update visuals.
"""
# If a breakpoint halted the program inform thr user
# Update cpu clock counter every tick
self.updateCpuClockCycle()
# 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__())
# 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
elif steps > self.HALT_MESSAGE_THRESHOLD:
self.messageBox("The processor halted.")
self.updateCpuListeners()
self.cpu_running = False
self.setDisabledWhenRunning(False)
self.updateCpuListeners()
# 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.")
self.updateCpuListeners()
# A signal of 0 steps signifies end of execution, i.e. the CPU has
# halted or run the specified amount of ticks
# => Enable the relevant parts of the GUI again
if steps == 0:
self.cpu_running = False
self.setDisabledWhenRunning(False)
def stopToolBarButtonClick(self) -> None:
"""
......
import time
from qtpy.QtCore import QRunnable
CPU_TICK_DELAY = 0.0000001
class RunThread(QRunnable):
"""
This class is used to run the cpu on a seperate thread.
This allows the user to interact with the GUI will th cpu is running.
When the cpu halts this thread will emit to it's given signal
the GUI can then handel what should happend after execution on its own.
This class is used to run the simulated cpu several ticks or continuously on
a seperate thread. This allows the user to interact with the GUI while the
simulation is running.
After each cpu tick, this thread will emit to its given QT signal so that
the GUI can update itself and possibly inform the user of when the execution
has halted.
"""
def __init__(self, cpu, signal, run_continuously=True, steps=0):
......@@ -18,10 +24,16 @@ class RunThread(QRunnable):
def run(self):
if self.run_continuously:
self.cpu.run_continuously()
while not self.cpu.should_halt() and not self.cpu.is_stopped:
self.cpu.do_tick()
self.signal.emit(1)
time.sleep(CPU_TICK_DELAY)
else:
for _ in range(self.steps):
self.cpu.do_tick()
self.signal.emit(1)
time.sleep(CPU_TICK_DELAY)
self.signal.emit(self.steps)
# Signal end of execution as having run 0 ticks
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