source: soft/giet_vm/giet_common/utils.c @ 818

Last change on this file since 818 was 817, checked in by cfuguet, 9 years ago

Add some utility functions into giet_common/utils.

File size: 25.6 KB
RevLine 
[523]1///////////////////////////////////////////////////////////////////////////
[258]2// File     : utils.c
3// Date     : 18/10/2013
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
[523]6///////////////////////////////////////////////////////////////////////////
[258]7// The utils.c and utils.h files are part of the GIET-VM nano-kernel.
[523]8///////////////////////////////////////////////////////////////////////////
[258]9
[442]10#include <utils.h>
[455]11#include <tty0.h>
[258]12#include <giet_config.h>
[324]13#include <hard_config.h>
[258]14#include <mapping_info.h>
[442]15#include <tty_driver.h>
[258]16#include <ctx_handler.h>
17
[709]18// This variable is allocated in boot.c file or in kernel_init.c file
19extern static_scheduler_t*  _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX];
[258]20
[523]21///////////////////////////////////////////////////////////////////////////
[399]22//         CP0 registers access functions
[523]23///////////////////////////////////////////////////////////////////////////
[258]24
[709]25////////////////////////////////
26static_scheduler_t* _get_sched() 
[258]27{
28    unsigned int ret;
[295]29    asm volatile( "mfc0      %0,     $4,2    \n" 
30                  : "=r"(ret) );
[709]31
32    return (static_scheduler_t*)ret;
[258]33}
[408]34///////////////////////
[378]35unsigned int _get_epc() 
[258]36{
37    unsigned int ret;
[295]38    asm volatile( "mfc0      %0,    $14     \n"
39                  : "=r"(ret) );
[258]40    return ret;
41}
[408]42////////////////////////
[378]43unsigned int _get_bvar() 
[258]44{
45    unsigned int ret;
[295]46    asm volatile( "mfc0      %0,    $8     \n"
47                  : "=r"(ret));
[258]48    return ret;
49}
[408]50//////////////////////
[378]51unsigned int _get_cr() 
[258]52{
53    unsigned int ret;
[295]54    asm volatile( "mfc0      %0,    $13    \n"
55                  : "=r"(ret));
[258]56    return ret;
57}
[408]58//////////////////////
[378]59unsigned int _get_sr() 
[258]60{
61    unsigned int ret;
[295]62    asm volatile( "mfc0      %0,     $12   \n"
63                  : "=r"(ret));
[258]64    return ret;
65}
[408]66//////////////////////////
[378]67unsigned int _get_procid() 
[258]68{
69    unsigned int ret;
[295]70    asm volatile ( "mfc0     %0,     $15, 1  \n"
71                   :"=r" (ret) );
[430]72    return (ret & 0xFFF);
[258]73}
[408]74////////////////////////////
[378]75unsigned int _get_proctime() 
[258]76{
77    unsigned int ret;
[295]78    asm volatile ( "mfc0     %0,     $9      \n"
79                   :"=r" (ret) );
[258]80    return ret;
81}
[817]82////////////////////////////
83void _set_proctime( unsigned int val )
84{
85    asm volatile ( "mtc0     $0,     $9      \n"
86                   :
87                   :"r" (val));
88}
[408]89/////////////////////////////////////////////
[378]90void _it_disable( unsigned int * save_sr_ptr) 
[258]91{
[345]92    unsigned int sr = 0;
[295]93    asm volatile( "li      $3,        0xFFFFFFFE    \n"
94                  "mfc0    %0,        $12           \n"
95                  "and     $3,        $3,   %0      \n" 
96                  "mtc0    $3,        $12           \n" 
[345]97                  : "+r"(sr)
[295]98                  :
[345]99                  : "$3" );
[295]100    *save_sr_ptr = sr;
[258]101}
[408]102//////////////////////////////////////////////
[378]103void _it_restore( unsigned int * save_sr_ptr ) 
[295]104{
105    unsigned int sr = *save_sr_ptr;
106    asm volatile( "mtc0    %0,        $12           \n" 
107                  :
[301]108                  : "r"(sr)
109                  : "memory" );
[295]110}
111
[408]112/////////////////////////////////
[399]113void _set_sched(unsigned int val) 
114{
115    asm volatile ( "mtc0     %0,     $4, 2          \n"
116                   :
117                   :"r" (val) );
118}
[408]119//////////////////////////////
120void _set_sr(unsigned int val) 
121{
122    asm volatile ( "mtc0     %0,     $12            \n"
123                   :
124                   :"r" (val) );
125}
[399]126
[817]127void _cpu_sync()
128{
129    asm volatile("sync" ::: "memory");
130}
[408]131
[523]132///////////////////////////////////////////////////////////////////////////
[399]133//         CP2 registers access functions
[523]134///////////////////////////////////////////////////////////////////////////
[399]135
[408]136////////////////////////////
[399]137unsigned int _get_mmu_ptpr() 
138{
139    unsigned int ret;
140    asm volatile( "mfc2      %0,     $0      \n"
141                  : "=r"(ret) );
142    return ret;
143}
[408]144////////////////////////////
[399]145unsigned int _get_mmu_mode() 
146{
147    unsigned int ret;
148    asm volatile( "mfc2      %0,     $1      \n"
149                  : "=r"(ret) );
150    return ret;
151}
[408]152////////////////////////////////////
[378]153void _set_mmu_ptpr(unsigned int val) 
[258]154{
[408]155    asm volatile ( "mtc2     %0,     $0      \n"
[295]156                   :
[345]157                   :"r" (val)
158                   :"memory" );
[258]159}
[408]160////////////////////////////////////
[378]161void _set_mmu_mode(unsigned int val) 
[258]162{
[408]163    asm volatile ( "mtc2     %0,     $1      \n"
[295]164                   :
[345]165                   :"r" (val)
166                   :"memory" );
[258]167}
[408]168////////////////////////////////////////////
169void _set_mmu_dcache_inval(unsigned int val) 
170{
171    asm volatile ( "mtc2     %0,     $7      \n"
172                   :
173                   :"r" (val)
174                   :"memory" );
175}
[258]176
[408]177
[523]178///////////////////////////////////////////////////////////////////////////
[258]179//          Physical addressing related functions
[523]180///////////////////////////////////////////////////////////////////////////
[258]181
[442]182///////////////////////////////////////////////////////
[378]183unsigned int _physical_read( unsigned long long paddr ) 
[258]184{
185    unsigned int value;
186    unsigned int lsb = (unsigned int) paddr;
187    unsigned int msb = (unsigned int) (paddr >> 32);
[301]188    unsigned int sr;
[258]189
[301]190    _it_disable(&sr);
[258]191
[523]192    asm volatile( "mfc2   $2,     $1            \n"  /* $2 <= MMU_MODE   */
193                  "andi   $3,     $2,     0xb   \n"
194                  "mtc2   $3,     $1            \n"  /* DTLB off         */   
[258]195
[523]196                  "mtc2   %2,     $24           \n"  /* PADDR_EXT <= msb */   
197                  "lw     %0,     0(%1)         \n"  /* value <= *paddr  */
198                  "mtc2   $0,     $24           \n"  /* PADDR_EXT <= 0   */   
[344]199
[523]200                  "mtc2   $2,     $1            \n"  /* restore MMU_MODE */
[344]201                  : "=r" (value)
202                  : "r" (lsb), "r" (msb)
203                  : "$2", "$3" );
204
[301]205    _it_restore(&sr);
[258]206    return value;
207}
[442]208////////////////////////////////////////////////
[378]209void _physical_write( unsigned long long paddr, 
[430]210                      unsigned int       value ) 
[258]211{
212    unsigned int lsb = (unsigned int)paddr;
213    unsigned int msb = (unsigned int)(paddr >> 32);
[301]214    unsigned int sr;
[258]215
[430]216   _it_disable(&sr);
[258]217
[523]218    asm volatile( "mfc2   $2,     $1           \n"  /* $2 <= MMU_MODE   */
219                  "andi   $3,     $2,    0xb   \n"
220                  "mtc2   $3,     $1           \n"  /* DTLB off         */   
[258]221
[523]222                  "mtc2   %2,     $24          \n"  /* PADDR_EXT <= msb */   
223                  "sw     %0,     0(%1)        \n"  /* *paddr <= value  */
224                  "mtc2   $0,     $24          \n"  /* PADDR_EXT <= 0   */   
[344]225
[523]226                  "mtc2   $2,     $1           \n"  /* restore MMU_MODE */
227                  "sync                        \n"
[344]228                  :
229                  : "r" (value), "r" (lsb), "r" (msb)
230                  : "$2", "$3" );
231
[301]232    _it_restore(&sr);
[258]233}
234
[442]235/////////////////////////////////////////////////////////////////
[378]236unsigned long long _physical_read_ull( unsigned long long paddr ) 
[370]237{
238    unsigned int data_lsb;
239    unsigned int data_msb;
240    unsigned int addr_lsb = (unsigned int) paddr;
241    unsigned int addr_msb = (unsigned int) (paddr >> 32);
242    unsigned int sr;
243
244    _it_disable(&sr);
245
[523]246    asm volatile( "mfc2   $2,     $1           \n"  /* $2 <= MMU_MODE       */
247                  "andi   $3,     $2,    0xb   \n"
248                  "mtc2   $3,     $1           \n"  /* DTLB off             */   
[370]249
[523]250                  "mtc2   %3,     $24          \n"  /* PADDR_EXT <= msb     */   
251                  "lw     %0,     0(%2)        \n"  /* data_lsb <= *paddr   */
252                  "lw     %1,     4(%2)        \n"  /* data_msb <= *paddr+4 */
253                  "mtc2   $0,     $24          \n"  /* PADDR_EXT <= 0       */   
[370]254
[523]255                  "mtc2   $2,     $1           \n"  /* restore MMU_MODE     */
[370]256                  : "=r" (data_lsb), "=r"(data_msb)
257                  : "r" (addr_lsb), "r" (addr_msb)
258                  : "$2", "$3" );
259
260    _it_restore(&sr);
261
262    return ( (((unsigned long long)data_msb)<<32) +
263             (((unsigned long long)data_lsb)) );
264}
265
[442]266///////////////////////////////////////////////////
[378]267void _physical_write_ull( unsigned long long paddr, 
[399]268                          unsigned long long value ) 
[370]269{
270    unsigned int addr_lsb = (unsigned int)paddr;
271    unsigned int addr_msb = (unsigned int)(paddr >> 32);
272    unsigned int data_lsb = (unsigned int)value;
273    unsigned int data_msb = (unsigned int)(value >> 32);
274    unsigned int sr;
275
276    _it_disable(&sr);
277
[523]278    asm volatile( "mfc2   $2,     $1           \n"  /* $2 <= MMU_MODE     */
279                  "andi   $3,     $2,    0xb   \n"
280                  "mtc2   $3,     $1           \n"  /* DTLB off           */   
[370]281
[523]282                  "mtc2   %3,     $24          \n"  /* PADDR_EXT <= msb   */   
283                  "sw     %0,     0(%2)        \n"  /* *paddr <= value    */
284                  "sw     %1,     4(%2)        \n"  /* *paddr+4 <= value  */
285                  "mtc2   $0,     $24          \n"  /* PADDR_EXT <= 0     */   
[370]286
[523]287                  "mtc2   $2,     $1           \n"  /* restore MMU_MODE   */
288                  "sync                        \n"
[370]289                  :
[523]290                  : "r"(data_lsb),"r"(data_msb),"r"(addr_lsb),"r"(addr_msb)
[370]291                  : "$2", "$3" );
292
293    _it_restore(&sr);
294}
295
[442]296////////////////////////////////////////////////////
[523]297void _physical_memcpy( unsigned long long dst_paddr,  // dest buffer paddr
[399]298                       unsigned long long src_paddr,  // source buffer paddr
299                       unsigned int size )            // bytes
[344]300{
301    // check alignment constraints
302    if ( (dst_paddr & 3) || (src_paddr & 3) || (size & 3) ) 
303    {
[442]304        _puts("\n[GIET ERROR] in _physical_memcpy() : buffer unaligned\n");
[344]305        _exit();
306    }
307
308    unsigned int src_lsb = (unsigned int)src_paddr;
309    unsigned int src_msb = (unsigned int)(src_paddr >> 32);
310    unsigned int dst_lsb = (unsigned int)dst_paddr;
311    unsigned int dst_msb = (unsigned int)(dst_paddr >> 32);
312    unsigned int iter    = size>>2;
313    unsigned int data;
314    unsigned int sr;
315
316    _it_disable(&sr);
317
[523]318    asm volatile( "mfc2   $2,     $1         \n" /* $2 <= current MMU_MODE */
319                  "andi   $3,     $2,   0xb  \n" /* $3 <= new MMU_MODE     */
320                  "mtc2   $3,     $1         \n" /* DTLB off               */   
[344]321
[523]322                  "move   $4,     %5         \n" /* $4 < iter              */
323                  "move   $5,     %1         \n" /* $5 < src_lsb           */
324                  "move   $6,     %3         \n" /* $6 < src_lsb           */
[344]325
[523]326                  "ph_memcpy_loop:           \n"
327                  "mtc2   %2,     $24        \n" /* PADDR_EXT <= src_msb   */   
328                  "lw     %0,     0($5)      \n" /* data <= *src_paddr     */
329                  "mtc2   %4,     $24        \n" /* PADDR_EXT <= dst_msb   */   
330                  "sw     %0,     0($6)      \n" /* *dst_paddr <= data     */
[344]331
[523]332                  "addi   $4,     $4,   -1   \n" /* iter = iter - 1        */
333                  "addi   $5,     $5,   4    \n" /* src_lsb += 4           */
334                  "addi   $6,     $6,   4    \n" /* dst_lsb += 4           */
[344]335                  "bne    $4,     $0, ph_memcpy_loop \n"
[523]336                  "nop                       \n"
[344]337
[523]338                  "mtc2   $0,     $24        \n" /* PADDR_EXT <= 0         */   
339                  "mtc2   $2,     $1         \n" /* restore MMU_MODE       */
[344]340                  : "=r" (data)
[523]341                  : "r"(src_lsb),"r"(src_msb),"r"(dst_lsb),
342                    "r"(dst_msb), "r"(iter)
[344]343                  : "$2", "$3", "$4", "$5", "$6" );
344
345    _it_restore(&sr);
[430]346} // end _physical_memcpy()
[344]347
[442]348////////////////////////////////////////////////
[523]349void _physical_memset( unsigned long long paddr,     // dest buffer paddr
[430]350                       unsigned int       size,      // bytes
351                       unsigned int       data )     // written value
352{
353    // check alignment constraints
[433]354    if ( (paddr & 3) || (size & 7) )
[430]355    {
[442]356        _puts("\n[GIET ERROR] in _physical_memset() : buffer unaligned\n");
[430]357        _exit();
358    }
359
360    unsigned int lsb  = (unsigned int)paddr;
361    unsigned int msb  = (unsigned int)(paddr >> 32);
362    unsigned int sr;
363
364    _it_disable(&sr);
365
[523]366    asm volatile( "mfc2   $8,     $1         \n" /* $8 <= current MMU_MODE */
367                  "andi   $9,     $8,   0xb  \n" /* $9 <= new MMU_MODE     */
368                  "mtc2   $9,     $1         \n" /* DTLB off               */
369                  "mtc2   %3,     $24        \n" /* PADDR_EXT <= msb       */
[430]370
[523]371                  "1:                        \n" /* set 8 bytes per iter   */
372                  "sw     %2,     0(%0)      \n" /* *src_paddr     = data  */
373                  "sw     %2,     4(%0)      \n" /* *(src_paddr+4) = data  */
374                  "addi   %1,     %1,   -8   \n" /* size -= 8              */
375                  "addi   %0,     %0,    8   \n" /* src_paddr += 8         */
376                  "bnez   %1,     1b         \n" /* loop while size != 0   */
[430]377
[523]378                  "mtc2   $0,     $24        \n" /* PADDR_EXT <= 0         */
379                  "mtc2   $8,     $1         \n" /* restore MMU_MODE       */
[433]380                  : "+r"(lsb), "+r"(size)
381                  : "r"(data), "r" (msb)
382                  : "$8", "$9", "memory" );
[430]383
384    _it_restore(&sr);
[433]385}  // _physical_memset()
[430]386
[442]387///////////////////////////////////////////////
[378]388void _io_extended_write( unsigned int*  vaddr,
[399]389                         unsigned int   value )
[295]390{
391    unsigned long long paddr;
392
393    if ( _get_mmu_mode() & 0x4 )  // MMU activated : use virtual address
394    {
395        *vaddr = value;
396    }
397    else                          // use paddr extension for IO
398    {
399        paddr = (unsigned long long)(unsigned int)vaddr +
400                (((unsigned long long)((X_IO<<Y_WIDTH) + Y_IO))<<32); 
401        _physical_write( paddr, value );
402    }
403    asm volatile("sync" ::: "memory");
404}
405
[442]406//////////////////////////////////////////////////////
[378]407unsigned int _io_extended_read( unsigned int*  vaddr )
[295]408{
409    unsigned long long paddr;
410
411    if ( _get_mmu_mode() & 0x4 )  // MMU activated : use virtual address
412    {
413        return *(volatile unsigned int*)vaddr;
414    }
415    else                          // use paddr extension for IO
416    {
417        paddr = (unsigned long long)(unsigned int)vaddr +
418                (((unsigned long long)((X_IO<<Y_WIDTH) + Y_IO))<<32); 
419        return _physical_read( paddr );
420    }
421}
422
[523]423////////////////////////////////////////////////////////////////////////////
[709]424//           Scheduler and threads context access functions
[523]425////////////////////////////////////////////////////////////////////////////
[258]426
[430]427
[709]428///////////////////////////////
429unsigned int _get_thread_ltid() 
[258]430{
[709]431    static_scheduler_t* psched = (static_scheduler_t *) _get_sched();
432    return psched->current;
[258]433}
[442]434
[709]435////////////////////////////////
436unsigned int _get_thread_trdid() 
[258]437{
[709]438    static_scheduler_t* psched  = (static_scheduler_t *) _get_sched();
439    unsigned int        current = psched->current;
440    return psched->context[current].slot[CTX_TRDID_ID];
441}
442
443//////////////////////////////////////////////
444unsigned int _get_thread_slot( unsigned int x,
445                               unsigned int y,
446                               unsigned int p,
447                               unsigned int ltid,
448                               unsigned int slotid )
449{
[430]450    static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p];
[709]451    return psched->context[ltid].slot[slotid];
[258]452}
[442]453
[709]454//////////////////////////////////////
455void _set_thread_slot( unsigned int x,
456                       unsigned int y,
457                       unsigned int p,
458                       unsigned int ltid,
459                       unsigned int slotid,
460                       unsigned int value )
[258]461{
[430]462    static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p];
[709]463    psched->context[ltid].slot[slotid] = value;
[258]464}
[442]465
[709]466/////////////////////////////////////////////////////
467unsigned int _get_context_slot( unsigned int slotid )
[258]468{
469    static_scheduler_t* psched  = (static_scheduler_t*)_get_sched();
[709]470    unsigned int        ltid    = psched->current;
471    return psched->context[ltid].slot[slotid];
[258]472}
[442]473
[709]474////////////////////////////////////////////
475void _set_context_slot( unsigned int slotid,
476                        unsigned int value )
[258]477{
478    static_scheduler_t* psched  = (static_scheduler_t*)_get_sched();
[709]479    unsigned int        ltid    = psched->current;
480    psched->context[ltid].slot[slotid] = value;
[258]481}
482
483/////////////////////////////////////////////////////////////////////////////
484//      Access functions to mapping_info data structure
485/////////////////////////////////////////////////////////////////////////////
[442]486
487////////////////////////////////////////////////////////////////
[378]488mapping_cluster_t * _get_cluster_base(mapping_header_t * header) 
[258]489{
490    return (mapping_cluster_t *) ((char *) header +
491            MAPPING_HEADER_SIZE);
492}
[442]493//////////////////////////////////////////////////////////
[378]494mapping_pseg_t * _get_pseg_base(mapping_header_t * header) 
[258]495{
496    return (mapping_pseg_t *) ((char *) header +
497            MAPPING_HEADER_SIZE +
[263]498            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE);
[258]499}
[442]500//////////////////////////////////////////////////////////////
[378]501mapping_vspace_t * _get_vspace_base(mapping_header_t * header) 
[258]502{
503    return (mapping_vspace_t *)  ((char *) header +
504            MAPPING_HEADER_SIZE +
[263]505            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
[258]506            MAPPING_PSEG_SIZE * header->psegs);
507}
[442]508//////////////////////////////////////////////////////////
[378]509mapping_vseg_t * _get_vseg_base(mapping_header_t * header)
[258]510{
511    return (mapping_vseg_t *) ((char *) header +
512            MAPPING_HEADER_SIZE +
[263]513            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
[258]514            MAPPING_PSEG_SIZE * header->psegs +
515            MAPPING_VSPACE_SIZE * header->vspaces);
516}
[709]517//////////////////////////////////////////////////////////////
518mapping_thread_t * _get_thread_base(mapping_header_t * header) 
[258]519{
[709]520    return (mapping_thread_t *) ((char *) header +
[258]521            MAPPING_HEADER_SIZE +
[263]522            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
[258]523            MAPPING_PSEG_SIZE * header->psegs +
524            MAPPING_VSPACE_SIZE * header->vspaces +
525            MAPPING_VSEG_SIZE * header->vsegs);
526}
[442]527/////////////////////////////////////////////////////////
[378]528mapping_proc_t *_get_proc_base(mapping_header_t * header) 
[258]529{
530    return (mapping_proc_t *) ((char *) header +
531            MAPPING_HEADER_SIZE +
[263]532            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
[258]533            MAPPING_PSEG_SIZE * header->psegs +
534            MAPPING_VSPACE_SIZE * header->vspaces +
535            MAPPING_VSEG_SIZE * header->vsegs +
[709]536            MAPPING_THREAD_SIZE * header->threads);
[258]537}
[442]538///////////////////////////////////////////////////////
[378]539mapping_irq_t *_get_irq_base(mapping_header_t * header) 
[258]540{
541    return (mapping_irq_t *) ((char *) header +
542            MAPPING_HEADER_SIZE +
[263]543            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
[258]544            MAPPING_PSEG_SIZE * header->psegs +
545            MAPPING_VSPACE_SIZE * header->vspaces +
546            MAPPING_VSEG_SIZE * header->vsegs +
[709]547            MAPPING_THREAD_SIZE * header->threads +
[258]548            MAPPING_PROC_SIZE * header->procs);
549}
[442]550///////////////////////////////////////////////////////////////
[378]551mapping_periph_t *_get_periph_base(mapping_header_t * header) 
[258]552{
553    return (mapping_periph_t *) ((char *) header +
554            MAPPING_HEADER_SIZE +
[263]555            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
[258]556            MAPPING_PSEG_SIZE * header->psegs +
557            MAPPING_VSPACE_SIZE * header->vspaces +
558            MAPPING_VSEG_SIZE * header->vsegs +
[709]559            MAPPING_THREAD_SIZE * header->threads +
[258]560            MAPPING_PROC_SIZE * header->procs +
[523]561            MAPPING_IRQ_SIZE * header->irqs);
[258]562}
563
[523]564///////////////////////////////////////////////////////////////////////////
[442]565//             Miscelaneous functions
[523]566///////////////////////////////////////////////////////////////////////////
[399]567
[442]568//////////////////////////////////////
569__attribute__((noreturn)) void _exit() 
570{
[523]571    unsigned int procid = _get_procid();
572    unsigned int x      = (procid >> (Y_WIDTH + P_WIDTH)) & ((1<<X_WIDTH)-1);
573    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
574    unsigned int lpid   = procid & ((1<<P_WIDTH)-1);
[442]575
576
[734]577    _printf("\n[GIET PANIC] P[%d,%d,%d] suicide at cycle %d",
578            x , y , lpid , _get_proctime() );
[442]579
580    while (1) { asm volatile ("nop"); }
581}
582
583/////////////////////////////////////
[399]584void _random_wait( unsigned int val )
585{
586    unsigned int mask  = (1<<(val&0x1F))-1;
587    unsigned int delay = (_get_proctime() ^ (_get_procid()<<4)) & mask;
588    asm volatile( "move  $3,   %0                 \n"
589                  "loop_nic_completed:            \n"
[466]590                  "nop                            \n"
[399]591                  "addi  $3,   $3, -1             \n"
592                  "bnez  $3,   loop_nic_completed \n"
593                  "nop                            \n"
594                  :
595                  : "r" (delay)
596                  : "$3" ); 
597}
[442]598
[817]599/////////////////////////////////////
600void _sleep( unsigned int cycles )
601{
602    unsigned int delay = cycles;
603    asm volatile( ".set noreorder                 \n"
604                  "1:                             \n"
605                  "bnez  %0,   1b                 \n"
606                  "addi  %0,   %0,  -1            \n"
607                  ".set reorder                   \n"
608                  : "+r" (delay) );
609}
610
[442]611///////////////////////////
[399]612void _break( char* string ) 
613{
614    char byte;
615
[442]616    _puts("\n[GIET DEBUG] break from ");
617    _puts( string );
618    _puts(" / stoke any key to continue\n");
[399]619    _getc( &byte );
620}
621
[594]622////////////////////////////////////
623unsigned int _strlen( char* string )
624{
625    unsigned int i = 0;
626    while ( string[i] != 0 ) i++;
627    return i;
628}
629
[442]630///////////////////////////////////////
[618]631unsigned int _strcmp( const char * s1,
632                      const char * s2 )
633{
634    while (1)
635    {
636        if (*s1 != *s2) return 1;
637        if (*s1 == 0)   break;
638        s1++, s2++;
639    }
640    return 0;
641}
642
643///////////////////////////////////////
[399]644unsigned int _strncmp( const char * s1, 
645                       const char * s2, 
646                       unsigned int n ) 
647{
648    unsigned int i;
649    for (i = 0; i < n; i++) 
650    {
651        if (s1[i] != s2[i])  return 1; 
652        if (s1[i] == 0)      break;
653    }
654    return 0;
655}
656
[442]657/////////////////////////////////////////
[399]658char* _strcpy( char* dest, char* source )
659{
660    if (!dest || !source) return dest;
661
662    while (*source)
[594]663    {
664        *(dest) = *(source);
665        dest++;
666        source++;
667    }
668    *dest = 0;
[399]669    return dest;
670}
671
[442]672/////////////////////////////////////////////////////
[408]673void _dcache_buf_invalidate( unsigned int buf_vbase, 
674                             unsigned int buf_size ) 
[399]675{
[408]676    unsigned int offset;
[399]677    unsigned int tmp;
[408]678    unsigned int line_size;   // bytes
[399]679
680    // compute data cache line size based on config register (bits 12:10)
681    asm volatile(
682                 "mfc0 %0, $16, 1" 
683                 : "=r" (tmp) );
[408]684
[399]685    tmp = ((tmp >> 10) & 0x7);
686    line_size = 2 << tmp;
687
688    // iterate on cache lines
[408]689    for ( offset = 0; offset < buf_size; offset += line_size) 
[399]690    {
[408]691        _set_mmu_dcache_inval( buf_vbase + offset );
[399]692    }
693}
694
695
696
[495]697/////////////////////////////////////////////
698void _get_sqt_footprint( unsigned int* width,
699                         unsigned int* heigth,
700                         unsigned int* levels )
701{
702    mapping_header_t*   header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
703    mapping_cluster_t*  cluster = _get_cluster_base(header);
704
705    unsigned int x;
706    unsigned int y;
707    unsigned int cid;
708    unsigned int w = 0;
709    unsigned int h = 0;
710
711    // scan all clusters to compute SQT footprint (w,h)
712    for ( x = 0 ; x < X_SIZE ; x++ )
713    {
714        for ( y = 0 ; y < Y_SIZE ; y++ )
715        {
716            cid = x * Y_SIZE + y;
717            if ( cluster[cid].procs )  // cluster contains processors
718            {
719                if ( x > w ) w = x;
720                if ( y > h ) h = y;
721            }
722        }
723    }           
724    *width  = w + 1;
725    *heigth = h + 1;
726   
727    // compute SQT levels
728    unsigned int z = (h > w) ? h : w;
729    *levels = (z < 1) ? 1 : (z < 2) ? 2 : (z < 4) ? 3 : (z < 8) ? 4 : 5;
730}
731     
732
733
[523]734///////////////////////////////////////////////////////////////////////////
[399]735//   Required by GCC
[523]736///////////////////////////////////////////////////////////////////////////
[399]737
[442]738////////////////////////////////
[399]739void* memcpy( void*        dest,     // dest buffer vbase
740              const void*  source,   // source buffer vbase
741              unsigned int size )    // bytes
742{
743    unsigned int* idst = (unsigned int*)dest;
744    unsigned int* isrc = (unsigned int*)source;
745
[745]746    // word-by-word copy if both buffers are word aligned
[399]747    if (!((unsigned int) idst & 3) && !((unsigned int) isrc & 3)) 
748    {
749        while (size > 3) 
750        {
751            *idst++ = *isrc++;
752            size -= 4;
753        }
754    }
755
[745]756    unsigned char* cdst = (unsigned char*)idst;
757    unsigned char* csrc = (unsigned char*)isrc;
[399]758
[745]759    // byte-by-byte copy if size not multiple of 4 bytes
760    while (size) 
[399]761    {
762        *cdst++ = *csrc++;
[745]763        size--;
[399]764    }
[745]765
[399]766    return dest;
767}
[442]768
769/////////////////////////////////
[594]770void* memset( void*        dst, 
771              int          value, 
772              unsigned int count ) 
[399]773{
774    // word-by-word copy
[442]775    unsigned int* idst = dst;
[399]776    unsigned int  data = (((unsigned char)value)      ) |
777                         (((unsigned char)value) <<  8) |
778                         (((unsigned char)value) << 16) |
779                         (((unsigned char)value) << 24) ;
780
781    if ( ! ((unsigned int)idst & 3) )
782    {
783        while ( count > 3 )
784        {
785            *idst++ = data;
786            count -= 4;
787        }
788    }
789   
790    // byte-by-byte copy
[442]791    unsigned char* cdst = dst;
[399]792    while (count--) 
793    {
794        *cdst++ = (unsigned char)value;
795    }
[442]796    return dst;
[399]797}
798
799
[258]800// Local Variables:
801// tab-width: 4
802// c-basic-offset: 4
803// c-file-offsets:((innamespace . 0)(inline-open . 0))
804// indent-tabs-mode: nil
805// End:
806// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
807
Note: See TracBrowser for help on using the repository browser.