Exemple #1
0
def test_multi_resource_communication_phase(slow_resource, mediocre_resource,
                                            fast_resource):
    read_phase = CommunicationPhase(
        name="read",
        resources=[slow_resource, mediocre_resource, fast_resource],
        direction="read",
    )
    write_phase = CommunicationPhase(
        name="write",
        resources=[slow_resource, mediocre_resource, fast_resource],
        direction="write",
    )

    expected_read_latency = (slow_resource.read_latency() +
                             mediocre_resource.read_latency() +
                             fast_resource.read_latency())
    expected_write_latency = (slow_resource.write_latency() +
                              mediocre_resource.write_latency() +
                              fast_resource.write_latency())
    assert expected_read_latency == read_phase.get_costs(0)
    assert expected_write_latency == write_phase.get_costs(0)

    assert int(
        round(expected_read_latency + 100 /
              slow_resource.read_throughput())) == read_phase.get_costs(100)
    assert int(
        round(expected_write_latency + 100 /
              slow_resource.write_throughput())) == write_phase.get_costs(100)
Exemple #2
0
def primitives_from_buses(buses):
    """Generate a list of primitives from a list of buses.

    This creates a single phase communication primitive for each storage device
    that is connected to one of the buses. Processors that can reach the
    storage folowing the bus hierarchy are added as sources and sinks to these
    primitives. The buses that are required to reach the storage device from a
    processor are added as communication_resources to the consume or produce
    phases.
    """
    # first, get a list of all storages
    storages = []
    for b in buses:
        storages.extend(b._storages)

    primitives = []
    # create a primitive per storage
    for storage in storages:
        prim = Primitive("cp_%s" % (storage.name))

        # find the bus that connects to this storage
        storage_bus = None
        for b in buses:
            if storage in b._storages:
                storage_bus = b
                break

        connections = storage_bus.get_processor_connections()
        for c_buses, c_processors in connections:
            produce = CommunicationPhase("produce", c_buses + [storage],
                                         "write")
            consume = CommunicationPhase("consume", c_buses + [storage],
                                         "read")
            for p in c_processors:
                prim.add_producer(p, produce)
                prim.add_consumer(p, consume)

        primitives.append(prim)

    return primitives
Exemple #3
0
def test_multi_phase_primitive(slow_resource, mediocre_resource, fast_resource,
                               mocker):
    src = mocker.Mock(name="src")
    sink = mocker.Mock(name="sink")

    read_phases = [
        CommunicationPhase("read_ph1", [fast_resource], "read"),
        CommunicationPhase("read_ph2", [mediocre_resource], "read"),
        CommunicationPhase("read_ph3", [slow_resource], "read"),
    ]
    write_phases = [
        CommunicationPhase("write_ph1", [fast_resource], "write"),
        CommunicationPhase("write_ph2", [mediocre_resource], "write"),
        CommunicationPhase("write_ph3", [slow_resource], "write"),
    ]

    prim = Primitive("prim")
    prim.add_consumer(sink, read_phases)
    prim.add_producer(src, write_phases)

    expected_consume_costs_8 = sum([p.get_costs(8) for p in read_phases])
    expected_consume_costs_100 = sum([p.get_costs(100) for p in read_phases])
    assert prim.static_consume_costs(sink) == expected_consume_costs_8
    assert prim.static_consume_costs(sink, 100) == expected_consume_costs_100

    expected_produce_costs_8 = sum([p.get_costs(8) for p in write_phases])
    expected_produce_costs_100 = sum([p.get_costs(100) for p in write_phases])
    assert prim.static_produce_costs(src) == expected_produce_costs_8
    assert prim.static_produce_costs(src, 100) == expected_produce_costs_100

    expected_costs_8 = expected_consume_costs_8 + expected_produce_costs_8
    expected_costs_100 = expected_consume_costs_100 + expected_produce_costs_100
    assert prim.static_costs(src, sink) == expected_costs_8
    assert prim.static_costs(src, sink, 100) == expected_costs_100
    assert prim.static_costs(src, sink, 8) <= prim.static_costs(src, sink, 16)
Exemple #4
0
def test_single_resource_communication_phase(resource):
    read_phase = CommunicationPhase(name="read",
                                    resources=[resource],
                                    direction="read")
    write_phase = CommunicationPhase(name="write",
                                     resources=[resource],
                                     direction="write")

    assert resource.read_latency() == read_phase.get_costs(0)
    assert resource.write_latency() == write_phase.get_costs(0)

    assert int(
        round(resource.read_latency() +
              100 / resource.read_throughput())) == read_phase.get_costs(100)
    assert int(
        round(resource.write_latency() +
              100 / resource.write_throughput())) == write_phase.get_costs(100)
Exemple #5
0
def test_single_phase_primitive(resource, mocker):
    read_phase = CommunicationPhase(name="read",
                                    resources=[resource],
                                    direction="read")
    write_phase = CommunicationPhase(name="write",
                                     resources=[resource],
                                     direction="write")
    src = mocker.Mock(name="src")
    sink = mocker.Mock(name="sink")
    prim = Primitive("prim")
    prim.add_consumer(sink, [read_phase])
    prim.add_producer(src, [write_phase])

    with pytest.raises(RuntimeError):
        prim.add_consumer(sink, [])
    with pytest.raises(RuntimeError):
        prim.add_producer(src, [])

    with pytest.raises(RuntimeError):
        prim.add_producer(sink, [read_phase])
    with pytest.raises(RuntimeError):
        prim.add_consumer(src, [write_phase])

    assert prim.static_consume_costs(sink) == read_phase.get_costs(8)
    assert prim.static_consume_costs(sink, 100) == read_phase.get_costs(100)

    assert prim.static_produce_costs(src) == write_phase.get_costs(8)
    assert prim.static_produce_costs(src, 100) == write_phase.get_costs(100)

    expected_costs_8 = write_phase.get_costs(8) + read_phase.get_costs(8)
    expected_costs_100 = write_phase.get_costs(100) + read_phase.get_costs(100)
    assert prim.static_costs(src, sink) == expected_costs_8
    assert prim.static_costs(src, sink, 100) == expected_costs_100
Exemple #6
0
    def createNetworkForChips(
        self,
        networkName,
        adjacencyList,
        routingFunction,
        frequencyDomain,
        readLatency,
        writeLatency,
        readThroughput,
        writeThroughput,
    ):
        """Creates a network between the given elements.

        :param networkName: The name of the network. (primitives belonging to the network will be named
                                like this.
        :type networkName: String
        :param adjacencyList: The adjacency list of the elements within the network. The key is the name of
                                an element and the list contains the names of elements the key has a physical
                                link to.
        :type adjacencyList: dict {String : list[String]}
        :param routingFunction: A function, that takes the name of a source element, a target element and
                                the adjacency list. Should return the path, taken to communicate between source and
                                target, in case there is no direct physical link between them.
        :type routingFunction: function
        :param frequencyDomain: The frequency of the physical links an network routers.
        :type frequencyDomaing: int
        :param readLatency: The read latency of the physical links an network routers.
        :type readLatency: int
        :param writeLatency: The write latency of the physical links an network routers.
        :type writeLatency: int
        :param readThroughput: The read throughput of the physical links an network routers.
        :type readThroughput: int
        :param writeThroughput: The write throughput of the physical links and network routers.
        :type writeThroughput: int
        """

        fd = FrequencyDomain("fd_" + networkName, frequencyDomain)

        if self.__activeScope != None:
            """Creating a network between independent chips"""
            if self.__elementDict == {}:
                return
            for key in adjacencyList:
                """workaround with i, because different elements can have the same
                adjacency entry
                """
                name = networkName + "_" + "router_" + key
                communicationResource = CommunicationResource(
                    name,
                    CommunicationResourceType.Router,
                    fd,
                    readLatency,
                    writeLatency,
                    readThroughput,
                    writeThroughput,
                )
                self.__platform.add_communication_resource(
                    communicationResource
                )

                for target in adjacencyList[key]:
                    name = networkName + "_pl_" + str(target) + "_" + key
                    communicationResource = CommunicationResource(
                        name,
                        CommunicationResourceType.PhysicalLink,
                        fd,
                        readLatency,
                        writeLatency,
                        readThroughput,
                        writeThroughput,
                    )
                    self.__platform.add_communication_resource(
                        communicationResource
                    )

            for key in self.__elementDict[self.__activeScope]:
                if adjacencyList[key] == []:
                    continue
                for pe in self.__elementDict[self.__activeScope][key]:
                    """Adding a primitive for each pe in the network"""
                    prim = Primitive("prim_" + networkName + "_" + pe[0].name)

                    routerName = networkName + "_" + "router_" + str(key)
                    router = self.__platform.find_communication_resource(
                        routerName
                    )

                    for innerKey in self.__elementDict[self.__activeScope]:
                        if adjacencyList[innerKey] == []:
                            continue

                        resourceList = [router]

                        if innerKey != key:
                            path = routingFunction(adjacencyList, key, innerKey)
                            lastPoint = None

                            for point in path:
                                if lastPoint != None:
                                    name = (
                                        networkName
                                        + "_pl_"
                                        + str(lastPoint)
                                        + "_"
                                        + str(point)
                                    )
                                    resource = self.__platform.find_communication_resource(
                                        name
                                    )
                                    resourceList.append(resource)
                                lastPoint = point

                        for innerPe in self.__elementDict[self.__activeScope][
                            innerKey
                        ]:
                            """Iterating again over all pe's in the network to
                            create their consumer and producer phases etc. for
                            the primitive.
                            """
                            produce = CommunicationPhase(
                                "produce", resourceList, "write"
                            )
                            consume = CommunicationPhase(
                                "consume", resourceList, "read"
                            )

                            prim.add_producer(innerPe[0], [produce])
                            prim.add_consumer(innerPe[0], [consume])

                    self.__platform.add_primitive(prim)

            if self.__symLibrary:
                chipIds = set(adjacencyList.keys()) | set(
                    c for v in adjacencyList.values() for c in v
                )

                if not self._ag_classifyIdentifiers(chipIds):
                    raise ValueError(
                        "mpsym: chip network must consist of chips only"
                    )

                if self._ag_hasIdenticalChips():
                    if not self._ag_hasSuperGraph():
                        self._ag_createSuperGraph()

                    self._ag_connectSuperGraph(adjacencyList, networkName)

                    if self.__activeScope == "base":
                        self._ag_updateBaseAgs()
        else:
            return
Exemple #7
0
    def createNetworkForCluster(
        self,
        clusterIdentifier,
        networkName,
        adjacencyList,
        routingFunction,
        frequencyDomain,
        readLatency,
        writeLatency,
        readThroughput,
        writeThroughput,
    ):
        """Creates a network on chip topology for the given cluster.

        :param clusterIdentifier: The identifier of the cluster the network will be created for.
        :type clusterIdentifier: int
        :param networkName: The name of the network. (primitives belonging to the network will be named
                                like this.
        :type networkName: String
        :param adjacencyList: The adjacency list of the processing elements within the network.
                                The key is the name of a processing element and the list contains
                                the names of processing elements the key has a physical link to.
        :type adjacencyList: dict {String : list[String]}
        :param routingFunction: A function that takes the name of a source processing element, a target
                                processing element and the adjacency list. Should return the path taken to communicate
                                between source and target, in case there is no direct physical link between them.
        :type routingFunction: function
        :param frequencyDomain: The frequency of the physical links an network routers.
        :type frequencyDomain: int
        :param readLatency: The read latency of the physical links an network routers.
        :type readLatency: int
        :param writeLatency: The write latency of the physical links an network routers.
        :type witeLatency: int
        :param readThroughput: The read throughput of the physical links an network routers.
        :type readThroughput: int
        :param writeThroughput: The write throughput of the physical links and network routers.
        :type writeThroughput: int
        """
        fd = FrequencyDomain("fd_" + networkName, frequencyDomain)

        if self.__activeScope is not None:
            processorList = self.__elementDict[self.__activeScope][
                clusterIdentifier
            ]
            processorNames = [p.name for p, _ in processorList]

            """Adding physical links and NOC memories according to the adjacency list
            """
            for key in adjacencyList:
                name = str(clusterIdentifier) + "_noc_mem_" + str(key)
                communicationResource = Storage(
                    name,
                    fd,
                    readLatency,
                    writeLatency,
                    readThroughput,
                    writeThroughput,
                )
                self.__platform.add_communication_resource(
                    communicationResource
                )

                for target in adjacencyList[key]:
                    name = (
                        str(clusterIdentifier)
                        + "_pl_"
                        + str(target)
                        + "_"
                        + str(key)
                    )
                    communicationResource = CommunicationResource(
                        name,
                        fd,
                        CommunicationResourceType.PhysicalLink,
                        readLatency,
                        writeLatency,
                        readThroughput,
                        writeThroughput,
                    )
                    self.__platform.add_communication_resource(
                        communicationResource
                    )

                    if self.__symLibrary:
                        self._ag_addClusterChannel(key, target, networkName)

            for processor in processorList:
                if not adjacencyList[processor[0].name]:
                    continue
                else:
                    prim = Primitive(networkName + "_" + processor[0].name)
                    memoryName = (
                        str(clusterIdentifier)
                        # FIXME: this will lead to issues if we have >=2 NoCs
                        + "_noc_mem_"
                        + str(processor[0].name)
                    )
                    memory = self.__platform.find_communication_resource(
                        memoryName
                    )

                    for innerProcessor in processorList:
                        if not adjacencyList[innerProcessor[0].name]:
                            continue

                        resourceList = [memory]

                        if innerProcessor != processor:
                            path = routingFunction(
                                adjacencyList,
                                processor[0].name,
                                innerProcessor[0].name,
                            )
                            lastPoint = None

                            for point in path:
                                if lastPoint != None:
                                    name = (
                                        str(clusterIdentifier)
                                        + "_pl_"
                                        + str(lastPoint)
                                        + "_"
                                        + str(point)
                                    )
                                    resource = self.__platform.find_communication_resource(
                                        name
                                    )
                                    resourceList.append(resource)
                                lastPoint = point

                            produce = CommunicationPhase(
                                "produce", resourceList, "write"
                            )
                            consume = CommunicationPhase(
                                "consume", list(reversed(resourceList)), "read"
                            )

                            prim.add_producer(innerProcessor[0], [produce])
                            prim.add_consumer(innerProcessor[0], [consume])

                        else:
                            produce = CommunicationPhase(
                                "produce", resourceList, "write"
                            )
                            consume = CommunicationPhase(
                                "consume", list(reversed(resourceList)), "read"
                            )

                            prim.add_producer(innerProcessor[0], [produce])
                            prim.add_consumer(innerProcessor[0], [consume])

                    self.__platform.add_primitive(prim)
        else:
            return
Exemple #8
0
    def addCommunicationResource(
        self,
        name,
        clusterIds,
        readLatency,
        writeLatency,
        readThroughput,
        writeThroughput,
        # FIXME: probably we should just rename the method to add_storage
        resourceType=CommunicationResourceType.Storage,
        # FIXME: this argument should either be renamed to frequency or
        # expect an actual FrequencyDomain object
        frequencyDomain=0,
    ):
        """Adds a communication resource to the platform. All cores of the given cluster identifiers can communicate
        via this resource.

        :param name: The name of the storage
        :type name: String
        :param clusterIds: A list of identifiers for all clusters which will be connected.
        :type clusterIds: list[int]
        :param readLatency: The read latency of the communication resource.
        :type readLatency: int
        :param writeLatency: The write latency of the communication resource.
        :type writeLatency: int
        :param readThroughput: The read throughput of the communication resource.
        :type readThroughput: int
        :param writeThroughput: The write throughput of the communication resource.
        :type writeThroughput: int
        """
        # FIXME: shouldn't these checks produce an error instead of just
        # silently aborting?
        if not self.__schedulingPolicy:
            return
        if not self.__activeScope:
            return

        for clusterId in clusterIds:
            if clusterId not in self.__elementDict[self.__activeScope]:
                return

        clusterDict = self.__elementDict[self.__activeScope]
        nameToGive = (
            str(self.__activeScope)
            + "_"
            + name
            + "_"
            + str(self.__namingSuffix)
        )
        fd = FrequencyDomain("fd_" + name, frequencyDomain)

        try:
            # FIXME: why distinguish storage and other types here?
            if resourceType == CommunicationResourceType.Storage:
                com_resource = Storage(
                    nameToGive,
                    fd,
                    readLatency,
                    writeLatency,
                    readThroughput,
                    writeThroughput,
                )
            else:
                com_resource = CommunicationResource(
                    nameToGive,
                    fd,
                    resourceType,
                    readLatency,
                    writeLatency,
                    readThroughput,
                    writeThroughput,
                )

            self.__platform.add_communication_resource(com_resource)
            prim = Primitive("prim_" + nameToGive)

            for clusterId in clusterIds:
                for pe in clusterDict[clusterId]:
                    pe[1].append(com_resource)
                    produce = CommunicationPhase(
                        "produce", [com_resource], "write"
                    )
                    consume = CommunicationPhase(
                        "consume", [com_resource], "read"
                    )
                    prim.add_producer(pe[0], [produce])
                    prim.add_consumer(pe[0], [consume])

            self.__platform.add_primitive(prim)

        except:  # FIXME: this is fishy
            log.error("Exception caught: " + str(sys.exc_info()[0]))
            return

        if self.__symLibrary:
            idType = self._ag_classifyIdentifiers(clusterIds)

            if self._ag_hasChips():
                if idType != "chips":
                    raise ValueError(
                        "mpsym: cannot mix clusters/chips connections"
                    )

                if self._ag_hasIdenticalChips():
                    if not self._ag_hasSuperGraph():
                        self._ag_createSuperGraph()

                    self._ag_fullyConnectSuperGraph(clusterIds, name)

                    if self.__activeScope == "base":
                        self._ag_updateBaseAgs()
            else:
                if idType != "clusters":
                    raise ValueError(
                        "mpsym: cannot mix clusters/chips connections"
                    )

                self._ag_fullyConnectClusters(clusterIds, name)
Exemple #9
0
    def addCacheForPEs(
        self,
        identifier,
        readLatency,
        writeLatency,
        readThroughput,
        writeThroughput,
        # FIXME, this is a strange default
        frequencyDomain=100000,  # TODO: this should be added to tests
        name="L1_",
    ):
        """Adds a level 1 cache to each PE of the given cluster.

        :param identifier: The identifier of the cluster to which the cache will be added.
        :type identifier: int
        :param readLatency: The read latency of the cache.
        :type readLatency: int
        :param writeLatency: The write latency of the cache.
        :type writeLatency: int
        :param readThroughput: The read throughput of the cache.
        :type readThroughput: int
        :param writeThroughput: The write throughput of the cache.
        :type writeThroughput: int
        :param name: The cache name, in case it differs from L1.
        :type name: String
        """
        # FIXME: this should probably produce an error instead of returning
        # silently
        if self.__schedulingPolicy == None:
            return
        if self.__activeScope == None:
            return

        nameToGive = name

        if not identifier in self.__elementDict[self.__activeScope]:
            raise RuntimeWarning("Identifier does not exist in active scope.")

        peList = self.__elementDict[self.__activeScope][identifier]

        fd = FrequencyDomain("fd_" + name, frequencyDomain)

        try:
            for pe in peList:
                l1 = Storage(
                    nameToGive + pe[0].name,
                    frequency_domain=fd,
                    read_latency=readLatency,
                    write_latency=writeLatency,
                    read_throughput=readThroughput,
                    write_throughput=writeThroughput,
                )
                self.__platform.add_communication_resource(l1)

                # FIXME: What is this doing??
                pe[1].append(l1)

                prim = Primitive("prim_" + nameToGive + pe[0].name)

                produce = CommunicationPhase("produce", [l1], "write")
                consume = CommunicationPhase("consume", [l1], "read")
                prim.add_producer(pe[0], [produce])
                prim.add_consumer(pe[0], [consume])
                self.__platform.add_primitive(prim)

        except:  # FIXME: This is fishy
            log.error("Exception caught: " + sys.exc_info()[0])

        if self.__symLibrary:
            self._ag_addClusterCache(identifier, name)
Exemple #10
0
def convert(
    platform,
    xml_platform,
    scheduler_cycles=None,
    fd_frequencies=None,
    ppm_power=None,
):
    # keep a map of scheduler names to processors, this helps when creating
    # scheduler objects
    schedulers_to_processors = {}
    for s in xml_platform.get_Scheduler():
        schedulers_to_processors[s.get_id()] = []

    # Check the fd_frequencies defined the frequencies of only known domains
    if fd_frequencies is not None:
        fd_names = map(lambda x: x.get_id(),
                       xml_platform.get_FrequencyDomain())
        for fd in fd_frequencies:
            if fd not in fd_names:
                log.warning(f"The fd_frequencies defines the frequency of "
                            f"an unknown domain {fd}")

    # Collect all frequency and voltage domains
    voltage_domains = {}
    for vd in xml_platform.get_VoltageDomain():
        name = vd.get_id()
        voltage_domains[name] = []
        for v in vd.get_Voltage():
            voltage = ur(v.get_value() + v.get_unit()).to("V").magnitude
            voltage_domains[name].append(voltage)

    frequency_domains = {}
    # We do not save voltage domains by their names defined in MAPS XML files,
    # instead we save under the same names as frequency domains
    fd_voltage_cond = {}
    for fd in xml_platform.get_FrequencyDomain():
        name = fd.get_id()
        max_frequency = 0
        supported_frequency_voltage_pairs = []
        for f in fd.get_Frequency():
            voltage_domain_conds = f.get_VoltageDomainCondition()
            if len(voltage_domain_conds) > 1:
                raise RuntimeError(
                    f"The xml defines multiple voltages for the frequency domain "
                    f"{name} at {f.get_value()}{f.get_unit()}.")
            voltage_cond = None
            for v in voltage_domain_conds:
                voltage_cond = (ur(v.get_value() +
                                   v.get_unit()).to("V").magnitude)
            frequency = ur(f.get_value() + f.get_unit()).to("Hz").magnitude
            supported_frequency_voltage_pairs.append(
                tuple((frequency, voltage_cond)))
        if fd_frequencies is not None and name in fd_frequencies:
            frequency = fd_frequencies[name]
            voltage_cond = None
            found = False
            for f, v in supported_frequency_voltage_pairs:
                if frequency != f:
                    continue
                voltage_cond = v
                found = True
            if not found:
                log.warning(
                    f"The fd_frequencies sets the frequency of the domain {name} "
                    f"to {frequency} Hz, which is not defined in the xml. ")
        else:
            frequency, voltage_cond = max(supported_frequency_voltage_pairs)
            if len(fd.get_Frequency()) > 1:
                log.warning(
                    "The xml defines multiple frequencies for the domain "
                    "%s. -> Select Maximum",
                    name,
                )
        frequency_domains[name] = FrequencyDomain(name, frequency)
        fd_voltage_cond[name] = voltage_cond
        log.debug(
            "Found frequency domain %s (%d Hz).",
            name,
            frequency,
        )

    # Collect processor power model parameters
    processor_power_params = {}

    for ppm in xml_platform.get_ProcessorPowerModel():
        name = ppm.get_id()
        leakage_current = (ur(ppm.get_leakageCurrentValue() +
                              ppm.get_leakageCurrentUnit()).to("A").magnitude)
        switched_capacitance = (
            ur(ppm.get_switchedCapacitanceValue() +
               ppm.get_switchedCapacitanceUnit()).to("F").magnitude)
        processor_power_params[name] = {
            "leakage_current": leakage_current,
            "switched_capacitance": switched_capacitance,
        }

    # Check custom power
    if ppm_power is not None:
        for ppm, powers in ppm_power.items():
            if ppm not in processor_power_params:
                log.warning(f"The ppm_power defines the power of "
                            f"an unknown processor power model {ppm}")
                continue
            for power_mode in ["static", "dynamic"]:
                if power_mode not in powers:
                    log.warning(
                        f"The ppm_power does not define the {power_mode} power of "
                        f"a processor power model {ppm}")

    processor_power_models = {}

    # Initialize all Processors
    for xp in xml_platform.get_Processor():
        name = xp.get_id()
        type = xp.get_core()
        fd_name = xp.get_frequencyDomain()
        fd = frequency_domains[fd_name]

        # Initialize a processor power model
        vd_name = xp.get_voltageDomain()
        ppm_name = xp.get_processorPowerModel()
        if ppm_name is None:
            ppm = None
        else:
            if ppm_name not in processor_power_models:
                ppm = create_processor_power_model(
                    fd_name,
                    vd_name,
                    ppm_name,
                    frequency_domains,
                    voltage_domains,
                    fd_voltage_cond,
                    processor_power_params,
                    ppm_power,
                )
                processor_power_models[ppm_name] = ppm
            else:
                ppm = processor_power_models[ppm_name]

        context_load = get_value_in_cycles(xp, "contextLoad", 0)
        context_store = get_value_in_cycles(xp, "contextStore", 0)
        p = Processor(name, type, fd, ppm, context_load, context_store)
        schedulers_to_processors[xp.get_scheduler()].append(p)
        platform.add_processor(p)
        log.debug("Found processor %s of type %s", name, type)

    # Initialize all Schedulers
    for xs in xml_platform.get_Scheduler():
        name = xs.get_id()
        policy = create_policy(xml_platform, xs.get_schedulingPolicyList(),
                               scheduler_cycles)
        s = Scheduler(name, schedulers_to_processors[name], policy)
        log.debug(
            "Found scheduler %s for %s supporting %s",
            name,
            schedulers_to_processors[name],
            policy.name,
        )
        platform.add_scheduler(s)

    # Initialize all Memories, Caches, and Fifos as CommunicationResources
    for xm in xml_platform.get_Memory():
        name = xm.get_id()
        read_latency = get_value_in_cycles(xm, "readLatency", 0)
        write_latency = get_value_in_cycles(xm, "writeLatency", 0)
        read_throughput = get_value_in_byte_per_cycle(xm, "readThroughput",
                                                      float("inf"))
        write_throughput = get_value_in_byte_per_cycle(xm, "writeThroughput",
                                                       float("inf"))
        fd = frequency_domains[xm.get_frequencyDomain()]
        mem = Storage(
            name,
            fd,
            read_latency,
            write_latency,
            read_throughput,
            write_throughput,
        )
        platform.add_communication_resource(mem)
        log.debug("Found memory %s", name)

    for xc in xml_platform.get_Cache():
        name = xc.get_id()
        # XXX we assume 100% cache hit rate
        read_latency = get_value_in_cycles(xc, "readHitLatency", 0)
        write_latency = get_value_in_cycles(xc, "writeHitLatency", 0)
        read_throughput = get_value_in_byte_per_cycle(xc, "readHitThroughput",
                                                      float("inf"))
        write_throughput = get_value_in_byte_per_cycle(xc,
                                                       "writeHitThroughput",
                                                       float("inf"))
        fd = frequency_domains[xc.get_frequencyDomain()]
        cache = Storage(
            name,
            fd,
            read_latency,
            write_latency,
            read_throughput,
            write_throughput,
        )
        platform.add_communication_resource(cache)
        log.debug("Found cache %s", name)

    for xf in xml_platform.get_Fifo():
        name = xf.get_id()
        read_latency = get_value_in_cycles(xf, "readLatency", 0)
        write_latency = get_value_in_cycles(xf, "writeLatency", 0)
        read_throughput = get_value_in_byte_per_cycle(xf, "readThroughput",
                                                      float("inf"))
        write_throughput = get_value_in_byte_per_cycle(xf, "writeThroughput",
                                                       float("inf"))
        fd = frequency_domains[xf.get_frequencyDomain()]
        fifo = Storage(
            name,
            fd,
            read_latency,
            write_latency,
            read_throughput,
            write_throughput,
        )
        platform.add_communication_resource(fifo)
        log.debug("Found FIFO %s", name)

    # We also need to collect all the physical links, logical links and dma
    # controllers

    # modified by Felix Teweleit 10.08.2018

    for ll in xml_platform.get_PhysicalLink():
        name = ll.get_id()
        latency = get_value_in_cycles(ll, "latency", 0)
        throughput = get_value_in_byte_per_cycle(ll, "throughput",
                                                 float("inf"))
        fd = frequency_domains[ll.get_frequencyDomain()]
        link = CommunicationResource(
            name,
            fd,
            CommunicationResourceType.PhysicalLink,
            latency,
            latency,
            throughput,
            throughput,
        )
        platform.add_communication_resource(link)
        log.debug("Found link or DMA %s", name)

    for ll in xml_platform.get_LogicalLink():
        name = ll.get_id()
        latency = get_value_in_cycles(ll, "latency", 0)
        throughput = get_value_in_byte_per_cycle(ll, "throughput",
                                                 float("inf"))
        fd = frequency_domains[ll.get_frequencyDomain()]
        link = CommunicationResource(
            name,
            fd,
            CommunicationResourceType.LogicalLink,
            latency,
            latency,
            throughput,
            throughput,
        )
        platform.add_communication_resource(link)
        log.debug("Found link or DMA %s", name)

    for ll in xml_platform.get_DMAController():
        name = ll.get_id()
        latency = get_value_in_cycles(ll, "latency", 0)
        throughput = get_value_in_byte_per_cycle(ll, "throughput",
                                                 float("inf"))
        fd = frequency_domains[ll.get_frequencyDomain()]
        link = CommunicationResource(
            name,
            fd,
            CommunicationResourceType.DMAController,
            latency,
            latency,
            throughput,
            throughput,
        )
        platform.add_communication_resource(link)
        log.debug("Found link or DMA %s", name)

    # end of modified code

    # Initialize all Communication Primitives
    for xcom in xml_platform.get_Communication():
        name = xcom.get_id()

        producers = {}
        consumers = {}

        # Read the Producers
        for xp in xcom.get_Producer():
            pn = xp.get_processor()

            # TODO implement passive producing costs
            if xp.get_Passive() is not None:
                log.warning(
                    "Passive producing costs are not supported"
                    " -> ignore passive phase of primitive %s",
                    name,
                )

            # We create a single phase for each producer
            active = CommunicationPhase(
                "Produce Active",
                resources_from_access(xp.get_Active(), platform),
                "write",
            )
            producers[pn] = [active]

        # Read the Consumers
        for xc in xcom.get_Consumer():
            cn = xc.get_processor()

            # TODO implement passive producing costs
            if xc.get_Passive() is not None:
                log.warning(
                    "Passive consuming costs are not supported"
                    " -> ignore passive phase of primitive %s",
                    name,
                )

            # We create a single phase for each producer
            active = CommunicationPhase(
                "Consume Active",
                resources_from_access(xc.get_Active(), platform),
                "read",
            )
            consumers[cn] = [active]

        # Create a Primitive for each combination of producer and consumer
        primitive = Primitive(name)

        for pn in producers:
            primitive.add_producer(platform.find_processor(pn), producers[pn])
        for cn in consumers:
            primitive.add_consumer(platform.find_processor(cn), consumers[cn])

        log.debug("Found the communication primitive %s: %s -> %s" %
                  (name, str(producers.keys()), str(consumers.keys())))

        platform.add_primitive(primitive)
Exemple #11
0
    def __init__(self):
        super(Exynos2Chips, self).__init__("Exynos2Chips")

        # Frequency domains
        fd_a7 = FrequencyDomain("fd_a7", 1400000000)
        fd_a15 = FrequencyDomain("fd_a15", 2000000000)
        fd_l3 = FrequencyDomain("fd_l3", 1400000000)
        fd_ram = FrequencyDomain("fd_ram", 933000000)

        # Processors
        for i in range(0, 4):
            self.add_processor(Processor("PE%02d" % i, "ARM_CORTEX_A7", fd_a7))
        for i in range(4, 8):
            self.add_processor(
                Processor("PE%02d" % i, "ARM_CORTEX_A15", fd_a15))
        for i in range(8, 12):
            self.add_processor(Processor("PE%02d" % i, "ARM_CORTEX_A7", fd_a7))
        for i in range(12, 16):
            self.add_processor(
                Processor("PE%02d" % i, "ARM_CORTEX_A15", fd_a15))

        # Schedulers
        sp = SchedulingPolicy("FIFO", 1000)
        for i in range(0, 16):
            self.add_scheduler(
                Scheduler("sched%02d" % i, [self.find_processor("PE%02d" % i)],
                          [sp]))

        # L1 Caches
        for i in range(0, 4):
            self.add_communication_resource(
                Storage(
                    "L1_PE%02d" % i,
                    fd_a7,
                    read_latency=1,
                    write_latency=4,
                    read_throughput=8,
                    write_throughput=8,
                ))
        for i in range(4, 8):
            self.add_communication_resource(
                Storage(
                    "L1_PE%02d" % i,
                    fd_a15,
                    read_latency=1,
                    write_latency=4,
                    read_throughput=8,
                    write_throughput=8,
                ))
        for i in range(8, 12):
            self.add_communication_resource(
                Storage(
                    "L1_PE%02d" % i,
                    fd_a7,
                    read_latency=1,
                    write_latency=4,
                    read_throughput=8,
                    write_throughput=8,
                ))
        for i in range(12, 16):
            self.add_communication_resource(
                Storage(
                    "L1_PE%02d" % i,
                    fd_a15,
                    read_latency=1,
                    write_latency=4,
                    read_throughput=8,
                    write_throughput=8,
                ))

        # L1 Primitives
        for i in range(0, 16):
            pe = self.find_processor("PE%02d" % i)
            l1 = self.find_communication_resource("L1_PE%02d" % i)
            produce = CommunicationPhase("produce", [l1], "write")
            consume = CommunicationPhase("consume", [l1], "read")

            prim = Primitive("prim_L1_PE%02d" % i)
            prim.add_producer(pe, [produce])
            prim.add_consumer(pe, [consume])
            self.add_primitive(prim)

        # L2 Caches
        l2_C0_A7 = Storage(
            "L2_C0_A7",
            fd_a7,
            read_latency=16,
            write_latency=21,
            read_throughput=8,
            write_throughput=8,
        )
        l2_C0_A15 = Storage(
            "L2_C0_A15",
            fd_a15,
            read_latency=16,
            write_latency=21,
            read_throughput=8,
            write_throughput=8,
        )
        l2_C1_A7 = Storage(
            "L2_C1_A7",
            fd_a7,
            read_latency=16,
            write_latency=21,
            read_throughput=8,
            write_throughput=8,
        )
        l2_C1_A15 = Storage(
            "L2_C1_A15",
            fd_a15,
            read_latency=16,
            write_latency=21,
            read_throughput=8,
            write_throughput=8,
        )
        self.add_communication_resource(l2_C0_A7)
        self.add_communication_resource(l2_C0_A15)
        self.add_communication_resource(l2_C1_A7)
        self.add_communication_resource(l2_C1_A15)

        # L2 Primitives
        prim = Primitive("prim_L2_C0_A7")
        for i in range(0, 4):
            pe = self.find_processor("PE%02d" % i)
            l1 = self.find_communication_resource("L1_PE%02d" % i)

            produce = CommunicationPhase("produce", [l1, l2_C0_A7], "write")
            consume = CommunicationPhase("consume", [l1, l2_C0_A7], "read")
            prim.add_producer(pe, [produce])
            prim.add_consumer(pe, [consume])
        self.add_primitive(prim)

        prim = Primitive("prim_L2_C0_A15")
        for i in range(4, 8):
            pe = self.find_processor("PE%02d" % i)
            l1 = self.find_communication_resource("L1_PE%02d" % i)

            produce = CommunicationPhase("produce", [l1, l2_C0_A15], "write")
            consume = CommunicationPhase("consume", [l1, l2_C0_A15], "read")
            prim.add_producer(pe, [produce])
            prim.add_consumer(pe, [consume])
        self.add_primitive(prim)

        prim = Primitive("prim_L2_C1_A7")
        for i in range(8, 12):
            pe = self.find_processor("PE%02d" % i)
            l1 = self.find_communication_resource("L1_PE%02d" % i)

            produce = CommunicationPhase("produce", [l1, l2_C1_A7], "write")
            consume = CommunicationPhase("consume", [l1, l2_C1_A7], "read")
            prim.add_producer(pe, [produce])
            prim.add_consumer(pe, [consume])
        self.add_primitive(prim)

        prim = Primitive("prim_L2_C1_A15")
        for i in range(12, 16):
            pe = self.find_processor("PE%02d" % i)
            l1 = self.find_communication_resource("L1_PE%02d" % i)

            produce = CommunicationPhase("produce", [l1, l2_C1_A15], "write")
            consume = CommunicationPhase("consume", [l1, l2_C1_A15], "read")
            prim.add_producer(pe, [produce])
            prim.add_consumer(pe, [consume])
        self.add_primitive(prim)

        # L3 Caches
        l3_C0 = Storage(
            "L3_C0",
            fd_l3,
            read_latency=30,
            write_latency=21,
            read_throughput=8,
            write_throughput=8,
        )
        l3_C1 = Storage(
            "L3_C1",
            fd_l3,
            read_latency=40,
            write_latency=21,
            read_throughput=8,
            write_throughput=8,
        )
        self.add_communication_resource(l3_C0)
        self.add_communication_resource(l3_C1)

        # L3 Primitives
        prim = Primitive("prim_L3_C0")
        for i in range(0, 4):
            pe = self.find_processor("PE%02d" % i)
            l1 = self.find_communication_resource("L1_PE%02d" % i)

            produce = CommunicationPhase("produce", [l1, l2_C0_A7, l3_C0],
                                         "write")
            consume = CommunicationPhase("consume", [l1, l2_C0_A7, l3_C0],
                                         "read")
            prim.add_producer(pe, [produce])
            prim.add_consumer(pe, [consume])
        for i in range(4, 8):
            pe = self.find_processor("PE%02d" % i)
            l1 = self.find_communication_resource("L1_PE%02d" % i)

            produce = CommunicationPhase("produce", [l1, l2_C0_A15, l3_C0],
                                         "write")
            consume = CommunicationPhase("consume", [l1, l2_C0_A15, l3_C0],
                                         "read")
            prim.add_producer(pe, [produce])
            prim.add_consumer(pe, [consume])
        self.add_primitive(prim)

        prim = Primitive("prim_L3_C1")
        for i in range(8, 12):
            pe = self.find_processor("PE%02d" % i)
            l1 = self.find_communication_resource("L1_PE%02d" % i)

            produce = CommunicationPhase("produce", [l1, l2_C1_A7, l3_C1],
                                         "write")
            consume = CommunicationPhase("consume", [l1, l2_C1_A7, l3_C1],
                                         "read")
            prim.add_producer(pe, [produce])
            prim.add_consumer(pe, [consume])
        for i in range(12, 16):
            pe = self.find_processor("PE%02d" % i)
            l1 = self.find_communication_resource("L1_PE%02d" % i)

            produce = CommunicationPhase("produce", [l1, l2_C1_A15, l3_C1],
                                         "write")
            consume = CommunicationPhase("consume", [l1, l2_C1_A15, l3_C1],
                                         "read")
            prim.add_producer(pe, [produce])
            prim.add_consumer(pe, [consume])
        self.add_primitive(prim)

        # RAM
        ram = Storage(
            "RAM",
            fd_ram,
            read_latency=120,
            write_latency=120,
            read_throughput=8,
            write_throughput=8,
        )
        self.add_communication_resource(ram)

        prim = Primitive("prim_RAM")
        for i in range(0, 4):
            pe = self.find_processor("PE%02d" % i)
            l1 = self.find_communication_resource("L1_PE%02d" % i)

            produce = CommunicationPhase("produce", [l1, l2_C0_A7, l3_C0, ram],
                                         "write")
            consume = CommunicationPhase("consume", [l1, l2_C0_A7, l3_C0, ram],
                                         "read")
            prim.add_producer(pe, [produce])
            prim.add_consumer(pe, [consume])
        for i in range(4, 8):
            pe = self.find_processor("PE%02d" % i)
            l1 = self.find_communication_resource("L1_PE%02d" % i)

            produce = CommunicationPhase("produce",
                                         [l1, l2_C0_A15, l3_C0, ram], "write")
            consume = CommunicationPhase("consume",
                                         [l1, l2_C0_A15, l3_C0, ram], "read")
            prim.add_producer(pe, [produce])
            prim.add_consumer(pe, [consume])
        for i in range(8, 12):
            pe = self.find_processor("PE%02d" % i)
            l1 = self.find_communication_resource("L1_PE%02d" % i)

            produce = CommunicationPhase("produce", [l1, l2_C1_A7, l3_C1, ram],
                                         "write")
            consume = CommunicationPhase("consume", [l1, l2_C1_A7, l3_C1, ram],
                                         "read")
            prim.add_producer(pe, [produce])
            prim.add_consumer(pe, [consume])
        for i in range(12, 16):
            pe = self.find_processor("PE%02d" % i)
            l1 = self.find_communication_resource("L1_PE%02d" % i)

            produce = CommunicationPhase("produce",
                                         [l1, l2_C1_A15, l3_C1, ram], "write")
            consume = CommunicationPhase("consume",
                                         [l1, l2_C1_A15, l3_C1, ram], "read")
            prim.add_producer(pe, [produce])
            prim.add_consumer(pe, [consume])
        self.add_primitive(prim)