source: trunk/IPs/systemC/shared/soclib_segment_table.h @ 88

Last change on this file since 88 was 88, checked in by rosiere, 15 years ago

Almost complete design
with Test and test platform

  • Property svn:keywords set to Id
File size: 19.4 KB
Line 
1///////////////////////////////////////////////////////////////////////////
2// File : soclib_segment_table.h
3// Date : 08/07/2004
4// authors : François Pécheux & Alain Greiner
5//
6// Copyright : UPMC - LIP6
7// This program is released under the GNU public license
8//
9// This object is used to describe the memory mapping and address
10// decoding scheme. It supports a two level hierarchical interconnect :
11// All VCI initiators and VCI targets share the same address space.
12// - Several sub-systems can be interconnected thanks to a VCI ADVANCED
13// global interconnect that can be either a micro-network, or a global system bus.
14// - Each sub-system can contain as many targets as the LSB size allows.
15// They are connected by a VCI ADVANCED local interconnect, that can be
16// a local bus, or a VCI to VCI bridge such as the TARGET_DEMUX
17// and INITIATOR_MUX components of the SoCLib library.
18//
19// The VCI ADDRESS is structured as follows (three fields): | MSB | LSB | OFFSET |
20// The MSB bits of the VCI ADDRESS are decoded by the global interconnect
21// to route a VCI CMD/RSP packet to a given sub-system.
22// In each sub-system, the LSB bits of the VCI ADDRESS are decoded by the
23// local interconnect to route the a VCI CMD/RSP packet to the selected target/initiator.
24//
25// If the number of bits of the LSB field is zero, a global "flat" interconnect
26// is used, and both the VCI target index and the VCI initiator index are coded
27// on 8 bits.
28//
29// The segment table is an associative table that is organized as a
30// list of segments. This table must be built in the system top cell.
31//
32// Each segment descriptor contains the following fields:
33//
34// - const char         *name     : segment name
35// - unsigned int       base      : base address
36// - unsigned int       size      : segment size (in bytes)
37// - unsigned int       globalindex     : VCI subsystem index
38// - unsigned int       localindex      : VCI target index in the subsystem
39// - bool               uncached  : uncached when true
40//
41// The constraints on the memory mapping are the following :
42//
43// 1/ The system designer must define the number of bits for the address
44// MSB and LSB fields. Both numbers can be zero. (For example the number
45// of LSB bits will be zero, in case of a "flat" VCI interconnect).
46//
47// 2/ The (MSB | LSB) bits are indexing a "page" in the address space.
48// Several pages can be mapped to the same VCI target.
49//
50// 3/ A segment is allocated to a VCI target, and must be contained in
51// a single page or in several contiguous pages.
52//
53// 4/ Several segments can be mapped to the same VCI target
54// (thanks to the SOCLIB_VCI_MULTIRAM component)
55//
56// 5/ A given page cannot contain two segments that are not
57// mapped to the same VCI target.
58//
59// The segment table is used by most SoCLib  components :
60//
61// - The constructors of the VCI interconnect components can use it to build
62// the ROMs implementing the routing tables
63// - The constructors of all VCI targets use it to implement the segmentation
64// violation detection mechanism, and allocate the buffers representing
65// the memory in case of an embedded memory component.
66// - The constructors of several processors (MIPS, SPARC) use it to build
67// the ROM implementing the uncached table.
68///////////////////////////////////////////////////////////////////////////
69
70#ifndef SEGMENT_TABLE_H
71#define SEGMENT_TABLE_H
72
73#include <list>
74#include <iostream>
75// using namespace std;
76
77//////////////////////////////////////////////
78//      SEGMENT_TABLE_ENTRY definition
79//////////////////////////////////////////////
80
81struct SEGMENT_TABLE_ENTRY
82{
83
84private:
85
86  const char            *name;
87  unsigned int          base;
88  unsigned int          size;
89  unsigned int          globalTarget;
90  unsigned int          localTarget;
91  bool                  uncached ;
92  //-----[ SIM2OS - begin ]-----------------------------------------
93  void *                addr_alloc;
94  //-----[ SIM2OS - end   ]-----------------------------------------
95
96public:
97
98// constructor
99
100SEGMENT_TABLE_ENTRY(const char *nm ,
101                    unsigned int ba , 
102                    unsigned int sz ,
103                    unsigned int glt,
104                    unsigned int lct,
105                    bool unc
106                    )
107        {
108        name=nm;
109        base=ba;
110        size=sz;
111        globalTarget=glt;
112        localTarget=lct;
113        uncached=unc;
114  //-----[ SIM2OS - begin ]-----------------------------------------
115        addr_alloc = (void *) 0;
116  //-----[ SIM2OS - end   ]-----------------------------------------
117        }; // end constructor
118
119// basic methods
120
121void print()
122        { 
123        printf("segment : %s , base = %.8x , size = %.8x , Global target = %d , Local Target = %d , unc = %d, addr_alloc : %.8x\n",
124               name, base, size, globalTarget, localTarget, uncached, (unsigned int)((long long)addr_alloc));
125        };
126
127const char *getName()
128        {
129        return name;
130        };
131
132unsigned int getBase()
133        {
134        return base;
135        };
136
137unsigned int getSize()
138        {
139        return size;
140        };
141
142unsigned int getGlobalTarget()
143        {
144        return globalTarget;
145        };
146       
147unsigned int getLocalTarget()
148        {
149        return localTarget;
150        };
151
152bool getUncached()
153        {
154        return uncached;
155        };
156
157  //-----[ SIM2OS - begin ]-----------------------------------------
158  void * getAddrAlloc()
159  {
160    return addr_alloc;
161  }
162
163  void setAddrAlloc (void * addr)
164  {
165    addr_alloc = addr;
166  }
167  //-----[ SIM2OS - end   ]-----------------------------------------
168
169  };// end struct SEGMENT_TABLE_ENTRY
170
171
172//////////////////////////////////////////////////////////
173//      SegmentTable definition
174//////////////////////////////////////////////////////////
175
176// using namespace std;
177
178struct SOCLIB_SEGMENT_TABLE {
179       
180private :
181
182std::list<SEGMENT_TABLE_ENTRY>  segList;
183int                             MSBNumber;
184int                             LSBNumber;
185unsigned int                    defaultTargetGlobalIndex;
186unsigned int                    defaultTargetLocalIndex;
187bool                            MSBNumberCalled;
188bool                            defaultTargetCalled;
189bool                            LSBNumberCalled;
190
191public :       
192
193//      CONSTRUCTOR
194
195SOCLIB_SEGMENT_TABLE()
196        {
197        MSBNumberCalled=false;
198        LSBNumberCalled=false;
199        defaultTargetCalled=false;
200        };  // end constructor
201
202//      BASIC METHODS
203
204void setMSBNumber (int number) 
205        {
206        if ((number<0)||(number>16))
207                {
208                std::cerr << "ERROR in the Segment Table :" << std::endl ;
209                std::cerr << "MSB number must be in the [0..16] range !" << std::endl ;
210                //sc_stop();
211                }
212                MSBNumberCalled=true;
213                MSBNumber=number;
214        };
215
216void setLSBNumber (int number) 
217        {
218        if ((number<0)||(number>16))
219                {
220                std::cerr << "ERROR in the Segment Table :" << std::endl ;
221                std::cerr << "LSB number must be in the [0..16] range !" << std::endl ;
222                //sc_stop();
223                }
224                LSBNumberCalled=true;           
225                LSBNumber=number;
226        };
227
228int getMSBNumber()
229        {
230        return MSBNumber;
231        };
232
233int getLSBNumber()
234        {
235        return LSBNumber;
236        };
237
238void setDefaultTarget (int _defTargetGlobalIndex , int _defTargetLocalIndex)
239        {
240                defaultTargetCalled=true;
241        defaultTargetGlobalIndex=_defTargetGlobalIndex;
242        defaultTargetLocalIndex=_defTargetLocalIndex;
243        };
244
245int getdefaultTargetGlobalIndex()
246        {
247        return defaultTargetGlobalIndex;
248        };
249       
250int getdefaultTargetLocalIndex()
251                {
252                return defaultTargetLocalIndex;
253                };     
254
255void addSegment(const char *nm,
256                unsigned int ba,
257                unsigned int sz,
258                unsigned int glt,
259                unsigned int lct,
260                bool unc)
261        {
262        SEGMENT_TABLE_ENTRY *seg=new SEGMENT_TABLE_ENTRY(nm,ba,sz,glt,lct,unc);
263        segList.push_back(*seg);
264        delete seg;
265        };
266
267  //-----[ SIM2OS - begin ]-----------------------------------------
268  void setAddrAlloc(unsigned int ba  ,
269                    void *       addr)
270  {
271    std::list<SEGMENT_TABLE_ENTRY>::iterator segIterator;
272    // Scan of all list
273    for (segIterator = segList.begin() ; segIterator != segList.end() ; ++segIterator) 
274      {
275        // Find a entry match with number of base
276        // NOTE : The memory is shared, also we can't have 2 segment with the same base
277        if (ba == (*segIterator).getBase ())
278          {
279            (*segIterator).setAddrAlloc(addr);
280          }
281      }
282  };
283
284  void * getAddrAlloc(unsigned int addr)
285  {
286    std::list<SEGMENT_TABLE_ENTRY>::iterator segIterator;
287
288    // Scan of all list
289    for (segIterator = segList.begin() ; segIterator != segList.end() ; ++segIterator) 
290      {
291        unsigned int addr_min = (*segIterator).getBase ();
292        unsigned int addr_max = addr_min + (*segIterator).getSize ();
293       
294        if ((addr >= addr_min) && (addr <= addr_max))
295          {
296            unsigned int offset = (addr-addr_min);
297            return (void*)((unsigned int)(long long)((*segIterator).getAddrAlloc()) + offset);
298          }
299      }
300    return NULL;
301  }
302  //-----[ SIM2OS - end   ]-----------------------------------------
303
304void print()
305        {
306          std::cout << "\n                 SEGMENT_TABLE\n\n" ;
307        std::list<SEGMENT_TABLE_ENTRY>::iterator iter;
308        for (iter = segList.begin() ; iter != segList.end() ; ++iter)
309                {
310                (*iter).print();
311                }
312        std::cout << "\n" ;
313        }
314
315void printMSBRoutingTable()
316        {
317          std::cout << "\n                 MSB ROUTING_TABLE\n\n" ;
318          int size = 1 << MSBNumber+LSBNumber;
319          unsigned int  *tab = new unsigned int[size];
320          initRoutingTable(tab);
321          for(int index = 0 ; index < size ; index++) {
322            if (tab[index]!=0xFFFFFFFF){
323              printf("TAB[%x] = %d\n", index, tab[index]);
324            }
325          }
326          std::cout << "\n" ;
327        };
328 
329  void printLSBRoutingTable(int glt)
330  {
331    printf( "\n    LSB_ROUTING_TABLE OF GLOBAL TARGET :%d \n\n", glt );
332    int size = 1 << MSBNumber+LSBNumber;
333    unsigned int        *tab = new unsigned int[size];
334    initLocalRoutingTable(tab,glt);
335    for(int index = 0 ; index < size ; index++) {
336      if (tab[index]!=0xFFFFFFFF){
337        printf("TAB[%d] = %d\n", index, tab[index]);
338      }
339    }
340    std::cout << "\n" ;
341  };
342       
343
344
345void initRoutingTable(unsigned int* tab) {
346        if (MSBNumberCalled==false) {
347                std::cerr << "ERROR in initMSBRoutingTable:" << std::endl ;
348                std::cerr << "MSB number has not been defined !" << std::endl ;
349                //sc_stop();
350        }
351        if (LSBNumberCalled==false) {
352          std::cout << "WARNING in initMSBRoutingTable:" << std::endl ;
353          std::cout << "LSB number has not been defined !" << std::endl ;
354          std::cout << "it is set to 0" << std::endl ;
355          LSBNumberCalled=true;
356          LSBNumber=0;
357        }
358       
359       
360        if (defaultTargetCalled==false) {
361                std::cerr << "ERROR in initMSBRoutingTable:" << std::endl ;
362                std::cerr << "Default Target has not been defined!" << std::endl ;
363                //sc_stop();
364        }
365
366        int RoutingTableSize = 1 << MSBNumber+LSBNumber;
367        int PageSize         = 1 << (32 - MSBNumber - LSBNumber);
368       
369        // The 0xFFFFFFFF value means "not allocated"
370        for (int i=0 ; i < RoutingTableSize ; i++) {
371                tab[i] = 0xFFFFFFFF;
372        }
373//              printf ( " tableau rempli de 0xFFFFFFFF \n");
374
375        // loop on the segment list
376        std::list<SEGMENT_TABLE_ENTRY>::iterator seg;
377        for (seg = segList.begin() ; seg != segList.end() ; ++seg) {
378                const char    *name   = (*seg).getName();
379                unsigned int  base    = (*seg).getBase();
380                unsigned int  size    = (*seg).getSize();
381                unsigned int globalTarget  = (*seg).getGlobalTarget();
382
383                unsigned int page = base >> (32-MSBNumber - LSBNumber) ;
384               
385                for (int x = (int) size ; x > 0 ; x = x - PageSize) {               
386                        if(tab[page] != 0xFFFFFFFF) {
387                //              printf("\n page n° %x can not be added to cluster %x because it is already allocated to %x\n",page,globalTarget,tab[page]);
388                                std::cerr << "Error in initMSBRoutingTable:" << std::endl ;
389                                std::cerr << "Segment " << name << " allocated to VCI target " << globalTarget << std::endl;
390                                std::cerr << "overlap another segment... or is in the same page" << std::endl;
391                                std::cerr << "as another segment allocated to another VCI target" << std::endl;
392                                //sc_stop();
393                        } else {
394                                tab[page]=globalTarget;
395                               
396                //              printf("\n page n° %x allocated to cluster °%x i.e %s \n",page,tab[page],name);
397                                }
398                        page = page + 1;
399                        } // end for x
400        } // end for seg
401       
402        // Default target
403        for (int i=0 ; i < RoutingTableSize ; i++) {
404                if(tab[i] == 0xFFFFFFFF) tab[i] = defaultTargetGlobalIndex;
405        }
406       
407};  // end initRoutingTable()
408
409////////////////////////////////////////////////////////////////
410//              initGlobalRoutingTable()
411//      This method can be used by any global VCI interconnect.
412//      It initializes the routing table that implements
413//      the VCI address MSB bits decoding ROM.
414//      - The argument is a pointer to the int table that
415//      has been allocated by the constructor of the
416//      VCI interconnect component.
417//      - Each entry contains a VCI target global index.
418//      The VCI local Target index is not used here
419////////////////////////////////////////////////////////////////
420
421
422void initGlobalRoutingTable(unsigned int* tab) {
423        if (MSBNumberCalled==false) {
424                std::cerr << "ERROR in initMSBRoutingTable:" << std::endl ;
425                std::cerr << "MSB number has not been defined !" << std::endl ;
426                //sc_stop();
427        }
428       
429        if (defaultTargetCalled==false) {
430                std::cerr << "ERROR in initMSBRoutingTable:" << std::endl ;
431                std::cerr << "Default Target has not been defined!" << std::endl ;
432                //sc_stop();
433        }
434
435        int RoutingTableSize = 1 << MSBNumber;
436        int PageSize         = 1 << (32 - MSBNumber);
437       
438        // The 0xFFFFFFFF value means "not allocated"
439        for (int i=0 ; i < RoutingTableSize ; i++) {
440                tab[i] = 0xFFFFFFFF;
441        }
442//              printf ( " tableau rempli de 0xFFFFFFFF \n");
443
444        // loop on the segment list
445        std::list<SEGMENT_TABLE_ENTRY>::iterator seg;
446        for (seg = segList.begin() ; seg != segList.end() ; ++seg) {
447                const char    *name   = (*seg).getName();
448                unsigned int  base    = (*seg).getBase();
449                unsigned int  size    = (*seg).getSize();
450                unsigned int globalTarget  = (*seg).getGlobalTarget();
451
452                unsigned int page = base >> (32-MSBNumber) ;
453               
454                for (int x = (int) size ; x > 0 ; x = x - PageSize) {               
455                        if(tab[page] != 0xFFFFFFFF) {
456                //              printf("\n page n° %x can not be added to cluster %x because it is already allocated to %x\n",page,globalTarget,tab[page]);
457                                std::cerr << "Error in initGlobalRoutingTable:" << std::endl ;
458                                std::cerr << "Segment " << name << " allocated to VCI target " << globalTarget << std::endl;
459                                std::cerr << "overlap another segment... or is in the same page" << std::endl;
460                                std::cerr << "as another segment allocated to another VCI target" << std::endl;
461                                //sc_stop();
462                        } else {
463                                tab[page]=globalTarget;
464                               
465                //              printf("\n page n° %x allocated to cluster °%x i.e %s \n",page,tab[page],name);
466                                }
467                        page = page + 1;
468                        } // end for x
469        } // end for seg
470       
471        // Default target
472        for (int i=0 ; i < RoutingTableSize ; i++) {
473                if(tab[i] == 0xFFFFFFFF) tab[i] = defaultTargetGlobalIndex;
474        }
475       
476};  // end initGlobalRoutingTable()
477
478
479////////////////////////////////////////////////////////////////
480//              initLocalRoutingTable()
481//      This method can be used by the local VCI interconnect.
482//      It initializes the routing table that implements
483//      the VCI address LSB bits decoding ROM.
484//      - The argument is a pointer to the char table that
485//      has been allocated by the constructor of the local
486//      VCI interconnect component.
487//      - Each entry contains a VCI target local index as well as a global index .
488//      - This method needs a parameter : the global index of the subsystem ,
489//      because it only fills the pages corresponding to a segment in this subsystem
490//      other pages are adressed to the Default Target
491////////////////////////////////////////////////////////////////
492
493void initLocalRoutingTable(unsigned int* tab, unsigned int cluster) {
494        if (MSBNumberCalled==false) {
495                std::cerr << "ERROR in initLocalRoutingTable:" << std::endl ;
496                std::cerr << "MSB number has not been defined !" << std::endl ;
497                //sc_stop();
498        }
499               
500        if (defaultTargetCalled==false) {
501                std::cerr << "ERROR in initLocalRoutingTable:" << std::endl ;
502                std::cerr << "Default Target has not been defined!" << std::endl ;
503                //sc_stop();
504        }
505
506        int RoutingTableSize = 1 << MSBNumber+LSBNumber;
507        int PageSize         = 1 << (32 - MSBNumber - LSBNumber );
508       
509        // The 0xFF value means "not allocated"
510        for (int i=0 ; i < RoutingTableSize ; i++) {
511                tab[i] = 0xFF;
512        }
513        // printf ( " Local routing table cluster %x: tableau rempli de 0xFF \n",cluster);
514        // loop on the segment list
515        std::list<SEGMENT_TABLE_ENTRY>::iterator seg;
516        for (seg = segList.begin() ; seg != segList.end() ; ++seg) {
517                const char    *name   = (*seg).getName();
518                unsigned int  base    = (*seg).getBase();
519                unsigned int  size    = (*seg).getSize();
520                unsigned int localTarget  = (*seg).getLocalTarget();
521                unsigned int globalTarget = (*seg).getGlobalTarget();
522
523                unsigned int page = base >> (32 - MSBNumber - LSBNumber) ;
524               
525                for (int x = (int) size ; x > 0 ; x = x - PageSize) {               
526                          if(tab[page] != 0xFF) {
527                          // printf("\n page n° %x ne peut etre adressée à target n°%x car elle est allouée à %x \n",page,localTarget,tab[page]);       
528                          std::cerr << "Error in initLocalRoutingTable:" << std::endl ;
529                          std::cerr << "Segment " << name << " allocated to VCI target " << localTarget << std::endl;
530                          std::cerr << "overlap another segment... or is in the same page" << std::endl;
531                          std::cerr << "as another segment allocated to another VCI target" << std::endl;
532                          //sc_stop();
533                          } else {
534                                if (globalTarget==cluster){
535                                        tab[page] = localTarget;
536                                        // printf(" page n° %x adressée à target n°%x dans cluster %x i.e %s \n",page,tab[page],cluster,name);
537                                  }
538                          page = page + 1;
539                         
540                          }
541                } 
542        } // end loop segment list
543
544        for (int i=0 ; i < RoutingTableSize ; i++) {
545                if ((tab[i]==0xFF) && (defaultTargetGlobalIndex==cluster))
546                        tab[i]=defaultTargetLocalIndex;
547        }
548               
549};  // end initLocalRoutingTable()
550
551//////////////////////////////////////////////////////////////
552//              getSegmentList()
553//      returns the list of all segments
554//      allocated to a given VCI target.
555//      This method tests both the local and global VCI target index
556//////////////////////////////////////////////////////////////
557
558std::list<SEGMENT_TABLE_ENTRY> getSegmentList(unsigned int globalIndex,unsigned int localIndex){
559        std::list<SEGMENT_TABLE_ENTRY> targetlist;
560        std::list<SEGMENT_TABLE_ENTRY>::iterator segIterator;
561        unsigned int localTarget;
562        unsigned int globalTarget;
563       
564        for (segIterator = segList.begin() ; segIterator != segList.end() ; ++segIterator) {
565                localTarget=(*segIterator).getLocalTarget();
566                globalTarget=(*segIterator).getGlobalTarget();
567                if ((localTarget==localIndex)&&(globalTarget==globalIndex)){
568                        targetlist.push_back(*segIterator);
569                }
570        }
571        return(targetlist);
572       
573}; // end getSegmentList()
574
575////////////////////////////////////////////////////
576// function getTotalsegmentList
577// used to get the whole segmentlist
578///////////////////////////////////////////////////
579
580std::list<SEGMENT_TABLE_ENTRY> getTotalSegmentList()
581{
582
583return(segList);
584
585}; // end getSegmentList()
586
587////////////////////////////////////////////////////////////////
588//              initUncachedTable()
589//      This method can be used by any SoCLib processor.
590//      It initializes an "Uncached Table" that implements
591//      the address MSB bits decoding ROM.
592//      - The argument is a pointer to the bool table that
593//      has been allocated by the constructor of the processor.
594//      - Each ROM entry contains a boolean that is true when
595//      the adress Ris to an uncached segment.
596///////////////////////////////////////////////////////////////:
597
598void initUncachedTable(bool* tab) {
599        if ((MSBNumberCalled==false)||(LSBNumberCalled==false))
600                {
601                std::cerr << "ERROR in initUncachedTable:" << std::endl ;
602                std::cerr << "MSB or LSB number has not been defined !" << std::endl ;
603                //sc_stop();
604                }
605
606        int UncachedTableSize  = 1 << (MSBNumber+LSBNumber);
607        int PageSize           = 1 << (32 - (MSBNumber + LSBNumber));
608       
609        for (int i=0 ; i < UncachedTableSize ; i++) 
610                {
611                tab[i] = true;
612                }
613
614        std::list<SEGMENT_TABLE_ENTRY>::iterator iter;
615
616        for (   iter = segList.begin() ; 
617                iter != segList.end() ; 
618                ++iter)
619                {
620                unsigned int  base      = (*iter).getBase();
621                unsigned int  size      = (*iter).getSize();
622                bool          uncached  = (*iter).getUncached();
623
624                unsigned int page_index = base >> (32-((MSBNumber + LSBNumber))) ;
625
626                for (int x = (int) size ; x > 0 ; x = x - PageSize) 
627                        {                   
628                        tab[page_index] = uncached;
629                        page_index = page_index + 1;
630                        } 
631                } // end for segment list
632};  // end initUncachedTable()
633
634};  // end struct SOCLIB_SEGMENT_TABLE
635
636
637#endif
Note: See TracBrowser for help on using the repository browser.