d05a1ff3af87d1fee815d6db4c38bb127baf4e6a
[ipc/ipcdev.git] / packages / ti / sdo / ipc / SharedRegion.xs
1 /*
2  * Copyright (c) 2012-2013, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 /*
33  *  ======== SharedRegion.xs ========
34  *
35  */
37 var GateMP       = null;
38 var HeapMemMP    = null;
39 var Ipc          = null;
40 var MultiProc    = null;
41 var SharedRegion = null;
42 var Cache        = null;
44 var staticInited = false;   /* set to true in  module$static$init */
45 var idArray = [];           /* for storing the id of an entry     */
47 /*
48  *  ======== module$meta$init ========
49  */
50 function module$meta$init()
51 {
52     /* Only process during "cfg" phase */
53     if (xdc.om.$name != "cfg") {
54         return;
55     }
57     SharedRegion = this;
59     SharedRegion.entry.length = 0;
60     SharedRegion.entryCount = 0;
61     SharedRegion.numOffsetBits = 0;
62     SharedRegion.$object.regions.length = 0;
63 }
65 /*
66  *  ======== module$use ========
67  */
68 function module$use()
69 {
70     GateMP    = xdc.useModule("ti.sdo.ipc.GateMP");
71     Ipc       = xdc.useModule("ti.sdo.ipc.Ipc");
72     HeapMemMP = xdc.useModule("ti.sdo.ipc.heaps.HeapMemMP");
73     MultiProc = xdc.useModule("ti.sdo.utils.MultiProc");
74     Cache     = xdc.useModule("ti.sysbios.hal.Cache");
76     /* in a single processor system, we should never translate */
77     if (MultiProc.numProcessors == 1) {
78         SharedRegion.translate = false;
79     }
81     if (SharedRegion.translate == false) {
82         SharedRegion.INVALIDSRPTR = 0x0;
83     }
84 }
86 /*
87  *  ======== module$static$init ========
88  *  Initialize module values.
89  */
90 function module$static$init(mod, params)
91 {
92     var Memory    = xdc.module('xdc.runtime.Memory');
93     var regions   = SharedRegion.$object.regions;
95     staticInited = true;
97     /* allocate the number of entries in the table and intialize it */
98     regions.length   = params.numEntries;
100     for (var i = 0; i < params.numEntries; i++) {
101         regions[i].entry.base          = $addr(0);
102         regions[i].entry.len           = 0;
103         regions[i].entry.ownerProcId   = 0;
104         regions[i].entry.isValid       = false;
105         regions[i].entry.cacheEnable   = true;
106         regions[i].entry.cacheLineSize = params.cacheLineSize;
107         regions[i].entry.createHeap    = true;
108         regions[i].reservedSize        = 0;
109         regions[i].heap                = null;
110         regions[i].entry.name          = String(null);
111     }
113     /* set the length of the genSectionInLinkCmd[] */
114     SharedRegion.genSectionInLinkCmd.length   = params.numEntries;
116     /* default the generate output section to be true for all shared regions */
117     for (var i = 0; i < SharedRegion.genSectionInLinkCmd.length; i++) {
118         SharedRegion.genSectionInLinkCmd[i] = true;
119     }
121     SharedRegion.numOffsetBits = getNumOffsetBits();
122     SharedRegion.offsetMask = (1 << SharedRegion.numOffsetBits) - 1;
124     /*
125      *  Add entry to lookup table for all segments added by 'addEntry'. Each
126      *  entry's info was temporarily stored into SharedRegion.entry[].
127      *  where 'i' is equivalent to the number of entries.
128      */
129     for (var i = 0; i < SharedRegion.entry.length; i++) {
130         var entry = SharedRegion.entry[i];
132         /* make sure id is smaller than numEntries */
133         if (idArray[i] >= params.numEntries) {
134             SharedRegion.$logError("Id: " + idArray[i] + " " +
135                 "is greater than or equal to numEntries.", SharedRegion);
136         }
138         if (idArray[i] != SharedRegion.INVALIDREGIONID) {
139             regions[idArray[i]].entry.base          = entry.base;
140             regions[idArray[i]].entry.len           = entry.len;
141             regions[idArray[i]].entry.ownerProcId   = entry.ownerProcId;
142             regions[idArray[i]].entry.isValid       = entry.isValid;
143             regions[idArray[i]].entry.cacheEnable   = entry.cacheEnable;
144             regions[idArray[i]].entry.cacheLineSize = entry.cacheLineSize;
145             regions[idArray[i]].entry.createHeap    = entry.createHeap;
146             regions[idArray[i]].entry.name          = entry.name;
147         }
148     }
151 /*
152  *  ======== setEntryMeta ========
153  *  Adds a memory region to the lookup table.
154  *  Function places entries in temporary storage and process this structure
155  *  at the end of module$static$init() because the number of entries
156  *  cannot be initialize until after user's configuration is executed.
157  */
158 function setEntryMeta(id, entry)
160     var num = SharedRegion.entryCount;
162     SharedRegion.entryCount++;
163     idArray.length++;
164     SharedRegion.entry.length = SharedRegion.entryCount;
166     /* Initialize new table entry for all processors. */
167     SharedRegion.entry[num].base          = $addr(0);
168     SharedRegion.entry[num].len           = 0;
169     SharedRegion.entry[num].ownerProcId   = 0;
170     SharedRegion.entry[num].isValid       = false;
171     SharedRegion.entry[num].cacheEnable   = true;
172     SharedRegion.entry[num].cacheLineSize = SharedRegion.cacheLineSize;
173     SharedRegion.entry[num].createHeap    = true;
174     SharedRegion.entry[num].name          = String(null);
176     /* check to see region does not overlap */
177     checkOverlap(entry);
179     /* squirrel away entry information to be processed in module$static$init */
180     idArray[num]                          = id;
181     SharedRegion.entry[num].base          = $addr(entry.base);
182     SharedRegion.entry[num].len           = entry.len;
184     /* set 'ownerProcId' if defined otherwise no default owner */
185     if (entry.ownerProcId != undefined) {
186         SharedRegion.entry[num].ownerProcId   = entry.ownerProcId;
187     }
189     /* set 'name' field if defined otherwise name is null */
190     if (entry.name != undefined) {
191         SharedRegion.entry[num].name = entry.name;
192     }
194     /* set 'isValid' field if defined otherwise its false */
195     if (entry.isValid != undefined) {
196         SharedRegion.entry[num].isValid = entry.isValid;
197     }
199     /* set the 'cacheEnable' field if defined otherwise is true */
200     if (entry.cacheEnable != undefined) {
201         SharedRegion.entry[num].cacheEnable = entry.cacheEnable;
202     }
204     /* set the 'createHeap' field if defined otherwise use default */
205     if (entry.createHeap != undefined) {
206         SharedRegion.entry[num].createHeap = entry.createHeap;
207     }
209     /* set the 'cacheLineSize' field if defined otherwise its the default */
210     if (entry.cacheLineSize != undefined) {
211         /* Error if cacheEnable but cacheLineSize set to 0 */
212         if (SharedRegion.entry[num].cacheEnable && (entry.cacheLineSize == 0)) {
213             SharedRegion.$logError("cacheEnable is set to true for " +
214                 "region: " + id + " cacheLineSize it set to 0.", SharedRegion);
215         }
216         else {
217             SharedRegion.entry[num].cacheLineSize = entry.cacheLineSize;
218         }
219     }
221     /*
222      *  The cacheLineSize is used for alignment of an address as well as
223      *  padding of shared structures therefore it cannot be 0.
224      *  This value must be the same across different processors in the system.
225      *  Initially it was thought this would be the size of a Ptr (4), but the
226      *  max default alignment is the size of a Long or Double (8) on C64P
227      *  target therefore the minimum cacheLineSize must be 8.
228      */
229     if (SharedRegion.entry[num].cacheLineSize == 0) {
230         var target  = Program.build.target;
231         SharedRegion.entry[num].cacheLineSize = 8;
232     }
234     if (entry.base % SharedRegion.entry[num].cacheLineSize != 0) {
235         /* Error if base address not aligned to cache boundary */
236         SharedRegion.$logError("Base Address of 0x" +
237             Number(entry.base).toString(16) +
238             " is not aligned to cache boundary (" +
239             SharedRegion.entry[num].cacheLineSize + ")", SharedRegion);
240     }
243 /*
244  *  ======== genSectionInCmd ========
245  *  Depending on what 'gen' is, it will either generate or not
246  *  generate an output section for the given shared region with 'id'.
247  */
248 function genSectionInCmd(id, gen)
250     /* make sure id is smaller than numEntries */
251     if (id >= SharedRegion.numEntries) {
252         SharedRegion.$logError("Id: " + id + " " +
253             "is greater than or equal to numEntries.", SharedRegion);
254     }
256     SharedRegion.genSectionInLinkCmd[id] = gen;
259 /*
260  *  ======== getPtrMeta ========
261  *  Get the pointer given the SRPtr.
262  */
263 function getPtrMeta(srptr)
265     var returnPtr = 0;
266     var offsetBits = getNumOffsetBits();
267     var base;
268     var entry;
269     var foundBase = false;
271     if (staticInited && (SharedRegion.translate == false)) {
272         returnPtr = srptr;
273     }
274     else {
275         entry = SharedRegion.entry;
277         /* unsigned right shift by offsetBits to get id */
278         var id = srptr >>> offsetBits;
280         /* loop through entry table */
281         for (var i = 0; i < entry.length; i++) {
282             if ((entry[i].isValid == true) && (idArray[i] == id)) {
283                 base = entry[i].base;
284                 foundBase = true;
285                 break;
286             }
287         }
289         /* a valid entry was found so get the ptr from srptr */
290         if (foundBase) {
291             returnPtr = (srptr & ((1 << offsetBits) - 1)) + base;
292         }
293     }
295     return (returnPtr);
298 /*
299  *  ======== getIdMeta ========
300  *  Get the id given the addr
301  */
302 function getIdMeta(addr)
304     var entry;
305     var id = SharedRegion.INVALIDREGIONID;
307     if (staticInited && (SharedRegion.translate == false)) {
308         id = 0;
309     }
310     else {
311         entry = SharedRegion.entry;
312         for (var i = 0; i < entry.length; i++) {
313             if ((addr >= entry[i].base) &&
314                 (addr < (entry[i].base + entry[i].len))) {
315                 id = idArray[i];
316                 break;
317             }
318         }
319     }
321     return (id);
324 /*
325  *  ======== getCacheLineSizeMeta ========
326  */
327 function getCacheLineSizeMeta(id)
329     /* make sure id is smaller than numEntries */
330     if (id >= SharedRegion.numEntries) {
331         SharedRegion.$logError("Id: " + id + " " +
332             "is greater than or equal to numEntries.", SharedRegion);
333     }
335     return (cacheLineSize[id]);
338 /*
339  *  ======== isCacheEnabledMeta ========
340  *  Given the id return the 'cacheEnable' flag.
341  *  function cannot be called from user's *.cfg file.
342  */
343 function isCacheEnabledMeta(id)
345     /* make sure id is smaller than numEntries */
346     if (id >= SharedRegion.numEntries) {
347         SharedRegion.$logError("Id: " + id + " " +
348             "is greater than or equal to numEntries.", SharedRegion);
349     }
351     return (SharedRegion.entry[id].cacheEnable);
354 /*
355  *  ======== checkOverlap ========
356  *  Checks to make sure the memory region does not overlap with another region.
357  *  This function is only called if MultiProc.id has been set to a valid id.
358  */
359 function checkOverlap(memseg)
361     var map  = SharedRegion.entry;
363     for (var i = 0; i < map.length; i++) {
364         if (memseg.base >= map[i].base) {
365             if (memseg.base < (map[i].base + map[i].len)) {
366                 /* base of new region is within another region */
367                 SharedRegion.$logError("Segment: " + utils.toHex(memseg.base) +
368                     " overlaps with: " + map[i].name, SharedRegion);
369             }
370         }
371         else {
372             if ((memseg.base + memseg.len) > map[i].base) {
373                     /* part of region is within another region */
374                 SharedRegion.$logError("Segment: " + utils.toHex(memseg.base) +
375                     " overlaps with: " + map[i].name, SharedRegion);
376             }
377         }
378     }
381 /*
382  *  ======== getNumOffsetBits ========
383  *  Return the number of offsetBits bits
384  */
385 function getNumOffsetBits()
387     var numEntries = SharedRegion.numEntries;
388     var indexBits = 0;
389     var numOffsetBits;
391     if (numEntries == 0) {
392         indexBits = 0;
393     }
394     else if (numEntries == 1) {
395         indexBits = 1;
396     }
397     else {
398         numEntries = numEntries - 1;
400         /* determine the number of bits for the index */
401         while (numEntries) {
402             indexBits++;
403             numEntries = numEntries >> 1;
404         }
405     }
407     numOffsetBits = 32 - indexBits;
409     return (numOffsetBits);
412 /*
413  *  ======== reserveNumBytes ========
414  */
415 function reserveNumBytes(numBytes)
417     SharedRegion.numBytesReserved = numBytes;
420 /*
421  *  ======== viewInitRegions ========
422  */
423 function viewInitRegions(view)
425     var Program = xdc.useModule('xdc.rov.Program');
426     var SharedRegion = xdc.useModule('ti.sdo.ipc.SharedRegion');
428     /* Scan the raw view in order to obtain the module state. */
429     var rawView;
430     try {
431         rawView = Program.scanRawView('ti.sdo.ipc.SharedRegion');
432     }
433     catch (e) {
434         var entryView = Program.newViewStruct('ti.sdo.ipc.SharedRegion',
435                 'Regions');
436         Program.displayError(entryView, 'base',
437             "Problem retrieving raw view: " + e);
438         view.elements.$add(entryView);
439         return;
440     }
442     var mod = rawView.modState;
444     /* Retrieve the module configuration. */
445     var modCfg = Program.getModuleConfig('ti.sdo.ipc.SharedRegion');
447     /* Retrieve the table of entries. */
448     try {
449         var regions = Program.fetchArray(SharedRegion.Region$fetchDesc,
450                                          mod.regions,
451                                          modCfg.numEntries);
452     }
453     catch (e) {
454         var entryView = Program.newViewStruct('ti.sdo.ipc.SharedRegion',
455                 'Regions');
456         Program.displayError(entryView, 'base',
457             "Caught exception while trying to retrieve regions table: " + e);
458         view.elements.$add(entryView);
459         return;
460     }
462     /* Display each of the regions. */
463     for (var i = 0; i < regions.length; i++) {
464         var entry = regions[i].entry;
466         var entryView = Program.newViewStruct('ti.sdo.ipc.SharedRegion',
467                                               'Regions');
469         var base =  Number(entry.base);
470         var len =  Number(entry.len);
472         entryView.id = i;
473         entryView.base = "0x" + Number(base).toString(16);
474         entryView.len = "0x" + Number(len).toString(16);
475         if (len == 0) {
476             entryView.end = "0x" + Number(base + len).toString(16);
477         }
478         else {
479             entryView.end = "0x" + Number(base + len - 1).toString(16);
480         }
481         entryView.ownerProcId = entry.ownerProcId;
482         entryView.isValid = entry.isValid;
483         entryView.cacheEnable = entry.cacheEnable;
484         entryView.cacheLineSize = entry.cacheLineSize;
485         entryView.reservedSize = regions[i].reservedSize;
486         entryView.heap = regions[i].heap;
487         try {
488             entryView.name = Program.fetchString(Number(entry.name));
489         }
490         catch (e) {
491             Program.displayError(entryView, 'name', "Problem retrieving name: " + e);
492         }
494         view.elements.$add(entryView);
495     }
498 /*
499  *  ======== getPtrMeta$view ========
500  */
501 function getPtrMeta$view(srptr)
503     var Program = xdc.useModule('xdc.rov.Program');
505     /*
506      * Retrieve the SharedRegion module configuration.
507      * Store the configuration to the 'SharedRegion' global variable in this
508      * file so that we can call the config-time API 'getNumOffsetBits'.
509      */
510     SharedRegion = Program.getModuleConfig('ti.sdo.ipc.SharedRegion');
512     /* Ensure that srptr is a number */
513     srptr = Number(srptr);
515     /* If there's no translation to be done, just return the pointer. */
516     if (SharedRegion.translate == false) {
517         return (srptr);
518     }
520     /* If srptr is SharedRegion.INVALIDSRPTR then return NULL*/
521     if (srptr == SharedRegion.INVALIDSRPTR) {
522         return (0);
523     }
525     /*
526      * Retrieve the 'Regions' view.
527      * This view may throw an exception; let this exception propogate up and
528      * be caught by the view calling this API.
529      */
530     var regionsView = Program.scanModuleDataView('ti.sdo.ipc.SharedRegion',
531         'Regions');
533     /* Get the regions from the view. */
534     var regions = regionsView.elements;
537     /* Retrieve the number of offset bits. */
538     var numOffsetBits = getNumOffsetBits();
540     /* unsigned right shift by offset to get id */
541     var id = srptr >>> numOffsetBits;
543     /* Verify the computed id is within range. */
544     if (id > regions.length) {
545         throw (new Error("The region id " + id + " of the SharedRegion " +
546                          "pointer 0x" + Number(srptr).toString(16) + " is " +
547                          "not a valid id."));
548     }
550     /* Retrieve the region. */
551     var region = regions[id];
553     /* Verify the region is valid. */
554     if (!region.isValid) {
555         throw (new Error("The SharedRegion " + id + " of the SharedRegion " +
556                          "pointer 0x" + Number(srptr).toString(16) + " is " +
557                          "currently invalid."));
558     }
560     /* Compute the local address. */
561     var ptr = (srptr & ((1 << numOffsetBits) - 1)) + parseInt(region.base);
563     return (ptr);
566 /*
567  *  ======== getSRPtrMeta$view ========
568  */
569 function getSRPtrMeta$view(addr)
571     /*
572      * Retrieve the SharedRegion module configuration.
573      * Store the configuration to the 'SharedRegion' global variable in this
574      * file so that we can call the config-time API 'getNumOffsetBits'.
575      */
576     SharedRegion = Program.getModuleConfig('ti.sdo.ipc.SharedRegion');
578     /* Ensure the address is a number */
579     addr = Number(addr);
581     /* If there's no translation to be done, just return the pointer. */
582     if (SharedRegion.translate == false) {
583         return (addr);
584     }
586     /* If addr is NULL, return SharedRegion.INVALIDSRPTR */
587     if (addr == 0) {
588         return (SharedRegion.INVALIDSRPTR);
589     }
591     /*
592      * Retrieve the 'Regions' view.
593      * This view may throw an exception; let this exception propogate up and
594      * be caught by the view calling this API.
595      */
596     var regionsView = Program.scanModuleDataView('ti.sdo.ipc.SharedRegion',
597         'Regions');
599     /* Get the regions from the view. */
600     var regions = regionsView.elements;
603     /* Retrieve the number of offset bits. */
604     var numOffsetBits = getNumOffsetBits();
606     /* Look through each of the regions for this address. */
607     for (var i = 0; i < regions.length; i++) {
609         /* Compute the beginning and end address of this region. */
610         var begin = parseInt(regions[i].base);
611         var end = parseInt(regions[i].end);
613         /* If the address falls within this region... */
614         if ((addr >= begin) && (addr < end)) {
615             /* Compute the shared region address and return. */
616             return ((i << numOffsetBits) + (addr - begin));
617         }
618     }
620     /* If we didn't find a region containing the address, throw an error. */
621     throw("No address range found for: " + Number(addr).toString(16));