diff --git a/.gitignore b/.gitignore index 31a2ae473b61b58e212f445c2e5511401fc19ff1..dae54c3ada7b570b393b6ec95dc20570e1ef06c3 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,10 @@ test_save_to_file test_save_to_file_layout cpu_save_file +# mock files +mock* +dummy + *~ *.autosave *.a diff --git a/dummy b/dummy new file mode 100644 index 0000000000000000000000000000000000000000..50f62b930aa7bfb53b977188d487bb992fcd103b --- /dev/null +++ b/dummy @@ -0,0 +1,3 @@ +a: +value:: 1 + diff --git a/mock_file b/mock_file new file mode 100644 index 0000000000000000000000000000000000000000..704d1e4125be1a06e285f4c73c2210b690a96287 --- /dev/null +++ b/mock_file @@ -0,0 +1,75 @@ +a: +value:: 1 + +a: +value:: 1 + +a: +value:: 1 + +a: +value:: 1 + +a: +value:: 1 + +a: +value:: 1 + +a: +value:: 1 + +a: +value:: 1 + +a: +value:: 1 + +a: +value:: 1 + +a: +value:: 1 + +a: +value:: 1 + +a: +value:: 1 + +a: +value:: 1 + +a: +value:: 1 + +a: +value:: 1 + +a: +value:: 1 + +a: +value:: 1 + +a: +value:: 1 + +a: +value:: 1 + +a: +value:: 1 + +a: +value:: 1 + +a: +value:: 1 + +a: +value:: 1 + +a: +value:: 1 + diff --git a/mock_file.txt b/mock_file.txt new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/simudator/core/processor.py b/src/simudator/core/processor.py index 061bec12e280e77fa84bd28235f918e781fec6db..35044c6cea2684e02ff4bc9e28be9839b3aec122 100644 --- a/src/simudator/core/processor.py +++ b/src/simudator/core/processor.py @@ -513,11 +513,11 @@ class Processor: file.close() for module in self.modules.values(): - res =module.save_state_to_file(file_path) + res = module.save_state_to_file(file_path) if not res: return False - + return True def pretty_print(self) -> None: diff --git a/test/test_core/test_breakpoint.py b/test/test_core/test_breakpoint.py index 01f115d012ba1a4cf042244d71761be28dd28673..ec961f4ee887db8e5ad28f493c41b38b2e16ca74 100644 --- a/test/test_core/test_breakpoint.py +++ b/test/test_core/test_breakpoint.py @@ -5,6 +5,7 @@ from simudator.core.module import Module from simudator.core.modules.memory import Memory from simudator.core.processor import Processor from simudator.core.signal import Signal +from simudator.processor.mia.modules.lc import LC class DummyModule(Module): @@ -184,3 +185,120 @@ def test_lambda_breakpoint_ref_args(): dummy.value = value assert bp.is_break() == func_dummy_val(dummy, value) assert bp.is_break() == (not func_dummy_val(dummy, not value)) + + +def test_add_remove_memory_breakpoint(): + """ + Test that the cpu properly add/removes memory breakpoints. + + Id counter starts at 1 and is only incremented. + """ + cpu = Processor() + in_s = Signal(cpu) + out_s = Signal(cpu) + ctrl_s = Signal(cpu) + adr_s = Signal(cpu) + mem = Memory(in_s, out_s, ctrl_s, adr_s, 8) + cpu.add_module(mem) + + assert len(cpu.breakpoints) == 0 + assert cpu.breakpoint_id_counter == 1 + cpu.add_memory_breakpoint("Memory", 1, 1) + assert cpu.breakpoint_id_counter == 2 + assert len(cpu.breakpoints) == 1 + assert cpu.remove_breakpoint(1) == True + assert cpu.breakpoints == {} + assert len(cpu.breakpoints) == 0 + + +def test_stop_on_memory_breakpoint(): + """ + Test that the cpu properly stops on a memory breakpoint. + """ + cpu = Processor() + in_s = Signal(cpu) + out_s = Signal(cpu) + ctrl_s = Signal(cpu) + adr_s = Signal(cpu) + mem = Memory(in_s, out_s, ctrl_s, adr_s, 8) + cpu.add_module(mem) + assert mem._memory == [0 for _ in range(8)] + assert cpu.clock == 0 + + in_s.update_value(1) + ctrl_s.update_value(True) + adr_s.update_value(2) + + # Add breakpoint if address 3 reaches value 1 + cpu.add_memory_breakpoint("Memory", 2, 1) + cpu.set_enabled_breakpoint(1, True) + cpu.run_continuously() + assert mem._memory == [0, 0, 1, 0, 0, 0, 0, 0] + assert cpu.is_stopped == True + assert cpu.clock == 2 + + mem._memory = [0 for _ in range(8)] + in_s.update_value(1) + ctrl_s.update_value(True) + adr_s.update_value(2) + cpu.set_enabled_breakpoint(1, False) + cpu.do_tick() + assert cpu.is_stopped == False + + +def test_add_remove_state_breakpoint(): + """ + Test that the cpu properly adds/removes state breakpoints. + + Id counter starts at 1 and is only incremented. + """ + cpu = Processor() + s = Signal(cpu) + lc = LC(s, s, s, s) + cpu.add_module(lc) + + assert len(cpu.breakpoints) == 0 + assert cpu.breakpoint_id_counter == 1 + cpu.add_state_breakpoint("LC", "value", 1) + assert len(cpu.breakpoints) == 1 + assert cpu.breakpoint_id_counter == 2 + assert cpu.remove_breakpoint(1) == True + assert cpu.breakpoints == {} + assert len(cpu.breakpoints) == 0 + + +def test_stop_on_state_breakpoint(): + """ + Test that the cpu properly stops on a state breakpoint. + """ + cpu = Processor() + mM_control = Signal(cpu) + + # Sets the behaviour of the LC to decrement by one each tick + mM_control.set_value(1) + + bus_input = Signal(cpu) + l_flag = Signal(cpu) + mM_uADR = Signal(cpu) + lc = LC(mM_control, bus_input, l_flag, mM_uADR) + + lc.value = 10 + cpu.add_module(lc) + + cpu.add_state_breakpoint("LC", "value", 5) + cpu.run_continuously() + assert lc.value == 5 + assert cpu.is_stopped == True + + cpu.add_state_breakpoint("LC", "value", 2) + cpu.run_continuously() + assert lc.value == 2 + assert cpu.is_stopped == True + + # 'Reset' loop counter and turn off previous breakpoint + lc.value = 10 + cpu.set_enabled_breakpoint(1, False) + cpu.set_enabled_breakpoint(2, False) + for _ in range(10): + cpu.do_tick() + assert cpu.is_stopped == False diff --git a/test/test_core/test_reset.py b/test/test_core/test_reset.py new file mode 100644 index 0000000000000000000000000000000000000000..6d84136c19bafa0f5bd8e314329dd2b7e293f880 --- /dev/null +++ b/test/test_core/test_reset.py @@ -0,0 +1,56 @@ +from simudator.core.module import Module +from simudator.core.modules.memory import Memory +from simudator.core.processor import Processor +from simudator.core.signal import Signal +from simudator.processor.mia.modules.lc import LC + + +class DummyModule(Module): + def __init__(self): + self.name = "name" + self.a = 4 + self.b = "a" + self.c = [1, 2, 3] + + def reset(self): + self.name = "dummy" + self.a = 0 + self.b = "" + self.c = [] + + def get_state(self): + return { + "name": self.name, + "a": self.a, + "b": self.b, + "c": self.c, + } + + def output_register(self): + pass + + def update_logic(self): + pass + + +def test_reset(): + cpu = Processor() + cpu.signal_history = ["this", "should", "be", "removed"] + dummy = DummyModule() + cpu.clock = 100 + cpu.removed_cycles = 1337 + cpu.module_history.append(dummy.get_state()) + cpu.signal_history.clear() + cpu.removed_cycles = 0 + cpu.assembly_cycles = [i for i in range(9)] + cpu.add_module(dummy) + cpu.reset() + assert dummy.name == "dummy" + assert dummy.a == 0 + assert dummy.b == "" + assert dummy.c == [] + assert cpu.clock == 0 + assert cpu.removed_cycles == 0 + assert cpu.module_history == [] + assert cpu.signal_history == [] + assert cpu.assembly_cycles == [0] diff --git a/test/test_core/test_save_state.py b/test/test_core/test_save_state.py new file mode 100644 index 0000000000000000000000000000000000000000..16199e77a9b1e2795d0563d55ff97a0c0e046ef7 --- /dev/null +++ b/test/test_core/test_save_state.py @@ -0,0 +1,43 @@ +from unittest.mock import mock_open, patch + +from simudator.core.module import Module +from simudator.core.modules.register import Register +from simudator.core.signal import Signal +from simudator.processor.simple.simple import SIMPLE_CPU + + +def test_module_save_state(): + module = Module({}) + + dummy_file_path = "dummy" + + mock_file = mock_open() + + content = module.name + with patch("builtins.open", mock_file): + module._helper_save_state_to_file(dummy_file_path, content) + mock_file.assert_called_once_with(dummy_file_path, "a") + mock_file().write.assert_called_once_with(content) + + module.name = "aaa" + content = module.name + with patch("builtins.open", mock_file): + module._helper_save_state_to_file(dummy_file_path, content) + mock_file().write.assert_called_with(content) + + +def test_default_register_save_state(): + in_sigal = Signal(None) + register = Register(in_sigal, None) + register.name = "a" + register._value = "a" + + dummy_file_path = "dummy" + + mock_file = mock_open() + + content = register.name + ":\nvalue:: " + str(register._value) + "\n\n" + with patch("builtins.open", mock_file): + register.save_state_to_file(dummy_file_path) + mock_file.assert_called_once_with(dummy_file_path, "a") + mock_file().write.assert_called_once_with(content) diff --git a/test/test_mia/test_ir.py b/test/test_mia/test_ir.py index 113a19c1cd885e960b6ea3641626136e764a0e7d..ef4a45f2f8611106f18cd71c540ee456475f0f3a 100644 --- a/test/test_mia/test_ir.py +++ b/test/test_mia/test_ir.py @@ -1,3 +1,5 @@ +from unittest.mock import mock_open, patch + from simudator.core.processor import Processor from simudator.core.signal import Signal from simudator.processor.mia.modules.ir import IR @@ -24,3 +26,27 @@ def test_ir(): assert m_s.get_value() == (instruction >> 8) & 0b11 assert grx_s.get_value() == (instruction >> 10) & 0b11 assert op_s.get_value() == (instruction >> 12) & 0b1111 + + +def test_save_state(): + cpu = Processor() + s = Signal(cpu) + ir = IR( + s, + s, + s, + s, + s, + s, + ) + + dummy_file_path = "dummy" + + mock_file = mock_open() + + content = ir.name + ":\n" + content += "Instruction: " + hex(ir.instruction)[2:] + "\n\n" + with patch("builtins.open", mock_file): + ir.save_state_to_file(dummy_file_path) + mock_file.assert_called_once_with(dummy_file_path, "a") + mock_file().write.assert_called_once_with(content) diff --git a/test/test_mia/test_lc.py b/test/test_mia/test_lc.py index 407979aead137cf1d3d965f5377442dbc7f822c6..94f05b98a8779ff2fba7352c40883469da8ae3ff 100644 --- a/test/test_mia/test_lc.py +++ b/test/test_mia/test_lc.py @@ -1,3 +1,5 @@ +from unittest.mock import mock_open, patch + from simudator.core.modules import Flag from simudator.core.processor import Processor from simudator.core.signal import Signal @@ -186,3 +188,20 @@ def test_get_state(): assert state["read_from_bus"] is False assert state["read_from_uADR"] is True assert state["decrement_by_one"] is False + + +def test_save_state(): + cpu = Processor() + s = Signal(cpu) + lc = LC(s, s, s, s) + + dummy_file_path = "dummy" + + mock_file = mock_open() + + content = lc.name + ":\n" + content += "value: " + hex(lc.value)[2:] + "\n\n" + with patch("builtins.open", mock_file): + lc.save_state_to_file(dummy_file_path) + mock_file.assert_called_once_with(dummy_file_path, "a") + mock_file().write.assert_called_once_with(content) diff --git a/test/test_mia/test_mia_grx.py b/test/test_mia/test_mia_grx.py index 7740e2a673c800c3264a2fd7303d0ee75de70cae..69e9d41009dd83821bc6a68adc6ebd2963c509bc 100644 --- a/test/test_mia/test_mia_grx.py +++ b/test/test_mia/test_mia_grx.py @@ -1,6 +1,7 @@ from simudator.core.processor import Processor from simudator.core.signal import Signal from simudator.processor.mia.modules.mia_grx import GRX +from unittest.mock import patch, mock_open def test_default_name(): @@ -145,3 +146,24 @@ def test_set_value_from_bus(): error = True assert error is True + +def test_save_state(): + cpu = Processor() + s = Signal(cpu) + grx = GRX(s, s, s, s, s, s, 1) + + dummy_file_path = "dummy" + + mock_file = mock_open() + + content = grx.name + ":\n" + for index, value in enumerate(grx.registers): + content += str(hex(index)[2:]) + ": " + content += str(hex(value)[2:]) + content += "\n" + + content += "\n" + with patch("builtins.open", mock_file): + grx.save_state_to_file(dummy_file_path) + mock_file.assert_called_once_with(dummy_file_path, "a") + mock_file().write.assert_called_once_with(content) diff --git a/test/test_mia/test_micro_memory.py b/test/test_mia/test_micro_memory.py index efa544c6c1028b8c19aa757a43c783eed365f896..8cfe4206ff751966dfe54cf561dbdd775ebce165 100644 --- a/test/test_mia/test_micro_memory.py +++ b/test/test_mia/test_micro_memory.py @@ -1,6 +1,7 @@ from simudator.core.processor import Processor from simudator.core.signal import Signal from simudator.processor.mia.modules.micro_memory import MicroMemory +from unittest.mock import patch, mock_open def test_alu_field(): @@ -393,3 +394,26 @@ def test_seq_field(): # uPC should be reset to 0, corresponding to control signal 011 assert upc_control_s.get_value() == 0b011 # TODO: Test for some sort of HALT signal + +def test_save_state(): + cpu = Processor() + s = Signal(cpu) + uM = MicroMemory(s,s,s,s,s,s,s,s,s,s,s,s,s,s,s) + + dummy_file_path = "dummy" + + mock_file = mock_open() + + content = uM.name + ":\n" + for index, value in enumerate(uM.memory): + content += ( + str(hex(index)[2:].rjust(uM.MEMORY_ADDRESS_PADDING, "0")) + ": " + ) + content += str(hex(value)[2:].rjust(uM.MEMORY_VALUE_PADDING, "0")) + content += "\n" + + content += "\n" + with patch("builtins.open", mock_file): + uM.save_state_to_file(dummy_file_path) + mock_file.assert_called_once_with(dummy_file_path, "a") + mock_file().write.assert_called_once_with(content) diff --git a/test/test_mia/test_micro_pc.py b/test/test_mia/test_micro_pc.py index 1772b552331e538153f4170570d8c7b4a23320b7..91073e409c9da4566227df1ac29c45e329e21153 100644 --- a/test/test_mia/test_micro_pc.py +++ b/test/test_mia/test_micro_pc.py @@ -1,6 +1,7 @@ from simudator.core.processor import Processor from simudator.core.signal import Signal from simudator.processor.mia.modules.micro_pc import MicroPC +from unittest.mock import patch, mock_open def test_upc(): @@ -69,3 +70,19 @@ def test_upc(): assert upc.value == f_um.get_value() assert t_supc.get_value() == temp assert t_um.get_value() == upc.value + +def test_save_state(): + cpu = Processor() + s = Signal(cpu) + upc = MicroPC(s,s,s,s,s,s,s) + + dummy_file_path = "dummy" + + mock_file = mock_open() + + content = upc.name + ":\n" + content += "value: " + hex(upc.value)[2:] + "\n\n" + with patch("builtins.open", mock_file): + upc.save_state_to_file(dummy_file_path) + mock_file.assert_called_once_with(dummy_file_path, "a") + mock_file().write.assert_called_once_with(content) diff --git a/test/test_mia/test_pc.py b/test/test_mia/test_pc.py index 48d216cfd83ef37ae7cfea4a73efd9e54d3f06a3..5c417e37f034da909c8aa5031851ef3b85fe5073 100644 --- a/test/test_mia/test_pc.py +++ b/test/test_mia/test_pc.py @@ -1,6 +1,7 @@ from simudator.core.processor import Processor from simudator.core.signal import Signal from simudator.processor.mia.modules.pc import PC +from unittest.mock import patch, mock_open def test_default_name(): @@ -198,3 +199,19 @@ def test_set_state(): assert pc.name == "pc" assert pc.value == 23 assert pc.increase_by_one is True + +def test_save_state(): + cpu = Processor() + s = Signal(cpu) + pc = PC(s,s,s,s,0) + + dummy_file_path = "dummy" + + mock_file = mock_open() + + content = pc.name + ":\n" + content += "value: " + hex(pc.value)[2:] + "\n\n" + with patch("builtins.open", mock_file): + pc.save_state_to_file(dummy_file_path) + mock_file.assert_called_once_with(dummy_file_path, "a") + mock_file().write.assert_called_once_with(content)