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 Sep 26 18:25:03 2009
19 ****************************************************************************/
20 #include <stdlib.h>
21 #include <string.h>
22 #include "tkgate.h"
23
24
25 #define RAM_A 0
26 #define RAM_D 1
27 #define RAM_WE 2
28 #define RAM_OE 3
29 #define RAM_CS 4
30
31 static void Ram_WriteCellDef(FILE *f,GCellSpec *gcs);
32
33 static iconDimensions ram_iconDims[] = {
34 {0, 0, 34, 49, 17, 23},
35 {35, 0, 49, 34, 23, 16},
36 {50, 35, 34, 49, 16, 25},
37 {0, 50, 49, 34, 25, 17},
38 };
39 static int ram_iconBoldOffset = 85;
40
41 GPadLoc ram_A_loc[] = {
42 {-18, 1, -18, 1, D_LEFT},
43 {1, 18, 1, 18, D_DOWN},
44 {18, -1, 18, -1, D_RIGHT},
45 {-1, -18, -1, -18, D_UP}
46 };
47
48 GPadLoc ram_D_loc[] = {
49 {17, -1, 17, -1, D_RIGHT},
50 {-1, -17, -1, -17, D_UP},
51 {-17, 1, -17, 1, D_LEFT},
52 {1, 17, 1, 17, D_DOWN}
53
54 };
55 GPadLoc ram_we_loc[] = {
56 {0, -24, 0, -24, D_UP},
57 {-24, 0, -24, 0, D_LEFT},
58 {0, 24, 0, 24, D_DOWN},
59 {24, 0, 24, 0, D_RIGHT}
60 };
61 GPadLoc ram_cs_loc[] = {
62 {-7, 26, -7, 26, D_DOWN},
63 {26, 7, 26, 7, D_RIGHT},
64 {7, -26, 7, -26, D_UP},
65 {-26, -7, -26, -7, D_LEFT}
66 };
67 GPadLoc ram_oe_loc[] = {
68 {7, 26, 7, 26, D_DOWN},
69 {26, -7, 26, -7, D_RIGHT},
70 {-7, -26, -7, -26, D_UP},
71 {-26, 7, -26, 7, D_LEFT}
72 };
73
74 GCElement *RamRom_Make(EditState **es,GModuleDef *env,int GType,
75 int x,int y,int r,const char *Name,int noWires,const char **options,int nOptions);
76 int RamRom_EditProps(GCElement *g,int isLoadDialog);
77 void RamRom_SetProp(GCElement*,const char*,const void*);
78 int RamRom_SimHitFunc(EditState *es,GCElement *g);
79 void RamRom_VerSave(FILE *f,GCElement *g);
80
81 static char *psRam[] = {
82 "%",
83 "% x y r ram",
84 "%",
85 "/psram {",
86 " startgate",
87 " -17.5 23.5 moveto",
88 " 16.5 23.5 lineto",
89 " 16.5 -25.5 lineto",
90 " -17.5 -25.5 lineto",
91 " closepath stroke",
92 " 8 rfont",
93 " -15 -2 moveto (A) show",
94 " 5 -2 moveto (D) show",
95 " 6 rfont",
96 " (_cs) -11 -23 prshow",
97 " (_oe) 4 -23 prshow",
98 " (_we) -4 16 prshow",
99 " grestore",
100 "} def",
101 0
102 };
103
104 GGateInfo gate_ram_info = {
105 GC_RAM,
106 "RAM",
107 "ram",0x0,
108 "psram",psRam,
109 -1,-1,
110
111 {{"R", {"gm.mem",5}, {"gm.mem.ram",0,"mem",100}, "gat_make RAM"},
112 {0}},
113
114
115 ram_iconDims,
116
117 5,{{"A",IN,8,1,ram_A_loc},
118 {"D",TRI,8,1,ram_D_loc},
119 {"WE",IN,1,1,ram_we_loc},
120 {"OE",IN,1,1,ram_oe_loc},
121 {"CS",IN,1,1,ram_cs_loc}},
122 {{5,-30,LJ},{5,-30,LJ},{5,-30,LJ},{5,-30,LJ}},
123 {1},
124
125 {"Dout","Dread","Dwrite","Daddr_setup","Daddr_hold","Ddata_hold",0},
126
127 RamRom_Make,
128 Ram_WriteCellDef,
129 Generic_Init,
130 Generic_Delete,
131 Generic_GetExtents,
132 Generic_HitDistance,
133 Generic_Draw,
134 Generic_Move,
135 Generic_Copy,
136 Err_AddInput,
137 Err_AddOutput,
138 Err_AddInOut,
139 Generic_Rotate,
140 Err_RemovePort,
141 Err_ChangePin,
142 Nop_SimInitFunc,
143 RamRom_SimHitFunc,
144 Generic_PSWrite,
145 Generic_EditProps,
146 RamRom_VerSave
147 };
148
RamRom_Make(EditState ** es,GModuleDef * env,int GType,int x,int y,int r,const char * Name,int noWires,const char ** options,int nOptions)149 GCElement *RamRom_Make(EditState **es,GModuleDef *env,int GType,
150 int x,int y,int r,const char *Name,int noWires,const char **options,int nOptions)
151 {
152 GCElement *g;
153 const char *DefV;
154
155 if (!(g = Generic_Make(es,env,GType,x,y,r,Name,noWires,options,nOptions)))
156 return NULL;
157
158 DefV = seekOption("-memfile",options,nOptions);
159
160 ob_touch(g);
161
162 if (!DefV)
163 g->u.mem.memfile = 0;
164 else
165 g->u.mem.memfile = ob_strdup(DefV);
166
167 return g;
168 }
169
170
RamRom_EditProps(GCElement * g,int isLoadDialog)171 int RamRom_EditProps(GCElement *g,int isLoadDialog)
172 {
173 Tcl_Interp *tcl = TkGate.tcl;
174
175 Generic_EditProps(g,isLoadDialog);
176 if (isLoadDialog) {
177 DoTcl("set ::edgat_memFile \"%s\"",g->u.mem.memfile ? g->u.mem.memfile : "");
178 } else {
179 const char *p;
180
181 ob_touch(g);
182 if (g->u.mem.memfile) ob_free(g->u.mem.memfile);
183 g->u.mem.memfile = 0;
184
185 if ((p = Tcl_GetVar(tcl,"edgat_memFile",TCL_GLOBAL_ONLY))) {
186 if (strspn(p," ") != strlen(p))
187 g->u.mem.memfile = ob_strdup(p);
188 }
189 }
190
191 return 0;
192 }
193
RamRom_SetProp(GCElement * g,const char * name,const void * value)194 void RamRom_SetProp(GCElement *g,const char *name,const void *value)
195 {
196 if (strcmp(name,"/mem") == 0) {
197 ob_touch(g);
198 if (g->u.mem.memfile) ob_free(g->u.mem.memfile);
199 g->u.mem.memfile = ob_strdup(value);
200 }
201 }
202
RamRom_SimHitFunc(EditState * es,GCElement * g)203 int RamRom_SimHitFunc(EditState *es,GCElement *g)
204 {
205 EditState_selectGate(es,TkGate.ed->tx,TkGate.ed->ty);
206 return 1;
207 }
208
RamRom_VerSave(FILE * f,GCElement * g)209 void RamRom_VerSave(FILE *f,GCElement *g)
210 {
211 VerilogBasicGateCall(f,g);
212 VerilogBasicGateParmList(f,g);
213 VerilogBasicGateComment(f,g,1);
214 if (g->u.mem.memfile)
215 fprintf(f," /mem:\"%s\"",g->u.mem.memfile);
216 fprintf(f,"\n");
217 }
218
219 /*****************************************************************************
220 *
221 * Generate primitive cell definition for rams.
222 *
223 * Parameters:
224 * f File to write cell to.
225 * name Name of cell to write.
226 *
227 * Note on RAMS with invert on D port: Placing an inverter on the D port of
228 * a RAM causes the RAM data to be stored inverted, but subsequent reads will
229 * reinvert on output resulting in the originally stored number. The only way
230 * to see the difference between a RAM and an NRAM is when loading or storing
231 * a memory contents file.
232 *
233 *****************************************************************************/
Ram_WriteCellDef(FILE * f,GCellSpec * gcs)234 static void Ram_WriteCellDef(FILE *f,GCellSpec *gcs)
235 {
236 /** @TODO to remove */
237 /* GGateInfo *gi = gcs->gc_info; */
238 int AnumBits = gcs->gc_multiPad; /* Hack for ROM/RAM gates */
239 int DnumBits = gcs->gc_numBits;
240 /** @TODO to remove */
241 /* const char *invSpec = gcs->gc_invSpec; */
242 PrimParm primParm;
243
244 PrimParm_init(&primParm);
245 PrimParm_rangeSet(&primParm,"A_RANGE",AnumBits);
246 PrimParm_rangeSet(&primParm,"D_RANGE",DnumBits);
247 PrimParm_set(&primParm,"MEM_RANGE","[0:%u]",(1 << AnumBits) - 1);
248 PrimParm_intSet(&primParm,"D_BITS",DnumBits);
249 Primitive_write(f,"ram",gcs,&primParm);
250 }
251
init_ram()252 void init_ram()
253 {
254 Pixmap P;
255
256 P = Pixmap_registerFromFile("ram","ram.b");
257 gateinfo_iconInit(&gate_ram_info,P,ram_iconDims,ram_iconBoldOffset);
258 RegisterGate(&gate_ram_info);
259 }
260
261