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 23:41:17 2009
19 ****************************************************************************/
20
21 #include "tkgate.h"
22 #include "print.h"
23
24 #define REV_PADS 4 /* First four pads subject to mirror */
25 #define JKFF_Q 0
26 #define JKFF_NQ 1
27 #define JKFF_J 2
28 #define JKFF_K 3
29 #define JKFF_PRE 4
30 #define JKFF_CLR 5
31 #define JKFF_CK 6
32
33 static void JKFF_WriteCellDef(FILE *f,GCellSpec *gcs);
34 static GCElement *JKFF_Make(EditState **es,GModuleDef *env,int GType,
35 int x,int y,int r,const char *Name,int noWires,const char **options,int nOptions);
36 static void JKFF_Draw(GCElement *g,int md);
37 static int JKFF_EditProps(GCElement *g,int isLoadDialog);
38 static void JKFF_VerSave(FILE *f,GCElement *g);
39 static GCElement *JKFF_Copy(GModuleDef *M,GCElement *g,int x,int y,unsigned);
40 static void JKFF_SetProp(GCElement *g,const char *prop,const void *value);
41 static void JKFF_PSWrite(GPrint *gp,GModLayout*,GCElement *g);
42 static GWireNode *JKFF_wireSnap(GCElement *g,GWire *w,int *mod,int retry);
43 static void JKFF_Rotate(GCElement *g, int centX, int centY,int rdir);
44
45 static iconDimensions jkff_iconDims[] = {
46 {0, 0, 31, 31, 15, 15},
47 {32, 0, 31, 31, 15, 15},
48 {32, 32, 31, 31, 15, 15},
49 {0, 32, 31, 31, 15, 15},
50 };
51 static int jkff_iconBoldOffset = 64;
52
53 GPadLoc jkff_j_loc[] = {
54 {-16,-5,-16,-5,D_LEFT},
55 {-5,16,-5,16,D_DOWN},
56 {16,5,16,5,D_RIGHT},
57 {5,-16,5,-16,D_UP},
58 };
59
60 GPadLoc jkff_k_loc[] = {
61 {-16,5,-16,5,D_LEFT},
62 {5,16,5,16,D_DOWN},
63 {16,-5,16,-5,D_RIGHT},
64 {-5,-16,-5,-16,D_UP},
65 };
66
67 GPadLoc jkff_out_loc[] = {
68 {16,-5,16,-5,D_RIGHT},
69 {-5,-16,-5,-16,D_UP},
70 {-16,5,-16,5,D_LEFT},
71 {5,16,5,16,D_DOWN},
72 };
73
74 GPadLoc jkff_nout_loc[] = {
75 {16,5,16,5,D_RIGHT},
76 {5,-16,5,-16,D_UP},
77 {-16,-5,-16,-5,D_LEFT},
78 {-5,16,-5,16,D_DOWN},
79 };
80
81 GPadLoc jkff_ck_loc[] = {
82 {0,16,0,16,D_DOWN},
83 {16,0,16,0,D_RIGHT},
84 {0,-16,0,-16,D_UP},
85 {-16,0,-16,0,D_LEFT},
86 };
87
88 GPadLoc jkff_clr_loc[] = {
89 {5,-16,5,-16,D_UP},
90 {-16,-5,-16,-5,D_LEFT},
91 {-5,16,-5,16,D_DOWN},
92 {16,5,16,5,D_RIGHT},
93 };
94
95 GPadLoc jkff_pre_loc[] = {
96 {-5,-16,-5,-16,D_UP},
97 {-16,5,-16,5,D_LEFT},
98 {5,16,5,16,D_DOWN},
99 {16,-5,16,-5,D_RIGHT},
100 };
101
102 /***************************************************************************************/
103 /* Reverse locations */
104 /***************************************************************************************/
105 struct locate rjkff_j_loc[] = {
106 {16,-5,16,-5,D_RIGHT},
107 {-5,-16,-5,-16,D_UP},
108 {-16,5,-16,5,D_LEFT},
109 {5,16,5,16,D_DOWN},
110 };
111
112 struct locate rjkff_k_loc[] = {
113 {16,5,16,5,D_RIGHT},
114 {5,-16,5,-16,D_UP},
115 {-16,-5,-16,-5,D_LEFT},
116 {-5,16,-5,16,D_DOWN},
117 };
118
119 struct locate rjkff_out_loc[] = {
120 {-16,-5,-16,-5,D_LEFT},
121 {-5,16,-5,16,D_DOWN},
122 {16,5,16,5,D_RIGHT},
123 {5,-16,5,-16,D_UP},
124 };
125
126 struct locate rjkff_nout_loc[] = {
127 {-16,5,-16,5,D_LEFT},
128 {5,16,5,16,D_DOWN},
129 {16,-5,16,-5,D_RIGHT},
130 {-5,-16,-5,-16,D_UP},
131 };
132
133 static char *psJKFF[] = {
134 "%",
135 "% A JK flip-flop",
136 "/psjkff {",
137 " [[0 0][0 0][0 0][0 0]] adjstartgate",
138 " -15.5 -15.5 moveto",
139 " -15.5 15.5 lineto",
140 " 15.5 15.5 lineto",
141 " 15.5 -15.5 lineto",
142 " closepath stroke",
143 " -5 -15.5 moveto",
144 " 0 -10.5 lineto",
145 " 5 -15.5 lineto",
146 " stroke",
147 " 7 rfont",
148 " (_C) -8 6 prshow",
149 " (_P) 2 6 prshow",
150 " {",
151 " (Q) -14 2 prshow",
152 " (_Q) -14 -8 prshow",
153 " (J) 8 2 prshow",
154 " (K) 8 -8 prshow",
155 " } {",
156 " (Q) 8 2 prshow",
157 " (_Q) 8 -8 prshow",
158 " (J) -14 2 prshow",
159 " (K) -14 -8 prshow",
160 " } ifelse",
161 " grestore",
162 "} def",
163 0
164 };
165
166 GGateInfo gate_jkff_info = {
167 0,
168 "JKFF",
169 "jkff",0x0,
170 "psjkff",psJKFF,
171 -1,0,
172
173 {{"j", {"gm.mem",5}, {"gm.mem.jkff",0,0,200}, "gat_make JKFF"},
174 {"J", {"gm.mem",5}, {"gm.mem.rjkff",0,0,200}, "gat_make JKFF -reverse 1"},
175
176 {0}},
177
178
179 jkff_iconDims,
180
181 7,{{"Q",OUT,1,1,jkff_out_loc},
182 {"_Q",OUT,1,1,jkff_nout_loc},
183 {"J",IN,1,1,jkff_j_loc},
184 {"K",IN,1,1,jkff_k_loc},
185 {"PRE",IN,1,1,jkff_pre_loc},
186 {"CLR",IN,1,1,jkff_clr_loc},
187 {"CK",IN,1,1,jkff_ck_loc}},
188 {{-17,15,RJ},{17,15,LJ},{17,15,LJ},{-17,15,RJ}},
189 {1},
190
191 {"Dsetup","Dhold","Dck_q",0},
192
193 JKFF_Make,
194 JKFF_WriteCellDef,
195 Generic_Init,
196 Generic_Delete,
197 Generic_GetExtents,
198 Generic_HitDistance,
199 JKFF_Draw,
200 Generic_Move,
201 JKFF_Copy,
202 Err_AddInput,
203 Err_AddOutput,
204 Err_AddInOut,
205 JKFF_Rotate,
206 Err_RemovePort,
207 Err_ChangePin,
208 Nop_SimInitFunc,
209 Nop_SimHitFunc,
210 JKFF_PSWrite,
211 JKFF_EditProps,
212 JKFF_VerSave,
213 JKFF_SetProp,
214 0,
215 JKFF_wireSnap
216 };
217
218 /*****************************************************************************
219 *
220 * Make the GGateInfo structure reflect a normal flip-flop
221 *
222 *****************************************************************************/
JKFF_normal_gateinfo()223 static void JKFF_normal_gateinfo()
224 {
225 gate_jkff_info.Pad[JKFF_Q].Loc = jkff_out_loc;
226 gate_jkff_info.Pad[JKFF_NQ].Loc = jkff_nout_loc;
227 gate_jkff_info.Pad[JKFF_J].Loc = jkff_j_loc;
228 gate_jkff_info.Pad[JKFF_K].Loc = jkff_k_loc;
229 }
230
231 /*****************************************************************************
232 *
233 * Make the GGateInfo structure reflect a mirror flip-flop
234 *
235 *****************************************************************************/
JKFF_reverse_gateinfo()236 static void JKFF_reverse_gateinfo()
237 {
238 gate_jkff_info.Pad[JKFF_Q].Loc = rjkff_out_loc;
239 gate_jkff_info.Pad[JKFF_NQ].Loc = rjkff_nout_loc;
240 gate_jkff_info.Pad[JKFF_J].Loc = rjkff_j_loc;
241 gate_jkff_info.Pad[JKFF_K].Loc = rjkff_k_loc;
242 }
243
JKFF_Make(EditState ** es,GModuleDef * env,int GType,int x,int y,int r,const char * Name,int noWires,const char ** options,int nOptions)244 static GCElement *JKFF_Make(EditState **es,GModuleDef *env,int GType,
245 int x,int y,int r,const char *Name,int noWires,
246 const char **options,int nOptions)
247 {
248 GCElement *g;
249 const char *revOpt;
250 int isMirror = 0;
251
252 revOpt = seekOption("-reverse",options,nOptions);
253 if (revOpt && *revOpt == '1')
254 isMirror = 1;
255
256 if (isMirror)
257 JKFF_reverse_gateinfo();
258
259 g = Generic_Make(es,env,GType,x,y,r,Name,noWires,options,nOptions);
260 ob_touch(g);
261 g->u.ff.mirror = isMirror;
262
263 if (isMirror)
264 JKFF_normal_gateinfo();
265
266 return g;
267 }
268
JKFF_Draw(GCElement * g,int md)269 static void JKFF_Draw(GCElement *g,int md)
270 {
271 int x = g->xpos;
272 int y = g->ypos;
273 GGateInfo *gi = g->typeinfo;
274 int idx = g->orient;
275 int selected = g->selected;
276
277 if (selected) idx += 4;
278
279 if (g->u.ff.mirror)
280 Icon_draw(TkGate.D,TkGate.W,TkGate.instGC,ctow_x(x),ctow_y(y),gi->altIcon[idx]);
281 else
282 Icon_draw(TkGate.D,TkGate.W,TkGate.instGC,ctow_x(x),ctow_y(y),gi->icon[idx]);
283
284 gate_drawWires(g,md);
285
286 if (g->ename && g->show_name)
287 gate_drawgatename(g,g->ename);
288 }
289
JKFF_EditProps(GCElement * g,int isLoadDialog)290 static int JKFF_EditProps(GCElement *g,int isLoadDialog)
291 {
292 Tcl_Interp *tcl = TkGate.tcl;
293
294 Generic_EditProps(g,isLoadDialog);
295 if (isLoadDialog) {
296 DoTcl("set ::edgat_ffmirror %d",g->u.ff.mirror);
297 } else {
298 const char *p;
299 int mirror = g->u.ff.mirror;
300
301 if ((p = Tcl_GetVar(tcl,"edgat_ffmirror",TCL_GLOBAL_ONLY)))
302 sscanf(p,"%d",&mirror);
303
304 if (g->u.ff.mirror != mirror) {
305 int p;
306
307 g->u.ff.mirror = mirror;
308
309 if (mirror)
310 JKFF_reverse_gateinfo();
311
312 for (p = 0;p < REV_PADS;p++) {
313 GPadLoc *pd = &g->typeinfo->Pad[p].Loc[g->orient];
314
315 wire_rePort(g->wires[p],g->xpos+pd->x2,g->ypos+pd->y2,pd->dir);
316 }
317
318 if (mirror)
319 JKFF_normal_gateinfo();
320 }
321
322 ob_touch(g);
323 }
324
325 return 0;
326 }
327
JKFF_Rotate(GCElement * g,int centX,int centY,int rdir)328 static void JKFF_Rotate(GCElement *g, int centX, int centY,int rdir)
329 {
330 if (g->u.ff.mirror)
331 JKFF_reverse_gateinfo();
332
333 Generic_Rotate(g,centX,centY,rdir);
334
335 if (g->u.ff.mirror)
336 JKFF_normal_gateinfo();
337 }
338
339
JKFF_VerSave(FILE * f,GCElement * g)340 static void JKFF_VerSave(FILE *f,GCElement *g)
341 {
342 VerilogBasicGateCall(f,g);
343 VerilogBasicGateParmList(f,g);
344 VerilogBasicGateComment(f,g,1);
345 fprintf(f," /mi:%d",g->u.ff.mirror);
346 fprintf(f,"\n");
347 }
348
JKFF_Copy(GModuleDef * M,GCElement * g,int x,int y,unsigned flags)349 static GCElement *JKFF_Copy(GModuleDef *M,GCElement *g,int x,int y,unsigned flags)
350 {
351 GCElement *ng;
352
353 if (g->u.ff.mirror)
354 JKFF_reverse_gateinfo();
355
356 ng = Generic_Copy(M,g,x,y,flags);
357 ob_touch(ng);
358 ng->u.ff.mirror = g->u.ff.mirror;
359
360 if (g->u.ff.mirror)
361 JKFF_normal_gateinfo();
362
363 return ng;
364 }
365
JKFF_SetProp(GCElement * g,const char * prop,const void * value)366 static void JKFF_SetProp(GCElement *g,const char *prop,const void *value)
367 {
368 int i;
369
370 if (strcmp(prop,"/mi") == 0) g->u.ff.mirror = *((int*)value);
371
372 if (g->u.ff.mirror) {
373 for (i = 0;i < REV_PADS;i++) {
374 if (g->wires[i])
375 g->wires[i]->orient = (g->wires[i]->orient + 2) % 4;
376 }
377 }
378 }
379
JKFF_PSWrite(GPrint * gp,GModLayout * mli,GCElement * g)380 static void JKFF_PSWrite(GPrint *gp,GModLayout *mli,GCElement *g)
381 {
382 Generic_PSLabels(gp,g);
383
384 fprintf(gp->p_f,"%s %d %d %d %s\n",
385 g->u.ff.mirror ? "true" : "false",
386 g->xpos,g->ypos,-g->orient*90,
387 g->typeinfo->psprint);
388 }
389
JKFF_wireSnap(GCElement * g,GWire * w,int * mod,int retry)390 static GWireNode *JKFF_wireSnap(GCElement *g,GWire *w,int *mod,int retry)
391 {
392 int p,n;
393
394 if (posongate(w,w->gate,&p,&n) == 0) {
395 GPadLoc *pd;
396
397 if (g->u.ff.mirror)
398 JKFF_reverse_gateinfo();
399
400 pd = &g->typeinfo->Pad[p].Loc[g->orient];
401
402 if (g->u.ff.mirror)
403 JKFF_normal_gateinfo();
404
405
406 *mod = wire_force(w,pd->dir,retry);
407 }
408 return w->nodes;
409 }
410
411 /*****************************************************************************
412 *
413 * Generate primitive cell definition for flip-flops.
414 *
415 * Parameters:
416 * f File to write cell to.
417 * name Name of cell to write.
418 *
419 *****************************************************************************/
JKFF_WriteCellDef(FILE * f,GCellSpec * gcs)420 static void JKFF_WriteCellDef(FILE *f,GCellSpec *gcs)
421 {
422 int numBit = gcs->gc_numBits;
423 const char *invSpec = gcs->gc_invSpec;
424 int invQ = 0, invNQ = 1;
425 PrimParm primParm;
426
427 if (*invSpec) {
428 if (*invSpec == 'N')
429 invQ = 1;
430 if (!invSpec[1] || invSpec[1] == 'N')
431 invNQ = 0;
432 }
433
434 PrimParm_init(&primParm);
435 PrimParm_rangeSet(&primParm,"JK_RANGE",numBit);
436 PrimParm_intSet(&primParm,"JK_BITS",numBit);
437 PrimParm_invSet(&primParm,"invQ",invQ);
438 PrimParm_invSet(&primParm,"invNQ",invNQ);
439 Primitive_write(f,"jkff",gcs,&primParm);
440 }
441
init_jkff()442 void init_jkff()
443 {
444 Pixmap P;
445
446 P = Pixmap_registerFromFile("jkff","jkff.b");
447 gateinfo_iconInit(&gate_jkff_info,P,jkff_iconDims,jkff_iconBoldOffset);
448
449 P = Pixmap_registerFromFile("rjkff","rjkff.b");
450 gateinfo_altIconInit(&gate_jkff_info,P,jkff_iconDims,jkff_iconBoldOffset);
451
452 RegisterGate(&gate_jkff_info);
453 }
454