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