Ejemplo n.º 1
0
    def __init__(self,
                 type_prefix,
                 name_prefix,
                 device_class,
                 common_group='monitor',
                 get_revision_fields=None):
        """Initialize the generator.

    Args:
      type_prefix: A snake_case string to prefix each monitor structure type.
      name_prefix: A snake_case string to prefix each enum and function name.
      device_class: A device class that inherits DeviceConfigBase.
      common_group: Name of group containing all monitors.
      get_revision_fields: A function that returns an initialization string
                           for extra fields in the revision map. Used by
                           the analog monitors to initialize channel_map.
    """
        self._type_prefix = c_helpers.SnakeToCamel(type_prefix)
        self._name_prefix = c_helpers.SnakeToCamel(name_prefix)
        self._device_class = device_class
        self._get_revision_fields = get_revision_fields
        self._groups = {}
        self._includes = []

        return_true = lambda x: True
        self.CreateGroup(name=common_group, is_member_function=return_true)
Ejemplo n.º 2
0
def _GenerateTypeInfo(type_info, prefix):
  """Generate TypeInfo structures."""
  fields = ''
  for path, field_type in _GetType(type_info.ctype):
    fields += textwrap.dedent("""\
        {{".{prefix}.{path}", kDataType{type}, OFFSET_OF({name}, {path})}},
        """).format(name=type_info.struct_name, prefix=prefix, path=path[1:],
                    type=c_helpers.SnakeToCamel(field_type))

  s = textwrap.dedent("""\
      const TypeInfoField kTypeInfoField{struct_name}[] = {{
      {fields}
      }};

      const TypeInfo kTypeInfo{struct_name} = {{
        reinterpret_cast<PackTypeFunction>({pack_func}), {pack_size},
        reinterpret_cast<UnpackTypeFunction>({unpack_func}), {unpack_size},
        ARRAYSIZE(kTypeInfoField{struct_name}), kTypeInfoField{struct_name}
      }};

      """).format(fields=c_helpers.Indent(fields, 1)[:-1],
                  struct_name=type_info.struct_name,
                  pack_func=type_info.pack_func,
                  pack_size=type_info.pack_size,
                  unpack_func=type_info.unpack_func,
                  unpack_size=type_info.unpack_size)

  return s
Ejemplo n.º 3
0
def _GenerateHeader(header_file):
  """Generate output header file."""
  guard = re.sub('[/.]', '_', header_file).upper() + '_'
  data_types = sorted(['kDataType' + c_helpers.SnakeToCamel(s)
                       for s in _TYPE_MAP.values()])
  s = textwrap.dedent("""\
      #ifndef {guard}
      #define {guard}

      #include <stddef.h>
      #include <stdint.h>

      #include "avionics/network/message_type.h"

      typedef size_t (*PackTypeFunction)(const void *in,
                                         size_t num,
                                         uint8_t *out);

      typedef size_t (*UnpackTypeFunction)(const uint8_t *in,
                                           size_t num,
                                           void *out);

      typedef enum {{
      {data_types},
        kNumDataTypes
      }} DataType;

      typedef struct {{
        const char *path;
        DataType type;
        size_t offset;
      }} TypeInfoField;

      typedef struct {{
        PackTypeFunction pack;
        size_t pack_size;
        UnpackTypeFunction unpack;
        size_t unpack_size;
        int32_t num_fields;
        const TypeInfoField *field;
      }} TypeInfo;

      template <typename T> const TypeInfo *GetTypeInfo();

      const TypeInfo *GetCaptureHeaderTypeInfo(void);
      const TypeInfo *GetAioHeaderTypeInfo(void);
      const TypeInfo *GetMessageTypeInfo(MessageType message);

      void ConvertDataType(int64_t n, DataType src_type, size_t src_offset,
                           size_t src_step, const void *src, DataType dst_type,
                           size_t dst_offset, size_t dst_step, void *dst);

      #endif  // {guard}
      """).format(guard=guard,
                  data_types=c_helpers.Indent(',\n'.join(data_types)))
  return s
Ejemplo n.º 4
0
def JlinkProgramBootloaderElf(target_snake,
                              hardware_type_snake,
                              elf_file,
                              speed=4000):
    """Program an elf_file bootloader on a node of hardware_type using Jlink."""
    target_camel = c_helpers.SnakeToCamel(target_snake)
    hardware_type_camel = c_helpers.SnakeToCamel(hardware_type_snake)

    with tempfile.NamedTemporaryFile(suffix='.bin') as bin_file:
        node_info = {
            'aio_node':
            target_camel,
            'hardware_type':
            generate_image.hardware_type_helper.Name(hardware_type_camel)
        }
        assert (node_info['hardware_type']
                in generate_image.hardware_type_helper.Names())
        generate_image.GenerateBootloaderImage(node_info, elf_file,
                                               bin_file.name)
        return JlinkProgramBootloaderBin(bin_file.name, speed)
Ejemplo n.º 5
0
    def __init__(self, config, expected_parameters):
        """Initialize the base class.

    Args:
      config: Specify a dict containing the per-device configuration.
      expected_parameters: Specify a list of keys to expect in config.
    """
        self._config = copy.deepcopy(config)

        # Validate configuration.
        self._CheckExpectedParameters(self._config, expected_parameters)
        self._config['camel_name'] = c_helpers.SnakeToCamel(config.get('name'))
        self.ComputeParameters(self._config)
        self.CheckParameterValues(self._config)
Ejemplo n.º 6
0
 def _GenerateEnum(self, name, members):
     """Generate common enum that describes the monitor outputs."""
     enum_prefix = self._GetEnumPrefix(name)
     parts = [
         textwrap.dedent("""\
     typedef enum {{
       k{enum_prefix}ForceSigned = -1,""").format(enum_prefix=enum_prefix)
     ]
     for value, name in enumerate(sorted(members)):
         parts.append('  k{enum_prefix}{name} = {value},'.format(
             enum_prefix=enum_prefix,
             name=c_helpers.SnakeToCamel(name),
             value=value))
     parts.append(
         textwrap.dedent("""\
       kNum{enum_prefix}s = {num}
     }} {enum_prefix};
     """).format(enum_prefix=enum_prefix, num=len(members)))
     return '\n'.join(parts)
Ejemplo n.º 7
0
    def GetGroupEnumValues(self, device):
        """Get group enumeration values for a particular device.

    See the analog monitors. The analog monitors defines groups 'input' and
    'voltage'. This function creates a dict mapping 'input' and 'voltage' to
    the device's respective enumeration value for each type.

    Args:
      device: A device object that inherits DeviceConfigBase.

    Returns:
      A dict mapping each group name to an enumeration value.
    """
        enum_values = {}
        for name, group in self._groups.iteritems():
            prefix = 'k' + self._GetEnumPrefix(name)
            if self.IsDeviceInGroup(group, device):
                enum_values[name] = prefix + c_helpers.SnakeToCamel(
                    device.GetName())
            else:
                enum_values[name] = prefix + 'ForceSigned'  # Not supported.
        return enum_values
Ejemplo n.º 8
0
def _GenerateParameterTypeInfo(module, name):
  """Generates TypeInfo for members of the 'parameters' group.

  These types are not required for hdf5_to_pcap, so no pack function, pack size,
  or unpack function are required.

  Args:
    module: Module that specifies the Python version of the type.
    name: Name of the type.

  Returns:
    String containing TypeInfo definitions.
  """
  type_info = aio_message.GetInfoByModule(module, name)

  fields = ''
  for path, field_type in _GetType(type_info.ctype):
    fields += textwrap.dedent("""\
        {{".{path}", kDataType{type}, OFFSET_OF({name}, {path})}},
        """).format(name=type_info.struct_name, path=path[1:],
                    type=c_helpers.SnakeToCamel(field_type))

  return textwrap.dedent("""\
      const TypeInfoField kTypeInfoField{struct_name}[] = {{
      {fields}
      }};

      const TypeInfo kTypeInfo{struct_name} = {{
        reinterpret_cast<PackTypeFunction>(NULL), 0,
        reinterpret_cast<UnpackTypeFunction>(NULL), {unpack_size},
        ARRAYSIZE(kTypeInfoField{struct_name}), kTypeInfoField{struct_name}
      }};

      """).format(fields=c_helpers.Indent(fields, 1)[:-1],
                  struct_name=type_info.struct_name,
                  unpack_size=ctypes.sizeof(type_info.ctype))
Ejemplo n.º 9
0
def _WriteSwitchInfo(autogen_root, output_dir, script_name, config):
    """Write switch_info.c.

  Args:
    autogen_root: The MAKANI_HOME-equivalent top directory.
    output_dir: The directory in which to output the files.
    script_name: This script's filename.
    config: A NetworkConfig.

  Raises:
    IpAddressException: On any IP address error.
    SwitchMismatchException: If the TMS570 port of a switch is invalid.
    TrunkException: If there is a problem with the trunk configuration.
  """
    file_without_extension = os.path.join(output_dir, 'switch_info')
    rel_path = os.path.relpath(file_without_extension, autogen_root)

    parts = [
        textwrap.dedent("""
      // Generated by {name}; do not edit.

      #include "{header}"

      #include <assert.h>
      #include <stdbool.h>
      #include <stdint.h>
      #include <string.h>

      """.format(name=script_name, header=rel_path + '.h'))
    ]

    ip_addr = {node.snake_name: node.ip_octet for node in config.aio_nodes}
    switches = config.GetSwitches()
    switches_sorted = sorted(switches.iterkeys())
    message_types = config.all_messages

    def _GetTms570Node(switch):
        if 'config' not in switch or 'tms570' not in switch['config']:
            return None
        port = switch['ports'][switch['config']['tms570']]
        if not port.startswith('aio_nodes.'):
            raise SwitchMismatchException(
                'No AIO node connected to TMS570 port.')
        return port[len('aio_nodes.'):]

    # The VLAN numbering convention here uses the lowest of the last octet of the
    # IP addresses of the TMS570s on the two connected switches, concatenated
    # with the port number on the associated switch.  Since the core switches have
    # 27 ports we need 5 bits to represent the port number.  As a consequence
    # TMS570s with last octets greater than 127 will present a problem for this
    # scheme.  Additionally the IP with last octet 0 is reserved for other VLANs.
    def _GetSegId(node, port, remote_node, remote_port):
        ip = ip_addr[node]
        remote_ip = ip_addr[remote_node]
        if remote_ip < ip:
            ip = remote_ip
            port = remote_port
        if ip <= 0 or ip > 127:
            raise IpAddressException('Invalid IP octet 0 >= IP or IP > 127.')
        return (ip << 5) | int(port)

    def _GenerateMask(port_list):
        return sum(1 << i for i in port_list)

    path_finder = network_util.PathFinder(switches, None, network_c=True)
    net_c_forward = network_util.MakeNetworkCForwardingMap(path_finder)

    for switch_name in switches_sorted:
        switch = switches[switch_name]
        # We use simple configs for virtual or managed switches.
        if 'config' not in switch or 'tms570' not in switch['config']:
            continue
        config = switch['config']
        node = _GetTms570Node(switch)
        seg_ids = [0] * config['chip']['num_ports']
        for port, remote in switch['ports'].iteritems():
            if remote.startswith('switches.'):
                _, remote_switch_name, remote_port = remote.split('.')
                remote_switch = switches[remote_switch_name]
                remote_node = _GetTms570Node(remote_switch)
                if not remote_node or remote_node not in ip_addr:
                    continue
                seg_ids[int(port)] = _GetSegId(node, port, remote_node,
                                               remote_port)
        info = {}
        info['node_camel'] = c_helpers.SnakeToCamel(node)
        info['switch_type'] = 'kSwitchType' + c_helpers.SnakeToCamel(
            config['chip']['type'])
        info['segment_vlans'] = 'segmentVlanIds' + info['node_camel']
        info['num_ports'] = config['chip']['num_ports']
        info['num_fiber_ports'] = config['chip']['num_fiber_ports']
        parts.append(
            textwrap.fill('static const uint16_t {}[{}] = {{{}}};'.format(
                info['segment_vlans'], info['num_ports'],
                ', '.join(str(i) for i in seg_ids)),
                          80,
                          subsequent_indent='  '))

        # Trunk configuration.
        trunk_ports = set()
        select_ports = set()
        trunk_unicast_learning_ports = set()
        info['num_multicast_overrides'] = 0
        info['multicast_overrides'] = 'NULL'
        if 'trunk' in config:
            trunk_ports = config['trunk']['ports']
            if 'unicast_learning' in config['trunk']:
                trunk_unicast_learning_ports = config['trunk'][
                    'unicast_learning']
            if 'override_message_routes' in config['trunk']:
                mcast_overrides = []
                override = config['trunk']['override_message_routes']
                for override_type, override_ports in override.iteritems():
                    mask = _GenerateMask(override_ports)
                    for m in message_types:
                        if m.name == override_type:
                            if m.eop_message:
                                mac = network_config.EopMessageTypeToEthernetAddress(
                                    eop_message_type.__dict__['kEopMessageType'
                                                              + override_type])
                            elif m.winch_message:
                                mac = network_config.WinchMessageTypeToEthernetAddress(
                                    winch_message_type.__dict__[
                                        'kWinchMessageType' + override_type])
                            else:
                                mac = network_config.AioMessageTypeToEthernetAddress(
                                    message_type.__dict__['kMessageType' +
                                                          override_type])
                            break
                    else:
                        raise TrunkException(
                            'Override contains invalid message type %s.' %
                            override_type)
                    mcast_overrides.append(('{%s}' % ', '.join(
                        '0x%02X' % x
                        for x in [mac.a, mac.b, mac.c, mac.d, mac.e, mac.f]),
                                            mask))
                info['multicast_overrides'] = 'multicastOverrides' + info[
                    'node_camel']
                info['num_multicast_overrides'] = len(mcast_overrides)
                parts.append(
                    'static const TrunkMulticastOverride {}[{}] = {{\n{}\n}};'.
                    format(
                        info['multicast_overrides'],
                        info['num_multicast_overrides'],
                        ',\n'.join('  {%s, 0x%08X}' % o
                                   for o in mcast_overrides)))
            if 'select_default_ports' in config['trunk']:
                select_ports = config['trunk']['select_default_ports']
            else:
                select_ports = trunk_ports

        info['forward_mask_a'] = _GenerateMask(config['network_a'])
        info['forward_mask_b'] = _GenerateMask(config['network_b'])
        info['forward_mask_c'] = net_c_forward[switch_name]
        info['egress_mask_c'] = _GenerateMask(config.get('network_c', []))
        if 'isolate' in config:
            if trunk_ports:
                raise TrunkException(
                    'Isolate and trunk definitions are currently not '
                    'supported together.')
            else:
                isolate_ports = config['isolate']
        else:
            isolate_ports = trunk_ports
        info['isolate_mask'] = _GenerateMask(isolate_ports)
        info['trunk_mask'] = _GenerateMask(trunk_ports)
        info['unicast_learning_mask'] = _GenerateMask(
            trunk_unicast_learning_ports)
        info['select_default_mask'] = _GenerateMask(select_ports)
        info['unicast_mask'] = _GenerateMask(config['unicast'])
        info['host_port'] = config['tms570']
        info['mirror_port'] = config['mirror']

        parts.append(
            'static const SwitchInfo switchInfo{node_camel} = {{\n'
            '  {switch_type}, {num_ports}, {num_fiber_ports},\n'
            '  {host_port}, {mirror_port},\n'
            '  0x{forward_mask_a:X}, 0x{forward_mask_b:X},\n'
            '  0x{forward_mask_c:X}, 0x{egress_mask_c:X},\n'
            '  0x{isolate_mask:X}, 0x{unicast_mask:X}, {segment_vlans},\n'
            '  {{0x{trunk_mask:X}, 0x{select_default_mask:X},'
            ' 0x{unicast_learning_mask:X},\n'
            '   {num_multicast_overrides}, {multicast_overrides}}}\n'
            '}};\n'.format(**info))

    parts.append(
        textwrap.dedent("""
      const SwitchInfo *GetSwitchInfo(AioNode node) {
        switch (node) {"""[1:]))

    unused_nodes = set(c_helpers.EnumHelper('AioNode', aio_node).Names())

    for switch_name in switches_sorted:
        switch = switches[switch_name]
        if 'config' not in switch or 'tms570' not in switch['config']:
            continue
        node = _GetTms570Node(switch)
        node_camel = c_helpers.SnakeToCamel(node)
        node_name = 'kAioNode' + node_camel
        unused_nodes.remove(node_name)
        parts.append('    case %s:' % node_name)
        if 'config' not in switch:
            parts.append('      assert(false);')
            parts.append('      return NULL;')
        else:
            parts.append('      return &switchInfo%s;' % node_camel)

    parts.append('    // Fall-through intentional.')
    for node in sorted(unused_nodes):
        parts.append('    case %s:' % node)
    parts.append(
        textwrap.dedent("""
          case kAioNodeForceSigned:
          case kNumAioNodes:
          default:
            assert(false);
            return NULL;
        }
      }
  """[1:]))

    with open(file_without_extension + '.c', 'w') as f:
        f.write('\n'.join(parts))
Ejemplo n.º 10
0
 def _GetEnumPrefix(self, name):
     return self._name_prefix + c_helpers.SnakeToCamel(name)