/*-------------------------------------------------*\ | | | Ficheiro: PE_ROM.C | | Alteração: 03-05-96 | | Alterado por: A. Esteves | \*-------------------------------------------------*/ /* "shared signals" +------------------------------------------+ | op0_select op1_select cy_select | | 1 MD0 1 MD1 1 CY_IN | | 2 DCARE 2 DCARE 2 DCARE | | 3 NOT_MD0 3 NOT_MD1 3 UM | | 4 TAG_IN 4 ZERO | | 5 NOT_TAG_IN | +------------------------------------------+ int linhas; declarado em data.h Assim: op0_select op1_select cy_select valor de "linhas" MD0 TAG_IN DCARE 142 O comentario que se encontra a seguir ao nome de algumas funcoes, indica os valores que as linhas de controle "shared signals" podem tomar para as referidas instrucoes. Na funcao "void read_this (void)": tag[0] tag[1] -> bloco ------------------- ------------------- 31 30 1 0 31 30 1 0 -> indice do bit +--+--+- -+--+--+ +--+--+- -+--+--+ na palavra. | | | ... | | | | | | ... | | | +--+--+- -+--+--+ +--+--+- -+--+--+ 0 1 30 31 32 33 62 63 -> indice do PE linha da cam correspondente. A tecnica utilizada nao verifica se existe mais do que uma tag activa. O indice devolvido e' o da primeira linha da cam com a correspondente tag activa. */ #include "datadef.h" /*----------------------------------------------------------------*/ void nop (void) {} /*----------------------------------------------------------------*/ /* DESLOCAMENTO DE TAGS */ /* Desloca as tags, no sentido UP, entre varios PEs; a distancia eï dada pelo parametro 'pos1'. O parametro 'pos2' indica o tipo de deslocamento: ZERO (insere-se 0 no PE do inicio da cadeia), UM (insere-se 1 no PE do inicio da cadeia) e CICLICO (as tags passam dum chip para o seguinte/anterior). uCODIGO: fPE fPBL pos1 x..x pos2 x..x xxxx ... VALORES para os parametros: pos1 -> [1-63] pos2 -> ZERO, UM, CICLICO PEs: CY=CY TAG=TAG_IN TAG_ROUTE=BELOW */ void shift_up (void) /*----------- NOVA VERSAO -------------------*/ { WORD tag_out; ms[0]=msbak[0]; /* Hold ms */ ms[1]=msbak[1]; switch(pos2) { case ZERO: for(;pos1<0;++pos1) { tag[0] <<= 1; tag_out = tag[1] >> 31; tag[0] = tag[0] | tag_out; tag[1] = tag[1] << 1; } break; case UM: for(;pos1<0;++pos1) { tag[0] <<= 1; tag_out = tag[1] >> 31; tag[0] = tag[0] | tag_out; tag[1] = tag[1] << 1; tag[1] |= 1; } break; case CICLICO: for(;pos1<0;++pos1) TagBelow(); break; default: erro("\nErro na funcao shift_up(). \n"); break; } } /*----------------------------------------------------------------*/ /* Desloca as tags, no sentido DOWN, entre varios PEs; a distancia eï dada pelo parametro 'pos1'. O parametro 'pos2' indica o tipo de deslocamento: ZERO (insere-se 0 no PE do inicio da cadeia), UM (insere-se 1 no PE do inicio da cadeia) e CICLICO (as tags passam dum chip para o seguinte/anterior). uCODIGO: fPE fPBL pos1 x..x pos2 x..x xxxx ... VALORES para os parametros: pos1 -> [1-63] pos2 -> ZERO, UM, CICLICO PEs: CY=CY TAG=TAG_IN TAG_ROUTE=ABOVE */ void shift_down (void) /*-------- NOVA VERSAO --------------------*/ { WORD tag_out; ms[0]=msbak[0]; /* Hold ms */ ms[1]=msbak[1]; switch(pos2) { case ZERO: for(;pos1>0;--pos1) { tag[1] >>= 1; tag_out = tag[0] & (WORD) 1; tag_out <<= 31; tag[1] |= tag_out; tag[0] >>= 1; } break; case UM: for(;pos1>0;--pos1) { tag[1] >>= 1; tag_out = tag[0] & (WORD) 1; tag_out <<= 31; tag[1] |= tag_out; tag[0] >>= 1; tag[0] |= (WORD) 0x80000000; } break; case CICLICO: for(;pos1>0;--pos1) TagAbove(); break; default: erro("\nErro na funcao shift_down(). \n"); break; } } /*----------------------------------------------------------------*/ /* MANIPULAR TAGS DE VARIOS CHIPS */ void init_alt_ch (void) { ms[0]=msbak[0]; /* Hold ms */ ms[1]=msbak[1]; Chip_ALT_LATCH ( RESET ); Chip_ENABLE_LATCH ( RESET ); } /*----------------------------------------------------------------*/ void init_alt_b1 (void) { ms[0]=msbak[0]; /* Hold ms */ ms[1]=msbak[1]; Chip_ALT_LATCH ( SET ); Chip_ENABLE_LATCH ( SET ); } /*---------------------------------------------------------*/ void init_alt_b0 (void) { ms[0]=msbak[0]; /* Hold ms */ ms[1]=msbak[1]; Chip_ALT_LATCH ( RESET ); Chip_ENABLE_LATCH ( SET ); } /*----------------------------------------------------------------*/ /* Para que alt(), carry_alt() e tag_alt() funcionen correctamente e' preciso que haja interligacao entre as flags de saida dum chip e as flags de entrada de outro chip (vizinho). */ void alt(void) /* NOVA VERSAO */ { util_tags(ALT); } void tag_alt(void) /* NOVA VERSAO */ { util_tags(TAG_ALT); } void carry_alt(void) /* NOVA VERSAO */ { util_tags(CARRY_ALT); } /*----------------------------------------------------------------- Funcao utilizada nas microinstrucoes alt(), carry_alt(), tag_alt(). SE instrucao=0 => implementa alt() SE instrucao=1 => implementa tag_alt() SE instrucao=2 => implementa carry_alt() */ void util_tags(int instrucao) { int i, b, offset, m, blocos,size; UWORD inicio, mask, nmask, bit, old, new; ms[0]=msbak[0]; /* Hold ms */ ms[1]=msbak[1]; if((Enable[0] & Enable[1]) == WORD_UM) /* BLOCO */ { blocos = PES_CHIP/16; /* cada bloco = 16 PEs */ } else /* CHIP, CHIP2, CHIP4, CHIP8, CHIP64, ARRAY */ { while((EFLAGS_IN[num_chip] & ENABLEINOUT) == 0) ; /* Espera-se que chegue do chip vizinho a propagacao do sinal ENABLE */ blocos = 1; /* bloco = todos os PEs do chip */ } Enable[0] = 0xFFFF0000 | Enable[0]; /* 1o bloco de 16 PEs habilitado */ inicio = (EFLAGS_IN[num_chip]&ALTINOUT) ? 0x80000000 : 0; /* flag ALT_IN*/ size = PES_CHIP/blocos; for(b=0;b> offset; nmask = ~mask; old = inicio >> offset; if(b < 2) m=0; else m=1; for(i=0;i> 1; mask = mask >> 1; nmask = ~mask; } if((i%16) == 15) { if((i%32) == 31) Enable[m] = 0xFFFF0000 | Enable[m]; else Enable[m] = WORD_UM; } } } EFLAGS_OUT[num_chip]=(AltIn[1]&1) ? (EFLAGS_OUT[num_chip] | ALTINOUT): (EFLAGS_OUT[num_chip] & (!ALTINOUT)); EFLAGS_OUT[num_chip] = EFLAGS_OUT[num_chip] | ENABLEINOUT; /* flag ENABLE=1 */ } /*----------------------------------------------------------------*/ void first(void) /* NOVA VERSAO */ { int blocos, size, fim[4], inicio[4], i, b, m, p, TagUmFinded=0; WORD mask, nmask, bit, new; ms[0]=msbak[0]; /* Hold ms */ ms[1]=msbak[1]; cy[0]=cy[1]=0; if( ((FirstIn[1]&1) == 0) || (EFLAGS_OUT[num_chip]&FIRSTINOUT)) /* tipo bloco = CHIP/ARRAY */ { blocos = 1; size = PES_CHIP; /* bloco = todos os PEs do chip */ while((EFLAGS_IN[num_chip] & FIRSTINOUT) == 0) ; /* Espera-se que chegue do chip vizinho a propagacao do sinal FIRST */ } else /* tipo bloco = BLOCO */ { blocos = PES_CHIP/16; size = 16; /* 1 bloco = 16 PEs */ } for(b=0;b> (PALAVRA-1-i); nmask = ~mask; /* coloca FIRST=1 e CY=0, na posicao anterior 'a posicao inicial de busca, no caso de se tratar da continuacÆo de outra instrucao de first() */ if(posFirst[b] < inicio[b]) { if(mask & 0x80000000) { FirstIn[1-m] |= 1; cy[1-m] &= 0xFFFFFFFE; } else { FirstIn[m] |= (mask<<1); cy[m] &= (~(mask<<1)); } } bit = mask; p = i+(1-m)*PALAVRA; for(;p>=fim[b];p--) /* bit = bit ordem p de FIRST */ { new = tag[m] & bit; /* cy[p]=TAG[p] & FIRST[p-1] */ cy[m] = (new) ? (cy[m] | mask) : (cy[m] & nmask); bit = (~tag[m]) & bit; /* first[p]=first[p-1] & ~tag[p] */ FirstIn[m] = (bit) ? (FirstIn[m] | mask) : (FirstIn[m] & nmask); if(tag[m] & mask) /* TAG[p] = 1 */ { posFirst[b] = p-1; TagUmFinded = 1; } if(p==32) { m=1; mask = 0x80000000; nmask = ~mask; if(bit) bit = 0x80000000; } else { bit = bit >> 1; mask = mask >> 1; nmask = ~mask; } if(TagUmFinded==1) p=fim[b]; /* terminar o bloco pois encontrou-se TAG[p]=1 */ } } EFLAGS_OUT[num_chip] |= CARRYOUT; /* sinalizar com flag CARRY=1 a ocorrencia de TAG[p]=1 */ if((blocos==1) && (TagUmFinded==0)) EFLAGS_OUT[num_chip] |= FIRSTINOUT; /* sinalizar com flag FIRST_OUT=1 o facto de no modo CHIP/ARRAY se ter encontrado todas as TAGs=1 */ } /*----------------------------------------------------------------*/ void init_first0 (void) { int i; ms[0]=msbak[0]; /* Hold ms */ ms[1]=msbak[1]; Chip_FIRST_LATCH ( RESET ); for(i=0;i<4;++i) posFirst[i]=PES_CHIP-16*i-1;/*controlo do inicio de busca */ } /*----------------------------------------------------------------*/ void init_first1 (void) { int i; ms[0]=msbak[0]; /* Hold ms */ ms[1]=msbak[1]; Chip_FIRST_LATCH ( SET ); for(i=0;i<4;++i) posFirst[i]=PES_CHIP-16*i-1;/*controlo do inicio de busca */ } /*----------------------------------------------------------------*/ void clear_first (void) { /* tag = alt_first_logic ( clr_first ) */ /* cy = alu_output ( overflow ) */ ms[0]=msbak[0]; /* Hold ms */ ms[1]=msbak[1]; tag[0] = (tag[0] & ~cy[0]); tag[1] = (tag[1] & ~cy[1]); switch (linhas) { case 312 : /* NOT_MD0 MD1 DCARE */ cy[0] = ~(~md0[0] ^ md1[0]) & (~md0[0] ^ cy[0]) & ms[0]; cy[1] = ~(~md0[1] ^ md1[1]) & (~md0[1] ^ cy[1]) & ms[1]; break; default : erro("\nERRO na funcao clear_first(). \n"); break; } } /*----------------------------------------------------------------*/ /* INSTRUCOES DE LEITURA */ void read_this (void) /* obtem a posicao da TAG a "1" + significativa */ { int x; WORD aux_reg[SIZE], mask; ms[0]=msbak[0]; /* Hold ms */ ms[1]=msbak[1]; linhacam = -1; /* Flag para o modulo PBL.C */ switch (linhas) { case 10 : /* all tag global -> a linha L da CAM a ler para o exterior do chip e´ seleccionada se TAG[L]/TAG[L-1]/TAG[L+1]=1 */ if (tag[0]) { aux_reg[0] = tag[0]; for(x=0; aux_reg[0] ; x++) aux_reg[0] = aux_reg[0] >> 1; if (x) /* Flag para o modulo PBL.C */ linhacam = PALAVRA+x; /* Dependente da palavra do transputer */ mask = 1 << x; mask = ~mask; if(((tag[0] & mask)!=0)||(tag[1]!=0)) { linhacam = -1; erro("\nErro 1 em read_this(): seleccionou-se + do que 1 linha da CAM\n"); break; } } if (tag[1] && linhacam==-1) { aux_reg[1] = tag[1]; for(x=0; aux_reg[1] ; x++) aux_reg[1] = aux_reg[1] >> 1; if (x) /* Flag para o modulo PBL.C */ linhacam = x; /* Dependente da palavra do transputer */ mask = 1 << x; mask = ~mask; if(((tag[1] & mask)!=0)||(tag[0]!=0)) { linhacam = -1; erro("\nErro 2 em read_this(): seleccionou-se + do que 1 linha da CAM\n"); break; } } if (linhacam==-1) erro("\nErro 3 na funcao read_this(): nao ha' tags a 1. \n"); break; case 20 : /* all carry global -> a linha L a ler para o exterior do chip e´ seleccionada se CY[L]=1 */ linhacam = -1; /* Flag para o modulo PBL.C */ if (cy[0]) { aux_reg[0] = cy[0]; /* Estamos a testar o carry */ for(x=0; aux_reg[0] ; x++) aux_reg[0] = aux_reg[0] >> 1; if (x) /* Flag para o modulo PBL.C */ linhacam = PALAVRA+x; /* Dependente da palavra do transputer */ mask = 1 << x; mask = ~mask; if(((cy[0] & mask)!=0) || (cy[1]!=0)) { linhacam = -1; erro("\nErro 4 em read_this(): seleccionou-se + do que 1 linha da CAM\n"); break; } } if (cy[1] && linhacam==-1) { aux_reg[1] = cy[1]; /* Estamos a testar o carry */ for(x=0; aux_reg[1] ; x++) aux_reg[1] = aux_reg[1] >> 1; if (x) /* Flag para o modulo PBL.C */ linhacam = 2*PALAVRA-x; /* Dependente da palavra do transputer */ mask = 1 << x; mask = ~mask; if(((cy[1] & mask)!=0) || (cy[0]!=0)) { linhacam = -1; erro("\nErro 5 em read_this(): seleccionou-se + do que 1 linha da CAM\n"); break; } } if (linhacam==-1) erro("\nErro 6 na funcao read_this(). \n"); break; default : erro("\nErro 7 na funcao read_this(). \n"); break; } } /*----------------------------------------------------------------*/ void read_above (void) { TagAbove(); read_this(); } /*----------------------------------------------------------------*/ void read_below (void) { TagBelow(); read_this(); } /*----------------------------------------------------------------*/ /* INSTRUCOES ESCRITA */ void write_this (void) { ms[0]=msbak[0]; /* Hold ms */ ms[1]=msbak[1]; } /*----------------------------------------------------------------*/ void write_above (void) { ms[0]=msbak[0]; /* Hold ms */ ms[1]=msbak[1]; TagAbove(); } /*----------------------------------------------------------------*/ void write_below (void) { ms[0]=msbak[0]; /* Hold ms */ ms[1]=msbak[1]; TagBelow(); } /*----------------------------------------------------------------*/ /* DIVERSAS */ void tag_to_cy (void) { /* cy = alu_output (sum) */ switch (linhas) { case 344 : /* NOT_MD0 TAG_IN ZERO */ cy[0] = (~md0[0] ^ tag[0]); cy[1] = (~md0[1] ^ tag[1]); break; default : erro("\nERRO na funcao tag_to_cy(). \n"); break; } } /*----------------------------------------------------------------*/ void tag_to_subs (void) { ms[0] = tag[0]; ms[1] = tag[1]; } /*----------------------------------------------------------------*/ void tag_subset (void) { /* Isto vem antes do backup de ms */ tag[0] = ms[0]; tag[1] = ms[1]; ms[0]=msbak[0]; /* Hold ms */ ms[1]=msbak[1]; } /*----------------------------------------------------------------*/ void cy_subset (void) { /* Isto vem antes do backup de ms */ /* cy = alu_output (sum) */ switch (linhas) { case 114 : /* MD= MD1 ZERO */ cy[0] = ms[0]; cy[1] = ms[1]; break; default : erro("\nERRO na funcao cy_subset(). \n"); break; } ms[0]=msbak[0]; /* Hold ms */ ms[1]=msbak[1]; } /*----------------------------------------------------------------*/ void clear_n_sub (void) { /* cy = alu_output ( overflow ) */ switch (linhas) { case 331 : /* NOT_MD0 NOT_MD1 CY_IN */ cy[0] = ~(~md0[0] ^ ~md1[0]) & (~md0[0] ^ cy[0]) & ms[0]; cy[1] = ~(~md0[1] ^ ~md1[1]) & (~md0[1] ^ cy[1]) & ms[1]; break; default : erro("\nERRO na funcao clear_n_sub(). \n"); break; } } /*----------------------------------------------------------------*/ void refresh (void) { ms[0]=msbak[0]; /* Hold ms */ ms[1]=msbak[1]; } /*----------------------------------------------------------------*/ void extract_tag (void) /* deve ter-se pos1=multiplo de 4 */ { char str[17], res[20]; int i; ms[0]=msbak[0]; /* Hold ms */ ms[1]=msbak[1]; linhacam = -1;/* Flag para as funcoes pbl_read2() e pbl_read3() */ if (pos1) { sprintf (str, "%8x%8x", tag[0], tag[1]); for (i=0; i<(PES_CHIP/4); i++) str[i] = (str[i]==' ' ? '0' : str[i]); if(pos1>=0) for (i=0; i<(PES_CHIP/4); i++) res[(i+(pos1/4))%(PES_CHIP/4)] = str[i]; /* Roda tags na direccao (63 <- 0) em multiplos 4 */ else /* pos1 < 0 */ for (i=0; i<(PES_CHIP/4); i++) res[i] = str[(i-(pos1/4))%(PES_CHIP/4)]; /* Roda tags na direccao (63 -> 0), em multiplos 4 */ for (i=15; i>7; i--) res[i+1] = res[i]; /*cria espaco para separar res em dois */ res[8] = ' '; /* divide res em dois */ res[17] = 0; /* terminador para sscanf */ sscanf (res, "%x %x", &tag2[0], &tag2[1]); } else { tag2[0] = tag[0]; tag2[1] = tag[1]; } } /*----------------------------------------------------------------*/ void restore_tag (void) { int i, bloco, mascara; ms[0]=msbak[0]; /* Hold ms */ ms[1]=msbak[1]; tag[0] = tag[1] = 0; bloco = 0; mascara = 0x80000000; for (i=0; i>=1; } } extern void (match)(void); extern void (tag_match)(void); extern void (cy_match)(void); extern void (and_match)(void); extern void (arith_this)(void); extern void (arith_above)(void); extern void (arith_below)(void); extern void (arith_image)(void); extern void (rotate_imag)(void); extern void (swap_this)(void); extern void (swap_above)(void); extern void (swap_below)(void); extern void (swap_image)(void); extern void (arithholdms)(void); extern void (swap_holdms)(void); extern void (overf_this)(void); extern void (overf_above)(void); extern void (overf_below)(void); extern void (overf_image)(void); extern void (overfholdms)(void); extern void (cpdata_this)(void); extern void (cpdata_abov)(void); extern void (cpdata_belo)(void); extern void (cpdata_imag)(void); extern void (cpsign_this)(void); extern void (cpsign_abov)(void); extern void (cpsign_belo)(void); extern void (cpsign_imag)(void); extern void (logic_this)(void); extern void (logic_above)(void); extern void (logic_below)(void); extern void (logic_image)(void); extern void (xor_this)(void); extern void (xor_above)(void); extern void (xor_below)(void); extern void (xor_image)(void); extern void (write_image)(void); extern void (shiftVsr)(void); /* NOVA */ extern void (extract_imag)(void); /* NOVA */ void init_rom (void) /* Inicializar os apontadores */ { PE_ROM[0] = nop ; /*----------------------- OPERACOES DE MATCH */ PE_ROM[1] = match ; PE_ROM[2] = tag_match ; PE_ROM[3] = cy_match ; PE_ROM[4] = and_match ; /*----------------------- OPERACOES ARITMETICAS */ PE_ROM[5] = arith_this ; PE_ROM[6] = arith_above ; PE_ROM[7] = arith_below ; PE_ROM[8] = arith_image ; PE_ROM[9] = swap_this ; PE_ROM[10] = swap_above ; PE_ROM[11] = swap_below ; PE_ROM[12] = swap_image ; PE_ROM[13] = arithholdms ; PE_ROM[14] = swap_holdms ; /*----------------------- CALCULO DO BIT DE SINAL */ PE_ROM[15] = overf_this ; PE_ROM[16] = overf_above ; PE_ROM[17] = overf_below ; PE_ROM[18] = overf_image ; PE_ROM[19] = overfholdms ; /*----------------------- COMPARACAO DE MAGNITUDE */ PE_ROM[20] = cpdata_this ; PE_ROM[21] = cpdata_abov ; PE_ROM[22] = cpdata_belo ; PE_ROM[23] = cpdata_imag ; PE_ROM[24] = cpsign_this ; PE_ROM[25] = cpsign_abov ; PE_ROM[26] = cpsign_belo ; PE_ROM[27] = cpsign_imag ; /*----------------------- OPERACOES LOGICAS */ PE_ROM[28] = logic_this ; PE_ROM[29] = logic_above ; PE_ROM[30] = logic_below ; PE_ROM[31] = logic_image ; PE_ROM[32] = xor_this ; PE_ROM[33] = xor_above ; PE_ROM[34] = xor_below ; PE_ROM[35] = xor_image ; /*----------------------- DESLOCAMENTO DE TAGS */ PE_ROM[36] = shift_up ; PE_ROM[37] = shift_down ; PE_ROM[38] = extract_tag ; PE_ROM[39] = restore_tag ; /*----------------------- MANIPULAR TAGS DE VARIOS CHIPS */ PE_ROM[40] = init_alt_ch ; PE_ROM[41] = init_alt_b1 ; PE_ROM[42] = init_alt_b0 ; PE_ROM[43] = alt ; PE_ROM[44] = tag_alt ; PE_ROM[45] = carry_alt ; PE_ROM[46] = init_first0 ; PE_ROM[47] = init_first1 ; PE_ROM[48] = first ; PE_ROM[49] = clear_first ; /*----------------------- LEITURA DA CAM */ PE_ROM[50] = read_this ; PE_ROM[51] = read_above ; PE_ROM[52] = read_below ; /*----------------------- ESCRITA NA */ PE_ROM[53] = write_this ; PE_ROM[54] = write_above ; PE_ROM[55] = write_below ; PE_ROM[56] = write_image ; /*----------------------- OPERAR COM VSR */ PE_ROM[57] = rotate_imag ; /*----------------------- VARIADAS */ PE_ROM[58] = tag_to_cy ; PE_ROM[59] = tag_to_subs ; PE_ROM[60] = tag_subset ; PE_ROM[61] = cy_subset ; PE_ROM[62] = clear_n_sub ; PE_ROM[63] = refresh ; PE_ROM[64] = shiftVsr ; /* NOVA */ PE_ROM[65] = extract_imag ; /* NOVA */ }