/**************************************************************************** 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 TAP_Z 0 #define TAP_I 1 #define TAP_DELAY 0 struct tap_data { int msb; int lsb; }; static SGate *Tap_copyGate(SGate *sg,const char *name,SModule *M); static void Tap_processEvent(SGate*,EvQueue*,SEvent*); static int Tap_checkGate(SGate *g); static void Tap_setProp(SGate*,const char*,const void*); static void Tap_propFrwdDelay(SPort *P,simTime t); static void Tap_propBackDelay(SPort *P,simTime t); static simTime Tap_delay(SPort *Pfrom,SPort *Pto); static SGateInfo tap_info = { 0, "tran",0x0, 2,{{"Z",GIO_OUT,0}, {"I",GIO_IN,0}}, {{0}}, Tap_copyGate, Tap_processEvent, Tap_checkGate, Nop_initGate, Tap_setProp, 0, 0, Tap_propFrwdDelay, Tap_propBackDelay, Tap_delay }; void init_tap() { SGateInfo_register(&tap_info,0); } static SGate *Tap_copyGate(SGate *sg,const char *name,SModule *M) { SGate *ng = Generic_copyGate(sg,name,M); struct tap_data *nd = (struct tap_data *) malloc(sizeof(struct tap_data)); struct tap_data *sd = (struct tap_data *) sg->g_data; ng->g_data = nd; *nd = *sd; return ng; } static void Tap_processEvent(SGate *g,EvQueue *Q,SEvent *E) { SPort *Z = g->g_ports.port[TAP_Z]; SState *I = SGate_allocPortState(g,TAP_I); SState *S = alloc_SState(); struct tap_data *d = (struct tap_data *)g->g_data; int wc = SSNUMWORDS(I->nbits); int w = d->lsb >> SSWORDSHIFT; int b = d->lsb & SSBITMASK; SState_reinit(S,Z->p_state.nbits); S->flt[0] = I->flt[w] >> b; S->one[0] = I->one[w] >> b; S->zero[0] = I->zero[w] >> b; if (w+1 < wc && (SSWORDSIZE-b) > (d->msb-d->lsb+1)) { S->flt[0] |= I->flt[w+1] << (SSWORDSIZE-b); S->one[0] |= I->one[w+1] << (SSWORDSIZE-b); S->zero[0] |= I->zero[w+1] << (SSWORDSIZE-b); } EvQueue_setPort(Q,Z,S,0); /* no delay */ free_SState(I); free_SState(S); } int Tap_checkGate(SGate *g) { SPort *Z = g->g_ports.port[TAP_Z]; SPort *I = g->g_ports.port[TAP_I]; struct tap_data *d = (struct tap_data *)g->g_data; int Zbits = Z->p_net->n_nbits; int Ibits = I->p_net->n_nbits; if (d->msb < d->lsb || d->lsb < 0) { errorGate(g->g_name,"Range \\[%d:%d\\] is illegal " "(msb must be >= lsb and lsb must be >= 0)." ,d->msb,d->lsb); return -1; } if (Zbits > 32) { errorGate(g->g_name,"Ranges greater than 32 bits are unsupported."); return -1; } if (d->msb >= Ibits) { errorGate(g->g_name,"Range \\[%d:%d\\] falls outside range of " "addressed wire." ,d->msb,d->lsb); return -1; } if (d->msb-d->lsb+1 != Zbits) { errorGate(g->g_name,"Number of bits in range \\[%d:%d\\] does " "not match size of output.",d->msb,d->lsb); return -1; } return 0; } static void Tap_setProp(SGate *g,const char *prop,const void *val) { struct tap_data *d = (struct tap_data *)g->g_data; int *n = (int*)val; if (!d) { d = (struct tap_data *) malloc(sizeof(struct tap_data)); g->g_data = d; } if (strcmp(prop,"/msb") == 0) d->msb = *n; else if (strcmp(prop,"/lsb") == 0) d->lsb = *n; } static void Tap_propFrwdDelay(SPort *P,simTime t) { SGate *g = P->p_gate; if (P == g->g_ports.port[TAP_I]) SNet_propFrwdDelay(g->g_ports.port[TAP_Z]->p_net,t); } static void Tap_propBackDelay(SPort *P,simTime t) { SGate *g = P->p_gate; if (P == g->g_ports.port[TAP_Z]) SNet_propBackDelay(g->g_ports.port[TAP_I]->p_net,t); } static simTime Tap_delay(SPort *Pfrom,SPort *Pto) { if (!Pto) return 0; if (Pfrom == Pto) return NO_TIME; return 0; }