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
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