1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
32 33 34
35
36 import ti.sdo.utils.MultiProc;
37 import ti.sdo.ipc.interfaces.INotifyDriver;
38 import ti.sdo.ipc.notifyDrivers.IInterrupt;
39 import ti.sdo.ipc.Notify;
40
41 import xdc.rov.ViewInfo;
42
43 /*!
44 * ======== NotifyDriverCirc ========
45 * A shared memory driver using circular buffer for the Notify Module.
46 *
47 * This is a {@link ti.sdo.ipc.Notify} driver that utilizes shared memory
48 * and inter-processor hardware interrupts for notification between cores.
49 * This driver supports caching.
50 *
51 * This driver is designed to work with a variety of devices, each with
52 * distinct interrupt mechanisms. Therefore, this module needs to be plugged
53 * with an appropriate module that implements the {@link IInterrupt} interface
54 * for a given device.
55 *
56 * The driver utilizes shared memory in the manner indicated by the following
57 * diagram.
58 *
59 * @p(code)
60 *
61 * NOTE: Processors '0' and '1' correspond to the processors with lower and
62 * higher MultiProc ids, respectively
63 *
64 * sharedAddr -> --------------------------- bytes
65 * | eventEntry0 (0) | 8
66 * | eventEntry1 (0) | 8
67 * | ... |
68 * | eventEntry15 (0) | 8
69 * | [align to cache size] |
70 * |-------------------------|
71 * | eventEntry16 (0) | 8
72 * | eventEntry17 (0) | 8
73 * | ... |
74 * | eventEntry31 (0) | 8
75 * | [align to cache size] |
76 * |-------------------------|
77 * | putWriteIndex (0) | 4
78 * | [align to cache size] |
79 * |-------------------------|
80 * | putReadIndex (0) | 4
81 * | [align to cache size] |
82 * |-------------------------|
83 * | eventEntry0 (1) | 8
84 * | eventEntry1 (1) | 8
85 * | ... |
86 * | eventEntry15 (1) | 8
87 * | [align to cache size] |
88 * |-------------------------|
89 * | eventEntry16 (1) | 8
90 * | eventEntry17 (1) | 8
91 * | ... |
92 * | eventEntry31 (1) | 8
93 * | [align to cache size] |
94 * |-------------------------|
95 * | getWriteIndex (1) | 4
96 * | [align to cache size] |
97 * |-------------------------|
98 * | getReadIndex (1) | 4
99 * | [align to cache size] |
100 * |-------------------------|
101 *
102 *
103 * Legend:
104 * (0), (1) : Memory that belongs to the proc with lower and higher
105 * MultiProc.id, respectively
106 * |----| : Cache line boundary
107 *
108 * @p
109 */
110
111 @InstanceFinalize
112
113 module NotifyDriverCirc inherits ti.sdo.ipc.interfaces.INotifyDriver
114 {
115 /*! @_nodoc */
116 metaonly struct BasicView {
117 String remoteProcName;
118 Bool cacheEnabled;
119 UInt bufSize;
120 UInt spinCount;
121 UInt maxSpinWait;
122 }
123
124 /*! @_nodoc */
125 metaonly struct EventDataView {
126 UInt index;
127 String buffer;
128 Ptr addr;
129 UInt eventId;
130 Ptr payload;
131 }
132
133 /*!
134 * ======== rovViewInfo ========
135 */
136 @Facet
137 metaonly config ViewInfo.Instance rovViewInfo =
138 ViewInfo.create({
139 viewMap: [
140 ['Basic',
141 {
142 type: ViewInfo.INSTANCE,
143 viewInitFxn: 'viewInitBasic',
144 structName: 'BasicView'
145 }
146 ],
147 ['Events',
148 {
149 type: ViewInfo.INSTANCE_DATA,
150 viewInitFxn: 'viewInitData',
151 structName: 'EventDataView'
152 }
153 ],
154 ]
155 });
156
157
158 /*! @_nodoc
159 * IInterrupt proxy that handles interrupts between multiple CPU cores
160 */
161 proxy InterruptProxy inherits IInterrupt;
162
163 /*!
164 * ======== enableStats ========
165 * Enable statistics for sending an event
166 *
167 * If this parameter is to 'TRUE' and 'waitClear' is also set to
168 * TRUE when calling (@link #sendEvent(), then the module keeps
169 * track of the number of times the processor spins waiting for
170 * an empty slot and the max amount of time it waits.
171 */
172 config Bool enableStats = false;
173
174 /*!
175 * ======== numMsgs ========
176 * The number of messages or slots in the circular buffer
177 *
178 * This is use to determine the size of the put and get buffers.
179 * Each eventEntry is two 32bits wide, therefore the total size
180 * of each circular buffer is [numMsgs * sizeof(eventEntry)].
181 * The total size of each buffer must be a multiple of the
182 * the cache line size. For example, if the cacheLineSize = 128
183 * then numMsgs could be 16, 32, etc...
184 */
185 config UInt numMsgs = 32;
186
187 /*!
188 * ======== sharedMemReq ========
189 * Amount of shared memory required for creation of each instance
190 *
191 * @param(params) Pointer to parameters that will be used in the
192 * create
193 *
194 * @a(returns) Number of MAUs in shared memory needed to create
195 * the instance.
196 */
197 SizeT sharedMemReq(const Params *params);
198
199 instance:
200
201 /*!
202 * ======== sharedAddr ========
203 * Address in shared memory where this instance will be placed
204 *
205 * Use {@link #sharedMemReq} to determine the amount of shared memory
206 * required.
207 */
208 config Ptr sharedAddr = null;
209
210 /*!
211 * ======== cacheEnabled ========
212 * Whether cache operations will be performed
213 *
214 * If it is known that no cache operations are needed for this instance
215 * set this flag to FALSE. If {@link #sharedAddr} lies within a shared
216 * region and the cache enabled setting for the region is FALSE,
217 * then the value specified here will be overriden to FALSE.
218 */
219 config Bool cacheEnabled = true;
220
221 /*!
222 * ======== cacheLineSize ========
223 * The cache line size of the shared memory
224 *
225 * This value should be configured
226 */
227 config SizeT cacheLineSize = 128;
228
229 /*!
230 * ======== remoteProcId ========
231 * The MultiProc ID corresponding to the remote processor
232 *
233 * This parameter must be set for every device. The
234 * {@link ti.sdo.utils.MultiProc#getId} call can be used to obtain
235 * a MultiProc id given the remote processor's name.
236 */
237 config UInt16 remoteProcId = MultiProc.INVALIDID;
238
239 /*!
240 * ======== intVectorId ========
241 * Interrupt vector ID to be used by the driver.
242 *
243 * This parameter is only used by C64x+ targets
244 */
245 config UInt intVectorId = ~1u;
246
247 /*!
248 * ======== localIntId ========
249 * Local interrupt ID for interrupt line
250 *
251 * For devices that support multiple inter-processor interrupt lines, this
252 * configuration parameter allows selecting a specific line to use for
253 * receiving an interrupt. The value specified here corresponds to the
254 * incoming interrupt line on the local processor.
255 *
256 * If this configuration is not set, a default interrupt id is
257 * typically chosen.
258 */
259 config UInt localIntId = -1u;
260
261 /*!
262 * ======== remoteIntId ========
263 * Remote interrupt ID for interrupt line
264 *
265 * For devices that support multiple inter-processor interrupt lines, this
266 * configuration parameter allows selecting a specific line to use for
267 * receiving an interrupt. The value specified here corresponds to the
268 * incoming interrupt line on the remote processor.
269 *
270 * If this configuration is not set, a default interrupt id is
271 * typically chosen.
272 */
273 config UInt remoteIntId = -1u;
274
275 internal:
276
277 /*! The max index set to (numMsgs - 1) */
278 config UInt maxIndex;
279
280 /*!
281 * The modulo index value. Set to (numMsgs / 4).
282 * Used in the isr for doing cache_wb of readIndex.
283 */
284 config UInt modIndex;
285
286 /*!
287 * Plugs the interrupt and executes the callback functions according
288 * to event priority
289 */
290 Void isr(UArg arg);
291
292 /*!
293 * Structure for each event. This struct is placed in shared memory.
294 */
295 struct EventEntry {
296 volatile Bits32 eventid;
297 volatile Bits32 payload;
298 }
299
300 /*! Instance state structure */
301 struct Instance_State {
302 EventEntry *putBuffer;
303 Bits32 *putReadIndex;
304 Bits32 *putWriteIndex;
305 EventEntry *getBuffer;
306 Bits32 *getReadIndex;
307 Bits32 *getWriteIndex;
308 Bits32 evtRegMask;
309 SizeT opCacheSize;
310 UInt32 spinCount;
311 UInt32 spinWaitTime;
312 Notify.Handle notifyHandle;
313 IInterrupt.IntInfo intInfo;
314 UInt16 remoteProcId;
315 Bool cacheEnabled;
316 }
317 }
318 319 320
321