/**************************************************************************** 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 "gsim.h" #define MULT_Z 0 #define MULT_A 1 #define MULT_B 2 #define MULT_DELAY 0 #if USELONGLONG #define MULT_MAXBITS (2*SSWORDSIZE) #else #define MULT_MAXBITS SSWORDSIZE #endif static void Mult_processEvent(SGate*,EvQueue*,SEvent*); static int Mult_checkGate(SGate*); static SGateInfo mult_info = { 0, "mult",0x1, 3,{{"P",GIO_OUT,0}, {"A",GIO_IN,0}, {"B",GIO_IN,0}}, {{"A/B-P",bit(1)|bit(2),0}, {0}}, Generic_copyGate, Mult_processEvent, Mult_checkGate, Nop_initGate, Generic_setProp, 0, 0, Generic_propFrwdDelay, Generic_propBackDelay, Generic_delay, }; void init_mult() { SGateInfo_register(&mult_info,0); } static int Mult_checkGate(SGate *g) { SPort *Z = g->g_ports.port[MULT_Z]; if (Z->p_net->n_nbits > MULT_MAXBITS) { errorGate(g->g_name,"Multiplier outputs greater than %s bits unsupported.",MULT_MAXBITS); return -1; } return 0; } static void Mult_processEvent(SGate *g,EvQueue *Q,SEvent *E) { SPort *Z = g->g_ports.port[MULT_Z]; SState *aS = SGate_allocPortState(g,MULT_A); SState *bS = SGate_allocPortState(g,MULT_B); SState *S = alloc_SState(); SState_reinit(S,Z->p_state.nbits); if (!SState_isValue(aS) || !SState_isValue(bS)) { SState_unknown(S); } else { #if USELONGLONG unsigned long long A,B,P; if (aS->nbits > SSWORDSIZE) A = aS->one[0] | ((((unsigned long long)aS->one[1]) << SSWORDSIZE)&LMASK(aS->nbits&SSBITMASK)); else A = aS->one[0] & LMASK(aS->nbits); if (bS->nbits > SSWORDSIZE) B = bS->one[0] | ((((unsigned long long)bS->one[1]) << SSWORDSIZE)&LMASK(bS->nbits&SSBITMASK)); else B = bS->one[0] & LMASK(bS->nbits); P = A*B; S->one[0] = P; S->zero[0] = ~P; S->flt[0] = 0; if (S->nbits > SSWORDSIZE) { P >>= SSWORDSIZE; S->one[1] = P; S->zero[1] = ~P; S->flt[1] = 0; } #else unsigned A,B,P; A = aS->one[0] & LMASK(aS->nbits); B = bS->one[0] & LMASK(bS->nbits); P = A*B; S->one[0] = P; S->zero[0] = ~P; S->flt[0] = 0; #endif } EvQueue_setPort(Q,Z,S,g->g_delayParms[MULT_DELAY]); free_SState(aS); free_SState(bS); free_SState(S); }