1 /****************************************************************************
2 Copyright (C) 1987-2015 by Jeffery P. Hansen
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18 Last edit by hansen on Mon Jan 19 18:14:05 2009
19 ****************************************************************************/
20
21 #include "tkgate.h"
22
23 #include "print.h"
24
25 #define CLOCK_OUT 0
26 #define CLOCKPARAMXOFFSET 0
27 #define CLOCKPARAMYOFFSET 20
28
29 /* Defines local to this file */
30 #define F_PW 0x1
31 #define F_PHI 0x2
32 #define F_DW 0x4
33
34 /* Default clock parameters */
35 #define CLOCK_OMEGA 100
36 #define CLOCK_PHI 0
37 #define CLOCK_DUTY 50
38
39 static void Clock_WriteCellDef(FILE *f,GCellSpec *gcs);
40
41 static iconDimensions clock_iconDims[] = {
42 {0, 0, 27, 25, 13, 12},
43 {27, 0, 25, 26, 12, 14},
44 {26, 27, 27, 25, 12, 13},
45 {0, 26, 25, 26, 15, 14},
46 };
47 static int clock_iconBoldOffset = 53;
48
49 GCElement *Clock_Make(EditState **es,GModuleDef *env,int GType,
50 int x,int y,int r,const char *Name,int noWire,const char**,int);
51 void Clock_Draw(GCElement *g,int md);
52 GCElement *Clock_Copy(GModuleDef *M,GCElement *g,int x,int y,unsigned flags);
53 int Clock_EditProps(GCElement *g,int isLoadDialog);
54 void Clock_PSWrite(GPrint *P,GModLayout*,GCElement *g);
55 void Clock_VerSave(FILE*,GCElement*);
56 void Clock_SetProp(GCElement*,const char*,const void*);
57
58 GPadLoc clock_out_loc[] = {
59 {13,0,13,0,D_RIGHT},
60 {0,-15,0,-15,D_UP},
61 {-13,-1,-13,-1,D_LEFT},
62 {-3,12,-3,12,D_DOWN}};
63
64 static char *psClock[] = {
65 "%",
66 "% dw phi pw x y r clockgate",
67 "%",
68 "/psclock_base {",
69 " [[-1 0][0 0][1 -1][-3 -2]] adjstartgate",
70 " -8 -12 moveto",
71 " 16 0 lineto",
72 " -8 12 lineto",
73 " closepath",
74 " stroke",
75 " -6 -4 moveto",
76 " -4 -4 lineto",
77 " -4 4 lineto",
78 " 0 4 lineto",
79 " 0 -4 lineto",
80 " 2 -4 lineto",
81 " stroke",
82 " grestore",
83 "} def",
84 "/psclock {",
85 " 3 copy psclock_base",
86 " startnorotgate",
87 " 0 -20 translate",
88 " 0 0 moveto",
89 " 8 rfont",
90 " (P = ) show",
91 " 20 string cvs show",
92 " ( ) show",
93 " 8 syfont",
94 " (f) show ",
95 " 8 rfont",
96 " ( = ) show",
97 " 20 string cvs show",
98 " ( D = ) show",
99 " 20 string cvs show",
100 " grestore",
101 "} bind def",
102 0
103 };
104
105 GGateInfo gate_clock_info = {
106 GC_CLOCK,
107 "CLOCK",
108 "clock",0x0,
109 "psclock",psClock,
110 -1,-1,
111
112 {{"c", {"gm.io",0}, {"gm.io.clock",0,"x",100}, "gat_make CLOCK"},
113 {0}},
114
115 clock_iconDims,
116
117 1,{{"Z",OUT,1,1,clock_out_loc}},
118 {{0,-17,CT},{17,0,LJ},{0,-17,CT},{17,0,LJ}},
119 {1},
120
121 {0},
122
123 Clock_Make,
124 Clock_WriteCellDef,
125 Generic_Init,
126 Generic_Delete,
127 Generic_GetExtents,
128 Generic_HitDistance,
129 Clock_Draw,
130 Generic_Move,
131 Clock_Copy,
132 Err_AddInput,
133 Err_AddOutput,
134 Err_AddInOut,
135 Generic_Rotate,
136 Err_RemovePort,
137 Err_ChangePin,
138 Nop_SimInitFunc,
139 Nop_SimHitFunc,
140 Clock_PSWrite,
141 Clock_EditProps,
142 Clock_VerSave,
143 Clock_SetProp
144 };
145
gate_drawclockparams(GCElement * g)146 void gate_drawclockparams(GCElement *g)
147 {
148 char b[STRMAX];
149 int x,y;
150
151 x = g->xpos + CLOCKPARAMXOFFSET;
152 y = g->ypos + CLOCKPARAMYOFFSET;
153
154 if (g->selected)
155 XSetFont(TkGate.D,TkGate.instGC,TkGate.stextbXF[TkGate.circuit->zoom_factor]->fid);
156 else
157 XSetFont(TkGate.D,TkGate.instGC,TkGate.stextXF[TkGate.circuit->zoom_factor]->fid);
158
159 sprintf(b,"f=%d ",g->u.clock.omega);
160 x = RelPosDrawString(TkGate.painterW,TkGate.stextXF[TkGate.circuit->zoom_factor],TkGate.instGC,x,y,b,AtLeft);
161
162 sprintf(b,"p=%d ",g->u.clock.phi);
163 x = RelPosDrawString(TkGate.painterW,TkGate.stextXF[TkGate.circuit->zoom_factor],TkGate.instGC,x,y,b,AtLeft);
164
165 sprintf(b,"dw=%d ",g->u.clock.duty);
166 x = RelPosDrawString(TkGate.painterW,TkGate.stextXF[TkGate.circuit->zoom_factor],TkGate.instGC,x,y,b,AtLeft);
167 }
168
Clock_Make(EditState ** es,GModuleDef * env,int GType,int x,int y,int r,const char * Name,int noWire,const char ** options,int nOptions)169 GCElement *Clock_Make(EditState **es,GModuleDef *env,int GType,
170 int x,int y,int r,const char *Name,int noWire,const char **options,int nOptions)
171 {
172 GCElement *g;
173 const char *LPW,*LPhi,*LDW;
174
175 if (!(g = Generic_Make(es,env,GType,x,y,r,Name,noWire,options,nOptions)))
176 return NULL;
177
178 LPW = seekOption("-pw",options,nOptions);
179 LPhi = seekOption("-phi",options,nOptions);
180 LDW = seekOption("-dw",options,nOptions);
181
182 if (!LPW || sscanf(LPW,"%hd",&g->u.clock.omega) != 1)
183 g->u.clock.omega = CLOCK_OMEGA;
184
185 if (!LPhi || sscanf(LPhi,"%hd",&g->u.clock.phi) != 1)
186 g->u.clock.phi = CLOCK_PHI;
187
188 if (!LDW || sscanf(LDW,"%hd",&g->u.clock.duty) != 1)
189 g->u.clock.duty = CLOCK_DUTY;
190
191 return g;
192 }
193
194
Clock_Draw(GCElement * g,int md)195 void Clock_Draw(GCElement *g,int md)
196 {
197 Generic_Draw(g,md);
198 gate_drawclockparams(g);
199 }
200
Clock_Copy(GModuleDef * M,GCElement * g,int x,int y,unsigned flags)201 GCElement *Clock_Copy(GModuleDef *M,GCElement *g,int x,int y,unsigned flags)
202 {
203 GCElement *ng;
204
205 ng = Generic_Copy(M,g,x,y,flags);
206
207 ng->u.clock.omega = g->u.clock.omega;
208 ng->u.clock.phi = g->u.clock.phi;
209 ng->u.clock.duty = g->u.clock.duty;
210
211 return ng;
212 }
213
Clock_PSWrite(GPrint * P,GModLayout * L,GCElement * g)214 void Clock_PSWrite(GPrint *P,GModLayout *L,GCElement *g)
215 {
216 Generic_PSLabels(P,g);
217
218 fprintf(P->p_f,"%d %d %d %d %d %d %s\n",
219 g->u.clock.duty,g->u.clock.phi,g->u.clock.omega,
220 g->xpos,g->ypos,-g->orient*90,g->typeinfo->psprint);
221 }
222
Clock_EditProps(GCElement * g,int isLoadDialog)223 int Clock_EditProps(GCElement *g,int isLoadDialog)
224 {
225 Tcl_Interp *tcl = TkGate.tcl;
226
227 Generic_EditProps(g,isLoadDialog);
228 if (isLoadDialog) {
229 DoTcl("set ::ecpOmega %d",g->u.clock.omega);
230 DoTcl("set ::ecpPhi %d",g->u.clock.phi);
231 DoTcl("set ::ecpDuty %d",g->u.clock.duty);
232 } else {
233 const char *p;
234 if ((p = Tcl_GetVar(tcl,"ecpOmega",TCL_GLOBAL_ONLY)))
235 sscanf(p,"%hd",&g->u.clock.omega);
236 if ((p = Tcl_GetVar(tcl,"ecpPhi",TCL_GLOBAL_ONLY)))
237 sscanf(p,"%hd",&g->u.clock.phi);
238 if ((p = Tcl_GetVar(tcl,"ecpDuty",TCL_GLOBAL_ONLY)))
239 sscanf(p,"%hd",&g->u.clock.duty);
240 }
241
242 return 0;
243 }
244
Clock_VerSave(FILE * f,GCElement * g)245 void Clock_VerSave(FILE *f,GCElement *g)
246 {
247 VerilogBasicGateCall(f,g);
248 VerilogBasicGateParmList(f,g);
249 VerilogBasicGateComment(f,g,1);
250 fprintf(f," /omega:%d /phi:%d /duty:%d",g->u.clock.omega,g->u.clock.phi,g->u.clock.duty);
251 fprintf(f,"\n");
252 }
253
Clock_SetProp(GCElement * g,const char * prop,const void * value)254 void Clock_SetProp(GCElement *g,const char *prop,const void *value)
255 {
256 if (strcmp(prop,"/omega") == 0) {
257 int n = *((int*)value);
258 g->u.clock.omega = n;
259 } else if (strcmp(prop,"/phi") == 0) {
260 int n = *((int*)value);
261 g->u.clock.phi = n;
262 } else if (strcmp(prop,"/duty") == 0) {
263 int n = *((int*)value);
264 g->u.clock.duty = n;
265 }
266 }
267
Clock_WriteCellDef(FILE * f,GCellSpec * gcs)268 static void Clock_WriteCellDef(FILE *f,GCellSpec *gcs)
269 {
270 const char *invSpec = gcs->gc_invSpec;
271 int period = gcs->gc_parms[0];
272 int shift = gcs->gc_parms[1]*period/100;
273 int duty = gcs->gc_parms[2];
274 int on_time, off_time;
275 /** @TODO to remove */
276 /*
277 int on_value = 1;
278 */
279 int start_value;
280 int phase_wait;
281 PrimParm primParm;
282
283 if (period < 2) period = 2;
284 if (duty <= 0 || duty >= 100) duty = 50;
285 if (shift < 0) shift = 0;
286 off_time = period*duty/100;
287 on_time = period - off_time;
288 shift %= period;
289 if (on_time <= 0) {
290 on_time = 1;
291 off_time--;
292 }
293 if (off_time <= 0) {
294 off_time = 1;
295 on_time--;
296 }
297
298 if (shift < off_time) {
299 start_value = 0;
300 phase_wait = off_time-shift;
301 } else {
302 start_value = 1;
303 phase_wait = period-shift;
304 }
305
306
307 PrimParm_init(&primParm);
308 PrimParm_intSet(&primParm,"INITIAL",start_value);
309 PrimParm_intSet(&primParm,"PHASE",phase_wait);
310 PrimParm_intSet(&primParm,"OFF_TIME",off_time);
311 PrimParm_intSet(&primParm,"ON_TIME",on_time);
312 PrimParm_invSet(&primParm,"invZ",(*invSpec == 'N'));
313 Primitive_write(f,"clock",gcs,&primParm);
314 }
315
init_clock()316 void init_clock()
317 {
318 Pixmap P;
319
320 P = Pixmap_registerFromFile("clock","clock.b");
321 gateinfo_iconInit(&gate_clock_info,P,clock_iconDims,clock_iconBoldOffset);
322 RegisterGate(&gate_clock_info);
323 }
324