Merge branch 'master' of steve-icarus@icarus.com:git/verilog
[iverilog.git] / vpi / sys_time.c
blob2a178580595e6b0269f885338adcd66ccf6cce40
1 /*
2 * Copyright (c) 2000 Stephen Williams (steve@icarus.com)
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)
8 * any later version.
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
19 #ifdef HAVE_CVS_IDENT
20 #ident "$Id: sys_time.c,v 1.12 2007/03/14 04:05:51 steve Exp $"
21 #endif
23 # include "vpi_config.h"
25 # include "vpi_user.h"
26 # include <string.h>
27 # include <math.h>
28 # include <assert.h>
30 static vpiHandle module_of_function(vpiHandle obj)
32 while (vpi_get(vpiType, obj) != vpiModule) {
33 obj = vpi_handle(vpiScope, obj);
34 assert(obj);
37 return obj;
40 static PLI_INT32 sys_time_sizetf(PLI_BYTE8*x)
42 return 64;
45 static PLI_INT32 sys_stime_sizetf(PLI_BYTE8*x)
47 return 32;
50 static PLI_INT32 sys_time_calltf(PLI_BYTE8*name)
52 s_vpi_value val;
53 s_vpi_time now;
54 vpiHandle call_handle;
55 vpiHandle mod;
56 int units, prec;
57 long scale;
58 long frac;
60 call_handle = vpi_handle(vpiSysTfCall, 0);
61 assert(call_handle);
63 mod = module_of_function(call_handle);
65 now.type = vpiSimTime;
66 vpi_get_time(0, &now);
68 /* All the variants but $simtime return the time in units of
69 the local scope. The $simtime function returns the
70 simulation time. */
71 if (strcmp(name, "$simtime") == 0)
72 units = vpi_get(vpiTimePrecision, 0);
73 else
74 units = vpi_get(vpiTimeUnit, mod);
76 prec = vpi_get(vpiTimePrecision, 0);
77 scale = 1;
78 while (units > prec) {
79 scale *= 10;
80 units -= 1;
83 assert(8*sizeof(long long) >= 64);
84 { long long tmp_now = ((long long)now.high) << 32;
85 tmp_now += (long long)now.low;
86 frac = tmp_now % (long long)scale;
87 tmp_now /= (long long)scale;
89 /* Round to the nearest integer, which may be up. */
90 if ((scale > 1) && (frac >= scale/2))
91 tmp_now += 1;
93 now.low = tmp_now & 0xffffffff;
94 now.high = tmp_now >> 32LL;
97 val.format = vpiTimeVal;
98 val.value.time = &now;
100 vpi_put_value(call_handle, &val, 0, vpiNoDelay);
102 return 0;
105 static PLI_INT32 sys_realtime_calltf(PLI_BYTE8*name)
107 s_vpi_value val;
108 s_vpi_time now;
109 vpiHandle call_handle;
110 vpiHandle mod;
111 int units, prec;
113 call_handle = vpi_handle(vpiSysTfCall, 0);
114 assert(call_handle);
116 mod = module_of_function(call_handle);
118 now.type = vpiSimTime;
119 vpi_get_time(0, &now);
121 units = vpi_get(vpiTimeUnit, mod);
122 prec = vpi_get(vpiTimePrecision, 0);
124 val.format = vpiRealVal;
125 val.value.real = pow(10.0, prec-units) * now.low;
126 assert(now.high == 0);
128 vpi_put_value(call_handle, &val, 0, vpiNoDelay);
130 return 0;
133 void sys_time_register()
135 s_vpi_systf_data tf_data;
137 tf_data.type = vpiSysFunc;
138 tf_data.tfname = "$time";
139 tf_data.calltf = sys_time_calltf;
140 tf_data.compiletf = 0;
141 tf_data.sizetf = sys_time_sizetf;
142 tf_data.user_data = "$time";
143 vpi_register_systf(&tf_data);
145 tf_data.type = vpiSysFunc;
146 tf_data.tfname = "$realtime";
147 tf_data.calltf = sys_realtime_calltf;
148 tf_data.compiletf = 0;
149 tf_data.sizetf = 0;
150 tf_data.user_data = "$realtime";
151 vpi_register_systf(&tf_data);
153 tf_data.type = vpiSysFunc;
154 tf_data.tfname = "$stime";
155 tf_data.calltf = sys_time_calltf;
156 tf_data.compiletf = 0;
157 tf_data.sizetf = sys_stime_sizetf;
158 tf_data.user_data = "$stime";
159 vpi_register_systf(&tf_data);
161 tf_data.type = vpiSysFunc;
162 tf_data.tfname = "$simtime";
163 tf_data.calltf = sys_time_calltf;
164 tf_data.compiletf = 0;
165 tf_data.sizetf = sys_time_sizetf;
166 tf_data.user_data = "$simtime";
167 vpi_register_systf(&tf_data);
171 * $Log: sys_time.c,v $
172 * Revision 1.12 2007/03/14 04:05:51 steve
173 * VPI tasks take PLI_BYTE* by the standard.
175 * Revision 1.11 2006/10/30 22:45:37 steve
176 * Updates for Cygwin portability (pr1585922)
178 * Revision 1.10 2004/01/21 01:22:53 steve
179 * Give the vip directory its own configure and vpi_config.h
181 * Revision 1.9 2003/06/18 00:54:28 steve
182 * Account for all 64 bits in results of $time.
184 * Revision 1.8 2003/02/07 02:44:25 steve
185 * Properly round inter time values from $time.
187 * Revision 1.7 2003/01/28 04:41:55 steve
188 * Use more precise pow function to scale time by units.
190 * Revision 1.6 2003/01/27 00:14:37 steve
191 * Support in various contexts the $realtime
192 * system task.
194 * Revision 1.5 2002/12/21 00:55:58 steve
195 * The $time system task returns the integer time
196 * scaled to the local units. Change the internal
197 * implementation of vpiSystemTime the $time functions
198 * to properly account for this. Also add $simtime
199 * to get the simulation time.
201 * Revision 1.4 2002/08/12 01:35:05 steve
202 * conditional ident string using autoconfig.
204 * Revision 1.3 2002/01/11 05:20:59 steve
205 * Add the stime system function.
207 * Revision 1.2 2001/07/25 03:10:50 steve
208 * Create a config.h.in file to hold all the config
209 * junk, and support gcc 3.0. (Stephan Boettcher)
211 * Revision 1.1 2000/11/01 03:19:36 steve
212 * Add the general $time system function.