/**************************************************************************** Copyright (C) 1987-2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Last edit by hansen on Mon Jan 19 18:14:05 2009 ****************************************************************************/ #include "tkgate.h" #include "print.h" #define CLOCK_OUT 0 #define CLOCKPARAMXOFFSET 0 #define CLOCKPARAMYOFFSET 20 /* Defines local to this file */ #define F_PW 0x1 #define F_PHI 0x2 #define F_DW 0x4 /* Default clock parameters */ #define CLOCK_OMEGA 100 #define CLOCK_PHI 0 #define CLOCK_DUTY 50 static void Clock_WriteCellDef(FILE *f,GCellSpec *gcs); static iconDimensions clock_iconDims[] = { {0, 0, 27, 25, 13, 12}, {27, 0, 25, 26, 12, 14}, {26, 27, 27, 25, 12, 13}, {0, 26, 25, 26, 15, 14}, }; static int clock_iconBoldOffset = 53; GCElement *Clock_Make(EditState **es,GModuleDef *env,int GType, int x,int y,int r,const char *Name,int noWire,const char**,int); void Clock_Draw(GCElement *g,int md); GCElement *Clock_Copy(GModuleDef *M,GCElement *g,int x,int y,unsigned flags); int Clock_EditProps(GCElement *g,int isLoadDialog); void Clock_PSWrite(GPrint *P,GModLayout*,GCElement *g); void Clock_VerSave(FILE*,GCElement*); void Clock_SetProp(GCElement*,const char*,const void*); GPadLoc clock_out_loc[] = { {13,0,13,0,D_RIGHT}, {0,-15,0,-15,D_UP}, {-13,-1,-13,-1,D_LEFT}, {-3,12,-3,12,D_DOWN}}; static char *psClock[] = { "%", "% dw phi pw x y r clockgate", "%", "/psclock_base {", " [[-1 0][0 0][1 -1][-3 -2]] adjstartgate", " -8 -12 moveto", " 16 0 lineto", " -8 12 lineto", " closepath", " stroke", " -6 -4 moveto", " -4 -4 lineto", " -4 4 lineto", " 0 4 lineto", " 0 -4 lineto", " 2 -4 lineto", " stroke", " grestore", "} def", "/psclock {", " 3 copy psclock_base", " startnorotgate", " 0 -20 translate", " 0 0 moveto", " 8 rfont", " (P = ) show", " 20 string cvs show", " ( ) show", " 8 syfont", " (f) show ", " 8 rfont", " ( = ) show", " 20 string cvs show", " ( D = ) show", " 20 string cvs show", " grestore", "} bind def", 0 }; GGateInfo gate_clock_info = { GC_CLOCK, "CLOCK", "clock",0x0, "psclock",psClock, -1,-1, {{"c", {"gm.io",0}, {"gm.io.clock",0,"x",100}, "gat_make CLOCK"}, {0}}, clock_iconDims, 1,{{"Z",OUT,1,1,clock_out_loc}}, {{0,-17,CT},{17,0,LJ},{0,-17,CT},{17,0,LJ}}, {1}, {0}, Clock_Make, Clock_WriteCellDef, Generic_Init, Generic_Delete, Generic_GetExtents, Generic_HitDistance, Clock_Draw, Generic_Move, Clock_Copy, Err_AddInput, Err_AddOutput, Err_AddInOut, Generic_Rotate, Err_RemovePort, Err_ChangePin, Nop_SimInitFunc, Nop_SimHitFunc, Clock_PSWrite, Clock_EditProps, Clock_VerSave, Clock_SetProp }; void gate_drawclockparams(GCElement *g) { char b[STRMAX]; int x,y; x = g->xpos + CLOCKPARAMXOFFSET; y = g->ypos + CLOCKPARAMYOFFSET; if (g->selected) XSetFont(TkGate.D,TkGate.instGC,TkGate.stextbXF[TkGate.circuit->zoom_factor]->fid); else XSetFont(TkGate.D,TkGate.instGC,TkGate.stextXF[TkGate.circuit->zoom_factor]->fid); sprintf(b,"f=%d ",g->u.clock.omega); x = RelPosDrawString(TkGate.painterW,TkGate.stextXF[TkGate.circuit->zoom_factor],TkGate.instGC,x,y,b,AtLeft); sprintf(b,"p=%d ",g->u.clock.phi); x = RelPosDrawString(TkGate.painterW,TkGate.stextXF[TkGate.circuit->zoom_factor],TkGate.instGC,x,y,b,AtLeft); sprintf(b,"dw=%d ",g->u.clock.duty); x = RelPosDrawString(TkGate.painterW,TkGate.stextXF[TkGate.circuit->zoom_factor],TkGate.instGC,x,y,b,AtLeft); } GCElement *Clock_Make(EditState **es,GModuleDef *env,int GType, int x,int y,int r,const char *Name,int noWire,const char **options,int nOptions) { GCElement *g; const char *LPW,*LPhi,*LDW; if (!(g = Generic_Make(es,env,GType,x,y,r,Name,noWire,options,nOptions))) return NULL; LPW = seekOption("-pw",options,nOptions); LPhi = seekOption("-phi",options,nOptions); LDW = seekOption("-dw",options,nOptions); if (!LPW || sscanf(LPW,"%hd",&g->u.clock.omega) != 1) g->u.clock.omega = CLOCK_OMEGA; if (!LPhi || sscanf(LPhi,"%hd",&g->u.clock.phi) != 1) g->u.clock.phi = CLOCK_PHI; if (!LDW || sscanf(LDW,"%hd",&g->u.clock.duty) != 1) g->u.clock.duty = CLOCK_DUTY; return g; } void Clock_Draw(GCElement *g,int md) { Generic_Draw(g,md); gate_drawclockparams(g); } GCElement *Clock_Copy(GModuleDef *M,GCElement *g,int x,int y,unsigned flags) { GCElement *ng; ng = Generic_Copy(M,g,x,y,flags); ng->u.clock.omega = g->u.clock.omega; ng->u.clock.phi = g->u.clock.phi; ng->u.clock.duty = g->u.clock.duty; return ng; } void Clock_PSWrite(GPrint *P,GModLayout *L,GCElement *g) { Generic_PSLabels(P,g); fprintf(P->p_f,"%d %d %d %d %d %d %s\n", g->u.clock.duty,g->u.clock.phi,g->u.clock.omega, g->xpos,g->ypos,-g->orient*90,g->typeinfo->psprint); } int Clock_EditProps(GCElement *g,int isLoadDialog) { Tcl_Interp *tcl = TkGate.tcl; Generic_EditProps(g,isLoadDialog); if (isLoadDialog) { DoTcl("set ::ecpOmega %d",g->u.clock.omega); DoTcl("set ::ecpPhi %d",g->u.clock.phi); DoTcl("set ::ecpDuty %d",g->u.clock.duty); } else { const char *p; if ((p = Tcl_GetVar(tcl,"ecpOmega",TCL_GLOBAL_ONLY))) sscanf(p,"%hd",&g->u.clock.omega); if ((p = Tcl_GetVar(tcl,"ecpPhi",TCL_GLOBAL_ONLY))) sscanf(p,"%hd",&g->u.clock.phi); if ((p = Tcl_GetVar(tcl,"ecpDuty",TCL_GLOBAL_ONLY))) sscanf(p,"%hd",&g->u.clock.duty); } return 0; } void Clock_VerSave(FILE *f,GCElement *g) { VerilogBasicGateCall(f,g); VerilogBasicGateParmList(f,g); VerilogBasicGateComment(f,g,1); fprintf(f," /omega:%d /phi:%d /duty:%d",g->u.clock.omega,g->u.clock.phi,g->u.clock.duty); fprintf(f,"\n"); } void Clock_SetProp(GCElement *g,const char *prop,const void *value) { if (strcmp(prop,"/omega") == 0) { int n = *((int*)value); g->u.clock.omega = n; } else if (strcmp(prop,"/phi") == 0) { int n = *((int*)value); g->u.clock.phi = n; } else if (strcmp(prop,"/duty") == 0) { int n = *((int*)value); g->u.clock.duty = n; } } static void Clock_WriteCellDef(FILE *f,GCellSpec *gcs) { const char *invSpec = gcs->gc_invSpec; int period = gcs->gc_parms[0]; int shift = gcs->gc_parms[1]*period/100; int duty = gcs->gc_parms[2]; int on_time, off_time; /** @TODO to remove */ /* int on_value = 1; */ int start_value; int phase_wait; PrimParm primParm; if (period < 2) period = 2; if (duty <= 0 || duty >= 100) duty = 50; if (shift < 0) shift = 0; off_time = period*duty/100; on_time = period - off_time; shift %= period; if (on_time <= 0) { on_time = 1; off_time--; } if (off_time <= 0) { off_time = 1; on_time--; } if (shift < off_time) { start_value = 0; phase_wait = off_time-shift; } else { start_value = 1; phase_wait = period-shift; } PrimParm_init(&primParm); PrimParm_intSet(&primParm,"INITIAL",start_value); PrimParm_intSet(&primParm,"PHASE",phase_wait); PrimParm_intSet(&primParm,"OFF_TIME",off_time); PrimParm_intSet(&primParm,"ON_TIME",on_time); PrimParm_invSet(&primParm,"invZ",(*invSpec == 'N')); Primitive_write(f,"clock",gcs,&primParm); } void init_clock() { Pixmap P; P = Pixmap_registerFromFile("clock","clock.b"); gateinfo_iconInit(&gate_clock_info,P,clock_iconDims,clock_iconBoldOffset); RegisterGate(&gate_clock_info); }