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