Exemplo n.º 1
0
def component_from_yaml(
    yaml: Union[str, pathlib.Path, IO[Any]],
    component_factory=None,
    route_factory=route_factory,
    **kwargs,
) -> Component:
    """Returns a Component defined from YAML


    Args:
        yaml: YAML IO describing Component (instances, placements, routing, ports, connections)
        component_factory: dict of {factory_name: factory_function}
        route_factory: for routes
        kwargs: cache, pins ... to pass to all factories

    Returns:
        Component

    valid properties:
    name: name of Component
    instances:
        name
        component
        settings
    placements: x, y and rotations
    connections: between instances
    ports (Optional): defines ports to expose
    routes (Optional): defines bundles of routes
    ports (Optional): defines ports to expose

    """
    yaml = io.StringIO(yaml) if isinstance(yaml, str) and "\n" in yaml else yaml
    component_factory = component_factory or component_factory_default

    conf = OmegaConf.load(yaml)
    for key in conf.keys():
        assert key in valid_keys, f"{key} not in {list(valid_keys)}"

    instances = {}
    routes = {}
    name = conf.get("name") or "Unnamed"
    c = Component(name)
    placements_conf = conf.get("placements")
    routes_conf = conf.get("routes")
    ports_conf = conf.get("ports")
    connections_conf = conf.get("connections")

    for instance_name in conf.instances:
        instance_conf = conf.instances[instance_name]
        component_type = instance_conf["component"]
        assert (
            component_type in component_factory
        ), f"{component_type} not in {list(component_factory.keys())}"
        component_settings = instance_conf["settings"] or {}
        component_settings.update(**kwargs)
        ci = component_factory[component_type](**component_settings)
        ref = c << ci
        instances[instance_name] = ref

        if placements_conf:
            placement_settings = placements_conf[instance_name] or {}
            for k, v in placement_settings.items():
                if k not in valid_placements:
                    raise ValueError(
                        f"`{k}` not valid placement {valid_placements} for"
                        f" {instance_name}"
                    )
                elif k == "rotation":
                    ref.rotate(v, (ci.x, ci.y))
                elif k == "mirror":
                    ref.mirror((v[0], v[1]), (v[2], v[3]))
                else:
                    setattr(ref, k, v)

    if connections_conf:
        for port_src_string, port_dst_string in connections_conf.items():
            instance_src_name, port_src_name = port_src_string.split(",")
            instance_dst_name, port_dst_name = port_dst_string.split(",")

            instance_src_name = instance_src_name.strip()
            instance_dst_name = instance_dst_name.strip()
            port_src_name = port_src_name.strip()
            port_dst_name = port_dst_name.strip()

            assert (
                instance_src_name in instances
            ), f"{instance_src_name} not in {list(instances.keys())}"
            assert (
                instance_dst_name in instances
            ), f"{instance_dst_name} not in {list(instances.keys())}"
            instance_src = instances[instance_src_name]
            instance_dst = instances[instance_dst_name]

            assert port_src_name in instance_src.ports, (
                f"{port_src_name} not in {list(instance_src.ports.keys())} for"
                f" {instance_src_name} "
            )
            assert port_dst_name in instance_dst.ports, (
                f"{port_dst_name} not in {list(instance_dst.ports.keys())} for"
                f" {instance_dst_name}"
            )
            port_dst = instance_dst.ports[port_dst_name]
            instance_src.connect(port=port_src_name, destination=port_dst)

    if routes_conf:
        for route_type in routes_conf:
            route_names = []
            ports1 = []
            ports2 = []
            routes_dict = routes_conf[route_type]
            assert (
                route_type in route_factory
            ), f"route_type `{route_type}` not in route_factory {list(route_factory.keys())}"
            route_filter = route_factory[route_type]
            for port_src_string, port_dst_string in routes_dict.items():
                instance_src_name, port_src_name = port_src_string.split(",")
                instance_dst_name, port_dst_name = port_dst_string.split(",")

                instance_src_name = instance_src_name.strip()
                instance_dst_name = instance_dst_name.strip()
                port_src_name = port_src_name.strip()
                port_dst_name = port_dst_name.strip()

                assert (
                    instance_src_name in instances
                ), f"{instance_src_name} not in {list(instances.keys())}"
                assert (
                    instance_dst_name in instances
                ), f"{instance_dst_name} not in {list(instances.keys())}"

                instance_in = instances[instance_src_name]
                instance_out = instances[instance_dst_name]

                assert port_src_name in instance_in.ports, (
                    f"{port_src_name} not in {list(instance_in.ports.keys())} for"
                    f" {instance_src_name} "
                )
                assert port_dst_name in instance_out.ports, (
                    f"{port_dst_name} not in {list(instance_out.ports.keys())} for"
                    f" {instance_dst_name}"
                )

                ports1.append(instance_in.ports[port_src_name])
                ports2.append(instance_out.ports[port_dst_name])
                route_names.append(f"{port_src_string}:{port_dst_string}")
            route = link_ports(ports1, ports2, route_filter=route_filter)
            for i, r in enumerate(route):
                routes[route_names[i]] = r

            c.add(route)

    if ports_conf:
        assert hasattr(ports_conf, "items"), f"{ports_conf} needs to be a dict"
        for port_name, instance_comma_port in ports_conf.items():
            instance_name, instance_port_name = instance_comma_port.split(",")
            instance_name = instance_name.strip()
            instance_port_name = instance_port_name.strip()
            assert (
                instance_name in instances
            ), f"{instance_name} not in {list(instances.keys())}"
            instance = instances[instance_name]
            assert instance_port_name in instance.ports, (
                f"{instance_port_name} not in {list(instance.ports.keys())} for"
                f" {instance_name} "
            )
            c.add_port(port_name, port=instance.ports[instance_port_name])
    c.instances = instances
    c.routes = routes
    return c
Exemplo n.º 2
0
def component_from_yaml(
    yaml_str: Union[str, pathlib.Path, IO[Any]],
    component_factory=None,
    route_factory=route_factory,
    link_factory=link_factory,
    label_instance_function=_add_instance_label,
    **kwargs,
) -> Component:
    """Returns a Component defined in YAML file or string.

    Args:
        yaml: YAML IO describing Component file or string (with newlines)
            (instances, placements, routes, ports, connections, names)
        component_factory: dict of {factory_name: factory_function}
        route_factory: for routes
        link_factory: for links
        label_instance_function: to label each instance
        kwargs: cache, pins ... to pass to all factories

    Returns:
        Component

    .. code::

        valid properties:
        name: name of Component
        instances:
            name:
                component:
                settings (Optional)
        placements:
            x: Optional[float, str]  str can be instanceName,portName
            y: Optional[float, str]
            rotation: Optional[float]
            mirror: Optional[bool, float] float is x mirror axis
            port: Optional[str] port anchor
        connections (Optional): between instances
        ports (Optional): defines ports to expose
        routes (Optional): defines bundles of routes
            routeName:
            factory: optical
            links:
                instance1,port1: instance2,port2


    .. code::

        instances:
            mmi_bot:
              component: mmi1x2
              settings:
                width_mmi: 4.5
                length_mmi: 10
            mmi_top:
              component: mmi1x2
              settings:
                width_mmi: 4.5
                length_mmi: 5

        placements:
            mmi_top:
                port: W0
                x: 0
                y: 0
            mmi_bot:
                port: W0
                x: mmi_top,E1
                y: mmi_top,E1
                dx: 30
                dy: -30
        routes:
            optical:
                factory: optical
                links:
                    mmi_top,E0: mmi_bot,W0

    """
    yaml_str = (io.StringIO(yaml_str) if isinstance(yaml_str, str)
                and "\n" in yaml_str else yaml_str)
    component_factory = component_factory or component_factory_default

    conf = OmegaConf.load(
        yaml_str)  # nicer loader than conf = yaml.safe_load(yaml_str)
    for key in conf.keys():
        assert key in valid_keys, f"{key} not in {list(valid_keys)}"

    instances = {}
    routes = {}
    name = conf.get("name", "Unnamed")
    c = Component(name)
    placements_conf = conf.get("placements")
    routes_conf = conf.get("routes")
    ports_conf = conf.get("ports")
    connections_conf = conf.get("connections")
    instances_dict = conf["instances"]

    for instance_name in instances_dict:
        instance_conf = instances_dict[instance_name]
        component_type = instance_conf["component"]
        assert (component_type in component_factory
                ), f"{component_type} not in {list(component_factory.keys())}"
        component_settings = instance_conf["settings"] or {}
        component_settings.update(**kwargs)
        ci = component_factory[component_type](**component_settings)
        ref = c << ci
        instances[instance_name] = ref

    while placements_conf:
        place(
            placements_conf=placements_conf,
            instances=instances,
            encountered_insts=list(),
        )

    if connections_conf:
        for port_src_string, port_dst_string in connections_conf.items():
            instance_src_name, port_src_name = port_src_string.split(",")
            instance_dst_name, port_dst_name = port_dst_string.split(",")

            instance_src_name = instance_src_name.strip()
            instance_dst_name = instance_dst_name.strip()
            port_src_name = port_src_name.strip()
            port_dst_name = port_dst_name.strip()

            assert (instance_src_name in instances
                    ), f"{instance_src_name} not in {list(instances.keys())}"
            assert (instance_dst_name in instances
                    ), f"{instance_dst_name} not in {list(instances.keys())}"
            instance_src = instances[instance_src_name]
            instance_dst = instances[instance_dst_name]

            assert port_src_name in instance_src.ports, (
                f"{port_src_name} not in {list(instance_src.ports.keys())} for"
                f" {instance_src_name} ")
            assert port_dst_name in instance_dst.ports, (
                f"{port_dst_name} not in {list(instance_dst.ports.keys())} for"
                f" {instance_dst_name}")
            port_dst = instance_dst.ports[port_dst_name]
            instance_src.connect(port=port_src_name, destination=port_dst)

    for instance_name in instances_dict:
        label_instance_function(component=c,
                                instance_name=instance_name,
                                reference=instances[instance_name])

    if routes_conf:
        for route_alias in routes_conf:
            route_names = []
            ports1 = []
            ports2 = []
            routes_dict = routes_conf[route_alias]
            if not hasattr(routes_dict, "__items__"):
                print(f"Unvalid syntax for {routes_dict}\n", sample_mmis)
                raise ValueError(f"Unvalid syntax for {routes_dict}")
            for key in routes_dict.keys():
                if key not in valid_route_keys:
                    raise ValueError(
                        f"`{route_alias}` has a key=`{key}` not in valid {valid_route_keys}"
                    )

            if "factory" not in routes_dict:
                raise ValueError(
                    f"`{route_alias}` route needs `factory` : {list(route_factory.keys())}"
                )
            route_type = routes_dict.pop("factory")
            assert isinstance(route_factory,
                              dict), "route_factory needs to be a dict"
            assert (
                route_type in route_factory
            ), f"factory `{route_type}` not in route_factory {list(route_factory.keys())}"
            route_filter = route_factory[route_type]
            route_settings = routes_dict.pop("settings", {})

            link_function_name = routes_dict.pop("link_factory", "link_ports")
            assert (
                link_function_name in link_factory
            ), f"function `{link_function_name}` not in link_factory {list(link_factory.keys())}"
            link_function = link_factory[link_function_name]
            link_settings = routes_dict.pop("link_settings", {})

            if "links" not in routes_dict:
                raise ValueError(
                    f"You need to define links for the `{route_alias}` route")
            links_dict = routes_dict["links"]

            for port_src_string, port_dst_string in links_dict.items():
                # print(port_src_string)

                if ":" in port_src_string:
                    src, src0, src1 = [
                        s.strip() for s in port_src_string.split(":")
                    ]
                    dst, dst0, dst1 = [
                        s.strip() for s in port_dst_string.split(":")
                    ]
                    instance_src_name, port_src_name = [
                        s.strip() for s in src.split(",")
                    ]
                    instance_dst_name, port_dst_name = [
                        s.strip() for s in dst.split(",")
                    ]

                    src0 = int(src0)
                    src1 = int(src1)
                    dst0 = int(dst0)
                    dst1 = int(dst1)

                    if src1 > src0:
                        ports1names = [
                            f"{port_src_name}{i}"
                            for i in range(src0, src1 + 1, 1)
                        ]
                    else:
                        ports1names = [
                            f"{port_src_name}{i}"
                            for i in range(src0, src1 - 1, -1)
                        ]

                    if dst1 > dst0:
                        ports2names = [
                            f"{port_dst_name}{i}"
                            for i in range(dst0, dst1 + 1, 1)
                        ]
                    else:
                        ports2names = [
                            f"{port_dst_name}{i}"
                            for i in range(dst0, dst1 - 1, -1)
                        ]

                    # print(ports1names)
                    # print(ports2names)

                    assert len(ports1names) == len(ports2names)
                    route_names += [
                        f"{instance_src_name},{i}:{instance_dst_name},{j}"
                        for i, j in zip(ports1names, ports2names)
                    ]

                    instance_src = instances[instance_src_name]
                    instance_dst = instances[instance_dst_name]

                    for port_src_name in ports1names:
                        assert port_src_name in instance_src.ports, (
                            f"{port_src_name} not in {list(instance_src.ports.keys())}"
                            f"for {instance_src_name} ")
                        ports1.append(instance_src.ports[port_src_name])

                    for port_dst_name in ports2names:
                        assert port_dst_name in instance_dst.ports, (
                            f"{port_dst_name} not in {list(instance_dst.ports.keys())}"
                            f"for {instance_dst_name}")
                        ports2.append(instance_dst.ports[port_dst_name])

                    # print(ports1)
                    # print(ports2)
                    print(route_names)

                else:
                    instance_src_name, port_src_name = port_src_string.split(
                        ",")
                    instance_dst_name, port_dst_name = port_dst_string.split(
                        ",")

                    instance_src_name = instance_src_name.strip()
                    instance_dst_name = instance_dst_name.strip()
                    port_src_name = port_src_name.strip()
                    port_dst_name = port_dst_name.strip()
                    assert (
                        instance_src_name in instances
                    ), f"{instance_src_name} not in {list(instances.keys())}"
                    assert (
                        instance_dst_name in instances
                    ), f"{instance_dst_name} not in {list(instances.keys())}"

                    instance_src = instances[instance_src_name]
                    instance_dst = instances[instance_dst_name]

                    assert port_src_name in instance_src.ports, (
                        f"{port_src_name} not in {list(instance_src.ports.keys())} for"
                        f" {instance_src_name} ")
                    assert port_dst_name in instance_dst.ports, (
                        f"{port_dst_name} not in {list(instance_dst.ports.keys())} for"
                        f" {instance_dst_name}")

                    ports1.append(instance_src.ports[port_src_name])
                    ports2.append(instance_dst.ports[port_dst_name])
                    route_name = f"{port_src_string}:{port_dst_string}"
                    route_names.append(route_name)

            if link_function_name in [
                    "link_electrical_waypoints",
                    "link_optical_waypoints",
            ]:
                route = link_function(
                    route_filter=route_filter,
                    **route_settings,
                    **link_settings,
                )
                routes[route_name] = route

            else:
                route = link_function(
                    ports1,
                    ports2,
                    route_filter=route_filter,
                    **route_settings,
                    **link_settings,
                )
                for i, r in enumerate(route):
                    routes[route_names[i]] = r

            c.add(route)

    if ports_conf:
        assert hasattr(ports_conf, "items"), f"{ports_conf} needs to be a dict"
        for port_name, instance_comma_port in ports_conf.items():
            instance_name, instance_port_name = instance_comma_port.split(",")
            instance_name = instance_name.strip()
            instance_port_name = instance_port_name.strip()
            assert (instance_name in instances
                    ), f"{instance_name} not in {list(instances.keys())}"
            instance = instances[instance_name]
            assert instance_port_name in instance.ports, (
                f"{instance_port_name} not in {list(instance.ports.keys())} for"
                f" {instance_name} ")
            c.add_port(port_name, port=instance.ports[instance_port_name])
    c.instances = instances
    c.routes = routes
    return c