/**************************************************************************** Copyright (C) 1987-2005 by Jeffery P. Hansen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ****************************************************************************/ #include #include #include #include #include #include #include #include #include "gsim.h" #define DEBUG_SSTATE 0 #define isBDig(x) ((x) == SYM_ONE || (x) == SYM_ZERO) #define ABS(n) ((n) < 0 ? -(n) : (n)) static char *sym_table_lc = "*01@zlhx"; static char *sym_table = "*01@zLHx"; static int sym_table_len = 8; static int sstate_print_showbits = 1; static struct sstate_fl *sstate_freePool = 0; /* Allocate a temporary SState object */ SState *alloc_SState() { struct sstate_fl *S; static int fl_count = 0; static int ma_count = 0; if (!sstate_freePool) { S = (struct sstate_fl*) malloc(sizeof(struct sstate_fl)); SState_init((SState*)S,1); S->state.status = 1; ma_count++; } else { S = sstate_freePool; sstate_freePool = sstate_freePool->next; fl_count++; if (S->state.status != -1) { printf("echo bad state object in alloc_State() (status=%d).\n",S->state.status); assert(0); } S->state.status = 2; } #if DEBUG_SSTATE if (((fl_count+ma_count) % 10000) == 0) { printf("echo sstate: fl:%d ma:%d (%f)\n",fl_count,ma_count,(double)ma_count/(double)fl_count); fflush(stdout); } #endif return (SState*)S; } void free_SState(SState *S) { struct sstate_fl *flS = (struct sstate_fl *)S; flS->next = sstate_freePool; sstate_freePool = flS; if (S->status != 1 && S->status != 2) { printf("echo bad state object in free_State() (status=%d).\n",S->status); assert(0); } S->status = -1; } /* Logic values 0 1 x z L H ------------------------- one 0 1 1 0 0 1 zero 1 0 1 0 1 0 flt 0 0 1 1 1 1 */ static int charToSym(char c) { char *x; int p; if (isupper((int)c)) c = tolower(c); x = strchr(sym_table_lc,c); p = x ? (x-sym_table_lc) : SYM_ZERO; return p; } void SState_init(SState *S,int nbits) { int wc = SSNUMWORDS(nbits); S->status = 0; S->nbits = nbits; S->nalloc = wc; S->one = (unsigned*)malloc(wc*sizeof(unsigned)); S->zero = (unsigned*)malloc(wc*sizeof(unsigned)); S->flt = (unsigned*)malloc(wc*sizeof(unsigned)); SState_zero(S); } void SState_uninit(SState *S) { free(S->one); free(S->zero); free(S->flt); } void SState_reinit(SState *S,int nbits) { int nwc = SSNUMWORDS(nbits); if (nwc <= S->nalloc) { S->nbits = nbits; S->nalloc = nwc; SState_zero(S); } else { SState_uninit(S); SState_init(S,nbits); } } int SState_eq(SState *A,SState *B) { int wc = SSNUMWORDS(A->nbits); unsigned mask = (A->nbits==SSWORDSIZE) ? SSWORDMASK : ((1<<(A->nbits & SSBITMASK))-1); int i; if (A->nbits != B->nbits) return 0; for (i = 0;i < wc;i++) { if (i == wc-1) { if ((A->one[i]&mask) != (B->one[i]&mask)) return 0; if ((A->zero[i]&mask) != (B->zero[i]&mask)) return 0; if ((A->flt[i]&mask) != (B->flt[i]&mask)) return 0; } else { if (A->one[i] != B->one[i]) return 0; if (A->zero[i] != B->zero[i]) return 0; if (A->flt[i] != B->flt[i]) return 0; } } return 1; } void SState_unknown(SState *S) { int wc = SSNUMWORDS(S->nbits); int i; for (i = 0;i < wc;i++) { S->zero[i] = ~0; S->one[i] = ~0; S->flt[i] = ~0; } } void SState_float(SState *S) { int wc = SSNUMWORDS(S->nbits); int i; for (i = 0;i < wc;i++) { S->zero[i] = 0; S->one[i] = 0; S->flt[i] = ~0; } } void SState_zero(SState *S) { int wc = SSNUMWORDS(S->nbits); int i; for (i = 0;i < wc;i++) { S->zero[i] = ~0; S->one[i] = 0; S->flt[i] = 0; } } void SState_one(SState *S) { int wc = SSNUMWORDS(S->nbits); int i; for (i = 0;i < wc;i++) { S->one[i] = ~0; S->flt[i] = 0; S->zero[i] = 0; } } /* return non-zero if S has only 0 and 1 bits */ int SState_isValue(SState *S) { int wc = SSNUMWORDS(S->nbits); unsigned top_mask = LMASK(S->nbits & SSBITMASK); unsigned mask = SSWORDMASK; int i; for (i = 0;i < wc;i++) { if (i == wc-1 && (S->nbits & SSBITMASK)) mask = top_mask; if ((S->flt[i] & mask)) return 0; } return 1; } void SState_xclear(SState *S) { int wc = SSNUMWORDS(S->nbits); int i; for (i = 0;i < wc;i++) { S->one[i] = 0; S->flt[i] = 0; S->zero[i] = 0; } } static int getSymBit(SState *S,int i) { int w; unsigned b; int x = 0; if (i >= S->nbits) return SYM_ZERO; w = i >> SSWORDSHIFT; b = 1 << (i & SSBITMASK); if ((S->zero[w] & b)) x |= 0x1; if ((S->one[w] & b)) x |= 0x2; if ((S->flt[w] & b)) x |= 0x4; return x; } static void putSymBit(SState *S,int i,int p) { int w; unsigned b; if (i >= S->nbits) return; w = i >> SSWORDSHIFT; b = 1 << (i & SSBITMASK); if ((p & 0x1)) S->zero[w] |= b; else S->zero[w] &= ~b; if ((p & 0x2)) S->one[w] |= b; else S->one[w] &= ~b; if ((p & 0x4)) S->flt[w] |= b; else S->flt[w] &= ~b; } int SState_getBitSym(SState *S,int n) { return getSymBit(S,n); } static void SState_extend(SState *S,int d) { int i; int p = (d > 0) ? getSymBit(S,d-1) : SYM_ZERO; if (p == SYM_ONE) p = SYM_ZERO; for (i = d;i < S->nbits;i++) putSymBit(S,i,p); } static void SState_extendSym(SState *S,int d,int sym) { int i; for (i = d;i < S->nbits;i++) putSymBit(S,i,sym); } void SState_expandExtend(SState *R,int nbits) { if (nbits != R->nbits) { SState *X = alloc_SState(); int sym = getSymBit(R,R->nbits-1); int ob = R->nbits; SState_reinit(X,nbits); SState_copy(X,R); SState_reinit(R,nbits); SState_copy(R,X); SState_extendSym(R,ob,sym); free_SState(X); } } int SState_convertToInt(SState *S,unsigned *I) { if (S->nbits > SSWORDSIZE) return -1; if ((LMASK(S->nbits) & S->flt[0])) return -1; *I = S->one[0]; return 0; } int SState_convertFromInt(SState *S,unsigned I) { if (S->nbits > SSWORDSIZE) return -1; S->one[0] = I; S->zero[0] = ~I; S->flt[0] = 0; return 0; } static void SState_convertBits(SState *S,char *A,int nbits) { int d = strlen(A); int i; if (!nbits) nbits = d; SState_reinit(S,nbits); SState_xclear(S); for (i = 0;i < d;i++) { putSymBit(S,i,charToSym(A[d-i-1])); } SState_extend(S,d); } static void SState_convertHex(SState *S,char *A,int nbits) { int d = strlen(A); int i; if (!nbits) nbits = d*4; SState_reinit(S,nbits); SState_xclear(S); for (i = 0;i < d;i++) { char c = A[d-i-1]; if (isxdigit((int)c)) { int b = 4*i; int v; if (isdigit((int)c)) v = c - '0'; else { if (isupper((int)c)) c = tolower(c); v = c - 'a' + 10; } putSymBit(S,b, (v&0x1)?SYM_ONE:SYM_ZERO); putSymBit(S,b+1,(v&0x2)?SYM_ONE:SYM_ZERO); putSymBit(S,b+2,(v&0x4)?SYM_ONE:SYM_ZERO); putSymBit(S,b+3,(v&0x8)?SYM_ONE:SYM_ZERO); } else { int p = charToSym(c); int b = 4*i; putSymBit(S,b,p); putSymBit(S,b+1,p); putSymBit(S,b+2,p); putSymBit(S,b+3,p); } } SState_extend(S,4*d); } void SState_convert(SState *S,char *A) { int nbits = 0; char c,*p; if (sscanf(A,"%d'%c",&nbits,&c) == 2) { p = strchr(A,'\'')+2; } else if (sscanf(A,"'%c",&c) == 1) { nbits = 0; p = strchr(A,'\'')+2; } else { nbits = 0; p = A; c = 'b'; } if (c == 'b') SState_convertBits(S,p,nbits); else if (c == 'h') SState_convertHex(S,p,nbits); else { S->nbits = 1; *S->one = *S->zero = *S->flt = 0; } } void SState_printSymbol(int x,FILE *f) { if (x >= 0 && x < sym_table_len) fputc(sym_table[x],f); else fprintf(f,":%d:",x); } int SState_symbolStr(int x,char *p) { if (x >= 0 && x < sym_table_len) { *p = sym_table[x]; return 1; } else return sprintf(p,":%d:",x); } int SState_getstr(SState *S,char *p) { int N = S->nbits; int M = (N & 0x3) ? (N | 0x3)+1 : N; int i; char *q = p; *p = 0; if (N == 1) { int x = getSymBit(S,0); p += sprintf(p,"1'b"); p += SState_symbolStr(x,p); *p = 0; return p-q; } p += sprintf(p,"%d'h",N); for (i = N-1;i >= 0;i--) if (getSymBit(S,i) != SYM_FLOAT) break; if (i < 0) { p += sprintf(p,"z"); return p-q; } for (i = M;i > 0;i -= 4) { int x0 = getSymBit(S,i-4); int x1 = getSymBit(S,i-3); int x2 = getSymBit(S,i-2); int x3 = getSymBit(S,i-1); int bits_same,logic_digs; bits_same = (x3 == x0 || i-1 >= N) && (x2 == x0 || i-2 >= N) && (x1 == x0 || i-3 >= N); logic_digs = isBDig(x0) && isBDig(x1) && isBDig(x2) && isBDig(x3); if (bits_same && !isBDig(x0)) p += SState_symbolStr(x0,p); else if (logic_digs) { int d = 0; if (x0 == SYM_ONE) d |= 0x1; if (x1 == SYM_ONE) d |= 0x2; if (x2 == SYM_ONE) d |= 0x4; if (x3 == SYM_ONE) d |= 0x8; if (d <= 9) p += sprintf(p,"%d",d); else p += sprintf(p,"%c",d-10+'a'); } else { if (sstate_print_showbits) { p += sprintf(p,"("); if (i-1 < N) p += SState_symbolStr(x3,p); if (i-2 < N) p += SState_symbolStr(x2,p); if (i-3 < N) p += SState_symbolStr(x1,p); if (i-4 < N) p += SState_symbolStr(x0,p); p += sprintf(p,")"); } else p += sprintf(p,"?"); } } *p = 0; return p-q; } void SState_print(SState *S,FILE *f) { char buf[STRMAX]; SState_getstr(S,buf); fprintf(f,"%s",buf); } void SState_makeSameSize(SState *A,SState *B) { if (A->nbits < B->nbits) { int d = A->nbits-1; A->nbits = B->nbits; SState_extend(A,d); } else if (B->nbits < A->nbits) { int d = B->nbits-1; B->nbits = A->nbits; SState_extend(B,d); } } void SState_copy(SState *R,SState *A) { int wc = SSNUMWORDS(R->nbits); int i; for (i = 0;i < wc;i++) { R->one[i] = A->one[i]; R->zero[i] = A->zero[i]; R->flt[i] = A->flt[i]; } } /* Copy a range of bits. Copies bits in the range [ah:al] of A into R starting at bit rl */ void SState_copyRange(SState *R,int rl,SState *A,int ah,int al) { int awc = SSNUMWORDS(A->nbits); /* Words in A */ int rwc = SSNUMWORDS(R->nbits); /* Words in R */ int rh = rl+(ah-al); /* High bit of target in R */ int r_low_w = rl >> SSWORDSHIFT; /* Low word of destination */ int r_high_w = rh >> SSWORDSHIFT; /* High word of source */ unsigned low_mask = HMASKZ(rl&SSBITMASK); /* Mask for low word of destination */ unsigned high_mask = LMASK((rh+1)&SSBITMASK); /* Mask for high word of destination */ int ar_shift = ABS(rl-al); /* Difference between start points */ int ar_shift_b = ar_shift & SSBITMASK; /* Bits into word to shift */ int ar_shift_w = ar_shift >> SSWORDSHIFT; /* # of words to shift */ int i; assert(ah >= al); for (i = rwc-1;i >= 0;i--) { unsigned mask = SSWORDMASK; unsigned aone,azero,aflt; if (i < r_low_w || i > r_high_w) continue; if (i == r_low_w) mask &= low_mask; if (i == r_high_w) mask &= high_mask; aone = azero = aflt = 0; if (rl >= al) { int j = i-ar_shift_w; int k = j-1; if (j < awc && j >= 0) { aone |= A->one[j] << ar_shift_b; azero |= A->zero[j] << ar_shift_b; aflt |= A->flt[j] << ar_shift_b; } if (k < awc && k >= 0) { int shift = SSWORDSIZE - ar_shift_b; aone |= (A->one[k] >> shift) & LMASK(ar_shift_b); azero |= (A->zero[k] >> shift) & LMASK(ar_shift_b); aflt |= (A->flt[k] >> shift) & LMASK(ar_shift_b); } } else { int j = i+ar_shift_w; int k = j+1; if (j < awc && j >= 0) { aone |= A->one[j] >> ar_shift_b; azero |= A->zero[j] >> ar_shift_b; aflt |= A->flt[j] >> ar_shift_b; } if (k < awc && k >= 0) { int shift = SSWORDSIZE - ar_shift_b; aone |= (A->one[k] << shift) & HMASK(ar_shift_b); azero |= (A->zero[k] << shift) & HMASK(ar_shift_b); aflt |= (A->flt[k] << shift) & HMASK(ar_shift_b); } } R->one[i] = (mask&aone) | (~mask&R->one[i]); R->zero[i] = (mask&azero) | (~mask&R->zero[i]); R->flt[i] = (mask&aflt) | (~mask&R->flt[i]); } } void SState_not(SState *R,SState *A) { int wc = SSNUMWORDS(R->nbits); int i; for (i = 0;i < wc;i++) { register unsigned one = A->zero[i]; register unsigned zero = A->one[i]; R->one[i] = one|A->flt[i]; R->zero[i] = zero|A->flt[i]; R->flt[i] = A->flt[i]; } } void SState_buf(SState *R,SState *A) { int wc = SSNUMWORDS(R->nbits); int i; for (i = 0;i < wc;i++) { R->one[i] = A->one[i]|A->flt[i]; R->zero[i] = A->zero[i]|A->flt[i]; R->flt[i] = A->flt[i]; } } /* OR one zero flt 0 1 x z L H 0 1 x z L H 0 1 x z L H 0 1 x z L H +----------- +----------- +----------- +----------- 0|0 1 x x x x 0|0 1 1 1 1 1 0|1 0 1 1 1 1 0|0 0 1 1 1 1 1|1 1 1 1 1 1 1|1 1 1 1 1 1 1|0 0 0 0 0 0 1|0 0 0 0 0 0 x|x 1 x x x x x|1 1 1 1 1 1 x|1 0 1 1 1 1 x|1 0 1 1 1 1 z|x 1 x x x x z|1 1 1 1 1 1 z|1 0 1 1 1 1 z|1 0 1 1 1 1 L|x 1 x x x x L|1 1 1 1 1 1 L|1 0 1 1 1 1 L|1 0 1 1 1 1 H|x 1 x x x x H|1 1 1 1 1 1 H|1 0 1 1 1 1 H|1 0 1 1 1 1 */ void SState_or(SState *R,SState *A,SState *B,int invert) { int wc = SSNUMWORDS(R->nbits); register int i; for (i = 0;i < wc;i++) { register unsigned RisOne = (A->one[i]&~A->flt[i])|(B->one[i]&~B->flt[i]); register unsigned inHasFloat = A->flt[i]|B->flt[i]; if (invert) { R->one[i] = ~RisOne; R->zero[i] = RisOne|inHasFloat; } else { R->one[i] = RisOne|inHasFloat; R->zero[i] = ~RisOne; } R->flt[i] = (inHasFloat&~RisOne); } } /* AND one zero flt 0 1 x z L H 0 1 x z L H 0 1 x z L H 0 1 x z L H +----------- +----------- +----------- +----------- 0|0 0 0 0 0 0 0|0 0 0 0 0 0 0|1 1 1 1 1 1 0|0 0 0 0 0 0 1|0 1 x x x x 1|0 1 1 1 1 1 1|1 0 1 1 1 1 1|0 0 1 1 1 1 x|0 x x x x x x|0 1 1 1 1 1 x|1 1 1 1 1 1 x|0 1 1 1 1 1 z|0 x x x x x z|0 1 1 1 1 1 z|1 1 1 1 1 1 z|0 1 1 1 1 1 L|0 x x x x x L|0 1 1 1 1 1 L|1 1 1 1 1 1 L|0 1 1 1 1 1 H|0 x x x x x H|0 1 1 1 1 1 H|1 1 1 1 1 1 H|0 1 1 1 1 1 */ void SState_and(SState *R,SState *A,SState *B,int invert) { int wc = SSNUMWORDS(R->nbits); register int i; for (i = 0;i < wc;i++) { register unsigned RisZero = (A->zero[i]&~A->flt[i])|(B->zero[i]&~B->flt[i]); register unsigned inHasFloat = A->flt[i]|B->flt[i]; if (invert) { R->one[i] = RisZero|inHasFloat; R->zero[i] = ~RisZero; } else { R->one[i] = ~RisZero; R->zero[i] = RisZero|inHasFloat; } R->flt[i] = (inHasFloat&~RisZero); } } /* XOR one zero flt 0 1 x z L H 0 1 x z L H 0 1 x z L H 0 1 x z L H +----------- +----------- +----------- +----------- 0|0 1 x x x x 0|0 1 1 1 1 1 0|1 0 1 1 1 1 0|0 0 1 1 1 1 1|1 0 x x x x 1|1 0 1 1 1 1 1|0 1 1 1 1 1 1|0 0 1 1 1 1 x|x x x x x x x|1 1 1 1 1 1 x|1 1 1 1 1 1 x|1 1 1 1 1 1 z|x x x x x x z|1 1 1 1 1 1 z|1 1 1 1 1 1 z|1 1 1 1 1 1 L|x x x x x x L|1 1 1 1 1 1 L|1 1 1 1 1 1 L|1 1 1 1 1 1 H|x x x x x x H|1 1 1 1 1 1 H|1 1 1 1 1 1 H|1 1 1 1 1 1 */ void SState_xor(SState *R,SState *A,SState *B,int invert) { int wc = SSNUMWORDS(R->nbits); register int i; for (i = 0;i < wc;i++) { register unsigned RisOne = A->one[i]^B->one[i]; register unsigned inHasFloat = A->flt[i]|B->flt[i]; if (invert) { R->one[i] = ~(RisOne)|inHasFloat; R->zero[i] = RisOne|inHasFloat; } else { R->one[i] = RisOne|inHasFloat; R->zero[i] = ~(RisOne)|inHasFloat; } R->flt[i] = inHasFloat; } } /* bufif /E\ one zero flt 0 1 x z L H 0 1 x z L H 0 1 x z L H 0 1 x z L H +----------- +----------- +----------- +----------- 0|z 0 L L L L 0|0 0 0 0 0 0 0|0 1 1 1 1 1 0|1 0 1 1 1 1 1|z 1 H H H H 1|0 1 1 1 1 1 1|0 0 0 0 0 0 1|1 0 1 1 1 1 Ix|z x x x x x x|0 1 1 1 1 1 x|0 1 1 1 1 1 x|1 1 1 1 1 1 z|z x x x x x z|0 1 1 1 1 1 z|0 1 1 1 1 1 z|1 1 1 1 1 1 L|z x x x x x L|0 1 1 1 1 1 L|0 1 1 1 1 1 L|1 1 1 1 1 1 H|z x x x x x H|0 1 1 1 1 1 H|0 1 1 1 1 1 H|1 1 1 1 1 1 */ void SState_bufif(SState *R,SState *I,SState *E) { int wc = SSNUMWORDS(R->nbits); register int i; for (i = 0;i < wc;i++) { register unsigned IisZero = I->zero[i] & ~I->one[i] & ~I->flt[i]; register unsigned EisZero = E->zero[i] & ~E->one[i] & ~E->flt[i]; register unsigned IisOne = ~I->zero[i] & I->one[i] & ~I->flt[i]; register unsigned EisOne = ~E->zero[i] & E->one[i] & ~E->flt[i]; R->one[i] = ~(IisZero|EisZero); R->zero[i] = ~(EisZero|IisOne); R->flt[i] = ~((IisZero|IisOne)&EisOne); } } /* nmos /G\ one zero flt 0 1 x z L H 0 1 x z L H 0 1 x z L H 0 1 x z L H 01z +----------- +----------- +----------- +----------- --- 0|z 0 L L L L 0|0 0 0 0 0 0 0|0 1 1 1 1 1 0|1 0 1 1 1 1 100 1|z 1 H H H H 1|0 1 1 1 1 1 1|0 0 0 0 0 0 1|1 0 1 1 1 1 010 Ix|z x x x x x x|0 1 1 1 1 1 x|0 1 1 1 1 1 x|1 1 1 1 1 1 111 z|z z z z z z z|0 0 0 0 0 0 z|0 0 0 0 0 0 z|1 1 1 1 1 1 001 L|z L L L L L L|0 0 0 0 0 0 L|0 1 1 1 1 1 L|1 1 1 1 1 1 101 H|z H H H H H H|0 1 1 1 1 1 H|0 0 0 0 0 0 H|1 1 1 1 1 1 011 */ void SState_nmos(SState *R,SState *I,SState *G) { int wc = SSNUMWORDS(R->nbits); register int i; for (i = 0;i < wc;i++) { register unsigned GisZero = G->zero[i] & ~G->one[i] & ~G->flt[i]; register unsigned GisOne = ~G->zero[i] & G->one[i] & ~G->flt[i]; register unsigned IisLogic = (I->zero[i] ^ I->one[i]) & ~I->flt[i]; R->one[i] = I->one[i] & ~GisZero; R->zero[i] = I->zero[i] & ~GisZero; R->flt[i] = ~(IisLogic & GisOne); } } /* pmos /G\ one zero flt 0 1 x z L H 0 1 x z L H 0 1 x z L H 0 1 x z L H 01z +----------- +----------- +----------- +----------- --- 0|0 z L L L L 0|0 0 0 0 0 0 0|1 0 1 1 1 1 0|0 1 1 1 1 1 100 1|1 z H H H H 1|1 0 1 1 1 1 1|0 0 0 0 0 0 1|0 1 1 1 1 1 010 Ix|z z x x x x x|1 0 1 1 1 1 x|1 0 1 1 1 1 x|1 1 1 1 1 1 111 z|z z z z z z z|0 0 0 0 0 0 z|0 0 0 0 0 0 z|1 1 1 1 1 1 001 L|L z L L L L L|0 0 0 0 0 0 L|1 0 1 1 1 1 L|1 1 1 1 1 1 101 H|H z H H H H H|1 0 1 1 1 1 H|0 0 0 0 0 0 H|1 1 1 1 1 1 011 */ void SState_pmos(SState *R,SState *I,SState *G) { int wc = SSNUMWORDS(R->nbits); register int i; for (i = 0;i < wc;i++) { register unsigned GisZero = G->zero[i] & ~G->one[i] & ~G->flt[i]; register unsigned GisOne = ~G->zero[i] & G->one[i] & ~G->flt[i]; register unsigned IisLogic = (I->zero[i] ^ I->one[i]) & ~I->flt[i]; R->one[i] = I->one[i] & ~GisOne; R->zero[i] = I->zero[i] & ~GisOne; R->flt[i] = ~(IisLogic & GisZero); } } /* Wire merge function WIRE one zero flt 0 1 x z L H 0 1 x z L H 0 1 x z L H 0 1 x z L H 01z +----------- +----------- +----------- +----------- --- 0|0 x x 0 0 x 0|0 1 1 0 0 1 0|1 1 1 1 1 1 0|0 1 1 0 0 1 100 1|x 1 x 1 x 1 1|1 1 1 1 1 1 1|1 0 1 0 1 0 1|1 0 1 0 1 0 010 x|x x x x x x x|1 1 1 1 1 1 x|1 1 1 1 1 1 x|1 1 1 1 1 1 111 z|0 1 x z L H z|0 1 1 0 0 1 z|1 0 1 0 1 0 z|0 0 1 1 1 1 001 L|0 x x L L x L|0 1 1 0 0 1 L|1 1 1 1 1 1 L|0 1 1 1 1 1 101 H|x 1 x H x H H|1 1 1 1 1 1 H|1 0 1 0 1 0 H|1 0 1 1 1 1 011 */ void SState_wire(SState *R,SState *A,SState *B) { int wc = SSNUMWORDS(R->nbits); register int i; for (i = 0;i < wc;i++) { register unsigned RisOne = A->one[i]|B->one[i]; register unsigned RisZero = A->zero[i]|B->zero[i]; register unsigned RhasFloat = (A->flt[i]&B->flt[i]); R->one[i] = RisOne; R->zero[i] = RisZero; R->flt[i] = ~(RisOne ^ RisZero) | RhasFloat; } } /* * Does S contain only 1s and 0s? */ int SState_isLogic(SState *S) { int wc = SSNUMWORDS(S->nbits); unsigned mask = LMASK((S->nbits & SSBITMASK)); int i; for (i = 0;i < wc-1;i++) { if (S->flt[i]) return 0; } if ((S->flt[wc-1] & mask)) return 0; return 1; } /* * Shift I and place the result in R. * * Arguments: * * R Return value from operation * I Value to be shifted * n Bits to shift (>0 for left shift, <0 for right shift) * in1 Shift-in value to use in 'one' field * in0 Shift-in value to use in 'zero' field * inZ Shift-in value to use in 'flt' field */ void SState_roll(SState *R,SState *I,int n) { int bits = R->nbits; unsigned mask = (bits<32) ? ((1<nbits <= 32); assert(n >= 0); if (n > 0) { unsigned emask = (n<32) ? ((1<one[0] = (I->one[0] << n) | ((I->one[0] >> (bits-n)) & emask); R->zero[0] = (I->zero[0] << n) | ((I->zero[0] >> (bits-n)) & emask); R->flt[0] = (I->flt[0] << n) | ((I->flt[0] >> (bits-n)) & emask); } else { R->one[0] = I->one[0]; R->zero[0] = I->zero[0]; R->flt[0] = I->flt[0]; } R->one[0] &= mask; R->zero[0] &= mask; R->flt[0] &= mask; } /* * Shift I and place the result in R. * * Arguments: * * R Return value from operation * I Value to be shifted * n Bits to shift (>0 for left shift, <0 for right shift) * in1 Shift-in value to use in 'one' field * in0 Shift-in value to use in 'zero' field * inZ Shift-in value to use in 'flt' field */ void SState_shift(SState *R,SState *I,int n,int in1,int in0,int inZ) { int bits = R->nbits; unsigned mask = (bits<32) ? ((1<nbits <= 32); if (n > 0) { unsigned emask = (n<32) ? ((1<one[0] = (I->one[0] << n) | (in1*emask); R->zero[0] = (I->zero[0] << n) | (in0*emask); R->flt[0] = (I->flt[0] << n) | (inZ*emask); } else if (n < 0) { unsigned emask; n = -n; emask = ((n<32) ? ((1<one[0] = (I->one[0] >> n) | (in1*emask); R->zero[0] = (I->zero[0] >> n) | (in0*emask); R->flt[0] = (I->flt[0] >> n) | (inZ*emask); } else { R->one[0] = I->one[0]; R->zero[0] = I->zero[0]; R->flt[0] = I->flt[0]; } R->one[0] &= mask; R->zero[0] &= mask; R->flt[0] &= mask; } int testLogic(char *command) { char buf1[STRMAX],buf2[STRMAX]; static SState R,A,B; static int isInit = 0; int n1,n2,n3; if (!isInit) { SState_init(&R,8); SState_init(&A,8); SState_init(&B,8); isInit = 1; } if (sscanf(command," state %s",buf1) == 1) { SState_convert(&R,buf1); printf("state = "); SState_print(&R,stdout); printf("\n"); return 1; } else if (sscanf(command," not %s",buf1) == 1) { SState_convert(&A,buf1); SState_reinit(&R,A.nbits); SState_not(&R,&A); printf("state = "); SState_print(&A,stdout); printf("\n"); printf("not = "); SState_print(&R,stdout); printf("\n"); return 1; } else if (sscanf(command," and %s %s",buf1,buf2) == 2) { SState_convert(&A,buf1); SState_convert(&B,buf2); SState_makeSameSize(&A,&B); SState_reinit(&R,A.nbits); SState_and(&R,&A,&B,0); printf("A = "); SState_print(&A,stdout); printf("\n"); printf("B = "); SState_print(&B,stdout); printf("\n"); printf("and = "); SState_print(&R,stdout); printf("\n"); return 1; } else if (sscanf(command," or %s %s",buf1,buf2) == 2) { SState_convert(&A,buf1); SState_convert(&B,buf2); SState_makeSameSize(&A,&B); SState_reinit(&R,A.nbits); SState_or(&R,&A,&B,0); printf("A = "); SState_print(&A,stdout); printf("\n"); printf("B = "); SState_print(&B,stdout); printf("\n"); printf("or = "); SState_print(&R,stdout); printf("\n"); return 1; } else if (sscanf(command," xor %s %s",buf1,buf2) == 2) { SState_convert(&A,buf1); SState_convert(&B,buf2); SState_makeSameSize(&A,&B); SState_reinit(&R,A.nbits); SState_xor(&R,&A,&B,0); printf("A = "); SState_print(&A,stdout); printf("\n"); printf("B = "); SState_print(&B,stdout); printf("\n"); printf("xor = "); SState_print(&R,stdout); printf("\n"); return 1; } else if (sscanf(command," nand %s %s",buf1,buf2) == 2) { SState_convert(&A,buf1); SState_convert(&B,buf2); SState_makeSameSize(&A,&B); SState_reinit(&R,A.nbits); SState_and(&R,&A,&B,1); printf("A = "); SState_print(&A,stdout); printf("\n"); printf("B = "); SState_print(&B,stdout); printf("\n"); printf("nand = "); SState_print(&R,stdout); printf("\n"); return 1; } else if (sscanf(command," nor %s %s",buf1,buf2) == 2) { SState_convert(&A,buf1); SState_convert(&B,buf2); SState_makeSameSize(&A,&B); SState_reinit(&R,A.nbits); SState_or(&R,&A,&B,1); printf("A = "); SState_print(&A,stdout); printf("\n"); printf("B = "); SState_print(&B,stdout); printf("\n"); printf("nor = "); SState_print(&R,stdout); printf("\n"); return 1; } else if (sscanf(command," xnor %s %s",buf1,buf2) == 2) { SState_convert(&A,buf1); SState_convert(&B,buf2); SState_makeSameSize(&A,&B); SState_reinit(&R,A.nbits); SState_xor(&R,&A,&B,1); printf("A = "); SState_print(&A,stdout); printf("\n"); printf("B = "); SState_print(&B,stdout); printf("\n"); printf("xnor = "); SState_print(&R,stdout); printf("\n"); return 1; } else if (sscanf(command," bufif %s %s",buf1,buf2) == 2) { SState_convert(&A,buf1); SState_convert(&B,buf2); SState_makeSameSize(&A,&B); SState_reinit(&R,A.nbits); SState_bufif(&R,&A,&B); printf("A = "); SState_print(&A,stdout); printf("\n"); printf("B = "); SState_print(&B,stdout); printf("\n"); printf("bufif = "); SState_print(&R,stdout); printf("\n"); return 1; } else if (sscanf(command," nmos %s %s",buf1,buf2) == 2) { SState_convert(&A,buf1); SState_convert(&B,buf2); SState_makeSameSize(&A,&B); SState_reinit(&R,A.nbits); SState_nmos(&R,&A,&B); printf("I = "); SState_print(&A,stdout); printf("\n"); printf("G = "); SState_print(&B,stdout); printf("\n"); printf("nmos = "); SState_print(&R,stdout); printf("\n"); return 1; } else if (sscanf(command," cpr %s %d %s %d %d",buf1,&n1,buf2,&n2,&n3) == 5) { SState_convert(&A,buf1); SState_convert(&B,buf2); SState_reinit(&R,A.nbits); SState_copy(&R,&A); SState_copyRange(&R,n1,&B,n2,n3); printf("A[%d] = ",n1); SState_print(&A,stdout); printf("\n"); printf("B[%d:%d] = ",n2,n3); SState_print(&B,stdout); printf("\n"); printf("cpr = "); SState_print(&R,stdout); printf("\n"); } else if (sscanf(command," pmos %s %s",buf1,buf2) == 2) { SState_convert(&A,buf1); SState_convert(&B,buf2); SState_makeSameSize(&A,&B); SState_reinit(&R,A.nbits); SState_pmos(&R,&A,&B); printf("I = "); SState_print(&A,stdout); printf("\n"); printf("G = "); SState_print(&B,stdout); printf("\n"); printf("pmos = "); SState_print(&R,stdout); printf("\n"); return 1; } else if (sscanf(command," eq %s %s",buf1,buf2) == 2) { SState_convert(&A,buf1); SState_convert(&B,buf2); SState_makeSameSize(&A,&B); printf("A = "); SState_print(&A,stdout); printf("\n"); printf("B = "); SState_print(&B,stdout); printf("\n"); printf("eq = %d\n",SState_eq(&A,&B)); return 1; } else if (sscanf(command," wfunc %s %s",buf1,buf2) == 2) { SState_convert(&A,buf1); SState_convert(&B,buf2); SState_makeSameSize(&A,&B); SState_reinit(&R,A.nbits); SState_wire(&R,&A,&B); printf("A = "); SState_print(&A,stdout); printf("\n"); printf("B = "); SState_print(&B,stdout); printf("\n"); printf("wire = "); SState_print(&R,stdout); printf("\n"); return 1; } else if (sscanf(command," echo %s",buf1) == 1) { printf("%s\n",buf1); } return 0; }