Esempio n. 1
0
    def generate_flow_network(self, fig_subgraph_view) -> MINTDevice:
        # TODO - For now just assume that the networks basically are a bunch
        # of nodes with nets/channels connecting them
        ret = MINTDevice("flow_network_temp")
        mint_layer = ret.create_mint_layer("0", "0", 0, MINTLayerType.FLOW)
        for node in fig_subgraph_view.nodes:
            n = MINTNode("node_{}".format(node), mint_layer)
            ret.add_component(n)
            self._store_fig_netlist_name(node, n.ID)

        i = 1
        for node in fig_subgraph_view.nodes:
            # Create the channel between these nodes
            channel_name = "c_{}".format(i)
            i += 1
            params = dict()
            params["channelWidth"] = 400
            source = MINTTarget("node_{}".format(node))
            sinks = []

            # Add all the outgoing edges
            for edge in fig_subgraph_view.out_edges(node):
                tar = edge[1]
                if tar not in fig_subgraph_view.nodes:
                    # We skip because this might be a weird edge that we were not supposed
                    # to have in this network
                    continue

                sinks.append(MINTTarget("node_{}".format(tar)))

            ret.create_mint_connection(channel_name, "CHANNEL", params, source,
                                       sinks, "0")

        return ret
Esempio n. 2
0
class MINTCompiler(mintListener):
    """Primary ANTLR listener class for the compiler"""

    def __init__(self):
        super().__init__()
        self.current_device: MINTDevice = MINTDevice("DEFAULT_NAME")
        self.current_block_id = 0
        self.current_layer_id = 0
        self.flow_layer_count = 0
        self.control_layer_count = 0
        self.integration_layer_count = 0
        self.current_entity: Optional[str] = None
        self.current_params: Dict = {}
        self._current_layer: Optional[Layer] = None

    def enterNetlist(self, ctx: mintParser.NetlistContext):
        self.current_device = MINTDevice("DEFAULT_NAME")

    def exitNetlist(self, ctx: mintParser.NetlistContext):
        if self.current_device is None:
            raise Exception("Could not find the device")

    def enterHeader(self, ctx: mintParser.HeaderContext):
        if self.current_device is None:
            raise Exception(
                "Error Initializing the device. Could not find the current device"
            )

        if ctx.device_name is None:
            raise Exception("Could not find Device Name")
        self.current_device.device.name = ctx.device_name.text

    def exitLayerBlock(self, ctx: mintParser.LayerBlockContext):
        # Increement teh layer block
        self.current_block_id += 1

    def enterFlowBlock(self, ctx: mintParser.FlowBlockContext):
        if self.current_device is None:
            raise Exception(
                "Error Initializing the device. Could not find the current device"
            )
        layer = self.current_device.create_mint_layer(
            str(self.current_layer_id),
            str(self.flow_layer_count),
            str(self.current_block_id),
            MINTLayerType.FLOW,
        )
        self._current_layer = layer
        self.flow_layer_count += 1
        self.current_layer_id += 1

    def enterControlBlock(self, ctx: mintParser.ControlBlockContext):
        if self.current_device is None:
            raise Exception(
                "Error Initializing the device. Could not find the current device"
            )

        layer = self.current_device.create_mint_layer(
            str(self.current_layer_id),
            str(self.control_layer_count),
            str(self.current_block_id),
            MINTLayerType.CONTROL,
        )
        self._current_layer = layer
        self.control_layer_count += 1
        self.current_layer_id += 1

    def enterIntegrationBlock(self, ctx: mintParser.IntegrationBlockContext):
        if self.current_device is None:
            raise Exception(
                "Error Initializing the device. Could not find the current device"
            )

        layer = self.current_device.create_mint_layer(
            str(self.current_layer_id),
            str(self.integration_layer_count),
            str(self.current_block_id),
            MINTLayerType.INTEGRATION,
        )
        self._current_layer = layer
        self.integration_layer_count += 1
        self.current_layer_id += 1

    def enterEntity(self, ctx: mintParser.EntityContext):
        self.current_entity = ctx.getText()

    def enterParamsStat(self, ctx: mintParser.ParamsStatContext):
        self.current_params = {}

    def enterIntParam(self, ctx: mintParser.IntParamContext):
        value = ctx.value().getText()  # type: ignore
        key = ctx.param_element().getText()  # type: ignore
        self.current_params[key] = int(value)

    def enterBoolParam(self, ctx: mintParser.BoolParamContext):
        if ctx.boolvalue.getText() == "YES":
            value = True
        else:
            value = False
        key = ctx.param_element.getText()
        self.current_params[key] = value

    def enterLengthParam(self, ctx: mintParser.LengthParamContext):
        value = float(ctx.value().getText())  # type: ignore
        self.current_params["length"] = value

    def enterSpacingParam(self, ctx: mintParser.SpacingParamContext):
        value = float(ctx.value().getText())  # type: ignore
        self.current_params["spacing"] = value

    def enterWidthParam(self, ctx: mintParser.WidthParamContext):
        value = ctx.value().getText()  # type: ignore
        if ctx.key is None:
            raise AssertionError
        key = ctx.key.text
        if key is None:
            raise Exception("Error in parsing the width parameter")
        if key == "w":
            key = "width"

        self.current_params[key] = int(value)

    def enterFlowStat(self, ctx: mintParser.FlowStatContext):
        self.current_entity = None
        self.current_params = {}

    def enterControlStat(self, ctx: mintParser.ControlStatContext):
        self.current_entity = None
        self.current_params = {}

    def exitPrimitiveStat(self, ctx: mintParser.PrimitiveStatContext):
        if self.current_device is None:
            raise Exception(
                "Error Initializing the device. Could not find the current device"
            )

        entity = self.current_entity
        if entity is None:
            raise Exception("Could not find the technology for the pimitive")

        # Loop for each of the components that need to be created with this param
        for ufname in ctx.ufnames().ufname():  # type: ignore
            if self._current_layer is None:
                raise Exception("Current layer is set to None")
            if not (
                self._current_layer is not None and self._current_layer.ID is not None
            ):
                raise AssertionError
            self.current_device.create_mint_component(
                ufname.getText(),
                entity,
                self.current_params,
                [self._current_layer.ID],
            )

    def exitBankDeclStat(self, ctx: mintParser.BankDeclStatContext):
        entity = self.current_entity
        if entity is None:
            raise Exception("Could not find the technology for the primitive")

        # Clean up the constraint specific params
        self._cleanup_bank_params()

        for ufname in ctx.ufnames().ufname():  # type: ignore
            component_name = ufname.getText()
            if self._current_layer is None:
                raise AssertionError
            self.current_device.create_mint_component(
                component_name,
                entity,
                self.current_params,
                [self._current_layer.ID],
            )

    def exitBankGenStat(self, ctx: mintParser.BankGenStatContext):
        entity = self.current_entity
        if entity is None:
            raise Exception("Could not find the technology for the primitive")

        self._cleanup_bank_params()

        if ctx.dim is None:
            raise AssertionError
        dim = int(ctx.dim.text)

        name = ctx.ufname().getText()  # type: ignore

        for i in range(1, dim + 1):
            component_name = name + "_" + str(i)
            if self._current_layer is None:
                raise Exception("Current Layer not Set")
            if not (
                self._current_layer is not None and self._current_layer.ID is not None
            ):
                raise AssertionError
            self.current_device.create_mint_component(
                component_name, entity, self.current_params, [self._current_layer.ID]
            )

    def exitGridDeclStat(self, ctx: mintParser.GridDeclStatContext):
        if self.current_device is None:
            raise Exception(
                "Error Initializing the device. Could not find the current device"
            )

        entity = self.current_entity
        if entity is None:
            raise Exception("Could not find the technology for the primitive")

        self._cleanup_grid_params()

        for ufname in ctx.ufnames().ufname():  # type: ignore
            component_name = ufname.getText()
            if self._current_layer is None:
                raise AssertionError
            self.current_device.create_mint_component(
                component_name,
                entity,
                self.current_params,
                [self._current_layer.ID],
            )

    def exitChannelStat(self, ctx: mintParser.ChannelStatContext):
        if self.current_device is None:
            raise Exception(
                "Error Initializing the device. Could not find the current device"
            )

        entity = self.current_entity
        if entity is None:
            entity = "CHANNEL"
        connection_name = ctx.ufname().getText()  # type: ignore

        source_target = ctx.uftarget()[0]  # type: ignore
        source_id = source_target.ID().getText()
        if self.current_device.device.component_exists(source_id) is False:
            raise Exception(
                "Error ! - Could not find the component '{}' in device '{}'".format(
                    source_id, self.current_device.device.name
                )
            )
        if source_target.INT():
            source_port = source_target.INT().getText()
        else:
            source_port = None

        # source_uftarget = Target(component_id=source_id, port=source_port)
        source_uftarget = Target(component_id=source_id, port=source_port)

        sink_target = ctx.uftarget()[1]  # type: ignore
        sink_id = sink_target.ID().getText()
        if self.current_device.device.component_exists(sink_id) is False:
            raise Exception(
                "Error ! - Could not find the component '{}' in device '{}'".format(
                    sink_id, self.current_device.device.name
                )
            )
        if sink_target.INT():
            sink_port = sink_target.INT().getText()
        else:
            sink_port = None

        sink_uftarget = Target(component_id=sink_id, port=sink_port)

        self._cleanup_channel_params()

        # Create a connection between the different components in the device
        if not (self._current_layer is not None and self._current_layer.ID is not None):
            raise AssertionError
        self.current_device.create_mint_connection(
            connection_name,
            entity,
            self.current_params,
            source_uftarget,
            [sink_uftarget],
            self._current_layer.ID,
        )

    def exitNetStat(self, ctx: mintParser.NetStatContext):
        entity = self.current_entity
        if entity is None:
            entity = "NET"

        connection_name = ctx.ufname().getText()  # type: ignore

        source_target = ctx.uftarget()
        source_id = source_target.ID().getText()  # type: ignore
        if source_target.INT():  # type: ignore
            source_port = source_target.INT().getText()  # type: ignore
        else:
            source_port = None

        source_uftarget = Target(component_id=source_id, port=source_port)

        sink_uftargets = []

        for sink_target in ctx.uftargets().uftarget():  # type: ignore
            sink_id = sink_target.ID().getText()
            if sink_target.INT():
                sink_port = sink_target.INT().getText()
            else:
                sink_port = None

            sink_uftargets.append(Target(component_id=sink_id, port=sink_port))
        if not (self._current_layer is not None and self._current_layer.ID is not None):
            raise AssertionError
        self.current_device.create_mint_connection(
            connection_name,
            entity,
            self.current_params,
            source_uftarget,
            sink_uftargets,
            self._current_layer.ID,
        )

    def exitSpanStat(self, ctx: mintParser.SpanStatContext):
        if self.current_device is None:
            raise Exception(
                "Error Initializing the device. Could not find the current device"
            )

        entity = self.current_entity
        if entity is None:
            raise Exception("Could not find the technology for the pimitive")

        # pipe in the in / out values to params for sizing
        if ctx.indim is not None:
            in_value = int(ctx.indim.text)
            self.current_params["in"] = in_value
        if ctx.outdim is not None:
            out_value = int(ctx.outdim.text)
            self.current_params["out"] = out_value

        # Loop for each of the components that need to be created with this param
        for ufname in ctx.ufnames().ufname():  # type: ignore
            if self._current_layer is None:
                raise AssertionError
            self.current_device.create_mint_component(
                ufname.getText(),
                entity,
                self.current_params,
                [self._current_layer.ID],
            )

    def exitNodeStat(self, ctx: mintParser.NodeStatContext):
        entity = "NODE"
        if self.current_device is None:
            raise Exception(
                "Error Initializing the device. Could not find the current device"
            )

        # Loop for each of the components that need to be created with this param
        if not (self._current_layer is not None and self._current_layer.ID is not None):
            raise AssertionError
        for ufname in ctx.ufnames().ufname():  # type: ignore
            self.current_device.create_mint_component(
                ufname.getText(),
                entity,
                self.current_params,
                [self._current_layer.ID],
            )

    def exitValveStat(self, ctx: mintParser.ValveStatContext):
        if self.current_device is None:
            raise Exception(
                "Error Initializing the device. Could not find the current device"
            )

        entity = self.current_entity
        if entity is None:
            logging.error("Could not find entitry information for valve")
            raise Exception("Could not find entitry information for valve")
        valve_name = ctx.ufname()[0].getText()  # type: ignore
        if not (self._current_layer is not None and self._current_layer.ID is not None):
            raise AssertionError
        valve_component = self.current_device.create_mint_component(
            valve_name,
            entity,
            self.current_params,
            [self._current_layer.ID],
        )
        connection_name = ctx.ufname()[1].getText()  # type: ignore
        valve_connection = self.current_device.device.get_connection(connection_name)
        if valve_connection is None:
            raise Exception(
                "Error: Could not find connection '{}' in device '{}'".format(
                    connection_name, self.current_device.device.name
                )
            )

        self.current_device.device.map_valve(valve_component, valve_connection)

    def enterViaStat(self, ctx: mintParser.ViaStatContext):
        if self.current_device is None:
            raise Exception(
                "Error Initializing the device. Could not find the current device"
            )

        for ufname in ctx.ufnames().ufname():
            self.current_device.add_via(ufname.getText(), [])

    def enterTerminalStat(self, ctx: mintParser.TerminalStatContext):
        if self.current_device is None:
            raise Exception(
                "Error Initializing the device. Could not find the current device"
            )

        terminal_name = ctx.ufname().getText()
        pin_number = int(ctx.INT.getText())
        if not (self._current_layer is not None and self._current_layer.ID is not None):
            raise AssertionError
        self.current_device.add_terminal(
            terminal_name,
            pin_number,
            self._current_layer.ID,
        )

    def _cleanup_bank_params(self):
        if "spacing" in self.current_params:
            del self.current_params["spacing"]

    def _cleanup_grid_params(self):
        if "horizontalSpacing" in self.current_params:
            del self.current_params["horizontalSpacing"]
        if "verticalSpacing" in self.current_params:
            del self.current_params["verticalSpacing"]

    def _cleanup_channel_params(self):
        if "length" in self.current_params:
            del self.current_params["length"]
Esempio n. 3
0
def generate(module: Module, library: MappingLibrary) -> MINTDevice:

    construction_graph = ConstructionGraph()

    name_generator = NameGenerator()

    cur_device = MINTDevice(module.name)

    # Add a MINT Layer so that the device has something to work with
    cur_device.create_mint_layer("0", "0", 0, MINTLayerType.FLOW)

    # TODO - I need to change this DummyStrategy later on
    if library.name == "dropx":
        active_strategy = DropXStrategy(construction_graph, module.FIG)
    elif library.name == "mars":
        raise NotImplementedError()
    elif library.name == "hmlp":
        raise NotImplementedError()
    else:
        active_strategy = DummyStrategy(construction_graph, module.FIG)

    # First go through all the interactions in the design

    # IF interaction is mix/sieve/divide/dilute/meter look at the library
    # to get all the options available and set them up as options for the
    # construction graph to pick and choose from the options.
    #
    # FUTURE WORK
    #
    # Do the regex matching to find the mapping options
    # This means that we might need to have a forest of construction of graphs
    # as there would be alternatives for each type of mapping
    for interaction in module.FIG.get_interactions():
        operator_candidates = library.get_operators(
            interaction_type=interaction.type)
        cn = ConstructionNode(interaction.id)
        # if isinstance(interaction, ValueNode):
        #     continue

        for operator_candidate in operator_candidates:
            # TODO: This will change in the future when we can match subgraphs correctly
            if isinstance(interaction,
                          (FluidNumberInteraction, FluidIntegerInteraction)):
                # Basically add the value node id into the subgraph view also
                node_ids = [
                    module.FIG.get_fignode(edge[0]).id
                    for edge in module.FIG.in_edges(interaction.id)
                    if isinstance(module.FIG.get_fignode(edge[0]), ValueNode)
                ]
                node_ids.append(interaction.id)
                sub_graph = module.FIG.subgraph(node_ids)
            else:
                sub_graph = module.FIG.subgraph(interaction.id)
            mapping_option = MappingOption(operator_candidate, sub_graph)
            cn.add_mapping_option(mapping_option)

        construction_graph.add_construction_node(cn)

    # Generate all ports necessary for the Explicitly declared IO
    # -------
    # Generate the flow layer IO. These are typically declared explicitly
    # TODO - Figure out how we should generate the construction nodes for control networks

    for io_ref in module.io:
        if io_ref.type is IOType.CONTROL:
            continue
        for io in io_ref.vector_ref:
            cn = ConstructionNode(io.id)
            sub_graph = module.FIG.subgraph(io.id)
            mapping_candidate = library.get_default_IO()
            mapping_option = MappingOption(mapping_candidate, sub_graph)
            cn.add_mapping_option(mapping_option)

            construction_graph.add_construction_node(cn)

    # Map the storage and pump elements to their own individual construction graph nodes
    for fig_node_id in list(module.FIG.nodes):
        fig_node = module.FIG.get_fignode(fig_node_id)
        if isinstance(fig_node, Pump):
            cn = ConstructionNode(fig_node.id)
            sub_graph = module.FIG.subgraph(fig_node_id)
            mapping_candidates = library.get_pump_entries()
            for mapping_candidate in mapping_candidates:
                mapping_option = MappingOption(mapping_candidate, sub_graph)
                cn.add_mapping_option(mapping_option)

        elif isinstance(fig_node, Storage):
            cn = ConstructionNode(fig_node.id)
            sub_graph = module.FIG.subgraph(fig_node_id)
            mapping_candidates = library.get_storage_entries()
            for mapping_candidate in mapping_candidates:
                mapping_option = MappingOption(mapping_candidate, sub_graph)
                cn.add_mapping_option(mapping_option)

    # TODO - Validate if this is a legit way to do things
    mappings = module.get_explicit_mappings()
    override_network_mappings(mappings, library, module.FIG,
                              construction_graph)

    # TODO - Go through the different flow-flow edge networks to generate construction nodes
    # specific to these networks, Conditions:
    # if its a 1-1 flow-flow connection, then create a construction node for the two flow nodes
    # if its a 1-n / n-1 / n-n construction nodes, then create a construction node capturing the whole network

    # TODO - Deal with coverage issues here since we need to figure out what are the flow networks,
    # that we want to match first and then ensure that they're no included on any list
    cn_nodes = get_flow_flow_candidates(module, active_strategy)
    for cn in cn_nodes:
        construction_graph.add_construction_node(cn)

    # Apply all the explicit mappings in the module to the nodes, overwriting
    # the options from the library to match against
    # TODO - Modify Explicit Mapping Data structure

    # Find all the explicit mappings and override them in the construction graph
    override_mappings(mappings, library, module.FIG, construction_graph)

    # Whittle Down the mapping options here to only include the requried single candidates
    # TODO - Check what library is being used and use the required library here
    active_strategy.reduce_mapping_options()

    # TODO - Consider what needs to get done for a combinatorial design space
    # ----------------
    # Generate edges in the construction graph, these edges will guide the generation/
    # reduction of path and pipelineing that needs to get done for mars devices
    construction_graph.generate_edges(module.FIG)

    # TODO - Extract all pass through networks
    eliminate_passthrough_nodes(construction_graph)

    # Now since all the mapping options are finalized Extract the netlist necessary
    construction_graph.construct_components(name_generator, cur_device)

    construction_graph.construct_connections(name_generator, cur_device)

    # Finally join all the netlist pieces attached to the construction nodes
    # and the input/output/load/carrier flows
    # TODO - MINIMIZE - carrier / load flows - this might require us to generate
    # multiple netlist options and pick the best
    construction_graph.generate_flow_cn_edges(module)

    construction_graph.generate_control_cn_edges(module)

    # Generate all the unaccounted carriers and waste output lines necessary
    # for this to function
    connect_orphan_IO()

    # Size the component netlist
    active_strategy.size_netlist(cur_device)

    return cur_device