From 2d1b8e4c8193063256bd1ed62261d4c3e463a5ff Mon Sep 17 00:00:00 2001 From: Cary R Date: Fri, 22 Jan 2010 15:26:02 -0800 Subject: [PATCH] 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. --- driver/cflexor.lex | 6 +- driver/cfparse.y | 13 +++- driver/globals.h | 5 +- driver/iverilog.man.in | 11 +++- driver/main.c | 7 ++- main.cc | 135 ++++++++++++++++++++++++++++++++++++++++- 6 files changed, 167 insertions(+), 10 deletions(-) diff --git a/driver/cflexor.lex b/driver/cflexor.lex index 526f8eaed..0dabdff0b 100644 --- a/driver/cflexor.lex +++ b/driver/cflexor.lex @@ -4,7 +4,7 @@ %{ /* - * Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -76,13 +76,15 @@ int cmdfile_stack_ptr = 0; "+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; } +"+timescale+" { BEGIN(PLUS_ARGS); return TOK_TIMESCALE; } /* If it is not any known plus-flag, return the generic form. */ "+"[^\n \t\b\f\r+]* { diff --git a/driver/cfparse.y b/driver/cfparse.y index 9ee38e7d3..002bd289d 100644 --- a/driver/cfparse.y +++ b/driver/cfparse.y @@ -1,6 +1,6 @@ %{ /* - * Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -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 -%token TOK_INTEGER_WIDTH +%token TOK_DEFINE TOK_INCDIR TOK_INTEGER_WIDTH TOK_LIBDIR TOK_LIBDIR_NOCASE +%token TOK_LIBEXT TOK_TIMESCALE %token TOK_PLUSARG TOK_PLUSWORD TOK_STRING %% @@ -135,6 +135,13 @@ item free(tmp); } + | TOK_TIMESCALE TOK_PLUSARG + { char*tmp = substitutions($2); + process_timescale(tmp); + free($2); + free(tmp); + } + | TOK_DEFINE TOK_PLUSARG { process_define($2); free($2); diff --git a/driver/globals.h b/driver/globals.h index d51cde863..e26b52d51 100644 --- a/driver/globals.h +++ b/driver/globals.h @@ -1,7 +1,7 @@ #ifndef __globals_H #define __globals_H /* - * Copyright (c) 2000-2009 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2010 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -41,4 +41,7 @@ extern void process_include_dir(const char*name); /* Add a new -D define. */ extern void process_define(const char*name); + /* Set the default timescale for the simulator. */ +extern void process_timescale(const char*ts_string); + #endif diff --git a/driver/iverilog.man.in b/driver/iverilog.man.in index e0a5a6c24..5457483ef 100644 --- a/driver/iverilog.man.in +++ b/driver/iverilog.man.in @@ -1,4 +1,4 @@ -.TH iverilog 1 "October 28th, 2009" "" "Version %M.%m.%n %E" +.TH iverilog 1 "January 22nd, 2010" "" "Version %M.%m.%n %E" .SH NAME iverilog - Icarus Verilog compiler @@ -402,6 +402,13 @@ letters are correct. For example, "foo" matches "Foo.v" but not The \fB+define+\fP token is the same as the \fB\-D\fP option on the command line. The value part of the token is optional. +.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 @@ -472,7 +479,7 @@ Tips on using, debugging, and developing the compiler can be found at .SH COPYRIGHT .nf -Copyright \(co 2002\-2009 Stephen Williams +Copyright \(co 2002\-2010 Stephen Williams This document can be freely redistributed according to the terms of the GNU General Public License version 2.0 diff --git a/driver/main.c b/driver/main.c index 46f5021c4..48d11c7c7 100644 --- a/driver/main.c +++ b/driver/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2009 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2010 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -568,6 +568,11 @@ void process_define(const char*name) fprintf(defines_file,"D:%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 diff --git a/main.cc b/main.cc index a168b4099..def4bbcb3 100644 --- a/main.cc +++ b/main.cc @@ -1,6 +1,6 @@ const char COPYRIGHT[] = - "Copyright (c) 1998-2009 Stephen Williams (steve@icarus.com)"; + "Copyright (c) 1998-2010 Stephen Williams (steve@icarus.com)"; /* * This source code is free software; you can redistribute it @@ -297,6 +297,127 @@ static void parm_to_flagmap(const string&flag) static void find_module_mention(map&check_map, Module*m); static void find_module_mention(map&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' > + * + * " '/' + * + * 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 @@ -369,6 +490,7 @@ static void find_module_mention(map&check_map, PGenerate*s); * warnings: * Warning flag letters. */ +bool had_timescale = false; static void read_iconfig_file(const char*ipath) { char buf[8*1024]; @@ -542,6 +664,17 @@ static void read_iconfig_file(const char*ipath) flag_errors += 1; } + } 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);