2 * Copyright (c) 2000 Stephen G. Tell <steve@telltronics.org>
4 * This source code is free software; you can redistribute it
5 * and/or modify it in source code form under the terms of the GNU
6 * General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 #ident "$Id: vpi_mcd.cc,v 1.13 2006/08/03 05:05:31 steve Exp $"
23 # include "vpi_priv.h"
30 extern FILE* vpi_trace
;
33 * This table keeps track of the MCD files. Note that there may be
34 * only 31 such files, and mcd bit0 (32'h00_00_00_01) is the special
35 * standard output file, which may be replicated to a logfile
36 * depending on flags to the command line.
40 * MCD/FD manipulation macros
42 #define IS_MCD(mcd) !((mcd)>>31&1)
43 #define FD_IDX(fd) ((fd)&~(1U<<31))
50 static struct mcd_entry mcd_table
[31];
51 static struct mcd_entry fd_table
[FD_MAX
];
55 /* Initialize mcd portion of vpi. Must be called before
56 * any vpi_mcd routines can be used.
58 void vpi_mcd_init(FILE *log
)
60 mcd_table
[0].fp
= stdout
;
61 mcd_table
[0].filename
= "stdout";
63 fd_table
[0].fp
= stdin
;
64 fd_table
[0].filename
= "stdin";
65 fd_table
[1].fp
= stdout
;
66 fd_table
[1].filename
= "stdout";
67 fd_table
[2].fp
= stderr
;
68 fd_table
[2].filename
= "stderr";
74 * close one or more channels. we silently refuse to close the preopened ones.
76 extern "C" PLI_UINT32
vpi_mcd_close(PLI_UINT32 mcd
)
81 for(int i
= 1; i
< 31; i
++) {
82 if(((mcd
>>i
) & 1) && mcd_table
[i
].fp
) {
83 if(fclose(mcd_table
[i
].fp
)) rc
|= 1<<i
;
84 free(mcd_table
[i
].filename
);
85 mcd_table
[i
].fp
= NULL
;
86 mcd_table
[i
].filename
= NULL
;
92 unsigned idx
= FD_IDX(mcd
);
93 if (idx
> 2 && idx
< FD_MAX
&& fd_table
[idx
].fp
) {
94 rc
= fclose(fd_table
[idx
].fp
);
95 free(fd_table
[idx
].filename
);
96 fd_table
[idx
].fp
= NULL
;
97 fd_table
[idx
].filename
= NULL
;
103 extern "C" char *vpi_mcd_name(PLI_UINT32 mcd
)
106 for(int i
= 0; i
< 31; i
++) {
108 return mcd_table
[i
].filename
;
111 unsigned idx
= FD_IDX(mcd
);
113 return fd_table
[idx
].filename
;
118 extern "C" PLI_UINT32
vpi_mcd_open(char *name
)
122 for(i
= 0; i
< 31; i
++) {
123 if(mcd_table
[i
].filename
== NULL
)
126 return 0; /* too many open mcd's */
129 mcd_table
[i
].fp
= fopen(name
, "w");
130 if(mcd_table
[i
].fp
== NULL
)
132 mcd_table
[i
].filename
= strdup(name
);
135 fprintf(vpi_trace
, "vpi_mcd_open(%s) --> 0x%08x\n",
143 vpi_mcd_vprintf(PLI_UINT32 mcd
, const char*fmt
, va_list ap
)
148 if (!IS_MCD(mcd
)) return 0;
151 fprintf(vpi_trace
, "vpi_mcd_vprintf(0x%08x, %s, ...);\n",
155 rc
= vsnprintf(buffer
, sizeof buffer
, fmt
, ap
);
157 for(int i
= 0; i
< 31; i
++) {
159 if(mcd_table
[i
].fp
) {
161 if (i
== 0 && logfile
)
162 fputs(buffer
, logfile
);
163 fputs(buffer
, mcd_table
[i
].fp
);
173 extern "C" PLI_INT32
vpi_mcd_printf(PLI_UINT32 mcd
, const char *fmt
, ...)
177 int r
= vpi_mcd_vprintf(mcd
,fmt
,ap
);
182 extern "C" PLI_INT32
vpi_mcd_flush(PLI_UINT32 mcd
)
187 for(int i
= 0; i
< 31; i
++) {
189 if (i
== 0 && logfile
) fflush(logfile
);
190 if (fflush(mcd_table
[i
].fp
)) rc
|= 1<<i
;
194 unsigned idx
= FD_IDX(mcd
);
195 if (idx
< FD_MAX
) rc
= fflush(fd_table
[idx
].fp
);
205 * The vpi_fopen function opens a file with the given path, and
206 * returns a file descriptor that includes bit 31 set. This is to
207 * differentiate the fd from a mcd discriptor. Note that these
208 * descriptors are distinct from the mcd descriptors, so uses a
209 * different fd table.
211 extern "C" PLI_INT32
vpi_fopen(const char*name
, const char*mode
)
214 for(i
= 0; i
< FD_MAX
; i
++) {
215 if(fd_table
[i
].filename
== NULL
)
218 return 0; /* too many open fd's */
221 fd_table
[i
].fp
= fopen(name
, mode
);
222 if(fd_table
[i
].fp
== NULL
)
224 fd_table
[i
].filename
= strdup(name
);
228 extern "C" FILE *vpi_get_file(PLI_INT32 fd
)
230 // Only deal with FD's
231 if (IS_MCD(fd
)) return NULL
;
233 // Only know about FD_MAX indicies
234 if (FD_IDX(fd
) >= FD_MAX
) return NULL
;
236 return fd_table
[FD_IDX(fd
)].fp
;
240 * $Log: vpi_mcd.cc,v $
241 * Revision 1.13 2006/08/03 05:05:31 steve
242 * Better comments for vpi_fopen function.
244 * Revision 1.12 2004/10/04 01:10:59 steve
245 * Clean up spurious trailing white space.
247 * Revision 1.11 2003/07/21 01:20:59 steve
248 * vpi_mcd_vprintf can only scan the va_list once.
250 * Revision 1.10 2003/05/23 04:04:02 steve
251 * Add vpi_fopen and vpi_get_file.
253 * Revision 1.9 2003/05/15 16:51:09 steve
254 * Arrange for mcd id=00_00_00_01 to go to stdout
255 * as well as a user specified log file, set log
256 * file to buffer lines.
258 * Add vpi_flush function, and clear up some cunfused
259 * return codes from other vpi functions.
261 * Adjust $display and vcd/lxt messages to use the
262 * standard output/log file.
264 * Revision 1.8 2002/08/12 01:35:09 steve
265 * conditional ident string using autoconfig.
267 * Revision 1.7 2002/08/11 23:47:05 steve
268 * Add missing Log and Ident strings.