Skip to content
Snippets Groups Projects
Commit 15ecc403 authored by Oscar Gustafsson's avatar Oscar Gustafsson :bicyclist:
Browse files

Merge branch 'flagmove' into 'main'

Initial approach for unifying Flag and Register

See merge request johku144/simudator!3
parents 74fdde6b 4a4fe643
No related branches found
No related tags found
1 merge request!3Initial approach for unifying Flag and Register
Pipeline #104078 passed
from .demux import Demux
from .flag import Flag
from .memory import Memory
from .mux import Mux
from .register import Register
from .register import Flag, IntegerRegister, Register
__all__ = ["Demux", "Flag", "Memory", "Mux", "Register"]
__all__ = ["Demux", "Flag", "IntegerRegister", "Memory", "Mux", "Register"]
from __future__ import annotations
from typing import Any
from simudator.core.module import Module
from simudator.core.signal import Signal
class Flag(Module):
"""
A simple module that can store a value. This module is also
updated during the 'update logic' phase.
"""
def __init__(self, input_signal: Signal, output_signal: Signal,
bit_length=1, value=0, name="Flag") -> None:
# set the flags name
super().__init__(name)
# signals
self.input_s = input_signal
self.output_s = output_signal
self.value = value
# set the flag as destination of its input signal
self.input_s.add_destination(self)
# set the bit length of the register
self.bit_length = bit_length
# set the flags mask
self.mask = 2**bit_length -1
def update_register(self) -> None:
"""
Propagate the input signal to the flags internal state.
Throw away bits larger than the length of the flag.
"""
input_value = self.input_s.get_value()
if input_value is not None:
self.value = input_value & self.mask
def output_register(self) -> None:
"""
Propagate the value of the flag to the output signal.
It is the response of the destination to know when it should
read the output.
"""
self.output_s.update_value(self.value)
def update_logic(self):
"""
The flag has no logic but it still need to be updated during
the update logic phase. This is due the fact that the flag
should update the same tick as the change that causes the flag
to activate (ex: loop counter reaches zero -> set L flag to 1)
"""
input_value = self.input_s.get_value()
self.value = input_value & self.mask
def get_state(self) -> dict[str: Any]:
"""
Returns a dict of the register state.
These states are changable via set_states.
"""
state = super().get_state()
state["value"] = self.value
state["bit_length"] = self.bit_length
state["mask"] = self.mask
return state
def get_gui_state(self) -> dict:
state = super().get_gui_state()
state["value"] = self.value
return state
def set_state(self, state: dict[str: Any]) -> None:
"""
Sets the register state to one given in dict.
"""
self.name = state["name"]
self.value = state["value"]
if "bit_length" in state:
self.bit_length = state["bit_length"]
if "mask" in state:
self.mask = state["mask"]
def reset(self) -> None:
"""
Resets the flag to value 0.
"""
self.value = 0
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 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)
def print_module(self) -> None:
print("", self.name, "\n -----",
"\n value: ", self.value,
"\n bit length: ", self.bit_length,
"\n mask: ", self.mask,
)
......@@ -42,7 +42,7 @@ class Mux(Module):
def update_register(self) -> None:
"""
Read which signal to read from from the control signal
Read which signal to read from the control signal
'to_mux_s' and forward that signal to the output.
"""
input_index = self.to_mux_s.get_value()
......
......@@ -13,7 +13,7 @@ class Register(Module):
def __init__(self, input_signal: Signal,
output_signal: Signal,
value=0, name="Register") -> None:
value: Any = 0, name: str = "Register") -> None:
# set the registers name
super().__init__(name)
......@@ -104,7 +104,7 @@ class IntegerRegister(Register):
"""
def __init__(self, input_signal: Signal, output_signal: Signal,
bit_length: int, value: int=0, name=None) -> None:
bit_length: int, value: int = 0, name: str | None = None) -> None:
# set the registers name
if name is None:
......@@ -117,7 +117,7 @@ class IntegerRegister(Register):
# set the registers mask. An 8 bit register should
# have the mask 1111 1111, aka one '1' for every bit
self.mask = 2**bit_length -1
self.mask = 2**bit_length - 1
def update_register(self) -> None:
"""
......@@ -134,7 +134,6 @@ class IntegerRegister(Register):
"""
state = super().get_state()
state["bit_length"] = self.bit_length
state["mask"] = self.mask
return state
def set_state(self, state: dict[str: Any]) -> None:
......@@ -146,15 +145,6 @@ class IntegerRegister(Register):
self.bit_length = state["bit_length"]
self.mask = 2**self.bit_length -1
def reset(self) -> None:
self.value = 0
def get_input_signals(self) -> list[Signal]:
return [self.input_s]
def get_output_signals(self) -> list[Signal]:
return [self.output_s]
def save_state_to_file(self, file_path: str) -> None:
"""
Tries to save the modules state to a given file.
......@@ -168,3 +158,57 @@ class IntegerRegister(Register):
string_pair = state_string.split(": ")
#TODO: Maybe check if it starts with value: ?
self.value = int(string_pair[1], 16)
class Flag(IntegerRegister):
"""
A simple module that can store a value. This module is also
updated during the 'update logic' phase.
"""
def __init__(self, input_signal: Signal, output_signal: Signal,
bit_length=1, value=0, name="Flag") -> None:
# set the flags name
super().__init__(input_signal=input_signal, output_signal=output_signal,
bit_length=bit_length, value=value, name=name)
def output_register(self) -> None:
"""
Propagate the value of the flag to the output signal.
It is the response of the destination to know when it should
read the output.
"""
self.output_s.update_value(self.value)
def update_logic(self):
"""
The flag has no logic but it still need to be updated during
the update logic phase. This is due the fact that the flag
should update the same tick as the change that causes the flag
to activate (ex: loop counter reaches zero -> set L flag to 1)
"""
input_value = self.input_s.get_value()
self.value = input_value & self.mask
def get_gui_state(self) -> dict:
state = super().get_gui_state()
state["value"] = self.value
return state
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("", self.name, "\n -----",
"\n value: ", self.value,
"\n bit length: ", self.bit_length,
"\n mask: ", self.mask,
)
......@@ -3,7 +3,7 @@ import sys
from qtpy.QtWidgets import QApplication
from simudator.cli.cli import CLI
from simudator.core.modules.flag import Flag
from simudator.core.modules import Flag
from simudator.core.modules.register import IntegerRegister
from simudator.core.processor import Processor, Signal
from simudator.gui.gui import GUI
......
from simudator.core.modules.flag import Flag
from simudator.core.modules import Flag
from simudator.core.processor import Processor
from simudator.core.signal import Signal
from simudator.processor.mia.lc import LC
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment