def __init__(self): pyrogue.Root.__init__(self, name='dummyTree', description="Dummy tree for example") # Use a memory space emulator sim = pyrogue.interfaces.simulation.MemEmulate() # Add Device self.add(surf.axi.AxiVersion(memBase=sim, offset=0x0)) # File writer example self.add(pyrogue.DataWriter()) self.add(pyrogue.RunControl()) self.test = TestClass() pyrogue.streamConnect(self, self.test) # Start the tree with pyrogue server, internal nameserver, default interface # Set pyroHost to the address of a network interface to specify which nework to run on # set pyroNs to the address of a standalone nameserver (startPyrorNs.py) self.start(timeout=2.0, pyroGroup='testGroup', pyroAddr="127.0.0.1", pyroNsAddr=None)
def __init__(self): pyrogue.Root.__init__(self,name='evalBoard',description='Evaluation Board') # File writer dataWriter = pyrogue.utilities.fileio.StreamWriter(name='dataWriter') self.add(dataWriter) # Create the PGP interfaces udp = pyrogue.protocols.UdpRssiPack(host='192.168.2.194',port=8192,size=1400) # Create and Connect SRP to VC0 srp = rogue.protocols.srp.SrpV3() pyrogue.streamConnectBiDir(srp,udp.application(0)) # Add configuration stream to file as channel 0 pyrogue.streamConnect(self,dataWriter.getChannel(0x0)) pyrogue.streamConnect(udp.application(1),dataWriter.getChannel(0x1)) # PRBS Receiver as secdonary receiver for VC1 #prbsRx = pyrogue.utilities.prbs.PrbsRx('prbsRx') #pyrogue.streamTap(udp.application(1),prbsRx) #self.add(prbsRx) # Add Devices self.add(surf.axi.AxiVersion(memBase=srp,offset=0x0,expand=False)) #self.add(surf.protocols.ssi.SsiPrbsTx(memBase=srp,offset=0x40000)) self.add(pyrogue.LocalVariable(name='list',value=([0] * 10))) 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(pollEn=True,pyroGroup='rogueTest',pyroHost='134.79.229.11',pyroNs='134.79.229.11') #self.start(pollEn=True,pyroGroup='rogueTest',pyroHost='134.79.229.11') #self.start(pollEn=True,pyroGroup='rogueTest') self.start(pollEn=True,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() self.mysql = pyrogue.mysql.MysqlGw(dbHost='localhost',dbName='rogue',dbUser='******',dbPass='******',root=self) self.mysql.start()
def __init__(self): pyrogue.Root.__init__(self, 'evalBoard', 'Evaluation Board') # File writer dataWriter = pyrogue.utilities.fileio.StreamWriter('dataWriter') self.add(dataWriter) # Create and Connect SRP to VC0 srp = pyrogue.simulation.MemEmulate() # PRBS Receiver as secdonary receiver for VC1 prbsRx = pyrogue.utilities.prbs.PrbsRx('prbsRx') self.add(prbsRx) # Add Devices self.add(surf.axi.AxiVersion(memBase=srp, offset=0x0)) self.add(surf.protocols.ssi.SsiPrbsTx(memBase=srp, offset=0x30000)) self.testBlock = pyrogue.RawBlock(srp) self.smem = pyrogue.smem.SMemControl('rogueTest', self) # Run control self.add( pyrogue.RunControl('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('rogueTest', self, pvMap) self.epics.start()
def __init__(self): self._scnt = 0 self._sdata = np.zeros(100, dtype=np.float64) pyrogue.Root.__init__(self, name='dummyTree', description="Dummy tree for example", timeout=2.0, pollEn=True, serverPort=0) # Use a memory space emulator sim = rogue.interfaces.memory.Emulate(4, 0x1000) sim.setName("SimSlave") self.addInterface(sim) # Add Device self.add( test_device.AxiVersion(memBase=sim, guiGroup='TestGroup', offset=0x0)) self.add(test_large.TestLarge(guiGroup='TestGroup')) # Add Data Writer self._prbsTx = pyrogue.utilities.prbs.PrbsTx() self.add(self._prbsTx) self._fw = pyrogue.utilities.fileio.StreamWriter() self.add(self._fw) self._prbsTx >> self._fw.getChannel(0) # Add Data Receiver drx = pyrogue.DataReceiver() self._prbsTx >> drx self.add(drx) # Add Run Control self.add(pyrogue.RunControl()) # Add process controller p = pyrogue.Process() p.add(pyrogue.LocalVariable(name='Test1', value='')) p.add(pyrogue.LocalVariable(name='Test2', value='')) self.add(p) #self.AxiVersion.AlarmTest.addToGroup('NoServe') self.add( pyrogue.LocalVariable(name='TestPlot', mode='RO', pollInterval=1.0, localGet=self._mySin, minimum=-1.0, maximum=1.0, disp='{:1.2f}', value=0.0)) self.add( pyrogue.LocalVariable(name='TestXAxis', mode='RO', pollInterval=1.0, localGet=self._myXAxis, disp='{:1.2f}', value=1.0)) self.add( pyrogue.LocalVariable(name='TestArray', mode='RO', pollInterval=1.0, localGet=self._myArray, disp='{:1.2f}')) #value = np.zeros(100,dtype=np.float64))) #self.add(pyrogue.LocalVariable( # name = 'Test/Slash', # mode = 'RW', # value = '')) #self.add(pyrogue.LocalVariable( # name = 'Test.Dot', # mode = 'RW', # value = '')) #self.add(pyrogue.LocalVariable( # name = 'Test\BackSlash', # mode = 'RW', # value = '')) #self.add(pyrogue.LocalVariable( # name = 'Test&And', # mode = 'RW', # value = '')) #self.rudpServer = pyrogue.protocols.UdpRssiPack( # name = 'UdpServer', # port = 8192, # jumbo = True, # server = True, # expand = False, # ) #self.add(self.rudpServer) # Create the ETH interface @ IP Address = args.dev #self.rudpClient = pyrogue.protocols.UdpRssiPack( # name = 'UdpClient', # host = "127.0.0.1", # port = 8192, # jumbo = True, # expand = False, # ) #self.add(self.rudpClient) #self.prbsTx = pyrogue.utilities.prbs.PrbsTx() #self.add(self.prbsTx) #pyrogue.streamConnect(self.prbsTx,self.rudpClient.application(0)) if args.epics3: self._epics = pyrogue.protocols.epics.EpicsCaServer(base="test", root=self) self.addProtocol(self._epics) if args.epics4: self._epics4 = pyrogue.protocols.epicsV4.EpicsPvServer( base="test", root=self, incGroups=None, excGroups=None) self.addProtocol(self._epics4)
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
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))
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
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
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()