diff --git a/src/simudator/cli/cli.py b/src/simudator/cli/cli.py index c92a65d210f00c5118886e2db7fa5091faece039..201bb48c4e6ad87f12873758b3f05f3ab11d244a 100644 --- a/src/simudator/cli/cli.py +++ b/src/simudator/cli/cli.py @@ -5,6 +5,74 @@ 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. + + - p [name*], print [name*]: + Prints the states with given name. Prints all modules if no names are given. + + - 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. + + - 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,38 +97,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 ["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, @@ -68,20 +118,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, @@ -100,16 +136,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 @@ -127,14 +170,54 @@ 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 ["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 ["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] @@ -176,104 +259,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" - "CLI control: \n" - " - h, help : Shows this message.\n" - - " - q, quit : Closes the program. Nothing will be saved.\n" - - "\n" - # --------------------------------------------------- - "Simulation control: \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" - - " - r, reset : Resets processor to initial state.\n" - - " - u [x], undo [x]: Undos the last x clock cycle. " - "If no x is given one cycle is undone.\n" - - - "\n" - # --------------------------------------------------- - "State information: \n" - " - c, clock: Prints the processors current clock cycle.\n" - - " - p, print: Prints all states of all modules.\n" - - " - p [name*], print [name*]: Prints the states with " - "given name. " - "Will print all modules if no names are given.\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" - - " - pp, pretty print: Prints relevant processor state information in a readable and compact format.\n" - - " - ppv, pretty print verbose: Prints all processor state information in a readable and compact format.\n" - - - "\n" - # --------------------------------------------------- - "Breakpoints: \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" - - " - 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.\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" - - "\n" - # --------------------------------------------------- - "File I/O: \n" - " - l, load [path]: " - "Loads a processors state from a given file path.\n" - - " - sf, save to file [path]: " - "Saves the processor state to the specified file. \n" - ) - - 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" @@ -283,6 +276,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.")