Add +timescale to the command file.

This patch adds a +timescale command to the command file
syntax that can be used to set the default time scale of
the simulation.
This commit is contained in:
Cary R 2009-12-29 20:23:58 -08:00 committed by Stephen Williams
parent d2dd0daa3c
commit 3cef85b06b
6 changed files with 168 additions and 9 deletions

View File

@ -72,19 +72,21 @@ int cmdfile_stack_ptr = 0;
\n { cflloc.first_line += 1; }
"+parameter+" { BEGIN(PLUS_ARGS); return TOK_PARAMETER; }
"+define+" { BEGIN(PLUS_ARGS); return TOK_DEFINE; }
"+incdir+" { BEGIN(PLUS_ARGS); return TOK_INCDIR; }
"+integer-width+" { BEGIN(PLUS_ARGS); return TOK_INTEGER_WIDTH; }
"+libdir+" { BEGIN(PLUS_ARGS); return TOK_LIBDIR; }
"+libdir-nocase+" { BEGIN(PLUS_ARGS); return TOK_LIBDIR_NOCASE; }
"+libext+" { BEGIN(PLUS_ARGS); return TOK_LIBEXT; }
"+integer-width+" { BEGIN(PLUS_ARGS); return TOK_INTEGER_WIDTH; }
"+parameter+" { BEGIN(PLUS_ARGS); return TOK_PARAMETER; }
"+timescale+" { BEGIN(PLUS_ARGS); return TOK_TIMESCALE; }
/* If it is not any known plus-flag, return the generic form. */
"+"[^\n \t\b\f\r+]* {

View File

@ -57,8 +57,8 @@ static void translate_file_name(char*text)
};
%token TOK_Da TOK_Dc TOK_Dv TOK_Dy
%token TOK_DEFINE TOK_INCDIR TOK_LIBDIR TOK_LIBDIR_NOCASE TOK_LIBEXT TOK_PARAMETER
%token TOK_INTEGER_WIDTH
%token TOK_DEFINE TOK_INCDIR TOK_INTEGER_WIDTH TOK_LIBDIR TOK_LIBDIR_NOCASE
%token TOK_LIBEXT TOK_PARAMETER TOK_TIMESCALE
%token <text> TOK_PLUSARG TOK_PLUSWORD TOK_STRING
%%
@ -142,6 +142,15 @@ item
free(tmp);
}
/* The +timescale token is used to set the default timescale for
the simulator. */
| TOK_TIMESCALE TOK_PLUSARG
{ char*tmp = substitutions($2);
process_timescale(tmp);
free($2);
free(tmp);
}
| TOK_DEFINE TOK_PLUSARG
{ process_define($2);
free($2);

View File

@ -44,4 +44,7 @@ extern void process_define(const char*name);
/* Add a new parameter definition */
extern void process_parameter(const char*name);
/* Set the default timescale for the simulator. */
extern void process_timescale(const char*ts_string);
#endif

View File

@ -1,4 +1,4 @@
.TH iverilog 1 "October 28th, 2009" "" "Version %M.%m.%n %E"
.TH iverilog 1 "December 29th, 2009" "" "Version %M.%m.%n %E"
.SH NAME
iverilog - Icarus Verilog compiler
@ -425,9 +425,16 @@ command line. The value part of the token is optional.
.TP 8
.B +parameter+\fINAME\fP=\fIvalue\fP
The \fB+default+\fP token is the same as the \fB\-P\fP option on the
The \fB+parameter+\fP token is the same as the \fB\-P\fP option on the
command line.
.TP 8
.B +timescale+\fIvalue\fP
The \fB+timescale+\fP token is used to set the default timescale for
the simulation. This is the time units and precision before any
`timescale directive or after a `resetall directive. The default is
1s/1s.
.TP 8
.B +toupper-filename
This token causes file names after this in the command file to be

View File

@ -582,6 +582,11 @@ void process_parameter(const char*name)
fprintf(iconfig_file,"defparam:%s\n", name);
}
void process_timescale(const char*ts_string)
{
fprintf(iconfig_file, "timescale:%s\n", ts_string);
}
/*
* This function is called while processing a file name in a command
* file, or a file name on the command line. Look to see if there is a

133
main.cc
View File

@ -312,6 +312,127 @@ static void parm_to_flagmap(const string&flag)
static void find_module_mention(map<perm_string,bool>&check_map, Module*m);
static void find_module_mention(map<perm_string,bool>&check_map, PGenerate*s);
/*
* Convert a string to a time unit or precision.
*
* Returns true on failure.
*/
static bool get_ts_const(const char*&cp, int&res, bool is_units)
{
/* Check for the 1 digit. */
if (*cp != '1') {
if (is_units) {
cerr << "Error: Invalid +timescale units constant "
"(1st digit)." << endl;
} else {
cerr << "Error: Invalid +timescale precision constant "
"(1st digit)." << endl;
}
return true;
}
cp += 1;
/* Check the number of zeros after the 1. */
res = strspn(cp, "0");
if (res > 2) {
if (is_units) {
cerr << "Error: Invalid +timescale units constant "
"(number of zeros)." << endl;
} else {
cerr << "Error: Invalid +timescale precision constant "
"(number of zeros)." << endl;
}
return true;
}
cp += res;
/* Now process the scaling string. */
if (strncmp("s", cp, 1) == 0) {
res -= 0;
cp += 1;
return false;
} else if (strncmp("ms", cp, 2) == 0) {
res -= 3;
cp += 2;
return false;
} else if (strncmp("us", cp, 2) == 0) {
res -= 6;
cp += 2;
return false;
} else if (strncmp("ns", cp, 2) == 0) {
res -= 9;
cp += 2;
return false;
} else if (strncmp("ps", cp, 2) == 0) {
res -= 12;
cp += 2;
return false;
} else if (strncmp("fs", cp, 2) == 0) {
res -= 15;
cp += 2;
return false;
}
if (is_units) {
cerr << "Error: Invalid +timescale units scale." << endl;
} else {
cerr << "Error: Invalid +timescale precision scale." << endl;
}
return true;
}
/*
* Process a string with the following form (no space allowed):
*
* num = < '1' | '10' | '100' >
* scale = < 's' | 'ms' | 'us' | 'ns' | 'ps' | 'fs' >
*
* "<num> <scale> '/' <num> <scale>
*
* and set the default time units and precision if successful.
*
* Return true if we have an error processing the timescale string.
*/
static bool set_default_timescale(const char*ts_string)
{
/* Because this came from a command file we can not have embedded
* space in this string. */
const char*cp = ts_string;
int units = 0;
int prec = 0;
/* Get the time units. */
if (get_ts_const(cp, units, true)) return true;
/* Skip the '/'. */
if (*cp != '/') {
cerr << "Error: +timescale separator '/' is missing." << endl;
return true;
}
cp += 1;
/* Get the time precision. */
if (get_ts_const(cp, prec, false)) return true;
/* The time unit must be greater than or equal to the precision. */
if (units < prec) {
cerr << "Error: +timescale unit must not be less than the "
"precision." << endl;
return true;
}
/* We have valid units and precision so set the global defaults. */
def_ts_units = units;
def_ts_prec = prec;
return false;
}
/*
* Read the contents of a config file. This file is a temporary
* configuration file made by the compiler driver to carry the bulky
@ -384,6 +505,7 @@ static void find_module_mention(map<perm_string,bool>&check_map, PGenerate*s);
* warnings:<string>
* Warning flag letters.
*/
bool had_timescale = false;
static void read_iconfig_file(const char*ipath)
{
char buf[8*1024];
@ -561,6 +683,17 @@ static void read_iconfig_file(const char*ipath)
}
} else if (strcmp(buf,"defparam") == 0) {
parm_to_defparam_list(cp);
} else if (strcmp(buf,"timescale") == 0) {
if (had_timescale) {
cerr << "Command File: Warning: default timescale "
"is being set multiple times." << endl;
cerr << " : using the last valid "
"+timescale found." << endl;
}
if (set_default_timescale(cp)) {
cerr << " : with +timescale+" << cp << "+" << endl;
flag_errors += 1;
} else had_timescale = true;
}
}
fclose(ifile);