Example #1
0
class MainWindow(QtGui.QMainWindow, QtMainWindow.Ui_qtMainWindow):
    def __init__(self, cli_param, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.setCentralWidget(self.mdiArea)
        self.statusTxt = QtGui.QLabel("")
        self.dagFile = QtGui.QLabel("")
        self.statusBar().addWidget(self.dagFile)
        self.statusBar().addWidget(self.statusTxt)

        # connect to the machine
        if len(cli_param) > 1:
            ip = cli_param[1]
            if len(cli_param) > 2:
                self.myPC = cli_param[2]
            else:
                self.myPC = DEF_MYPC
        else:
            ip, ok = QtGui.QInputDialog.getText(None, "Connect to SpiNNaker",
                                                "Please specify machine IP",
                                                QtGui.QLineEdit.Normal,
                                                DEF_HOST)
            if ok is False:
                ip = ''
        print "Using machine at", ip
        self.mc = MachineController(ip)
        if BOOT_MACHINE is True:
            if self.mc.boot() is True:
                print "Machine is now booted..."
            else:
                print "Machine is already booted..."

        # then use machineInfo to build the map
        self.mInfo = self.mc.get_system_info()
        wMachine = self.mInfo.width
        hMachine = self.mInfo.height
        self.chipList = self.mInfo.keys()
        print "Found", len(self.chipList), "active chips:"
        """
        self.mc.iptag_set(0,'192.168.240.2',17892,0,0) # prepare iptag for myTub, because boot in rig doesn't provide this
        if DEF_HOST=='192.168.240.1':
            self.statusTxt.setText("Using SpiNN-5 board at {}".format(DEF_HOST))
        else:
            self.statusTxt.setText("Using SpiNN-3 board at {}".format(DEF_HOST))
        """

        #self.vis = visWidget(wMachine, hMachine, self.chipList, self.mdiArea)
        # for known dead chips on certain boards
        knownDeadChips = []
        if (len(self.chipList) % 48) != 0:
            # dead chip is detected
            lst = QtGui.QInputDialog.getText(
                self, "Dead chip is detected",
                "Please provide chip coordinate in () separated by space",
                QtGui.QLineEdit.Normal, "(0,2)")
            knownDeadChips = getDeadChipList(lst)
        self.tgvisWidget = visWidget(wMachine, hMachine, self.chipList,
                                     knownDeadChips)
        self.vis = tgViever(self.tgvisWidget)
        #self.vis.setGeometry(0,0,1024,1024)
        #self.vis.scale(0.5,0.5) # put in half size

        self.vis.hide()
        self.action_Visualiser.setCheckable(True)
        #self.action_Visualiser.setChecked(False)

        self.connect(self.action_Quit, QtCore.SIGNAL("triggered()"),
                     QtCore.SLOT("Quit()"))
        self.connect(self.action_Load_XML, QtCore.SIGNAL("triggered()"),
                     QtCore.SLOT("loadXML()"))
        self.connect(self.action_Visualiser, QtCore.SIGNAL("triggered()"),
                     QtCore.SLOT("showVisualiser()"))
        self.connect(self.action_Send_and_Init, QtCore.SIGNAL("triggered()"),
                     QtCore.SLOT("sendAndInit()"))
        self.connect(self.actionInspect_SpinConf, QtCore.SIGNAL("triggered()"),
                     QtCore.SLOT("testSpin1()"))
        self.connect(self.actionSet_Tick, QtCore.SIGNAL("triggered()"),
                     QtCore.SLOT("getSimulationTick()"))
        self.connect(self.actionStart, QtCore.SIGNAL("triggered()"),
                     QtCore.SLOT("startSim()"))
        self.connect(self.actionStop, QtCore.SIGNAL("triggered()"),
                     QtCore.SLOT("stopSim()"))

        # 22 March 2017 - 11:48 - Buat experiment ambil data untuk paper
        self.timer = QtCore.QTimer(self)
        #self.timer.setInterval(60000) # one minute experiment
        self.timer.timeout.connect(self.timeout)

        # Simulation parameters
        self.simTick = 1000000  # default value that yield 1second resolution
        self.runningTime = 0  # 0 means runs forever
        self.dag = None  # this is a list of list of dict that contains target dependency data
        """
        self.srcTarget = dict()     # this similar to self.dag, but just contains target for SOURCE node
                                    # (as a dict of a list), e.g: from dag0020, srcTarget = {0: [4,3,2]}
        """
        self.srcTarget = list(
        )  # now scrTarget becomes simpler, because we don't send the trigger's payload
        self.sdp = sdpComm(self.chipList, ip)
        self.sdp.histUpdate.connect(self.vis.updateHist)
        self.setGeometry(0, 0, 1024, 1024)

    @QtCore.pyqtSlot()
    def timeout(self):
        """
        Ini buat ambil data. Setelah jalan 1 menit, otomatis stop. Kemudian lihat iobuf dari srcsink node!
        :return:
        """
        self.stopSim()
        self.timer.stop()

    def closeEvent(self, e):
        self.vis.close()
        e.accept()

    @QtCore.pyqtSlot()
    def Quit(self):
        # TODO: clean up...
        self.close()

    @QtCore.pyqtSlot()
    def showVisualiser(self):
        if self.action_Visualiser.isChecked() is True:
            #self.vis = visWidget(self.mdiArea)     # cuman buat sejarah kalau dulu aku letakkan di sini!
            #self.vis.setGeometry(0,0,1024,1024)
            self.vis.animate()
            #self.vis.sceneTimer.start(500)
            self.vis.show()
        else:
            self.vis.deanimate()
            self.vis.hide()
            #self.vis.sceneTimer.stop()

    def buildMap(self):
        """
        Let's build map correctly
        :input: self.dag
        :output: self.TGmap
        """

    def readTGmap(self, fname, chipList, numNode):
        """
        Read TGmap configuration from the given fname
        :param fname: .tgmap configuration file
        :param chipList: a dict() that contains all active chip coordinate in the machine
        :return: list() if success, otherwise None
        """
        result = None
        ok = False
        with open(fname, 'r') as fid:
            dct = dict()
            nodeFound = 0
            for line in fid:
                #print "line:", line
                idFromXY = getChipIDfromXY(line)
                if idFromXY is not None:
                    dct.update(idFromXY)
                    nodeFound += 1
            if len(dct) > 0:
                print "Found", nodeFound, "nodes (including SRC/SINK)"
                result = [-1 for _ in range(len(chipList))]
                for i in range(len(chipList)):
                    try:
                        result[i] = dct[chipList[i]]
                    except KeyError:
                        result[i] = -1
                if nodeFound == numNode + 1:
                    ok = True
        return result, ok

    @QtCore.pyqtSlot()
    def loadXML(self):
        print "Loading XML..."
        fullPathFileName = QtGui.QFileDialog.getOpenFileName(
            self, "Open XML file", "./", "*.xml")
        if not fullPathFileName:
            print "Cancelled!"
        else:

            fi = QtCore.QFileInfo()
            fi.setFile(fullPathFileName)
            fn = fi.fileName()
            self.dagFile.setText("Using {}".format(fn))
            print "Processing ", fullPathFileName
            parser = xml.sax.make_parser()

            # turn off namespace
            parser.setFeature(xml.sax.handler.feature_namespaces, 0)

            # override the default ContextHandler
            Handler = tgxmlHandler()
            parser.setContentHandler(Handler)
            parser.parse(str(fullPathFileName))

            if SHOW_PARSING_RESULT:
                showParsingResult(Handler)
            """ Let's put the c-like struct as a list:
                Let's create a variable cfg, which is a list of a dict.
                Then, let's create a variable dag, which is a list of cfg. Hence, dag is a list of a list of a dict.
            """
            dag = list()
            for nodes in Handler.Nodes:
                cfg = list()
                srcPayload = list()
                srcFound = False
                for target in nodes.Target:
                    dct = dict()
                    dct['nodeID'] = nodes.Id
                    dct['destID'] = target.destId
                    dct['nPkt'] = target.nPkt
                    dct['nDependant'] = target.nDependant
                    for d in range(target.nDependant):
                        srcIDkey = "dep{}_srcID".format(d)
                        nTriggerPktkey = "dep{}_nTriggerPkt".format(d)
                        dct[srcIDkey] = target.Dep[d].srcId
                        dct[nTriggerPktkey] = target.Dep[d].nTriggerPkt
                        # also search for SOURCE dependant
                        if target.Dep[d].srcId == DEF_SOURCE_ID:
                            srcFound = True
                            srcPayload.append(target.Dep[d].nTriggerPkt)
                    cfg.append(dct)
                    # and put the payload to the current word in the dict
                if srcFound:
                    self.srcTarget.append(nodes.Id)
                    # self.srcTarget[nodes.Id] = srcPayload --> ini yang lama sebelum aku REVISI
                dag.append(cfg)

            self.dag = dag
            #self.dag = experiment_dag0020()

            # for debugging:
            #print "SpiNNaker usage  :", self.TGmap
            if SHOW_PARSING_RESULT:
                print "TG configuration :", self.dag
            #print len(self.dag)
            print "Source Target    :", self.srcTarget

            # then load the TGmap configuration file
            tgmapConfigFile = QtGui.QFileDialog.getOpenFileName(
                self, "Open TGmap file", "./", "*.tgmap")
            if not tgmapConfigFile:
                print "Cancelled!"
                self.dag = None
                self.srcTarget = list()
                return

            tgmap, ok = self.readTGmap(tgmapConfigFile, self.chipList,
                                       len(self.dag))
            if tgmap is None:
                print "Failed to get correct TGmap configuration!"
                # then cancel the operation and reset
                self.dag = None
                self.srcTarget = list()
                return
            else:
                if ok:
                    #print tgmap
                    print "Loaded tgmap from:", tgmapConfigFile
                    self.TGmap = tgmap
                else:
                    print "Missing node is detected! Maybe dead chip?"
                    # then cancel the operation and reset
                    self.dag = None
                    self.srcTarget = list()
            """
            # Then ask for the appropriate map
            cbItem = tg2spinMap.keys();
            # simTick, ok = QtGui.QInputDialog.getInt(self, "Simulation Tick", "Enter Simulation Tick in microsecond", self.simTick, DEF_MIN_TIMER_TICK, 10000000, 1)

            mapItem, ok = QtGui.QInputDialog.getItem(self, "Select Map", "Which map will be used?", cbItem, 0, False)
            if ok is True:
                print "Will use",mapItem,':',tg2spinMap[str(mapItem)]
                # self.initMap(mapItem)
                self.TGmap = tg2spinMap[str(mapItem)]
            else:
                print "Cancelled!"
                return
            """

            # continue with send and init?
            contSendInit = QtGui.QMessageBox.question(
                self, "Continue", "Continue with Send and Init?",
                QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel)
            if contSendInit == QtGui.QMessageBox.Ok:
                self.sendAndInit()
            else:
                QtGui.QMessageBox.information(
                    self, "Done",
                    "Loading XML and TGmap is done! You can continue with Send and Init!"
                )

    @QtCore.pyqtSlot()
    def testSpin1(self):
        """
        send a request to dump tgsdp configuration data
        sendSDP(self, flags, tag, dp, dc, dax, day, cmd, seq, arg1, arg2, arg3, bArray):
        """
        f = NO_REPLY
        t = DEF_SEND_IPTAG
        p = DEF_SDP_CONF_PORT
        c = DEF_SDP_CORE
        m = TGPKT_HOST_ASK_REPORT

        for item in self.TGmap:
            if item != -1 and item != DEF_SOURCE_ID:
                x, y = getChipXYfromID(self.TGmap, item, self.chipList)
                #print "Sending a request to <{},{}:{}>".format(x,y,c)
                self.sdp.sendSDP(f, t, p, c, x, y, m, 0, 0, 0, 0, None)
                time.sleep(DEF_SDP_TIMEOUT)

    @QtCore.pyqtSlot()
    def sendAndInit(self):
        """
        will send aplx to corresponding chip and initialize/configure the chip
        Assuming that the board has been booted?
        """

        if self.dag == None:
            QtGui.QMessageBox.information(self, "Information",
                                          "No valid network structure yet!")
            return

        # First, need to translate from node-ID to chip position <x,y>, including the SOURCE and SINK node
        # use self.TGmap
        print "Doing translation from node to chip..."
        self.xSrc, self.ySrc = getChipXYfromID(self.TGmap, DEF_SOURCE_ID,
                                               self.chipList)
        appCores = dict()
        for item in self.TGmap:
            if item != -1 and item != DEF_SOURCE_ID:
                x, y = getChipXYfromID(self.TGmap, item, self.chipList)
                appCores[(x, y)] = [DEF_APP_CORE]

        if SHOW_PARSING_RESULT:
            print "Application cores :", appCores
        allChips = dict()
        for item in self.chipList:
            allChips[(item[0], item[1])] = [DEF_MON_CORE]
        if SHOW_PARSING_RESULT:
            print "Monitor cores :", allChips
        # Second, send the aplx (tgsdp.aplx and srcsink.aplx) to the corresponding chip
        # example: mc.load_application("bla_bla_bla.aplx", {(0,0):[1,2,10,17]}, app_id=16)
        # so, the chip is a tupple and cores is in a list!!!
        # Do you want something nice? Use QFileDialog

        if ENABLE_IPTAG:
            print "Send iptag..."
            self.mc.iptag_set(
                DEF_TUBO_IPTAG, self.myPC, DEF_TUBO_PORT, 0, 0
            )  # prepare iptag for myTub, because boot in rig doesn't provide this
            self.mc.iptag_set(DEF_REPORT_IPTAG, self.myPC, DEF_REPORT_PORT, 0,
                              0)

        print "Send the aplxs to the corresponding chips...",
        srcsinkaplx = "/local/new_home/indi/Projects/P/Graceful_TG_SDP_virtualenv/src/aplx/srcsink.aplx"
        tgsdpaplx = "/local/new_home/indi/Projects/P/Graceful_TG_SDP_virtualenv/src/aplx/tgsdp.aplx"
        monaplx = "/local/new_home/indi/Projects/P/Graceful_TG_SDP_virtualenv/src/aplx/monitor.aplx"
        self.mc.load_application(srcsinkaplx,
                                 {(self.xSrc, self.ySrc): [DEF_APP_CORE]},
                                 app_id=APPID_SRCSINK)
        self.mc.load_application(tgsdpaplx, appCores, app_id=APPID_TGSDP)
        self.mc.load_application(monaplx, allChips, app_id=APPID_MONITOR)
        time.sleep(5)
        self.mc.send_signal('sync0', app_id=APPID_SRCSINK)
        self.mc.send_signal('sync0', app_id=APPID_TGSDP)
        self.mc.send_signal('sync0', app_id=APPID_MONITOR)
        print "done!"

        # Debugging: why some chips generate WDOG?
        self.sdp.sendPing(self.TGmap)

        # Third, send the configuration to the corresponding node
        print "Sending the configuration data to the corresponding chip...",
        for node in self.dag:  # self.dag should be a list of a list of a dict
            #print "Node =",node
            time.sleep(
                DEF_SDP_TIMEOUT
            )  # WEIRD!!!! If I remove this, then node-0 will be corrupted!!!
            self.sdp.sendConfig(self.TGmap, node)
        print "done!"

        print "Sending special configuration to SOURCE/SINK node...",
        # TODO: send the source target list!!!
        self.sdp.sendSourceTarget(
            self.TGmap,
            self.srcTarget)  # butuh TGmap karena butuh xSrc dan ySrc
        print "done! ---------- WAIT, Abaikan nilai payload-nya!!!! ------------"
        # NOTE: di bagian sdp.sendSourceTarget() tidak aku ubah untuk akomodasi hal tersebut!!!!!!!!!
        #       Jadi, sangat tergantung srcsink.c untuk betulin-nya!!!!

        print "Sending network map...",
        self.sdp.sendChipMap(self.TGmap)
        print "done! SpiNNaker is ready for TGSDP simulation (set tick if necessary)!"
        QtGui.QMessageBox.information(
            self, "Done",
            "SpiNNaker is ready for TGSDP simulation (set tick if necessary)!")

        # TODO: 1. Baca P2P table
        #       2. Petakan dan kirim ke tgsdpvis.py. Nanti tgsdpvis.py akan memberi warna
        apasihini = self.mc.get_system_info()
        p2p_tables = {(x, y): self.mc.get_p2p_routing_table(x, y)
                      for x, y in self.mc.get_system_info()}
        #for c in apasihini.chips():
        #    print c

    @QtCore.pyqtSlot()
    def getSimulationTick(self):
        simTick, ok = QtGui.QInputDialog.getInt(
            self, "Simulation Tick", "Enter Simulation Tick in microsecond",
            self.simTick, DEF_MIN_TIMER_TICK, 1000, 1)
        if ok is True:
            print "Sending tick {} microseconds".format(simTick)
            self.simTick = simTick
            self.sdp.sendSimTick(self.xSrc, self.ySrc, simTick)

    @QtCore.pyqtSlot()
    def startSim(self):
        # First ask, for how long
        msLong, ok = QtGui.QInputDialog.getInt(
            self, "Running Time", "Enter simulation running time (in ms)",
            60000, DEF_MIN_RUNNING_TIME, DEF_MAX_RUNNING_TIME, 1)
        if ok:
            self.runningTime = msLong

        self.actionStop.setEnabled(True)
        self.actionStart.setEnabled(False)
        self.sdp.sendStartCmd(self.xSrc, self.ySrc)
        print "Starting simulation..."
        # untuk ambil data, buat timer:
        if self.runningTime > 0:
            print "Set interval to", self.runningTime, "ms"
            self.timer.setInterval(self.runningTime)
            self.timer.start()

    @QtCore.pyqtSlot()
    def stopSim(self):
        if self.timer.isActive():
            self.timer.stop()
        self.actionStop.setEnabled(False)
        self.actionStart.setEnabled(True)
        # self.sdp.sendStopCmd(self.xSrc, self.ySrc) #-> only to SOURCE/SINK node
        self.sdp.sendStopCmd(self.xSrc, self.ySrc,
                             self.TGmap)  #-> to all nodes
        print "Experimen selesai. Sekarang lihat iobuf core-1 di chip<0,0> (srcsink node)"
        QtGui.QMessageBox.information(
            self, "Experiment Done!",
            "Look the result at iobuf core-1 in chip<0,0> (srcsink node)!")
Example #2
0
class MainWindow(QtGui.QMainWindow, QtMainWindow.Ui_qtMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.setCentralWidget(self.mdiArea)
        self.statusTxt = QtGui.QLabel("")
        self.dagFile = QtGui.QLabel("")
        self.statusBar().addWidget(self.dagFile)
        self.statusBar().addWidget(self.statusTxt)

        self.vis = visWidget(self.mdiArea)
        self.vis.setGeometry(0, 0, 1024, 1024)
        #self.vis.scale(0.5,0.5) # put in half size
        self.vis.hide()
        self.action_Visualiser.setCheckable(True)
        #self.action_Visualiser.setChecked(False)

        self.connect(self.action_Quit, QtCore.SIGNAL("triggered()"),
                     QtCore.SLOT("Quit()"))
        self.connect(self.action_Load_XML, QtCore.SIGNAL("triggered()"),
                     QtCore.SLOT("loadXML()"))
        self.connect(self.action_Visualiser, QtCore.SIGNAL("triggered()"),
                     QtCore.SLOT("showVisualiser()"))
        self.connect(self.action_Send_and_Init, QtCore.SIGNAL("triggered()"),
                     QtCore.SLOT("sendAndInit()"))
        self.connect(self.actionInspect_SpinConf, QtCore.SIGNAL("triggered()"),
                     QtCore.SLOT("testSpin1()"))
        self.connect(self.actionSet_Tick, QtCore.SIGNAL("triggered()"),
                     QtCore.SLOT("getSimulationTick()"))
        self.connect(self.actionStart, QtCore.SIGNAL("triggered()"),
                     QtCore.SLOT("startSim()"))
        self.connect(self.actionStop, QtCore.SIGNAL("triggered()"),
                     QtCore.SLOT("stopSim()"))

        self.simTick = 1000000  # default value that yield 1second resolution
        self.output = None  # this is a list of list of dict that contains target dependency data
        """
        self.srcTarget = dict()     # this similar to self.output, but just contains target for SOURCE node
                                    # (as a dict of a list), e.g: from dag0020, srcTarget = {0: [4,3,2]}
        """
        self.srcTarget = list(
        )  # now scrTarget becomes simpler, because we don't send the trigger's payload
        self.sdp = sdpComm()
        self.sdp.histUpdate.connect(self.vis.updateHist)
        self.mc = MachineController(DEF_HOST)
        if BOOT_MACHINE is True:
            if self.mc.boot() is True:
                print "Machine is now booted..."
            else:
                print "Machine is already booted..."
        self.machineInfo = self.mc.get_system_info()
        """
        self.mc.iptag_set(0,'192.168.240.2',17892,0,0) # prepare iptag for myTub, because boot in rig doesn't provide this
        if DEF_HOST=='192.168.240.1':
            self.statusTxt.setText("Using SpiNN-5 board at {}".format(DEF_HOST))
        else:
            self.statusTxt.setText("Using SpiNN-3 board at {}".format(DEF_HOST))
        """
        self.setGeometry(0, 0, 1024, 1024)

    @QtCore.pyqtSlot()
    def Quit(self):
        # TODO: clean up...
        self.close()

    @QtCore.pyqtSlot()
    def showVisualiser(self):
        if self.action_Visualiser.isChecked() is True:
            #self.vis = visWidget(self.mdiArea)     # cuman buat sejarah kalau dulu aku letakkan di sini!
            #self.vis.setGeometry(0,0,1024,1024)
            self.vis.sceneTimer.start(500)
            self.vis.show()
        else:
            self.vis.hide()
            self.vis.sceneTimer.stop()

    @QtCore.pyqtSlot()
    def loadXML(self):
        print "Loading XML..."
        fullPathFileName = QtGui.QFileDialog.getOpenFileName(
            self, "Open XML file", "./", "*.xml")
        if not fullPathFileName:
            print "Cancelled!"
        else:
            # Then ask for the appropriate map
            cbItem = tg2spinMap.keys()
            # simTick, ok = QtGui.QInputDialog.getInt(self, "Simulation Tick", "Enter Simulation Tick in microsecond", self.simTick, DEF_MIN_TIMER_TICK, 10000000, 1)

            mapItem, ok = QtGui.QInputDialog.getItem(
                self, "Select Map", "Which map will be used?", cbItem, 0,
                False)
            if ok is True:
                print "Will use", mapItem
                # self.initMap(mapItem)
                self.TGmap = tg2spinMap[str(mapItem)]
            else:
                print "Cancelled!"
                return

            fi = QtCore.QFileInfo()
            fi.setFile(fullPathFileName)
            fn = fi.fileName()
            self.dagFile.setText("Using {}".format(fn))
            print "Processing ", fullPathFileName
            parser = xml.sax.make_parser()

            # turn off namespace
            parser.setFeature(xml.sax.handler.feature_namespaces, 0)

            # override the default ContextHandler
            Handler = tgxmlHandler()
            parser.setContentHandler(Handler)
            parser.parse(str(fullPathFileName))

            if SHOW_PARSING_RESULT:
                showParsingResult(Handler)
            """ Let's put the c-like struct as a list:
                Let's create a variable cfg, which is a list of a dict.
                Then, let's create a variable dag, which is a list of cfg. Hence, dag is a list of a list of a dict.
            """
            dag = list()
            for nodes in Handler.Nodes:
                cfg = list()
                srcPayload = list()
                srcFound = False
                for target in nodes.Target:
                    dct = dict()
                    dct['nodeID'] = nodes.Id
                    dct['destID'] = target.destId
                    dct['nPkt'] = target.nPkt
                    dct['nDependant'] = target.nDependant
                    for d in range(target.nDependant):
                        srcIDkey = "dep{}_srcID".format(d)
                        nTriggerPktkey = "dep{}_nTriggerPkt".format(d)
                        dct[srcIDkey] = target.Dep[d].srcId
                        dct[nTriggerPktkey] = target.Dep[d].nTriggerPkt
                        # also search for SOURCE dependant
                        if target.Dep[d].srcId == DEF_SOURCE_ID:
                            srcFound = True
                            srcPayload.append(target.Dep[d].nTriggerPkt)
                    cfg.append(dct)
                    # and put the payload to the current word in the dict
                if srcFound:
                    self.srcTarget.append(nodes.Id)
                    # self.srcTarget[nodes.Id] = srcPayload --> ini yang lama sebelum aku REVISI
                dag.append(cfg)

            self.output = dag
            #self.output = experiment_dag0020()

            # for debugging:
            print "SpiNNaker usage  :", self.TGmap
            print "TG configuration :", self.output
            print "Source Target    :", self.srcTarget

    @QtCore.pyqtSlot()
    def testSpin1(self):
        """
        send a request to dump tgsdp configuration data
        sendSDP(self, flags, tag, dp, dc, dax, day, cmd, seq, arg1, arg2, arg3, bArray):
        """
        f = NO_REPLY
        t = DEF_SEND_IPTAG
        p = DEF_SDP_CONF_PORT
        c = DEF_SDP_CORE
        m = TGPKT_HOST_ASK_REPORT

        for item in self.TGmap:
            if item != -1 and item != DEF_SOURCE_ID:
                x, y = getChipXYfromID(self.TGmap, item)
                #print "Sending a request to <{},{}:{}>".format(x,y,c)
                self.sdp.sendSDP(f, t, p, c, x, y, m, 0, 0, 0, 0, None)
                time.sleep(DEF_SDP_TIMEOUT)

    @QtCore.pyqtSlot()
    def sendAndInit(self):
        """
        will send aplx to corresponding chip and initialize/configure the chip
        Assuming that the board has been booted?
        """

        if self.output == None:
            QtGui.QMessageBox.information(self, "Information",
                                          "No valid network structure yet!")
            return

        # First, need to translate from node-ID to chip position <x,y>, including the SOURCE and SINK node
        # use self.TGmap
        print "Do translation from node to chip..."
        self.xSrc, self.ySrc = getChipXYfromID(self.TGmap, DEF_SOURCE_ID)
        appCores = dict()
        for item in self.TGmap:
            if item != -1 and item != DEF_SOURCE_ID:
                x, y = getChipXYfromID(self.TGmap, item)
                appCores[(x, y)] = [DEF_APP_CORE]

        print "Application cores :", appCores
        allChips = dict()
        for item in CHIP_LIST_48:
            allChips[(item[0], item[1])] = [DEF_MON_CORE]
        print "Monitor cores :", allChips
        # Second, send the aplx (tgsdp.aplx and srcsink.aplx) to the corresponding chip
        # example: mc.load_application("bla_bla_bla.aplx", {(0,0):[1,2,10,17]}, app_id=16)
        # so, the chip is a tupple and cores is in a list!!!
        # Do you want something nice? Use QFileDialog

        print "Send iptag...",
        self.mc.iptag_set(
            DEF_TUBO_IPTAG, '192.168.240.2', DEF_TUBO_PORT, 0, 0
        )  # prepare iptag for myTub, because boot in rig doesn't provide this
        self.mc.iptag_set(DEF_REPORT_IPTAG, '192.168.240.2', DEF_REPORT_PORT,
                          0, 0)
        if DEF_HOST == '192.168.240.1':
            self.statusTxt.setText(
                "Using SpiNN-5 board at {}".format(DEF_HOST))
        else:
            self.statusTxt.setText(
                "Using SpiNN-3 board at {}".format(DEF_HOST))
        print "done!"

        print "Send the aplxs to the corresponding chips...",
        srcsinkaplx = "/local/new_home/indi/Projects/P/Graceful_TG_SDP_virtualenv/src/aplx/srcsink.aplx"
        tgsdpaplx = "/local/new_home/indi/Projects/P/Graceful_TG_SDP_virtualenv/src/aplx/tgsdp.aplx"
        monaplx = "/local/new_home/indi/Projects/P/Graceful_TG_SDP_virtualenv/src/aplx/monitor.aplx"
        self.mc.load_application(srcsinkaplx,
                                 {(self.xSrc, self.ySrc): [DEF_APP_CORE]},
                                 app_id=APPID_SRCSINK)
        self.mc.load_application(tgsdpaplx, appCores, app_id=APPID_TGSDP)
        self.mc.load_application(monaplx, allChips, app_id=APPID_MONITOR)
        print "done!"

        # Debugging: why some chips generate WDOG?
        self.sdp.sendPing(self.TGmap)

        # Third, send the configuration to the corresponding node
        print "Sending the configuration data to the corresponding chip...",
        for node in self.output:  # self.output should be a list of a list of a dict
            #print "Node =",node
            time.sleep(
                DEF_SDP_TIMEOUT
            )  # WEIRD!!!! If I remove this, then node-0 will be corrupted!!!
            self.sdp.sendConfig(self.TGmap, node)
        print "done!"

        print "Sending special configuration to SOURCE/SINK node...",
        # TODO: send the source target list!!!
        self.sdp.sendSourceTarget(
            self.TGmap,
            self.srcTarget)  # butuh TGmap karena butuh xSrc dan ySrc
        print "done! ---------- WAIT, Abaikan nilai payload-nya!!!! ------------"
        # NOTE: di bagian sdp.sendSourceTarget() tidak aku ubah untuk akomodasi hal tersebut!!!!!!!!!
        #       Jadi, sangat tergantung srcsink.c untuk betulin-nya!!!!

        print "Sending network map...",
        self.sdp.sendChipMap(self.TGmap)
        print "done! SpiNNaker is ready for TGSDP simulation (set tick if necessary)!"

        # TODO: 1. Baca P2P table
        #       2. Petakan dan kirim ke tgsdpvis.py. Nanti tgsdpvis.py akan memberi warna
        apasihini = self.mc.get_system_info()
        p2p_tables = {(x, y): self.mc.get_p2p_routing_table(x, y)
                      for x, y in self.mc.get_system_info()}
        #for c in apasihini.chips():
        #    print c

    @QtCore.pyqtSlot()
    def getSimulationTick(self):
        simTick, ok = QtGui.QInputDialog.getInt(
            self, "Simulation Tick", "Enter Simulation Tick in microsecond",
            self.simTick, DEF_MIN_TIMER_TICK, 10000000, 1)
        if ok is True:
            print "Sending tick {} microseconds".format(simTick)
            self.simTick = simTick
            self.sdp.sendSimTick(self.xSrc, self.ySrc, simTick)

    @QtCore.pyqtSlot()
    def startSim(self):
        self.actionStop.setEnabled(True)
        self.actionStart.setEnabled(False)
        self.sdp.sendStartCmd(self.xSrc, self.ySrc)

    @QtCore.pyqtSlot()
    def stopSim(self):
        self.actionStop.setEnabled(False)
        self.actionStart.setEnabled(True)
        # self.sdp.sendStopCmd(self.xSrc, self.ySrc) #-> only to SOURCE/SINK node
        self.sdp.sendStopCmd(self.xSrc, self.ySrc,
                             self.TGmap)  #-> to all nodes
        0x02,  # NT_CMD_BARRIER
        0x00,  # NT_CMD_EXIT
    ]

    data = struct.pack("<{}I".format(len(commands) + 1),
                       len(commands) * 4, *commands)
    mem = mc.sdram_alloc_as_filelike(max(len(data),
                                         4 + num_samples * num_vals * 4),
                                     tag=1,
                                     x=0,
                                     y=0)
    mem.write(data)

    # Catch-all route
    entries = [RoutingTableEntry(set([Routes.core_1]), 0x00000000, 0x00000000)]
    mc.load_routing_table_entries(entries, x=0, y=0)

    mc.load_application(binary, {(0, 0): set([1])})
    time.sleep(1.5)
    mc.wait_for_cores_to_reach_state("sync0", 1)
    mc.send_signal("sync0")
    mem.seek(0)
    error_state = struct.unpack("<I", mem.read(4))[0]
    print("Error state: {}".format(error_state))
    print(
        struct.unpack("<{}I".format(num_samples * num_vals),
                      mem.read(4 * num_samples * num_vals)))

    if error_state:
        input("press enter to kill...")
    def run(self):
        """Run the simulation."""
        # Define the resource requirements of each component in the simulation.
        vertices_resources = {
            # Every component runs on exactly one core and consumes a certain
            # amount of SDRAM to hold configuration data.
            component: {Cores: 1, SDRAM: component._get_config_size()}
            for component in self._components
        }

        # Work out what SpiNNaker application needs to be loaded for each
        # component
        vertices_applications = {component: component._get_kernel()
                                 for component in self._components}

        # Convert the Wire objects into Rig Net objects and create a lookup
        # from Net to the (key, mask) to use.
        net_keys = {Net(wire.source, wire.sinks): (wire.routing_key,
                                                   0xFFFFFFFF)
                    for wire in self._wires}
        nets = list(net_keys)

        # Boot the SpiNNaker machine and interrogate it to determine what
        # resources (e.g. cores, SDRAM etc.) are available.
        mc = MachineController(self._hostname)
        mc.boot()
        system_info = mc.get_system_info()

        # Automatically chose which chips and cores to use for each component
        # and generate routing tables.
        placements, allocations, application_map, routing_tables = \
            place_and_route_wrapper(vertices_resources,
                                    vertices_applications,
                                    nets, net_keys,
                                    system_info)

        with mc.application():
            # Allocate memory for configuration data, tagged by core number.
            memory_allocations = sdram_alloc_for_vertices(mc, placements,
                                                          allocations)

            # Load the configuration data for all components
            for component, memory in memory_allocations.items():
                component._write_config(memory)

            # Load all routing tables
            mc.load_routing_tables(routing_tables)

            # Load all SpiNNaker application kernels
            mc.load_application(application_map)

            # Wait for all six cores to reach the 'sync0' barrier
            mc.wait_for_cores_to_reach_state("sync0", len(self._components))

            # Send the 'sync0' signal to start execution and wait for the
            # simulation to finish.
            mc.send_signal("sync0")
            time.sleep(self.length * 0.001)
            mc.wait_for_cores_to_reach_state("exit", len(self._components))

            # Retrieve result data
            for component, memory in memory_allocations.items():
                component._read_results(memory)
Example #5
0
    # Build the targets dictionary
    targets = {chip: {1} for chip in iterkeys(chip_mem)}

    # Load the data
    print("Loading data...")
    t = time.time()
    for chip, mem in iteritems(chip_mem):
        mem.write(chip_data[chip])
    load_time = time.time() - t
    print("... took {:.3f} s".format(load_time))

    # Load the application
    print("Loading application...")
    if args.memory_profile is None:
        mc.load_application("./ordered_covering.aplx", targets)
    else:
        mc.load_application("./ordered_covering_profiled.aplx", targets)
    t = time.time()

    # Wait until this does something interesting
    print("Minimising...")
    ready = mc.wait_for_cores_to_reach_state("exit",
                                             len(uncompressed),
                                             timeout=60.0)
    if ready < len(uncompressed):
        raise Exception("Something didn't work...")
    run_time = time.time() - t
    print("... took ~{:.3f} s".format(run_time))

    # Read back the routing tables
class Experiment(object):
    """Defines a network experiment to be run on a SpiNNaker machine.

    An experiment consists of a fixed set of 'vertices'
    (:py:meth:`.new_vertex`) connected together by 'nets'
    (:py:meth:`.new_net`). Vertices correspond with SpiNNaker application cores
    running artificial traffic generators and the nets correspond with traffic
    flows between cores.

    An experiment is broken up into 'groups' (:py:meth:`.new_group`), during
    which the traffic generators produce packets according to a specified
    traffic pattern. Within each group, metrics, such as packet counts, may be
    recorded. Though the placement of vertices and the routing of nets is
    fixed throughout an experiment, the rate and pattern with which which
    packets are produced can be varied between groups allowing, for example,
    different traffic patterns to be tested.

    When the experiment is :py:meth:`.run`, appropriately-configured traffic
    generator applications will be loaded onto SpiNNaker and, after the
    experiment completes, the results are read back ready for analysis.
    """

    def __init__(self, hostname_or_machine_controller):
        """Create a new network experiment on a particular SpiNNaker machine.

        Example usage::

            >>> import sys
            >>> from network_tester import Experiment
            >>> e = Experiment(sys.argv[1])  # Takes hostname as a CLI argument

        The experimental parameters can be set by setting attributes of the
        :py:class:`Experiment` instance like so::

            >>> e = Experiment(...)
            >>> # Set the probability of a packet being generated at the source
            >>> # of each net every timestep
            >>> e.probability = 1.0

        Parameters
        ----------
        hostname_or_machine_controller : \
                str or :py:class:`rig.machine_control.MachineController`
            The hostname or :py:class:`~rig.machine_control.MachineController`
            of a SpiNNaker machine to run the experiment on.
        """
        if isinstance(hostname_or_machine_controller, str):
            self._mc = MachineController(hostname_or_machine_controller)
        else:
            self._mc = hostname_or_machine_controller

        # A cached reference to the SpiNNaker machine the experiment will run
        # in. To be accessed via .machine which automatically fetches the
        # machine the first time it is requested.
        self._machine = None

        # A set of placements, allocations and routes for the
        # traffic-generating/consuming vertices.
        self._placements = None
        self._allocations = None
        self._routes = None

        # The experimental group currently being defined. Set and cleared on
        # entry and exit of Group context-managers.
        self._cur_group = None

        # A list of experimental groups which have been defined
        self._groups = []

        # A list of vertices in the experiment
        self._vertices = []

        # A list of nets in the experiment
        self._nets = []

        # Holds the value of every option along with any special cases.
        # If a value can have per-node or per-group exceptions it is stored as
        # a dictionary with keys (group, vert_or_net) with the value being
        # defined as below. Otherwise, the value is just stored immediately in
        # the _values dictionary. The list below gives the order of priority
        # for definitions.
        # * (None, None) The global default
        # * (group, None) The default for a particular experimental group
        # * (None, vertex) The default for a particular vertex
        # * (None, net) The default for a particular net
        # * (group, vertex) The value for a particular vertex in a specific
        #   group
        # * (group, net) The value for a particular net in a specific group
        # {option: value or {(group, vert_or_net): value, ...}, ...}
        self._values = {
            "seed": {(None, None): None},
            "timestep": {(None, None): 0.001},
            "warmup": {(None, None): 0.0},
            "duration": {(None, None): 1.0},
            "cooldown": {(None, None): 0.0},
            "flush_time": {(None, None): 0.01},
            "record_interval": {(None, None): 0.0},
            "probability": {(None, None): 1.0},
            "burst_period": {(None, None): 0.0},
            "burst_duty": {(None, None): 0.0},
            "burst_phase": {(None, None): 0.0},
            "use_payload": {(None, None): False},
            "consume_packets": {(None, None): True},
            "router_timeout": {(None, None): None},
            "reinject_packets": {(None, None): False},
        }

        # All counters are global-only options and default to False.
        for counter in Counters:
            self._values["record_{}".format(counter.name)] = False

    def new_vertex(self, name=None):
        """Create a new :py:class:`Vertex`.

        A vertex corresponds with a SpiNNaker application core and can produce
        or consume SpiNNaker packets.

        Example::

            >>> # Create three vertices
            >>> v0 = e.new_vertex()
            >>> v1 = e.new_vertex()
            >>> v2 = e.new_vertex()

        The experimental parameters for each vertex can also be overridden
        individually if desired::

            >>> # Nets sourced at vertex v2 will transmit with 50% probability
            >>> # each timestep
            >>> v2.probability = 0.5

        Parameters
        ----------
        name
            *Optional.* A name for the vertex. If not specified the vertex will
            be given a number as its name. This name will be used in results
            tables.

        Returns
        -------
        :py:class:`Vertex`
            An object representing the vertex.
        """
        v = Vertex(self, name if name is not None else len(self._vertices))
        self._vertices.append(v)

        # Adding a new vertex invalidates any existing placement solution
        self.placements = None

        return v

    def new_net(self, source, sinks, weight=1.0, name=None):
        """Create a new net.

        A net represents a flow of SpiNNaker packets from one source vertex to
        many sink vertices.

        For example::

            >>> # A net with v0 as a source and v1 as a sink.
            >>> n0 = e.new_net(v0, v1)

            >>> # Another net with v0 as a source and both v1 and v2 as sinks.
            >>> n1 = e.new_net(v0, [v1, v2])

        The experimental parameters for each net can also be overridden
        individually if desired. This will take precedence over any overridden
        values set for the source vertex of the net.

        For example::

            >>> # Net n0 will generate a packet in 80% of timesteps
            >>> n0.probability = 0.8

        Parameters
        ----------
        source : :py:class:`Vertex`
            The source :py:class:`Vertex` of the net. A stream of packets will
            be generated by this vertex and sent to all sinks.

            Only :py:class:`Vertex` objects created by this
            :py:class:`Experiment` may be used.
        sinks : :py:class:`Vertex` or [:py:class:`Vertex`, ...]
            The sink :py:class:`Vertex` or list of sink vertices for the net.

            Only :py:class:`Vertex` objects created by this
            :py:class:`Experiment` may be used.
        weight : float
            *Optional.* A hint for place and route tools indicating the
            relative amount of traffic that may flow through this net. This
            number is not used by the traffic generator.
        name
            *Optional.* A name for the net. If not specified the net will be
            given a number as its name. This name will be used in results
            tables.

        Returns
        -------
        :py:class:`Net`
            An object representing the net.
        """
        if name is None:
            name = len(self._nets)
        n = Net(self, name, source, sinks, weight)

        # Adding a new net invalidates any routing solution.
        self.routes = None

        self._nets.append(n)
        return n

    def new_group(self, name=None):
        """Define a new experimental group.

        The experiment can be divided up into groups where the traffic pattern
        generated (but not the structure of connectivity) varies for each
        group. Results are recorded separately for each group and the network
        is drained of packets between groups.

        The returned :py:class:`Group` object can be used as a context manager
        within which experimental parameters specific to that group may be set,
        including per-vertex and per-net parameters. Note that parameters set
        globally for the experiment in particular group do not take precedence
        over per-vertex or per-net parameter settings.

        For example::

            >>> with e.new_group():
            ...     # Overrides default probability of sending a packet within
            ...     # the group.
            ...     e.probability = 0.5
            ...     # Overrides the probability for v2 within the group
            ...     v2.probability = 0.25
            ...     # Overrides the probability for n0 within the group
            ...     n0.probability = 0.4

        Parameters
        ----------
        name
            *Optional.* A name for the group. If not specified the group will
            be given a number as its name. This name will be used in results
            tables.

        Returns
        -------
        :py:class:`Group`
            An object representing the group.
        """
        g = Group(self, name if name is not None else len(self._groups))
        self._groups.append(g)
        return g

    def run(self, app_id=0x42, create_group_if_none_exist=True,
            ignore_deadline_errors=False):
        """Run the experiment on SpiNNaker and return the results.

        If placements, allocations or routes have not been provided, the
        vertices and nets will be automatically placed, allocated and routed
        using the default algorithms in Rig.

        Following placement, the experimental parameters are loaded onto the
        machine and each experimental group is executed in turn. Results are
        recorded by the machine and at the end of the experiment are read back.

        .. warning::
            Though a global synchronisation barrier is used between the
            execution of each group, the timers in each vertex may drift out of
            sync during each group's execution. Further, the barrier
            synchronisation does not give any guarantees about how
            closely-synchronised the timers will be at the start of each run.

        Parameters
        ----------
        app_id : int
            *Optional.* The SpiNNaker application ID to use for the experiment.
        create_group_if_none_exist : bool
            *Optional.* If True (the default), a single group will be
            automatically created if none have been defined with
            :py:meth:`.new_group`. This is the most sensible behaviour for most
            applications.

            If you *really* want to run an experiment with no experimental
            groups (where no traffic will ever be generated and no results
            recorded), you can set this option to False.
        ignore_deadline_errors : bool
            If True, any realtime deadline-missed errors will no longer cause
            this method to raise an exception. Other errors will still cause an
            exception to be raised.

            This option is useful when running experiments which involve
            over-saturating packet sinks or the network in some experimental
            groups.

        Returns
        -------
        :py:class:`Results`
            If no vertices reported errors, the experimental results are
            returned.  See the :py:class:`Results` object for details.

        Raises
        ------
        NetworkTesterError
            A :py:exc:`NetworkTesterError` is raised if any vertices reported
            an error. The most common error is likely to be a 'deadline missed'
            error as a result of the experimental timestep being too short or
            the load on some vertices too high in extreme circumstances. Other
            types of error indicate far more severe problems.

            Any results recorded during the run will be included in the
            ``results`` attribute of the exception. See the :py:class:`Results`
            object for details.
        """
        # Sensible default: Create a single experimental group if none defined.
        if create_group_if_none_exist and len(self._groups) == 0:
            self.new_group()

        # Place and route the vertices (if required)
        self.place_and_route()

        # Add nodes to unused chips to access router registers/counters (if
        # necessary).
        (vertices, router_access_vertices,
         placements, allocations, routes) = \
            self._add_router_recording_vertices()

        # Assign a unique routing key to each net
        net_keys = {net: num << 8
                    for num, net in enumerate(self._nets)}
        routing_tables = build_routing_tables(
            routes,
            {net: (key, 0xFFFFFF00) for net, key in iteritems(net_keys)})

        network_tester_binary = pkg_resources.resource_filename(
            "network_tester", "binaries/network_tester.aplx")
        reinjector_binary = pkg_resources.resource_filename(
            "network_tester", "binaries/reinjector.aplx")

        # Specify the appropriate binary for the network tester vertices.
        application_map = build_application_map(
            {vertex: network_tester_binary for vertex in vertices},
            placements, allocations)

        # Get the set of source and sink nets for each vertex. Also sets an
        # explicit ordering of the sources/sinks within each.
        # {vertex: [source_or_sink, ...], ...}
        vertices_source_nets = {v: [] for v in vertices}
        vertices_sink_nets = {v: [] for v in vertices}
        for net in self._nets:
            vertices_source_nets[net.source].append(net)
            for sink in net.sinks:
                vertices_sink_nets[sink].append(net)

        vertices_records = self._get_vertex_record_lookup(
            vertices, router_access_vertices, placements,
            vertices_source_nets, vertices_sink_nets)

        # Fill out the set of commands for each vertex
        vertices_commands = {
            vertex: self._construct_vertex_commands(
                vertex=vertex,
                source_nets=vertices_source_nets[vertex],
                sink_nets=vertices_sink_nets[vertex],
                net_keys=net_keys,
                records=[cntr for obj, cntr in vertices_records[vertex]],
                router_access_vertex=vertex in router_access_vertices)
            for vertex in vertices
        }

        # The data size for the results from each vertex
        total_num_samples = sum(g.num_samples for g in self._groups)
        vertices_result_size = {
            vertex: (
                # The error flag (one word)
                1 +
                # One word per recorded value per sample.
                (total_num_samples * len(vertices_records[vertex]))
            ) * 4
            for vertex in vertices}

        # The raw result data for each vertex.
        vertices_result_data = {}

        # Actually load and run the experiment on the machine.
        with self._mc.application(app_id):
            # Allocate SDRAM. This is enough to fit the commands and also any
            # recored results.
            vertices_sdram = {}
            logger.info("Allocating SDRAM...")
            for vertex in vertices:
                size = max(
                    # Size of commands (with length prefix)
                    vertices_commands[vertex].size,
                    # Size of results (plus the flags)
                    vertices_result_size[vertex],
                )
                x, y = placements[vertex]
                p = allocations[vertex][Cores].start
                vertices_sdram[vertex] = self._mc.sdram_alloc_as_filelike(
                    size, x=x, y=y, tag=p)

            # Load each vertex's commands
            logger.info("Loading {} bytes of commands...".format(
                sum(c.size for c in itervalues(vertices_commands))))
            for vertex, sdram in iteritems(vertices_sdram):
                sdram.write(vertices_commands[vertex].pack())

            # Load routing tables
            logger.info("Loading routing tables...")
            self._mc.load_routing_tables(routing_tables)

            # Load the packet-reinjection application if used. This must be
            # completed before the main application since it creates a tagged
            # memory allocation.
            if self._reinjection_used():
                logger.info("Loading packet-reinjection application...")
                self._mc.load_application(reinjector_binary,
                                          {xy: set([1])
                                           for xy in self.machine})

            # Load the application
            logger.info("Loading application on to {} cores...".format(
                len(vertices)))
            self._mc.load_application(application_map)

            # Run through each experimental group
            next_barrier = "sync0"
            for group_num, group in enumerate(self._groups):
                # Reach the barrier before the run starts
                logger.info("Waiting for barrier...")
                num_at_barrier = self._mc.wait_for_cores_to_reach_state(
                    next_barrier, len(vertices), timeout=2.0)
                assert num_at_barrier == len(vertices), \
                    "Not all cores reached the barrier " \
                    "before {}.".format(group)

                self._mc.send_signal(next_barrier)
                next_barrier = "sync1" if next_barrier == "sync0" else "sync0"

                # Give the run time to complete
                warmup = self._get_option_value("warmup", group)
                duration = self._get_option_value("duration", group)
                cooldown = self._get_option_value("cooldown", group)
                flush_time = self._get_option_value("flush_time", group)
                total_time = warmup + duration + cooldown + flush_time

                logger.info(
                    "Running group {} ({} of {}) for {} seconds...".format(
                        group.name, group_num + 1, len(self._groups),
                        total_time))
                time.sleep(total_time)

            # Wait for all cores to exit after their final run
            logger.info("Waiting for barrier...")
            num_at_barrier = self._mc.wait_for_cores_to_reach_state(
                "exit", len(vertices), timeout=2.0)
            assert num_at_barrier == len(vertices), \
                "Not all cores reached the final barrier."

            # Read recorded data back
            logger.info("Reading back {} bytes of results...".format(
                sum(itervalues(vertices_result_size))))
            for vertex, sdram in iteritems(vertices_sdram):
                sdram.seek(0)
                vertices_result_data[vertex] = \
                    sdram.read(vertices_result_size[vertex])

        # Process read results
        results = Results(self, self._vertices, self._nets, vertices_records,
                          router_access_vertices, placements, routes,
                          vertices_result_data, self._groups)
        if any(not e.is_deadline if ignore_deadline_errors else True
               for e in results.errors):
            logger.error(
                "Experiment completed with errors: {}".format(results.errors))
            raise NetworkTesterError(results)
        else:
            logger.info("Experiment completed successfully")
            return results

    def place_and_route(self,
                        constraints=None,
                        place=place, place_kwargs={},
                        allocate=allocate, allocate_kwargs={},
                        route=route, route_kwargs={}):
        """Place and route the vertices and nets in the current experiment, if
        required.

        If extra control is required over placement and routing of vertices and
        nets in an experiment, this method allows additional constraints and
        custom placement, allocation and routing options and algorithms to be
        used.

        The result of placement, allocation and routing can be found in
        :py:attr:`placements`, :py:attr:`allocations` and  :py:attr:`routes`
        respectively.

        If even greater control is required, :py:attr:`placements`,
        :py:attr:`allocations` and  :py:attr:`routes` may be set explicitly.
        Once these attributes have been set, this method will not alter them.

        Since many applications will not care strongly about placement,
        allocation and routing, this method is called implicitly by
        :py:meth:`.run`.

        Parameters
        ----------
        constraints : [constraint, ...]
            A list of additional constraints to apply. A
            :py:class:`rig.place_and_route.constraints.ReserveResourceConstraint`
            will be applied to reserve the monitor processor on top of this
            constraint.
        place : placer
            A Rig-API complaint placement algorithm.
        place_kwargs : dict
            Additional algorithm-specific keyword arguments to supply to the
            placer.
        allocate : allocator
            A Rig-API complaint allocation algorithm.
        allocate_kwargs : dict
            Additional algorithm-specific keyword arguments to supply to the
            allocator.
        route : router
            A Rig-API complaint route algorithm.
        route_kwargs : dict
            Additional algorithm-specific keyword arguments to supply to the
            router.
        """
        # Each traffic generator consumes a core and a negligible amount of
        # memory.
        vertices_resources = {vertex: {Cores: 1} for vertex in
                              self._vertices}

        # Reserve the monitor processor for each chip
        constraints = constraints or []
        constraints += [ReserveResourceConstraint(Cores, slice(0, 1))]

        # Reserve a core for packet reinjection on each chip (if required)
        if self._reinjection_used():
            constraints += [ReserveResourceConstraint(Cores, slice(1, 2))]

        if self.placements is None:
            logger.info("Placing vertices...")
            self.placements = place(vertices_resources=vertices_resources,
                                    nets=self._nets,
                                    machine=self.machine,
                                    constraints=constraints,
                                    **place_kwargs)
            self.allocations = None
            self.routes = None

        if self.allocations is None:
            logger.info("Allocating vertices...")
            self.allocations = allocate(vertices_resources=vertices_resources,
                                        nets=self._nets,
                                        machine=self.machine,
                                        constraints=constraints,
                                        placements=self.placements,
                                        **allocate_kwargs)
            self.routes = None

        if self.routes is None:
            logger.info("Routing vertices...")
            self.routes = route(vertices_resources=vertices_resources,
                                nets=self._nets,
                                machine=self.machine,
                                constraints=constraints,
                                placements=self.placements,
                                allocations=self.allocations,
                                **allocate_kwargs)

    @property
    def placements(self):
        """A dictionary {:py:class:`Vertex`: (x, y), ...}, or None.

        Defines the chip on which each vertex will be placed during the
        experiment. Note that the placement must define the position of *every*
        vertex. If None, calling :py:meth:`.run` or :py:meth:`.place_and_route`
        will cause all vertices to be placed automatically.

        Setting this attribute will also set :py:attr:`.allocations` and
        :py:attr:`.routes` to None.

        Any placement must be valid for the :py:class:`~rig.machine.Machine`
        specified by the :py:attr:`.machine` attribute. Core 0 must always be
        reserved for the monitor processor and, if packet reinjection is used
        or recorded (see :py:attr:`Experiment.reinject_packets`), core 1 must
        also be reserved for the packet reinjection application.

        See also :py:func:`rig.place_and_route.place`.
        """
        return self._placements

    @placements.setter
    def placements(self, value):
        self._placements = value
        self.allocation = None
        self.routes = None

    @property
    def allocations(self):
        """A dictionary {:py:class:`Vertex`: {resource: slice}, ...} or None.

        Defines the resources allocated to each vertex. This must include
        exactly 1 unit of the :py:class:`~rig.machine.Cores` resource.  Note
        that the allocation must define the resource allocation of *every*
        vertex. If None, calling :py:meth:`.run` or :py:meth:`.place_and_route`
        will cause all vertices to have their resources allocated
        automatically.

        Setting this attribute will also set :py:attr:`.routes` to None.

        Any allocation must be valid for the :py:class:`~rig.machine.Machine`
        specified by the :py:attr:`.machine` attribute. Core 0 must always be
        reserved for the monitor processor and, if packet reinjection is used
        or recorded (see :py:attr:`Experiment.reinject_packets`), core 1 must
        also be reserved for the packet reinjection application.

        See also :py:func:`rig.place_and_route.allocate`.
        """
        return self._allocations

    @allocations.setter
    def allocations(self, value):
        self._allocations = value
        self.routes = None

    @property
    def routes(self):
        """A dictionary {:py:class:`Net`: \
        :py:class:`rig.place_and_route.routing_tree.RoutingTree`, ...} or None.

        Defines the route used for each net.  Note that the route must be
        defined for *every* net. If None, calling :py:meth:`.run` or
        :py:meth:`.place_and_route` will cause all nets to be routed
        automatically.

        See also :py:func:`rig.place_and_route.route`.
        """
        return self._routes

    @routes.setter
    def routes(self, value):
        self._routes = value

    def _any_router_registers_used(self):
        """Are any router registers (including reinjection counters) being
        recorded or configured during the experiment?"""
        return (any(self._get_option_value("record_{}".format(counter.name))
                    for counter in Counters if counter.router_counter) or
                self._get_option_value("router_timeout") is not None or
                any(self._get_option_value("router_timeout", g) is not None
                    for g in self._groups) or
                self._reinjection_used())

    def _reinjection_used(self):
        """Is dropped packet reinjection used (or recorded) in the
        experiment?
        """
        return (any(self._get_option_value("record_{}".format(counter.name))
                    for counter in Counters if counter.reinjector_counter) or
                self._get_option_value("reinject_packets") or
                any(self._get_option_value("reinject_packets", g)
                    for g in self._groups))

    @property
    def machine(self):
        """The :py:class:`~rig.machine.Machine` object describing the SpiNNaker
        system under test.

        This property caches the machine description read from the machine to
        avoid repeatedly polling the SpiNNaker system.
        """
        if self._machine is None:
            logger.info("Getting SpiNNaker machine information...")
            self._machine = self._mc.get_machine()
        return self._machine

    @machine.setter
    def machine(self, value):
        self._machine = value

    def _construct_vertex_commands(self, vertex, source_nets, sink_nets,
                                   net_keys, records, router_access_vertex):
        """For internal use. Produce the Commands for a particular vertex.

        Parameters
        ----------
        vertex : :py:class:`.Vertex`
            The vertex to pack
        source_nets : [:py:class:`.Net`, ...]
            The nets which are sourced at this vertex.
        sink_nets : [:py:class:`.Net`, ...]
            The nets which are sunk at this vertex.
        net_keys : {:py:class:`.Net`: key, ...}
            A mapping from net to routing key.
        records : [counter, ...]
            The set of counters this vertex records
        router_access_vertex : bool
            Should this vertex be used to configure router/reinjector
            parameters.
        """
        commands = Commands()

        # Set up the sources and sinks for the vertex
        commands.num(len(source_nets), len(sink_nets))
        for source_num, source_net in enumerate(source_nets):
            commands.source_key(source_num, net_keys[source_net])
        for sink_num, sink_net in enumerate(sink_nets):
            commands.sink_key(sink_num, net_keys[sink_net])

        # Generate commands for each experimental group
        for group in self._groups:
            # Set general parameters for the group
            commands.seed(self._get_option_value("seed", group))
            commands.timestep(self._get_option_value("timestep", group))
            commands.record_interval(self._get_option_value("record_interval",
                                                            group))

            # Set per-source parameters for the group
            for source_num, source_net in enumerate(source_nets):
                commands.burst(
                    source_num,
                    self._get_option_value("burst_period", group, source_net),
                    self._get_option_value("burst_duty", group, source_net),
                    self._get_option_value("burst_phase", group, source_net))
                commands.probability(
                    source_num,
                    self._get_option_value("probability",
                                           group,
                                           source_net))
                commands.payload(
                    source_num,
                    self._get_option_value("use_payload",
                                           group,
                                           source_net))

            # Synchronise before running the group
            commands.barrier()

            # Turn on reinjection as required
            if router_access_vertex:
                commands.reinject(
                    self._get_option_value("reinject_packets", group))

            # Turn off consumption as required
            commands.consume(
                self._get_option_value("consume_packets", group, vertex))

            # Set the router timeout
            router_timeout = self._get_option_value("router_timeout", group)
            if router_timeout is not None and router_access_vertex:
                if isinstance(router_timeout, integer_types):
                    commands.router_timeout(router_timeout)
                else:
                    commands.router_timeout(*router_timeout)

            # warming up without recording data
            commands.record()
            commands.run(self._get_option_value("warmup", group))

            # Run the actual experiment and record results
            commands.record(*records)
            commands.run(self._get_option_value("duration", group))

            # Run without recording (briefly) after the experiment to allow
            # for clock skew between cores.
            commands.record()  # Record nothing during cooldown
            commands.run(self._get_option_value("cooldown", group))

            # Restore router timeout, turn consumption back on and reinjection
            # back off after the run
            commands.consume(True)
            if router_timeout is not None and router_access_vertex:
                commands.router_timeout_restore()
            if router_access_vertex:
                commands.reinject(False)

            # Drain the network of any remaining packets
            commands.sleep(self._get_option_value("flush_time", group))

        # Finally, terminate
        commands.exit()

        return commands

    def _add_router_recording_vertices(self):
        """Adds extra vertices to chips with no other vertices to facilitate
        recording or setting of router counters and registers, if necessary.

        Returns
        -------
        (vertices, router_access_vertices, placements, allocations, routes)
            vertices is a list containing all vertices (including any added for
            router-recording purposes).

            router_access_vertices is set of vertices which are responsible
            for recording router counters or setting router registers on their
            core.

            placements, allocations and routes are updated sets of placements
            accounting for any new router-recording vertices.
        """
        # Make a local list of vertices, placements and allocations in the
        # model. This may be extended with extra vertices for recording router
        # counter values.
        vertices = self._vertices[:]
        placements = self.placements.copy()
        allocations = self.allocations.copy()
        routes = self.routes.copy()  # Not actually modified at present

        router_access_vertices = set()

        # The set of chips (x, y) which have a core allocated to recording
        # router counters.
        recorded_chips = set()

        # If router information is being recorded or the router registers are
        # changed, a vertex must be assigned on every chip to access these
        # registers.
        if self._any_router_registers_used():
            # Assign the job of recording/setting router registers to an
            # arbitrary vertex on every chip which already has vertices on it.
            for vertex, placement in iteritems(self.placements):
                if placement not in recorded_chips:
                    router_access_vertices.add(vertex)
                    recorded_chips.add(placement)

            # If there are chips without any vertices allocated, new
            # router-access-only vertices must be added.
            num_extra_vertices = 0
            for xy in self.machine:
                if xy not in recorded_chips:
                    # Create a new vertex for recording of router data only.
                    num_extra_vertices += 1
                    vertex = Vertex(self, "router access {}, {}".format(*xy))
                    router_access_vertices.add(vertex)
                    recorded_chips.add(xy)
                    placements[vertex] = xy
                    allocations[vertex] = {Cores: slice(2, 3)}
                    vertices.append(vertex)

            logger.info(
                "{} vertices added to access router registers".format(
                    num_extra_vertices))

        return (vertices, router_access_vertices,
                placements, allocations, routes)

    def _get_vertex_record_lookup(self, vertices, router_access_vertices,
                                  placements,
                                  vertices_source_nets, vertices_sink_nets):
        """Generates a lookup from vertex to a list of counters that vertex
        records.

        Parameters
        ----------
        vertices : [:py:class:`.Vertex`, ...]
        router_access_vertices : set([:py:class:`.Vertex`, ...])
        placements : {:py:class:`.Vertex`: (x, y), ...}
        vertices_source_nets : {:py:class:`.Vertex`: [net, ...], ...}
        vertices_sink_nets : {:py:class:`.Vertex`: [net, ...], ...}

        Returns
        -------
        vertices_records : {vertex: [(object, counter), ...], ...}
            For each vertex, gives an ordered-list of the things recorded by
            that vertex.

            For router counters, object will be a tuple (x, y) indicating which
            chip that counter is responsible for.

            For non-router counters, object will be the Net associated with the
            counter.
        """
        # Get the set of recorded counters for each vertex
        # {vertex, [counter, ...]}
        vertices_records = {}
        for vertex in vertices:
            records = []

            # Add any router-counters if this vertex is recording them
            if vertex in router_access_vertices:
                xy = placements[vertex]
                for counter in Counters:
                    if ((counter.router_counter or
                         counter.reinjector_counter) and
                            self._get_option_value(
                                "record_{}".format(counter.name))):
                        records.append((xy, counter))

            # Add any source counters
            for counter in Counters:
                if (counter.source_counter and
                        self._get_option_value(
                            "record_{}".format(counter.name))):
                    for net in vertices_source_nets[vertex]:
                        records.append((net, counter))

            # Add any sink counters
            for counter in Counters:
                if (counter.sink_counter and
                        self._get_option_value(
                            "record_{}".format(counter.name))):
                    for net in vertices_sink_nets[vertex]:
                        records.append((net, counter))

            vertices_records[vertex] = records

        return vertices_records

    def _get_option_value(self, option, group=None, vert_or_net=None):
        """For internal use. Get an option's value for a given
        group/vertex/net."""

        values = self._values[option]
        if isinstance(values, dict):
            if isinstance(vert_or_net, Net):
                vertex = vert_or_net.source
                net = vert_or_net
            else:
                vertex = vert_or_net

            global_value = values[(None, None)]
            group_value = values.get((group, None), global_value)
            vertex_value = values.get((None, vertex), group_value)
            group_vertex_value = values.get((group, vertex), vertex_value)

            if isinstance(vert_or_net, Net):
                net_value = values.get((None, net), group_vertex_value)
                group_net_value = values.get((group, net), net_value)
                return group_net_value
            else:
                return group_vertex_value
        else:
            return values

    def _set_option_value(self, option, value, group=None, vert_or_net=None):
        """For internal use. Set an option's value for a given
        group/vertex/net.
        """
        values = self._values[option]
        if isinstance(values, dict):
            values[(group, vert_or_net)] = value
        else:
            if group is not None or vert_or_net is not None:
                raise ValueError(
                    "Cannot set {} option on a group-by-group, "
                    "vertex-by-vertex or net-by-net basis.".format(option))
            self._values[option] = value

    class _Option(object):
        """A descriptor which provides access to the _values dictionary."""

        def __init__(self, option):
            self.option = option

        def __get__(self, obj, type=None):
            return obj._get_option_value(self.option, obj._cur_group)

        def __set__(self, obj, value):
            return obj._set_option_value(self.option, value, obj._cur_group)

    seed = _Option("seed")

    timestep = _Option("timestep")

    warmup = _Option("warmup")
    duration = _Option("duration")
    cooldown = _Option("cooldown")
    flush_time = _Option("flush_time")

    record_local_multicast = _Option("record_local_multicast")
    record_external_multicast = _Option("record_external_multicast")
    record_local_p2p = _Option("record_local_p2p")
    record_external_p2p = _Option("record_external_p2p")
    record_local_nearest_neighbour = _Option("record_local_nearest_neighbour")
    record_external_nearest_neighbour = _Option(
        "record_external_nearest_neighbour")
    record_local_fixed_route = _Option("record_local_fixed_route")
    record_external_fixed_route = _Option("record_external_fixed_route")
    record_dropped_multicast = _Option("record_dropped_multicast")
    record_dropped_p2p = _Option("record_dropped_p2p")
    record_dropped_nearest_neighbour = _Option(
        "record_dropped_nearest_neighbour")
    record_dropped_fixed_route = _Option("record_dropped_fixed_route")
    record_counter12 = _Option("record_counter12")
    record_counter13 = _Option("record_counter13")
    record_counter14 = _Option("record_counter14")
    record_counter15 = _Option("record_counter15")

    record_reinjected = _Option("record_reinjected")
    record_reinject_overflow = _Option("record_reinject_overflow")
    record_reinject_missed = _Option("record_reinject_missed")

    record_sent = _Option("record_sent")
    record_blocked = _Option("record_blocked")
    record_received = _Option("record_received")

    record_interval = _Option("record_interval")

    burst_period = _Option("burst_period")
    burst_duty = _Option("burst_duty")
    burst_phase = _Option("burst_phase")

    probability = _Option("probability")

    use_payload = _Option("use_payload")

    consume_packets = _Option("consume_packets")

    router_timeout = _Option("router_timeout")

    reinject_packets = _Option("reinject_packets")
        RTE({Routes.north, Routes.north_east}, 0b1100, 0b1111),
        RTE({Routes.south, Routes.south_west}, 0b0100, 0b1111),
    ]

    # Talk to the machine
    mc = MachineController("192.168.1.1")
    with mc.application(57):
        # Write the table table into memory on chip (0, 0)
        print("Loading tables...")
        with mc(x=0, y=0):
            mem = mc.sdram_alloc_as_filelike(len(table) * 16 + 12, tag=1)
            mem.write(pack_table(table, 57))

        # Load the application
        print("Loading app...")
        mc.load_application("./rt_minimise.aplx", {(0, 0): {1}})

        # Wait until this does something interesting
        print("Minimising...")
        ready = mc.wait_for_cores_to_reach_state("exit", 1, timeout=5.0)
        if ready < 1:
            print(mc.get_iobuf(x=0, y=0, p=1))
            raise Exception("Something didn't work...")

    print("\nReading minimised table...")
    for e in mc.get_routing_table_entries(x=0, y=0):
        if e is not None:
            entry, app, _ = e
            print("{:d}: {:#010x}/{:#010x} --> {}".format(
                app, entry.key, entry.mask, entry.route))
Example #8
0
"""
A Rig-based program which boots a SpiNNaker machine and loads the "hello world"
SpiNNaker binary onto it.
"""

import sys

from rig.machine_control import MachineController

# Control the SpiNNaker machine whose hostname is given on the command line
mc = MachineController(sys.argv[1])

# To boot the machine, we take its network dimensions as command line
# arguments.
mc.boot(int(sys.argv[2]), int(sys.argv[3]))

# Load the hello world application onto core 1 of chip (0, 0).
mc.load_application("hello.aplx", {(0, 0): {1}})

# Wait for the application to finish
mc.wait_for_cores_to_reach_state("exit", 1)

# Print out the message printed by the application
print(mc.get_iobuf(x=0, y=0, p=1))

# Free up any SpiNNaker resources 
mc.send_signal("stop")
Example #9
0
 def simulate(self, hostname, sim_length=128):
     """Simulate the current circuit for the specified number of timer
     ticks.
     """
     # We define the set of ticks for convenience when plotting
     self.ticks = list(range(sim_length))
     
     # We define our simulation within the following "with" block which
     # causes the SpiNNaker applications and their associated resources to
     # be automatically freed at the end of simulation or in the event of
     # some failure.
     mc = MachineController(hostname)
     with mc.application():
         # Step 1: Determine what resources are available in the supplied
         # SpiNNaker machine.
         system_info = mc.get_system_info()
         
         # Step 2: Describe the simulation as a graph of SpiNNaker applications
         # which Rig will place in the machine
         
         # Each device uses a single core and consumes some amount of SDRAM for
         # config and result data.
         vertices_resources = {
             d: {Cores: 1, SDRAM: d.sdram_required(sim_length)}
             for d in self._devices
         }
         vertices_applications = {d: d.app_name for d in self._devices}
         
         # We'll make a net for every signal in our circuit. Packets will have
         # their bottom 31-bits be the unique signal ID and the top bit will
         # contain the state of the signal (and is thus masked off here)
         net_keys = {Net(s.source, s.sinks): (s.id, 0x7FFFFFFF)
                     for s in self._signals}
         nets = list(net_keys)
         
         # Step 3: Place and route the application graph we just described
         placements, allocations, application_map, routing_tables = \
             place_and_route_wrapper(vertices_resources, vertices_applications,
                                     nets, net_keys, system_info)
         
         # Step 4: Allocate SDRAM for each device. We use the
         # `sdram_alloc_for_vertices` utility method to allocate SDRAM on
         # the chip each device has been placed on, tagging the allocation
         # with the core number so the application can discover the
         # allocation using `sark_tag_ptr`. The returned file-like objects
         # may then conveniently be used to read/write to this allocated
         # region of SDRAM.
         # A dictionary {Device: filelike} is returned.
         device_sdram_filelikes = sdram_alloc_for_vertices(mc, placements, allocations)
         
         # Step 5: Write the config data to SDRAM for all devices.
         for d in self._devices:
             d.write_config(device_sdram_filelikes[d], sim_length)
         
         # Step 6: Load application binaries and routing tables
         mc.load_application(application_map)
         mc.load_routing_tables(routing_tables)
         
         # Step 7: Wait for all applications to reach the initial sync0
         # barrier and then start the simulation.
         mc.wait_for_cores_to_reach_state("sync0", len(self._devices))
         mc.send_signal("sync0")
         
         # Step 8: Wait for the simulation to run and all cores to finish
         # executing and enter the EXIT state.
         time.sleep(0.001 * sim_length)
         mc.wait_for_cores_to_reach_state("exit", len(self._devices))
         
         # Step 9: Retrieve any results and we're done!
         for d in self._devices:
             d.read_results(device_sdram_filelikes[d], sim_length)
class MainWindow(QtGui.QMainWindow, QtMainWindow.Ui_QtMainWindow):
    """ It inherits QMainWindow and uses pyuic4-generated python files from the .ui """
    pltDataRdy = pyqtSignal(list)  # for streaming data to the plotter/calibrator

    def __init__(self, mIP=None, logFName=None, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.setCentralWidget(self.mdiArea);
        self.statusTxt = QtGui.QLabel("")
        self.statusBar().addWidget(self.statusTxt)

        # load setting
        self.loadSettings()

        # if machine IP is provided, check if it is booted and/or if the profiler has been loaded
        if mIP is not None:
            self.mIP = mIP
            self.checkSpiNN4()
        else:
            self.mIP = None

        self.connect(self.actionShow_Chips, SIGNAL("triggered()"), SLOT("showChips()"))

        """
        Scenario: 
        - sw and pw send data to MainWindow
        - MainWindow do the averaging on sw data, then send avg_sw and pw to plotter
          At the same time, MainWindow store the data
        """

        #-------------------- GUI setup ---------------------               
        # Dump raw data in arduConsole widget (cw).
        self.cw = ifaceArduSpiNN(logFName,self)
        self.subWinConsole = QtGui.QMdiSubWindow(self)
        self.subWinConsole.setWidget(self.cw)
        self.mdiArea.addSubWindow(self.subWinConsole)
        self.subWinConsole.setGeometry(0,0,self.cw.width(),500)
        self.cw.show()

        # Power plot widget (pw).
        self.pw = Pwidget(self)
        self.subWinPW = QtGui.QMdiSubWindow(self)
        self.subWinPW.setWidget(self.pw)
        self.mdiArea.addSubWindow(self.subWinPW)
        self.subWinPW.setGeometry(self.cw.width()+10,0,760,500)
        self.pw.show()

        # SpiNNaker profiler plot widget (sw).
        self.sw = Swidget(self)
        self.subWinSW = QtGui.QMdiSubWindow(self)
        self.subWinSW.setWidget(self.sw)
        self.mdiArea.addSubWindow(self.subWinSW)
        self.subWinSW.setGeometry(self.subWinPW.x(), self.subWinPW.y()+self.subWinPW.height(),760,500)
        self.sw.show()

        # initially, we don't show chip visualizer
        self.vis = None

        # SIGNAL-SLOT connection
        self.cw.spinUpdate.connect(self.sw.readPltData)
        self.cw.arduUpdate.connect(self.pw.readPltData)
        # just for debugging:
        # self.cw.arduUpdate.connect(self.readArduData)
        # self.cw.spinUpdate.connect(self.readSpinData)

    def loadSettings(self):
        """
        Load configuration setting from file.
        Let's use INI format and UserScope
        :return:
        """
        #init value
        self.conf = config()

        #if used before, then load from previous one; otherwise, it use the initial value above
        self.settings = QSettings(QSettings.IniFormat, QSettings.UserScope, "APT", "SpiNN-4 Power Profiler")
        self.conf.xPos,ok = self.settings.value(self.conf.xPosKey, self.conf.xPos).toInt()
        self.conf.yPos,ok = self.settings.value(self.conf.yPosKey, self.conf.yPos).toInt()
        self.conf.width,ok = self.settings.value(self.conf.widthKey, self.conf.width).toInt()
        self.conf.height,ok = self.settings.value(self.conf.heightKey, self.conf.height).toInt()

        #print "isWritable?", self.settings.isWritable()
        #print "conf filename", self.settings.fileName()

        #then apply to self
        self.setGeometry(self.conf.xPos, self.conf.yPos, self.conf.width, self.conf.height)

    def checkSpiNN4(self, alwaysAsk=True):

        #return #go out immediately for experiment with Basab

        """
        if the MainWindow class is called with an IP, then check if the machine is ready
        """
        loadProfiler = False

        # first, check if the machine is booted
        print "Check the machine: ",
        self.mc = MachineController(self.mIP)
        bootByMe = self.mc.boot()
        # if bootByMe is true, then the machine is booted by readSpin4Pwr.py, otherwise it is aleady booted
        # if rig cannot boot the machine (eq. the machine is not connected or down), the you'll see error
        # message in the arduConsole
        if bootByMe is False:
            print "it is booted already!"
        else:
            print "it is now booted!"
            loadProfiler = True
            alwaysAsk = False       # because the machine is just booted, then force it load profiler

        # second, ask if profilers need to be loaded
        cpustat = self.mc.get_processor_status(1,0,0) #core-1 in chip <0,0>
        profName = cpustat.app_name
        profState = int(cpustat.cpu_state)
        profVersion = cpustat.user_vars[0] # read from sark.vcpu->user0
        #print "Profiler name: ", profName
        #print "Profiler state: ", profState
        #print "Profiler version: ", profVersion
        if profName.upper()==DEF.REQ_PROF_NAME.upper() and profState==7 and profVersion==DEF.REQ_PROF_VER:
            print "Required profiler.aplx is running!"
            loadProfiler = False
        else:
            if alwaysAsk:
                askQ = raw_input('Load the correct profiler.aplx? [Y/n]')
                if len(askQ) == 0 or askQ.upper() == 'Y':
                    loadProfiler = True
                else:
                    loadProfiler = False
                    print "[WARNING] profiler.aplx is not ready or invalid version"

            # third, load the profilers
            if loadProfiler:
                # then load the correct profiler version
                print "Loading profiler from", DEF.REQ_PROF_APLX
                # populate all chips in the board
                chips = self.mc.get_system_info().keys()
                dest = dict()
                for c in chips:
                    dest[c] = [1]   # the profiler.aplx goes to core-1
                self.mc.load_application(DEF.REQ_PROF_APLX, dest, app_id=DEF.REQ_PROF_APLX_ID)
                print "Profilers are sent to SpiNN4!"
            else:
                print "No valid profiler! This program might not work correctly!"

        # Last but important: MAKE SURE IPTAG 3 IS SET
        iptag = self.mc.iptag_get(DEF.REPORT_IPTAG,0,0)
        if iptag.addr is '0.0.0.0' or iptag.port is not DEF.REPORT_IPTAG:
            #iptag DEF.REPORT_IPTAG is not defined yet
            self.mc.iptag_set(DEF.REPORT_IPTAG, DEF.HOST_PC, DEF.RECV_PORT, 0, 0)

    @pyqtSlot()
    def reactiveShopCipMenu(self):
        self.actionShow_Chips.setEnabled(True)
        del self.subWinVis

    @pyqtSlot()
    def showChips(self):
        """
        Show chip layout
        :return: 
        """
        if self.mIP is None:
            """
            i.e., the IP is not defined when this menu is clicked
            """
            # first, ask the IP of the machine
            mIP, ok = QtGui.QInputDialog.getText(self, "SpiNN4 Location", "SpiNN4 IP address",
                                                 QtGui.QLineEdit.Normal, DEF.MACHINE)
            if ok is True:
                self.mIP = mIP
                self.checkSpiNN4(False)     # after this, self.mc is available

        # then open the widget
        mInfo = self.mc.get_system_info()
        w = mInfo.width
        h = mInfo.height
        chipList = mInfo.keys()
        #self.vis = visWidget(w, h, chipList) # Segmentation fault
        self.vis = visWidget(w, h, chipList, self)

        self.subWinVis = QtGui.QMdiSubWindow(self)
        self.subWinVis.setWidget(self.vis)
        self.mdiArea.addSubWindow(self.subWinVis)
        #self.subWinVis.setGeometry(self.subWinPW.x(), self.subWinPW.y()+self.subWinPW.height(),760,500)

        # connect to the source of temperature data
        # masih salah: self.cw.spinUpdate.connect(self.vis.readSpinData)

        self.vis.show()

        # and disable the menu item
        self.actionShow_Chips.setEnabled(False) # the menu will be reset to enable if the widget is closed
        self.vis.visWidgetTerminated.connect(self.reactiveShopCipMenu)

    """
    ######################### GUI callback ########################### 
    """

    # readSpinData and readArduData are just for debugging
    @pyqtSlot(list)
    def readSpinData(self, prfData):
        """
        Read profiler data and prepare for saving.
        prfData is a list of 48 "Integer" item that should be decoded as:
        freq, nActive, temp
        Hence, fmt = "<2BH"
        """
        #print len(prfData)
        #print type(prfData[0])
        #return

        fmt = "<2BH"
        #fmt = "<H2B"
        print "{",
        for i in range(len(prfData)):
            cpu = struct.pack("<I",prfData[i])
            #print "0x%x " % cpu,

            #f,nA,T = struct.unpack(fmt, prfData[i])
            f,nA,T = struct.unpack(fmt, cpu)
            #print "[{},{},{}]".format(f,nA,T),
            if i < (len(prfData)-1):
                print "[{},{},{}],".format(f, nA, T),
            else:
                print "[{},{},{}]".format(f, nA, T),

        print "}"

    @pyqtSlot(list)
    def readArduData(self, pwrData):
        """
        Read power data from Arduino and prepare for saving.
        """

    def closeEvent(self, event):

        #print "x, y, w, h =",self.x(),self.y(),self.width(),self.height()
        # save the current configuration
        self.settings = QSettings(QSettings.IniFormat, QSettings.UserScope, "APT", "SpiNN-4 Power Profiler")
        self.settings.setValue(self.conf.xPosKey, self.x())
        self.settings.setValue(self.conf.yPosKey, self.y())
        self.settings.setValue(self.conf.widthKey, self.width())
        self.settings.setValue(self.conf.heightKey, self.height())
        self.settings.sync()
        #print "Conf saved!"

        # Notify ifaceArduSpiNN to stop the thread:
        self.cw.stop() # to avoid QThread being destroyed while thread is still running
        event.accept()
Example #11
0
from rig.machine_control import MachineController

# Control the SpiNNaker machine whose hostname is given on the command line. We
# assume the machine has already been booted, e.g. with rig-boot.
mc = MachineController(sys.argv[1])

# Allocate space for the two 32-bit numbers to add together and the 32-bit
# result.
sdram_addr = mc.sdram_alloc(12, x=0, y=0, tag=1)

# Pick two random numbers to be added together and write them to SDRAM
num_a = random.getrandbits(30)
num_b = random.getrandbits(30)
data = struct.pack("<II", num_a, num_b)
mc.write(sdram_addr, data, x=0, y=0)

# Load the adder application onto core 1 of chip (0, 0).
mc.load_application("adder.aplx", {(0, 0): {1}})

# Wait for the application to finish
mc.wait_for_cores_to_reach_state("exit", 1)

# Read back the result and print it out
result_data = mc.read(sdram_addr + 8, 4, x=0, y=0)
result, = struct.unpack("<I", result_data)
print("{} + {} = {}".format(num_a, num_b, result))

# Free up any SpiNNaker resources 
mc.send_signal("stop")
        # Build the targets dictionary
        targets = {chip: {1} for chip in iterkeys(chip_mem)}

        # Load the data
        print("Loading data...")
        t = time.time()
        for chip, mem in iteritems(chip_mem):
            mem.write(chip_data[chip])
        load_time = time.time() - t
        print("... took {:.3f} s".format(load_time))

        # Load the application
        print("Loading application...")
        if args.memory_profile is None:
            mc.load_application("./ordered_covering.aplx", targets)
        else:
            mc.load_application("./ordered_covering_profiled.aplx", targets)
        t = time.time()

        # Wait until this does something interesting
        print("Minimising...")
        ready = mc.wait_for_cores_to_reach_state("exit", len(uncompressed),
                                                 timeout=60.0)
        if ready < len(uncompressed):
            raise Exception("Something didn't work...")
        run_time = time.time() - t
        print("... took ~{:.3f} s".format(run_time))

        # Read back the routing tables
        print("Reading back results...")
        RTE({Routes.south, Routes.south_west}, 0b0100, 0b1111),
    ]

    # Talk to the machine
    mc = MachineController("192.168.1.1")
    mc.send_signal("stop")

    # Write the table table into memory on chip (0, 0)
    print("Loading tables...")
    with mc(x=0, y=0):
        mem = mc.sdram_alloc_as_filelike(len(table)*16 + 8, tag=1)
        mem.write(pack_table(table, 0))

    # Load the application
    print("Loading app...")
    mc.load_application("./ordered_covering_profiled.aplx", {(0, 0): {1}})

    # Wait until this does something interesting
    print("Minimising...")
    ready = mc.wait_for_cores_to_reach_state("exit", 1, timeout=5.0)
    if ready < 1:
        raise Exception("Something didn't work...")

    # Read back the table
    print("Reading back table...")
    mem.seek(0)
    new_table = unpack_table(mem.read())

    print("\n---")
    for entry in new_table:
        print("{!s}".format(entry))