diff --git a/src/simudator/cli/cli.py b/src/simudator/cli/cli.py index 7eb5e46ddcf8349ff805b61a6b647575bdbccca0..a375743567c885d6d9f284ab2d6413db0828b4b2 100644 --- a/src/simudator/cli/cli.py +++ b/src/simudator/cli/cli.py @@ -5,6 +5,72 @@ from os.path import exists, isdir from simudator.core.processor import Processor +HELP_TEXT = """Here is a list of possible commands: +CLI control: + - h, help : Shows this message. + + - q, quit : Closes the program. Nothing will be saved. + +Simulation control: + - n [x], next [x]: Simulates x ticks. + If no x is given, simulates one tick. + + - rc, run_continuously: + Continuously simulate ticks until a HALT is signalled + or a breakpoint is reached. + + - u [x], undo [x]: Undoes the last x clock cycle. + If no x is given one cycle is undone. + + - r, reset : Resets processor to initial state. + +State information: + - c, clock: Prints the processors current clock cycle. + + - p, print: Prints all states of all modules. + + - pl, printlist [add/remove] [module name] ...: + Add or remove the given modules to a list of modules to print. If no + arguments are given, i.e. "pl" or "printlist" on their own, all the modules + in the list will be printed. + + - pp, pretty print: Prints relevant processor state information in a + readable and compact format. + + - ppv, pretty print verbose: Prints all processor state information in a + readable and compact format. + +Breakpoints: + - p br, print breaks: Prints all breakpoints. + + - p br lam, print break lambdas: + Prints all available lambdas of this processor to use for lambda + breakpoints. + + - br state, break state [module name] [state name] [value]: + Add a breakpoint for the module with the given name. The breakpoint brakes + when the specified state of the module has the specified value. + + - br mem, break memory [module name] [adress] [value]: + Add a breakpoint for a memory module with the given name. The breakpoint + breaks when the specified adress of the memory has the specified value. + + - br lam, break lambda [lambda_name] [keyword argument] ...: + Add a breakpoint that uses the referenced lambda to evaluate when to + break. Any module names in the keyword arguments will be substituted with + the actual module. Strings must be enclosed with quotation marks. + + - rm br [id], remove break [id]: + Remove the breakpoint with the given ID. + +File I/O: + - l, load [path]: + Loads a processors state from a given file path. + + - sf, save to file [path]: + Saves the processor state to the specified file. +""" + class CLI: """ @@ -29,41 +95,20 @@ class CLI: # Get user commands here user_input = input("> ") + # Note: Keep the order of the cases consistent with the help text + # for convenience match user_input.split(): - case ["hi"] | ["hello"]: - print("Greeting!") - - case ["c"] | ["clock"]: - # shows current clockcycle - print("Clock is at: ", str(self.processor.get_clock())) - - case ["p"] | ["print"]: - print("\n") - # prints all module states, is most prbably hard to read - for module in self.processor.get_modules(): - module.print_module() - print("\n") - - case ["p", "br"] | ["print", "breaks"]: - self.processor.print_breakpoints() - - case ["p", "br", "lam"] | ["print", "break", "lambdas"]: - lambdas = self.processor.get_breakpoint_lambdas() - if not lambdas: - print("There are no lambdas for this processor.") - else: - print(lambdas) + # CLI control ------------------------------------------------- + case ["h"] | ["help"]: + # prints help message + print(HELP_TEXT) - case ["p", *_] | ["print", *_]: - print("\n") - # print modules with given names - for name in user_input.split()[1:]: - try: - self.processor.get_module(name).print_module() - print("\n") - except KeyError: - print("\nNo module named", name, "\n") + case ["q"] | ["quit"]: + # Ends the loop + print("Goodbye") + self.running = False + # Simulation control ------------------------------------------ case ["n"] | ["next"]: # runs next tick in the processor # this could take time for larger simulations, @@ -71,20 +116,6 @@ class CLI: self.processor.do_tick() - case ["rc"] | ["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"]: - # self.processor.load_cycle(0) - self.processor.reset() - case ["n", _] | ["next", _]: # runs a given number of ticks # this could take time for larger simulations, @@ -103,16 +134,23 @@ class CLI: except ValueError: print("Invalid value") - case ["l", _] | ["load", _]: - # load processor state from file - try: - self.processor.reset() - self.processor.load_state_from_file(user_input.split()[1]) - except FileNotFoundError: - print("No file called ", user_input.split()[1], " was found") + case ["rc"] | ["run_continuously"]: + self.processor.run_continuously() + if self.processor.breakpoint_reached: + bp = self.processor.last_breakpoint + print(f"Reached breakpoint: {bp}") - case ["pl", *_] | ["printlist", *_]: - self.print_list_command(user_input.split()) + if self.processor.should_halt(): + print("The processor halted") + + case ["u"] | ["undo"]: + # undo one clock cycles + + current_cycle = self.processor.get_clock() + try: + self.processor.load_cycle(max(current_cycle - 1, 0)) + except IndexError: + print("Index out of range") case ["u", _] | ["undo", _]: # undo many clock cycles @@ -130,14 +168,44 @@ class CLI: except IndexError: print("Index out of range") - case ["u"] | ["undo"]: - # undo one clock cycles + case ["r"] | ["resets"]: + # self.processor.load_cycle(0) + self.processor.reset() - current_cycle = self.processor.get_clock() - try: - self.processor.load_cycle(max(current_cycle - 1, 0)) - except IndexError: - print("Index out of range") + # State information ------------------------------------------- + case ["c"] | ["clock"]: + # shows current clockcycle + print("Clock is at: ", str(self.processor.get_clock())) + + case ["p"] | ["print"]: + print("\n") + # prints all module states, is most prbably hard to read + for module in self.processor.get_modules(): + module.print_module() + print("\n") + + case ["pl", *_] | ["printlist", *_]: + self.print_list_command(user_input.split()) + + case ["pp"] | ["pretty print"]: + # pretty print the modules of the processor + self.processor.pretty_print() + + case ["ppv"] | ["pretty print verbose"]: + # pretty print the modules of the processor + # with all available information + self.processor.pretty_print_verbose() + + # Breakpoints ------------------------------------------------- + case ["p", "br"] | ["print", "breaks"]: + self.processor.print_breakpoints() + + case ["p", "br", "lam"] | ["print", "break", "lambdas"]: + lambdas = self.processor.get_breakpoint_lambdas() + if not lambdas: + print("There are no lambdas for this processor.") + else: + print(lambdas) case ["br", "state", _, _, _] | ["break", "state", _, _, _]: module_name = user_input.split()[2] @@ -179,65 +247,14 @@ class CLI: except ValueError: print("Breakpoint ID must be an integer") - case ["h"] | ["help"]: - # prints help message - print( - "Here is a list of possible commands:\n" - "- c, clock : Prints the processors current clock cycle.\n" - "- p [name*], print [name*]: Prints the states with " - "given name. " - "Will print all modules if no names are given.\n" - "- p br, print breaks: Prints all breakpoints.\n" - "- p br lam, print break lambdas: Prints all available " - "lambdas of this processor to use for lambda " - "breakpoints. \n" - "- pl, printlist [add] [remove]: " - "Prints all modules in the print list. " - "Add or remove followed by a modules name " - "will add or remove them from the print list.\n" - "- l, load [path]: " - "Loads a processors state from a given file path.\n" - "- r, reset : Resets processor to initial state.\n" - "- n [x], next [x]: Simulates x ticks. " - "If no x is given simulates one tick.\n" - "- rc, run_continuously: " - "Continuously simulate ticks until a HALT is signalled " - "or a breakpoint is reached.\n" - "- u [x], undo [x]: Undos the last x clock cycle. " - "If no x is given one cycle is undone.\n" - "- br, break [module name] [state name] [value]: " - "Add a breakpoint for the module with the given name. " - "The breakpoint brakes when the specified state of the " - "module has the specified value.\n" - "- br mem, break memory [module name] [adress] [value]: " - "Add a breakpoint for a memory module with the given " - "name. The breakpoint breaks when the specified adress " - "of the memory has the specified value.\n" - "- br lam, break lambda [lambda_name] " - "[keyword argument] ...: Add a breakpoint that uses " - "the referenced lambda to evaluate when to break. Any " - "module names in the keyword arguments will be " - "substituted with the actual module. Strings must be " - "enclosed with quotation marks. \n" - "- rm br [id], remove break [id]: Remove the " - "breakpoint with the given ID.\n" - "- h, help : Shows this message.\n" - "- q, quit : Closes the program. Nothing will be saved." - ) - - case ["q"] | ["quit"]: - # Ends the loop - print("Goodbye") - self.running = False - - case ["pp"] | ["pretty print"]: - # pretty print the modules of the processor - self.processor.pretty_print() - - case ["ppv"] | ["pretty print verbose"]: - # pretty print the modules of the processor - # with all available information - self.processor.pretty_print_verbose() + # File I/O ---------------------------------------------------- + case ["l", _] | ["load", _]: + # load processor state from file + try: + self.processor.reset() + self.processor.load_state_from_file(user_input.split()[1]) + except FileNotFoundError: + print("No file called ", user_input.split()[1], " was found") case ["sf"] | ["save to file"]: file_path = "cpu_save_file" @@ -247,6 +264,7 @@ class CLI: file_path = user_input.split()[1] self.check_file_path(file_path) + # ------------------------------------------------------------- case _: # message for unknown command print("Unknown command. Write \"help\" for assistance.") @@ -295,24 +313,25 @@ class CLI: print("\n") return + names = user_input[2:] # add name to print list if user_input[1] == "add": - name = user_input[2] - # check if name exists - try: - self.processor.get_module(name) - except KeyError: - print("\nNo module named", name, "\n") - return + for name in names: + # check if name exists + try: + self.processor.get_module(name) + if name not in self.print_list: + self.print_list.append(name) + except KeyError: + print("No module named", name,) - self.print_list.append(name) elif user_input[1] == "remove": - name = user_input[2] - if name in self.print_list: - self.print_list.remove(name) - else: - print(name, "not in print list") + for name in names: + if name in self.print_list: + self.print_list.remove(name) + else: + print(name, "not in print list") else: print("Unknown command") diff --git a/src/simudator/processor/mia/mia.py b/src/simudator/processor/mia/mia.py index 05641f6560e2fe47cecb204e0966373f5084a147..27333e5c0c7581e8e9cbf5dd4aa6b277c8dd5012 100644 --- a/src/simudator/processor/mia/mia.py +++ b/src/simudator/processor/mia/mia.py @@ -388,8 +388,6 @@ class MIA_CPU(Processor): def launch_cli(self): mia_cpu = MIA_CPU() cli = CLI(mia_cpu) - cli.print_list = ["IR", "PC", "uPC"] - mia_cpu.load_state_from_file("mia_uppg3.txt") mia_cpu.reset() cli.run()