From 286cef19fb9b2876b376f0f7703afac16035a38b Mon Sep 17 00:00:00 2001 From: steve Date: Sat, 22 Jul 2000 22:09:03 +0000 Subject: [PATCH] Parse and elaborate timescale to scopes. --- Module.h | 8 +++- design_dump.cc | 9 +++- elab_scope.cc | 10 ++++- elaborate.cc | 12 +++++- lexor.lex | 113 +++++++++++++++++++++++++++++++++++++++++++++++-- net_design.cc | 31 +++++++++++++- net_scope.cc | 27 +++++++++++- netlist.h | 36 +++++++++++++++- pform.cc | 16 ++++++- 9 files changed, 248 insertions(+), 14 deletions(-) diff --git a/Module.h b/Module.h index e95a3f387..18d545e1d 100644 --- a/Module.h +++ b/Module.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: Module.h,v 1.19 2000/05/16 04:05:15 steve Exp $" +#ident "$Id: Module.h,v 1.20 2000/07/22 22:09:03 steve Exp $" #endif # include @@ -84,6 +84,9 @@ class Module { /* Keep a table of named events declared in the module. */ mapevents; + /* These are the timescale for this module. The default is + set by the `timescale directive. */ + int time_unit, time_precision; const string&get_name() const { return name_; } @@ -136,6 +139,9 @@ class Module { /* * $Log: Module.h,v $ + * Revision 1.20 2000/07/22 22:09:03 steve + * Parse and elaborate timescale to scopes. + * * Revision 1.19 2000/05/16 04:05:15 steve * Module ports are really special PEIdent * expressions, because a name can be used diff --git a/design_dump.cc b/design_dump.cc index e3013194a..0c9b074dc 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: design_dump.cc,v 1.90 2000/07/14 06:12:57 steve Exp $" +#ident "$Id: design_dump.cc,v 1.91 2000/07/22 22:09:03 steve Exp $" #endif /* @@ -679,6 +679,9 @@ void NetScope::dump(ostream&o) const } o << endl; + o << " timescale = 10e" << time_unit() << " / 10e" + << time_precision() << endl; + /* Dump the parameters for this scope. */ { map::const_iterator pp; @@ -935,6 +938,7 @@ void NetEUnary::dump(ostream&o) const void Design::dump(ostream&o) const { + o << "DESIGN TIME PRECISION: 10e" << get_precision() << endl; o << "SCOPES:" << endl; root_scope_->dump(o); @@ -977,6 +981,9 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.91 2000/07/22 22:09:03 steve + * Parse and elaborate timescale to scopes. + * * Revision 1.90 2000/07/14 06:12:57 steve * Move inital value handling from NetNet to Nexus * objects. This allows better propogation of inital diff --git a/elab_scope.cc b/elab_scope.cc index 8c1aeb307..2b079c8cc 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: elab_scope.cc,v 1.4 2000/04/09 17:44:30 steve Exp $" +#ident "$Id: elab_scope.cc,v 1.5 2000/07/22 22:09:03 steve Exp $" #endif /* @@ -209,7 +209,10 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const // Create the new scope as a MODULE with my name. NetScope*my_scope = new NetScope(sc, get_name(), NetScope::MODULE); - + // Set time units and precision. + my_scope->time_unit(mod->time_unit); + my_scope->time_precision(mod->time_precision); + des->set_precision(mod->time_precision); // This call actually arranges for the description of the // module type to process this instance and handle parameters @@ -415,6 +418,9 @@ void PWhile::elaborate_scope(Design*des, NetScope*scope) const /* * $Log: elab_scope.cc,v $ + * Revision 1.5 2000/07/22 22:09:03 steve + * Parse and elaborate timescale to scopes. + * * Revision 1.4 2000/04/09 17:44:30 steve * Catch event declarations during scope elaborate. * diff --git a/elaborate.cc b/elaborate.cc index 71470d2e4..f78ac8572 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: elaborate.cc,v 1.178 2000/07/14 06:12:57 steve Exp $" +#ident "$Id: elaborate.cc,v 1.179 2000/07/22 22:09:03 steve Exp $" #endif /* @@ -1611,13 +1611,15 @@ NetProc* PDelayStatement::elaborate(Design*des, const string&path) const } assert(num); + /* Convert the delay in the units of the scope to the + precision of the design as a whole. */ + unsigned long val = des->scale_to_precision(num->as_ulong(), scope); /* If there is a statement, then elaborate it and create a NetPDelay statement to contain it. Note that we create a NetPDelay statement even if the value is 0 because #0 does in fact have a well defined meaning in Verilog. */ - unsigned long val = num->as_ulong(); if (statement_) { NetProc*stmt = statement_->elaborate(des, path); return new NetPDelay(val, stmt); @@ -2425,6 +2427,9 @@ Design* elaborate(const map&modules, // Make the root scope, then scan the pform looking for scopes // and parameters. NetScope*scope = des->make_root_scope(root); + scope->time_unit(rmod->time_unit); + scope->time_precision(rmod->time_precision); + des->set_precision(rmod->time_precision); if (! rmod->elaborate_scope(des, scope)) { delete des; return 0; @@ -2472,6 +2477,9 @@ Design* elaborate(const map&modules, /* * $Log: elaborate.cc,v $ + * Revision 1.179 2000/07/22 22:09:03 steve + * Parse and elaborate timescale to scopes. + * * Revision 1.178 2000/07/14 06:12:57 steve * Move inital value handling from NetNet to Nexus * objects. This allows better propogation of inital diff --git a/lexor.lex b/lexor.lex index 312723b66..447980fb0 100644 --- a/lexor.lex +++ b/lexor.lex @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: lexor.lex,v 1.45 2000/06/27 04:36:29 steve Exp $" +#ident "$Id: lexor.lex,v 1.46 2000/07/22 22:09:03 steve Exp $" #endif //# define YYSTYPE lexval @@ -39,6 +39,8 @@ extern string vl_file; # define yylval VLlval extern YYLTYPE yylloc; +extern void pform_set_timescale(int, int); + static void reset_lexor(); static void line_directive(); static void line_directive2(); @@ -53,6 +55,8 @@ static verinum*make_unsized_dec(const char*txt); static verinum*make_unsized_octal(const char*txt); static verinum*make_unsized_hex(const char*txt); +static void process_timescale(const char*txt); + static int comment_enter; %} @@ -218,10 +222,8 @@ W [ \t\b\f\r]+ /* Notice and handle the timescale directive. */ `timescale { BEGIN(PPTIMESCALE); } -. { ; } +.* { process_timescale(yytext); } \n { - cerr << yylloc.text << ":" << yylloc.first_line - << ": Sorry, `timescale not supported." << endl; yylloc.first_line += 1; BEGIN(0); } @@ -815,6 +817,109 @@ static verinum*make_unsized_dec(const char*txt) return make_dec_with_size(INTEGER_WIDTH, false, txt+1); } +/* + * The timescale parameter has the form: + * " xs / xs" + */ +static void process_timescale(const char*txt) +{ + unsigned num; + const char*cp = txt + strspn(txt, " \t"); + char*tmp; + const char*ctmp; + + int unit = 0; + int prec = 0; + + num = strtoul(cp, &tmp, 10); + if (num == 0) { + VLerror(yylloc, "Invalid timescale string."); + return; + } + + while (num >= 10) { + unit += 1; + num /= 10; + } + if (num != 1) { + VLerror(yylloc, "Invalid timescale unit number."); + return; + } + + cp = tmp; + cp += strspn(cp, " \t"); + ctmp = cp + strcspn(cp, " \t/"); + + if (strncmp("s", cp, ctmp-cp) == 0) { + unit -= 0; + + } else if (strncmp("ms", cp, ctmp-cp) == 0) { + unit -= 3; + + } else if (strncmp("us", cp, ctmp-cp) == 0) { + unit -= 6; + + } else if (strncmp("ns", cp, ctmp-cp) == 0) { + unit -= 9; + + } else if (strncmp("ps", cp, ctmp-cp) == 0) { + unit -= 12; + + } else if (strncmp("fs", cp, ctmp-cp) == 0) { + unit -= 15; + + } else { + VLerror(yylloc, "Invalid timescale unit of measurement"); + return; + } + + cp = ctmp; + cp += strspn(cp, " \t/"); + + num = strtoul(cp, &tmp, 10); + if (num == 0) { + VLerror(yylloc, "Invalid timescale string."); + return; + } + assert(num); + while (num >= 10) { + prec += 1; + num /= 10; + } + if (num != 1) { + VLerror(yylloc, "Invalid timescale precision number."); + return; + } + + cp = tmp; + cp += strspn(cp, " \t"); + ctmp = cp + strcspn(cp, " \t"); + + if (strncmp("s", cp, ctmp-cp) == 0) { + prec -= 0; + + } else if (strncmp("ms", cp, ctmp-cp) == 0) { + prec -= 3; + + } else if (strncmp("us", cp, ctmp-cp) == 0) { + prec -= 6; + + } else if (strncmp("ns", cp, ctmp-cp) == 0) { + prec -= 9; + + } else if (strncmp("ps", cp, ctmp-cp) == 0) { + prec -= 12; + + } else if (strncmp("fs", cp, ctmp-cp) == 0) { + prec -= 15; + + } else { + VLerror(yylloc, "Invalid timescale precision units of measurement"); + return; + } + + pform_set_timescale(unit, prec); +} static int yywrap() { diff --git a/net_design.cc b/net_design.cc index 1f82b80ad..da46b9385 100644 --- a/net_design.cc +++ b/net_design.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: net_design.cc,v 1.10 2000/07/16 04:56:08 steve Exp $" +#ident "$Id: net_design.cc,v 1.11 2000/07/22 22:09:03 steve Exp $" #endif /* @@ -47,6 +47,7 @@ Design:: Design() : errors(0), root_scope_(0), nodes_(0), procs_(0), lcounter_(0) { procs_idx_ = 0; + des_precision_ = 0; } Design::~Design() @@ -61,6 +62,31 @@ string Design::local_symbol(const string&path) return path + "." + res.str(); } +void Design::set_precision(int val) +{ + if (val < des_precision_) + des_precision_ = val; +} + +int Design::get_precision() const +{ + return des_precision_; +} + +unsigned long Design::scale_to_precision(unsigned long val, + const NetScope*scope) const +{ + int units = scope->time_unit(); + assert( units > des_precision_ ); + + while (units > des_precision_) { + units -= 1; + val *= 10; + } + + return val; +} + NetScope* Design::make_root_scope(const string&root) { assert(root_scope_ == 0); @@ -471,6 +497,9 @@ void Design::delete_process(NetProcTop*top) /* * $Log: net_design.cc,v $ + * Revision 1.11 2000/07/22 22:09:03 steve + * Parse and elaborate timescale to scopes. + * * Revision 1.10 2000/07/16 04:56:08 steve * Handle some edge cases during node scans. * diff --git a/net_scope.cc b/net_scope.cc index 3201ff432..b91f073be 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: net_scope.cc,v 1.6 2000/05/02 03:13:31 steve Exp $" +#ident "$Id: net_scope.cc,v 1.7 2000/07/22 22:09:03 steve Exp $" #endif # include "netlist.h" @@ -46,6 +46,8 @@ NetScope::NetScope(NetScope*up, const string&n, NetScope::TYPE t) memories_ = 0; signals_ = 0; events_ = 0; + time_unit_ = up->time_unit(); + time_prec_ = up->time_precision(); sib_ = up_->sub_; up_->sub_ = this; } @@ -93,6 +95,26 @@ NetScope::TYPE NetScope::type() const return type_; } +void NetScope::time_unit(int val) +{ + time_unit_ = val; +} + +void NetScope::time_precision(int val) +{ + time_prec_ = val; +} + +int NetScope::time_unit() const +{ + return time_unit_; +} + +int NetScope::time_precision() const +{ + return time_prec_; +} + string NetScope::basename() const { return name_; @@ -281,6 +303,9 @@ string NetScope::local_symbol() /* * $Log: net_scope.cc,v $ + * Revision 1.7 2000/07/22 22:09:03 steve + * Parse and elaborate timescale to scopes. + * * Revision 1.6 2000/05/02 03:13:31 steve * Move memories to the NetScope object. * diff --git a/netlist.h b/netlist.h index 375edc900..926351531 100644 --- a/netlist.h +++ b/netlist.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: netlist.h,v 1.147 2000/07/16 04:56:08 steve Exp $" +#ident "$Id: netlist.h,v 1.148 2000/07/22 22:09:04 steve Exp $" #endif /* @@ -2461,6 +2461,20 @@ class NetScope { TYPE type() const; + /* Scopes have their own time units and time precision. The + unit and precision are given as power of 10, i.e. -3 is + units of milliseconds. + + If a NetScope is created with a parent scope, the new scope + will initially inherit the unit and precision of the + parent scope. */ + + void time_unit(int); + void time_precision(int); + + int time_unit() const; + int time_precision() const; + /* The name of the scope is the fully qualified hierarchical name, whereas the basename is just my name within my parent scope. */ @@ -2492,6 +2506,8 @@ class NetScope { TYPE type_; string name_; + signed char time_unit_, time_prec_; + mapparameters_; maplocalparams_; @@ -2531,6 +2547,19 @@ class Design { NetScope* make_root_scope(const string&name); NetScope* find_root_scope(); + + /* Attempt to set the precision to the specified value. If the + precision is already more precise, the keep the precise + setting. This is intended to hold the simulation precision + for use throughout the entire design. */ + + void set_precision(int val); + int get_precision() const; + + /* This function takes a delay value and a scope, and returns + the delay value scaled to the precision of the design. */ + unsigned long scale_to_precision(unsigned long, const NetScope*)const; + /* look up a scope. If no starting scope is passed, then the path name string is taken as an absolute scope name. Otherwise, the scope is located starting at the @@ -2613,6 +2642,8 @@ class Design { map flags_; + int des_precision_; + unsigned lcounter_; private: // not implemented @@ -2660,6 +2691,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.148 2000/07/22 22:09:04 steve + * Parse and elaborate timescale to scopes. + * * Revision 1.147 2000/07/16 04:56:08 steve * Handle some edge cases during node scans. * diff --git a/pform.cc b/pform.cc index 18f88c6d2..3b4566cee 100644 --- a/pform.cc +++ b/pform.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: pform.cc,v 1.61 2000/05/23 16:03:13 steve Exp $" +#ident "$Id: pform.cc,v 1.62 2000/07/22 22:09:04 steve Exp $" #endif # include "compiler.h" @@ -39,6 +39,8 @@ string vl_file = ""; extern int VLparse(); static Module*pform_cur_module = 0; +static int pform_time_unit = 0; +static int pform_time_prec = 0; /* * The scope stack and the following functions handle the processing @@ -53,6 +55,13 @@ struct scope_name_t { }; static scope_name_t*scope_stack = 0; +void pform_set_timescale(int unit, int prec) +{ + assert(unit >= prec); + pform_time_unit = unit; + pform_time_prec = prec; +} + void pform_push_scope(const string&name) { scope_name_t*cur = new scope_name_t; @@ -110,6 +119,8 @@ void pform_startmodule(const string&name, svector*ports) } pform_cur_module = new Module(name, ports); + pform_cur_module->time_unit = pform_time_unit; + pform_cur_module->time_precision = pform_time_prec; delete ports; } @@ -874,6 +885,9 @@ int pform_parse(const char*path, map&modules, /* * $Log: pform.cc,v $ + * Revision 1.62 2000/07/22 22:09:04 steve + * Parse and elaborate timescale to scopes. + * * Revision 1.61 2000/05/23 16:03:13 steve * Better parsing of expressions lists will empty expressoins. *