def _set_register_fields(self, reg, reg_node):
        fields_node_list = reg_node.findall("./reg_fieldsets/fields")

        for fields_node in fields_node_list:
            fieldset = Fieldset(int(reg.size))
            fieldset_condition_node = fields_node.find("./fields_condition")
            field_node_list = fields_node.findall("./field")
            dbg_msg = "fieldset: "

            if fieldset_condition_node is not None:
                fieldset.condition = fieldset_condition_node.text

            for field_node in field_node_list:
                name_node = field_node.find("./field_name")
                if name_node is None:
                    name_node = field_node.find("./field_shortdesc")
                if name_node is None:
                    error_msg = str(reg.name) + " invalid field"
                    logger.error(error_msg)
                    raise ShoulderParserException(error_msg)

                name = name_node.text
                name = name.replace(" ", "_")
                msb = int(field_node.find("./field_msb").text)
                lsb = int(field_node.find("./field_lsb").text)
                fieldset.add_field(name, msb, lsb)
                dbg_msg += str(name) + " (" + str(msb) + ":" + str(lsb) + ") "

            reg.add_fieldset(fieldset)
            logger.debug(dbg_msg)
    def parse_registers(self, path):
        registers = []

        try:
            etree = ET.parse(path)
            root_node = etree.getroot()
            registers_node = root_node.findall("./registers/register")
            reg_count = len(registers_node)
            msg = type(self).__name__ + ": processing " + str(reg_count)
            msg += " register " if reg_count == 1 else " registers "
            msg += "from " + str(path)
            logger.debug(msg)

            for reg_node in registers_node:
                if (str(reg_node.attrib["is_register"]) == "True"):
                    logger.debug("Register Attributes:")
                    reg = Register()
                    self._set_register_name(reg, reg_node)
                    self._set_register_long_name(reg, reg_node)
                    self._set_register_access_attributes(reg, reg_node)
                    self._set_register_purpose(reg, reg_node)
                    self._set_register_size(reg, reg_node)
                    self._set_register_fields(reg, reg_node)
                    registers.append(reg)

        except Exception as e:
            msg = "Failed to parse register file " + str(path)
            msg += ": " + str(e)
            raise ShoulderParserException(msg)

        return registers
    def _generate_register_fieldsets(self, outfile, reg):
        """
        Generate accessors for all fieldsets that belong to a register
        """
        fieldsets = reg.fieldsets

        if len(fieldsets) == 1:
            self._generate_fieldset(outfile, reg, fieldsets[0])

        elif len(fieldsets) > 1:
            for idx, fieldset in enumerate(fieldsets):
                self._generate_fieldset_comment(outfile, fieldset)

                fieldset_namespace = "fieldset_" + str(idx)
                self.gadgets[
                    "shoulder.cxx.namespace"].name = fieldset_namespace
                self.gadgets["shoulder.cxx.namespace"].indent = 1

                @cxx.namespace
                def _in_fieldset_namespace(self, outfile, reg, fieldset):
                    self._generate_fieldset(outfile, reg, fieldset)

                _in_fieldset_namespace(self, outfile, reg, fieldset)
        else:
            logger.debug("No fieldsets generated for system register " +
                         str(reg.name))
Example #4
0
    def is_valid(self):
        if self.name is None:
            logger.debug("Register has no name")
            return False

        if self.long_name is None:
            logger.debug("Register " + str(self.name) + " has no long name")
            return False

        if self.access_attributes is None:
            logger.debug("Register " + str(self.name) +
                         " has no access attributes")
            return False

        if self.size is None:
            logger.debug("Register " + str(self.name) + " has no size")
            return False

        if self.purpose is None:
            logger.debug("Register " + str(self.name) + " has no purpose")
            return False

        for fs in self.fieldsets:
            if not fs.is_valid(): return False

        return True
 def _set_register_long_name(self, reg, reg_node):
     long_name_node = reg_node.find("./reg_long_name")
     if long_name_node is not None:
         reg.long_name = long_name_node.text
         logger.debug("long_name = " + reg.long_name)
     else:
         logger.warn(str(reg.name) + " long_name attribute not found")
Example #6
0
    def is_valid(self):
        expected_total_set = set(range(0, self.size))
        total_set = set()

        for f_idx, f in enumerate(self.fields):
            # Check individual field ranges
            if not (0 <= f.lsb <= f.msb < self.size):
                logger.debug(
                    "Invalid field position for \"{name}\" ({msb}:{lsb})".
                    format(name=f.name, msb=f.msb, lsb=f.lsb))
                return False

            # Check for intersections with other fields in this fieldset
            f_set = set(range(f.lsb, f.msb + 1))
            total_set = total_set.union(f_set)
            for x_idx, x in enumerate(self.fields):
                if f_idx == x_idx: continue
                x_set = set(range(x.lsb, x.msb + 1))
                intersect = f_set.intersection(x_set)
                if len(intersect) > 0:
                    logger.debug(
                        "Invalid field overlap, \"{f_name}\" ({f_msb}:{f_lsb}) "
                        "overlaps with \"{x_name}\" ({x_msb}:{x_lsb})".format(
                            f_name=f.name,
                            f_msb=f.msb,
                            f_lsb=f.lsb,
                            x_name=x.name,
                            x_msb=x.msb,
                            x_lsb=x.lsb))
                    return False

        return True
 def _set_register_name(self, reg, reg_node):
     name_node = reg_node.find("./reg_short_name")
     if name_node is not None:
         reg.name = name_node.text
         logger.debug("name = " + reg.name)
     else:
         logger.error("register name not found")
         raise ShoulderParserException()
    def _set_register_size(self, reg, reg_node):
        fields_node = reg_node.find("./reg_fieldsets/fields")

        if fields_node is not None:
            reg.size = int(fields_node.attrib["length"])
            logger.debug("size = " + str(reg.size))
        else:
            reg.size = None
            logger.debug(str(reg.name) + " size attribute not found")
Example #9
0
 def filter_inclusive(self, registers):
     """
     Filter the given registers such that registers matching the filter's
     criteria are included, while all others are excluded (removed)
     """
     logger.info("Applying filter: including {d}".format(d=str(self)))
     result = list(itertools.filterfalse(self._do_filter, registers))
     logger.debug("{count} registers remaining after {name}".format(
         name=str(type(self).__name__), count=str(len(result))))
     return result
    def do_transform(self, reg):
        for fs in reg.fieldsets:
            fs_len = len(fs.fields)
            fs.fields = [field for field in fs.fields if not "1" == field.name]

            count = fs_len - len(fs.fields)
            if count:
                logger.debug("Removed {count} field{s} from {reg}".format(
                    count=count, reg=reg.name, s="" if count == 1 else "s"))

        return reg
    def _generate(self, outfile, objects):
        for obj in objects:
            if (isinstance(obj, Register)):
                if not obj.is_sysreg: return

                logger.debug("Writing register: " + str(obj.name))
                self._generate_register(outfile, obj)
            else:
                msg = "Cannot generate object of unsupported {t} type".format(
                    t=type(obj))
                raise ShoulderGeneratorException(msg)
Example #12
0
 def filter_exclusive(self, registers):
     """
     Filter the given registers such that registers matching the filter's
     criteria are excluded (removed)
     """
     logger.info("Applying filter: excluding {d}".format(d=str(self)))
     result = list(filter(self._do_filter, registers))
     logger.debug("{name} removed {count} registers".format(
         name=str(type(self).__name__),
         count=str(len(registers) - len(result))))
     return result
    def _generate_register_fieldsets(self, outfile, reg):
        if not reg.is_sysreg: return

        fieldsets = reg.fieldsets
        if len(fieldsets) == 1:
            self._generate_fieldset(outfile, reg, fieldsets[0])
        elif len(fieldsets) > 1:
            for idx, fieldset in enumerate(fieldsets):
                self._generate_fieldset_comment(outfile, fieldset)
                temp = reg.name
                reg.name = reg.name + "_fieldset_" + str(idx + 1)
                self._generate_fieldset(outfile, reg, fieldset)
                reg.name = temp
        else:
            logger.debug("No fieldsets generated for system register " +
                         str(reg.name))
Example #14
0
    def _set_register_purpose(self, reg, reg_node):
        purpose_text_nodes = reg_node.findall("./reg_purpose/purpose_text")
        if len(purpose_text_nodes) == 1:
            purpose_node = reg_node.find("./reg_purpose/purpose_text/para")
            if purpose_node is not None:
                ET.strip_tags(purpose_node, "arm-defined-word",
                              "register_link")
                reg.purpose = purpose_node.text
                reg.purpose = reg.purpose.replace("\n", " ")
        elif len(purpose_text_nodes) > 1:
            text = "See the ARMv8 architecture reference manual for a "
            text += "description of this register"
            reg.purpose = text
            reg.purpose = reg.purpose.replace("\n", " ")

        if reg.purpose is not None:
            logger.debug("purpose = " + reg.purpose)
        else:
            logger.warn(str(reg.name) + " purpose attribute not found")
Example #15
0
def parse_registers(spec_path):
    if not os.path.exists(spec_path):
        msg = "Failed to parse registers, spec not found at: " + str(spec_path)
        logger.error(msg)
        raise ShoulderParserException(msg)

    logger.info("Parsing registers from: " + str(spec_path))

    paths = glob.glob(spec_path + "/*.xml")
    regs = []
    parser = ArmV8XmlParser()

    for path in paths:
        results = parser.parse_file(path)
        if results:
            for result in results:
                regs.append(result)

    logger.debug("Registers parsed: " + str(len(regs)))
    return regs
Example #16
0
    def do_transform(self, reg):
        new_name = reg.name.replace("<n>", "0")
        if new_name != reg.name:
            logger.debug("Register: {name} -> {new_name}".format(
                name = reg.name,
                new_name = new_name
            ))

            reg.name = new_name

        for fs in reg.fieldsets:
            for f in fs.fields:
                new_name = f.name.replace("<n>", "0")
                if new_name != f.name:
                    logger.debug("Field: {r}.{name} -> {r}.{new_name}".format(
                        r = reg.name,
                        name = f.name,
                        new_name = new_name
                    ))
                    f.name = new_name

        new_access_mnemonic = reg.access_attributes.mnemonic.replace("<n>", "0")
        if new_access_mnemonic != reg.access_attributes.mnemonic:
            logger.debug("Access mnemonic for {r}: {name} -> {new_name}".format(
                r = reg.name,
                name = reg.access_attributes.mnemonic,
                new_name = new_access_mnemonic
            ))
            reg.access_attributes.mnemonic = new_access_mnemonic

        return reg
Example #17
0
    def do_transform(self, reg):
        new_name = reg.name.translate(
            {ord(c): "_"
             for c in self.special_chars})
        if new_name != reg.name:
            logger.debug(
                "Replaced special characters in register: {name} -> {new_name}"
                .format(name=reg.name, new_name=new_name))
            reg.name = new_name

        for fs in reg.fieldsets:
            for f in fs.fields:
                new_name = f.name.translate(
                    {ord(c): "_"
                     for c in self.special_chars})
                if new_name != f.name:
                    logger.debug(
                        "Replaced special characters in field: {name} -> {new_name}"
                        .format(name=f.name, new_name=new_name))
                    f.name = new_name

        return reg
    def _generate(self, outfile, objects):
        """
        Generate for all objects passed into this generator.  Wrap all generated
        content in a license, include guard, and namespace. Append low-level
        accessor macros before generating register accessors
        """
        for obj in objects:
            if (isinstance(obj, Register)):
                if not obj.is_sysreg: return

                reg_name = str(obj.name).lower()
                self.gadgets["shoulder.cxx.namespace"].name = reg_name
                self.gadgets["shoulder.cxx.namespace"].indent = 0

                logger.debug("Writing register: " + reg_name)
                self._generate_register_comment(outfile, obj)
                self._generate_register(outfile, obj)

            else:
                msg = "Cannot generate object of unsupported {t} type".format(
                    t=type(obj))
                raise ShoulderGeneratorException(msg)
Example #19
0
    def do_transform(self, reg):
        if (reg.name == "FPEXC32_EL2"):
            for fs in reg.fieldsets:
                fs.fields = set([
                    field for field in fs.fields
                    if fs.fields.count(field.name) == "UFF"
                ])
                logger.debug(
                    "Removed overlapping field \"UFF\" from register FPEXC32_EL2"
                )

        if (reg.name == "HCR_EL2"):
            for fs in reg.fieldsets:
                for f_idx, f in enumerate(fs.fields):
                    if f.name == "TPC":
                        del fs.fields[f_idx]
                        logger.debug(
                            "Removed duplicate field \"TPC\" from register HCR_EL2"
                        )

        if (reg.name == "EDECCR"):
            for fs in reg.fieldsets:
                for f_idx, f in enumerate(fs.fields):
                    if f.name == "NSE":
                        del fs.fields[f_idx]
                        logger.debug(
                            "Removed overlapping field \"NSE\" from register EDECCR"
                        )

                for f_idx, f in enumerate(fs.fields):
                    if f.name == "SE":
                        del fs.fields[f_idx]
                        logger.debug(
                            "Removed overlapping field \"SE\" from register EDECCR"
                        )

        return reg
Example #20
0
    def _set_register_access_mechanisms(self, reg, reg_node, n=0):
        # Memory mapped access mechanisms
        reg_address_nodes = reg_node.findall("./reg_address")
        offsets = set()
        for node in reg_address_nodes:
            component_node = node.find("./reg_component")
            component = str(component_node.text).lower()
            component = component.replace(" ", "_")
            component = component.replace(".", "_")

            offset_node = node.find("./reg_offset/hexnumber")
            offset = int(offset_node.text, 0)
            offsets.add(offset)

            access_type_nodes = node.findall(
                "./reg_access/reg_access_state/reg_access_type")
            access_types = set()
            for access_type_node in access_type_nodes:
                access_type = access_type_node.text
                access_types.add(access_type)

            readable_types = set(
                ["RO", "RW", "WI", "IMPDEF", "RO or RW", "RAZ/WI"])
            writable_types = set(["RW", "WO", "RO or RW", "IMPDEF"])

            if access_types & readable_types:
                am = shoulder.model.armv8a.access_mechanism.LDR(
                    component, offset)
                reg.access_mechanisms["ldr"].append(am)

            if access_types & writable_types:
                am = shoulder.model.armv8a.access_mechanism.STR(
                    component, offset)
                reg.access_mechanisms["str"].append(am)

        # Instruction based access mechanisms
        access_mechanism_nodes = reg_node.findall(
            "./access_mechanisms/access_mechanism")
        for access_mechanism_node in access_mechanism_nodes:
            try:
                accessor = str(access_mechanism_node.attrib["accessor"])
                operation = accessor.split(' ', 1)[0]
                operand = accessor.split(' ', 1)[1]

                encoding_nodes = access_mechanism_node.findall("encoding/enc")
                encoding = {}
                for enc in encoding_nodes:
                    name = str(enc.attrib["n"]).lower()
                    try:
                        val = int(enc.attrib["v"], 2)
                    except ValueError:
                        strval = str(enc.attrib["v"])
                        n_field_strings = re.findall("\[n:\d+:\d+]", strval)
                        for n_string in n_field_strings:
                            n_trim = n_string[1:-1]
                            msb = int(n_trim.split(":")[1])
                            lsb = int(n_trim.split(":")[2])
                            replacement = ""
                            for i in range(lsb, msb + 1):
                                if ((1 << i) & n):
                                    replacement = "1" + replacement
                                else:
                                    replacement = "0" + replacement
                            strval = strval.replace(n_string, replacement)

                        n_bit_strings = re.findall("\[n:\d+]", strval)
                        for n_string in n_bit_strings:
                            n_trim = n_string[1:-1]
                            bit = int(n_trim.split(":")[1])
                            n_bit = bin(((1 << bit) & n) >> bit)
                            strval = strval.replace(n_string, str(n_bit)[2:])

                        n_strings = re.findall("n+", strval)
                        for n_string in n_strings:
                            num_bits = len(n_string)
                            replacement = ""
                            for i in range(num_bits):
                                if ((1 << i) & n):
                                    replacement = "1" + replacement
                                else:
                                    replacement = "0" + replacement
                            strval = strval.replace(n_string, replacement)

                        val = int(strval, 2)
                        operand = operand.replace("<n>", str(n))
                    encoding[name] = val

                if operation == "MSRregister":
                    am = shoulder.model.armv8a.access_mechanism.MSRRegister(
                        encoding["op0"],
                        encoding["op1"],
                        encoding["op2"],
                        encoding["crn"],
                        encoding["crm"],
                        operand,
                        rt=0b0)
                    reg.access_mechanisms["msr_register"].append(am)

                elif operation == "MSRbanked":
                    am = shoulder.model.armv8a.access_mechanism.MSRBanked(
                        encoding["m"], encoding["r"], encoding["m1"], operand)
                    reg.access_mechanisms["msr_banked"].append(am)

                elif operation == "MSRimmediate":
                    am = shoulder.model.armv8a.access_mechanism.MSRImmediate(
                        encoding["crn"], encoding["op0"], encoding["op1"],
                        encoding["op2"], operand)
                    reg.access_mechanisms["msr_immediate"].append(am)

                elif operation == "MRS":
                    am = shoulder.model.armv8a.access_mechanism.MRSRegister(
                        encoding["op0"],
                        encoding["op1"],
                        encoding["op2"],
                        encoding["crn"],
                        encoding["crm"],
                        operand,
                        rt=0b0)
                    reg.access_mechanisms["mrs_register"].append(am)

                elif operation == "MRSbanked":
                    am = shoulder.model.armv8a.access_mechanism.MRSBanked(
                        encoding["m"], encoding["r"], encoding["m1"], operand)
                    reg.access_mechanisms["mrs_banked"].append(am)

                elif operation == "MCR":
                    am = shoulder.model.armv8a.access_mechanism.MCR(
                        encoding["coproc"], encoding["opc1"], encoding["opc2"],
                        encoding["crn"], encoding["crm"])
                    reg.access_mechanisms["mcr"].append(am)

                elif operation == "MCRR":
                    am = shoulder.model.armv8a.access_mechanism.MCRR(
                        encoding["coproc"], encoding["opc1"], encoding["crm"])
                    reg.access_mechanisms["mcrr"].append(am)

                elif operation == "MRC":
                    am = shoulder.model.armv8a.access_mechanism.MRC(
                        encoding["coproc"], encoding["opc1"], encoding["opc2"],
                        encoding["crn"], encoding["crm"])
                    reg.access_mechanisms["mrc"].append(am)

                elif operation == "MRRC":
                    am = shoulder.model.armv8a.access_mechanism.MRRC(
                        encoding["coproc"], encoding["opc1"], encoding["crm"])
                    reg.access_mechanisms["mrrc"].append(am)

                elif operation == "VMRS":
                    am = shoulder.model.armv8a.access_mechanism.VMRS(
                        encoding["reg"], operand)
                    reg.access_mechanisms["vmrs"].append(am)

                elif operation == "VMSR":
                    am = shoulder.model.armv8a.access_mechanism.VMSR(
                        encoding["reg"], operand)
                    reg.access_mechanisms["vmsr"].append(am)

                else:
                    msg = "Invalid operation " + operation
                    msg += " in register " + reg.name
                    raise ShoulderParserException(msg)

                logger.debug(str(am))

            except Exception as e:
                msg = "Could not parse " + str(operation) + " access mechanism"
                msg += " in register " + reg.name + ":"
                logger.warn(msg)
                logger.warn("\t" + str(e))
                continue
Example #21
0
 def _do_filter(self, reg):
     result = self.do_filter(reg)
     if result == False:
         logger.debug(
             str(type(self).__name__) + " matched: " + str(reg.name))
     return result
Example #22
0
    def parse_file(self, path):
        registers = []

        try:
            etree = ET.parse(path)
            root_node = etree.getroot()
            registers_node = root_node.findall("./registers/register")
            reg_count = len(registers_node)
            msg = type(self).__name__ + ": processing " + str(reg_count)
            msg += " register " if reg_count == 1 else " registers "
            msg += "from " + str(path)
            logger.debug(msg)

            for reg_node in registers_node:
                if (str(reg_node.attrib["is_register"]) == "True"):
                    logger.debug("Register Attributes:")

                    reg = shoulder.model.armv8a.ARMv8ARegister()
                    self._set_register_name(reg, reg_node)

                    if "<n>" in reg.name:
                        array_start_node = reg_node.find(
                            "./reg_array/reg_array_start")
                        array_end_node = reg_node.find(
                            "./reg_array/reg_array_end")

                        if array_start_node is None or array_end_node is None:
                            logger.warn("Unbounded n-index register " +
                                        str(reg.name))
                            continue

                        array_start = int(array_start_node.text)
                        array_end = int(array_end_node.text)

                        # TODO: Figure out better way to identify long
                        # memory-mapped registers and access them with an
                        # offset
                        if ((array_end - array_start) > 32):
                            logger.warn("Excessively large n-index register " +
                                        str(reg.name))
                            continue

                        for n in range(array_start, array_end + 1):
                            n_reg = shoulder.model.armv8a.ARMv8ARegister()
                            self._set_register_name(n_reg, reg_node)
                            self._set_register_long_name(n_reg, reg_node)
                            self._set_register_execution_state(n_reg, reg_node)
                            self._set_register_attributes(n_reg, reg_node)
                            self._set_register_access_mechanisms(
                                n_reg, reg_node, n)
                            self._set_register_purpose(n_reg, reg_node)
                            self._set_register_size(n_reg, reg_node)
                            self._set_register_fields(n_reg, reg_node)

                            n_reg.name = n_reg.name.replace("<n>", str(n))
                            for fs in n_reg.fieldsets:
                                for f in fs.fields:
                                    f.name = f.name.replace("<n>", str(n))

                            registers.append(n_reg)
                    else:
                        self._set_register_long_name(reg, reg_node)
                        self._set_register_execution_state(reg, reg_node)
                        self._set_register_attributes(reg, reg_node)
                        self._set_register_access_mechanisms(reg, reg_node)
                        self._set_register_purpose(reg, reg_node)
                        self._set_register_size(reg, reg_node)
                        self._set_register_fields(reg, reg_node)
                        registers.append(reg)

        except Exception as e:
            msg = "Failed to parse register file " + str(path)
            msg += ": " + str(e)
            raise ShoulderParserException(msg)

        return registers