Пример #1
0
    def __init__(self, MACHINE_IP, parent=None):
        super(mainWidget, self).__init__(parent)
        self.setGeometry(0, 0, 640, 480)
        self.setWindowTitle("SpiNNaker Chips Visualizer")

        # get info from rig:
        mc = MachineController(MACHINE_IP)
        mc.boot()
        mInfo = mc.get_system_info()
        w = mInfo.width
        h = mInfo.height
        chipList = mInfo.keys()
        self.vis = visWidget(w, h, chipList, self)
        self.vis.setGeometry(0, 0, self.width(), self.height())
Пример #2
0
def run_job(job_args, job_kwargs, ip_file_filename):
    # Reason for destroying the job
    reason = None

    # Create the job
    try:
        job = Job(*job_args, **job_kwargs)
    except (OSError, IOError, ProtocolError, ProtocolTimeoutError) as e:
        info(t.red("Could not connect to server: {}".format(e)))
        return 6

    try:
        # Wait for it to become ready, keeping the user informed along the
        # way
        code, reason = wait_for_job_ready(job)
        if code != 0:
            return code

        # Machine is now ready
        write_ips_to_csv(job.connections, ip_file_filename)

        # Boot the machine if required
        if MachineController is not None and args.boot:
            update("Job {}: Booting...", t.yellow, job.id)
            mc = MachineController(job.hostname)
            mc.boot(job.width, job.height)

        update("Job {}: Ready!", t.green, job.id)

        # Either run the user's application or just print the details.
        if not args.command:
            print_info(job.machine_name, job.connections,
                       job.width, job.height, ip_file_filename)
            return 0
        return run_command(args.command, job.id, job.machine_name,
                           job.connections, job.width, job.height,
                           ip_file_filename)
    finally:
        # Destroy job and disconnect client
        if args.no_destroy:
            job.close()
        else:
            job.destroy(reason)
Пример #3
0
def main(args=None):
    parser = argparse.ArgumentParser(description="Boot a SpiNNaker board")
    parser.add_argument("--version",
                        "-V",
                        action="version",
                        version="%(prog)s {}".format(rig.__version__))

    parser.add_argument("hostname",
                        type=str,
                        help="hostname or IP of SpiNNaker system")

    # Automatically build a list of available machine parameters by inspecting
    # boot module.
    type_group = parser.add_mutually_exclusive_group()
    for dict_name in dir(boot):
        if dict_name.endswith(BOOT_OPTION_POSTFIX):
            type_name = dict_name[:-len(BOOT_OPTION_POSTFIX)]
            option_name = "--{}".format(type_name)
            option_dict = getattr(boot, dict_name)
            option_help = "use predefined boot options for a {} board".format(
                type_name)
            type_group.add_argument(option_name,
                                    action="store_const",
                                    const=option_dict,
                                    default={},
                                    dest="board_options",
                                    help=option_help)

    args = parser.parse_args(args)

    # Attempt to boot the machine
    mc = MachineController(args.hostname)
    try:
        if mc.boot(**args.board_options):
            return 0
        else:
            # The machine was already booted.
            sys.stderr.write("{}: error: machine already booted.\n".format(
                parser.prog))
            return 1
    except SpiNNakerBootError as e:
        # The machine could not be booted for some reason; show an appropriate
        # message
        sys.stderr.write("{}: error: {}\n".format(parser.prog, str(e)))
        return 2
Пример #4
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
Пример #5
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)!")
    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)
Пример #7
0
class Simulator(object):
    """SpiNNaker simulator for Nengo models.

    The simulator period determines how much data will be stored on SpiNNaker
    and is the maximum length of simulation allowed before data is transferred
    between the machine and the host PC. If the period is set to `None`
    function of time Nodes will not be optimised and probes will be disabled.
    For any other value simulation lengths of less than or equal to the period
    will be in real-time, longer simulations will be possible but will include
    short gaps when data is transferred between SpiNNaker and the host.

    :py:meth:`~.close` should be called when the simulator will no longer be
    used. This will close all sockets used to communicate with the SpiNNaker
    machine and will leave the machine in a clean state. Failure to call
    `close` may result in later failures. Alternatively `with` may be used::

        sim = nengo_spinnaker.Simulator(network)
        with sim:
            sim.run(10.0)
    """
    _open_simulators = set()

    @classmethod
    def _add_simulator(cls, simulator):
        cls._open_simulators.add(simulator)

    @classmethod
    def _remove_simulator(cls, simulator):
        cls._open_simulators.remove(simulator)

    def __init__(self,
                 network,
                 dt=0.001,
                 period=10.0,
                 timescale=1.0,
                 hostname=None,
                 use_spalloc=None,
                 allocation_fudge_factor=0.6):
        """Create a new Simulator with the given network.

        Parameters
        ----------
        period : float or None
            Duration of one period of the simulator. This determines how much
            memory will be allocated to store precomputed and probed data.
        timescale : float
            Scaling factor to apply to the simulation, e.g., a value of `0.5`
            will cause the simulation to run at half real-time.
        hostname : string or None
            Hostname of the SpiNNaker machine to use; if None then the machine
            specified in the config file will be used.
        use_spalloc : bool or None
            Allocate a SpiNNaker machine for the simulator using ``spalloc``.
            If None then the setting specified in the config file will be used.

        Other Parameters
        ----------------
        allocation_fudge_factor:
           Fudge factor to allocate more cores than really necessary when using
           `spalloc` to ensure that (a) there are sufficient "live" cores in
           the allocated machine, (b) there is sufficient room for a good place
           and route solution. This should generally be more than 0.1 (10% more
           cores than necessary) to account for the usual rate of missing
           chips.
        """
        # Add this simulator to the set of open simulators
        Simulator._add_simulator(self)

        # Create the IO controller
        io_cls = getconfig(network.config, Simulator, "node_io", Ethernet)
        io_kwargs = getconfig(network.config, Simulator, "node_io_kwargs",
                              dict())
        self.io_controller = io_cls(**io_kwargs)

        # Calculate the machine timestep, this is measured in microseconds
        # (hence the 1e6 scaling factor).
        self.timescale = timescale
        machine_timestep = int((dt / timescale) * 1e6)

        # Determine the maximum run-time
        self.max_steps = None if period is None else int(period / dt)

        self.steps = 0  # Steps simulated

        # If the simulator is in "run indefinite" mode (i.e., max_steps=None)
        # then we modify the builders to ignore function of time Nodes and
        # probes.
        builder_kwargs = self.io_controller.builder_kwargs
        if self.max_steps is None:
            raise NotImplementedError

        # Create a model from the network, using the IO controller
        logger.debug("Building model")
        start_build = time.time()
        self.model = Model(dt=dt,
                           machine_timestep=machine_timestep,
                           decoder_cache=get_default_decoder_cache())
        self.model.build(network, **builder_kwargs)

        logger.info("Build took {:.3f} seconds".format(time.time() -
                                                       start_build))

        self.model.decoder_cache.shrink()
        self.dt = self.model.dt
        self._closed = False  # Whether the simulator has been closed or not

        self.host_sim = self._create_host_sim()

        # Holder for probe data
        self.data = {}

        # Holder for profiling data
        self.profiler_data = {}

        # Convert the model into a netlist
        logger.info("Building netlist")
        start = time.time()
        self.netlist = self.model.make_netlist(self.max_steps or 0)

        # Determine whether to use a spalloc machine or not
        if use_spalloc is None:
            # Default is to not use spalloc; this is indicated by either the
            # absence of the option in the config file OR the option being set
            # to false.
            use_spalloc = (rc.has_option("spinnaker_machine", "use_spalloc")
                           and rc.getboolean("spinnaker_machine",
                                             "use_spalloc"))

        # Create a controller for the machine and boot if necessary
        self.job = None
        if not use_spalloc or hostname is not None:
            # Use the specified machine rather than trying to get one
            # allocated.
            if hostname is None:
                hostname = rc.get("spinnaker_machine", "hostname")
        else:
            # Attempt to get a machine allocated to us
            from spalloc import Job

            # Determine how many boards to ask for (assuming 16 usable cores
            # per chip and 48 chips per board).
            n_cores = self.netlist.n_cores * (1.0 + allocation_fudge_factor)
            n_boards = int(np.ceil((n_cores / 16.) / 48.))

            # Request the job
            self.job = Job(n_boards)
            logger.info("Allocated job ID %d...", self.job.id)

            # Wait until we're given the machine
            logger.info("Waiting for machine allocation...")
            self.job.wait_until_ready()

            # spalloc recommends a slight delay before attempting to boot the
            # machine, later versions of spalloc server may relax this
            # requirement.
            time.sleep(5.0)

            # Store the hostname
            hostname = self.job.hostname
            logger.info("Using %d board(s) of \"%s\" (%s)",
                        len(self.job.boards), self.job.machine_name, hostname)

        self.controller = MachineController(hostname)
        self.controller.boot()

        # Get a system-info object to place & route against
        logger.info("Getting SpiNNaker machine specification")
        system_info = self.controller.get_system_info()

        # Place & Route
        logger.info("Placing and routing")
        self.netlist.place_and_route(
            system_info,
            place=getconfig(network.config, Simulator, 'placer',
                            rig.place_and_route.place),
            place_kwargs=getconfig(network.config, Simulator, 'placer_kwargs',
                                   {}),
        )

        logger.info("{} cores in use".format(len(self.netlist.placements)))
        chips = set(six.itervalues(self.netlist.placements))
        logger.info("Using {}".format(chips))

        # Prepare the simulator against the placed, allocated and routed
        # netlist.
        self.io_controller.prepare(self.model, self.controller, self.netlist)

        # Load the application
        logger.info("Loading application")
        self.netlist.load_application(self.controller, system_info)

        # Check if any cores are in bad states
        if self.controller.count_cores_in_state(
            ["exit", "dead", "watchdog", "runtime_exception"]):
            for vertex, (x, y) in six.iteritems(self.netlist.placements):
                p = self.netlist.allocations[vertex][Cores].start
                status = self.controller.get_processor_status(p, x, y)
                if status.cpu_state is not AppState.sync0:
                    print("Core ({}, {}, {}) in state {!s}".format(
                        x, y, p, status))
                    print(self.controller.get_iobuf(p, x, y))
            raise Exception("Unexpected core failures.")

        logger.info("Preparing and loading machine took {:3f} seconds".format(
            time.time() - start))

        logger.info("Setting router timeout to 16 cycles")
        for x, y in system_info.chips():
            with self.controller(x=x, y=y):
                data = self.controller.read(0xf1000000, 4)
                self.controller.write(0xf1000000, data[:-1] + b'\x10')

    def __enter__(self):
        """Enter a context which will close the simulator when exited."""
        # Return self to allow usage like:
        #
        #     with nengo_spinnaker.Simulator(model) as sim:
        #         sim.run(1.0)
        return self

    def __exit__(self, exception_type, exception_value, traceback):
        """Exit a context and close the simulator."""
        self.close()

    def run(self, time_in_seconds):
        """Simulate for the given length of time."""
        # Determine how many steps to simulate for
        steps = int(np.round(float(time_in_seconds) / self.dt))
        self.run_steps(steps)

    def run_steps(self, steps):
        """Simulate a give number of steps."""
        while steps > 0:
            n_steps = min((steps, self.max_steps))
            self._run_steps(n_steps)
            steps -= n_steps

    def _run_steps(self, steps):
        """Simulate for the given number of steps."""
        if self._closed:
            raise Exception("Simulator has been closed and can't be used to "
                            "run further simulations.")

        if steps is None:
            if self.max_steps is not None:
                raise Exception(
                    "Cannot run indefinitely if a simulator period was "
                    "specified. Create a new simulator with Simulator(model, "
                    "period=None) to perform indefinite time simulations.")
        else:
            assert steps <= self.max_steps

        # Prepare the simulation
        self.netlist.before_simulation(self, steps)

        # Wait for all cores to hit SYNC0 (either by remaining it or entering
        # it from init)
        self._wait_for_transition(AppState.init, AppState.sync0,
                                  self.netlist.n_cores)
        self.controller.send_signal("sync0")

        # Get a new thread for the IO
        io_thread = self.io_controller.spawn()

        # Run the simulation
        try:
            # Prep
            exp_time = steps * self.dt / self.timescale
            io_thread.start()

            # Wait for all cores to hit SYNC1
            self._wait_for_transition(AppState.sync0, AppState.sync1,
                                      self.netlist.n_cores)
            logger.info("Running simulation...")
            self.controller.send_signal("sync1")

            # Execute the local model
            host_steps = 0
            start_time = time.time()
            run_time = 0.0
            local_timestep = self.dt / self.timescale
            while run_time < exp_time:
                # Run a step
                self.host_sim.step()
                run_time = time.time() - start_time

                # If that step took less than timestep then spin
                time.sleep(0.0001)
                while run_time < host_steps * local_timestep:
                    time.sleep(0.0001)
                    run_time = time.time() - start_time
        finally:
            # Stop the IO thread whatever occurs
            io_thread.stop()

        # Wait for cores to re-enter sync0
        self._wait_for_transition(AppState.run, AppState.sync0,
                                  self.netlist.n_cores)

        # Retrieve simulation data
        start = time.time()
        logger.info("Retrieving simulation data")
        self.netlist.after_simulation(self, steps)
        logger.info("Retrieving data took {:3f} seconds".format(time.time() -
                                                                start))

        # Increase the steps count
        self.steps += steps

    def _wait_for_transition(self, from_state, desired_to_state, num_verts):
        while True:
            # If no cores are still in from_state, stop
            if self.controller.count_cores_in_state(from_state) == 0:
                break

            # Wait a bit
            time.sleep(1.0)

        # Check if any cores haven't exited cleanly
        num_ready = self.controller.wait_for_cores_to_reach_state(
            desired_to_state, num_verts, timeout=5.0)

        if num_ready != num_verts:
            # Loop through all placed vertices
            for vertex, (x, y) in six.iteritems(self.netlist.placements):
                p = self.netlist.allocations[vertex][Cores].start
                status = self.controller.get_processor_status(p, x, y)
                if status.cpu_state is not desired_to_state:
                    print("Core ({}, {}, {}) in state {!s}".format(
                        x, y, p, status.cpu_state))
                    print(self.controller.get_iobuf(p, x, y))

            raise Exception("Unexpected core failures before reaching %s "
                            "state." % desired_to_state)

    def _create_host_sim(self):
        # change node_functions to reflect time
        # TODO: improve the reference simulator so that this is not needed
        #       by adding a realtime option
        node_functions = {}
        node_info = dict(start=None)
        for node in self.io_controller.host_network.all_nodes:
            if callable(node.output):
                old_func = node.output
                if node.size_in == 0:

                    def func(t, f=old_func):
                        now = time.time()
                        if node_info['start'] is None:
                            node_info['start'] = now

                        t = (now - node_info['start']) * self.timescale
                        return f(t)
                else:

                    def func(t, x, f=old_func):
                        now = time.time()
                        if node_info['start'] is None:
                            node_info['start'] = now

                        t = (now - node_info['start']) * self.timescale
                        return f(t, x)

                node.output = func
                node_functions[node] = old_func

        # Build the host simulator
        host_sim = nengo.Simulator(self.io_controller.host_network, dt=self.dt)
        # reset node functions
        for node, func in node_functions.items():
            node.output = func

        return host_sim

    def close(self):
        """Clean the SpiNNaker board and prevent further simulation."""
        if not self._closed:
            # Stop the application
            self._closed = True
            self.io_controller.close()
            self.controller.send_signal("stop")

            # Destroy the job if we allocated one
            if self.job is not None:
                self.job.destroy()

            # Remove this simulator from the list of open simulators
            Simulator._remove_simulator(self)

    def trange(self, dt=None):
        return np.arange(1, self.steps + 1) * (self.dt or dt)
Пример #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")
Пример #9
0
class Simulator(object):
    """SpiNNaker simulator for Nengo models.

    The simulator period determines how much data will be stored on SpiNNaker
    and is the maximum length of simulation allowed before data is transferred
    between the machine and the host PC. If the period is set to `None`
    function of time Nodes will not be optimised and probes will be disabled.
    For any other value simulation lengths of less than or equal to the period
    will be in real-time, longer simulations will be possible but will include
    short gaps when data is transferred between SpiNNaker and the host.

    :py:meth:`~.close` should be called when the simulator will no longer be
    used. This will close all sockets used to communicate with the SpiNNaker
    machine and will leave the machine in a clean state. Failure to call
    `close` may result in later failures. Alternatively `with` may be used::

        sim = nengo_spinnaker.Simulator(network)
        with sim:
            sim.run(10.0)
    """
    _open_simulators = set()

    @classmethod
    def _add_simulator(cls, simulator):
        cls._open_simulators.add(simulator)

    @classmethod
    def _remove_simulator(cls, simulator):
        cls._open_simulators.remove(simulator)

    def __init__(self, network, dt=0.001, period=10.0, timescale=1.0,
                 hostname=None, use_spalloc=None,
                 allocation_fudge_factor=0.6):
        """Create a new Simulator with the given network.

        Parameters
        ----------
        period : float or None
            Duration of one period of the simulator. This determines how much
            memory will be allocated to store precomputed and probed data.
        timescale : float
            Scaling factor to apply to the simulation, e.g., a value of `0.5`
            will cause the simulation to run at half real-time.
        hostname : string or None
            Hostname of the SpiNNaker machine to use; if None then the machine
            specified in the config file will be used.
        use_spalloc : bool or None
            Allocate a SpiNNaker machine for the simulator using ``spalloc``.
            If None then the setting specified in the config file will be used.

        Other Parameters
        ----------------
        allocation_fudge_factor:
           Fudge factor to allocate more cores than really necessary when using
           `spalloc` to ensure that (a) there are sufficient "live" cores in
           the allocated machine, (b) there is sufficient room for a good place
           and route solution. This should generally be more than 0.1 (10% more
           cores than necessary) to account for the usual rate of missing
           chips.
        """
        # Add this simulator to the set of open simulators
        Simulator._add_simulator(self)

        # Create the IO controller
        io_cls = getconfig(network.config, Simulator, "node_io", Ethernet)
        io_kwargs = getconfig(network.config, Simulator, "node_io_kwargs",
                              dict())
        self.io_controller = io_cls(**io_kwargs)

        # Calculate the machine timestep, this is measured in microseconds
        # (hence the 1e6 scaling factor).
        self.timescale = timescale
        machine_timestep = int((dt / timescale) * 1e6)

        # Determine the maximum run-time
        self.max_steps = None if period is None else int(period / dt)

        self.steps = 0  # Steps simulated

        # If the simulator is in "run indefinite" mode (i.e., max_steps=None)
        # then we modify the builders to ignore function of time Nodes and
        # probes.
        builder_kwargs = self.io_controller.builder_kwargs
        if self.max_steps is None:
            raise NotImplementedError

        # Create a model from the network, using the IO controller
        logger.debug("Building model")
        start_build = time.time()
        self.model = Model(dt=dt, machine_timestep=machine_timestep,
                           decoder_cache=get_default_decoder_cache())
        self.model.build(network, **builder_kwargs)

        logger.info("Build took {:.3f} seconds".format(time.time() -
                                                       start_build))

        self.model.decoder_cache.shrink()
        self.dt = self.model.dt
        self._closed = False  # Whether the simulator has been closed or not

        self.host_sim = self._create_host_sim()

        # Holder for probe data
        self.data = {}

        # Holder for profiling data
        self.profiler_data = {}

        # Convert the model into a netlist
        logger.info("Building netlist")
        start = time.time()
        self.netlist = self.model.make_netlist(self.max_steps or 0)

        # Determine whether to use a spalloc machine or not
        if use_spalloc is None:
            # Default is to not use spalloc; this is indicated by either the
            # absence of the option in the config file OR the option being set
            # to false.
            use_spalloc = (
                rc.has_option("spinnaker_machine", "use_spalloc") and
                rc.getboolean("spinnaker_machine", "use_spalloc"))

        # Create a controller for the machine and boot if necessary
        self.job = None
        if not use_spalloc or hostname is not None:
            # Use the specified machine rather than trying to get one
            # allocated.
            if hostname is None:
                hostname = rc.get("spinnaker_machine", "hostname")
        else:
            # Attempt to get a machine allocated to us
            from spalloc import Job

            # Determine how many boards to ask for (assuming 16 usable cores
            # per chip and 48 chips per board).
            n_cores = self.netlist.n_cores * (1.0 + allocation_fudge_factor)
            n_boards = int(np.ceil((n_cores / 16.) / 48.))

            # Request the job
            self.job = Job(n_boards)
            logger.info("Allocated job ID %d...", self.job.id)

            # Wait until we're given the machine
            logger.info("Waiting for machine allocation...")
            self.job.wait_until_ready()

            # spalloc recommends a slight delay before attempting to boot the
            # machine, later versions of spalloc server may relax this
            # requirement.
            time.sleep(5.0)

            # Store the hostname
            hostname = self.job.hostname
            logger.info("Using %d board(s) of \"%s\" (%s)",
                        len(self.job.boards), self.job.machine_name, hostname)

        self.controller = MachineController(hostname)
        self.controller.boot()

        # Get a system-info object to place & route against
        logger.info("Getting SpiNNaker machine specification")
        system_info = self.controller.get_system_info()

        # Place & Route
        logger.info("Placing and routing")
        self.netlist.place_and_route(
            system_info,
            place=getconfig(network.config, Simulator,
                            'placer', rig.place_and_route.place),
            place_kwargs=getconfig(network.config, Simulator,
                                   'placer_kwargs', {}),
        )

        logger.info("{} cores in use".format(len(self.netlist.placements)))
        chips = set(six.itervalues(self.netlist.placements))
        logger.info("Using {}".format(chips))

        # Prepare the simulator against the placed, allocated and routed
        # netlist.
        self.io_controller.prepare(self.model, self.controller, self.netlist)

        # Load the application
        logger.info("Loading application")
        self.netlist.load_application(self.controller, system_info)

        # Check if any cores are in bad states
        if self.controller.count_cores_in_state(["exit", "dead", "watchdog",
                                                 "runtime_exception"]):
            for vertex, (x, y) in six.iteritems(self.netlist.placements):
                p = self.netlist.allocations[vertex][Cores].start
                status = self.controller.get_processor_status(p, x, y)
                if status.cpu_state is not AppState.sync0:
                    print("Core ({}, {}, {}) in state {!s}".format(
                        x, y, p, status))
                    print(self.controller.get_iobuf(p, x, y))
            raise Exception("Unexpected core failures.")

        logger.info("Preparing and loading machine took {:3f} seconds".format(
            time.time() - start
        ))

        logger.info("Setting router timeout to 16 cycles")
        for x, y in system_info.chips():
            with self.controller(x=x, y=y):
                data = self.controller.read(0xf1000000, 4)
                self.controller.write(0xf1000000, data[:-1] + b'\x10')

    def __enter__(self):
        """Enter a context which will close the simulator when exited."""
        # Return self to allow usage like:
        #
        #     with nengo_spinnaker.Simulator(model) as sim:
        #         sim.run(1.0)
        return self

    def __exit__(self, exception_type, exception_value, traceback):
        """Exit a context and close the simulator."""
        self.close()

    def run(self, time_in_seconds):
        """Simulate for the given length of time."""
        # Determine how many steps to simulate for
        steps = int(np.round(float(time_in_seconds) / self.dt))
        self.run_steps(steps)

    def run_steps(self, steps):
        """Simulate a give number of steps."""
        while steps > 0:
            n_steps = min((steps, self.max_steps))
            self._run_steps(n_steps)
            steps -= n_steps

    def _run_steps(self, steps):
        """Simulate for the given number of steps."""
        if self._closed:
            raise Exception("Simulator has been closed and can't be used to "
                            "run further simulations.")

        if steps is None:
            if self.max_steps is not None:
                raise Exception(
                    "Cannot run indefinitely if a simulator period was "
                    "specified. Create a new simulator with Simulator(model, "
                    "period=None) to perform indefinite time simulations."
                )
        else:
            assert steps <= self.max_steps

        # Prepare the simulation
        self.netlist.before_simulation(self, steps)

        # Wait for all cores to hit SYNC0 (either by remaining it or entering
        # it from init)
        self._wait_for_transition(AppState.init, AppState.sync0,
                                  self.netlist.n_cores)
        self.controller.send_signal("sync0")

        # Get a new thread for the IO
        io_thread = self.io_controller.spawn()

        # Run the simulation
        try:
            # Prep
            exp_time = steps * self.dt / self.timescale
            io_thread.start()

            # Wait for all cores to hit SYNC1
            self._wait_for_transition(AppState.sync0, AppState.sync1,
                                      self.netlist.n_cores)
            logger.info("Running simulation...")
            self.controller.send_signal("sync1")

            # Execute the local model
            host_steps = 0
            start_time = time.time()
            run_time = 0.0
            local_timestep = self.dt / self.timescale
            while run_time < exp_time:
                # Run a step
                self.host_sim.step()
                run_time = time.time() - start_time

                # If that step took less than timestep then spin
                time.sleep(0.0001)
                while run_time < host_steps * local_timestep:
                    time.sleep(0.0001)
                    run_time = time.time() - start_time
        finally:
            # Stop the IO thread whatever occurs
            io_thread.stop()

        # Wait for cores to re-enter sync0
        self._wait_for_transition(AppState.run, AppState.sync0,
                                  self.netlist.n_cores)

        # Retrieve simulation data
        start = time.time()
        logger.info("Retrieving simulation data")
        self.netlist.after_simulation(self, steps)
        logger.info("Retrieving data took {:3f} seconds".format(
            time.time() - start
        ))

        # Increase the steps count
        self.steps += steps

    def _wait_for_transition(self, from_state, desired_to_state, num_verts):
        while True:
            # If no cores are still in from_state, stop
            if self.controller.count_cores_in_state(from_state) == 0:
                break

            # Wait a bit
            time.sleep(1.0)

        # Check if any cores haven't exited cleanly
        num_ready = self.controller.wait_for_cores_to_reach_state(
            desired_to_state, num_verts, timeout=5.0)

        if num_ready != num_verts:
            # Loop through all placed vertices
            for vertex, (x, y) in six.iteritems(self.netlist.placements):
                p = self.netlist.allocations[vertex][Cores].start
                status = self.controller.get_processor_status(p, x, y)
                if status.cpu_state is not desired_to_state:
                    print("Core ({}, {}, {}) in state {!s}".format(
                        x, y, p, status.cpu_state))
                    print(self.controller.get_iobuf(p, x, y))

            raise Exception("Unexpected core failures before reaching %s "
                            "state." % desired_to_state)

    def _create_host_sim(self):
        # change node_functions to reflect time
        # TODO: improve the reference simulator so that this is not needed
        #       by adding a realtime option
        node_functions = {}
        node_info = dict(start=None)
        for node in self.io_controller.host_network.all_nodes:
            if callable(node.output):
                old_func = node.output
                if node.size_in == 0:
                    def func(t, f=old_func):
                        now = time.time()
                        if node_info['start'] is None:
                            node_info['start'] = now

                        t = (now - node_info['start']) * self.timescale
                        return f(t)
                else:
                    def func(t, x, f=old_func):
                        now = time.time()
                        if node_info['start'] is None:
                            node_info['start'] = now

                        t = (now - node_info['start']) * self.timescale
                        return f(t, x)
                node.output = func
                node_functions[node] = old_func

        # Build the host simulator
        host_sim = nengo.Simulator(self.io_controller.host_network,
                                   dt=self.dt)
        # reset node functions
        for node, func in node_functions.items():
            node.output = func

        return host_sim

    def close(self):
        """Clean the SpiNNaker board and prevent further simulation."""
        if not self._closed:
            # Stop the application
            self._closed = True
            self.io_controller.close()
            self.controller.send_signal("stop")

            # Destroy the job if we allocated one
            if self.job is not None:
                self.job.destroy()

            # Remove this simulator from the list of open simulators
            Simulator._remove_simulator(self)

    def trange(self, dt=None):
        return np.arange(1, self.steps + 1) * (self.dt or dt)
Пример #10
0
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()
Пример #11
0
    parser.add_argument("target_length", type=int, default=0, nargs='?')
    parser.add_argument("--memory-profile", type=str)
    args = parser.parse_args()

    # Load and minimise all routing tables
    print("Reading routing tables...")
    with open(args.routing_table, "rb") as f:
        uncompressed = common.read_routing_tables(f)

    # Request a SpiNNaker machine
    print("Waiting for SpiNNaker machine...")
    with spalloc.Job(args.width, args.height) as job:
        # Talk to the machine
        print("Booting...")
        mc = MachineController(job.hostname)
        mc.boot()
        mc.discover_connections()

        # Convert the tables into the appropriate formats
        chip_data = {chip: pack_table(table, args.target_length) for
                     chip, table in iteritems(uncompressed)}

        # Allocate memory on the machine
        chip_mem = {
            (x, y): mc.sdram_alloc_as_filelike(len(data), x=x, y=y, tag=1) for
            (x, y), data in iteritems(chip_data)
        }

        # Build the targets dictionary
        targets = {chip: {1} for chip in iterkeys(chip_mem)}
Пример #12
0
def main(argv=None):
    t = Terminal(stream=sys.stderr)

    cfg = config.read_config()

    parser = argparse.ArgumentParser(
        description="Request (and allocate) a SpiNNaker machine.")

    parser.add_argument("--version",
                        "-V",
                        action="version",
                        version=__version__)

    parser.add_argument("--quiet",
                        "-q",
                        action="store_true",
                        default=False,
                        help="suppress informational messages")
    parser.add_argument("--debug",
                        action="store_true",
                        default=False,
                        help="enable additional diagnostic information")
    parser.add_argument("--no-destroy",
                        "-D",
                        action="store_true",
                        default=False,
                        help="do not destroy the job on exit")

    if MachineController is not None:
        parser.add_argument("--boot",
                            "-B",
                            action="store_true",
                            default=False,
                            help="boot the machine once powered on")

    allocation_args = parser.add_argument_group(
        "allocation requirement arguments")
    allocation_args.add_argument("what",
                                 nargs="*",
                                 default=[],
                                 type=int,
                                 metavar="WHAT",
                                 help="what to allocate: nothing or 1 "
                                 "requests 1 SpiNN-5 board, NUM requests "
                                 "at least NUM SpiNN-5 boards, WIDTH "
                                 "HEIGHT means WIDTHxHEIGHT triads of "
                                 "SpiNN-5 boards and X Y Z requests a "
                                 "board the specified logical board "
                                 "coordinate.")
    allocation_args.add_argument("--resume",
                                 "-r",
                                 type=int,
                                 help="if given, resume keeping the "
                                 "specified job alive rather than "
                                 "creating a new job (all allocation "
                                 "requirements will be ignored)")
    allocation_args.add_argument("--machine",
                                 "-m",
                                 nargs="?",
                                 default=cfg["machine"],
                                 help="only allocate boards which are part "
                                 "of a specific machine, or any machine "
                                 "if no machine is given "
                                 "(default: %(default)s)")
    allocation_args.add_argument("--tags",
                                 "-t",
                                 nargs="*",
                                 metavar="TAG",
                                 default=cfg["tags"] or ["default"],
                                 help="only allocate boards which have (at "
                                 "least) the specified flags "
                                 "(default: {})".format(" ".join(cfg["tags"]
                                                                 or [])))
    allocation_args.add_argument("--min-ratio",
                                 type=float,
                                 metavar="RATIO",
                                 default=cfg["min_ratio"],
                                 help="when allocating by number of boards, "
                                 "require that the allocation be at "
                                 "least as square as this ratio "
                                 "(default: %(default)s)")
    allocation_args.add_argument("--max-dead-boards",
                                 type=int,
                                 metavar="NUM",
                                 default=(-1 if cfg["max_dead_boards"] is None
                                          else cfg["max_dead_boards"]),
                                 help="boards allowed to be "
                                 "dead in the allocation, or -1 to allow "
                                 "any number of dead boards "
                                 "(default: %(default)s)")
    allocation_args.add_argument("--max-dead-links",
                                 type=int,
                                 metavar="NUM",
                                 default=(-1 if cfg["max_dead_links"] is None
                                          else cfg["max_dead_links"]),
                                 help="inter-board links allowed to be "
                                 "dead in the allocation, or -1 to allow "
                                 "any number of dead links "
                                 "(default: %(default)s)")
    allocation_args.add_argument(
        "--require-torus",
        "-w",
        action="store_true",
        default=cfg["require_torus"],
        help="require that the allocation contain "
        "torus (a.k.a. wrap-around) "
        "links {}".format("(default)" if cfg["require_torus"] else ""))
    allocation_args.add_argument(
        "--no-require-torus",
        "-W",
        action="store_false",
        dest="require_torus",
        help="do not require that the allocation "
        "contain torus (a.k.a. wrap-around) "
        "links {}".format("" if cfg["require_torus"] else "(default)"))

    command_args = parser.add_argument_group("command wrapping arguments")
    command_args.add_argument("--command",
                              "-c",
                              nargs=argparse.REMAINDER,
                              help="execute the specified command once boards "
                              "have been allocated and deallocate the "
                              "boards when the application exits ({} and "
                              "{hostname} are substituted for the chip "
                              "chip at (0, 0)'s hostname, {w} and "
                              "{h} give the dimensions of the SpiNNaker "
                              "machine in chips, {ethernet_ips} is a "
                              "temporary file containing a CSV with "
                              "three columns: x, y and hostname giving "
                              "the hostname of each Ethernet connected "
                              "SpiNNaker chip)")

    server_args = parser.add_argument_group("spalloc server arguments")

    server_args.add_argument("--owner",
                             default=cfg["owner"],
                             help="by convention, the email address of the "
                             "owner of the job (default: %(default)s)")
    server_args.add_argument("--hostname",
                             "-H",
                             default=cfg["hostname"],
                             help="hostname or IP of the spalloc server "
                             "(default: %(default)s)")
    server_args.add_argument("--port",
                             "-P",
                             default=cfg["port"],
                             type=int,
                             help="port number of the spalloc server "
                             "(default: %(default)s)")
    server_args.add_argument(
        "--keepalive",
        type=int,
        metavar="SECONDS",
        default=(-1 if cfg["keepalive"] is None else cfg["keepalive"]),
        help="the interval at which to require "
        "keepalive messages to be sent to "
        "prevent the server cancelling the "
        "job, or -1 to not require keepalive "
        "messages (default: %(default)s)")
    server_args.add_argument("--reconnect-delay",
                             default=cfg["reconnect_delay"],
                             type=float,
                             metavar="SECONDS",
                             help="seconds to wait before "
                             "reconnecting to the server if the "
                             "connection is lost (default: %(default)s)")
    server_args.add_argument("--timeout",
                             default=cfg["timeout"],
                             type=float,
                             metavar="SECONDS",
                             help="seconds to wait for a response "
                             "from the server (default: %(default)s)")

    args = parser.parse_args(argv)

    # Fail if no owner is defined (unless resuming)
    if not args.owner and args.resume is None:
        parser.error(
            "--owner must be specified (typically your email address)")

    # Fail if server not specified
    if args.hostname is None:
        parser.error("--hostname of spalloc server must be specified")

    # Set universal job arguments
    job_kwargs = {
        "hostname":
        args.hostname,
        "port":
        args.port,
        "reconnect_delay":
        args.reconnect_delay if args.reconnect_delay >= 0.0 else None,
        "timeout":
        args.timeout if args.timeout >= 0.0 else None,
    }

    if args.resume:
        job_args = []
        job_kwargs.update({
            "resume_job_id": args.resume,
        })
    else:
        # Make sure 'what' takes the right form
        if len(args.what) not in (0, 1, 2, 3):
            parser.error("expected either no arguments, one argument, NUM, "
                         "two arguments, WIDTH HEIGHT, or three arguments "
                         "X Y Z")

        # Unpack arguments for the job and server
        job_args = args.what
        job_kwargs.update({
            "owner":
            args.owner,
            "keepalive":
            args.keepalive if args.keepalive >= 0.0 else None,
            "machine":
            args.machine,
            "tags":
            args.tags if args.machine is None else None,
            "min_ratio":
            args.min_ratio,
            "max_dead_boards":
            args.max_dead_boards if args.max_dead_boards >= 0.0 else None,
            "max_dead_links":
            args.max_dead_links if args.max_dead_links >= 0.0 else None,
            "require_torus":
            args.require_torus,
        })

    # Set debug level
    if args.debug:
        logging.basicConfig(level=logging.DEBUG)

    # Create temporary file in which to write CSV of all board IPs
    _, ip_file_filename = tempfile.mkstemp(".csv", "spinnaker_ips_")

    def info(msg):
        if not args.quiet:
            t.stream.write("{}\n".format(msg))

    # Reason for destroying the job
    reason = None

    try:
        # Create the job
        try:
            job = Job(*job_args, **job_kwargs)
        except (OSError, IOError) as e:
            info(t.red("Could not connect to server: {}".format(e)))
            return 6
        try:
            # Wait for it to become ready, keeping the user informed along the
            # way
            old_state = None
            cur_state = job.state
            while True:
                # Show debug info on state-change
                if old_state != cur_state:
                    if cur_state == JobState.queued:
                        info(
                            t.update(
                                t.yellow("Job {}: Waiting in queue...".format(
                                    job.id))))
                    elif cur_state == JobState.power:
                        info(
                            t.update(
                                t.yellow(
                                    "Job {}: Waiting for power on...".format(
                                        job.id))))
                    elif cur_state == JobState.ready:
                        # Here we go!
                        break
                    elif cur_state == JobState.destroyed:
                        # Exit with error state
                        try:
                            reason = job.reason
                        except (IOError, OSError):
                            reason = None

                        if reason is not None:
                            info(
                                t.update(
                                    t.red("Job {}: Destroyed: {}".format(
                                        job.id, reason))))
                        else:
                            info(t.red("Job {}: Destroyed.".format(job.id)))
                        return 1
                    elif cur_state == JobState.unknown:
                        info(
                            t.update(
                                t.red("Job {}: Job not recognised by server.".
                                      format(job.id))))
                        return 2
                    else:
                        info(
                            t.update(
                                t.red(
                                    "Job {}: Entered an unrecognised state {}."
                                    .format(job.id, cur_state))))
                        return 3

                try:
                    old_state = cur_state
                    cur_state = job.wait_for_state_change(cur_state)
                except KeyboardInterrupt:
                    # Gracefully terminate from keyboard interrupt
                    info(
                        t.update(
                            t.red("Job {}: Keyboard interrupt.".format(
                                job.id))))
                    reason = "Keyboard interrupt."
                    return 4

            # Machine is now ready
            write_ips_to_csv(job.connections, ip_file_filename)

            # Boot the machine if required
            if MachineController is not None and args.boot:
                info(t.update(t.yellow("Job {}: Booting...".format(job.id))))
                mc = MachineController(job.hostname)
                mc.boot(job.width, job.height)

            info(t.update(t.green("Job {}: Ready!".format(job.id))))

            # Either run the user's application or just print the details.
            if args.command:
                return run_command(args.command, job.id, job.machine_name,
                                   job.connections, job.width, job.height,
                                   ip_file_filename)

            else:
                print_info(job.machine_name, job.connections, job.width,
                           job.height, ip_file_filename)
                return 0
        finally:
            # Destroy job and disconnect client
            if args.no_destroy:
                job.close()
            else:
                job.destroy(reason)
    finally:
        # Delete IP address list file
        os.remove(ip_file_filename)
Пример #13
0
    parser.add_argument("target_length", type=int, default=0, nargs='?')
    parser.add_argument("--memory-profile", type=str)
    args = parser.parse_args()

    # Load and minimise all routing tables
    print("Reading routing tables...")
    with open(args.routing_table, "rb") as f:
        uncompressed = common.read_routing_tables(f)

    # Request a SpiNNaker machine
    print("Waiting for SpiNNaker machine...")
    with spalloc.Job(args.width, args.height) as job:
        # Talk to the machine
        print("Booting...")
        mc = MachineController(job.hostname)
        mc.boot()
        mc.discover_connections()

        # Convert the tables into the appropriate formats
        chip_data = {
            chip: pack_table(table, args.target_length)
            for chip, table in iteritems(uncompressed)
        }

        # Allocate memory on the machine
        chip_mem = {(x, y): mc.sdram_alloc_as_filelike(len(data),
                                                       x=x,
                                                       y=y,
                                                       tag=1)
                    for (x, y), data in iteritems(chip_data)}