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