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