DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
master.py
Go to the documentation of this file.
1from __future__ import print_function
2
3import click
4import time
5import collections
6
7import timing.cli.toolbox as toolbox
8import timing.common.definitions as defs
9
10from .factory import ShellFactory, ShellContext
11from click import echo, style, secho
12from timing.core import SI534xSlave, I2CExpanderSlave, DACSlave
13
14from timing.common.definitions import kBoardSim, kBoardFMC, kBoardPC059, kBoardMicrozed, kBoardTLU
15from timing.common.definitions import kCarrierEnclustraA35, kCarrierKC705, kCarrierMicrozed
16from timing.common.definitions import kDesignOverlord, kDesignMaster, kDesignOuroboros, kDesignOuroborosSim, kDesignEndpoint, kDesignFanout
17from timing.common.definitions import kBoardNameMap, kCarrierNameMap, kDesignNameMap
18
19from os.path import join, expandvars, basename
20
21# ------------------------------------------------------------------------------
22class MasterShell(object):
23
24 kFWMajorRequired = 5
25
26 def __init__(self):
27
28 lMstCtx = ShellContext()
29
30 # Tol-level nodes
31 lMaster = self.device.getNode('master')
32 lExtTrigNode = self.device.getNode('trig_rx')
33 lIO = self.device.getNode('io')
34
35 lVersion = lMaster.getNode('global.version').read()
36 lGenerics = toolbox.readSubNodes(lMaster.getNode('global.config'), False)
37 self.device.dispatch()
38
39 lMajor = (lVersion >> 16) & 0xff
40 lMinor = (lVersion >> 8) & 0xff
41 lPatch = (lVersion >> 0) & 0xff
42
43 lMstCtx.version = (lVersion.value(), lMajor, lMinor, lPatch)
44 lMstCtx.generics = {k:v.value() for k,v in lGenerics.items()}
45
47 secho('ERROR: Incompatible master firmware version. Found {}, required {}'.format(hex(lMajor), hex(kMasterFWMajorRequired)), fg='red')
48 raise click.Abort()
49
50 # store references in context
51 lMstCtx.masterNode = lMaster
52 lMstCtx.globalNode = lMaster.getNode('global')
53 lMstCtx.aCmdNode = lMaster.getNode('acmd')
54 lMstCtx.echoNode = lMaster.getNode('echo')
55 lMstCtx.extTrigNode = lExtTrigNode
56
57 self.masterCtx = lMstCtx
58 self.ioNode = lIO
59 # ------------------------------------------------------------------------------
60
61
62 # ------------------------------------------------------------------------------
63 def identify(self):
64 echo("design '{}' on board '{}' on carrier '{}'".format(
65 style(kDesignNameMap[self.info.designType], fg='blue'),
66 style(kBoardNameMap[self.info.boardType], fg='blue'),
67 style(kCarrierNameMap[self.info.carrierType], fg='blue')
68 ))
69 echo("Master FW rev: {}, partitions: {}, channels: {}".format(
70 style(hex(self.masterCtx.version[0]), fg='cyan'),
71 style(str(self.masterCtx.generics['n_part']), fg='cyan'),
72 style(str(self.masterCtx.generics['n_chan']), fg='cyan'),
73 ))
74 # ------------------------------------------------------------------------------
75
76
77 # ------------------------------------------------------------------------------
78 def initPartitions(self):
79
80 for pid in range(self.masterCtx.generics['n_part']):
81
82 lPartNode = self.masterCtx.masterNode.getNode('partition{}'.format(pid))
83
84 lPartNode.reset();
85 lPartNode.configure(0x0, False);
86 lPartNode.enable();
87 # ------------------------------------------------------------------------------
88
89 # ------------------------------------------------------------------------------
90 def synctime(self):
91
92 lMaster = self.masterCtx.masterNode
93 lIO = self.ioNode
94
95 firmmware_frequency_hz = lIO.read_firmware_frequency()
96
97 lTStampReadNode = lMaster.getNode('tstamp.ctr.val')
98 lTStampWriteNode = lMaster.getNode('tstamp.ctr.set')
99
100 lTimeStamp = lTStampReadNode.readBlock(2)
101 lTStampReadNode.getClient().dispatch()
102
103 lTime = int(lTimeStamp[0]) + (int(lTimeStamp[1]) << 32)
104 secho('Old Timestamp {}'.format(hex(lTime)), fg='cyan')
105
106 # Take the local time and split it up
107 lNow = int(time.time()*firmmware_frequency_hz)
108 lNowH = (lNow >> 32) & ((1<<32)-1)
109 lNowL = (lNow >> 0) & ((1<<32)-1)
110
111 # push it on the board
112 lTStampWriteNode.writeBlock([lNowL, lNowH])
113 lTStampWriteNode.getClient().dispatch()
114
115 # Read it back
116 lTimeStamp = lTStampReadNode.readBlock(2)
117 lTStampReadNode.getClient().dispatch()
118 x = time.time()
119 lTime = (int(lTimeStamp[1]) << 32) + int(lTimeStamp[0])
120
121 secho('New Timestamp {}'.format(hex(lTime)), fg='cyan')
122
123 print(float(lTime)/firmmware_frequency_hz - x)
124
125 echo ("DeltaT {}".format(toolbox.formatTStamp(lTimeStamp)))
126 # ------------------------------------------------------------------------------
127
128
129
130 # ------------------------------------------------------------------------------
131 def enableEptAndWaitForReady( self, aTimeout=0.5 ):
132
133 lGlobal = self.masterCtx.globalNode
134
135 lGlobal.getNode('csr.ctrl.ep_en').write(0x0)
136 lGlobal.getClient().dispatch()
137 lGlobal.getNode('csr.ctrl.ep_en').write(0x1)
138 lGlobal.getClient().dispatch()
139
140 # Wait for the endpoint to be happy
141 lTOutStart = time.time()
142 # secho ('Return EPT reset, waiting for lock', fg='cyan')
143 while time.time() < lTOutStart + aTimeout:
144 time.sleep(0.1)
145
146 lEptRdy = lGlobal.getNode('csr.stat.ep_rdy').read()
147 lEptStat = lGlobal.getNode('csr.stat.ep_stat').read()
148 lEptFDel = lGlobal.getNode('csr.stat.ep_fdel').read()
149 lEptEdge = lGlobal.getNode('csr.stat.ep_edge').read()
150 lGlobal.getClient().dispatch()
151
152 if int(lEptRdy) == 1:
153 # secho('Endpoint locked: state={}'.format(hex(lEptStat)), fg='blue')
154 break
155 if int(lEptRdy) == 0:
156 raise RuntimeError('Failed to bring up the RTT endpoint. Current state {}'.format(hex(lEptStat)))
157 # else:
158 # secho ('Endpoint locked', fg='cyan')
159 return (lEptFDel.value(), lEptEdge.value())
160 # ------------------------------------------------------------------------------
161
162
163 # ------------------------------------------------------------------------------
164 def send_echo_and_measure_delay( self, aTimeout=0.5 ):
165
166 lEcho = self.masterCtx.echoNode
167
168 lEcho.getNode('csr.ctrl.go').write(0x1)
169 lEcho.getClient().dispatch()
170 lTOutStart = time.time()
171 while time.time() < lTOutStart + aTimeout:
172 time.sleep(0.1)
173
174 lDone = lEcho.getNode('csr.stat.rx_done').read()
175 lEcho.getClient().dispatch()
176
177 if int(lDone) == 1:
178 break
179 if not int(lDone):
180 raise RuntimeError("Timeout while waiting for echo")
181
182 lTimeRxL = lEcho.getNode('csr.rx_l').read()
183 lTimeRxH = lEcho.getNode('csr.rx_h').read()
184 lTimeTxL = lEcho.getNode('csr.tx_l').read()
185 lTimeTxH = lEcho.getNode('csr.tx_h').read()
186 lEcho.getClient().dispatch()
187
188 lTimeRx = (lTimeRxH << 32) + lTimeRxL
189 lTimeTx = (lTimeTxH << 32) + lTimeTxL
190
191 return lTimeTx, lTimeRx
192 # ------------------------------------------------------------------------------
193
194
195 # ------------------------------------------------------------------------------
196 def pushDelay( self, aAddr, aCDel):
197
198 lACmd = self.masterCtx.aCmdNode
199
200 # Keep the TX sfp on
201 toolbox.resetSubNodes(lACmd.getNode('csr.ctrl'), dispatch=False)
202 lACmd.getNode('csr.ctrl.tx_en').write(0x1)
203 lACmd.getNode('csr.ctrl.addr').write(aAddr)
204 lACmd.getNode('csr.ctrl.cdel').write(aCDel)
205 lACmd.getNode('csr.ctrl.update').write(0x1)
206 lACmd.getNode('csr.ctrl.go').write(0x1)
207 lACmd.getNode('csr.ctrl.go').write(0x0)
208 lACmd.getClient().dispatch()
209 secho('Coarse delay {} applied'.format(aCDel), fg='green')
210 # ------------------------------------------------------------------------------
211
212
213 # ------------------------------------------------------------------------------
214 def enableEndpointSFP(self, aAddr, aEnable=1):
215
216 lACmd = self.masterCtx.aCmdNode
217
218 toolbox.resetSubNodes(lACmd.getNode('csr.ctrl'))
219 lACmd.getNode('csr.ctrl.addr').write(aAddr)
220 lACmd.getNode('csr.ctrl.tx_en').write(aEnable)
221 lACmd.getNode('csr.ctrl.go').write(0x1)
222 lACmd.getNode('csr.ctrl.go').write(0x0)
223 lACmd.getClient().dispatch()
224 # ------------------------------------------------------------------------------
225
226
227# ------------------------------------------------------------------------------
228
229ShellFactory.registerBoard(kDesignOverlord, MasterShell)
230
231# ------------------------------------------------------------------------------
232
enableEptAndWaitForReady(self, aTimeout=0.5)
Definition master.py:131
enableEndpointSFP(self, aAddr, aEnable=1)
Definition master.py:214
send_echo_and_measure_delay(self, aTimeout=0.5)
Definition master.py:164
pushDelay(self, aAddr, aCDel)
Definition master.py:196