From 4991711672205a21acb0cd718b7e50f8822715b7 Mon Sep 17 00:00:00 2001 From: Cary R Date: Fri, 22 May 2009 11:03:36 -0700 Subject: [PATCH] Add support for `resetall and other directive changes. This patch adds support for the `resetall directive. It also changes `celldefine, `endcelldefine and `resetall to no longer grab text following them. These directives do not take an argument so they should not be grabbing any text and silently discarding it. The `timescale processing was reworked to handle being reset and hooks were added to easily change the default time units and precision when we add that feature request. --- Module.cc | 1 + Module.h | 1 + lexor.lex | 42 +++++++++++++++++++++++++++++++++++------- main.cc | 4 ++++ parse_api.h | 7 ++++++- pform.cc | 30 ++++++++++++++++++++++++------ 6 files changed, 71 insertions(+), 14 deletions(-) diff --git a/Module.cc b/Module.cc index 789e4137a0..e608a6401e 100644 --- a/Module.cc +++ b/Module.cc @@ -31,6 +31,7 @@ Module::Module(perm_string n) library_flag = false; is_cell = false; default_nettype = NetNet::NONE; + timescale_warn_done = false; } Module::~Module() diff --git a/Module.h b/Module.h index 4f4ead3d54..a2960bc747 100644 --- a/Module.h +++ b/Module.h @@ -108,6 +108,7 @@ class Module : public PScope, public LineInfo { set by the `timescale directive. */ int time_unit, time_precision; bool time_from_timescale; + bool timescale_warn_done; /* Task definitions within this module */ map tasks; diff --git a/lexor.lex b/lexor.lex index 6668cf5148..1f5d107371 100644 --- a/lexor.lex +++ b/lexor.lex @@ -67,9 +67,6 @@ static const char* set_file_name(char*text) return path; } - -extern void pform_set_timescale(int, int, const char*file, unsigned line); - void reset_lexor(); static void line_directive(); static void line_directive2(); @@ -88,6 +85,7 @@ static list keyword_mask_stack; static int comment_enter; static bool in_module = false; +static bool in_UDP = false; bool in_celldefine = false; %} @@ -238,6 +236,14 @@ S [afpnumkKMGT] in_module = false; break; + case K_primitive: + in_UDP = true; + break; + + case K_endprimitive: + in_UDP = false; + break; + default: yylval.text = 0; break; @@ -349,7 +355,7 @@ S [afpnumkKMGT] return REALTIME; } - /* Notice and handle the timescale directive. */ + /* Notice and handle the `timescale directive. */ ^{W}?`timescale { BEGIN(PPTIMESCALE); } .* { process_timescale(yytext); } @@ -363,8 +369,31 @@ S [afpnumkKMGT] yylloc.first_line += 1; BEGIN(0); } -^{W}?`celldefine{W}?.* { in_celldefine = true; } -^{W}?`endcelldefine{W}?.* { in_celldefine = false; } + /* Notice and handle the `celldefine and `endcelldefine directives. */ + +^{W}?`celldefine{W}? { in_celldefine = true; } +^{W}?`endcelldefine{W}? { in_celldefine = false; } + + /* Notice and handle the resetall directive. */ + +^{W}?`resetall{W}? { + if (in_module) { + cerr << yylloc.text << ":" << yylloc.first_line << ": error: " + "`resetall directive can not be inside a module " + "definition." << endl; + error_count += 1; + } else if (in_UDP) { + cerr << yylloc.text << ":" << yylloc.first_line << ": error: " + "`resetall directive can not be inside a UDP " + "definition." << endl; + error_count += 1; + } else { + pform_set_default_nettype(NetNet::WIRE, yylloc.text, + yylloc.first_line); + in_celldefine = false; + pform_set_timescale(def_ts_units, def_ts_prec, 0, 0); + /* Add `nounconnected_drive when implemented. */ + } } /* These are directives that I do not yet support. I think that IVL should handle these, not an external preprocessor. */ @@ -372,7 +401,6 @@ S [afpnumkKMGT] ^{W}?`line{W}?.* { } ^{W}?`nounconnected_drive{W}?.* { } ^{W}?`pragme{W}?.* { } -^{W}?`resetall{W}?.* { } ^{W}?`unconnected_drive{W}?.* { } /* From 1364-2005 Annex D. */ diff --git a/main.cc b/main.cc index c692a154a7..b3f1201c0f 100644 --- a/main.cc +++ b/main.cc @@ -142,6 +142,9 @@ bool verbose_flag = false; unsigned integer_width = 32; +int def_ts_units = 0; +int def_ts_prec = 0; + /* * Keep a heap of identifier strings that I encounter. This is a more * efficient way to allocate those strings. @@ -726,6 +729,7 @@ int main(int argc, char*argv[]) if (flag_tmp) recursive_mod_limit = strtoul(flag_tmp,NULL,0); /* Parse the input. Make the pform. */ + pform_set_timescale(def_ts_units, def_ts_prec, 0, 0); int rc = pform_parse(argv[optind]); if (pf_path) { diff --git a/parse_api.h b/parse_api.h index 76ea71531f..ba23c564e5 100644 --- a/parse_api.h +++ b/parse_api.h @@ -1,7 +1,7 @@ #ifndef __parse_api_H #define __parse_api_H /* - * Copyright (c) 2001 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2009 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 @@ -46,4 +46,9 @@ extern int pform_parse(const char*path, FILE*file =0); extern string vl_file; +extern void pform_set_timescale(int units, int prec, const char*file, + unsigned lineno); +extern int def_ts_units; +extern int def_ts_prec; + #endif diff --git a/pform.cc b/pform.cc index b87ac6e2b7..52dfed03cb 100644 --- a/pform.cc +++ b/pform.cc @@ -70,11 +70,11 @@ static NetNet::Type pform_default_nettype = NetNet::WIRE; * These variables track the current time scale, as well as where the * timescale was set. This supports warnings about tangled timescales. */ -static int pform_time_unit = 0; -static int pform_time_prec = 0; +static int pform_time_unit; +static int pform_time_prec; static char*pform_timescale_file = 0; -static unsigned pform_timescale_line = 0; +static unsigned pform_timescale_line; static inline void FILE_NAME(LineInfo*obj, const char*file, unsigned lineno) { @@ -298,10 +298,25 @@ void pform_set_timescale(int unit, int prec, first_flag = false; } - pform_timescale_file = strdup(file); + if (file) pform_timescale_file = strdup(file); + else pform_timescale_file = 0; pform_timescale_line = lineno; - if (warn_timescale && first_flag && (pform_modules.size() > 0)) { + if (!warn_timescale || !first_flag || !file) return; + + /* Look to see if we have any modules without a timescale. */ + bool have_no_ts = false; + map::iterator mod; + for (mod = pform_modules.begin(); mod != pform_modules.end(); mod++) { + const Module*mp = (*mod).second; + if (mp->time_from_timescale || + mp->timescale_warn_done) continue; + have_no_ts = true; + break; + } + + /* If we do then print a message for the new ones. */ + if (have_no_ts) { cerr << file << ":" << lineno << ": warning: " << "Some modules have no timescale. This may cause" << endl; @@ -312,7 +327,10 @@ void pform_set_timescale(int unit, int prec, map::iterator mod; for (mod = pform_modules.begin() ; mod != pform_modules.end() ; mod++) { - const Module*mp = (*mod).second; + Module*mp = (*mod).second; + if (mp->time_from_timescale || + mp->timescale_warn_done) continue; + mp->timescale_warn_done = true; cerr << file << ":" << lineno << ": : " << " -- module " << (*mod).first