Add support for $timeformat.
This commit is contained in:
parent
12c574d5c9
commit
f1ab9e63fa
16
README.txt
16
README.txt
|
|
@ -359,6 +359,22 @@ language that are defined.
|
||||||
It is said that some commercial compilers do allow macro
|
It is said that some commercial compilers do allow macro
|
||||||
definitions to span library modules. That's just plain weird.
|
definitions to span library modules. That's just plain weird.
|
||||||
|
|
||||||
|
Width in %t Time Formats
|
||||||
|
|
||||||
|
Standard Verilog does not allow width fields in the %t formats
|
||||||
|
of display strings. For example, this is illegal:
|
||||||
|
|
||||||
|
$display("Time is %0t", %time);
|
||||||
|
|
||||||
|
Standard Verilog instead relies on the $timeformat to
|
||||||
|
completely specify the format.
|
||||||
|
|
||||||
|
Icarus Verilog allows the programmer to specify the field
|
||||||
|
with. The "%t" format in Icarus Verilog works exactly as it
|
||||||
|
does in standard Verilog. However, if the programmer chooses
|
||||||
|
to specify a minimum width, i.e. "%5t" Then for that display
|
||||||
|
Icarus Verilog will override the $timeformat minimum width and
|
||||||
|
use the explicit minimum width.
|
||||||
|
|
||||||
6.0 CREDITS
|
6.0 CREDITS
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT) && !defined(macintosh)
|
#if !defined(WINNT) && !defined(macintosh)
|
||||||
#ident "$Id: sys_display.c,v 1.37 2002/05/24 19:05:30 steve Exp $"
|
#ident "$Id: sys_display.c,v 1.38 2002/05/31 04:26:54 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
|
|
@ -28,6 +28,15 @@
|
||||||
# include <ctype.h>
|
# include <ctype.h>
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
|
|
||||||
|
struct timeformat_info_s {
|
||||||
|
int units;
|
||||||
|
unsigned prec;
|
||||||
|
char*suff;
|
||||||
|
unsigned width;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct timeformat_info_s timeformat_info = { 0, 0, 0, 20 };
|
||||||
|
|
||||||
struct strobe_cb_info {
|
struct strobe_cb_info {
|
||||||
char*name;
|
char*name;
|
||||||
int default_format;
|
int default_format;
|
||||||
|
|
@ -97,6 +106,81 @@ static void array_from_iterator(struct strobe_cb_info*info, vpiHandle argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void format_time(unsigned mcd, int fsize, const char*value)
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
const char*cp;
|
||||||
|
char*bp;
|
||||||
|
unsigned len;
|
||||||
|
int cnt;
|
||||||
|
|
||||||
|
/* This is the time precision for the simulation. */
|
||||||
|
int prec = vpi_get(vpiTimePrecision, 0);
|
||||||
|
|
||||||
|
if (fsize < 0)
|
||||||
|
fsize = timeformat_info.width;
|
||||||
|
|
||||||
|
bp = buf + sizeof buf;
|
||||||
|
cp = value + strlen(value);
|
||||||
|
|
||||||
|
*--bp = 0;
|
||||||
|
|
||||||
|
/* Draw the suffix into the buffer. */
|
||||||
|
bp -= strlen(timeformat_info.suff);
|
||||||
|
strcpy(bp, timeformat_info.suff);
|
||||||
|
|
||||||
|
/* Draw 0s to pad out the precision to the requested count. */
|
||||||
|
cnt = timeformat_info.units - prec;
|
||||||
|
while (cnt < timeformat_info.prec) {
|
||||||
|
*--bp = '0';
|
||||||
|
cnt += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Chop excess precision. */
|
||||||
|
while (cnt > timeformat_info.prec) {
|
||||||
|
if (cp > value)
|
||||||
|
cp -= 1;
|
||||||
|
cnt -= 1;
|
||||||
|
prec += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw the digits of the time that are to the right of the
|
||||||
|
decimal point. Pad to the right with zeros if needed, to
|
||||||
|
get to the decimal point. */
|
||||||
|
if (prec < timeformat_info.units) {
|
||||||
|
while (prec < timeformat_info.units) {
|
||||||
|
char val;
|
||||||
|
if (cp == value)
|
||||||
|
val = '0';
|
||||||
|
else
|
||||||
|
val = *--cp;
|
||||||
|
|
||||||
|
*--bp = val;
|
||||||
|
prec += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*--bp = '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put the remaining characters to the left of the decimal
|
||||||
|
point. */
|
||||||
|
while (cp > value) {
|
||||||
|
*--bp = *--cp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*bp == '.')
|
||||||
|
*--bp = '0';
|
||||||
|
|
||||||
|
/* Pad the string on the left to the requested minimum
|
||||||
|
width. Pad with spaces. */
|
||||||
|
len = strlen(bp);
|
||||||
|
while (len < fsize) {
|
||||||
|
*--bp = ' ';
|
||||||
|
len += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vpi_mcd_printf(mcd, "%s", bp);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If $display discovers a string as a parameter, this function is
|
* If $display discovers a string as a parameter, this function is
|
||||||
|
|
@ -300,6 +384,9 @@ static int format_str(vpiHandle scope, unsigned int mcd,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
|
format_time(mcd, fsize, value.value.str);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'd':
|
case 'd':
|
||||||
if (fsize==-1){
|
if (fsize==-1){
|
||||||
// simple %d parameter.
|
// simple %d parameter.
|
||||||
|
|
@ -893,8 +980,70 @@ static int sys_fgetc_sizetf(char*x)
|
||||||
return 32;
|
return 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sys_timeformat_compiletf(char *xx)
|
||||||
|
{
|
||||||
|
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||||
|
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||||
|
vpiHandle tmp;
|
||||||
|
|
||||||
|
assert(argv);
|
||||||
|
tmp = vpi_scan(argv);
|
||||||
|
assert(tmp);
|
||||||
|
assert(vpi_get(vpiType, tmp) == vpiConstant);
|
||||||
|
|
||||||
|
tmp = vpi_scan(argv);
|
||||||
|
assert(tmp);
|
||||||
|
assert(vpi_get(vpiType, tmp) == vpiConstant);
|
||||||
|
|
||||||
|
tmp = vpi_scan(argv);
|
||||||
|
assert(tmp);
|
||||||
|
assert(vpi_get(vpiType, tmp) == vpiConstant);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sys_timeformat_calltf(char *xx)
|
||||||
|
{
|
||||||
|
s_vpi_value value;
|
||||||
|
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||||
|
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||||
|
vpiHandle units = vpi_scan(argv);
|
||||||
|
vpiHandle prec = vpi_scan(argv);
|
||||||
|
vpiHandle suff = vpi_scan(argv);
|
||||||
|
vpiHandle wid = vpi_scan(argv);
|
||||||
|
|
||||||
|
vpi_free_object(argv);
|
||||||
|
|
||||||
|
value.format = vpiIntVal;
|
||||||
|
vpi_get_value(units, &value);
|
||||||
|
timeformat_info.units = value.value.integer;
|
||||||
|
|
||||||
|
value.format = vpiIntVal;
|
||||||
|
vpi_get_value(prec, &value);
|
||||||
|
timeformat_info.prec = value.value.integer;
|
||||||
|
|
||||||
|
value.format = vpiStringVal;
|
||||||
|
vpi_get_value(suff, &value);
|
||||||
|
timeformat_info.suff = strdup(value.value.str);
|
||||||
|
|
||||||
|
value.format = vpiIntVal;
|
||||||
|
vpi_get_value(wid, &value);
|
||||||
|
timeformat_info.width = value.value.integer;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sys_end_of_compile(p_cb_data cb_data)
|
||||||
|
{
|
||||||
|
timeformat_info.suff = strdup("");
|
||||||
|
timeformat_info.units = vpi_get(vpiTimePrecision, 0);
|
||||||
|
timeformat_info.width = 20;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void sys_display_register()
|
void sys_display_register()
|
||||||
{
|
{
|
||||||
|
s_cb_data cb_data;
|
||||||
s_vpi_systf_data tf_data;
|
s_vpi_systf_data tf_data;
|
||||||
|
|
||||||
//============================== display
|
//============================== display
|
||||||
|
|
@ -1106,11 +1255,27 @@ void sys_display_register()
|
||||||
tf_data.sizetf = sys_fgetc_sizetf;
|
tf_data.sizetf = sys_fgetc_sizetf;
|
||||||
tf_data.user_data = "$fgetc";
|
tf_data.user_data = "$fgetc";
|
||||||
vpi_register_systf(&tf_data);
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
//============================ timeformat
|
||||||
|
tf_data.type = vpiSysTask;
|
||||||
|
tf_data.tfname = "$timeformat";
|
||||||
|
tf_data.calltf = sys_timeformat_calltf;
|
||||||
|
tf_data.compiletf = sys_timeformat_compiletf;
|
||||||
|
tf_data.sizetf = 0;
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
cb_data.reason = cbEndOfCompile;
|
||||||
|
cb_data.cb_rtn = sys_end_of_compile;
|
||||||
|
cb_data.user_data = "system";
|
||||||
|
vpi_register_cb(&cb_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: sys_display.c,v $
|
* $Log: sys_display.c,v $
|
||||||
|
* Revision 1.38 2002/05/31 04:26:54 steve
|
||||||
|
* Add support for $timeformat.
|
||||||
|
*
|
||||||
* Revision 1.37 2002/05/24 19:05:30 steve
|
* Revision 1.37 2002/05/24 19:05:30 steve
|
||||||
* support GCC __attributes__ for printf formats.
|
* support GCC __attributes__ for printf formats.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue