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 37 38 39 40 41 42 43 44 45 46 47
48
49 import xdc.runtime.Error;
50 import ti.sdo.utils.MultiProc;
51 import ti.sdo.ipc.interfaces.INotifyDriver;
52 import ti.sdo.ipc.notifyDrivers.IInterrupt;
53 import ti.sdo.ipc.Notify;
54
55 import xdc.rov.ViewInfo;
56
57 /*!
58 * ======== NotifyDriverShm ========
59 * A shared memory driver for the Notify Module.
60 *
61 * This is a {@link ti.sdo.ipc.Notify} driver that utilizes shared memory
62 * and inter-processor hardware interrupts for notification between cores.
63 * This driver supports caching and currently expects a cache line size of 128
64 * Bytes. Event priorities are supported and correspond to event numbers used
65 * to register the events.
66 *
67 * This driver is designed to work with a variety of devices, each with
68 * distinct interrupt mechanisms. Therefore, this module needs to be plugged
69 * with an appropriate module that implements the {@link IInterrupt} interface
70 * for a given device.
71 *
72 * The driver utilizes shared memory in the manner indicated by the following
73 * diagram.
74 *
75 * @p(code)
76 *
77 * NOTE: Processors '0' and '1' correspond to the processors with lower and
78 * higher MultiProc ids, respectively
79 *
80 * sharedAddr -> --------------------------- bytes
81 * | recvInitStatus (0) | 4 -\
82 * | sendInitStatus (0) | 4 |= sizeof(ProcCtrl)
83 * | eventRegMask (0) | 4 |
84 * | eventEnableMask (0) | 4 -/
85 * | [PADDING] (if needed) |
86 * |-------------------------|
87 * | recvInitStatus (1) | 4
88 * | sendInitStatus (1) | 4
89 * | eventRegMask (1) | 4
90 * | eventEnableMask (1) | 4
91 * | [PADDING] (if needed) |
92 * |-------------------------|
93 * | eventEntry_0 (0) | 12 -> sizeof(EventEntry)
94 * | [PADDING] (if needed) |
95 * |-------------------------|
96 * | eventEntry_1 (0) | 12
97 * | [PADDING] (if needed) |
98 * |-------------------------|
99 * ... ...
100 * |-------------------------|
101 * | eventEntry_N (0) | 12
102 * | [PADDING] (if needed) |
103 * |-------------------------|
104 * | eventEntry_0 (1) | 12
105 * | [PADDING] (if needed) |
106 * |-------------------------|
107 * | eventEntry_1 (1) | 12
108 * | [PADDING] (if needed) |
109 * |-------------------------|
110 * ... ...
111 * |-------------------------|
112 * | eventEntry_N (1) | 12
113 * | [PADDING] (if needed) |
114 * |-------------------------|
115 *
116 *
117 * Legend:
118 * (0), (1) : Memory that belongs to the proc with lower and higher
119 * MultiProc.id, respectively
120 * |----| : Cache line boundary
121 * N : Notify_numEvents - 1
122 *
123 * @p
124 */
125
126 @InstanceInitError
127 @InstanceFinalize
128
129 module NotifyDriverShm inherits ti.sdo.ipc.interfaces.INotifyDriver
130 {
131 /*! @_nodoc */
132 metaonly struct BasicView {
133 String remoteProcName;
134 Bool cacheEnabled;
135 }
136
137 /*! @_nodoc */
138 metaonly struct EventDataView {
139 UInt eventId;
140 String procName;
141 Bool enabled;
142 Bool flagged;
143 Ptr payload;
144 }
145
146 /*!
147 * ======== rovViewInfo ========
148 */
149 @Facet
150 metaonly config ViewInfo.Instance rovViewInfo =
151 ViewInfo.create({
152 viewMap: [
153 ['Basic',
154 {
155 type: ViewInfo.INSTANCE,
156 viewInitFxn: 'viewInitBasic',
157 structName: 'BasicView'
158 }
159 ],
160 ['Events',
161 {
162 type: ViewInfo.INSTANCE_DATA,
163 viewInitFxn: 'viewInitData',
164 structName: 'EventDataView'
165 }
166 ],
167 ]
168 });
169
170
171 /*! @_nodoc
172 * IInterrupt proxy that handles interrupts between multiple CPU cores
173 */
174 proxy InterruptProxy inherits IInterrupt;
175
176 /*!
177 * ======== sharedMemReq ========
178 * Amount of shared memory required for creation of each instance
179 *
180 * @param(params) Pointer to parameters that will be used in the
181 * create
182 *
183 * @a(returns) Number of MAUs in shared memory needed to create
184 * the instance.
185 */
186 SizeT sharedMemReq(const Params *params);
187
188 instance:
189
190 /*!
191 * ======== sharedAddr ========
192 * Address in shared memory where this instance will be placed
193 *
194 * Use {@link #sharedMemReq} to determine the amount of shared memory
195 * required.
196 */
197 config Ptr sharedAddr = null;
198
199 /*!
200 * ======== cacheEnabled ========
201 * Whether cache operations will be performed
202 *
203 * If it is known that no cache operations are needed for this instance
204 * set this flag to FALSE. If {@link #sharedAddr} lies within a shared
205 * region and the cache enabled setting for the region is FALSE,
206 * then the value specified here will be overriden to FALSE.
207 */
208 config Bool cacheEnabled = true;
209
210 /*!
211 * ======== cacheLineSize ========
212 * The cache line size of the shared memory
213 *
214 * This value should be configured
215 */
216 config SizeT cacheLineSize = 128;
217
218 /*!
219 * ======== remoteProcId ========
220 * The MultiProc ID corresponding to the remote processor
221 *
222 * This parameter must be set for every device. The
223 * {@link ti.sdo.utils.MultiProc#getId} call can be used to obtain
224 * a MultiProc id given the remote processor's name.
225 */
226 config UInt16 remoteProcId = MultiProc.INVALIDID;
227
228 /*!
229 * ======== intVectorId ========
230 * Interrupt vector ID to be used by the driver.
231 *
232 * This parameter is only used by C64x+ targets
233 */
234 config UInt intVectorId = ~1u;
235
236 /*!
237 * ======== localIntId ========
238 * Local interrupt ID for interrupt line
239 *
240 * For devices that support multiple inter-processor interrupt lines, this
241 * configuration parameter allows selecting a specific line to use for
242 * receiving an interrupt. The value specified here corresponds to the
243 * incoming interrupt line on the local processor.
244 *
245 * If this configuration is not set, a default interrupt id is
246 * typically chosen.
247 */
248 config UInt localIntId = -1u;
249
250 /*!
251 * ======== remoteIntId ========
252 * Remote interrupt ID for interrupt line
253 *
254 * For devices that support multiple inter-processor interrupt lines, this
255 * configuration parameter allows selecting a specific line to use for
256 * receiving an interrupt. The value specified here corresponds to the
257 * incoming interrupt line on the remote processor.
258 *
259 * If this configuration is not set, a default interrupt id is
260 * typically chosen.
261 */
262 config UInt remoteIntId = -1u;
263
264 internal:
265
266 /*! Flag an event up/down in shared memory */
267 const UInt16 DOWN = 0;
268 const UInt16 UP = 1;
269
270 /*! Initialization stamp */
271 const UInt32 INIT_STAMP = 0xA9C8B7D6;
272
273 /*!
274 * Plugs the interrupt and executes the callback functions according
275 * to event priority
276 */
277 Void isr(UArg arg);
278
279 /*!
280 * Used to flag a remote event and determine if a local event has been
281 * flagged. This struct is placed in shared memory.
282 */
283 struct EventEntry {
284 volatile Bits32 flag;
285 volatile Bits32 payload;
286 volatile Bits32 reserved;
287
288 }
289
290 /*!
291 * NotifyDriverShm state for a single processor in shared memory.
292 * Only the processor that owns this memory may write to it.
293 * However, the contents may be read by both processors.
294 *
295 * Two of these structs are place at the base of shared memory. Slots
296 * [0] and [1] are respectively assigned to the processors with the
297 * lower and higher MultiProc ids.
298 *
299 * Constraints: sizeof(NotifyDriverShm_ProcCtrl) must be a power of two
300 * and must be greater than sizeof(NotifyDriverShm_EventEntry)
301 */
302 struct ProcCtrl {
303 volatile Bits32 recvInitStatus;
304 volatile Bits32 sendInitStatus;
305 volatile Bits32 eventRegMask;
306 volatile Bits32 eventEnableMask;
307 }
308
309 struct Instance_State {
310 ProcCtrl *selfProcCtrl;
311 ProcCtrl *otherProcCtrl;
312 EventEntry *selfEventChart;
313 EventEntry *otherEventChart;
314 Notify.Handle notifyHandle;
315 UInt32 regChart[];
316 UInt selfId;
317 UInt otherId;
318 IInterrupt.IntInfo intInfo;
319 UInt16 remoteProcId;
320 UInt nesting;
321 Bool cacheEnabled;
322 SizeT eventEntrySize;
323 }
324 }