Ejemplo n.º 1
0
def write_files():

    fwrC = rogue.utilities.fileio.StreamWriter()
    fwrC.setBufferSize(BufferSize)
    fwrC.setMaxSize(MaxSize)

    fwrU = rogue.utilities.fileio.StreamWriter()
    fwrU.setBufferSize(BufferSize)
    fwrU.setMaxSize(MaxSize)

    prbs = rogue.utilities.Prbs()

    comp = rogue.utilities.StreamZip()

    pyrogue.streamConnect(prbs,fwrU.getChannel(0))
    pyrogue.streamTap(prbs,comp)
    pyrogue.streamConnect(comp,fwrC.getChannel(0))

    fwrC.open("compressed.dat")
    fwrU.open("uncompressed.dat")

    print("Writing data files")
    for _ in range(FrameCount):
        prbs.genFrame(FrameSize)

    time.sleep(5)
    fwrC.close()
    fwrU.close()
Ejemplo n.º 2
0
    def __init__(self, name, description, root=None, txDevice=None, **kwargs):
        pyrogue.Device.__init__(self,
                                name=name,
                                description=description,
                                **kwargs)

        # Add a data emulator module, at the beginning of the chain
        self.pre_data_emulator = pysmurf.core.emulators.StreamDataEmulatorI16(
            name="PreDataEmulator")
        self.add(self.pre_data_emulator)

        # Add a frame statistics module
        self.smurf_frame_stats = pysmurf.core.counters.FrameStatistics(
            name="FrameRxStats")
        self.add(self.smurf_frame_stats)

        # Add the SmurfProcessor C++ device. This module implements: channel mapping,
        # data unwrapping, filter, and downsampling. Python wrapper for these functions
        # are added here to give the same tree structure as the modular version.
        self.smurf_processor = smurf.core.processors.SmurfProcessor()

        self.smurf_mapper = SmurfChannelMapper(name="ChannelMapper",
                                               device=self.smurf_processor)
        self.add(self.smurf_mapper)

        self.smurf_unwrapper = Unwrapper(name="Unwrapper",
                                         device=self.smurf_processor)
        self.add(self.smurf_unwrapper)

        self.smurf_filter = GeneralAnalogFilter(name="Filter",
                                                device=self.smurf_processor)
        self.add(self.smurf_filter)

        self.smurf_downsampler = Downsampler(name="Downsampler",
                                             device=self.smurf_processor)
        self.add(self.smurf_downsampler)

        # This device doesn't have any user configurations, so we don't add it to the tree
        self.smurf_header2smurf = pysmurf.core.conventers.Header2Smurf(
            name="Header2Smurf")

        # Add a data emulator module, at the end of the chain
        self.post_data_emulator = pysmurf.core.emulators.StreamDataEmulatorI32(
            name="PostDataEmulator")
        self.add(self.post_data_emulator)

        # Use a standard Rogue file writer.
        # - Channel 0 will be use for the smurf data
        # - Channel 1 will be use for the configuration data (aka metadata)
        self.file_writer = pyrogue.utilities.fileio.StreamWriter(
            name='FileWriter')
        self.add(self.file_writer)

        # Add a Fifo. It will hold up to 100 copies of processed frames, to be processed by
        # downstream slaves. The frames will be tapped before the file writer.
        self.fifo = rogue.interfaces.stream.Fifo(100, 0, False)

        # Connect devices
        pyrogue.streamConnect(self.pre_data_emulator, self.smurf_frame_stats)
        pyrogue.streamConnect(self.smurf_frame_stats, self.smurf_processor)
        pyrogue.streamConnect(self.smurf_processor, self.smurf_header2smurf)
        pyrogue.streamConnect(self.smurf_header2smurf, self.post_data_emulator)
        pyrogue.streamConnect(self.post_data_emulator,
                              self.file_writer.getChannel(0))
        pyrogue.streamTap(self.post_data_emulator, self.fifo)

        # If a root was defined, connect it to the file writer, on channel 1
        if root:
            pyrogue.streamConnect(root, self.file_writer.getChannel(1))

        # If a TX device was defined, add it to the tree
        # and connect it to the chain, after the fifo
        if txDevice:
            self.transmitter = txDevice
            self.add(self.transmitter)
            # Connect the data channel to the FIFO.
            pyrogue.streamConnect(self.fifo, self.transmitter.getDataChannel())
            # If a root was defined, connect  it to the meta channel.
            # Use streamTap as it was already connected to the file writer.
            if root:
                pyrogue.streamTap(root, self.transmitter.getMetaChannel())
Ejemplo n.º 3
0
    def __init__(self,
                 name='Top',
                 description='Container for FEB FPGA',
                 ip=['10.0.0.1'],
                 pollEn=True,
                 initRead=True,
                 configProm=False,
                 advanceUser=False,
                 refClkSel=['IntClk'],
                 loadYaml=True,
                 userYaml=[''],
                 defaultFile='config/defaults.yml',
                 **kwargs):
        super().__init__(name=name, description=description, **kwargs)

        # Set the min. firmware Version support by the software
        self.minFpgaVersion = 0x20000060

        # Enable Init after config
        self.InitAfterConfig._default = True

        # Cache the parameters
        self.advanceUser = advanceUser
        self.configProm = configProm
        self.ip = ip
        self.numEthDev = len(ip) if (ip[0] != 'simulation') else 1
        self._timeout = 1.0 if (ip[0] != 'simulation') else 100.0
        self._pollEn = pollEn if (ip[0] != 'simulation') else False
        self._initRead = initRead if (ip[0] != 'simulation') else False
        self.usrLoadYaml = loadYaml
        self.userYaml = userYaml
        self.defaultFile = defaultFile
        self.pllConfig = [None for i in range(self.numEthDev)]

        # Check if missing refClkSel configuration
        if (len(refClkSel) < len(ip)):
            errMsg = f'len(refClkSel) = {len(refClkSel)} < len(ip) = {len(ip)}.\nMake sure to define a refClkSel for each IP address'
            click.secho(errMsg, bg='red')
            raise ValueError(errMsg)

        # Set the path of the PLL configuration file
        for i in range(self.numEthDev):
            if (refClkSel[i] == 'IntClk'):
                self.pllConfig[
                    i] = 'config/pll-config/Si5345-RevD-Registers-IntClk.csv'
            elif (refClkSel[i] == 'ExtSmaClk'):
                self.pllConfig[
                    i] = 'config/pll-config/Si5345-RevD-Registers-ExtSmaClk.csv'
            elif (refClkSel[i] == 'ExtLemoClk'):
                self.pllConfig[
                    i] = 'config/pll-config/Si5345-RevD-Registers-ExtLemoClk.csv'
            else:
                errMsg = f'refClkSel[{i}] argument must be either [IntClk,ExtSmaClk,ExtLemoClk]'
                click.secho(errMsg, bg='red')
                raise ValueError(errMsg)

        # File writer
        self.dataWriter = pr.utilities.fileio.StreamWriter()
        self.add(self.dataWriter)

        # Create arrays to be filled
        self.rudp = [None for i in range(self.numEthDev)]
        self.srpStream = [None for i in range(self.numEthDev)]
        self.dataStream = [None for i in range(self.numEthDev)]
        self.semStream = [None for i in range(self.numEthDev)]
        self.memMap = [None for i in range(self.numEthDev)]

        # SEM monitor streams
        self.semDataWriter = SemAsciiFileWriter()

        # Loop through the devices
        for i in range(self.numEthDev):

            ######################################################################
            if (self.ip[0] == 'simulation'):
                self.srpStream[i] = rogue.interfaces.stream.TcpClient(
                    'localhost', 9000)
                self.dataStream[i] = rogue.interfaces.stream.TcpClient(
                    'localhost', 9002)
            else:
                self.rudp[i] = pr.protocols.UdpRssiPack(host=ip[i],
                                                        port=8192,
                                                        packVer=2,
                                                        jumbo=False)
                self.srpStream[i] = self.rudp[i].application(0)
                self.dataStream[i] = self.rudp[i].application(1)
                self.semStream[i] = self.rudp[i].application(2)

            ######################################################################

            # Connect the SRPv3 to PGPv3.VC[0]
            self.memMap[i] = rogue.protocols.srp.SrpV3()
            pr.streamConnectBiDir(self.memMap[i], self.srpStream[i])

            # Check if not PROM loading
            if not self.configProm:

                # Connect data stream to file as channel to dataStream
                pr.streamConnect(self.dataStream[i],
                                 self.dataWriter.getChannel(i))

                # Connect to the SEM monitor streams and file writer
                pr.streamConnect(self.semStream[i], self.semDataWriter)
                pr.streamTap(self.semStream[i],
                             self.dataWriter.getChannel(i + 128))

            ######################################################################

            # Add devices
            self.add(
                common.Fpga(
                    name=f'Fpga[{i}]',
                    memBase=self.memMap[i],
                    offset=0x00000000,
                    configProm=self.configProm,
                    advanceUser=self.advanceUser,
                    expand=True,
                ))

            ######################################################################

        self.add(
            pr.LocalVariable(
                name="LiveDisplayRst",
                mode="RW",
                value=0x0,
                hidden=True,
            ))

        @self.command()
        def LiveDisplayReset(arg):
            print('LiveDisplayReset()')
            self.LiveDisplayRst.set(1)
            for reset in self.reset_list:
                reset()
            self.LiveDisplayRst.set(0)

        @self.command(
            description=
            'This command is intended to be executed before self.dataWriter is closed'
        )
        def StopRun(arg):
            click.secho('StopRun()', bg='yellow')

            # Stop the Master First
            for i in range(self.numEthDev):
                if self.Fpga[i].Asic.Trig.TrigTypeSel.getDisp() == 'Master':
                    self.Fpga[i].Asic.Trig.EnableReadout.set(0x0)
                    click.secho(
                        f'self.Fpga[{i}].Asic.Trig.EnableReadout.set(0x0)',
                        bg='bright_magenta')

            # Stop the Slave after the Master
            for i in range(self.numEthDev):
                if self.Fpga[i].Asic.Trig.TrigTypeSel.getDisp() == 'Slave':
                    self.Fpga[i].Asic.Trig.EnableReadout.set(0x0)
                    click.secho(
                        f'self.Fpga[{i}].Asic.Trig.EnableReadout.set(0x0)',
                        bg='magenta')

        @self.command(
            description=
            'This command is intended to be executed after self.dataWriter is opened'
        )
        def StartRun(arg):
            click.secho('StartRun()', bg='blue')

            # Reset the sequence and trigger counters
            for i in range(self.numEthDev):
                self.Fpga[i].Asic.Trig.countReset()
                self.Fpga[i].Asic.Readout.SeqCntRst()

            # Start the Slave First
            for i in range(self.numEthDev):
                if self.Fpga[i].Asic.Trig.TrigTypeSel.getDisp() == 'Slave':
                    self.Fpga[i].Asic.Trig.EnableReadout.set(0x1)
                    click.secho(
                        f'self.Fpga[{i}].Asic.Trig.EnableReadout.set(0x1)',
                        bg='magenta')

            # Start the Master after the Slave
            for i in range(self.numEthDev):
                if self.Fpga[i].Asic.Trig.TrigTypeSel.getDisp() == 'Master':
                    self.Fpga[i].Asic.Trig.EnableReadout.set(0x1)
                    click.secho(
                        f'self.Fpga[{i}].Asic.Trig.EnableReadout.set(0x1)',
                        bg='bright_magenta')

        @self.command(
            description=
            'This command is intended to be executed after self.dataWriter is opened'
        )
        def ResumeRun(arg):
            click.secho('ResumeRun()', bg='blue')

            # Start the Slave First
            for i in range(self.numEthDev):
                if self.Fpga[i].Asic.Trig.TrigTypeSel.getDisp() == 'Slave':
                    self.Fpga[i].Asic.Trig.EnableReadout.set(0x1)
                    click.secho(
                        f'self.Fpga[{i}].Asic.Trig.EnableReadout.set(0x1)',
                        bg='magenta')

            # Start the Master after the Slave
            for i in range(self.numEthDev):
                if self.Fpga[i].Asic.Trig.TrigTypeSel.getDisp() == 'Master':
                    self.Fpga[i].Asic.Trig.EnableReadout.set(0x1)
                    click.secho(
                        f'self.Fpga[{i}].Asic.Trig.EnableReadout.set(0x1)',
                        bg='bright_magenta')

        ######################################################################

        # Start the system
        self.start(
            pollEn=self._pollEn,
            initRead=self._initRead,
            timeout=self._timeout,
        )
    def __init__(self, ip_addr, config_file, server_mode, group_name, epics_prefix,\
        polling_en, comm_type, pcie_rssi_link, stream_pv_size, stream_pv_type,\
        pv_dump_file):

        try:
            pyrogue.Root.__init__(self, name='AMCc', description='AMC Carrier')

            # File writer for streaming interfaces
            # DDR interface (TDEST 0x80 - 0x87)
            stm_data_writer = pyrogue.utilities.fileio.StreamWriter(
                name='streamDataWriter')
            self.add(stm_data_writer)
            # Streaming interface (TDEST 0xC0 - 0xC7)
            stm_interface_writer = pyrogue.utilities.fileio.StreamWriter(
                name='streamingInterface')
            self.add(stm_interface_writer)

            # Workaround to FpgaTopLelevel not supporting rssi = None
            if pcie_rssi_link == None:
                pcie_rssi_link = 0

            # Instantiate Fpga top level
            fpga = FpgaTopLevel(ipAddr=ip_addr,
                                commType=comm_type,
                                pcieRssiLink=pcie_rssi_link)

            # Add devices
            self.add(fpga)

            # Add data streams (0-7) to file channels (0-7)
            for i in range(8):
                # DDR streams
                pyrogue.streamConnect(fpga.stream.application(0x80 + i),
                                      stm_data_writer.getChannel(i))
                # Streaming interface streams
                #pyrogue.streamConnect(fpga.stream.application(0xC0 + i),  # new commended out
                # stm_interface_writer.getChannel(i))

            # Our receiver
            data_fifo = rogue.interfaces.stream.Fifo(1000, 0, 1)  # new
            self.my_processor = MyModule.MyProcessor()
            self.my_processor.setDebug(False)
            #pyrogue.streamConnect(base.FpgaTopLevel.stream.application(0xC1), data_fifo) # new
            #pyrogue.streamConnect(base.FpgaTopLevel.stream.Application(0xC1), data_fifo) # new
            pyrogue.streamConnect(fpga.stream.application(0xC1), data_fifo)
            pyrogue.streamConnect(data_fifo, self.my_processor)
            #pyrogue.streamTap(fpga.stream.application(0xC1), rx)

            # Run control for streaming interfaces
            self.add(
                pyrogue.RunControl(name='streamRunControl',
                                   description='Run controller',
                                   cmd=fpga.SwDaqMuxTrig,
                                   rates={
                                       1: '1 Hz',
                                       10: '10 Hz',
                                       30: '30 Hz'
                                   }))

            # PVs for stream data, used on PCAS-based EPICS server
            if epics_prefix and stream_pv_size:
                if use_pcas:

                    print("Enabling stream data on PVs (buffer size = {} points, data type = {})"\
                        .format(stream_pv_size,stream_pv_type))

                    # Add data streams (0-7) to local variables so they are expose as PVs
                    # Also add PVs to select the data format
                    for i in range(8):

                        # Calculate number of bytes needed on the fifo
                        if '16' in stream_pv_type:
                            fifo_size = stream_pv_size * 2
                        else:
                            fifo_size = stream_pv_size * 4

                        # Setup a FIFO tapped to the steram data and a Slave data buffer
                        # Local variables will talk to the data buffer directly.
                        stream_fifo = rogue.interfaces.stream.Fifo(
                            0, fifo_size, 0)
                        data_buffer = DataBuffer(size=stream_pv_size,
                                                 data_type=stream_pv_type)
                        stream_fifo._setSlave(data_buffer)

                        #pyrogue.streamTap(fpga.stream.application(0x80 + i), stream_fifo)

                        # Variable to read the stream data
                        stream_var = pyrogue.LocalVariable(
                            name='Stream{}'.format(i),
                            description='Stream {}'.format(i),
                            mode='RO',
                            value=0,
                            localGet=data_buffer.read,
                            update=False,
                            hidden=True)

                        # Set the buffer callback to update the variable
                        data_buffer.set_callback(stream_var.updated)

                        # Variable to set the data format
                        data_format_var = pyrogue.LocalVariable(
                            name='StreamDataFormat{}'.format(i),
                            description='Type of data being unpacked',
                            mode='RW',
                            value=0,
                            enum={
                                i: j
                                for i, j in enumerate(
                                    data_buffer.get_data_format_list())
                            },
                            localSet=data_buffer.set_data_format,
                            localGet=data_buffer.get_data_format,
                            hidden=True)

                        # Variable to set the data byte order
                        byte_order_var = pyrogue.LocalVariable(
                            name='StreamDataByteOrder{}'.format(i),
                            description='Byte order of data being unpacked',
                            mode='RW',
                            value=0,
                            enum={
                                i: j
                                for i, j in enumerate(
                                    data_buffer.get_data_byte_order_list())
                            },
                            localSet=data_buffer.set_data_byte_order,
                            localGet=data_buffer.get_data_byte_order,
                            hidden=True)

                        # Variable to read the data format string
                        format_string_var = pyrogue.LocalVariable(
                            name='StreamDataFormatString{}'.format(i),
                            description='Format string used to unpack the data',
                            mode='RO',
                            value=0,
                            localGet=data_buffer.get_data_format_string,
                            hidden=True)

                        # Add listener to update the format string readback variable
                        # when the data format or data byte order is changed
                        data_format_var.addListener(format_string_var)
                        byte_order_var.addListener(format_string_var)

                        # Add the local variable to self
                        self.add(stream_var)
                        self.add(data_format_var)
                        self.add(byte_order_var)
                        self.add(format_string_var)

            # lcaPut limits the maximun lenght of a string to 40 chars, as defined
            # in the EPICS R3.14 CA reference manual. This won't allowed to use the
            # command 'ReadConfig' with a long file path, which is usually the case.
            # This function is a workaround to that problem. Fomr matlab one can
            # just call this function without arguments an the function ReadConfig
            # will be called with a predefined file passed during startup
            # However, it can be usefull also win the GUI, so it is always added.
            self.config_file = config_file
            self.add(
                pyrogue.LocalCommand(name='setDefaults',
                                     description='Set default configuration',
                                     function=self.set_defaults_cmd))

            self.add(
                pyrogue.LocalCommand(name='runGarbageCollection',
                                     description='runGarbageCollection',
                                     function=self.run_garbage_collection))

            self.add(
                pyrogue.LocalVariable(
                    name='smurfProcessorDebug',
                    description='Enable smurf processor transmit debug',
                    mode='RW',
                    value=False,
                    localSet=lambda value: self.my_processor.setDebug(value),
                    hidden=False))

            # Start the root
            if group_name:
                # Start with Pyro4 server
                host_name = get_host_name()
                print(
                    "Starting rogue server with Pyro using group name \"{}\"".
                    format(group_name))
                self.start(pollEn=polling_en,
                           pyroGroup=group_name,
                           pyroHost=host_name,
                           pyroNs=None)
            else:
                # Start without Pyro4 server
                print("Starting rogue server")
                self.start(pollEn=polling_en)

            self.ReadAll()

        except KeyboardInterrupt:
            print("Killing server creation...")
            super(LocalServer, self).stop()
            exit()

        # Show image build information
        try:
            print("")
            print("FPGA image build information:")
            print("===================================")
            print("BuildStamp              : {}"\
                .format(self.FpgaTopLevel.AmcCarrierCore.AxiVersion.BuildStamp.get()))
            print("FPGA Version            : 0x{:x}"\
                .format(self.FpgaTopLevel.AmcCarrierCore.AxiVersion.FpgaVersion.get()))
            print("Git hash                : 0x{:x}"\
                .format(self.FpgaTopLevel.AmcCarrierCore.AxiVersion.GitHash.get()))
        except AttributeError as attr_error:
            print("Attibute error: {}".format(attr_error))
        print("")

        # Start the EPICS server
        if epics_prefix:
            print("Starting EPICS server using prefix \"{}\"".format(
                epics_prefix))

            # Choose the appropiate epics module:
            if use_pcas:
                self.epics = pyrogue.epics.EpicsCaServer(base=epics_prefix,
                                                         root=self)
            else:
                self.epics = pyrogue.protocols.epics.EpicsCaServer(
                    base=epics_prefix, root=self)

                # PVs for stream data, used on GDD-based EPICS server
                if stream_pv_size:

                    print("Enabling stream data on PVs (buffer size = {} points, data type = {})"\
                        .format(stream_pv_size,stream_pv_type))

                    for i in range(8):
                        stream_slave = self.epics.createSlave(
                            name="AMCc:Stream{}".format(i),
                            maxSize=stream_pv_size,
                            type=stream_pv_type)

                        # Calculate number of bytes needed on the fifo
                        if '16' in stream_pv_type:
                            fifo_size = stream_pv_size * 2
                        else:
                            fifo_size = stream_pv_size * 4

                        stream_fifo = rogue.interfaces.stream.Fifo(
                            0, fifo_size, 0)  # chnages
                        stream_fifo._setSlave(stream_slave)
                        pyrogue.streamTap(fpga.stream.application(0x80 + i),
                                          stream_fifo)

            self.epics.start()

            # Dump the PV list to the especified file
            if pv_dump_file:
                try:
                    # Try to open the output file
                    f = open(pv_dump_file, "w")
                except IOError:
                    print("Could not open the PV dump file \"{}\"".format(
                        pv_dump_file))
                else:
                    with f:
                        print("Dumping PV list to \"{}\"...".format(
                            pv_dump_file))
                        try:
                            try:
                                # Redirect the stdout to the output file momentarily
                                original_stdout, sys.stdout = sys.stdout, f
                                self.epics.dump()
                            finally:
                                sys.stdout = original_stdout

                            print("Done!")
                        except:
                            # Capture error from epics.dump() if any
                            print("Errors were found during epics.dump()")

        # If no in server Mode, start the GUI
        if not server_mode:
            create_gui(self)
        else:
            # Stop the server when Crtl+C is pressed
            print("")
            print("Running in server mode now. Press Ctrl+C to stop...")
            try:
                # Wait for Ctrl+C
                while True:
                    time.sleep(1)
            except KeyboardInterrupt:
                pass
Ejemplo n.º 5
0
    def __init__(
            self,
            *,
            config_file=None,
            epics_prefix="EpicsPrefix",
            polling_en=True,
            pv_dump_file=None,
            txDevice=None,
            fpgaTopLevel=None,
            stream_pv_size=2**19,  # Not sub-classed
            stream_pv_type='Int16',  # Not sub-classed
            configure=False,
            VariableGroups=None,
            server_port=0,
            **kwargs):

        pyrogue.Root.__init__(self,
                              name="AMCc",
                              initRead=True,
                              pollEn=polling_en,
                              streamIncGroups='stream',
                              serverPort=server_port,
                              **kwargs)

        #########################################################################################
        # The following interfaces are expected to be defined at this point by a sub-class
        # self._streaming_stream # Data stream interface
        # self._ddr_streams # 4 DDR Interface Streams
        # self._fpga = Top level FPGA

        # Add PySmurf Application Block
        self.add(pysmurf.core.devices.SmurfApplication())

        # Add FPGA
        self.add(self._fpga)

        # File writer for streaming interfaces
        # DDR interface (TDEST 0x80 - 0x87)
        self._stm_data_writer = pyrogue.utilities.fileio.StreamWriter(
            name='streamDataWriter')
        self.add(self._stm_data_writer)

        # Streaming interface (TDEST 0xC0 - 0xC7)
        self._stm_interface_writer = pyrogue.utilities.fileio.StreamWriter(
            name='streamingInterface')
        self.add(self._stm_interface_writer)

        # Add the SMuRF processor device
        self._smurf_processor = pysmurf.core.devices.SmurfProcessor(
            name="SmurfProcessor",
            description="Process the SMuRF Streaming Data Stream",
            root=self,
            txDevice=txDevice)
        self.add(self._smurf_processor)

        # Connect smurf processor
        pyrogue.streamConnect(self._streaming_stream, self._smurf_processor)

        # Add data streams (0-3) to file channels (0-3)
        for i in range(4):
            ## DDR streams
            pyrogue.streamConnect(self._ddr_streams[i],
                                  self._stm_data_writer.getChannel(i))

        ## Streaming interface streams
        # We have already connected TDEST 0xC1 to the smurf_processor receiver,
        # so we need to tapping it to the data writer.
        pyrogue.streamTap(self._streaming_stream,
                          self._stm_interface_writer.getChannel(0))

        # TES Bias Update Function
        # smurf_processor bias index 0 = TesBiasDacDataRegCh[2] - TesBiasDacDataRegCh[1]
        # smurf_processor bias index l = TesBiasDacDataRegCh[4] - TesBiasDacDataRegCh[3]
        def _update_tes_bias(idx):
            v1 = self.FpgaTopLevel.AppTop.AppCore.RtmCryoDet.RtmSpiMax.node(
                f'TesBiasDacDataRegCh[{(2*idx)+2}]').value()
            v2 = self.FpgaTopLevel.AppTop.AppCore.RtmCryoDet.RtmSpiMax.node(
                f'TesBiasDacDataRegCh[{(2*idx)+1}]').value()
            val = (v1 - v2) // 2

            # Pass to data processor
            self._smurf_processor.setTesBias(index=idx, val=val)

        # Register TesBias values configuration to update stream processor
        # Bias values are ranged 1 - 32, matching tes bias indexes 0 - 16
        for i in range(1, 33):
            idx = (i - 1) // 2
            try:
                v = self.FpgaTopLevel.AppTop.AppCore.RtmCryoDet.RtmSpiMax.node(
                    f'TesBiasDacDataRegCh[{i}]')
                v.addListener(
                    lambda path, value, lidx=idx: _update_tes_bias(lidx))
            except Exception:
                print(f"TesBiasDacDataRegCh[{i}] not found... Skipping!")

        # Run control for streaming interfaces
        self.add(
            pyrogue.RunControl(name='streamRunControl',
                               description='Run controller',
                               cmd=self._fpga.SwDaqMuxTrig,
                               rates={
                                   1: '1 Hz',
                                   10: '10 Hz',
                                   30: '30 Hz'
                               }))

        # lcaPut limits the maximun lenght of a string to 40 chars, as defined
        # in the EPICS R3.14 CA reference manual. This won't allowed to use the
        # command 'ReadConfig' with a long file path, which is usually the case.
        # This function is a workaround to that problem. Fomr matlab one can
        # just call this function without arguments an the function ReadConfig
        # will be called with a predefined file passed during startup
        # However, it can be usefull also win the GUI, so it is always added.
        self._config_file = config_file
        self.add(
            pyrogue.LocalCommand(name='setDefaults',
                                 description='Set default configuration',
                                 function=self._set_defaults_cmd))

        # Flag that indicates if the default configuration should be loaded
        # once the root is started.
        self._configure = configure

        # Variable groups
        self._VariableGroups = VariableGroups

        # Add epics interface
        self._epics = None
        if epics_prefix:
            print("Starting EPICS server using prefix \"{}\"".format(
                epics_prefix))
            from pyrogue.protocols import epics
            self._epics = epics.EpicsCaServer(base=epics_prefix, root=self)
            self._pv_dump_file = pv_dump_file

            # PVs for stream data
            # This should be replaced with DataReceiver objects
            if stream_pv_size:
                print(
                    "Enabling stream data on PVs (buffer size = {} points, data type = {})"
                    .format(stream_pv_size, stream_pv_type))

                self._stream_fifos = []
                self._stream_slaves = []
                for i in range(4):
                    self._stream_slaves.append(
                        self._epics.createSlave(name="AMCc:Stream{}".format(i),
                                                maxSize=stream_pv_size,
                                                type=stream_pv_type))

                    # Calculate number of bytes needed on the fifo
                    if '16' in stream_pv_type:
                        fifo_size = stream_pv_size * 2
                    else:
                        fifo_size = stream_pv_size * 4

                    self._stream_fifos.append(
                        rogue.interfaces.stream.Fifo(1000, fifo_size,
                                                     True))  # changes
                    pyrogue.streamConnect(self._stream_fifos[i],
                                          self._stream_slaves[i])
                    pyrogue.streamTap(self._ddr_streams[i],
                                      self._stream_fifos[i])

        # Update SaveState to not read before saving
        self.SaveState.replaceFunction(
            lambda arg: self.saveYaml(name=arg,
                                      readFirst=False,
                                      modes=['RW', 'RO', 'WO'],
                                      incGroups=None,
                                      excGroups='NoState',
                                      autoPrefix='state',
                                      autoCompress=True))

        # Update SaveConfig to not read before saving
        self.SaveConfig.replaceFunction(
            lambda arg: self.saveYaml(name=arg,
                                      readFirst=False,
                                      modes=['RW', 'WO'],
                                      incGroups=None,
                                      excGroups='NoConfig',
                                      autoPrefix='config',
                                      autoCompress=False))
Ejemplo n.º 6
0
    def __init__(
            self,
            name='TimeToolDev',
            description='Container for TimeTool Dev',
            dataDebug=False,
            dev='/dev/datadev_0',  # path to PCIe device
            version3=False,  # true = PGPv3, false = PGP2b
            pollEn=True,  # Enable automatic polling registers
            initRead=True,  # Read all registers at start of the system
            numLane=1,  # Number of PGP lanes
            **kwargs):
        super().__init__(name=name,
                         description=description,
                         dev=dev,
                         version3=version3,
                         pollEn=pollEn,
                         initRead=initRead,
                         numLane=numLane,
                         **kwargs)

        # Check if not doing simulation
        if (dev != 'sim'):

            # Create arrays to be filled
            self._srp = [None for lane in range(numLane)]

            # Create the stream interface
            for lane in range(numLane):

                # SRP
                self._srp[lane] = rogue.protocols.srp.SrpV3()
                pr.streamConnectBiDir(self._dma[lane][0], self._srp[lane])

                # CameraLink Feb Board
                self.add(
                    feb.ClinkFeb(
                        name=(f'ClinkFeb[{lane}]'),
                        memBase=self._srp[lane],
                        serial=[self._dma[lane][2], None],
                        camType=['Piranha4', None],
                        version3=version3,
                        enableDeps=[
                            self.Hardware.PgpMon[lane].RxRemLinkReady
                        ],  # Only allow access if the PGP link is established
                        # expand      = False,
                    ))

        # Else doing Rogue VCS simulation
        else:

            # Create arrays to be filled
            self._frameGen = [None for lane in range(numLane)]

            # Create the stream interface
            for lane in range(numLane):

                # Create the frame generator
                self._frameGen[lane] = MyCustomMaster()

                # Connect the frame generator
                pr.streamConnect(self._frameGen[lane], self._pgp[lane][1])

                # Create a command to execute the frame generator
                self.add(
                    pr.BaseCommand(
                        name=f'GenFrame[{lane}]',
                        function=lambda cmd: self._frameGen[lane].myFrameGen(),
                    ))

        # Create arrays to be filled
        self._dbg = [None for lane in range(numLane)]

        # Create the stream interface
        for lane in range(numLane):
            # Debug slave
            if dataDebug:
                self._dbg[lane] = TimeToolRx(expand=False)
                pr.streamTap(self._dma[lane][1], self._dbg[lane])
                self.add(self._dbg)

        # Time tool application
        self.add(
            timeTool.Application(
                memBase=self._memMap,
                offset=0x00C00000,
                numLane=numLane,
            ))

        # Start the system
        self.start(
            pollEn=self._pollEn,
            initRead=self._initRead,
            timeout=self._timeout,
        )

        # Check if not simulation
        if (dev != 'sim'):
            # Read all the variables
            self.ReadAll()
            # Some initialization after starting root
            for lane in range(numLane):
                self.ClinkFeb[lane].ClinkTop.Ch[0].BaudRate.set(9600)
                self.ClinkFeb[lane].ClinkTop.Ch[0].SerThrottle.set(10000)
                self.ClinkFeb[lane].ClinkTop.Ch[0].LinkMode.setDisp('Full')
                self.ClinkFeb[lane].ClinkTop.Ch[0].DataMode.setDisp('8Bit')
                self.ClinkFeb[lane].ClinkTop.Ch[0].FrameMode.setDisp('Line')
                self.ClinkFeb[lane].ClinkTop.Ch[0].TapCount.set(8)
                self.ClinkFeb[lane].ClinkTop.Ch[0].UartPiranha4.SendEscape()
                self.ClinkFeb[lane].ClinkTop.Ch[0].UartPiranha4.SPF.setDisp(
                    '0')
                self.ClinkFeb[lane].ClinkTop.Ch[0].UartPiranha4.GCP()
        else:
            # Disable the PGP PHY device (speed up the simulation)
            self.Hardware.enable.set(False)
            self.Hardware.hidden = True
            # Bypass the time AXIS channel
            eventDev = self.find(typ=batcher.AxiStreamBatcherEventBuilder)
            for dev in eventDev:
                dev.Bypass.set(0x1)
Ejemplo n.º 7
0
    def __init__(self, ip_addr, config_file, server_mode, group_name, epics_prefix,\
        polling_en, comm_type, pcie_rssi_link, stream_pv_size, stream_pv_type,\
        pv_dump_file, disable_bay0, disable_bay1, disable_gc, windows_title, pcie_dev):

        try:
            pyrogue.Root.__init__(self, name='AMCc', description='AMC Carrier')

            # File writer for streaming interfaces
            # DDR interface (TDEST 0x80 - 0x87)
            stm_data_writer = pyrogue.utilities.fileio.StreamWriter(
                name='streamDataWriter')
            self.add(stm_data_writer)
            # Streaming interface (TDEST 0xC0 - 0xC7)
            stm_interface_writer = pyrogue.utilities.fileio.StreamWriter(
                name='streamingInterface')
            self.add(stm_interface_writer)

            # Workaround to FpgaTopLelevel not supporting rssi = None
            if pcie_rssi_link == None:
                pcie_rssi_link = 0

            # Instantiate Fpga top level
            fpga = FpgaTopLevel(ipAddr=ip_addr,
                                commType=comm_type,
                                pcieRssiLink=pcie_rssi_link,
                                disableBay0=disable_bay0,
                                disableBay1=disable_bay1)

            # Add devices
            self.add(fpga)

            # Create stream interfaces
            self.ddr_streams = []  # DDR streams
            self.streaming_streams = []  # Streaming interface streams

            # If the packetizer is being used, the FpgaTopLevel class will defined a 'stream' interface exposing it.
            # Otherwise, we are using DMA engine without packetizer. Create the stream interface accordingly.
            if hasattr(fpga, 'stream'):
                for i in range(8):
                    self.ddr_streams.append(fpga.stream.application(0x80 + i))
                    self.streaming_streams.append(
                        fpga.stream.application(0xC0 + i))
            else:
                for i in range(8):
                    self.ddr_streams.append(
                        rogue.hardware.axi.AxiStreamDma(
                            pcie_dev, (pcie_rssi_link * 0x100 + 0x80 + i),
                            True))
                    self.streaming_streams.append(
                        rogue.hardware.axi.AxiStreamDma(
                            pcie_dev, (pcie_rssi_link * 0x100 + 0xC0 + i),
                            True))

            # Our smurf_processor receiver
            # The data stream comes from TDEST 0xC1
            # We use a FIFO between the stream data and the receiver:
            # Stream -> FIFO -> smurf_processor receiver
            self.smurf_processor = Smurf.SmurfProcessor()
            self.smurf_processor.setDebug(False)
            self.smurf_processor_fifo = rogue.interfaces.stream.Fifo(
                1000, 0, True)
            pyrogue.streamConnect(self.streaming_streams[1],
                                  self.smurf_processor_fifo)
            pyrogue.streamConnect(self.smurf_processor_fifo,
                                  self.smurf_processor)

            # Add data streams (0-7) to file channels (0-7)
            for i in range(8):

                ## DDR streams
                pyrogue.streamConnect(self.ddr_streams[i],
                                      stm_data_writer.getChannel(i))

                ## Streaming interface streams

                # We have already connected TDEST 0xC1 to the smurf_processor receiver,
                # so we need to tapping it to the data writer.
                if i == 1:
                    pyrogue.streamTap(self.streaming_streams[i],
                                      stm_interface_writer.getChannel(i))
                # The rest of channels are connected directly to the data writer.
                else:
                    pyrogue.streamConnect(self.streaming_streams[i],
                                          stm_interface_writer.getChannel(i))

            # Look for the TesBias registers
            # TesBias register are located on
            # FpgaTopLevel.AppTop.AppCore.RtmCryoDet.RtmSpiMax
            # And their name is TesBiasDacDataRegCh[n], where x = [0:31]
            self.TestBiasVars = []
            self.TestBiasRegEx = re.compile('.*TesBiasDacDataRegCh\[(\d+)\]$')
            for var in self.FpgaTopLevel.AppTop.AppCore.RtmCryoDet.RtmSpiMax.variableList:
                m = self.TestBiasRegEx.match(var.name)
                if m:
                    reg_index = int(m[1]) - 1
                    if reg_index < 32:
                        print(
                            f'Found TesBias register: {var.name}, with index {reg_index}'
                        )
                        self.TestBiasVars.append(var)

            # Check that we have all 32 TesBias registers
            if len(self.TestBiasVars) == 32:
                print(
                    f'Found 32 TesBias registers. Assigning listener functions'
                )
                # Add listener to the TesBias registers
                for var in self.TestBiasVars:
                    var.addListener(self.send_test_bias)
                # Prepare a buffer to holds the TesBias register values
                self.TesBiasValue = [0] * 32
            else:
                print(
                    f'Error: {len(self.TestBiasVars)} TesBias register were found instead of 32. Aborting'
                )

            # Run control for streaming interfaces
            self.add(
                pyrogue.RunControl(name='streamRunControl',
                                   description='Run controller',
                                   cmd=fpga.SwDaqMuxTrig,
                                   rates={
                                       1: '1 Hz',
                                       10: '10 Hz',
                                       30: '30 Hz'
                                   }))

            # PVs for stream data, used on PCAS-based EPICS server
            if epics_prefix and stream_pv_size:
                if use_pcas:

                    print("Enabling stream data on PVs (buffer size = {} points, data type = {})"\
                        .format(stream_pv_size,stream_pv_type))

                    # Add data streams (0-7) to local variables so they are expose as PVs
                    # Also add PVs to select the data format
                    self.stream_fifos = []
                    self.data_buffers = []
                    for i in range(8):

                        # Calculate number of bytes needed on the fifo
                        if '16' in stream_pv_type:
                            fifo_size = stream_pv_size * 2
                        else:
                            fifo_size = stream_pv_size * 4

                        # Setup a FIFO tapped to the steram data and a Slave data buffer
                        # Local variables will talk to the data buffer directly.
                        self.stream_fifos.append(
                            rogue.interfaces.stream.Fifo(0, fifo_size, 0))
                        stream_fifo = self.stream_fifos[i]

                        self.data_buffers.append(
                            DataBuffer(size=stream_pv_size,
                                       data_type=stream_pv_type))
                        data_buffer = self.data_buffers[i]

                        stream_fifo._setSlave(data_buffer)

                        #pyrogue.streamTap(fpga.stream.application(0x80 + i), stream_fifo)

                        # Variable to read the stream data
                        stream_var = pyrogue.LocalVariable(
                            name='Stream{}'.format(i),
                            description='Stream {}'.format(i),
                            mode='RO',
                            value=0,
                            localGet=data_buffer.read,
                            update=False,
                            hidden=True)

                        # Set the buffer callback to update the variable
                        data_buffer.set_callback(stream_var.updated)

                        # Variable to set the data format
                        data_format_var = pyrogue.LocalVariable(
                            name='StreamDataFormat{}'.format(i),
                            description='Type of data being unpacked',
                            mode='RW',
                            value=0,
                            enum={
                                i: j
                                for i, j in enumerate(
                                    data_buffer.get_data_format_list())
                            },
                            localSet=data_buffer.set_data_format,
                            localGet=data_buffer.get_data_format,
                            hidden=True)

                        # Variable to set the data byte order
                        byte_order_var = pyrogue.LocalVariable(
                            name='StreamDataByteOrder{}'.format(i),
                            description='Byte order of data being unpacked',
                            mode='RW',
                            value=0,
                            enum={
                                i: j
                                for i, j in enumerate(
                                    data_buffer.get_data_byte_order_list())
                            },
                            localSet=data_buffer.set_data_byte_order,
                            localGet=data_buffer.get_data_byte_order,
                            hidden=True)

                        # Variable to read the data format string
                        format_string_var = pyrogue.LocalVariable(
                            name='StreamDataFormatString{}'.format(i),
                            description='Format string used to unpack the data',
                            mode='RO',
                            value=0,
                            localGet=data_buffer.get_data_format_string,
                            hidden=True)

                        # Add listener to update the format string readback variable
                        # when the data format or data byte order is changed
                        data_format_var.addListener(format_string_var)
                        byte_order_var.addListener(format_string_var)

                        # Add the local variable to self
                        self.add(stream_var)
                        self.add(data_format_var)
                        self.add(byte_order_var)
                        self.add(format_string_var)

            # lcaPut limits the maximun lenght of a string to 40 chars, as defined
            # in the EPICS R3.14 CA reference manual. This won't allowed to use the
            # command 'ReadConfig' with a long file path, which is usually the case.
            # This function is a workaround to that problem. Fomr matlab one can
            # just call this function without arguments an the function ReadConfig
            # will be called with a predefined file passed during startup
            # However, it can be usefull also win the GUI, so it is always added.
            self.config_file = config_file
            self.add(
                pyrogue.LocalCommand(name='setDefaults',
                                     description='Set default configuration',
                                     function=self.set_defaults_cmd))

            # If Garbage collection was disable, add this local variable to allow users
            # to manually run the garbage collection.
            if disable_gc:
                self.add(
                    pyrogue.LocalCommand(name='runGarbageCollection',
                                         description='runGarbageCollection',
                                         function=self.run_garbage_collection))

            self.add(
                pyrogue.LocalVariable(
                    name='smurfProcessorDebug',
                    description='Enable smurf processor transmit debug',
                    mode='RW',
                    value=False,
                    localSet=lambda value: self.smurf_processor.setDebug(value
                                                                         ),
                    hidden=False))

            # Lost frame counter from smurf_processor
            self.add(
                pyrogue.LocalVariable(
                    name='frameLossCnt',
                    description='Lost frame Counter',
                    mode='RO',
                    value=0,
                    localGet=self.smurf_processor.getFrameLossCnt,
                    pollInterval=1,
                    hidden=False))

            # Received frame counter from smurf_processor
            self.add(
                pyrogue.LocalVariable(
                    name='frameRxCnt',
                    description='Received frame Counter',
                    mode='RO',
                    value=0,
                    localGet=self.smurf_processor.getFrameRxCnt,
                    pollInterval=1,
                    hidden=False))

            # Out-of-order frame counter from smurf_processor
            self.add(
                pyrogue.LocalVariable(
                    name='frameOutOrderCnt',
                    description=
                    'Number of time out-of-order frames are detected',
                    mode='RO',
                    value=0,
                    localGet=self.smurf_processor.getFrameOutOrderCnt,
                    pollInterval=1,
                    hidden=False))

            # Command to clear all the frame counters on smurf_processor
            self.add(
                pyrogue.LocalCommand(
                    name='clearFrameCnt',
                    description='Clear all frame counters',
                    function=self.smurf_processor.clearFrameCnt))

            # Start the root
            if group_name:
                # Start with Pyro4 server
                host_name = get_host_name()
                print(
                    "Starting rogue server with Pyro using group name \"{}\"".
                    format(group_name))
                self.start(pollEn=polling_en,
                           pyroGroup=group_name,
                           pyroHost=host_name,
                           pyroNs=None)
            else:
                # Start without Pyro4 server
                print("Starting rogue server")
                self.start(pollEn=polling_en)

            self.ReadAll()

            # Call the get() method on the tesBias variable to force the call to
            # send_test_bias and update the array in Smurf2MCE
            for var in self.TestBiasVars:
                var.get()

        except KeyboardInterrupt:
            print("Killing server creation...")
            super(LocalServer, self).stop()
            exit()

        # Show image build information
        try:
            print("")
            print("FPGA image build information:")
            print("===================================")
            print("BuildStamp              : {}"\
                .format(self.FpgaTopLevel.AmcCarrierCore.AxiVersion.BuildStamp.get()))
            print("FPGA Version            : 0x{:x}"\
                .format(self.FpgaTopLevel.AmcCarrierCore.AxiVersion.FpgaVersion.get()))
            print("Git hash                : 0x{:x}"\
                .format(self.FpgaTopLevel.AmcCarrierCore.AxiVersion.GitHash.get()))
        except AttributeError as attr_error:
            print("Attibute error: {}".format(attr_error))
        print("")

        # Start the EPICS server
        if epics_prefix:
            print("Starting EPICS server using prefix \"{}\"".format(
                epics_prefix))

            # Choose the appropiate epics module:
            if use_pcas:
                self.epics = pyrogue.epics.EpicsCaServer(base=epics_prefix,
                                                         root=self)
            else:
                self.epics = pyrogue.protocols.epics.EpicsCaServer(
                    base=epics_prefix, root=self)

                # PVs for stream data, used on GDD-based EPICS server
                if stream_pv_size:

                    print("Enabling stream data on PVs (buffer size = {} points, data type = {})"\
                        .format(stream_pv_size,stream_pv_type))

                    self.stream_fifos = []
                    self.stream_slaves = []
                    for i in range(8):
                        self.stream_slaves.append(
                            self.epics.createSlave(
                                name="AMCc:Stream{}".format(i),
                                maxSize=stream_pv_size,
                                type=stream_pv_type))

                        # Calculate number of bytes needed on the fifo
                        if '16' in stream_pv_type:
                            fifo_size = stream_pv_size * 2
                        else:
                            fifo_size = stream_pv_size * 4

                        self.stream_fifos.append(
                            rogue.interfaces.stream.Fifo(
                                1000, fifo_size, True))  # changes
                        self.stream_fifos[i]._setSlave(self.stream_slaves[i])
                        pyrogue.streamTap(self.ddr_streams[i],
                                          self.stream_fifos[i])

            self.epics.start()

            # Dump the PV list to the especified file
            if pv_dump_file:
                try:
                    # Try to open the output file
                    f = open(pv_dump_file, "w")
                except IOError:
                    print("Could not open the PV dump file \"{}\"".format(
                        pv_dump_file))
                else:
                    with f:
                        print("Dumping PV list to \"{}\"...".format(
                            pv_dump_file))
                        try:
                            try:
                                # Redirect the stdout to the output file momentarily
                                original_stdout, sys.stdout = sys.stdout, f
                                self.epics.dump()
                            finally:
                                sys.stdout = original_stdout

                            print("Done!")
                        except:
                            # Capture error from epics.dump() if any
                            print("Errors were found during epics.dump()")

        # If no in server Mode, start the GUI
        if not server_mode:
            create_gui(self, title=windows_title)
        else:
            # Stop the server when Crtl+C is pressed
            print("")
            print("Running in server mode now. Press Ctrl+C to stop...")
            try:
                # Wait for Ctrl+C
                while True:
                    time.sleep(1)
            except KeyboardInterrupt:
                pass
Ejemplo n.º 8
0
    def __init__(self, ip_addr, config_file, server_mode, epics_prefix,\
        polling_en, comm_type, pcie_rssi_lane, stream_pv_size, stream_pv_type,\
        pv_dump_file, disable_bay0, disable_bay1, disable_gc, windows_title,\
        pcie_dev_rssi, pcie_dev_data):

        try:
            pyrogue.Root.__init__(self, name='AMCc', description='AMC Carrier')

            # File writer for streaming interfaces
            # DDR interface (TDEST 0x80 - 0x87)
            stm_data_writer = pyrogue.utilities.fileio.StreamWriter(name='streamDataWriter')
            self.add(stm_data_writer)
            # Streaming interface (TDEST 0xC0 - 0xC7)
            stm_interface_writer = pyrogue.utilities.fileio.StreamWriter(name='streamingInterface')
            self.add(stm_interface_writer)

            # Workaround to FpgaTopLelevel not supporting rssi = None
            if pcie_rssi_lane == None:
                pcie_rssi_lane = 0

            # Instantiate Fpga top level
            fpga = FpgaTopLevel(ipAddr=ip_addr,
                commType=comm_type,
                pcieRssiLink=pcie_rssi_lane,
                disableBay0=disable_bay0,
                disableBay1=disable_bay1)

            # Add devices
            self.add(fpga)

            # Create stream interfaces
            self.ddr_streams = []       # DDR streams


            # Our smurf2mce receiver
            # The data stream comes from TDEST 0xC1
            self.smurf2mce = MceTransmit.Smurf2MCE()
            self.smurf2mce.setDebug( False )

            # Check if we are using PCIe or Ethernet communication.
            if 'pcie-' in comm_type:
                # If we are suing PCIe communication, used AxiStreamDmas to get the DDR and streaming streams.

                # DDR streams. We are only using the first 2 channel of each AMC daughter card, i.e.
                # channels 0, 1, 4, 5.
                for i in [0, 1, 4, 5]:
                    self.ddr_streams.append(
                        rogue.hardware.axi.AxiStreamDma(pcie_dev_rssi,(pcie_rssi_lane*0x100 + 0x80 + i), True))

                # Streaming interface stream
                self.streaming_stream = \
                    rogue.hardware.axi.AxiStreamDma(pcie_dev_data,(pcie_rssi_lane*0x100 + 0xC1), True)

                # When PCIe communication is used, we connect the stream data directly to the receiver:
                # Stream -> smurf2mce receiver
                pyrogue.streamConnect(self.streaming_stream, self.smurf2mce)

            else:
                # If we are using Ethernet: DDR streams comes over the RSSI+packetizer channel, and
                # the streaming streams comes over a pure UDP channel.

                # DDR streams. The FpgaTopLevel class will defined a 'stream' interface exposing them.
                # We are only using the first 2 channel of each AMC daughter card, i.e. channels 0, 1, 4, 5.
                for i in [0, 1, 4, 5]:
                    self.ddr_streams.append(fpga.stream.application(0x80 + i))

                # Streaming interface stream. It comes over UDP, port 8195, without RSSI,
                # so we use an UDP Client receiver.
                self.streaming_stream = rogue.protocols.udp.Client(ip_addr, 8195, True)

                # When Ethernet communication is used, We use a FIFO between the stream data and the receiver:
                # Stream -> FIFO -> smurf2mce receiver
                self.smurf2mce_fifo = rogue.interfaces.stream.Fifo(100000,0,True)
                pyrogue.streamConnect(self.streaming_stream, self.smurf2mce_fifo)
                pyrogue.streamConnect(self.smurf2mce_fifo, self.smurf2mce)

                # Create a KeepAlive object and connect it to the UDP Client.
                # It is used to keep the UDP connection open. This in only needed when
                # using Ethernet communication, as the PCIe FW implements this functionality.
                self.keep_alive = KeepAlive()
                pyrogue.streamConnect(self.keep_alive, self.streaming_stream)
                # Start the KeepAlive thread
                self.keep_alive.start()

            # Add data streams (0-3) to file channels (0-3)
            for i in range(4):

                ## DDR streams
                pyrogue.streamConnect(self.ddr_streams[i],
                    stm_data_writer.getChannel(i))

            ## Streaming interface streams
            # We have already connected it to the smurf2mce receiver,
            # so we need to tapping it to the data writer.
            pyrogue.streamTap(self.streaming_stream, stm_interface_writer.getChannel(0))

            # Add Local variable to set the TesBias scale factor. The variable has a listener function
            # which is called when a new value is written to it.
            self.add(pyrogue.LocalVariable(
                name='TesBiasSF',
                description='Scale factor apply to the TesBias values before writing it to the MCE header',
                value=1.0,
                mode='RW'))
            self.TesBiasSF.addListener(self.send_test_bias_sf)

            # Look for the TesBias registers
            # TesBias register are located on
            # FpgaTopLevel.AppTop.AppCore.RtmCryoDet.RtmSpiMax
            # And their name is TesBiasDacDataRegCh[n], where x = [0:31]
            self.TestBiasVars = []
            self.TestBiasRegEx = re.compile('.*TesBiasDacDataRegCh\[(\d+)\]$')
            for var in self.FpgaTopLevel.AppTop.AppCore.RtmCryoDet.RtmSpiMax.variableList:
                m = self.TestBiasRegEx.match(var.name)
                if m:
                    reg_index = int(m[1]) - 1
                    if reg_index < 32:
                        print(f'Found TesBias register: {var.name}, with index {reg_index}')
                        self.TestBiasVars.append(var)

            # Check that we have all 32 TesBias registers
            if len(self.TestBiasVars) == 32:
                print(f'Found 32 TesBias registers. Assigning listener functions')
                # Add listener to the TesBias registers
                for var in self.TestBiasVars:
                    var.addListener(self.send_test_bias)
                # Prepare a buffer to holds the TesBias register values
                self.TesBiasValue = [0] * 32
            else:
                print(f'Error: {len(self.TestBiasVars)} TesBias register were found instead of 32. Aborting')

            # Run control for streaming interfaces
            self.add(pyrogue.RunControl(
                name='streamRunControl',
                description='Run controller',
                cmd=fpga.SwDaqMuxTrig,
                rates={
                    1:  '1 Hz',
                    10: '10 Hz',
                    30: '30 Hz'}))

            # lcaPut limits the maximun lenght of a string to 40 chars, as defined
            # in the EPICS R3.14 CA reference manual. This won't allowed to use the
            # command 'ReadConfig' with a long file path, which is usually the case.
            # This function is a workaround to that problem. Fomr matlab one can
            # just call this function without arguments an the function ReadConfig
            # will be called with a predefined file passed during startup
            # However, it can be usefull also win the GUI, so it is always added.
            self.config_file = config_file
            self.add(pyrogue.LocalCommand(
                name='setDefaults',
                description='Set default configuration',
                function=self.set_defaults_cmd))

            # If Garbage collection was disable, add this local variable to allow users
            # to manually run the garbage collection.
            if disable_gc:
                self.add(pyrogue.LocalCommand(
                    name='runGarbageCollection',
                    description='runGarbageCollection',
                    function=self.run_garbage_collection))

            self.add(pyrogue.LocalVariable(
                name='mcetransmitDebug',
                description='Enable mce transmit debug',
                mode='RW',
                value=False,
                localSet=lambda value: self.smurf2mce.setDebug(value),
                hidden=False))

            # Lost frame counter from smurf2mce
            self.add(pyrogue.LocalVariable(
                name='frameLossCnt',
                description='Lost frame Counter',
                mode='RO',
                value=0,
                localGet=self.smurf2mce.getFrameLossCnt,
                pollInterval=1,
                hidden=False))

            # Received frame counter from smurf2mce
            self.add(pyrogue.LocalVariable(
                name='frameRxCnt',
                description='Received frame Counter',
                mode='RO',
                value=0,
                localGet=self.smurf2mce.getFrameRxCnt,
                pollInterval=1,
                hidden=False))

            # Out-of-order frame counter from smurf2mce
            self.add(pyrogue.LocalVariable(
                name='frameOutOrderCnt',
                description='Number of time out-of-order frames are detected',
                mode='RO',
                value=0,
                localGet=self.smurf2mce.getFrameOutOrderCnt,
                pollInterval=1,
                hidden=False))

            # Bad frame counter
            self.add(pyrogue.LocalVariable(
                name='badFrameCnt',
                description='Number of lost frames due to a bad frame',
                mode='RO',
                value=0,
                localGet=self.smurf2mce.getBadFrameCnt,
                pollInterval=1,
                hidden=False))

            # Command to clear all the frame counters on smurf2mce
            self.add(pyrogue.LocalCommand(
                name='clearFrameCnt',
                description='Clear all the frame counters',
                function=self.smurf2mce.clearFrameCnt))

            # Start the root
            print("Starting rogue server")
            self.start(pollEn=polling_en)

            self.ReadAll()

            # Call the get() method on the tesBias variable to force the call to
            # send_test_bias and update the array in Smurf2MCE
            for var in self.TestBiasVars:
                var.get()

            # Call the get method on the tesBias variable to force the call to
            # send_tes_bias_sf and update the factor in Smurf2MCE
            self.TesBiasSF.get()

        except KeyboardInterrupt:
            print("Killing server creation...")
            super(LocalServer, self).stop()
            exit()

        # Show image build information
        try:
            print("")
            print("FPGA image build information:")
            print("===================================")
            print("BuildStamp              : {}"\
                .format(self.FpgaTopLevel.AmcCarrierCore.AxiVersion.BuildStamp.get()))
            print("FPGA Version            : 0x{:x}"\
                .format(self.FpgaTopLevel.AmcCarrierCore.AxiVersion.FpgaVersion.get()))
            print("Git hash                : 0x{:x}"\
                .format(self.FpgaTopLevel.AmcCarrierCore.AxiVersion.GitHash.get()))
        except AttributeError as attr_error:
            print("Attibute error: {}".format(attr_error))
        print("")

        # Start the EPICS server
        if epics_prefix:
            print("Starting EPICS server using prefix \"{}\"".format(epics_prefix))

            self.epics = pyrogue.protocols.epics.EpicsCaServer(base=epics_prefix, root=self)

            # PVs for stream data
            if stream_pv_size:

                print("Enabling stream data on PVs (buffer size = {} points, data type = {})"\
                    .format(stream_pv_size,stream_pv_type))

                self.stream_fifos  = []
                self.stream_slaves = []
                for i in range(4):
                    self.stream_slaves.append(self.epics.createSlave(name="AMCc:Stream{}".format(i),
                        maxSize=stream_pv_size, type=stream_pv_type))

                    # Calculate number of bytes needed on the fifo
                    if '16' in stream_pv_type:
                        fifo_size = stream_pv_size * 2
                    else:
                        fifo_size = stream_pv_size * 4

                    self.stream_fifos.append(rogue.interfaces.stream.Fifo(1000, fifo_size, True)) # changes
                    self.stream_fifos[i]._setSlave(self.stream_slaves[i])
                    pyrogue.streamTap(self.ddr_streams[i], self.stream_fifos[i])

            self.epics.start()

            # Dump the PV list to the specified file
            if pv_dump_file:
                try:
                    # Try to open the output file
                    f = open(pv_dump_file, "w")
                except IOError:
                    print("Could not open the PV dump file \"{}\"".format(pv_dump_file))
                else:
                    with f:
                        print("Dumping PV list to \"{}\"...".format(pv_dump_file))
                        try:
                            try:
                                # Redirect the stdout to the output file momentarily
                                original_stdout, sys.stdout = sys.stdout, f
                                self.epics.dump()
                            finally:
                                sys.stdout = original_stdout

                            print("Done!")
                        except:
                            # Capture error from epics.dump() if any
                            print("Errors were found during epics.dump()")

        # If no in server Mode, start the GUI
        if not server_mode:
            create_gui(self, title=windows_title)
        else:
            # Stop the server when Crtl+C is pressed
            print("")
            print("Running in server mode now. Press Ctrl+C to stop...")
            try:
                # Wait for Ctrl+C
                while True:
                    time.sleep(1)
            except KeyboardInterrupt:
                pass
Ejemplo n.º 9
0
top = feb.Top(
    ip          = args.ip,
    pollEn      = args.pollEn,
    initRead    = args.initRead,       
    loadYaml    = args.loadYaml,       
    defaultFile = args.defaultFile,       
    userYaml    = args.userYaml,       
    refClkSel   = args.refClkSel,       
)    

# Create the Event reader streaming interface
if (args.printEvents):
    eventReader = feb.PrintEventReader()

    # Connect the file reader to the event reader
    pr.streamTap(top.dataStream[0], eventReader) 

# Create Live Display
live_display_resets = []
if args.liveDisplay:
    for fpga_index in range( top.numEthDev ):
        # Create the fifo to ensure there is no back-pressure
        fifo = rogue.interfaces.stream.Fifo(100, 0, True)
        # Connect the device reader ---> fifo
        pr.streamTap(top.dataStream[fpga_index], fifo) 
        # Create the pixelreader streaming interface
        event_display = feb.onlineEventDisplay(
                plot_title='FPGA ' + str(fpga_index),
                submitDir='display_snapshots',
                font_size=4,
                fig_size=(10,6),
Ejemplo n.º 10
0
    def __init__(self):

        pyrogue.Root.__init__(self, 'evalBoard', 'Evaluation Board')

        # File writer
        dataWriter = pyrogue.utilities.fileio.StreamWriter('dataWriter')
        self.add(dataWriter)

        # Create the PGP interfaces
        pgpVc0 = rogue.hardware.pgp.PgpCard('/dev/pgpcard_0', 0,
                                            0)  # Registers
        pgpVc1 = rogue.hardware.pgp.PgpCard('/dev/pgpcard_0', 0, 1)  # Data
        pgpVc3 = rogue.hardware.pgp.PgpCard('/dev/pgpcard_0', 0,
                                            3)  # Microblaze

        print("")
        print("PGP Card Version: %x" % (pgpVc0.getInfo().version))

        # Create and Connect SRP to VC0
        srp = rogue.protocols.srp.SrpV0()
        pyrogue.streamConnectBiDir(pgpVc0, srp)

        # Add configuration stream to file as channel 0
        pyrogue.streamConnect(self, dataWriter.getChannel(0x0))

        # Add data stream to file as channel 1
        pyrogue.streamConnect(pgpVc1, dataWriter.getChannel(0x1))

        ## Add microblaze console stream to file as channel 2
        pyrogue.streamConnect(pgpVc3, dataWriter.getChannel(0x2))

        # PRBS Receiver as secdonary receiver for VC1
        prbsRx = pyrogue.utilities.prbs.PrbsRx('prbsRx')
        pyrogue.streamTap(pgpVc1, prbsRx)
        self.add(prbsRx)

        # Microblaze console monitor add secondary tap
        mbcon = MbDebug()
        pyrogue.streamTap(pgpVc3, mbcon)

        # Add Devices
        self.add(surf.axi.AxiVersion(memBase=srp, offset=0x0))
        self.add(surf.protocols.ssi.SsiPrbsTx(memBase=srp, offset=0x30000))

        self.smem = pyrogue.smem.SMemControl(group='rogueTest', root=self)

        # Run control
        self.add(
            pyrogue.RunControl(name='runControl',
                               rates={
                                   1: '1 Hz',
                                   10: '10 Hz',
                                   30: '30 Hz'
                               }))
        #cmd=self.SsiPrbsTx.oneShot()))

        # Export remote objects
        self.start(pyroGroup='rogueTest')

        # Create epics node
        pvMap = {
            'evalBoard.AxiVersion.UpTimeCnt': 'testCnt',
            'evalBoard.AxiVersion.ScratchPad': 'testPad'
        }
        pvMap = None  # Comment out to enable map
        self.epics = pyrogue.epics.EpicsCaServer(base='rogueTest',
                                                 root=self,
                                                 pvMap=pvMap)
        self.epics.start()