def get_register(outfile: TextIO, reg: Register, var: str, indent: int = 0): """Writes a function to the given output file that reads the given register. The generated function reads given register reg into a variable named var. Variable var must be previously declared in the output file. Args: outfile: The output file to be written reg: The register to be read var: The name of the variable to place the result of the read into indent (optional): The number of leading tab characters to be written Examples: >>> reg = shoulder.model.register.Register(name="example", size=64, arch="aarch64") >>> var = declare_variable(sys.stdout, "x", reg.size) >>> get_register(sys.stdout, reg, var) uint64_t x = 0; x = aarch64_example_get(); """ write_indent(outfile, indent) output = "{var} = {es}_{rname}_get();\n".format( var=str(var), es=reg.execution_state if reg.execution_state else "external", rname=reg.name.lower()) outfile.write(output)
def set_register(outfile: TextIO, reg: Register, val: Union[str, int], indent: int = 0): """Writes a function to the given output file that sets a value to a register. The generated function sets the given register reg with the given value val. Args: outfile: The output file to be written reg: The register to be written val: The value to be written to the register indent (optional): The number of leading tab characters to be written Examples: >>> reg = shoulder.model.register.Register(name="example", size=64, arch="aarch64") >>> set_register(sys.stdout, reg, 0xcafe) aarch64_example_set(0xcafe); """ write_indent(outfile, indent) output = "{es}_{rname}_set({val});\n".format( es=reg.execution_state if reg.execution_state else "external", rname=reg.name.lower(), val=str(val) if type(val) == str else hex(val)) outfile.write(output)
def execute_sys_instruction(outfile: TextIO, instr: Register, val: int, indent: int = 0): """Writes a function to the given output file that performs the given SYS operation. The generated function performs a SYS operation on the given undefined instruction with the given value val. Args: outfile: The output file to be written instr: The instruction to be written val: The value to be written to the instruction indent (optional): The number of leading tab characters to be written Examples: >>> instr = shoulder.model.register.Register(name="example", size=64, arch="aarch64") >>> sys_instruction(sys.stdout, instr, 0xcafe) SHOULDER_AARCH64_SYS_IMPL(instr.op1, instr.crn, instr.crm, instr.op2, 0xcafe) """ write_indent(outfile, indent) output = "SHOULDER_AARCH64_SYS_IMPL({o1}, {cn}, {cm}, {o2}, {val});\n".format( o1=instr.access_mechanisms["msr_register"][0].op1, cn=instr.access_mechanisms["msr_register"][0].crn, cm=instr.access_mechanisms["msr_register"][0].crm, o2=instr.access_mechanisms["msr_register"][0].op2, val=str(val) if type(val) == str else hex(val)) outfile.write(output)
def execute_sysl_instruction(outfile: TextIO, instr: Register, indent: int = 0): """Writes a function to the given output file that performs the given SYSL operation. The generated function performs a SYSL operation on the given undefined instruction. Args: outfile: The output file to be written instr: The instruction to be written indent (optional): The number of leading tab characters to be written Examples: >>> instr = shoulder.model.register.Register(name="example", size=64, arch="aarch64") >>> sysl_instruction(sys.stdout, instr) x = SHOULDER_AARCH64_SYSL_IMPL(instr.op1, instr.crn, instr.crm, instr.op2); """ write_indent(outfile, indent) output = "SHOULDER_AARCH64_SYSL_IMPL({o1}, {cn}, {cm}, {o2});\n".format( o1=instr.access_mechanisms["mrs_register"][0].op1, cn=instr.access_mechanisms["mrs_register"][0].crn, cm=instr.access_mechanisms["mrs_register"][0].crm, o2=instr.access_mechanisms["mrs_register"][0].op2) outfile.write(output)
def else_if_statement(outfile: TextIO, condition: str, indent: int = 0): """Writes an else if statement to the given output file. First closes the contents of a previously generated if statement. The given condition will then be written as the contents of the else if statement. Use endif() to close the written else if statement Args: outfile: The output file to be written condition: The logical condition to be written indent (optional): The number of leading tab characters to be written Examples: >>> if_statment(sys.stdout, "x == 1") >>> else_if_statment(sys.stdout, "x == 2") >>> endif(sys.stdout) if (x == 1) { } else if (x == 2) { } """ write_indent(outfile, indent) outfile.write("}\n") write_indent(outfile, indent) outfile.write("else ") if_statement(outfile, condition, indent)
def reset_exception_counter(outfile, indent=0): """Writes a function to the given output file that resets the Scapula OS exception counter to 0 Args: outfile: The output file to be written indent (optional): The number of leading tab characters to be written Examples: >>> reset_exception_counter(sys.stdout) reset_exception_counter(); """ write_indent(outfile, indent) outfile.write("reset_exception_counter();\n")
def panic(outfile, indent=0): """Writes a function to the given output file that halts execution of Scapula OS and prints an error banner. Args: outfile: The output file to be written indent (optional): The number of leading tab characters to be written Examples: >>> panic(sys.stdout) panic(); """ write_indent(outfile, indent) outfile.write("panic();\n")
def switch_to_el(outfile: TextIO, level: int, indent: int = 0): """Writes a function to the given output file that changes the current exception level that Scapula OS is executing at. Args: outfile: The output file to be written level: The exception level to swtich to indent (optional): The number of leading tab characters to be written Examples: >>> switch_to_el(sys.stdout, 1) switch_to_el(1); """ write_indent(outfile, indent) outfile.write("switch_to_el(" + str(level) + ");\n")
def assign_variable(outfile: TextIO, var: str, rvalue: str, indent: int = 0): """Writes a variable assignment statement using the given r-value expression Args: outfile: The output file to be written var: The name of the variable to be assigned rvalue: The r-value (expression) to be used in the variable assignment indent (optional): The number of leading tab characters to be written Examples: >>> var = declare_variable(sys.stdout, "x") >>> assign_variable(sys.stdout, var, "1 + 1") x = 1 + 1; """ write_indent(outfile, indent) outfile.write(str(var) + " = " + str(rvalue) + ";\n")
def get_current_el(outfile, var, indent=0): """Writes a function to the given output file that retrieves the current exception level that Scapula OS is executing at. Args: outfile: The output file to be written var: The name of the variable to read the result into indent (optional): The number of leading tab characters to be written Examples: >>> var = declare_variable(sys.stdout, "x", 64) >>> get_current_el(sys.stdout, var) uint64_t x = 0; x = get_current_el(); """ write_indent(outfile, indent) outfile.write(str(var) + " = get_current_el();\n")
def endif(outfile: TextIO, indent: int = 0): """Closes a series of if, if else, and else statements Writes a closing bracket '}' and a newline character to the given outfile Args: outfile: The output file to be written indent (optional): The number of leading tab characters to be written Examples: >>> if_statment(sys.stdout, "x == 1") >>> endif(sys.stdout) if (x == 1) { } """ write_indent(outfile, indent) outfile.write("}\n")
def get_exception_counter(outfile, var, indent=0): """Writes a function to the given output file that retrieves the number of synchronous exceptions that have occurred since the last time the Scapula OS exception counter was reset Args: outfile: The output file to be written var: The name of the variable to read the result into indent (optional): The number of leading tab characters to be written Examples: >>> var = declare_variable(sys.stdout, "x", 64) >>> get_exception_counter(sys.stdout, var) uint64_t x = 0; x = get_exception_counter(); """ write_indent(outfile, indent) outfile.write(str(var) + " = get_exception_counter();\n")
def if_statement(outfile: TextIO, condition: str, indent: int = 0): """Writes an if statement to the given output file. The given condition will be the contents of the if statement. Use endif() to close the written if statement Args: outfile: The output file to be written condition: The logical condition to be written indent (optional): The number of leading tab characters to be written Examples: >>> if_statment(sys.stdout, "x == 1") >>> endif(sys.stdout) if (x == 1) { } """ write_indent(outfile, indent) outfile.write("if(" + str(condition) + ") {\n")
def print_debug(outfile: TextIO, msg: str, format_str: str = "", indent: int = 0): """Writes a debug print statement to the given output file. The generated debug print statement will print at log level >= 4 Args: outfile: The output file to be written msg: A printf style message to be printed format_str (optional): A printf style format string for the message indent (optional): The number of leading tab characters to be written Examples: >>> print_debug(sys.stdout, "Debug: %d", format_str="1") SCAPULA_DEBUG("Debug: %d", 1); """ write_indent(outfile, indent) outfile.write("SCAPULA_DEBUG(\"{msg}\"{fmt});\n".format( msg=str(msg), fmt="" if not format_str else ", " + str(format_str)))
def set_field(outfile: TextIO, reg: Register, field: Field, val: int, indent: int = 0): """Writes a function to the given output file that sets a value to a register field The generated function sets the given field in the given register with the given value val. Args: outfile: The output file to be written reg: The register to be written field: The field to be written val: The value to be written to the register field indent (optional): The number of leading tab characters to be written Examples: >>> reg = shoulder.model.register.Register(name="example", size=64, arch="aarch64") >>> field = shoulder.model.field.Field(name="field_1", msb=32, lsb=0) >>> set_field(sys.stdout, reg, field, 0xcafe) aarch64_example_field_1_set(0xcafe); """ write_indent(outfile, indent) if field.msb == field.lsb: if val == 0: setter = "disable()" else: setter = "enable()" else: setter = "set(" + str(hex(val)) + ")" output = "{es}_{rname}_{fname}_{setter};\n".format( es=reg.execution_state if reg.execution_state else "external", rname=reg.name.lower(), fname=field.name.lower(), setter=setter) outfile.write(output)
def print_message(outfile: TextIO, msg: str, format_str: str = "", indent: int = 0): """Writes a print statement to the given output file. The generated print statement will print at run time regardless of the configured scapula OS log level Args: outfile: The output file to be written msg: A printf style message to be printed format_str (optional): A printf style format string for the message indent (optional): The number of leading tab characters to be written Examples: >>> print_message(sys.stdout, "Hello, Scapula OS!") SCAPULA_PRINT("Hello, Scapula OS!"); """ write_indent(outfile, indent) outfile.write("SCAPULA_PRINT(\"{msg}\"{fmt});\n".format( msg=str(msg), fmt="" if not format_str else ", " + str(format_str)))
def declare_variable(outfile: TextIO, name: str, size: int, value: int = 0, const: bool = False, indent: int = 0) -> str: """Declares a C-style variable in the given output file Args: outfile: The output file to be written name: The name of the variable to be declared size: The size of the variable to be declared value (optional): The initial value for the variable const (optional): True to declare variable const, False otherwise indent (optional): The number of leading tab characters to be written Examples: >>> declare_variable(sys.stdout, "x", 64) uint64_t x = 0; """ write_indent(outfile, indent) size_type = "uint32_t" if size == 64: size_type = "uint64_t" elif size == 16: size_type = "uint16_t" elif size == 8: size_type = "uint8_t" output = "{const}{size_type} {name} = {val};\n".format( const="const " if const is True else "volatile ", size_type=size_type, name=str(name), val=hex(value) if value else "0") outfile.write(output) return str(name)
def get_field(outfile: TextIO, reg: Register, field: Field, var: str, indent: int = 0): """Writes a function to the given output file that reads the given register field The generated function reads the given field of the given register reg into a variable named var. Variable var must be previously declared in the output file. Args: outfile: The output file to be written reg: The register to be read field: The field to be read var: The name of the variable to place the result of the read into indent (optional): The number of leading tab characters to be written Examples: >>> reg = shoulder.model.register.Register(name="example", size=64, arch="aarch64") >>> field = shoulder.model.field.Field(name="field_1", msb=32, lsb=0) >>> var = declare_variable(sys.stdout, "x", reg.size) >>> get_field(sys.stdout, reg, field, var) uint64_t x = 0; x = aarch64_example_field_1_get(); """ write_indent(outfile, indent) output = "{var} = {es}_{rname}_{fname}_{getter}();\n".format( var=str(var), es=reg.execution_state if reg.execution_state else "external", rname=reg.name.lower(), fname=field.name.lower(), getter="is_enabled" if field.lsb == field.msb else "get") outfile.write(output)