- Timestamp:
- Jul 10, 2014, 11:42:14 AM (10 years ago)
- Location:
- branches/fault_tolerance/softs
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/fault_tolerance/softs/giet_tsar/giet.S
r724 r745 4 4 * Date : 15/01/2014 5 5 ********************************************************************************* 6 * This is a very simple Interrupts/Exception/Traps handler for a generic 6 * This is a very simple Interrupts/Exception/Traps handler for a generic 7 7 * multi-clusters / multi-processors TSAR architecture (up to 256 clusters, 8 * up to 4 processors per cluster). 8 * up to 4 processors per cluster). 9 9 * The physical address is 40 bits, and the 8 MSB bits A[39:32] define the 10 10 * cluster index. … … 15 15 .section .giet,"ax",@progbits 16 16 .align 2 17 .global _interrupt_vector 17 .global _interrupt_vector 18 18 19 19 .extern seg_xcu_base … … 78 78 * System Call Handler 79 79 * 80 * As the GIET_TSAR does not support system calls, 80 * As the GIET_TSAR does not support system calls, 81 81 * an error message is displayed on TTY0, the program is killed. 82 82 ****************************************************************/ … … 97 97 98 98 mfc0 $4, $14 /* $4 <= EPC */ 99 la $5, _itoa_buffer /* $5 <= buffer address */ 99 la $5, _itoa_buffer /* $5 <= buffer address */ 100 100 addiu $5, $5, 2 /* skip the 0x prefix */ 101 101 jal _itoa_hex /* fill the buffer */ … … 108 108 nop 109 109 110 j _exit /* end of program */ 110 j _exit /* end of program */ 111 111 112 112 _itoa_buffer: .ascii "0x00000000" … … 122 122 * It makes the assumption that there is only one interrupt per 123 123 * entry in the interrupt vector (it can be PTI, HWI, or WTI). 124 * In case of a multi-clusters architecture, it exist one XCU 125 * per cluster, and the base address of the ICU segment depends 124 * In case of a multi-clusters architecture, it exist one XCU 125 * per cluster, and the base address of the ICU segment depends 126 126 * on both the cluster_xy and the proc_id: 127 127 * - base_address = seg_xcu_base + (32*local_id) + (4G*cluster_xy) … … 164 164 sw $31, 4*21($29) /* save $31 */ 165 165 mfc0 $27, $14 166 sw $27, 4*22($29) /* save EPC */ 166 sw $27, 4*22($29) /* save EPC */ 167 167 168 168 /* XICU PRIO register address computation */ … … 170 170 /* and we must use the physical address extension */ 171 171 mfc0 $10, $15, 1 /* $10 <= proc_id */ 172 andi $10, $10, 0x3FF /* at most 1024 processors */ 172 andi $10, $10, 0x3FF /* at most 1024 processors */ 173 173 li $11, NB_PROCS_MAX 174 174 divu $10, $11 … … 184 184 /* XCU[cluster_xy] access to get PRIO register value */ 185 185 mtc2 $12, $24 /* set PADDR extension */ 186 lw $15, ($26)/* $15 <= PRIO register value */186 lw $15, 0($26) /* $15 <= PRIO register value */ 187 187 mtc2 $0, $24 /* reset PADDR extension */ 188 188 … … 194 194 andi $27, $15, 0x4 /* test bit W in PRIO register */ 195 195 bne $27, $0, _int_WTI /* branch to WTI handler */ 196 196 197 197 /* exit interrupt handler: restore registers */ 198 198 _int_restore: … … 200 200 lw $1, 4*4($29) 201 201 .set at 202 lw $2, 4*5($29) 203 lw $3, 4*6($29) 202 lw $2, 4*5($29) 203 lw $3, 4*6($29) 204 204 lw $4, 4*7($29) 205 lw $5, 4*8($29) 205 lw $5, 4*8($29) 206 206 lw $6, 4*9($29) 207 lw $7, 4*10($29) 207 lw $7, 4*10($29) 208 208 lw $8, 4*11($29) 209 209 lw $9, 4*12($29) … … 217 217 lw $25, 4*20($29) 218 218 lw $31, 4*21($29) 219 lw $27, 4*22($29) /* get EPC */ 219 lw $27, 4*22($29) /* get EPC */ 220 220 addiu $29, $29, 23*4 /* restore SP */ 221 221 mtc0 $27, $14 /* restore EPC */ … … 233 233 la $27, _interrupt_vector 234 234 addu $26, $26, $27 235 lw $26, ($26) /* read ISR address */ 235 lw $26, ($26) /* read ISR address */ 236 236 jalr $26 /* call ISR */ 237 237 nop … … 246 246 la $27, _interrupt_vector 247 247 addu $26, $26, $27 /* $26 <= &ISR[HWI_INDEX */ 248 lw $26, ($26) /* read ISR address */ 248 lw $26, ($26) /* read ISR address */ 249 249 jalr $26 /* call ISR */ 250 250 nop … … 262 262 la $27, _interrupt_vector 263 263 addu $26, $26, $27 /* $26 <= &ISR[WTI_INDEX] */ 264 lw $26, ($26) /* read ISR address */ 264 lw $26, ($26) /* read ISR address */ 265 265 jalr $26 /* call ISR */ 266 266 nop 267 267 j _int_restore /* return from INT handler */ 268 268 nop 269 269 270 270 /* The default ISR is called when no specific ISR has been installed */ 271 271 /* in the interrupt vector. It simply displays a message on TTY0 */ … … 273 273 isr_default: 274 274 addiu $29, $29, -20 /* get space in stack */ 275 sw $31, 16($29) /* to save the return address */ 275 sw $31, 16($29) /* to save the return address */ 276 276 la $4, _msg_default /* $4 <= string address */ 277 277 addi $5, $0, 36 /* $5 <= string length */ 278 278 li $6, 0 /* $6 <= TTY0 */ 279 jal _tty_write 280 lw $31, 16($29) /* restore return address */ 279 jal _tty_write 280 lw $31, 16($29) /* restore return address */ 281 281 addiu $29, $29, 20 /* free space */ 282 282 jr $31 /* returns to interrupt handler */ … … 284 284 /**************************************************************** 285 285 * Interrupt Vector Table (indexed by interrupt index) 286 * 32 words corresponding to 32 ISR addresses 286 * 32 words corresponding to 32 ISR addresses 287 287 ****************************************************************/ 288 288 _interrupt_vector: … … 355 355 li $5, 36 /* $5 <= message length */ 356 356 li $6, 0 /* $6 <= TTY0 */ 357 jal _tty_write 357 jal _tty_write 358 358 nop 359 359 … … 362 362 li $5, 8 /* $5 <= message length */ 363 363 li $6, 0 /* $6 <= TTY0 */ 364 jal _tty_write 365 nop 366 364 jal _tty_write 365 nop 366 367 367 mfc0 $4, $14 /* $4 <= EPC value */ 368 368 la $5, _itoa_buffer /* $5 <= buffer address */ … … 377 377 nop 378 378 379 /* display BAR value */ 379 /* display BAR value */ 380 380 la $4, _msg_bar /* $4 <= message address */ 381 381 li $5, 8 /* $5 <= message length */ … … 385 385 386 386 mfc0 $4, $8 /* $4 <= BAR value */ 387 la $5, _itoa_buffer /* $5 <= buffer address */ 388 addiu $5, $5, 2 /* skip 0x prefix */ 387 la $5, _itoa_buffer /* $5 <= buffer address */ 388 addiu $5, $5, 2 /* skip 0x prefix */ 389 389 jal _itoa_hex /* fill buffer */ 390 390 nop … … 393 393 li $5, 10 /* $5 <= message length */ 394 394 li $6, 0 /* $6 <= TTY0 */ 395 jal _tty_write 396 nop 397 398 395 jal _tty_write 396 nop 397 398 399 399 /* release the lock on TTY0 */ 400 400 li $4, 0 -
branches/fault_tolerance/softs/giet_tsar/mips32_registers.h
r724 r745 58 58 /* CP2 registers */ 59 59 60 #define CP2_PTPR $0 60 #define CP2_PTPR $0 61 61 #define CP2_MODE $1 62 62 #define CP2_ICACHE_FLUSH $2 63 63 #define CP2_DCACHE_FLUSH $3 64 #define CP2_ITLB_INVAL $4 65 #define CP2_DTLB_INVAL $5 66 #define CP2_ICACHE_INVAL $6 64 #define CP2_ITLB_INVAL $4 65 #define CP2_DTLB_INVAL $5 66 #define CP2_ICACHE_INVAL $6 67 67 #define CP2_DCACHE_INVAL $7 68 #define CP2_ICACHE_PREFETCH $8 69 #define CP2_DCACHE_PREFETCH $9 70 #define CP2_SYNC $10 71 #define CP2_IETR $11 72 #define CP2_DETR $12 68 #define CP2_ICACHE_PREFETCH $8 69 #define CP2_DCACHE_PREFETCH $9 70 #define CP2_SYNC $10 71 #define CP2_IETR $11 72 #define CP2_DETR $12 73 73 #define CP2_IBVAR $13 74 74 #define CP2_DBVAR $14 75 #define CP2_PARAMS $15 76 #define CP2_RELEASE $16 77 #define CP2_DATA_LO $17 78 #define CP2_DATA_HI $18 79 #define CP2_ICACHE_INVAL_PA $19 80 #define CP2_DCACHE_INVAL_PA $20 75 #define CP2_PARAMS $15 76 #define CP2_RELEASE $16 77 #define CP2_DATA_LO $17 78 #define CP2_DATA_HI $18 79 #define CP2_ICACHE_INVAL_PA $19 80 #define CP2_DCACHE_INVAL_PA $20 81 81 #define CP2_PADDR_EXT $24 82 82 #endif -
branches/fault_tolerance/softs/giet_tsar/reset.S
r724 r745 1 1 /******************************************************************************** 2 * 3 * 4 * 2 * File : reset.S 3 * Author : Alain Greiner 4 * Date : 15/01/2014 5 5 ********************************************************************************* 6 6 * This is a boot code for a generic multi-clusters / multi-processors 7 * TSAR architecture (up to 256 clusters / up to 4 processors per cluster). 7 * TSAR architecture (up to 256 clusters / up to 4 processors per cluster). 8 8 * The physical address is 40 bits, and the 8 MSB bits A[39:32] define the 9 9 * cluster index. 10 10 * 11 * As we don't want to use the virtual memory, the physical address is 11 * As we don't want to use the virtual memory, the physical address is 12 12 * equal to the virtual address (identity mapping) and all processors stacks 13 * and code segments are allocated in the physical memory bank in cluster 0. 13 * and code segments are allocated in the physical memory bank in cluster 0. 14 14 * 15 15 * Both the reset base address and the kernel base address must be redefined … … 22 22 * There is two sets of peripherals: 23 23 * 24 * 1) A block device and a single channel TTY controller are available 24 * 1) A block device and a single channel TTY controller are available 25 25 * in cluster(0,0). 26 26 * 27 * 2) Other peripherals (including another Blockdevice, a multi-channels TTY 27 * 2) Other peripherals (including another Blockdevice, a multi-channels TTY 28 28 * contrÃŽler, a Frame buffer) are located in cluster_io. 29 29 * For those externals peripherals, hardware interrupts (HWI) are translated … … 34 34 * - Each processor initializes the stack pointer ($29) depending on proc_id. 35 35 * - Each processor initializes the CP0 EBASE register 36 * 36 * - Only processor 0 initializes the Interrupt vector. 37 37 * - Only processor 0 initializes the IOPIC component. 38 38 * - Each processor initializes its private XCU mask. 39 * - Each processor initializes the Status Register (SR)40 * 39 * - Each processor initializes the Status Register (SR) 40 * - Each processor jumps to the same main address in kernel mode... 41 41 ********************************************************************************/ 42 42 … … 44 44 #include "mips32_registers.h" 45 45 46 46 .section .reset,"ax",@progbits 47 47 48 .externseg_stack_base49 .externseg_xcu_base48 .extern seg_stack_base 49 .extern seg_xcu_base 50 50 .extern seg_pic_base 51 51 .extern seg_kcode_base 52 53 54 52 .extern _interrupt_vector 53 .extern _ioc_isr 54 .extern _mmc_isr 55 55 .extern _tty_isr 56 56 .extern main 57 57 58 .globl reset 59 .entreset60 .align258 .globl reset 59 .ent reset 60 .align 2 61 61 62 62 reset: 63 63 .set noreorder 64 64 65 65 /* each proc computes proc_id, lpid, cluster_xy */ 66 66 mfc0 $26, CP0_PROCID 67 andi $26, $26, 0x3FF 67 andi $26, $26, 0x3FF /* at most 1024 processors */ 68 68 move $10, $26 /* $10 <= proc_id */ 69 69 li $27, NB_PROCS_MAX … … 73 73 74 74 /* each proc initializes stack pointer (64K per processor) */ 75 srl $8, $12, Y_WIDTH /* $8 <= x */ 76 li $9, Y_SIZE 77 mul $8, $8, $9 /* $8 <= x * Y_SIZE */ 78 andi $13, $12, (1<<Y_WIDTH)-1 79 addu $8, $8, $13 /* $8 <= x * Y_SIZE + y */ 80 mul $8, $8, $27 /* $8 <= (x*Y_SIZE+y)*NB_PROCS_MAX */ 81 addu $10, $11, $8 /* $10 <= (x*Y_SIZE+y)*NB_PROCS_MAX + lpid */ 82 75 83 la $27, seg_stack_base 76 addi $26, $10, 1 84 addi $26, $10, 1 /* $26 <= (proc_id + 1) */ 77 85 sll $26, $26, 14 /* $26 <= (proc_id + 1) * 16K */ 78 addu $29, $27, $26 86 addu $29, $27, $26 /* $29 <= seg_stack_base(proc_id) */ 79 87 80 88 /* each proc initializes CP0 EBASE register */ … … 83 91 84 92 /* only proc (0,0,0) initializes interrupt vector for IOC, TTY, MMC */ 85 bne 93 bne $10, $0, reset_xcu 86 94 nop 87 95 88 96 la $26, _interrupt_vector /* interrupt vector address */ 89 la $27, _mmc_isr 97 la $27, _mmc_isr 90 98 sw $27, 32($26) /* interrupt_vector[8] <= _mmc_isr */ 91 la $27, _ioc_isr 99 la $27, _ioc_isr 92 100 sw $27, 36($26) /* interrupt_vector[9] <= _ioc_isr */ 93 la $27, _tty_isr 101 la $27, _tty_isr 94 102 sw $27, 40($26) /* interrupt_vector[10] <= _tty_isr */ 95 103 96 104 /* only proc (0,0,0) initializes IOPIC : IOPIC_ADDRESS[i] <= &XICU[0].WTI_REG[i] */ 97 105 98 li $26, USE_EXT_IO 99 beq $26, $0, reset_xcu /* IOPIC not initialised if not USE_EXT_IO */ 106 #if USE_IOPIC 100 107 101 108 li $20, X_SIZE … … 120 127 121 128 mtc2 $0, CP2_PADDR_EXT /* CP2_PADDR_EXT <= zero */ 122 129 130 #endif 131 123 132 reset_xcu: 124 133 … … 140 149 141 150 /* initializes SR register */ 142 li $26, 0x0000FF01143 mtc0 $26, $12 151 li $26, 0x0000FF01 152 mtc0 $26, $12 /* SR <= kernel mode / IRQ enable */ 144 153 145 154 /* jumps to main in kernel mode */ 146 la 155 la $26, main 147 156 jr $26 148 157 nop 149 158 150 .end 159 .end reset 151 160 152 161 .set reorder -
branches/fault_tolerance/softs/giet_tsar/stdio.c
r724 r745 1 1 //////////////////////////////////////////////////////////////////////////////////////// 2 2 // File : stdio.c 3 // Written by Alain Greiner 4 // Date : janvier 2014 3 // Written by Alain Greiner 4 // Date : janvier 2014 5 5 // 6 6 // This file defines various functions that can be used by applications to access … … 22 22 // - NB_PROCS_MAX : max number of processor per cluster 23 23 // - NB_TTY_CHANNELS : max number of TTY channels 24 // - USE_EXT_IO : use external peripherals if not zero25 24 // 26 25 // The follobing base addresses must be defined in the ldscript … … 36 35 #endif 37 36 38 #if !defined( USE_EXT_IO)39 #error: you must define USE_EXT_IO in the hard_config.h file37 #if !defined(X_IO) || !defined(Y_IO) 38 #error: you must define X_IO and Y_IO in the hard_config.h file 40 39 #endif 41 40 … … 68 67 #endif 69 68 70 71 72 73 69 #define NB_LOCKS 256 74 70 #define NB_BARRIERS 16 … … 82 78 83 79 struct plouf; 84 85 extern struct plouf seg_tty_base; 86 extern struct plouf seg_fbf_base; 87 extern struct plouf seg_ioc_base; 88 extern struct plouf seg_mmc_base; 89 extern struct plouf seg_ramdisk_base; 80 extern volatile struct plouf seg_tty_base; 81 extern volatile struct plouf seg_fbf_base; 82 extern volatile struct plouf seg_ioc_base; 83 extern volatile struct plouf seg_mmc_base; 84 extern volatile struct plouf seg_ramdisk_base; 90 85 91 86 //////////////////////////////////////////////////////////////////////////////////////// … … 93 88 //////////////////////////////////////////////////////////////////////////////////////// 94 89 95 in_unckdata int volatile_ioc_lock = 0;96 in_unckdata int volatile_ioc_done = 0;97 in_unckdata int volatile_ioc_status;98 99 in_unckdata char volatile_tty_get_buf[NB_TTY_CHANNELS];100 in_unckdata int volatile_tty_get_full[NB_TTY_CHANNELS] = { [0 ... NB_TTY_CHANNELS-1] = 0 };90 static in_unckdata int volatile _ioc_lock = 0; 91 static in_unckdata int volatile _ioc_done = 0; 92 static in_unckdata int volatile _ioc_status; 93 94 static in_unckdata char volatile _tty_get_buf[NB_TTY_CHANNELS]; 95 static in_unckdata int volatile _tty_get_full[NB_TTY_CHANNELS] = { [0 ... NB_TTY_CHANNELS-1] = 0 }; 101 96 102 97 //////////////////////////////////////////////////////////////////////////////////////// … … 104 99 //////////////////////////////////////////////////////////////////////////////////////// 105 100 106 in_unckdata int volatile _barrier_value[NB_BARRIERS]= { [0 ... NB_BARRIERS-1] = 0 };107 in_unckdata int volatile _barrier_count[NB_BARRIERS]= { [0 ... NB_BARRIERS-1] = 0 };108 in_unckdata int volatile _barrier_lock[NB_BARRIERS]= { [0 ... NB_BARRIERS-1] = 0 };101 static in_unckdata int volatile _barrier_value[NB_BARRIERS] = { [0 ... NB_BARRIERS-1] = 0 }; 102 static in_unckdata int volatile _barrier_count[NB_BARRIERS] = { [0 ... NB_BARRIERS-1] = 0 }; 103 static in_unckdata int volatile _barrier_lock[NB_BARRIERS] = { [0 ... NB_BARRIERS-1] = 0 }; 109 104 110 105 //////////////////////////////////////////////////////////////////////////////////////// … … 112 107 //////////////////////////////////////////////////////////////////////////////////////// 113 108 114 in_unckdata int volatile _spin_lock[NB_LOCKS] ={ [0 ... NB_LOCKS-1] = 0 };109 static in_unckdata int volatile _spin_lock[NB_LOCKS] = { [0 ... NB_LOCKS-1] = 0 }; 115 110 116 111 //////////////////////////////////////////////////////////////////////////////////////// 117 112 // Memcopy taken from MutekH. 118 113 //////////////////////////////////////////////////////////////////////////////////////// 119 in_drivers void* _memcpy( void* _dst, 120 const void* _src, 114 in_drivers void* _memcpy( void* _dst, 115 const void* _src, 121 116 unsigned int size ) 122 117 { … … 125 120 if ( ! ((unsigned int)dst & 3) && ! ((unsigned int)src & 3) ) 126 121 { 127 while (size > 3) 122 while (size > 3) 128 123 { 129 124 *dst++ = *src++; … … 135 130 unsigned char *csrc = (unsigned char*)src; 136 131 137 while (size--) 132 while (size--) 138 133 { 139 134 *cdst++ = *csrc++; … … 146 141 in_drivers void _extended_memcpy( unsigned int dst_cluster, 147 142 unsigned int dst_address, 148 unsigned int src_cluster,149 143 unsigned int src_address, 150 144 unsigned int length ) … … 189 183 // Returns the number of processsors controled by the GIET 190 184 //////////////////////////////////////////////////////////////////////////////////////// 191 in_drivers unsigned int _procnumber()185 in_drivers inline unsigned int _procnumber() 192 186 { 193 187 return (unsigned int)(NB_PROCS_MAX * X_SIZE * Y_SIZE); … … 205 199 } 206 200 //////////////////////////////////////////////////////////////////////////////////////// 201 // Access CP0 and enable IRQs 202 //////////////////////////////////////////////////////////////////////////////////////// 203 in_drivers inline void _it_enable() 204 { 205 asm volatile( 206 "mfc0 $8, $12 \n" 207 "ori $8, $8, 1 \n" 208 "mtc0 $8, $12 \n" 209 ::: "$8"); 210 } 211 //////////////////////////////////////////////////////////////////////////////////////// 207 212 // Access CP0 and mask IRQs 208 213 //////////////////////////////////////////////////////////////////////////////////////// 209 in_drivers void _it_mask() 210 { 211 int tmp; 212 asm volatile("mfc0 %0, $12" : "=r" (tmp) ); 213 asm volatile("ori %0, %0, 1" : "=r" (tmp) ); 214 asm volatile("mtc0 %0, $12" : "=r" (tmp) ); 215 } 216 //////////////////////////////////////////////////////////////////////////////////////// 217 // Access CP0 and enable IRQs 218 //////////////////////////////////////////////////////////////////////////////////////// 219 in_drivers void _it_enable() 220 { 221 int tmp; 222 asm volatile("mfc0 %0, $12" : "=r" (tmp) ); 223 asm volatile("addi %0, %0, -1" : "=r" (tmp) ); 224 asm volatile("mtc0 %0, $12" : "=r" (tmp) ); 225 } 214 in_drivers inline void _it_disable() 215 { 216 asm volatile( 217 "li $9, 0xFFFFFFFE \n" 218 "mfc0 $8, $12 \n" 219 "and $8, $8, $9 \n" 220 "mtc0 $8, $12 \n" 221 ::: "$8","$9"); 222 } 223 224 //////////////////////////////////////////////////////////////////////////////////////// 225 // Access CP0 and mask IRQs 226 //////////////////////////////////////////////////////////////////////////////////////// 227 in_drivers inline void _sr_write(int sr) 228 { 229 asm volatile("mtc0 %0, $12 \n" : /* no outputs */ : "r" (sr)); 230 } 231 232 in_drivers inline int _sr_read() 233 { 234 int ret; 235 asm volatile("mfc0 %0, $12 \n" : "=r" (ret)); 236 return ret; 237 } 238 226 239 ////////////////////////////////////////////////////////////////////// 227 240 // Invalidate all cache lines corresponding to a memory buffer. … … 246 259 247 260 //////////////////////////////////////////////////////////////////////////// 248 // This function makes a physical read access to a 32 bits word in memory, 261 // This function makes a physical read access to a 32 bits word in memory, 249 262 // after a temporary paddr extension. 250 263 //////////////////////////////////////////////////////////////////////////// 251 in_drivers unsigned int _word_extended_read( unsigned int cluster, 252 unsigned int address ) 253 { 254 unsigned int value; 264 in_drivers volatile unsigned int _word_extended_read( unsigned int cluster, 265 unsigned int address ) 266 { 267 int sr = _sr_read(); 268 volatile unsigned int value; 255 269 asm volatile( 256 270 "li $3, 0xFFFFFFFE \n" 257 "mfc0 $2, $12 \n" 258 "and $3, $2, $3 \n" 271 "and $3, %3, $3 \n" 259 272 "mtc0 $3, $12 \n" /* IRQ disabled */ 260 273 261 "mtc2 %2, $24 \n" /* PADDR_EXT <= msb */ 274 "mtc2 %2, $24 \n" /* PADDR_EXT <= msb */ 262 275 "lw %0, 0(%1) \n" /* value <= *paddr */ 263 276 "mtc2 $0, $24 \n" /* PADDR_EXT <= 0 */ 264 277 265 "li $3, 0x00000001 \n"266 "mfc0 $2, $12 \n"267 "or $3, $3, $2 \n"268 "mtc0 $3, $12 \n" /* IRQ enabled */269 278 : "=r" (value) 270 : "r" (address), "r" (cluster) 271 : "$2", "$3" ); 279 : "r" (address), "r" (cluster), "r" (sr) 280 : "$2", "$3", "memory" ); 281 282 _sr_write(sr); 272 283 return value; 273 284 } 274 285 //////////////////////////////////////////////////////////////////////////// 275 // This function makes a physical read access to a single byte in memory, 286 // This function makes a physical read access to a single byte in memory, 276 287 // after a temporary paddr extension. 277 288 //////////////////////////////////////////////////////////////////////////// 278 in_drivers unsigned char _byte_extended_read( unsigned int cluster, 279 unsigned int address ) 280 { 281 unsigned int value; 289 in_drivers volatile unsigned char _byte_extended_read( unsigned int cluster, 290 unsigned int address ) 291 { 292 int sr = _sr_read(); 293 volatile unsigned char value; 282 294 asm volatile( 283 295 "li $3, 0xFFFFFFFE \n" 284 "mfc0 $2, $12 \n" 285 "and $3, $2, $3 \n" 296 "and $3, %3, $3 \n" 286 297 "mtc0 $3, $12 \n" /* IRQ disabled */ 287 298 288 "mtc2 %2, $24 \n" /* PADDR_EXT <= msb */ 299 "mtc2 %2, $24 \n" /* PADDR_EXT <= msb */ 289 300 "lb %0, 0(%1) \n" /* value <= *paddr */ 290 301 "mtc2 $0, $24 \n" /* PADDR_EXT <= 0 */ 291 302 292 "li $3, 0x00000001 \n"293 "mfc0 $2, $12 \n"294 "or $3, $3, $2 \n"295 "mtc0 $3, $12 \n" /* IRQ enabled */296 303 : "=r" (value) 297 : "r" (address), "r" (cluster) 298 : "$2", "$3" ); 299 return (unsigned char)value; 304 : "r" (address), "r" (cluster), "r" (sr) 305 : "$2", "$3", "memory" ); 306 307 _sr_write(sr); 308 return value; 300 309 } 301 310 //////////////////////////////////////////////////////////////////////////// 302 // This function makes a physical write access to a 32 bits word in memory, 311 // This function makes a physical write access to a 32 bits word in memory, 303 312 // after a temporary DTLB address extension. 304 313 //////////////////////////////////////////////////////////////////////////// 305 in_drivers void _word_extended_write( unsigned int cluster, 314 in_drivers void _word_extended_write( unsigned int cluster, 306 315 unsigned int address, 307 unsigned int word ) 308 { 316 unsigned int word ) 317 { 318 int sr = _sr_read(); 309 319 asm volatile( 310 320 "li $3, 0xFFFFFFFE \n" 311 "mfc0 $2, $12 \n" 312 "and $3, $2, $3 \n" 321 "and $3, %3, $3 \n" 313 322 "mtc0 $3, $12 \n" /* IRQ disabled */ 314 323 315 "mtc2 %2, $24 \n" /* PADDR_EXT <= msb */ 324 "mtc2 %2, $24 \n" /* PADDR_EXT <= msb */ 316 325 "sw %0, 0(%1) \n" /* *paddr <= value */ 317 "mtc2 $0, $24 \n" /* PADDR_EXT <= 0 */ 318 319 "li $3, 0x00000001 \n" 320 "mfc0 $2, $12 \n" 321 "or $3, $2, $3 \n" 322 "mtc0 $3, $12 \n" /* IRQ enabled */ 326 "mtc2 $0, $24 \n" /* PADDR_EXT <= 0 */ 327 328 "sync \n" 323 329 : 324 : "r" (word), "r" (address), "r" (cluster) 325 : "$2", "$3"); 330 : "r" (word), "r" (address), "r" (cluster), "r" (sr) 331 : "$2", "$3", "memory"); 332 333 _sr_write(sr); 326 334 } 327 335 //////////////////////////////////////////////////////////////////////////// 328 // This function makes a physical write access to single byte in memory, 336 // This function makes a physical write access to single byte in memory, 329 337 // after a temporary DTLB de-activation and address extension. 330 338 //////////////////////////////////////////////////////////////////////////// 331 in_drivers void _byte_extended_write( unsigned int cluster, 339 in_drivers void _byte_extended_write( unsigned int cluster, 332 340 unsigned int address, 333 unsigned char byte ) 334 { 341 unsigned char byte ) 342 { 343 int sr = _sr_read(); 335 344 asm volatile( 336 345 "li $3, 0xFFFFFFFE \n" 337 "mfc0 $2, $12 \n" 338 "and $3, $2, $3 \n" 346 "and $3, %3, $3 \n" 339 347 "mtc0 $3, $12 \n" /* IRQ disabled */ 340 348 341 "mtc2 %2, $24 \n" /* PADDR_EXT <= msb */ 349 "mtc2 %2, $24 \n" /* PADDR_EXT <= msb */ 342 350 "sb %0, 0(%1) \n" /* *paddr <= value */ 343 "mtc2 $0, $24 \n" /* PADDR_EXT <= 0 */ 344 345 "li $3, 0x00000001 \n" 346 "mfc0 $2, $12 \n" 347 "or $3, $2, $3 \n" 348 "mtc0 $3, $12 \n" /* IRQ enabled */ 351 "mtc2 $0, $24 \n" /* PADDR_EXT <= 0 */ 352 353 "sync \n" 349 354 : 350 : "r" (byte), "r" (address), "r" (cluster) 351 : "$2", "$3"); 352 } 353 354 /////////////////////////////////////////////////////////////////////////////////////// 355 // Exit (suicide) after printing message on TTY0 355 : "r" (byte), "r" (address), "r" (cluster), "r" (sr) 356 : "$2", "$3", "memory"); 357 358 _sr_write(sr); 359 } 360 361 /////////////////////////////////////////////////////////////////////////////////////// 362 // Exit (suicide) after printing message on TTY0 356 363 /////////////////////////////////////////////////////////////////////////////////////// 357 364 in_drivers void _exit() … … 410 417 // - If there is only one terminal, it is supposed to be shared, and used by 411 418 // all processors: a lock must be taken before display. 412 // - If there is several terminals, and the number of processors is smaller 413 // than the number of terminals, there is one terminal per processor, but 419 // - If there is several terminals, and the number of processors is smaller 420 // than the number of terminals, there is one terminal per processor, but 414 421 // the TTY index is not equal to the proc_id, due to cluster indexing policy: 415 422 // proc_id = cluster_xy * NB_PROCS_MAX + local_id (with cluster_xy = x << Y_WIDTH + y) 416 423 // tty_id = cluster_id * NB_PROCS_MAX + local_id (with cluster_id = x * Y_SIZE + y) 417 424 // - If the computed tty_id is larger than NB_TTY_CHANNELS, an error is returned. 418 ///////////////////////////////////////////////////////////////////////////////////////419 // If USE_EXT_IO is set, we use the TTY controler implemented in cluster_io420 // (x = X_SIZE-1 / y = Y_SIZE), which requires and extended address access.421 // If USE_EXT_IO not set, we use the single channel TTY contrÃŽler in cluster (0,0).422 425 /////////////////////////////////////////////////////////////////////////////////////// 423 426 … … 430 433 // returns the number of characters that have been actually written. 431 434 /////////////////////////////////////////////////////////////////////////////////////// 432 in_drivers int _tty_write( char* buffer, 433 unsigned int length, 435 in_drivers int _tty_write( char* buffer, 436 unsigned int length, 434 437 unsigned int channel ) 435 438 { 436 unsigned int base = (unsigned int)&seg_tty_base + channel*TTY_SPAN*4; 437 unsigned int nwritten = 0; 438 unsigned int cluster_io = ((X_SIZE-1)<<Y_WIDTH) + Y_SIZE; 439 unsigned int base = (unsigned int)&seg_tty_base + channel*TTY_SPAN*4; 440 unsigned int nwritten = 0; 439 441 unsigned int status; 440 unsigned int 442 unsigned int i; 441 443 442 444 for ( i=0 ; i < length ; i++ ) 443 445 { 444 if( USE_EXT_IO ) // extended addressing to reach cluster_io 446 status = _word_extended_read( CLUSTER_IO, base + TTY_STATUS*4 ); 447 if ( (status & 0x2) == 0x2 ) break; 448 else 445 449 { 446 status = _word_extended_read( cluster_io, base + TTY_STATUS*4 ); 447 if ( (status & 0x2) == 0x2 ) break; 448 else 449 { 450 _byte_extended_write( cluster_io, base + TTY_WRITE*4 , buffer[i] ); 451 nwritten++; 452 } 453 } 454 else // direct addressing to cluster(0,0) 455 { 456 char* tty = (char*)base; 457 if ( (tty[TTY_STATUS*4] & 0x2) == 0x2 ) break; 458 else 459 { 460 tty[TTY_WRITE*4] = buffer[i]; // write character 461 nwritten++; 462 } 450 _byte_extended_write( CLUSTER_IO, base + TTY_WRITE*4 , buffer[i] ); 451 nwritten++; 463 452 } 464 453 } … … 474 463 // and returns 1 if the register is full. 475 464 /////////////////////////////////////////////////////////////////////////////////////// 476 in_drivers int _tty_read( char* buffer, 465 in_drivers int _tty_read( char* buffer, 477 466 unsigned int channel ) 478 467 { 479 unsigned int base = (unsigned int)&seg_tty_base + channel*TTY_SPAN*4; 480 unsigned int cluster_io = ((X_SIZE-1)<<Y_WIDTH) + Y_SIZE; 481 unsigned int status; 482 483 if( USE_EXT_IO ) 484 { 485 status = _word_extended_read( cluster_io, base + TTY_STATUS*4 ); 486 if ( (status & 0x1) == 0x1 ) 487 { 488 buffer[0] = (char)_word_extended_read( cluster_io, base + TTY_READ*4 ); 489 return 1; 490 } 491 else 492 { 493 return 0; 494 } 495 } 496 else 497 { 498 char* tty = (char*)base; 499 500 if((tty[TTY_STATUS*4] & 0x1) == 0x1) 501 { 502 buffer[0] = tty[TTY_READ*4]; 503 return 1; 504 } 505 else 506 { 507 return 0; 508 } 509 } 468 unsigned int base = (unsigned int)&seg_tty_base + channel*TTY_SPAN*4; 469 unsigned int status; 470 471 status = _word_extended_read( CLUSTER_IO, base + TTY_STATUS*4 ); 472 if ( (status & 0x1) == 0x1 ) 473 { 474 buffer[0] = (char)_word_extended_read( CLUSTER_IO, base + TTY_READ*4 ); 475 return 1; 476 } 477 return 0; 510 478 } 511 479 … … 524 492 // This function displays a 32 bits unsigned int as an hexa string on TTY0. 525 493 /////////////////////////////////////////////////////////////////////////////// 526 in_drivers void _tty_putx(unsigned int val) 494 in_drivers void _tty_putx(unsigned int val) 527 495 { 528 496 static const char HexaTab[] = "0123456789ABCDEF"; … … 534 502 buf[10] = 0; 535 503 536 for (c = 0; c < 8; c++) 537 { 504 for (c = 0; c < 8; c++) 505 { 538 506 buf[9 - c] = HexaTab[val & 0xF]; 539 507 val = val >> 4; … … 545 513 // This function displays a 32 bits unsigned int as a decimal string on TTY0. 546 514 /////////////////////////////////////////////////////////////////////////////// 547 in_drivers void _tty_putd( unsigned int val ) 515 in_drivers void _tty_putd( unsigned int val ) 548 516 { 549 517 static const char DecTab[] = "0123456789"; 550 518 char buf[11]; 551 519 unsigned int i; 552 unsigned int first ;520 unsigned int first = 0; 553 521 554 522 buf[10] = 0; 555 523 556 for (i = 0; i < 10; i++) 557 { 558 if ((val != 0) || (i == 0)) 524 for (i = 0; i < 10; i++) 525 { 526 if ((val != 0) || (i == 0)) 559 527 { 560 528 buf[9 - i] = DecTab[val % 10]; 561 529 first = 9 - i; 562 530 } 563 else 531 else 564 532 { 565 533 break; … … 571 539 572 540 ////////////////////////////////////////////////////////////////////////////// 573 // This function try to take the hardwired lock protecting exclusive access 541 // This function try to take the hardwired lock protecting exclusive access 574 542 // to TTY terminal identified by the channel argument. 575 543 // It returns only when the lock has been successfully taken. … … 577 545 in_drivers void _tty_get_lock( unsigned int channel ) 578 546 { 579 if ( USE_EXT_IO ) // extended addressing to cluster_io 580 { 581 unsigned int cluster_io = ((X_SIZE-1)<<Y_WIDTH) + Y_SIZE; 582 unsigned int address = (unsigned int)&seg_tty_base 583 + ((TTY_CONFIG + channel*TTY_SPAN)*4); 584 while ( _word_extended_read( cluster_io, address ) ) asm volatile("nop"); 585 } 586 else // direct addressing to cluster(0,0) 587 { 588 unsigned int* tty = (unsigned int *) &seg_tty_base; 589 while ( tty[channel * TTY_SPAN + TTY_CONFIG] ) asm volatile("nop"); 590 } 547 unsigned int base = (unsigned int)&seg_tty_base; 548 unsigned int offset = (TTY_CONFIG + channel*TTY_SPAN) << 2; 549 while ( _word_extended_read( CLUSTER_IO, base + offset ) ); 591 550 } 592 551 593 552 ////////////////////////////////////////////////////////////////////////////// 594 // This function releases the hardwired lock protecting exclusive access 553 // This function releases the hardwired lock protecting exclusive access 595 554 // to TTY terminal identified by the channel argument. 596 555 ////////////////////////////////////////////////////////////////////////////// 597 556 in_drivers void _tty_release_lock( unsigned int channel ) 598 557 { 599 if ( USE_EXT_IO ) // extended addressing to cluster_io 600 { 601 unsigned int cluster_io = ((X_SIZE-1)<<Y_WIDTH) + Y_SIZE; 602 unsigned int address = (unsigned int)&seg_tty_base 603 + ((TTY_CONFIG + channel*TTY_SPAN)*4); 604 _word_extended_write( cluster_io, address, 0 ); 605 } 606 else // direct addressing to cluster(0,0) 607 { 608 unsigned int* tty_address = (unsigned int *) &seg_tty_base; 609 tty_address[channel * TTY_SPAN + TTY_CONFIG] = 0; 610 } 558 unsigned int base = (unsigned int)&seg_tty_base; 559 unsigned int offset = (TTY_CONFIG + channel*TTY_SPAN) << 2; 560 _word_extended_write( CLUSTER_IO, base + offset, 0 ); 611 561 } 612 562 … … 626 576 // check TTY channel 627 577 l = (proc_id % NB_PROCS_MAX); 628 x = (proc_id / NB_PROCS_MAX) >> Y_WIDTH; 578 x = (proc_id / NB_PROCS_MAX) >> Y_WIDTH; 629 579 y = (proc_id / NB_PROCS_MAX) & ((1<<Y_WIDTH) - 1); 630 580 channel = (x * Y_SIZE + y) * NB_PROCS_MAX + l; … … 649 599 // The <DEL> character is interpreted, and previous characters can be 650 600 // cancelled. All others characters are ignored. 651 // When the <LF> or <CR> character is received, the string is converted 601 // When the <LF> or <CR> character is received, the string is converted 652 602 // to an unsigned int value. If the number of decimal digit is too large 653 603 // for the 32 bits range, the zero value is returned. … … 673 623 // check TTY channel 674 624 l = (proc_id % NB_PROCS_MAX); 675 x = (proc_id / NB_PROCS_MAX) >> Y_WIDTH; 625 x = (proc_id / NB_PROCS_MAX) >> Y_WIDTH; 676 626 y = (proc_id / NB_PROCS_MAX) & ((1<<Y_WIDTH) - 1); 677 627 channel = (x * Y_SIZE + y) * NB_PROCS_MAX + l; … … 751 701 752 702 // compute TTY channel : 753 // if the number of TTY channels is smaller 703 // if the number of TTY channels is smaller 754 704 // than the number of clusters, use TTY_0_0 755 705 // else, TTY channel <= cluster index … … 760 710 else 761 711 { 762 x = (proc_id / NB_PROCS_MAX) >> Y_WIDTH; 712 x = (proc_id / NB_PROCS_MAX) >> Y_WIDTH; 763 713 y = (proc_id / NB_PROCS_MAX) & ((1<<Y_WIDTH) - 1); 764 714 channel = (x * Y_SIZE + y); 765 715 } 766 716 767 // take the TTY lock 717 // take the TTY lock 768 718 _tty_get_lock( channel ); 769 719 770 720 printf_text: 771 721 772 while (*format) 722 while (*format) 773 723 { 774 724 unsigned int i; 775 725 for (i = 0; format[i] && format[i] != '%'; i++) 776 726 ; 777 if (i) 727 if (i) 778 728 { 779 729 _tty_write( format, i, channel ); 780 730 format += i; 781 731 } 782 if (*format == '%') 732 if (*format == '%') 783 733 { 784 734 format++; … … 811 761 break; 812 762 case ('d'): // decimal signed integer 813 if (val < 0) 763 if (val < 0) 814 764 { 815 765 val = -val; … … 817 767 } 818 768 case ('u'): // decimal unsigned integer 819 for( i=0 ; i<10 ; i++) 769 for( i=0 ; i<10 ; i++) 820 770 { 821 771 buf[9-i] = HexaTab[val % 10]; … … 827 777 case ('x'): // hexadecimal integer 828 778 _tty_write( "0x", 2, channel ); 829 for( i=0 ; i<8 ; i++) 779 for( i=0 ; i<8 ; i++) 830 780 { 831 781 buf[7-i] = HexaTab[val % 16U]; … … 860 810 in_drivers void _tty_isr_indexed(size_t index) 861 811 { 862 if ( USE_EXT_IO ) // extended addressing to TTY in cluster_io 863 { 864 unsigned int cluster = ((X_SIZE-1)<<Y_WIDTH) + Y_SIZE; 865 unsigned int base = (unsigned int)&seg_tty_base + 866 ((index*TTY_SPAN + TTY_READ)*4); 867 868 _tty_get_buf[index] = (char)_word_extended_read( cluster, base ); 869 } 870 else // direct addressing to TTY in cluster(0,0) 871 { 872 char* tty = (char*)&seg_tty_base + index*TTY_SPAN*4; 873 874 _tty_get_buf[index] = tty[TTY_READ*4]; // save character and reset IRQ 875 } 812 unsigned int base = (unsigned int)&seg_tty_base; 813 unsigned int offset = (index*TTY_SPAN + TTY_READ) << 2; 814 815 _tty_get_buf[index] = _byte_extended_read(CLUSTER_IO, base + offset); 876 816 _tty_get_full[index] = 1; // signals character available 877 817 } … … 917 857 ////////////////////////////////////////////////////////////////////////////////////////// 918 858 // The block size is 512 bytes. 919 // The functions below use the three variables _ioc_lock _ioc_done, 859 // The functions below use the three variables _ioc_lock _ioc_done, 920 860 // and _ioc_status for synchronisation. 921 861 // - As the IOC component can be used by several programs running in parallel, 922 862 // the _ioc_lock variable guaranties exclusive access to the device. 923 863 // The _ioc_read() and _ioc_write() functions use atomic LL/SC to get the lock. 924 // and set _ioc_lock to a non zero value. 864 // and set _ioc_lock to a non zero value. 925 865 // The _ioc_write() and _ioc_read() functions are blocking, polling the _ioc_lock 926 866 // variable until the device is available. … … 932 872 // reset the _ioc_done variable to zero, and releases the _ioc_lock variable. 933 873 /////////////////////////////////////////////////////////////////////////////////////// 934 // If USE_EXT_IO is set, we use the IOC controler implemented in cluster_io 935 // (x = X_SIZE-1 / y = Y_SIZE), which requires and extended address access. 936 // If USE_EXT_IO not set, we use the IOC contrÃŽler in cluster (0,0). 937 // 938 // If USE_RAMDISK is set, we access a "virtual" block device controler implemented 874 // If USE_RAMDISK is set, we access a "virtual" block device controler implemented 939 875 // as a memory-mapped segment in cluster [0,0] at address seg_ramdisk_base. 940 876 // The tranfer being fully synchronous, the IOC interrupt is not activated. … … 942 878 943 879 /////////////////////////////////////////////////////////////////////////////////////// 944 // This blocking function is used by the _ioc_read() and _ioc_write() functions 880 // This blocking function is used by the _ioc_read() and _ioc_write() functions 945 881 // to get _ioc_lock using LL/SC. 946 882 /////////////////////////////////////////////////////////////////////////////////////// 947 883 in_drivers void _ioc_get_lock() 948 884 { 949 register unsigned int* plock = (unsigned int*)&_ioc_lock; 950 951 asm volatile ("_ioc_llsc: \n" 952 "ll $2, 0(%0) \n" // $2 <= _ioc_lock 953 "bnez $2, _ioc_llsc \n" // retry if busy 954 "li $3, 1 \n" // prepare argument for sc 955 "sc $3, 0(%0) \n" // try to set _ioc_busy 956 "beqz $3, _ioc_llsc \n" // retry if not atomic 957 ::"r"(plock):"$2","$3"); 885 register unsigned int* plock = (unsigned int*)&_ioc_lock; 886 887 asm volatile ( 888 "1: \n" 889 "ll $2, 0(%0) \n" // $2 <= _ioc_lock 890 "bnez $2, 1b \n" // retry if busy 891 "li $3, 1 \n" // prepare argument for sc 892 "sc $3, 0(%0) \n" // try to set _ioc_busy 893 "beqz $3, 1b \n" // retry if not atomic 894 ::"r"(plock) :"$2","$3"); 958 895 } 959 896 … … 965 902 // - ext : cluster index for the memory buffer 966 903 /////////////////////////////////////////////////////////////////////////////////////// 967 in_drivers void _ioc_write( size_t lba, 968 void* buffer, 904 in_drivers void _ioc_write( size_t lba, 905 void* buffer, 969 906 size_t count, 970 907 size_t ext ) … … 985 922 src_address, 986 923 count*512 ); 987 924 988 925 _ioc_status = BLOCK_DEVICE_WRITE_SUCCESS; 989 926 _ioc_done = 1; 990 } 991 else if ( USE_EXT_IO ) // extended addressing to cluster_io 992 { 993 unsigned int cluster = ((X_SIZE-1)<<Y_WIDTH) + Y_SIZE; 994 unsigned int base = (unsigned int)&seg_ioc_base; 995 996 _word_extended_write( cluster, base + BLOCK_DEVICE_BUFFER*4, (unsigned int)buffer ); 997 _word_extended_write( cluster, base + BLOCK_DEVICE_BUFFER_EXT*4, ext ); 998 _word_extended_write( cluster, base + BLOCK_DEVICE_COUNT*4, count ); 999 _word_extended_write( cluster, base + BLOCK_DEVICE_LBA*4, lba ); 1000 _word_extended_write( cluster, base + BLOCK_DEVICE_IRQ_ENABLE*4, 1 ); 1001 _word_extended_write( cluster, base + BLOCK_DEVICE_OP*4, BLOCK_DEVICE_WRITE ); 1002 } 1003 else // direct addressing to cluster(0,0) 1004 { 1005 unsigned int* ioc = (unsigned int*)&seg_ioc_base; 1006 1007 ioc[BLOCK_DEVICE_BUFFER] = (unsigned int)buffer; 1008 ioc[BLOCK_DEVICE_BUFFER_EXT] = ext; 1009 ioc[BLOCK_DEVICE_COUNT] = count; 1010 ioc[BLOCK_DEVICE_LBA] = lba; 1011 ioc[BLOCK_DEVICE_IRQ_ENABLE] = 1; 1012 ioc[BLOCK_DEVICE_OP] = BLOCK_DEVICE_WRITE; 1013 } 927 928 return; 929 } 930 931 unsigned int base = (unsigned int)&seg_ioc_base; 932 _word_extended_write( CLUSTER_IO, base + BLOCK_DEVICE_BUFFER*4, (unsigned int)buffer ); 933 _word_extended_write( CLUSTER_IO, base + BLOCK_DEVICE_BUFFER_EXT*4, ext ); 934 _word_extended_write( CLUSTER_IO, base + BLOCK_DEVICE_COUNT*4, count ); 935 _word_extended_write( CLUSTER_IO, base + BLOCK_DEVICE_LBA*4, lba ); 936 _word_extended_write( CLUSTER_IO, base + BLOCK_DEVICE_IRQ_ENABLE*4, 1 ); 937 _word_extended_write( CLUSTER_IO, base + BLOCK_DEVICE_OP*4, BLOCK_DEVICE_WRITE ); 1014 938 } 1015 939 … … 1021 945 // - ext : cluster index for the memory buffer 1022 946 /////////////////////////////////////////////////////////////////////////////////////// 1023 in_drivers void _ioc_read( size_t lba, 1024 void* buffer, 947 in_drivers void _ioc_read( size_t lba, 948 void* buffer, 1025 949 size_t count, 1026 950 size_t ext ) … … 1044 968 _ioc_status = BLOCK_DEVICE_READ_SUCCESS; 1045 969 _ioc_done = 1; 1046 } 1047 else if ( USE_EXT_IO ) // extended addressing to cluster_io 1048 { 1049 unsigned int cluster = ((X_SIZE-1)<<Y_WIDTH) + Y_SIZE; 1050 unsigned int base = (unsigned int)&seg_ioc_base; 1051 1052 _word_extended_write( cluster, base + BLOCK_DEVICE_BUFFER*4, (unsigned int)buffer ); 1053 _word_extended_write( cluster, base + BLOCK_DEVICE_BUFFER_EXT*4, ext ); 1054 _word_extended_write( cluster, base + BLOCK_DEVICE_COUNT*4, count ); 1055 _word_extended_write( cluster, base + BLOCK_DEVICE_LBA*4, lba ); 1056 _word_extended_write( cluster, base + BLOCK_DEVICE_IRQ_ENABLE*4, 1 ); 1057 _word_extended_write( cluster, base + BLOCK_DEVICE_OP*4, BLOCK_DEVICE_READ ); 1058 } 1059 else // direct addressing to cluster(0,0) 1060 { 1061 unsigned int* ioc = (unsigned int*)&seg_ioc_base; 1062 1063 ioc[BLOCK_DEVICE_BUFFER] = (unsigned int)buffer; 1064 ioc[BLOCK_DEVICE_BUFFER_EXT] = ext; 1065 ioc[BLOCK_DEVICE_COUNT] = count; 1066 ioc[BLOCK_DEVICE_LBA] = lba; 1067 ioc[BLOCK_DEVICE_IRQ_ENABLE] = 1; 1068 ioc[BLOCK_DEVICE_OP] = BLOCK_DEVICE_READ; 1069 } 970 971 return; 972 } 973 974 const unsigned int base = (unsigned int)&seg_ioc_base; 975 _word_extended_write( CLUSTER_IO, base + BLOCK_DEVICE_BUFFER*4, (unsigned int)buffer ); 976 _word_extended_write( CLUSTER_IO, base + BLOCK_DEVICE_BUFFER_EXT*4, ext ); 977 _word_extended_write( CLUSTER_IO, base + BLOCK_DEVICE_COUNT*4, count ); 978 _word_extended_write( CLUSTER_IO, base + BLOCK_DEVICE_LBA*4, lba ); 979 _word_extended_write( CLUSTER_IO, base + BLOCK_DEVICE_IRQ_ENABLE*4, 1 ); 980 _word_extended_write( CLUSTER_IO, base + BLOCK_DEVICE_OP*4, BLOCK_DEVICE_READ ); 981 } 982 983 in_drivers inline unsigned int _ioc_get_blocksize() { 984 const unsigned int base = (unsigned int)&seg_ioc_base; 985 return _word_extended_read( CLUSTER_IO, base + BLOCK_DEVICE_BLOCK_SIZE*4 ); 1070 986 } 1071 987 … … 1078 994 { 1079 995 // waiting for completion 1080 while (_ioc_done == 0) asm volatile("nop"); 1081 996 while (_ioc_done == 0) asm volatile("nop"); 997 1082 998 // reset synchronisation variables 1083 999 _ioc_done = 0; … … 1102 1018 in_drivers void _ioc_isr() 1103 1019 { 1104 if ( USE_EXT_IO ) // extended addressing to cluster_io 1105 { 1106 unsigned int cluster = ((X_SIZE-1)<<Y_WIDTH) + Y_SIZE; 1107 unsigned int base = (unsigned int)&seg_ioc_base; 1108 1109 _ioc_status = _word_extended_read( cluster, base + BLOCK_DEVICE_STATUS*4 ); 1110 } 1111 else // direct addressing to cluster(Ã ,0) 1112 { 1113 unsigned int* ioc = (unsigned int*)&seg_ioc_base; 1114 1115 _ioc_status = ioc[BLOCK_DEVICE_STATUS]; // save status & reset IRQ 1116 } 1117 _ioc_done = 1; // signals completion 1020 unsigned int base = (unsigned int)&seg_ioc_base; 1021 1022 _ioc_status = _word_extended_read( CLUSTER_IO, base + BLOCK_DEVICE_STATUS*4 ); 1023 _ioc_done = 1; // signals completion 1118 1024 } 1119 1025 … … 1121 1027 // FRAME_BUFFER 1122 1028 ////////////////////////////////////////////////////////////////////////////////////// 1123 // The _fb_sync_write & _fb_sync_read functions use a memcpy strategy to implement 1029 // The _fb_sync_write & _fb_sync_read functions use a memcpy strategy to implement 1124 1030 // the transfer between a data buffer and the frame buffer. 1125 1031 // They are blocking until completion of the transfer. … … 1134 1040 // - ext : cluster_xy for the user buffer 1135 1041 ////////////////////////////////////////////////////////////////////////////////////// 1136 in_drivers void _fb_sync_write( unsigned int offset, 1137 unsigned int buffer, 1042 in_drivers void _fb_sync_write( unsigned int offset, 1043 unsigned int buffer, 1138 1044 unsigned int length, 1139 1045 unsigned int ext ) … … 1142 1048 unsigned int src_cluster = ext; 1143 1049 unsigned int dst_address = (unsigned int)&seg_fbf_base + offset; 1144 unsigned int dst_cluster = ((X_SIZE-1)<<Y_WIDTH) + Y_SIZE; // cluster_xy for I/O 1145 1146 _extended_memcpy( dst_cluster, 1050 1051 _extended_memcpy( CLUSTER_IO, 1147 1052 dst_address, 1148 1053 src_cluster, … … 1159 1064 // - ext : cluster_xy for the user buffer 1160 1065 ////////////////////////////////////////////////////////////////////////////////////// 1161 in_drivers void _fb_sync_read( unsigned int offset, 1162 unsigned int buffer, 1066 in_drivers void _fb_sync_read( unsigned int offset, 1067 unsigned int buffer, 1163 1068 unsigned int length, 1164 1069 unsigned int ext ) … … 1167 1072 unsigned int dst_cluster = ext; 1168 1073 unsigned int src_address = (unsigned int)&seg_fbf_base + offset; 1169 unsigned int src_cluster = ((X_SIZE-1)<<Y_WIDTH) + Y_SIZE; // cluster_xy for I/O1170 1074 1171 1075 _extended_memcpy( dst_cluster, 1172 1076 dst_address, 1173 src_cluster,1077 CLUSTER_IO, 1174 1078 src_address, 1175 1079 length ); … … 1184 1088 in_drivers void _mmc_isr() 1185 1089 { 1186 int* mmc_address = (int*)&seg_mmc_base;1090 //int* mmc_address = (int*)&seg_mmc_base; 1187 1091 unsigned int cluster_xy = _procid() / NB_PROCS_MAX; 1188 1092 1189 1093 _tty_printf( "WRITE ERROR signaled by Memory Cache in cluster %x\n", cluster_xy ); 1190 1094 } 1191 1095 1192 1096 /////////////////////////////////////////////////////////////////////////////////////// 1193 // Release a software spin-lock 1097 // Release a software spin-lock 1194 1098 /////////////////////////////////////////////////////////////////////////////////////// 1195 1099 in_drivers void _release_lock(size_t index) 1196 1100 1197 1101 { 1198 if( index >= NB_LOCKS ) 1102 if( index >= NB_LOCKS ) 1199 1103 { 1200 1104 _tty_get_lock( 0 ); … … 1203 1107 _exit(); 1204 1108 } 1205 1109 1206 1110 _spin_lock[index] = 0; 1207 1111 } … … 1225 1129 1226 1130 register int delay = ((_proctime() +_procid()) & 0xF) << 4; 1227 register int * plock = (int *) &_spin_lock[index]; 1228 1229 asm volatile ("_locks_llsc: 1230 "ll $2, 0(%0) 1231 "bnez $2, _locks_delay 1232 "li $3, 1 \n" // prepare argument for sc 1233 "sc $3, 0(%0) \n"// try to set _locks_busy1234 "bnez $3, _locks_ok \n" // exit if atomic 1131 register int * plock = (int *) &_spin_lock[index]; 1132 1133 asm volatile ("_locks_llsc: \n" 1134 "ll $2, 0(%0) \n" // $2 <= _locks_lock 1135 "bnez $2, _locks_delay \n" // random delay if busy 1136 "li $3, 1 \n" // prepare argument for sc 1137 "sc $3, 0(%0) \n" // try to set _locks_busy 1138 "bnez $3, _locks_ok \n" // exit if atomic 1235 1139 "_locks_delay: \n" 1236 1140 "move $4, %1 \n" // $4 <= delay … … 1239 1143 "beqz $4, _locks_loop \n" // test end delay 1240 1144 "j _locks_llsc \n" // retry 1241 "_locks_ok: 1145 "_locks_ok: \n" 1242 1146 ::"r"(plock),"r"(delay):"$2","$3","$4"); 1243 1147 } … … 1248 1152 // - barrier_count[index] <= N 1249 1153 // - barrier_lock[index] <= 0 1250 // All tasks try to initialize the barrier, but the initialisation 1154 // All tasks try to initialize the barrier, but the initialisation 1251 1155 // is done by only one task, using LL/SC instructions. 1252 // This cooperative initialisation is questionnable, 1156 // This cooperative initialisation is questionnable, 1253 1157 // because the barrier can ony be initialised once... 1254 1158 ////////////////////////////////////////////////////////////////////////////////////// 1255 1159 in_drivers void _barrier_init(unsigned int index, unsigned int value) 1256 1160 { 1257 1258 register int* pinit = (int*)&_barrier_value[index]; 1259 register int* pcount = (int*)&_barrier_count[index]; 1260 register int* plock = (int*)&_barrier_lock[index]; 1161 register int* pinit = (int*)&_barrier_value[index]; 1162 register int* pcount = (int*)&_barrier_count[index]; 1163 register int* plock = (int*)&_barrier_lock[index]; 1261 1164 1262 1165 if ( index >= NB_BARRIERS ) … … 1269 1172 1270 1173 // parallel initialisation using atomic instructions LL/SC 1271 asm volatile ("_barrier_init_test: 1272 "ll $2, 0(%0) \n" // read barrier_value1273 "bnez $2, _barrier_init_done 1274 "move $3, %3 1275 "sc $3, 0(%0) \n"// try to write barrier_value1276 "beqz $3, _barrier_init_test 1277 "move $3, %3 \n"1278 "sw $3, 0(%1) \n"// barrier_count <= barrier_value1279 "move $3, $0 \n" // 1280 "sw $3, 0(%2) \n"// barrier_lock <= 01281 "_barrier_init_done: 1174 asm volatile ("_barrier_init_test: \n" 1175 "ll $2, 0(%0) \n" // read barrier_value 1176 "bnez $2, _barrier_init_done \n" 1177 "move $3, %3 \n" 1178 "sc $3, 0(%0) \n" // try to write barrier_value 1179 "beqz $3, _barrier_init_test \n" 1180 "move $3, %3 \n" 1181 "sw $3, 0(%1) \n" // barrier_count <= barrier_value 1182 "move $3, $0 \n" // 1183 "sw $3, 0(%2) \n" // barrier_lock <= 0 1184 "_barrier_init_done: \n" 1282 1185 ::"r"(pinit),"r"(pcount),"r"(plock),"r"(value):"$2","$3"); 1283 1186 } 1284 1187 1285 1188 ////////////////////////////////////////////////////////////////////////////////////// 1286 // This blocking function uses a busy_wait technics (on the barrier_lock value), 1287 // because the GIET does not support dynamic scheduling/descheduling of tasks. 1189 // This blocking function uses a busy_wait technics (on the barrier_lock value), 1190 // because the GIET does not support dynamic scheduling/descheduling of tasks. 1288 1191 // The barrier state is actually defined by two variables: 1289 1192 // _barrier_count[index] define the number of particpants that are waiting 1290 // _barrier_lock[index] define the bool variable whose value is polled 1193 // _barrier_lock[index] define the bool variable whose value is polled 1291 1194 // The last participant change the value of _barrier_lock[index] to release the barrier... 1292 1195 // There is at most 16 independant barriers, and an error is returned … … 1295 1198 in_drivers void _barrier_wait(unsigned int index) 1296 1199 { 1297 register int* pcount = (int*)&_barrier_count[index]; 1298 register int count; 1299 1300 int lock = _barrier_lock[index]; 1200 register int* pcount = (int*)&_barrier_count[index]; 1201 register int count; 1202 int lock = _barrier_lock[index]; 1301 1203 1302 1204 if ( index >= NB_BARRIERS ) … … 1307 1209 _exit(); 1308 1210 } 1309 1211 1310 1212 // parallel decrement _barrier_count[index] using atomic instructions LL/SC 1311 1213 // input : pointer on _barrier_count[index] 1312 1214 // output : count = _barrier_count[index] (before decrementation) 1313 asm volatile ("_barrier_decrement: 1314 "ll %0, 0(%1) 1315 "addi $3, %0, -1 1316 "sc $3, 0(%1) 1317 "beqz $3, _barrier_decrement 1215 asm volatile ("_barrier_decrement: \n" 1216 "ll %0, 0(%1) \n" 1217 "addi $3, %0, -1 \n" 1218 "sc $3, 0(%1) \n" 1219 "beqz $3, _barrier_decrement \n" 1318 1220 :"=&r"(count) 1319 1221 :"r"(pcount) … … 1323 1225 // and the barrier_lock variable, waking up all other waiting tasks 1324 1226 1325 if ( count == 1 ) 1227 if ( count == 1 ) // last task 1326 1228 { 1327 1229 _barrier_count[index] = _barrier_value[index]; … … 1329 1231 _barrier_lock[index] = (lock == 0) ? 1 : 0; 1330 1232 } 1331 else 1332 { 1333 while ( lock == _barrier_lock[index] ) asm volatile("nop");1334 } 1335 } 1233 else // other tasks 1234 { 1235 while ( lock == _barrier_lock[index] ); 1236 } 1237 } 1336 1238 1337 1239 -
branches/fault_tolerance/softs/giet_tsar/stdio.h
r724 r745 1 1 //////////////////////////////////////////////////////////////////////////////////////// 2 2 // File : stdio.h 3 // Written by Alain Greiner 3 // Written by Alain Greiner 4 4 // Date : 17/01/2014 5 5 // … … 40 40 typedef unsigned int size_t; 41 41 42 // global variables defined in stdio.c42 // constants 43 43 44 extern int volatile _ioc_lock; 45 extern int volatile _ioc_done; 46 extern int volatile _ioc_status; 47 48 extern char volatile _tty_get_buf[]; 49 extern int volatile _tty_get_full[]; 50 51 extern int volatile _barrier_value[]; 52 extern int volatile _barrier_count[]; 53 extern int volatile _barrier_lock[]; 54 55 extern int volatile _spin_lock[]; 44 #define CLUSTER_IO (((X_IO) << (Y_WIDTH)) | (Y_IO)) 56 45 57 46 // functions defined in stdio.c … … 64 53 unsigned int src_address, 65 54 unsigned int length ); 66 unsigned int _procid(); 67 unsigned int _proctime(); 68 unsigned int _procnumber(); 55 inline unsigned int _procid(); 56 inline unsigned int _proctime(); 57 inline unsigned int _procnumber(); 58 59 inline unsigned int _io_cluster(); 69 60 70 61 unsigned int _rand(); … … 72 63 void _it_mask(); 73 64 void _it_enable(); 65 66 int _sr_read(); 67 void _sr_write(int sr); 74 68 75 69 void _dcache_buf_invalidate( const void* buffer, size_t size ); … … 95 89 void _ioc_write( size_t lba, void* buffer, size_t count, size_t ext ); 96 90 void _ioc_read (size_t lba, void* buffer, size_t count, size_t ext ); 91 unsigned int _ioc_get_blocksize(); 97 92 void _ioc_completed(); 98 93 void _ioc_isr(); … … 100 95 void _mmc_isr(); 101 96 102 void _fb_sync_write( unsigned int offset, 97 void _fb_sync_write( unsigned int offset, 103 98 unsigned int buffer, 104 99 unsigned int length, 105 100 unsigned int ext ); 106 void _fb_sync_read( unsigned int offset, 101 void _fb_sync_read( unsigned int offset, 107 102 unsigned int buffer, 108 103 unsigned int length, … … 115 110 void _barrier_wait(size_t index); 116 111 117 unsigned char _byte_extended_read( unsigned int cluster, 118 unsigned int address ); 119 unsigned int _word_extended_read( unsigned int cluster, 120 unsigned int address ); 121 void _word_extended_write( unsigned int cluster, 122 unsigned int address, 112 volatile unsigned char _byte_extended_read( unsigned int cluster, 113 unsigned int address ); 114 volatile unsigned int _word_extended_read( unsigned int cluster, 115 unsigned int address ); 116 117 void _word_extended_write( unsigned int cluster, 118 unsigned int address, 123 119 unsigned int word ); 124 void _byte_extended_write( unsigned int cluster, 125 unsigned int address, 120 void _byte_extended_write( unsigned int cluster, 121 unsigned int address, 126 122 unsigned char byte ); 127 123 #endif -
branches/fault_tolerance/softs/soft_sort_giet/Makefile
r724 r745 4 4 DU = mipsel-unknown-elf-objdump 5 5 6 OBJS = 7 8 9 6 OBJS = reset.o \ 7 giet.o \ 8 stdio.o \ 9 main.o 10 10 11 CFLAGS = -Wall -mno-gpopt -ffreestanding -fomit-frame-pointer -mips32 -ggdb11 CFLAGS = -Wall -mno-gpopt -ffreestanding -fomit-frame-pointer -mips32 12 12 13 13 GIET = ../giet_tsar -
branches/fault_tolerance/softs/soft_transpose_giet/Makefile
r724 r745 4 4 DU = mipsel-unknown-elf-objdump 5 5 6 OBJS = 7 8 9 6 OBJS = reset.o \ 7 giet.o \ 8 stdio.o \ 9 main.o 10 10 11 CFLAGS = -Wall -mno-gpopt -ffreestanding -fomit-frame-pointer -mips32 -ggdb 11 CFLAGS = -Wall -mno-gpopt -ffreestanding -fomit-frame-pointer -mips32 \ 12 -msoft-float -O2 \ 13 # -ggdb -mlong-calls 12 14 13 15 GIET = ../giet_tsar … … 18 20 19 21 reset.o: $(GIET)/reset.S hard_config.h 20 $(CC) -I. $(CFLAGS) -c -o $@ $<22 $(CC) -I. -I$(GIET) $(CFLAGS) -c -o $@ $< 21 23 $(DU) -D $@ > $@.txt 22 24 -
branches/fault_tolerance/softs/soft_transpose_giet/hard_config.h
r724 r745 7 7 #define _HARD_CONFIG_H 8 8 9 #define X_SIZE 210 #define Y_SIZE 29 #define X_SIZE 6 10 #define Y_SIZE 6 11 11 #define X_WIDTH 4 12 12 #define Y_WIDTH 4 13 #define X_IO 0//(X_SIZE - 1) 14 #define Y_IO 0//(Y_SIZE - 1) 13 15 14 #define NB_PROCS_MAX 116 #define NB_PROCS_MAX 4 15 17 16 #define USE_RAMDISK 117 #define USE_ EXT_IO 018 #define USE_RAMDISK 0 19 #define USE_PIC 1 18 20 19 21 #define NB_DMA_CHANNELS 0 … … 21 23 #define NB_NIC_CHANNELS 0 22 24 #define NB_CMA_CHANNELS 0 23 24 25 #define NB_TTY_CHANNELS 1 25 26 -
branches/fault_tolerance/softs/soft_transpose_giet/ldscript
r724 r745 10 10 peripherals are not present in the architecture */ 11 11 12 seg_reset_base = 0x 00000000; /* boot code */12 seg_reset_base = 0xBFC00000; /* boot code */ 13 13 14 14 seg_kcode_base = 0x00010000; /* kernel code */ … … 20 20 21 21 seg_heap_base = 0x00100000; /* heaps for applications */ 22 seg_stack_base = 0x00300000; /* stacks ifor applications*/22 seg_stack_base = 0x00300000; /* stacks for applications */ 23 23 24 seg_ramdisk_base = 0x 00800000; /* virtual disk */24 seg_ramdisk_base = 0xFFFFFFFF; /* virtual disk */ 25 25 26 seg_xcu_base = 0xF0000000; /* controler XCU */ 27 seg_tty_base = 0xF4000000; /* controler TTY */ 28 seg_fbf_base = 0xF3000000; /* controler FBF */ 29 seg_ioc_base = 0xF2000000; /* controler IOC */ 30 seg_nic_base = 0xF7000000; /* controler NIC */ 31 seg_cma_base = 0xF8000000; /* controler CMA */ 32 seg_pic_base = 0xF9000000; /* controler PIC */ 33 seg_mmc_base = 0xE0000000; /* config MMC */ 26 seg_xcu_base = 0xB0000000; /* XCU controller */ 27 seg_dma_base = 0xB1000000; /* DMA controller */ 28 seg_mmc_base = 0xB2000000; /* config MMC */ 29 seg_ioc_base = 0xB3000000; /* IOC controller */ 30 seg_tty_base = 0xB4000000; /* TTY controller */ 31 seg_nic_base = 0xB5000000; /* NIC controller */ 32 seg_cma_base = 0xB6000000; /* CMA controller */ 33 seg_fbf_base = 0xB7000000; /* FBF controller */ 34 seg_pic_base = 0xB8000000; /* PIC controller */ 34 35 36 ENTRY(reset) 35 37 36 38 /* Grouping sections into segments */ … … 60 62 seg_code : { 61 63 *(.text) 64 *(.text.*) 62 65 } 63 66 . = seg_reset_base; -
branches/fault_tolerance/softs/soft_transpose_giet/main.c
r724 r745 12 12 #define PRINTF(...) ({ if (lpid == 0) { _tty_printf(__VA_ARGS__); } }) 13 13 14 #define DISPLAY_OK 1 // enable display on frame buffer when non zero15 #define CHECK_VERBOSE 1// display a detailed check on TTY when non zero16 #define INSTRUMENTATION_OK 0 // display statistcs on TTY when non zero14 #define DISPLAY_OK 1 // enable display on frame buffer when non zero 15 #define CHECK_VERBOSE !DISPLAY_OK // display a detailed check on TTY when non zero 16 #define INSTRUMENTATION_OK 0 // display statistcs on TTY when non zero 17 17 18 18 // tricks to read some addresses from ldscript … … 41 41 unsigned int l; // line index for loops 42 42 unsigned int p; // pixel index for loops 43 44 unsigned int * ioc_address = (unsigned int *) &seg_ioc_base; 45 unsigned int block_size = ioc_address[BLOCK_DEVICE_BLOCK_SIZE]; 46 43 unsigned int block_size = _ioc_get_blocksize(); // get IOC block size 47 44 unsigned int proc_id = _procid(); // processor id 48 45 unsigned int nclusters = X_SIZE*Y_SIZE; // number of clusters … … 128 125 LOAD_END[cluster_id][lpid] = _proctime(); 129 126 127 128 _tty_printf("*** Proc [%d,%d,%d] barrier wait (0)\n", x, y, lpid); 130 129 _barrier_wait(0); 131 130
Note: See TracChangeset
for help on using the changeset viewer.