SharedRegion: Update to use linker symbols instead of platform map
[ipc/ipcdev.git] / packages / ti / sdo / ipc / SharedRegion.xs
1 /*
2  * Copyright (c) 2012-2018, 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, metaentry)
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 overlap not doable with symbol in entry, base address not yet availble so deprecated */
177         /* check to see region does not overlap */
178     if (metaentry.base) {
179         checkOverlap(metaentry);
180    }
182     /* squirrel away entry information to be processed in module$static$init */
183     idArray[num]                          = id;
184     if (metaentry.base) {
185         SharedRegion.entry[num].base          = $addr(metaentry.base);
186         SharedRegion.entry[num].len           = metaentry.len;
187     } else {
188         SharedRegion.entry[num].base          = $externPtr(metaentry.base_symbol);
189         SharedRegion.entry[num].len           = $externPtr(metaentry.len_symbol);
190     }
192     /* set 'ownerProcId' if defined otherwise no default owner */
193     if (metaentry.ownerProcId != undefined) {
194         SharedRegion.entry[num].ownerProcId   = metaentry.ownerProcId;
195     }
197     /* set 'name' field if defined otherwise name is null */
198     if (metaentry.name != undefined) {
199         SharedRegion.entry[num].name = metaentry.name;
200     }
202     /* set 'isValid' field if defined otherwise its false */
203     if (metaentry.isValid != undefined) {
204         SharedRegion.entry[num].isValid = metaentry.isValid;
205     }
207     /* set the 'cacheEnable' field if defined otherwise is true */
208     if (metaentry.cacheEnable != undefined) {
209         SharedRegion.entry[num].cacheEnable = metaentry.cacheEnable;
210     }
212     /* set the 'createHeap' field if defined otherwise use default */
213     if (metaentry.createHeap != undefined) {
214         SharedRegion.entry[num].createHeap = metaentry.createHeap;
215     }
217     /* set the 'cacheLineSize' field if defined otherwise its the default */
218     if (metaentry.cacheLineSize != undefined) {
219         /* Error if cacheEnable but cacheLineSize set to 0 */
220         if (SharedRegion.entry[num].cacheEnable && (metaentry.cacheLineSize == 0)) {
221             SharedRegion.$logError("cacheEnable is set to true for " +
222                 "region: " + id + " cacheLineSize it set to 0.", SharedRegion);
223         }
224         else {
225             SharedRegion.entry[num].cacheLineSize = metaentry.cacheLineSize;
226         }
227     }
229     /*
230      *  The cacheLineSize is used for alignment of an address as well as
231      *  padding of shared structures therefore it cannot be 0.
232      *  This value must be the same across different processors in the system.
233      *  Initially it was thought this would be the size of a Ptr (4), but the
234      *  max default alignment is the size of a Long or Double (8) on C64P
235      *  target therefore the minimum cacheLineSize must be 8.
236      */
237     if (SharedRegion.entry[num].cacheLineSize == 0) {
238         var target  = Program.build.target;
239         SharedRegion.entry[num].cacheLineSize = 8;
240     }
242 /* Check base address not doable as it is not yet availble. So deprecated */
243     if (metaentry.base) {
244         if (metaentry.base % SharedRegion.entry[num].cacheLineSize != 0) {
245             /* Error if base address not aligned to cache boundary */
246             SharedRegion.$logError("Base Address of 0x" +
247                 Number(entry.base).toString(16) +
248                 " is not aligned to cache boundary (" +
249                 SharedRegion.entry[num].cacheLineSize + ")", SharedRegion);
250         }
251     }
254 /*
255  *  ======== genSectionInCmd ========
256  *  Depending on what 'gen' is, it will either generate or not
257  *  generate an output section for the given shared region with 'id'.
258  */
259 function genSectionInCmd(id, gen)
261     /* make sure id is smaller than numEntries */
262     if (id >= SharedRegion.numEntries) {
263         SharedRegion.$logError("Id: " + id + " " +
264             "is greater than or equal to numEntries.", SharedRegion);
265     }
267     SharedRegion.genSectionInLinkCmd[id] = gen;
270 /*
271  *  ======== getPtrMeta ========
272  *  Get the pointer given the SRPtr.
273  */
274 function getPtrMeta(srptr)
276     var returnPtr = 0;
277     var offsetBits = getNumOffsetBits();
278     var base;
279     var entry;
280     var foundBase = false;
282     if (staticInited && (SharedRegion.translate == false)) {
283         returnPtr = srptr;
284     }
285     else {
286         entry = SharedRegion.entry;
288         /* unsigned right shift by offsetBits to get id */
289         var id = srptr >>> offsetBits;
291         /* loop through entry table */
292         for (var i = 0; i < entry.length; i++) {
293             if ((entry[i].isValid == true) && (idArray[i] == id)) {
294                 base = entry[i].base;
295                 foundBase = true;
296                 break;
297             }
298         }
300         /* a valid entry was found so get the ptr from srptr */
301         if (foundBase) {
302             returnPtr = (srptr & ((1 << offsetBits) - 1)) + base;
303         }
304     }
306     return (returnPtr);
309 /*
310  *  ======== getIdMeta ========
311  *  Get the id given the addr
312  */
313 function getIdMeta(addr)
315     var entry;
316     var id = SharedRegion.INVALIDREGIONID;
318     if (staticInited && (SharedRegion.translate == false)) {
319         id = 0;
320     }
321     else {
322         entry = SharedRegion.entry;
323         for (var i = 0; i < entry.length; i++) {
324             if ((addr >= entry[i].base) &&
325                 (addr < (entry[i].base + entry[i].len))) {
326                 id = idArray[i];
327                 break;
328             }
329         }
330     }
332     return (id);
335 /*
336  *  ======== getCacheLineSizeMeta ========
337  */
338 function getCacheLineSizeMeta(id)
340     /* make sure id is smaller than numEntries */
341     if (id >= SharedRegion.numEntries) {
342         SharedRegion.$logError("Id: " + id + " " +
343             "is greater than or equal to numEntries.", SharedRegion);
344     }
346     return (cacheLineSize[id]);
349 /*
350  *  ======== isCacheEnabledMeta ========
351  *  Given the id return the 'cacheEnable' flag.
352  *  function cannot be called from user's *.cfg file.
353  */
354 function isCacheEnabledMeta(id)
356     /* make sure id is smaller than numEntries */
357     if (id >= SharedRegion.numEntries) {
358         SharedRegion.$logError("Id: " + id + " " +
359             "is greater than or equal to numEntries.", SharedRegion);
360     }
362     return (SharedRegion.entry[id].cacheEnable);
365 /*
366  *  ======== checkOverlap ========
367  *  Checks to make sure the memory region does not overlap with another region.
368  *  This function is only called if MultiProc.id has been set to a valid id.
369  */
370 function checkOverlap(memseg)
372     var map  = SharedRegion.entry;
374     for (var i = 0; i < map.length; i++) {
375         if (memseg.base >= map[i].base) {
376             if (memseg.base < (map[i].base + map[i].len)) {
377                 /* base of new region is within another region */
378                 SharedRegion.$logError("Segment: " + utils.toHex(memseg.base) +
379                     " overlaps with: " + map[i].name, SharedRegion);
380             }
381         }
382         else {
383             if ((memseg.base + memseg.len) > map[i].base) {
384                     /* part of region is within another region */
385                 SharedRegion.$logError("Segment: " + utils.toHex(memseg.base) +
386                     " overlaps with: " + map[i].name, SharedRegion);
387             }
388         }
389     }
392 /*
393  *  ======== getNumOffsetBits ========
394  *  Return the number of offsetBits bits
395  */
396 function getNumOffsetBits()
398     var numEntries = SharedRegion.numEntries;
399     var indexBits = 0;
400     var numOffsetBits;
402     if (numEntries == 0) {
403         indexBits = 0;
404     }
405     else if (numEntries == 1) {
406         indexBits = 1;
407     }
408     else {
409         numEntries = numEntries - 1;
411         /* determine the number of bits for the index */
412         while (numEntries) {
413             indexBits++;
414             numEntries = numEntries >> 1;
415         }
416     }
418     numOffsetBits = 32 - indexBits;
420     return (numOffsetBits);
423 /*
424  *  ======== reserveNumBytes ========
425  */
426 function reserveNumBytes(numBytes)
428     SharedRegion.numBytesReserved = numBytes;
431 /*
432  *  ======== viewInitRegions ========
433  */
434 function viewInitRegions(view)
436     var Program = xdc.useModule('xdc.rov.Program');
437     var SharedRegion = xdc.useModule('ti.sdo.ipc.SharedRegion');
439     /* Scan the raw view in order to obtain the module state. */
440     var rawView;
441     try {
442         rawView = Program.scanRawView('ti.sdo.ipc.SharedRegion');
443     }
444     catch (e) {
445         var entryView = Program.newViewStruct('ti.sdo.ipc.SharedRegion',
446                 'Regions');
447         Program.displayError(entryView, 'base',
448             "Problem retrieving raw view: " + e);
449         view.elements.$add(entryView);
450         return;
451     }
453     var mod = rawView.modState;
455     /* Retrieve the module configuration. */
456     var modCfg = Program.getModuleConfig('ti.sdo.ipc.SharedRegion');
458     /* Retrieve the table of entries. */
459     try {
460         var regions = Program.fetchArray(SharedRegion.Region$fetchDesc,
461                                          mod.regions,
462                                          modCfg.numEntries);
463     }
464     catch (e) {
465         var entryView = Program.newViewStruct('ti.sdo.ipc.SharedRegion',
466                 'Regions');
467         Program.displayError(entryView, 'base',
468             "Caught exception while trying to retrieve regions table: " + e);
469         view.elements.$add(entryView);
470         return;
471     }
473     /* Display each of the regions. */
474     for (var i = 0; i < regions.length; i++) {
475         var entry = regions[i].entry;
477         var entryView = Program.newViewStruct('ti.sdo.ipc.SharedRegion',
478                                               'Regions');
480         var base =  Number(entry.base);
481         var len =  Number(entry.len);
483         entryView.id = i;
484         entryView.base = "0x" + Number(base).toString(16);
485         entryView.len = "0x" + Number(len).toString(16);
486         if (len == 0) {
487             entryView.end = "0x" + Number(base + len).toString(16);
488         }
489         else {
490             entryView.end = "0x" + Number(base + len - 1).toString(16);
491         }
492         entryView.ownerProcId = entry.ownerProcId;
493         entryView.isValid = entry.isValid;
494         entryView.cacheEnable = entry.cacheEnable;
495         entryView.cacheLineSize = entry.cacheLineSize;
496         entryView.reservedSize = regions[i].reservedSize;
497         entryView.heap = regions[i].heap;
498         try {
499             entryView.name = Program.fetchString(Number(entry.name));
500         }
501         catch (e) {
502             Program.displayError(entryView, 'name', "Problem retrieving name: " + e);
503         }
505         view.elements.$add(entryView);
506     }
509 /*
510  *  ======== getPtrMeta$view ========
511  */
512 function getPtrMeta$view(srptr)
514     var Program = xdc.useModule('xdc.rov.Program');
516     /*
517      * Retrieve the SharedRegion module configuration.
518      * Store the configuration to the 'SharedRegion' global variable in this
519      * file so that we can call the config-time API 'getNumOffsetBits'.
520      */
521     SharedRegion = Program.getModuleConfig('ti.sdo.ipc.SharedRegion');
523     /* Ensure that srptr is a number */
524     srptr = Number(srptr);
526     /* If there's no translation to be done, just return the pointer. */
527     if (SharedRegion.translate == false) {
528         return (srptr);
529     }
531     /* If srptr is SharedRegion.INVALIDSRPTR then return NULL*/
532     if (srptr == SharedRegion.INVALIDSRPTR) {
533         return (0);
534     }
536     /*
537      * Retrieve the 'Regions' view.
538      * This view may throw an exception; let this exception propogate up and
539      * be caught by the view calling this API.
540      */
541     var regionsView = Program.scanModuleDataView('ti.sdo.ipc.SharedRegion',
542         'Regions');
544     /* Get the regions from the view. */
545     var regions = regionsView.elements;
548     /* Retrieve the number of offset bits. */
549     var numOffsetBits = getNumOffsetBits();
551     /* unsigned right shift by offset to get id */
552     var id = srptr >>> numOffsetBits;
554     /* Verify the computed id is within range. */
555     if (id > regions.length) {
556         throw (new Error("The region id " + id + " of the SharedRegion " +
557                          "pointer 0x" + Number(srptr).toString(16) + " is " +
558                          "not a valid id."));
559     }
561     /* Retrieve the region. */
562     var region = regions[id];
564     /* Verify the region is valid. */
565     if (!region.isValid) {
566         throw (new Error("The SharedRegion " + id + " of the SharedRegion " +
567                          "pointer 0x" + Number(srptr).toString(16) + " is " +
568                          "currently invalid."));
569     }
571     /* Compute the local address. */
572     var ptr = (srptr & ((1 << numOffsetBits) - 1)) + parseInt(region.base);
574     return (ptr);
577 /*
578  *  ======== getSRPtrMeta$view ========
579  */
580 function getSRPtrMeta$view(addr)
582     /*
583      * Retrieve the SharedRegion module configuration.
584      * Store the configuration to the 'SharedRegion' global variable in this
585      * file so that we can call the config-time API 'getNumOffsetBits'.
586      */
587     SharedRegion = Program.getModuleConfig('ti.sdo.ipc.SharedRegion');
589     /* Ensure the address is a number */
590     addr = Number(addr);
592     /* If there's no translation to be done, just return the pointer. */
593     if (SharedRegion.translate == false) {
594         return (addr);
595     }
597     /* If addr is NULL, return SharedRegion.INVALIDSRPTR */
598     if (addr == 0) {
599         return (SharedRegion.INVALIDSRPTR);
600     }
602     /*
603      * Retrieve the 'Regions' view.
604      * This view may throw an exception; let this exception propogate up and
605      * be caught by the view calling this API.
606      */
607     var regionsView = Program.scanModuleDataView('ti.sdo.ipc.SharedRegion',
608         'Regions');
610     /* Get the regions from the view. */
611     var regions = regionsView.elements;
614     /* Retrieve the number of offset bits. */
615     var numOffsetBits = getNumOffsetBits();
617     /* Look through each of the regions for this address. */
618     for (var i = 0; i < regions.length; i++) {
620         /* Compute the beginning and end address of this region. */
621         var begin = parseInt(regions[i].base);
622         var end = parseInt(regions[i].end);
624         /* If the address falls within this region... */
625         if ((addr >= begin) && (addr < end)) {
626             /* Compute the shared region address and return. */
627             return ((i << numOffsetBits) + (addr - begin));
628         }
629     }
631     /* If we didn't find a region containing the address, throw an error. */
632     throw("No address range found for: " + Number(addr).toString(16));