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 Sat Feb 21 20:02:58 2009
19 ****************************************************************************/
20 #include "tkgate.h"
21 #include "switch.h"
22
23 #define SWITCH_OUT 0
24
25 static iconDimensions upswitch_iconDims[] = {
26 {0, 0, 34, 26, 17, 13},
27 {0, 0, 34, 26, 17, 13},
28 {0, 0, 34, 26, 17, 13},
29 {0, 0, 34, 26, 17, 13},
30 };
31
32 static iconDimensions dnswitch_iconDims[] = {
33 {35, 0, 34, 26, 17, 13},
34 {35, 0, 34, 26, 17, 13},
35 {35, 0, 34, 26, 17, 13},
36 {35, 0, 34, 26, 17, 13},
37 };
38 static int switch_iconBoldOffset = 27;
39
40 GCElement *Switch_Make(EditState **,GModuleDef *,int,int,int,int,const char *,int,const char**,int);
41 void Switch_Draw(GCElement *g,int md);
42 int Switch_EditProps(GCElement *g,int isLoadDialog);
43 int Switch_SimHitFunc(EditState*,GCElement*);
44 void Switch_SimInitFunc(EditState *es,GCElement *g,const char *path);
45
46 GPadLoc switch_out_loc[] = {
47 {17,0,17,0,D_RIGHT},
48 {0,-14,0,-14,D_UP},
49 {-18,0,-18,0,D_LEFT},
50 {0,13,0,13,D_DOWN}};
51
52 static char *psSwitch[] = {
53 "%",
54 "% A Switch",
55 "/switchgate {",
56 " startnorotgate",
57 " % Outer Box",
58 " 4 setlinewidth",
59 " -18 -12 moveto",
60 " 15 -12 lineto",
61 " 15 12 lineto",
62 " 1 setlinewidth",
63 " -18 12 lineto",
64 " closepath",
65 " stroke",
66 " gsave % Inner Box",
67 " -5 -9 moveto",
68 " -5 10 lineto",
69 " -16 10 lineto",
70 " -16 -9 lineto",
71 " closepath",
72 " stroke",
73 " 0.8 setgray",
74 " -5 -9 moveto",
75 " -5 10 lineto",
76 " -16 10 lineto",
77 " -16 -9 lineto",
78 " closepath",
79 " fill",
80 " grestore",
81
82 " -8 0 moveto % Knives",
83 " -8 7 lineto",
84 " -13 7 lineto",
85 " -13 0 lineto",
86 " stroke",
87
88 " -10.5 7 moveto % Handle",
89 " -10.5 7.5 lineto",
90 " stroke",
91 " -10.5 8 1 0 360 arc",
92 " closepath",
93 " fill",
94
95 " -7 -1 moveto % Hinges",
96 " -7 1 lineto",
97 " -9 -1 moveto",
98 " -9 1 lineto",
99 " -12 -1 moveto",
100 " -12 1 lineto",
101 " -14 -1 moveto",
102 " -14 1 lineto",
103 " stroke",
104 " -7 5 1 0 360 arc % Clips",
105 " closepath fill",
106 " newpath",
107 " -9 5 1 0 360 arc",
108 " closepath fill",
109 " newpath",
110 " -12 5 1 0 360 arc",
111 " closepath fill",
112 " newpath",
113 " -14 5 1 0 360 arc",
114 " closepath fill",
115 " newpath",
116 " -7 -5 1 0 360 arc",
117 " closepath fill",
118 " newpath",
119 " -9 -5 1 0 360 arc",
120 " closepath fill",
121 " newpath",
122 " -12 -5 1 0 360 arc",
123 " closepath fill",
124 " newpath",
125 " -14 -5 1 0 360 arc",
126 " closepath fill",
127 " 8 rfont",
128 " -3 4 moveto",
129 " (on) show",
130 " -3 -7 moveto",
131 " (off) show",
132 " grestore",
133 "} bind def",
134 0
135 };
136
137 GGateInfo gate_switch_info = {
138 GC_SWITCH,
139 "SWITCH",
140 "switch",0x0,
141 "switchgate",psSwitch,
142 -1,-1,
143
144 {{"s", {"gm.io",0}, {"gm.io.switch",0,0,100}, "gat_make SWITCH"},
145 {0}},
146
147 upswitch_iconDims,
148
149 1,{{"Z",OUT,1,1,switch_out_loc}},
150 {{0,-17,CT},{17,0,LJ},{0,-17,CT},{17,0,LJ}},
151 {1,1,1,0,0},
152
153 {0},
154
155 Switch_Make,
156 Nop_WriteCellDef,
157 Generic_Init,
158 Generic_Delete,
159 Generic_GetExtents,
160 Generic_HitDistance,
161 Switch_Draw,
162 Generic_Move,
163 SwitchDip_Copy,
164 Err_AddInput,
165 Err_AddOutput,
166 Err_AddInOut,
167 Generic_Rotate,
168 Err_RemovePort,
169 Err_ChangePin,
170 Switch_SimInitFunc,
171 Switch_SimHitFunc,
172 Generic_PSWrite,
173 Switch_EditProps,
174 SwitchDip_VerSave,
175 SwitchDip_SetProp,
176 };
177
Switch_Make(EditState ** es,GModuleDef * env,int GType,int x,int y,int r,const char * Name,int noWires,const char ** options,int nOptions)178 GCElement *Switch_Make(EditState **es,GModuleDef *env,int GType,
179 int x,int y,int r,const char *Name,int noWires,const char **options,int nOptions)
180 {
181 GCElement *g = Generic_Make(es,env,GType,x,y,r,Name,noWires,options,nOptions);
182
183 ob_touch(g);
184 g->u.sw.perm_dipval = 0;
185 g->u.sw.dipval = 0;
186 g->u.sw.showNet = TkGate.circuit->showSwitchNets;
187
188 return g;
189 }
190
SwitchDip_getCompositeName(GCElement * g,char * compositeName)191 void SwitchDip_getCompositeName(GCElement *g,char *compositeName)
192 {
193 GWire *w = g->wires[0];
194 char *netName = w->net->n_signame ? w->net->n_signame : "";
195
196 if (g->u.sw.showNet) {
197 if (g->ename && g->show_name)
198 sprintf(compositeName,"%s[%s]",g->ename,netName);
199 else
200 sprintf(compositeName,"[%s]",netName);
201 } else {
202 if (g->ename && g->show_name)
203 sprintf(compositeName,"%s",g->ename);
204 else
205 *compositeName = 0;
206 }
207 }
208
Switch_Draw(GCElement * g,int md)209 void Switch_Draw(GCElement *g,int md)
210 {
211 Icon *C;
212 int x,y;
213 int idx = 0;
214 char compositeName[STRMAX];
215
216 if (g->u.sw.dipval) idx++;
217 if (g->selected) idx += 4;
218
219 C = g->typeinfo->icon[idx];
220 x = g->xpos;
221 y = g->ypos;
222
223 Icon_draw(TkGate.D,TkGate.W,TkGate.instGC,ctow_x(x),ctow_y(y),C);
224
225
226 gate_drawWires(g,md);
227
228 SwitchDip_getCompositeName(g, compositeName);
229 if (*compositeName)
230 gate_drawgatename(g,compositeName);
231 }
232
SwitchDip_Copy(GModuleDef * M,GCElement * g,int x,int y,unsigned flags)233 GCElement *SwitchDip_Copy(GModuleDef *M,GCElement *g,int x,int y,unsigned flags)
234 {
235 GCElement *ng = Generic_Copy(M,g,x,y,flags);
236
237 ob_touch(ng);
238 ng->u.sw.perm_dipval = g->u.sw.perm_dipval;
239 ng->u.sw.dipval = g->u.sw.dipval;
240 ng->u.sw.showNet = g->u.sw.showNet;
241
242 return ng;
243 }
244
Switch_EditProps(GCElement * g,int isLoadDialog)245 int Switch_EditProps(GCElement *g,int isLoadDialog)
246 {
247 Tcl_Interp *tcl = TkGate.tcl;
248
249 Generic_EditProps(g,isLoadDialog);
250 if (isLoadDialog) {
251 DoTcl("set ::edgat_switch %d",g->u.sw.perm_dipval);
252 DoTcl("set ::edgat_shownet %d",g->u.sw.showNet);
253 } else {
254 const char *p;
255
256 ob_touch(g);
257
258 if ((p = Tcl_GetVar(tcl,"edgat_switch",TCL_GLOBAL_ONLY)))
259 sscanf(p,"%d",&g->u.sw.perm_dipval);
260 g->u.sw.dipval = g->u.sw.perm_dipval;
261
262 if ((p = Tcl_GetVar(tcl,"edgat_shownet",TCL_GLOBAL_ONLY)))
263 sscanf(p,"%d",&g->u.sw.showNet);
264 }
265 return 0;
266 }
267
SwitchDip_VerSave(FILE * f,GCElement * g)268 void SwitchDip_VerSave(FILE *f,GCElement *g)
269 {
270 fprintf(f," //: %s %s (%s)"
271 ,g->typeinfo->name
272 ,g->ename
273 ,g->wires[0]->net->n_signame);
274 VerilogBasicGateComment(f,g,0);
275 fprintf(f," /st:%d /dn:%d",g->u.sw.dipval,g->u.sw.showNet);
276 fprintf(f,"\n");
277 }
278
Switch_SimHitFunc(EditState * es,GCElement * g)279 int Switch_SimHitFunc(EditState *es,GCElement *g)
280 {
281 GSimSwitch *ss = SHash_find(es->smod->switches,g->ename);
282 gate_draw(g,0);
283 *ss->state = g->u.sw.dipval = !g->u.sw.dipval;
284 gate_draw(g,0);
285
286 DoTcl("tkg_simNetSet %s 1'b%d",ss->name,g->u.sw.dipval);
287 return 1;
288 }
289
Switch_SimInitFunc(EditState * es,GCElement * g,const char * path)290 void Switch_SimInitFunc(EditState *es,GCElement *g,const char *path)
291 {
292 g->u.sw.dipval = g->u.sw.perm_dipval;
293 }
294
SwitchDip_SetProp(GCElement * g,const char * prop,const void * value)295 void SwitchDip_SetProp(GCElement *g,const char *prop,const void *value)
296 {
297 if (strcmp(prop,"/st") == 0)
298 g->u.sw.dipval = g->u.sw.perm_dipval = *((int*)value);
299 else if (strcmp(prop,"/dn") == 0)
300 g->u.sw.showNet = *((int*)value);
301 }
302
init_switch()303 void init_switch()
304 {
305 Pixmap P;
306 Icon *upId,*upBId,*dnId,*dnBId;
307 GGateInfo *gi = &gate_switch_info;
308
309 P = Pixmap_registerFromFile("switch","switch.b");
310
311 upId = new_IconID(P,upswitch_iconDims,0);
312 upBId = new_IconID(P,upswitch_iconDims,switch_iconBoldOffset);
313 dnId = new_IconID(P,dnswitch_iconDims,0);
314 dnBId = new_IconID(P,dnswitch_iconDims,switch_iconBoldOffset);
315
316 gi->icon[0] = dnId;
317 gi->icon[1] = upId;
318
319 gi->icon[2] = dnId;
320 gi->icon[3] = upId;
321
322 gi->icon[4] = dnBId;
323 gi->icon[5] = upBId;
324
325 gi->icon[6] = dnId;
326 gi->icon[7] = upId;
327
328 RegisterGate(&gate_switch_info);
329 }
330