From 87885dbd9b2abbce3aa10fd21f15340da73a35f3 Mon Sep 17 00:00:00 2001 From: mole99 Date: Wed, 5 Jul 2023 16:22:08 +0200 Subject: [PATCH 1/9] Handle delayed signals in timing checks as assignments --- Makefile.in | 2 +- Module.h | 4 + PTimingCheck.cc | 94 +++++++++++++ PTimingCheck.h | 127 ++++++++++++++++++ elaborate.cc | 143 +++++++++++++++++++- parse.y | 351 ++++++++++++++++++++++++++++++++---------------- pform.cc | 67 +++++++++ pform.h | 28 ++++ pform_dump.cc | 23 ++++ 9 files changed, 722 insertions(+), 117 deletions(-) create mode 100644 PTimingCheck.cc create mode 100644 PTimingCheck.h diff --git a/Makefile.in b/Makefile.in index d648f66a45..65223fb600 100644 --- a/Makefile.in +++ b/Makefile.in @@ -119,7 +119,7 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \ pform_types.o \ symbol_search.o sync.o sys_funcs.o verinum.o verireal.o vpi_modules.o target.o \ Attrib.o HName.o Module.o PClass.o PDelays.o PEvent.o PExpr.o PFunction.o \ - PGate.o PGenerate.o PModport.o PNamedItem.o PPackage.o PScope.o PSpec.o \ + PGate.o PGenerate.o PModport.o PNamedItem.o PPackage.o PScope.o PSpec.o PTimingCheck.o \ PTask.o PUdp.o PWire.o Statement.o AStatement.o $M $(FF) $(TT) all: dep config.h _pli_types.h version_tag.h ivl@EXEEXT@ version.exe iverilog-vpi.man diff --git a/Module.h b/Module.h index 3630d4b1cb..3b77fb8c84 100644 --- a/Module.h +++ b/Module.h @@ -37,6 +37,7 @@ class PGate; class PGenerate; class PModport; class PSpecPath; +class PTimingCheck; class PTask; class PFunction; class PWire; @@ -136,7 +137,9 @@ class Module : public PScopeExtra, public PNamedItem { program blocks. */ std::map modports; + /* List for specify paths and timing checks */ std::list specify_paths; + std::list timing_checks; // The mod_name() is the name of the module type. perm_string mod_name() const { return pscope_name(); } @@ -170,6 +173,7 @@ class Module : public PScopeExtra, public PNamedItem { private: void dump_specparams_(std::ostream&out, unsigned indent) const; + void dump_timingchecks_(std::ostream&out, unsigned indent) const; std::list gates_; private: // Not implemented diff --git a/PTimingCheck.cc b/PTimingCheck.cc new file mode 100644 index 0000000000..02ce4bb78a --- /dev/null +++ b/PTimingCheck.cc @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2006-2023 Stephen Williams + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +# include "PTimingCheck.h" + +PRecRem::PRecRem(event_t reference_event, + event_t data_event, + //PExpr setup_limit, + //PExpr hold_limit, + pform_name_t* notifier, + pform_name_t* timestamp_cond, + pform_name_t* timecheck_cond, + pform_name_t* delayed_reference, + pform_name_t* delayed_data) + : + reference_event_ (reference_event), + data_event_ (data_event), + //setup_limit (setup_limit), + //hold_limit (hold_limit), + notifier_ (notifier), + timestamp_cond_ (timestamp_cond), + timecheck_cond_ (timecheck_cond), + delayed_reference_ (delayed_reference), + delayed_data_ (delayed_data) +{ +} + +PRecRem::~PRecRem() +{ + // Delete optional arguments + if (reference_event_.condition) delete reference_event_.condition; + if (data_event_.condition) delete data_event_.condition; + + if(notifier_) delete notifier_; + + if(timestamp_cond_) delete timestamp_cond_; + if(timecheck_cond_) delete timecheck_cond_; + + if(delayed_reference_) delete delayed_reference_; + if(delayed_data_) delete delayed_data_; +} + +PSetupHold::PSetupHold(event_t reference_event, + event_t data_event, + //PExpr setup_limit, + //PExpr hold_limit, + pform_name_t* notifier, + pform_name_t* timestamp_cond, + pform_name_t* timecheck_cond, + pform_name_t* delayed_reference, + pform_name_t* delayed_data) + : + reference_event_ (reference_event), + data_event_ (data_event), + //setup_limit (setup_limit), + //hold_limit (hold_limit), + notifier_ (notifier), + timestamp_cond_ (timestamp_cond), + timecheck_cond_ (timecheck_cond), + delayed_reference_ (delayed_reference), + delayed_data_ (delayed_data) +{ +} + +PSetupHold::~PSetupHold() +{ + // Delete optional arguments + if (reference_event_.condition) delete reference_event_.condition; + if (data_event_.condition) delete data_event_.condition; + + if(notifier_) delete notifier_; + + if(timestamp_cond_) delete timestamp_cond_; + if(timecheck_cond_) delete timecheck_cond_; + + if(delayed_reference_) delete delayed_reference_; + if(delayed_data_) delete delayed_data_; +} diff --git a/PTimingCheck.h b/PTimingCheck.h new file mode 100644 index 0000000000..eb98b200a2 --- /dev/null +++ b/PTimingCheck.h @@ -0,0 +1,127 @@ +#ifndef IVL_PTimingCheck_H +#define IVL_PTimingCheck_H +/* + * Copyright (c) 2006-2023 Stephen Williams + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +# include "LineInfo.h" +# include "pform_types.h" + +// TODO cleanup in destructor and cleanup in Module! + +/* +* The PTimingCheck is the base class for all timing checks +*/ +class PTimingCheck : public LineInfo { + + public: + enum EdgeType {EDGE_01, EDGE_0X, EDGE_10, EDGE_1X, EDGE_X0, EDGE_X1}; + + struct event_t { + pform_name_t name; + bool posedge; + bool negedge; + std::vector edges; + PExpr* condition; + }; + + PTimingCheck() { } + virtual ~PTimingCheck() { } + + virtual void elaborate(class Design*des, class NetScope*scope) const = 0; + + virtual void dump(std::ostream&out, unsigned ind) const = 0; +}; + +/* +* The PRecRem is the parse of a $recrem timing check +*/ +class PRecRem : public PTimingCheck { + + public: + PRecRem(event_t reference_event, + event_t data_event, + //PExpr setup_limit, + //PExpr hold_limit, + pform_name_t* notifier, + pform_name_t* timestamp_cond, + pform_name_t* timecheck_cond, + pform_name_t* delayed_reference, + pform_name_t* delayed_data); + + ~PRecRem(); + + void elaborate(class Design*des, class NetScope*scope) const override; + + void dump(std::ostream&out, unsigned ind) const override; + + public: // TODO + event_t reference_event_; // hierarchy_identifier + event_t data_event_; + + //PExpr setup_limit; + //PExpr hold_limit; + + pform_name_t* notifier_; + + pform_name_t* timestamp_cond_; + pform_name_t* timecheck_cond_; + + pform_name_t* delayed_reference_; + pform_name_t* delayed_data_; +}; + +/* +* The PSetupHold is the parse of a $setuphold timing check +*/ +class PSetupHold : public PTimingCheck { + + public: + PSetupHold(event_t reference_event, + event_t data_event, + //PExpr setup_limit, + //PExpr hold_limit, + pform_name_t* notifier, + pform_name_t* timestamp_cond, + pform_name_t* timecheck_cond, + pform_name_t* delayed_reference, + pform_name_t* delayed_data); + + ~PSetupHold(); + + void elaborate(class Design*des, class NetScope*scope) const override; + + void dump(std::ostream&out, unsigned ind) const override; + + public: // TODO + event_t reference_event_; // hierarchy_identifier + event_t data_event_; + + //PExpr setup_limit; + //PExpr hold_limit; + + pform_name_t* notifier_; + + pform_name_t* timestamp_cond_; + pform_name_t* timecheck_cond_; + + pform_name_t* delayed_reference_; + pform_name_t* delayed_data_; +}; + +#endif /* IVL_PTimingCheck_H */ diff --git a/elaborate.cc b/elaborate.cc index 0ee0656c4c..4f31941999 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -41,6 +41,7 @@ # include "PPackage.h" # include "PScope.h" # include "PSpec.h" +# include "PTimingCheck.h" # include "netlist.h" # include "netenum.h" # include "netvector.h" @@ -6308,6 +6309,140 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const } } +void PRecRem::elaborate(Design*des, NetScope*scope) const +{ + // At present, no timing checks are supported. + // Still, in order to get some models working + // assign the original reference and data signals to + // the delayed reference and data signals as per + // 15.5.4 Option behavior + + if (delayed_reference_ != nullptr) + { + if (debug_elaborate) { + cerr << get_fileline() << ": PRecRem::elaborate: Assigning" + << reference_event_.name + << " to " << *delayed_reference_ << endl; + } + + NetNet*sig = des->find_signal(scope, reference_event_.name); + + if (sig == nullptr) { + cerr << get_fileline() << ": error: Cannot find: " + << reference_event_.name << endl; + des->errors += 1; + return; + } + + NetNet*sig_delayed = des->find_signal(scope, *delayed_reference_); + + if (sig_delayed == nullptr) { + cerr << get_fileline() << ": error: Cannot find: " + << *delayed_reference_ << endl; + des->errors += 1; + return; + } + + connect(sig->pin(0), sig_delayed->pin(0)); + } + + if (delayed_data_ != nullptr) + { + if (debug_elaborate) { + cerr << get_fileline() << ": PRecRem::elaborate: Assigning" + << reference_event_.name + << " to " << *delayed_reference_ << endl; + } + + NetNet*sig = des->find_signal(scope, data_event_.name); + + if (sig == nullptr) { + cerr << get_fileline() << ": error: Cannot find: " + << data_event_.name << endl; + des->errors += 1; + return; + } + + NetNet*sig_delayed = des->find_signal(scope, *delayed_data_); + + if (sig_delayed == nullptr) { + cerr << get_fileline() << ": error: Cannot find: " + << *delayed_data_ << endl; + des->errors += 1; + return; + } + + connect(sig->pin(0), sig_delayed->pin(0)); + } +} + +void PSetupHold::elaborate(Design*des, NetScope*scope) const +{ + // At present, no timing checks are supported. + // Still, in order to get some models working + // assign the original reference and data signals to + // the delayed reference and data signals as per + // 15.5.4 Option behavior + + if (delayed_reference_ != nullptr) + { + if (debug_elaborate) { + cerr << get_fileline() << ": PSetupHold::elaborate: Assigning" + << reference_event_.name + << " to " << *delayed_reference_ << endl; + } + + NetNet*sig = des->find_signal(scope, reference_event_.name); + + if (sig == nullptr) { + cerr << get_fileline() << ": error: Cannot find: " + << reference_event_.name << endl; + des->errors += 1; + return; + } + + NetNet*sig_delayed = des->find_signal(scope, *delayed_reference_); + + if (sig_delayed == nullptr) { + cerr << get_fileline() << ": error: Cannot find: " + << *delayed_reference_ << endl; + des->errors += 1; + return; + } + + connect(sig->pin(0), sig_delayed->pin(0)); + } + + if (delayed_data_ != nullptr) + { + if (debug_elaborate) { + cerr << get_fileline() << ": PSetupHold::elaborate: Assigning" + << reference_event_.name + << " to " << *delayed_reference_ << endl; + } + + NetNet*sig = des->find_signal(scope, data_event_.name); + + if (sig == nullptr) { + cerr << get_fileline() << ": error: Cannot find: " + << data_event_.name << endl; + des->errors += 1; + return; + } + + NetNet*sig_delayed = des->find_signal(scope, *delayed_data_); + + if (sig_delayed == nullptr) { + cerr << get_fileline() << ": error: Cannot find: " + << *delayed_data_ << endl; + des->errors += 1; + return; + } + + connect(sig->pin(0), sig_delayed->pin(0)); + } +} + static void elaborate_functions(Design*des, NetScope*scope, const map&funcs) { @@ -6421,13 +6556,19 @@ bool Module::elaborate(Design*des, NetScope*scope) const result_flag &= elaborate_behaviors_(des, scope); // Elaborate the specify paths of the module. - for (list::const_iterator sp = specify_paths.begin() ; sp != specify_paths.end() ; ++ sp ) { (*sp)->elaborate(des, scope); } + // Elaborate the timing checks of the module. + for (list::const_iterator tc = timing_checks.begin() + ; tc != timing_checks.end() ; ++ tc ) { + + (*tc)->elaborate(des, scope); + } + // Elaborate the elaboration tasks. for (list::const_iterator et = elab_tasks.begin() ; et != elab_tasks.end() ; ++ et ) { diff --git a/parse.y b/parse.y index b7f880b8c8..bc34c57fb5 100644 --- a/parse.y +++ b/parse.y @@ -28,6 +28,7 @@ # include "pform.h" # include "Statement.h" # include "PSpec.h" +# include "PTimingCheck.h" # include "PPackage.h" # include # include @@ -87,13 +88,6 @@ static pform_name_t* pform_create_super(void) return res; } -/* This is used to keep track of the extra arguments after the notifier - * in the $setuphold and $recrem timing checks. This allows us to print - * a warning message that the delayed signals will not be created. We - * need to do this since not driving these signals creates real - * simulation issues. */ -static unsigned args_after_notifier; - /* The rules sometimes push attributes into a global context where sub-rules may grab them. This makes parser rules a little easier to write in some cases. */ @@ -530,6 +524,8 @@ Module::port_t *module_declare_port(const YYLTYPE&loc, char *id, PSpecPath* specpath; std::list *dimensions; + PTimingCheck::event_t* timing_check_event; + LexicalScope::lifetime_t lifetime; enum typedef_t::basic_type typedef_basic_type; @@ -696,6 +692,9 @@ Module::port_t *module_declare_port(const YYLTYPE&loc, char *id, %type let_port_item %type hierarchy_identifier implicit_class_handle class_hierarchy_identifier +%type spec_notifier_opt spec_notifier spec_condition_opt +%type spec_condition spec_delayed_opt spec_delayed +%type spec_reference_event %type assignment_pattern expression expr_mintypmax %type expr_primary_or_typename expr_primary %type class_new dynamic_array_new @@ -5900,72 +5899,167 @@ specify_item yyerrok; } | K_Sfullskew '(' spec_reference_event ',' spec_reference_event - ',' delay_value ',' delay_value spec_notifier_opt ')' ';' - { delete $7; - delete $9; + ',' delay_value ',' delay_value spec_notifier_opt /* TODO event_based_flag remain_active_flag */ ')' ';' + { + cerr << @3 << ": warning: Timing checks are not supported." << endl; + delete $3; // spec_reference_event + delete $5; // spec_reference_event + delete $7; // delay_value + delete $9; // delay_value + if($10) delete $10; // spec_notifier_opt } | K_Shold '(' spec_reference_event ',' spec_reference_event ',' delay_value spec_notifier_opt ')' ';' - { delete $7; + { + cerr << @3 << ": warning: Timing checks are not supported." << endl; + delete $3; // spec_reference_event + delete $5; // spec_reference_event + delete $7; // delay_value + if($8) delete $8; // spec_notifier_opt } | K_Snochange '(' spec_reference_event ',' spec_reference_event ',' delay_value ',' delay_value spec_notifier_opt ')' ';' - { delete $7; - delete $9; + { + cerr << @3 << ": warning: Timing checks are not supported." << endl; + delete $3; // spec_reference_event + delete $5; // spec_reference_event + delete $7; // delay_value + delete $9; // delay_value + if($10) delete $10; // spec_notifier_opt } | K_Speriod '(' spec_reference_event ',' delay_value spec_notifier_opt ')' ';' - { delete $5; + { + cerr << @3 << ": warning: Timing checks are not supported." << endl; + delete $3; // spec_reference_event + delete $5; // delay_value + if($6) delete $6; // spec_notifier_opt } | K_Srecovery '(' spec_reference_event ',' spec_reference_event ',' delay_value spec_notifier_opt ')' ';' - { delete $7; + { + cerr << @3 << ": warning: Timing checks are not supported." << endl; + delete $3; // spec_reference_event + delete $5; // spec_reference_event + delete $7; // delay_value + if($8) delete $8; // spec_notifier_opt } | K_Srecrem '(' spec_reference_event ',' spec_reference_event - ',' delay_value ',' delay_value spec_notifier_opt ')' ';' - { delete $7; - delete $9; + ',' expr_mintypmax ',' expr_mintypmax spec_notifier_opt spec_condition_opt + spec_condition_opt spec_delayed_opt spec_delayed_opt ')' ';' + { + cerr << @3 << ": warning: Timing checks are not supported. "; + if ($13 != nullptr || $14 != nullptr) + { + cerr << "Delayed reference and data signals become copies of the" + << " original reference and data signals." << endl; + } + else + { + cerr << endl; + } + + PRecRem*rec_rem = pform_make_rec_rem(@1, *$3, *$5, *$7, *$9, $10, $11, $12, $13, $14); + pform_module_timing_check((PTimingCheck*)rec_rem); + + delete $3; // spec_reference_event + delete $5; // spec_reference_event + delete $7; // delay_value + delete $9; // delay_value } | K_Sremoval '(' spec_reference_event ',' spec_reference_event ',' delay_value spec_notifier_opt ')' ';' - { delete $7; + { + cerr << @3 << ": warning: Timing checks are not supported." << endl; + delete $3; // spec_reference_event + delete $5; // spec_reference_event + delete $7; // delay_value + if($8) delete $8; // spec_notifier_opt } | K_Ssetup '(' spec_reference_event ',' spec_reference_event ',' delay_value spec_notifier_opt ')' ';' - { delete $7; + { + cerr << @3 << ": warning: Timing checks are not supported." << endl; + delete $3; // spec_reference_event + delete $5; // spec_reference_event + delete $7; // delay_value + if($8) delete $8; // spec_notifier_opt } | K_Ssetuphold '(' spec_reference_event ',' spec_reference_event - ',' delay_value ',' delay_value spec_notifier_opt ')' ';' - { delete $7; - delete $9; + ',' expr_mintypmax ',' expr_mintypmax spec_notifier_opt spec_condition_opt + spec_condition_opt spec_delayed_opt spec_delayed_opt ')' ';' + { + cerr << @3 << ": warning: Timing checks are not supported. "; + if ($13 != nullptr || $14 != nullptr) + { + cerr << "Delayed reference and data signals become copies of the" + << " original reference and data signals." << endl; + } + else + { + cerr << endl; + } + + PSetupHold*setup_hold = pform_make_setup_hold(@1, *$3, *$5, *$7, *$9, $10, $11, $12, $13, $14); + pform_module_timing_check((PTimingCheck*)setup_hold); + + delete $3; // spec_reference_event + delete $5; // spec_reference_event + delete $7; // delay_value + delete $9; // delay_value } | K_Sskew '(' spec_reference_event ',' spec_reference_event ',' delay_value spec_notifier_opt ')' ';' - { delete $7; + { + cerr << @3 << ": warning: Timing checks are not supported." << endl; + delete $3; // spec_reference_event + delete $5; // spec_reference_event + delete $7; // delay_value + if($8) delete $8; // spec_notifier_opt } | K_Stimeskew '(' spec_reference_event ',' spec_reference_event - ',' delay_value spec_notifier_opt ')' ';' - { delete $7; + ',' delay_value spec_notifier_opt /* TODO event_based_flag remain_active_flag */ ')' ';' + { + cerr << @3 << ": warning: Timing checks are not supported." << endl; + delete $3; // spec_reference_event + delete $5; // spec_reference_event + delete $7; // delay_value + if($8) delete $8; // spec_notifier_opt } | K_Swidth '(' spec_reference_event ',' delay_value ',' expression spec_notifier_opt ')' ';' - { delete $5; - delete $7; + { + cerr << @3 << ": warning: Timing checks are not supported." << endl; + delete $3; // spec_reference_event + delete $5; // delay_value + delete $7; // expression + if($8) delete $8; } | K_Swidth '(' spec_reference_event ',' delay_value ')' ';' - { delete $5; + { + cerr << @3 << ": warning: Timing checks are not supported." << endl; + delete $3; // spec_reference_event + delete $5; // delay_value } | K_pulsestyle_onevent specify_path_identifiers ';' - { delete $2; + { + cerr << @3 << ": warning: Timing checks are not supported." << endl; + delete $2; // specify_path_identifiers } | K_pulsestyle_ondetect specify_path_identifiers ';' - { delete $2; + { + cerr << @3 << ": warning: Timing checks are not supported." << endl; + delete $2; // specify_path_identifiers } | K_showcancelled specify_path_identifiers ';' - { delete $2; + { + cerr << @3 << ": warning: Timing checks are not supported." << endl; + delete $2; // specify_path_identifiers } | K_noshowcancelled specify_path_identifiers ';' - { delete $2; + { + cerr << @3 << ": warning: Timing checks are not supported." << endl; + delete $2; // specify_path_identifiers } ; @@ -6110,47 +6204,8 @@ specify_path_identifiers ; specparam - : IDENTIFIER '=' expression - { PExpr*tmp = $3; - pform_set_specparam(@1, lex_strings.make($1), specparam_active_range, tmp); - delete[]$1; - } - | IDENTIFIER '=' expression ':' expression ':' expression - { PExpr*tmp = 0; - switch (min_typ_max_flag) { - case MIN: - tmp = $3; - delete $5; - delete $7; - break; - case TYP: - delete $3; - tmp = $5; - delete $7; - break; - case MAX: - delete $3; - delete $5; - tmp = $7; - break; - } - if (min_typ_max_warn > 0) { - cerr << tmp->get_fileline() << ": warning: Choosing "; - switch (min_typ_max_flag) { - case MIN: - cerr << "min"; - break; - case TYP: - cerr << "typ"; - break; - case MAX: - cerr << "max"; - break; - } - cerr << " expression." << endl; - min_typ_max_warn -= 1; - } - pform_set_specparam(@1, lex_strings.make($1), specparam_active_range, tmp); + : IDENTIFIER '=' expr_mintypmax + { pform_set_specparam(@1, lex_strings.make($1), specparam_active_range, $3); delete[]$1; } | PATHPULSE_IDENTIFIER '=' expression @@ -6183,31 +6238,82 @@ spec_polarity | { $$ = 0; } ; +// TODO spec_controlled_reference_event spec_reference_event - : K_posedge expression - { delete $2; } - | K_negedge expression - { delete $2; } - | K_posedge expr_primary K_TAND expression - { delete $2; - delete $4; - } - | K_negedge expr_primary K_TAND expression - { delete $2; - delete $4; - } - | K_edge '[' edge_descriptor_list ']' expr_primary - { delete $5; } - | K_edge '[' edge_descriptor_list ']' expr_primary K_TAND expression - { delete $5; - delete $7; - } - | expr_primary K_TAND expression - { delete $1; - delete $3; + : hierarchy_identifier + { PTimingCheck::event_t* event = new PTimingCheck::event_t; + event->name = *$1; + event->posedge = false; + event->negedge = false; + event->condition = nullptr; + delete $1; + $$ = event; + } + | hierarchy_identifier K_TAND expression + { PTimingCheck::event_t* event = new PTimingCheck::event_t; + event->name = *$1; + event->posedge = false; + event->negedge = false; + event->condition = $3; + delete $1; + $$ = event; + } + | K_posedge hierarchy_identifier + { PTimingCheck::event_t* event = new PTimingCheck::event_t; + event->name = *$2; + event->posedge = true; + event->negedge = false; + event->condition = nullptr; + delete $2; + $$ = event; + } + | K_negedge hierarchy_identifier + { PTimingCheck::event_t* event = new PTimingCheck::event_t; + event->name = *$2; + event->posedge = false; + event->negedge = true; + event->condition = nullptr; + delete $2; + $$ = event; + } + | K_posedge hierarchy_identifier K_TAND expression + { PTimingCheck::event_t* event = new PTimingCheck::event_t; + event->name = *$2; + event->posedge = true; + event->negedge = false; + event->condition = $4; + delete $2; + $$ = event; + } + | K_negedge hierarchy_identifier K_TAND expression + { PTimingCheck::event_t* event = new PTimingCheck::event_t; + event->name = *$2; + event->posedge = false; + event->negedge = true; + event->condition = $4; + delete $2; + $$ = event; + } + | K_edge '[' edge_descriptor_list ']' hierarchy_identifier + { PTimingCheck::event_t* event = new PTimingCheck::event_t; + event->name = *$5; + event->posedge = false; + event->negedge = false; + // TODO add edge descriptors + event->condition = nullptr; + delete $5; + $$ = event; + } + | K_edge '[' edge_descriptor_list ']' hierarchy_identifier K_TAND expression + { PTimingCheck::event_t* event = new PTimingCheck::event_t; + event->name = *$5; + event->posedge = false; + event->negedge = false; + // TODO add edge descriptors + event->condition = $7; + delete $5; + $$ = event; } - | expr_primary - { delete $1; } ; /* The edge_descriptor is detected by the lexor as the various @@ -6221,29 +6327,44 @@ edge_descriptor_list spec_notifier_opt : /* empty */ - { } + { $$ = 0; } | spec_notifier - { } + { $$ = $1; } ; + spec_notifier : ',' - { args_after_notifier = 0; } + { $$ = 0; } | ',' hierarchy_identifier - { args_after_notifier = 0; delete $2; } - | spec_notifier ',' - { args_after_notifier += 1; } - | spec_notifier ',' hierarchy_identifier - { args_after_notifier += 1; - if (args_after_notifier >= 3) { - cerr << @3 << ": warning: Timing checks are not supported " - "and delayed signal \"" << *$3 - << "\" will not be driven." << endl; - } - delete $3; - } - /* How do we match this path? */ - | IDENTIFIER - { args_after_notifier = 0; delete[]$1; } + { $$ = $2; } + ; + +spec_condition_opt + : /* empty */ + { $$ = 0; } + | spec_condition + { $$ = $1; } + ; + +spec_condition + : ',' + { $$ = 0; } + | ',' hierarchy_identifier + { $$ = $2; } + ; + +spec_delayed_opt + : /* empty */ + { $$ = 0; } + | spec_delayed + { $$ = $1; } + ; + +spec_delayed + : ',' + { $$ = 0; } + | ',' hierarchy_identifier + { $$ = $2; } ; subroutine_call diff --git a/pform.cc b/pform.cc index 234134d887..39adddc04d 100644 --- a/pform.cc +++ b/pform.cc @@ -32,6 +32,7 @@ # include "PGenerate.h" # include "PModport.h" # include "PSpec.h" +# include "PTimingCheck.h" # include "discipline.h" # include # include @@ -3109,6 +3110,72 @@ extern void pform_module_specify_path(PSpecPath*obj) pform_cur_module.front()->specify_paths.push_back(obj); } +/* + * Timing checks. + */ + extern PRecRem* pform_make_rec_rem(const struct vlltype&li, + PTimingCheck::event_t&reference_event, + PTimingCheck::event_t&data_event, + PExpr&setup_limit, + PExpr&hold_limit, + pform_name_t* notifier, + pform_name_t* timestamp_cond, + pform_name_t* timecheck_cond, + pform_name_t* delayed_reference, + pform_name_t* delayed_data) +{ + PRecRem*rec_rem = new PRecRem( + reference_event, + data_event, + //setup_limit, + //hold_limit, + notifier, + timestamp_cond, + timecheck_cond, + delayed_reference, + delayed_data + ); + + FILE_NAME(rec_rem, li); + + return rec_rem; +} +extern PSetupHold* pform_make_setup_hold(const struct vlltype&li, + PTimingCheck::event_t&reference_event, + PTimingCheck::event_t&data_event, + PExpr&setup_limit, + PExpr&hold_limit, + pform_name_t* notifier, + pform_name_t* timestamp_cond, + pform_name_t* timecheck_cond, + pform_name_t* delayed_reference, + pform_name_t* delayed_data) +{ + PSetupHold*setup_hold = new PSetupHold( + reference_event, + data_event, + //setup_limit, + //hold_limit, + notifier, + timestamp_cond, + timecheck_cond, + delayed_reference, + delayed_data + ); + + FILE_NAME(setup_hold, li); + + return setup_hold; +} + +extern void pform_module_timing_check(PTimingCheck*obj) +{ + if (obj == 0) + return; + + pform_cur_module.front()->timing_checks.push_back(obj); +} + void pform_set_port_type(const struct vlltype&li, list*ports, diff --git a/pform.h b/pform.h index f88513f035..a8fdb69e87 100644 --- a/pform.h +++ b/pform.h @@ -30,6 +30,7 @@ # include "PTask.h" # include "PUdp.h" # include "PWire.h" +# include "PTimingCheck.h" # include "verinum.h" # include "discipline.h" # include @@ -429,6 +430,33 @@ extern PSpecPath*pform_assign_path_delay(PSpecPath*obj, std::list*delays extern void pform_module_specify_path(PSpecPath*obj); +/* + * Functions related to timing checks. + */ +extern PRecRem* pform_make_rec_rem(const struct vlltype&li, + PTimingCheck::event_t&reference_event, + PTimingCheck::event_t&data_event, + PExpr&setup_limit, + PExpr&hold_limit, + pform_name_t* notifier, + pform_name_t* timestamp_cond, + pform_name_t* timecheck_cond, + pform_name_t* delayed_reference, + pform_name_t* delayed_data + ); +extern PSetupHold* pform_make_setup_hold(const struct vlltype&li, + PTimingCheck::event_t&reference_event, + PTimingCheck::event_t&data_event, + PExpr&setup_limit, + PExpr&hold_limit, + pform_name_t* notifier, + pform_name_t* timestamp_cond, + pform_name_t* timecheck_cond, + pform_name_t* delayed_reference, + pform_name_t* delayed_data + ); +extern void pform_module_timing_check(PTimingCheck*obj); + /* * pform_make_behavior creates processes that are declared with always * or initial items. diff --git a/pform_dump.cc b/pform_dump.cc index 4f1e5391c9..86ab8a62d4 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -1442,6 +1442,16 @@ void PSpecPath::dump(std::ostream&out, unsigned ind) const out << ");" << endl; } +void PRecRem::dump(std::ostream&out, unsigned ind) const +{ + out << setw(ind) << "" << "recrem "; +} + +void PSetupHold::dump(std::ostream&out, unsigned ind) const +{ + out << setw(ind) << "" << "setuphold "; +} + void PGenerate::dump(ostream&out, unsigned indent) const { out << setw(indent) << "" << "generate(" << id_number << ")"; @@ -1704,6 +1714,17 @@ void Module::dump_specparams_(ostream&out, unsigned indent) const } } +void Module::dump_timingchecks_(ostream&out, unsigned indent) const +{ + cout << "dump_timingchecks_" << endl; + + typedef list::const_iterator tcheck_iter_t; + for (tcheck_iter_t cur = timing_checks.begin() + ; cur != timing_checks.end() ; ++ cur ) { + (*cur)->dump(out, indent); + } +} + void Module::dump(ostream&out) const { if (attributes.begin() != attributes.end()) { @@ -1752,6 +1773,8 @@ void Module::dump(ostream&out) const dump_specparams_(out, 4); + dump_timingchecks_(out, 4); + dump_enumerations_(out, 4); dump_classes_(out, 4); From 21b73eb187b41fabe52dffe1f7bb5a16cb407584 Mon Sep 17 00:00:00 2001 From: mole99 Date: Wed, 5 Jul 2023 16:23:15 +0200 Subject: [PATCH 2/9] Add test for parsing timing checks --- ivtest/ivltests/timing_check_syntax.v | 118 ++++++++++++++++++++++ ivtest/vvp_tests/timing_check_syntax.json | 4 + 2 files changed, 122 insertions(+) create mode 100644 ivtest/ivltests/timing_check_syntax.v create mode 100644 ivtest/vvp_tests/timing_check_syntax.json diff --git a/ivtest/ivltests/timing_check_syntax.v b/ivtest/ivltests/timing_check_syntax.v new file mode 100644 index 0000000000..da2cc4f7a8 --- /dev/null +++ b/ivtest/ivltests/timing_check_syntax.v @@ -0,0 +1,118 @@ +// Check that various timing checks can be parsed + +module test; + + initial begin + $display("PASSED"); + end + + wire sig1, sig2, del_sig1, del_sig2, notifier, cond1, cond2; + + specify + $setup(posedge sig1 , negedge sig2 , 0:0:0); + $setup(negedge sig1 , posedge sig2 , 0:0:0); + $setup(posedge sig1 &&& cond1 == cond2 , posedge sig2 &&& cond1 == cond2 , 0:0:0 , notifier); + $setup(negedge sig1 &&& cond1 == cond2 , negedge sig2 &&& cond1 == cond2 , 0:0:0 , notifier); + $setup(posedge sig1, negedge sig2 , 0:0:0 , notifier); + $setup(edge[10, x0, 1x] sig1 , posedge sig2 , 0:0:0 , notifier); + $setup(posedge sig1 , edge[10, x0, 1x] sig2 , 0:0:0 , notifier); + + $hold(posedge sig1 , negedge sig2 , 0:0:0); + $hold(negedge sig1 , posedge sig2 , 0:0:0); + $hold(posedge sig1 &&& cond1 == cond2 , posedge sig2 &&& cond1 == cond2 , 0:0:0 , notifier); + $hold(negedge sig1 &&& cond1 == cond2 , negedge sig2 &&& cond1 == cond2 , 0:0:0 , notifier); + $hold(posedge sig1, negedge sig2 , 0:0:0 , notifier); + $hold(edge[10, x0, 1x] sig1 , posedge sig2 , 0:0:0 , notifier); + $hold(posedge sig1 , edge[10, x0, 1x] sig2 , 0:0:0 , notifier); + + $setuphold(posedge sig1 , negedge sig2 , 0:0:0 , 0:0:0 , notifier); + $setuphold(negedge sig1 , posedge sig2 , 0:0:0 , 0:0:0 , notifier); + $setuphold(posedge sig1 &&& cond1 == cond2 , posedge sig2 &&& cond1 == cond2 , 0:0:0 , 0:0:0 , notifier); + $setuphold(negedge sig1 &&& cond1 == cond2 , negedge sig2 &&& cond1 == cond2 , 0:0:0 , 0:0:0 , notifier); + $setuphold(posedge sig1, negedge sig2 , 0:0:0 , 0:0:0 , notifier); + $setuphold(posedge sig1, negedge sig2 , 0:0:0 , 0:0:0 , notifier, cond1 , cond2) ; + $setuphold(posedge sig1, negedge sig2 , 0:0:0 , 0:0:0 , notifier, cond1 , cond2 , del_sig1 , del_sig2 ) ; + $setuphold(posedge sig1, negedge sig2 , 0:0:0 , 0:0:0 , notifier,,, del_sig1 , del_sig2 ) ; + $setuphold(posedge sig1, negedge sig2 , 0:0:0 , 0:0:0 , notifier,,, del_sig1 , del_sig2 ) ; + $setuphold(posedge sig1, negedge sig2 , 0:0:0 , 0:0:0 , notifier,,,, del_sig2 ) ; + $setuphold(posedge sig1, negedge sig2 , 0:0:0 , 0:0:0 , notifier,,, del_sig1 ,) ; + $setuphold(edge [10, x0, 1x] sig1 , posedge sig2 , 0:0:0 , 0:0:0 , notifier); + $setuphold(posedge sig1 , edge [10, x0, 1x] sig2 , 0:0:0 , 0:0:0 , notifier); + + $removal(posedge sig1 , negedge sig2 , 0:0:0); + $removal(negedge sig1 , posedge sig2 , 0:0:0); + $removal(posedge sig1 &&& cond1 == cond2 , posedge sig2 &&& cond1 == cond2 , 0:0:0 , notifier); + $removal(negedge sig1 &&& cond1 == cond2 , negedge sig2 &&& cond1 == cond2 , 0:0:0 , notifier); + $removal(posedge sig1, negedge sig2 , 0:0:0 , notifier); + $removal(edge[10, x0, 1x] sig1 , posedge sig2 , 0:0:0 , notifier); + $removal(posedge sig1 , edge[10, x0, 1x] sig2 , 0:0:0 , notifier); + + $recovery(posedge sig1 , negedge sig2 , 0:0:0); + $recovery(negedge sig1 , posedge sig2 , 0:0:0); + $recovery(posedge sig1 &&& cond1 == cond2 , posedge sig2 &&& cond1 == cond2 , 0:0:0 , notifier); + $recovery(negedge sig1 &&& cond1 == cond2 , negedge sig2 &&& cond1 == cond2 , 0:0:0 , notifier); + $recovery(posedge sig1, negedge sig2 , 0:0:0 , notifier); + $recovery(edge[10, x0, 1x] sig1 , posedge sig2 , 0:0:0 , notifier); + $recovery(posedge sig1 , edge[10, x0, 1x] sig2 , 0:0:0 , notifier); + + $recrem(posedge sig1 , negedge sig2 , 0:0:0 , 0:0:0); + $recrem(negedge sig1 , posedge sig2 , 0:0:0 , 0:0:0); + $recrem(posedge sig1 &&& cond1 == cond2 , posedge sig2 &&& cond1 == cond2 , 0:0:0 , 0:0:0 , notifier); + $recrem(negedge sig1 &&& cond1 == cond2 , negedge sig2 &&& cond1 == cond2 , 0:0:0 , 0:0:0 , notifier); + $recrem(posedge sig1, negedge sig2 , 0:0:0 , 0:0:0 , notifier); + $recrem(posedge sig1, negedge sig2 , 0:0:0 , 0:0:0 , notifier, cond1 , cond2); + $recrem(posedge sig1, negedge sig2 , 0:0:0 , 0:0:0 , notifier, cond1 , cond2 , del_sig1 , del_sig2 ); + $recrem(posedge sig1, negedge sig2 , 0:0:0 , 0:0:0 , notifier,,, del_sig1 , del_sig2 ); + $recrem(posedge sig1, negedge sig2 , 0:0:0 , 0:0:0 , notifier,,, del_sig1 , del_sig2 ); + $recrem(posedge sig1, negedge sig2 , 0:0:0 , 0:0:0 , notifier,,,, del_sig2 ); + $recrem(posedge sig1, negedge sig2 , 0:0:0 , 0:0:0 , notifier,,, del_sig1 ,); + $recrem(edge[10, x0, 1x] sig1 , posedge sig2 , 0:0:0 , 0:0:0 , notifier); + $recrem(posedge sig1 , edge[10, x0, 1x] sig2 , 0:0:0 , 0:0:0 , notifier); + + $skew(posedge sig1 , negedge sig2 , 0:0:0); + $skew(negedge sig1 , posedge sig2 , 0:0:0); + $skew(posedge sig1 &&& cond1 == cond2 , posedge sig2 &&& cond1 == cond2 , 0:0:0 , notifier); + $skew(negedge sig1 &&& cond1 == cond2 , negedge sig2 &&& cond1 == cond2 , 0:0:0 , notifier); + $skew(posedge sig1, negedge sig2 , 0:0:0 , notifier); + $skew(edge[10, x0, 1x] sig1 , posedge sig2 , 0:0:0 , notifier); + $skew(posedge sig1 , edge[10, x0, 1x] sig2 , 0:0:0 , notifier); + + $timeskew(posedge sig1 , negedge sig2 , 0:0:0); + $timeskew(negedge sig1 , posedge sig2 , 0:0:0); + $timeskew(posedge sig1 &&& cond1 == cond2 , posedge sig2 &&& cond1 == cond2 , 0:0:0 , notifier); + $timeskew(negedge sig1 &&& cond1 == cond2 , negedge sig2 &&& cond1 == cond2 , 0:0:0 , notifier); + $timeskew(posedge sig1, negedge sig2 , 0:0:0 , notifier); + $timeskew(edge[10, x0, 1x] sig1 , posedge sig2 , 0:0:0 , notifier); + $timeskew(posedge sig1 , edge[10, x0, 1x] sig2 , 0:0:0 , notifier); + // TODO $timeskew(posedge sig1 , negedge sig2 , 0:0:0, notifier , 1'b0); + // TODO $timeskew(negedge sig1 , posedge sig2 , 0:0:0 , 1'b1 , 1'b0); + // TODO $timeskew(negedge sig1 , posedge sig2 , 0:0:0 , , 1'b1); + + $fullskew(posedge sig1 , negedge sig2 , 0:0:0 , 0:0:0); + $fullskew(negedge sig1 , posedge sig2 , 0:0:0 , 0:0:0); + $fullskew(posedge sig1 &&& cond1 == cond2 , posedge sig2 &&& cond1 == cond2 , 0:0:0 , 0:0:0 , notifier); + $fullskew(negedge sig1 &&& cond1 == cond2 , negedge sig2 &&& cond1 == cond2 , 0:0:0 , 0:0:0 , notifier); + $fullskew(posedge sig1, negedge sig2 , 0:0:0 , 0:0:0 , notifier); + $fullskew(edge[10, x0, 1x] sig1 , posedge sig2 , 0:0:0 , 0:0:0 , notifier); + $fullskew(posedge sig1 , edge[10, x0, 1x] sig2 , 0:0:0 , 0:0:0 , notifier); + // TODO $fullskew(posedge sig1 , negedge sig2 , 0:0:0, notifier , 1'b0); + // TODO $fullskew(negedge sig1 , posedge sig2 , 0:0:0 , 1'b1 , 1'b0); + // TODO $fullskew(negedge sig1 , posedge sig2 , 0:0:0 , , 1'b1); + + $width(posedge sig1 , 0:0:0 ); + $width(posedge sig1 &&& cond1 , 0:0:0 , 0 ); + $width(posedge sig1 &&& cond1 , 0:0:0 , 0 , notifier ); + $width(edge[10, x0, 1x] sig1 &&& cond1 , 0:0:0 ); + + $period(posedge sig1 , 0:0:0 ); + $period(negedge sig1 &&& cond1 , 0:0:0 , notifier ); + $period(edge[10, x0, 1x] sig1 &&& cond1 , 0:0:0 ); + + $nochange(posedge sig1 , posedge sig2 , 10 , 20 ); + $nochange(negedge sig1 &&& cond1 , posedge sig2 , 10 , 20 ); + $nochange(negedge sig1 , posedge sig2 &&& cond1 , 10 , 20 , notifier ); + $nochange(edge[10, x0, 1x] sig1 &&& cond1 , posedge sig2 , 10 , 20 ); + $nochange(posedge sig1 &&& cond1 , edge[10, x0, 1x] sig2 , 10 , 20 ); + + endspecify +endmodule diff --git a/ivtest/vvp_tests/timing_check_syntax.json b/ivtest/vvp_tests/timing_check_syntax.json new file mode 100644 index 0000000000..8b6df22fae --- /dev/null +++ b/ivtest/vvp_tests/timing_check_syntax.json @@ -0,0 +1,4 @@ +{ + "type" : "normal", + "source" : "timing_check_syntax.v" +} From 7aabcc113ed4a7d6c52b24d43fb182e9756c601c Mon Sep 17 00:00:00 2001 From: mole99 Date: Wed, 5 Jul 2023 16:24:04 +0200 Subject: [PATCH 3/9] Add test for delayed signals in timing checks --- .../ivltests/timing_check_delayed_signals.v | 39 +++++++++++++++++++ ivtest/regress-vvp.list | 2 + .../timing_check_delayed_signals.json | 4 ++ 3 files changed, 45 insertions(+) create mode 100644 ivtest/ivltests/timing_check_delayed_signals.v create mode 100644 ivtest/vvp_tests/timing_check_delayed_signals.json diff --git a/ivtest/ivltests/timing_check_delayed_signals.v b/ivtest/ivltests/timing_check_delayed_signals.v new file mode 100644 index 0000000000..9c0542ce6f --- /dev/null +++ b/ivtest/ivltests/timing_check_delayed_signals.v @@ -0,0 +1,39 @@ +// Check that when timing checks are disabled (or in the case of Icarus Verilog not supported) +// that the delayed reference and data signals become copies of the original reference and data signals + +module test; + + wire sig1, sig2, del_sig1, del_sig2, del_sig3, del_sig4, notifier, cond1, cond2; + + assign sig1 = 1'b0; + assign sig2 = 1'b1; + + specify + + $setuphold(posedge sig1, negedge sig2 , 0:0:0 , 0:0:0 , notifier , cond1 , cond2 , del_sig1 , del_sig2 ) ; + + /* + Internally the simulator does the following: + assign del_sig1 = sig1; + assign del_sig2 = sig2; + */ + + $recrem(posedge sig1, negedge sig2 , 0:0:0 , 0:0:0 , notifier, cond1 , cond2 , del_sig3 , del_sig4 ); + + /* + Internally the simulator does the following: + assign del_sig3 = sig1; + assign del_sig4 = sig2; + */ + + endspecify + + initial begin + + if (del_sig1 == 1'b0 && del_sig2 == 1'b1 && del_sig3 == 1'b0 && del_sig4 == 1'b1) + $display("PASSED"); + else + $display("FAILED"); + end + +endmodule diff --git a/ivtest/regress-vvp.list b/ivtest/regress-vvp.list index fdacfbc4db..05fd8b6d4c 100644 --- a/ivtest/regress-vvp.list +++ b/ivtest/regress-vvp.list @@ -72,3 +72,5 @@ task_return1 vvp_tests/task_return1.json task_return2 vvp_tests/task_return2.json task_return_fail1 vvp_tests/task_return_fail1.json task_return_fail2 vvp_tests/task_return_fail2.json +timing_check_syntax vvp_tests/timing_check_syntax.json +timing_check_delayed_signals vvp_tests/timing_check_delayed_signals.json diff --git a/ivtest/vvp_tests/timing_check_delayed_signals.json b/ivtest/vvp_tests/timing_check_delayed_signals.json new file mode 100644 index 0000000000..b93e39f096 --- /dev/null +++ b/ivtest/vvp_tests/timing_check_delayed_signals.json @@ -0,0 +1,4 @@ +{ + "type" : "normal", + "source" : "timing_check_delayed_signals.v" +} From e54ff22fce9911454e4887528cebe85ec7627707 Mon Sep 17 00:00:00 2001 From: mole99 Date: Wed, 5 Jul 2023 16:50:10 +0200 Subject: [PATCH 4/9] Fix wrong output --- elaborate.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/elaborate.cc b/elaborate.cc index 4f31941999..bebc6399c1 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -6320,7 +6320,7 @@ void PRecRem::elaborate(Design*des, NetScope*scope) const if (delayed_reference_ != nullptr) { if (debug_elaborate) { - cerr << get_fileline() << ": PRecRem::elaborate: Assigning" + cerr << get_fileline() << ": PRecRem::elaborate: Assigning " << reference_event_.name << " to " << *delayed_reference_ << endl; } @@ -6349,9 +6349,9 @@ void PRecRem::elaborate(Design*des, NetScope*scope) const if (delayed_data_ != nullptr) { if (debug_elaborate) { - cerr << get_fileline() << ": PRecRem::elaborate: Assigning" - << reference_event_.name - << " to " << *delayed_reference_ << endl; + cerr << get_fileline() << ": PRecRem::elaborate: Assigning " + << data_event_.name + << " to " << *delayed_data_ << endl; } NetNet*sig = des->find_signal(scope, data_event_.name); From d46628b2f2848e21fe64f205f714cf24db980186 Mon Sep 17 00:00:00 2001 From: mole99 Date: Mon, 10 Jul 2023 15:59:14 +0200 Subject: [PATCH 5/9] Improve parsing of timing checks --- PTimingCheck.cc | 78 ++++---- PTimingCheck.h | 35 ++-- ivtest/ivltests/timing_check_syntax.v | 12 +- parse.y | 253 +++++++++++++++++++++----- pform.cc | 72 ++++---- pform.h | 24 +-- 6 files changed, 325 insertions(+), 149 deletions(-) diff --git a/PTimingCheck.cc b/PTimingCheck.cc index 02ce4bb78a..5ec24bd214 100644 --- a/PTimingCheck.cc +++ b/PTimingCheck.cc @@ -20,29 +20,32 @@ # include "PTimingCheck.h" PRecRem::PRecRem(event_t reference_event, - event_t data_event, - //PExpr setup_limit, - //PExpr hold_limit, - pform_name_t* notifier, - pform_name_t* timestamp_cond, - pform_name_t* timecheck_cond, - pform_name_t* delayed_reference, - pform_name_t* delayed_data) - : - reference_event_ (reference_event), - data_event_ (data_event), - //setup_limit (setup_limit), - //hold_limit (hold_limit), - notifier_ (notifier), - timestamp_cond_ (timestamp_cond), - timecheck_cond_ (timecheck_cond), - delayed_reference_ (delayed_reference), - delayed_data_ (delayed_data) + event_t data_event, + PExpr* setup_limit, + PExpr* hold_limit, + pform_name_t* notifier, + pform_name_t* timestamp_cond, + pform_name_t* timecheck_cond, + pform_name_t* delayed_reference, + pform_name_t* delayed_data) + : + reference_event_ (reference_event), + data_event_ (data_event), + setup_limit_ (setup_limit), + hold_limit_ (hold_limit), + notifier_ (notifier), + timestamp_cond_ (timestamp_cond), + timecheck_cond_ (timecheck_cond), + delayed_reference_ (delayed_reference), + delayed_data_ (delayed_data) { } PRecRem::~PRecRem() { + delete setup_limit_; + delete hold_limit_; + // Delete optional arguments if (reference_event_.condition) delete reference_event_.condition; if (data_event_.condition) delete data_event_.condition; @@ -57,29 +60,32 @@ PRecRem::~PRecRem() } PSetupHold::PSetupHold(event_t reference_event, - event_t data_event, - //PExpr setup_limit, - //PExpr hold_limit, - pform_name_t* notifier, - pform_name_t* timestamp_cond, - pform_name_t* timecheck_cond, - pform_name_t* delayed_reference, - pform_name_t* delayed_data) - : - reference_event_ (reference_event), - data_event_ (data_event), - //setup_limit (setup_limit), - //hold_limit (hold_limit), - notifier_ (notifier), - timestamp_cond_ (timestamp_cond), - timecheck_cond_ (timecheck_cond), - delayed_reference_ (delayed_reference), - delayed_data_ (delayed_data) + event_t data_event, + PExpr* setup_limit, + PExpr* hold_limit, + pform_name_t* notifier, + pform_name_t* timestamp_cond, + pform_name_t* timecheck_cond, + pform_name_t* delayed_reference, + pform_name_t* delayed_data) + : + reference_event_ (reference_event), + data_event_ (data_event), + setup_limit_ (setup_limit), + hold_limit_ (hold_limit), + notifier_ (notifier), + timestamp_cond_ (timestamp_cond), + timecheck_cond_ (timecheck_cond), + delayed_reference_ (delayed_reference), + delayed_data_ (delayed_data) { } PSetupHold::~PSetupHold() { + delete setup_limit_; + delete hold_limit_; + // Delete optional arguments if (reference_event_.condition) delete reference_event_.condition; if (data_event_.condition) delete data_event_.condition; diff --git a/PTimingCheck.h b/PTimingCheck.h index eb98b200a2..a716db122a 100644 --- a/PTimingCheck.h +++ b/PTimingCheck.h @@ -20,10 +20,9 @@ */ # include "LineInfo.h" +# include "PExpr.h" # include "pform_types.h" -// TODO cleanup in destructor and cleanup in Module! - /* * The PTimingCheck is the base class for all timing checks */ @@ -40,6 +39,17 @@ class PTimingCheck : public LineInfo { PExpr* condition; }; + // This struct is used to parse the optional arguments + struct optional_args_t { + pform_name_t* notifier = nullptr; + pform_name_t* timestamp_cond = nullptr; + pform_name_t* timecheck_cond = nullptr; + pform_name_t* delayed_reference = nullptr; + pform_name_t* delayed_data = nullptr; + PExpr* event_based_flag = nullptr; + PExpr* remain_active_flag = nullptr; + }; + PTimingCheck() { } virtual ~PTimingCheck() { } @@ -54,10 +64,11 @@ class PTimingCheck : public LineInfo { class PRecRem : public PTimingCheck { public: + PRecRem(event_t reference_event, event_t data_event, - //PExpr setup_limit, - //PExpr hold_limit, + PExpr* setup_limit, + PExpr* hold_limit, pform_name_t* notifier, pform_name_t* timestamp_cond, pform_name_t* timecheck_cond, @@ -70,12 +81,12 @@ class PRecRem : public PTimingCheck { void dump(std::ostream&out, unsigned ind) const override; - public: // TODO + private: event_t reference_event_; // hierarchy_identifier event_t data_event_; - //PExpr setup_limit; - //PExpr hold_limit; + PExpr* setup_limit_; + PExpr* hold_limit_; pform_name_t* notifier_; @@ -94,8 +105,8 @@ class PSetupHold : public PTimingCheck { public: PSetupHold(event_t reference_event, event_t data_event, - //PExpr setup_limit, - //PExpr hold_limit, + PExpr* setup_limit, + PExpr* hold_limit, pform_name_t* notifier, pform_name_t* timestamp_cond, pform_name_t* timecheck_cond, @@ -108,12 +119,12 @@ class PSetupHold : public PTimingCheck { void dump(std::ostream&out, unsigned ind) const override; - public: // TODO + private: event_t reference_event_; // hierarchy_identifier event_t data_event_; - //PExpr setup_limit; - //PExpr hold_limit; + PExpr* setup_limit_; + PExpr* hold_limit_; pform_name_t* notifier_; diff --git a/ivtest/ivltests/timing_check_syntax.v b/ivtest/ivltests/timing_check_syntax.v index da2cc4f7a8..3ef193ab8c 100644 --- a/ivtest/ivltests/timing_check_syntax.v +++ b/ivtest/ivltests/timing_check_syntax.v @@ -84,9 +84,9 @@ module test; $timeskew(posedge sig1, negedge sig2 , 0:0:0 , notifier); $timeskew(edge[10, x0, 1x] sig1 , posedge sig2 , 0:0:0 , notifier); $timeskew(posedge sig1 , edge[10, x0, 1x] sig2 , 0:0:0 , notifier); - // TODO $timeskew(posedge sig1 , negedge sig2 , 0:0:0, notifier , 1'b0); - // TODO $timeskew(negedge sig1 , posedge sig2 , 0:0:0 , 1'b1 , 1'b0); - // TODO $timeskew(negedge sig1 , posedge sig2 , 0:0:0 , , 1'b1); + $timeskew(posedge sig1 , negedge sig2 , 0:0:0, notifier , 1'b0); + $timeskew(negedge sig1 , posedge sig2 , 0:0:0 , 1'b1 , 1'b0); + $timeskew(negedge sig1 , posedge sig2 , 0:0:0 , , 1'b1); $fullskew(posedge sig1 , negedge sig2 , 0:0:0 , 0:0:0); $fullskew(negedge sig1 , posedge sig2 , 0:0:0 , 0:0:0); @@ -95,9 +95,9 @@ module test; $fullskew(posedge sig1, negedge sig2 , 0:0:0 , 0:0:0 , notifier); $fullskew(edge[10, x0, 1x] sig1 , posedge sig2 , 0:0:0 , 0:0:0 , notifier); $fullskew(posedge sig1 , edge[10, x0, 1x] sig2 , 0:0:0 , 0:0:0 , notifier); - // TODO $fullskew(posedge sig1 , negedge sig2 , 0:0:0, notifier , 1'b0); - // TODO $fullskew(negedge sig1 , posedge sig2 , 0:0:0 , 1'b1 , 1'b0); - // TODO $fullskew(negedge sig1 , posedge sig2 , 0:0:0 , , 1'b1); + $fullskew(posedge sig1 , negedge sig2 , 0:0:0, notifier , 1'b0); + $fullskew(negedge sig1 , posedge sig2 , 0:0:0 , 1'b1 , 1'b0); + $fullskew(negedge sig1 , posedge sig2 , 0:0:0 , , 1'b1); $width(posedge sig1 , 0:0:0 ); $width(posedge sig1 &&& cond1 , 0:0:0 , 0 ); diff --git a/parse.y b/parse.y index bc34c57fb5..d7b63559b4 100644 --- a/parse.y +++ b/parse.y @@ -525,6 +525,7 @@ Module::port_t *module_declare_port(const YYLTYPE&loc, char *id, std::list *dimensions; PTimingCheck::event_t* timing_check_event; + PTimingCheck::optional_args_t* spec_optional_args; LexicalScope::lifetime_t lifetime; @@ -692,9 +693,15 @@ Module::port_t *module_declare_port(const YYLTYPE&loc, char *id, %type let_port_item %type hierarchy_identifier implicit_class_handle class_hierarchy_identifier -%type spec_notifier_opt spec_notifier spec_condition_opt -%type spec_condition spec_delayed_opt spec_delayed +%type spec_notifier_opt spec_notifier %type spec_reference_event +%type setuphold_opt_args recrem_opt_args setuphold_recrem_opt_notifier +%type setuphold_recrem_opt_timestamp_cond setuphold_recrem_opt_timecheck_cond +%type setuphold_recrem_opt_delayed_reference setuphold_recrem_opt_delayed_data +%type timeskew_opt_args fullskew_opt_args +%type timeskew_fullskew_opt_notifier timeskew_fullskew_opt_event_based_flag +%type timeskew_fullskew_opt_remain_active_flag + %type assignment_pattern expression expr_mintypmax %type expr_primary_or_typename expr_primary %type class_new dynamic_array_new @@ -5899,14 +5906,19 @@ specify_item yyerrok; } | K_Sfullskew '(' spec_reference_event ',' spec_reference_event - ',' delay_value ',' delay_value spec_notifier_opt /* TODO event_based_flag remain_active_flag */ ')' ';' + ',' delay_value ',' delay_value fullskew_opt_args ')' ';' { cerr << @3 << ": warning: Timing checks are not supported." << endl; delete $3; // spec_reference_event delete $5; // spec_reference_event delete $7; // delay_value delete $9; // delay_value - if($10) delete $10; // spec_notifier_opt + + if ($10->notifier) delete $10->notifier; + if ($10->event_based_flag) delete $10->event_based_flag; + if ($10->remain_active_flag) delete $10->remain_active_flag; + + delete $10; // fullskew_opt_args } | K_Shold '(' spec_reference_event ',' spec_reference_event ',' delay_value spec_notifier_opt ')' ';' @@ -5945,11 +5957,10 @@ specify_item if($8) delete $8; // spec_notifier_opt } | K_Srecrem '(' spec_reference_event ',' spec_reference_event - ',' expr_mintypmax ',' expr_mintypmax spec_notifier_opt spec_condition_opt - spec_condition_opt spec_delayed_opt spec_delayed_opt ')' ';' + ',' expr_mintypmax ',' expr_mintypmax recrem_opt_args ')' ';' { cerr << @3 << ": warning: Timing checks are not supported. "; - if ($13 != nullptr || $14 != nullptr) + if ($10->delayed_reference != nullptr || $10->delayed_data != nullptr) { cerr << "Delayed reference and data signals become copies of the" << " original reference and data signals." << endl; @@ -5959,13 +5970,12 @@ specify_item cerr << endl; } - PRecRem*rec_rem = pform_make_rec_rem(@1, *$3, *$5, *$7, *$9, $10, $11, $12, $13, $14); - pform_module_timing_check((PTimingCheck*)rec_rem); + PRecRem*recrem = pform_make_recrem(@1, *$3, *$5, $7, $9, $10); + pform_module_timing_check((PTimingCheck*)recrem); delete $3; // spec_reference_event delete $5; // spec_reference_event - delete $7; // delay_value - delete $9; // delay_value + delete $10; // setuphold_recrem_opt_notifier } | K_Sremoval '(' spec_reference_event ',' spec_reference_event ',' delay_value spec_notifier_opt ')' ';' @@ -5986,11 +5996,10 @@ specify_item if($8) delete $8; // spec_notifier_opt } | K_Ssetuphold '(' spec_reference_event ',' spec_reference_event - ',' expr_mintypmax ',' expr_mintypmax spec_notifier_opt spec_condition_opt - spec_condition_opt spec_delayed_opt spec_delayed_opt ')' ';' + ',' expr_mintypmax ',' expr_mintypmax setuphold_opt_args ')' ';' { cerr << @3 << ": warning: Timing checks are not supported. "; - if ($13 != nullptr || $14 != nullptr) + if ($10->delayed_reference != nullptr || $10->delayed_data != nullptr) { cerr << "Delayed reference and data signals become copies of the" << " original reference and data signals." << endl; @@ -6000,13 +6009,12 @@ specify_item cerr << endl; } - PSetupHold*setup_hold = pform_make_setup_hold(@1, *$3, *$5, *$7, *$9, $10, $11, $12, $13, $14); - pform_module_timing_check((PTimingCheck*)setup_hold); + PSetupHold*setuphold = pform_make_setuphold(@1, *$3, *$5, $7, $9, $10); + pform_module_timing_check((PTimingCheck*)setuphold); delete $3; // spec_reference_event delete $5; // spec_reference_event - delete $7; // delay_value - delete $9; // delay_value + delete $10; // setuphold_recrem_opt_notifier } | K_Sskew '(' spec_reference_event ',' spec_reference_event ',' delay_value spec_notifier_opt ')' ';' @@ -6018,13 +6026,18 @@ specify_item if($8) delete $8; // spec_notifier_opt } | K_Stimeskew '(' spec_reference_event ',' spec_reference_event - ',' delay_value spec_notifier_opt /* TODO event_based_flag remain_active_flag */ ')' ';' + ',' delay_value timeskew_opt_args ')' ';' { cerr << @3 << ": warning: Timing checks are not supported." << endl; delete $3; // spec_reference_event delete $5; // spec_reference_event delete $7; // delay_value - if($8) delete $8; // spec_notifier_opt + + if ($8->notifier) delete $8->notifier; + if ($8->event_based_flag) delete $8->event_based_flag; + if ($8->remain_active_flag) delete $8->remain_active_flag; + + delete $8; // timeskew_opt_args } | K_Swidth '(' spec_reference_event ',' delay_value ',' expression spec_notifier_opt ')' ';' @@ -6325,42 +6338,200 @@ edge_descriptor_list | K_edge_descriptor ; -spec_notifier_opt - : /* empty */ - { $$ = 0; } - | spec_notifier - { $$ = $1; } +setuphold_opt_args + : setuphold_recrem_opt_notifier + { $$ = $1; } + | + { $$ = new PTimingCheck::optional_args_t; } ; -spec_notifier - : ',' - { $$ = 0; } - | ',' hierarchy_identifier +recrem_opt_args + : setuphold_recrem_opt_notifier + { $$ = $1; } + | + { $$ = new PTimingCheck::optional_args_t; } + ; + + /* The following rules are used for the optional arguments + in $recrem and $setuphold */ +setuphold_recrem_opt_notifier + : ',' // Empty and end of list + { + PTimingCheck::optional_args_t* args = new PTimingCheck::optional_args_t; + $$ = args; + } + | ',' hierarchy_identifier // End of list + { + PTimingCheck::optional_args_t* args = new PTimingCheck::optional_args_t; + args->notifier = $2; + $$ = args; + } + | ',' setuphold_recrem_opt_timestamp_cond // Empty { $$ = $2; } + | ',' hierarchy_identifier setuphold_recrem_opt_timestamp_cond + { + $$ = $3; + $$->notifier = $2; + } ; -spec_condition_opt - : /* empty */ - { $$ = 0; } - | spec_condition - { $$ = $1; } +setuphold_recrem_opt_timestamp_cond + : ',' // Empty and end of list + { + PTimingCheck::optional_args_t* args = new PTimingCheck::optional_args_t; + $$ = args; + } + | ',' hierarchy_identifier // End of list + { + PTimingCheck::optional_args_t* args = new PTimingCheck::optional_args_t; + args->timestamp_cond = $2; + $$ = args; + } + | ',' setuphold_recrem_opt_timecheck_cond // Empty + { $$ = $2; } + | ',' hierarchy_identifier setuphold_recrem_opt_timecheck_cond + { + $$ = $3; + $$->timestamp_cond = $2; + } ; -spec_condition - : ',' - { $$ = 0; } - | ',' hierarchy_identifier +setuphold_recrem_opt_timecheck_cond + : ',' // Empty and end of list + { + PTimingCheck::optional_args_t* args = new PTimingCheck::optional_args_t; + $$ = args; + } + | ',' hierarchy_identifier // End of list + { + PTimingCheck::optional_args_t* args = new PTimingCheck::optional_args_t; + args->timecheck_cond = $2; + $$ = args; + } + | ',' setuphold_recrem_opt_delayed_reference // Empty { $$ = $2; } + | ',' hierarchy_identifier setuphold_recrem_opt_delayed_reference + { + $$ = $3; + $$->timecheck_cond = $2; + } ; -spec_delayed_opt +setuphold_recrem_opt_delayed_reference + : ',' // Empty and end of list + { + PTimingCheck::optional_args_t* args = new PTimingCheck::optional_args_t; + $$ = args; + } + | ',' hierarchy_identifier // End of list + { + PTimingCheck::optional_args_t* args = new PTimingCheck::optional_args_t; + args->delayed_reference = $2; + $$ = args; + } + | ',' setuphold_recrem_opt_delayed_data // Empty + { $$ = $2; } + | ',' hierarchy_identifier setuphold_recrem_opt_delayed_data + { + $$ = $3; + $$->delayed_reference = $2; + } + ; + +setuphold_recrem_opt_delayed_data + : ',' // Empty and end of list + { + PTimingCheck::optional_args_t* args = new PTimingCheck::optional_args_t; + $$ = args; + } + | ',' hierarchy_identifier // End of list + { + PTimingCheck::optional_args_t* args = new PTimingCheck::optional_args_t; + args->delayed_data = $2; + $$ = args; + } + ; + +timeskew_opt_args + : timeskew_fullskew_opt_notifier + { $$ = $1; } + | + { $$ = new PTimingCheck::optional_args_t; } + ; + +fullskew_opt_args + : timeskew_fullskew_opt_notifier + { $$ = $1; } + | + { $$ = new PTimingCheck::optional_args_t; } + ; + + /* The following rules are used for the optional arguments + in $timeskew and $fullskew */ +timeskew_fullskew_opt_notifier + : ',' // Empty and end of list + { + PTimingCheck::optional_args_t* args = new PTimingCheck::optional_args_t; + $$ = args; + } + | ',' hierarchy_identifier // End of list + { + PTimingCheck::optional_args_t* args = new PTimingCheck::optional_args_t; + args->notifier = $2; + $$ = args; + } + | ',' timeskew_fullskew_opt_event_based_flag // Empty + { $$ = $2; } + | ',' hierarchy_identifier timeskew_fullskew_opt_event_based_flag + { + $$ = $3; + $$->notifier = $2; + } + ; + +timeskew_fullskew_opt_event_based_flag + : ',' // Empty and end of list + { + PTimingCheck::optional_args_t* args = new PTimingCheck::optional_args_t; + $$ = args; + } + | ',' expression // End of list + { + PTimingCheck::optional_args_t* args = new PTimingCheck::optional_args_t; + args->event_based_flag = $2; + $$ = args; + } + | ',' timeskew_fullskew_opt_remain_active_flag // Empty + { $$ = $2; } + | ',' expression timeskew_fullskew_opt_remain_active_flag + { + $$ = $3; + $$->event_based_flag = $2; + } + ; + +timeskew_fullskew_opt_remain_active_flag + : ',' // Empty and end of list + { + PTimingCheck::optional_args_t* args = new PTimingCheck::optional_args_t; + $$ = args; + } + | ',' expression // End of list + { + PTimingCheck::optional_args_t* args = new PTimingCheck::optional_args_t; + args->remain_active_flag = $2; + $$ = args; + } + ; + +spec_notifier_opt : /* empty */ { $$ = 0; } - | spec_delayed + | spec_notifier { $$ = $1; } ; -spec_delayed +spec_notifier : ',' { $$ = 0; } | ',' hierarchy_identifier diff --git a/pform.cc b/pform.cc index 39adddc04d..7b60d15f31 100644 --- a/pform.cc +++ b/pform.cc @@ -3113,59 +3113,55 @@ extern void pform_module_specify_path(PSpecPath*obj) /* * Timing checks. */ - extern PRecRem* pform_make_rec_rem(const struct vlltype&li, + extern PRecRem* pform_make_recrem(const struct vlltype&li, PTimingCheck::event_t&reference_event, PTimingCheck::event_t&data_event, - PExpr&setup_limit, - PExpr&hold_limit, - pform_name_t* notifier, - pform_name_t* timestamp_cond, - pform_name_t* timecheck_cond, - pform_name_t* delayed_reference, - pform_name_t* delayed_data) -{ - PRecRem*rec_rem = new PRecRem( + PExpr*setup_limit, + PExpr*hold_limit, + PTimingCheck::optional_args_t* args) +{ + ivl_assert(li, args); + + PRecRem*recrem = new PRecRem( reference_event, data_event, - //setup_limit, - //hold_limit, - notifier, - timestamp_cond, - timecheck_cond, - delayed_reference, - delayed_data + setup_limit, + hold_limit, + args->notifier, + args->timestamp_cond, + args->timecheck_cond, + args->delayed_reference, + args->delayed_data ); - FILE_NAME(rec_rem, li); + FILE_NAME(recrem, li); - return rec_rem; + return recrem; } -extern PSetupHold* pform_make_setup_hold(const struct vlltype&li, +extern PSetupHold* pform_make_setuphold(const struct vlltype&li, PTimingCheck::event_t&reference_event, PTimingCheck::event_t&data_event, - PExpr&setup_limit, - PExpr&hold_limit, - pform_name_t* notifier, - pform_name_t* timestamp_cond, - pform_name_t* timecheck_cond, - pform_name_t* delayed_reference, - pform_name_t* delayed_data) -{ - PSetupHold*setup_hold = new PSetupHold( + PExpr*setup_limit, + PExpr*hold_limit, + PTimingCheck::optional_args_t* args) +{ + ivl_assert(li, args); + + PSetupHold*setuphold = new PSetupHold( reference_event, data_event, - //setup_limit, - //hold_limit, - notifier, - timestamp_cond, - timecheck_cond, - delayed_reference, - delayed_data + setup_limit, + hold_limit, + args->notifier, + args->timestamp_cond, + args->timecheck_cond, + args->delayed_reference, + args->delayed_data ); - FILE_NAME(setup_hold, li); + FILE_NAME(setuphold, li); - return setup_hold; + return setuphold; } extern void pform_module_timing_check(PTimingCheck*obj) diff --git a/pform.h b/pform.h index a8fdb69e87..51038d1b1a 100644 --- a/pform.h +++ b/pform.h @@ -433,27 +433,19 @@ extern void pform_module_specify_path(PSpecPath*obj); /* * Functions related to timing checks. */ -extern PRecRem* pform_make_rec_rem(const struct vlltype&li, +extern PRecRem* pform_make_recrem(const struct vlltype&li, PTimingCheck::event_t&reference_event, PTimingCheck::event_t&data_event, - PExpr&setup_limit, - PExpr&hold_limit, - pform_name_t* notifier, - pform_name_t* timestamp_cond, - pform_name_t* timecheck_cond, - pform_name_t* delayed_reference, - pform_name_t* delayed_data + PExpr*setup_limit, + PExpr*hold_limit, + PTimingCheck::optional_args_t* args ); -extern PSetupHold* pform_make_setup_hold(const struct vlltype&li, +extern PSetupHold* pform_make_setuphold(const struct vlltype&li, PTimingCheck::event_t&reference_event, PTimingCheck::event_t&data_event, - PExpr&setup_limit, - PExpr&hold_limit, - pform_name_t* notifier, - pform_name_t* timestamp_cond, - pform_name_t* timecheck_cond, - pform_name_t* delayed_reference, - pform_name_t* delayed_data + PExpr*setup_limit, + PExpr*hold_limit, + PTimingCheck::optional_args_t* args ); extern void pform_module_timing_check(PTimingCheck*obj); From 7f5b8d49eba66877b038799af7af843c51f70c9d Mon Sep 17 00:00:00 2001 From: mole99 Date: Mon, 10 Jul 2023 16:12:27 +0200 Subject: [PATCH 6/9] Fix timing_check_syntax --- ivtest/ivltests/timing_check_syntax.v | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ivtest/ivltests/timing_check_syntax.v b/ivtest/ivltests/timing_check_syntax.v index 3ef193ab8c..c43347f019 100644 --- a/ivtest/ivltests/timing_check_syntax.v +++ b/ivtest/ivltests/timing_check_syntax.v @@ -84,9 +84,9 @@ module test; $timeskew(posedge sig1, negedge sig2 , 0:0:0 , notifier); $timeskew(edge[10, x0, 1x] sig1 , posedge sig2 , 0:0:0 , notifier); $timeskew(posedge sig1 , edge[10, x0, 1x] sig2 , 0:0:0 , notifier); - $timeskew(posedge sig1 , negedge sig2 , 0:0:0, notifier , 1'b0); - $timeskew(negedge sig1 , posedge sig2 , 0:0:0 , 1'b1 , 1'b0); - $timeskew(negedge sig1 , posedge sig2 , 0:0:0 , , 1'b1); + $timeskew(posedge sig1 , negedge sig2 , 0:0:0 , notifier , 1'b0); + $timeskew(negedge sig1 , posedge sig2 , 0:0:0 , notifier , 1'b1 , 1'b0); + $timeskew(negedge sig1 , posedge sig2 , 0:0:0 , , , 1'b1); $fullskew(posedge sig1 , negedge sig2 , 0:0:0 , 0:0:0); $fullskew(negedge sig1 , posedge sig2 , 0:0:0 , 0:0:0); @@ -95,9 +95,9 @@ module test; $fullskew(posedge sig1, negedge sig2 , 0:0:0 , 0:0:0 , notifier); $fullskew(edge[10, x0, 1x] sig1 , posedge sig2 , 0:0:0 , 0:0:0 , notifier); $fullskew(posedge sig1 , edge[10, x0, 1x] sig2 , 0:0:0 , 0:0:0 , notifier); - $fullskew(posedge sig1 , negedge sig2 , 0:0:0, notifier , 1'b0); - $fullskew(negedge sig1 , posedge sig2 , 0:0:0 , 1'b1 , 1'b0); - $fullskew(negedge sig1 , posedge sig2 , 0:0:0 , , 1'b1); + $fullskew(posedge sig1 , negedge sig2 , 0:0:0 , 0:0:0 , notifier , 1'b0); + $fullskew(negedge sig1 , posedge sig2 , 0:0:0 , 0:0:0 , notifier , 1'b1 , 1'b0); + $fullskew(negedge sig1 , posedge sig2 , 0:0:0 , 0:0:0 , , , 1'b1); $width(posedge sig1 , 0:0:0 ); $width(posedge sig1 &&& cond1 , 0:0:0 , 0 ); From 6b2990cfec74fe48e0297a28ef0f73d67ad8019f Mon Sep 17 00:00:00 2001 From: mole99 Date: Wed, 12 Jul 2023 15:10:23 +0200 Subject: [PATCH 7/9] Use more C++11 features --- PTimingCheck.cc | 36 ++++---------------------------- PTimingCheck.h | 47 +++++++++++++++++++++--------------------- elaborate.cc | 55 +++++++++++++++++++++---------------------------- parse.y | 25 ++++++++++------------ pform.cc | 10 ++++----- pform.h | 8 +++---- pform_dump.cc | 6 ++---- 7 files changed, 73 insertions(+), 114 deletions(-) diff --git a/PTimingCheck.cc b/PTimingCheck.cc index 5ec24bd214..42ea7219cf 100644 --- a/PTimingCheck.cc +++ b/PTimingCheck.cc @@ -19,8 +19,8 @@ # include "PTimingCheck.h" -PRecRem::PRecRem(event_t reference_event, - event_t data_event, +PRecRem::PRecRem(event_t* reference_event, + event_t* data_event, PExpr* setup_limit, PExpr* hold_limit, pform_name_t* notifier, @@ -43,24 +43,10 @@ PRecRem::PRecRem(event_t reference_event, PRecRem::~PRecRem() { - delete setup_limit_; - delete hold_limit_; - - // Delete optional arguments - if (reference_event_.condition) delete reference_event_.condition; - if (data_event_.condition) delete data_event_.condition; - - if(notifier_) delete notifier_; - - if(timestamp_cond_) delete timestamp_cond_; - if(timecheck_cond_) delete timecheck_cond_; - - if(delayed_reference_) delete delayed_reference_; - if(delayed_data_) delete delayed_data_; } -PSetupHold::PSetupHold(event_t reference_event, - event_t data_event, +PSetupHold::PSetupHold(event_t* reference_event, + event_t* data_event, PExpr* setup_limit, PExpr* hold_limit, pform_name_t* notifier, @@ -83,18 +69,4 @@ PSetupHold::PSetupHold(event_t reference_event, PSetupHold::~PSetupHold() { - delete setup_limit_; - delete hold_limit_; - - // Delete optional arguments - if (reference_event_.condition) delete reference_event_.condition; - if (data_event_.condition) delete data_event_.condition; - - if(notifier_) delete notifier_; - - if(timestamp_cond_) delete timestamp_cond_; - if(timecheck_cond_) delete timecheck_cond_; - - if(delayed_reference_) delete delayed_reference_; - if(delayed_data_) delete delayed_data_; } diff --git a/PTimingCheck.h b/PTimingCheck.h index a716db122a..cf1dfda4c7 100644 --- a/PTimingCheck.h +++ b/PTimingCheck.h @@ -22,6 +22,7 @@ # include "LineInfo.h" # include "PExpr.h" # include "pform_types.h" +# include /* * The PTimingCheck is the base class for all timing checks @@ -36,7 +37,7 @@ class PTimingCheck : public LineInfo { bool posedge; bool negedge; std::vector edges; - PExpr* condition; + std::unique_ptr condition; }; // This struct is used to parse the optional arguments @@ -65,8 +66,8 @@ class PRecRem : public PTimingCheck { public: - PRecRem(event_t reference_event, - event_t data_event, + PRecRem(event_t* reference_event, + event_t* data_event, PExpr* setup_limit, PExpr* hold_limit, pform_name_t* notifier, @@ -82,19 +83,19 @@ class PRecRem : public PTimingCheck { void dump(std::ostream&out, unsigned ind) const override; private: - event_t reference_event_; // hierarchy_identifier - event_t data_event_; + std::unique_ptr reference_event_; + std::unique_ptr data_event_; - PExpr* setup_limit_; - PExpr* hold_limit_; + std::unique_ptr setup_limit_; + std::unique_ptr hold_limit_; - pform_name_t* notifier_; + std::unique_ptr notifier_; - pform_name_t* timestamp_cond_; - pform_name_t* timecheck_cond_; + std::unique_ptr timestamp_cond_; + std::unique_ptr timecheck_cond_; - pform_name_t* delayed_reference_; - pform_name_t* delayed_data_; + std::unique_ptr delayed_reference_; + std::unique_ptr delayed_data_; }; /* @@ -103,8 +104,8 @@ class PRecRem : public PTimingCheck { class PSetupHold : public PTimingCheck { public: - PSetupHold(event_t reference_event, - event_t data_event, + PSetupHold(event_t* reference_event, + event_t* data_event, PExpr* setup_limit, PExpr* hold_limit, pform_name_t* notifier, @@ -120,19 +121,19 @@ class PSetupHold : public PTimingCheck { void dump(std::ostream&out, unsigned ind) const override; private: - event_t reference_event_; // hierarchy_identifier - event_t data_event_; + std::unique_ptr reference_event_; + std::unique_ptr data_event_; - PExpr* setup_limit_; - PExpr* hold_limit_; + std::unique_ptr setup_limit_; + std::unique_ptr hold_limit_; - pform_name_t* notifier_; + std::unique_ptr notifier_; - pform_name_t* timestamp_cond_; - pform_name_t* timecheck_cond_; + std::unique_ptr timestamp_cond_; + std::unique_ptr timecheck_cond_; - pform_name_t* delayed_reference_; - pform_name_t* delayed_data_; + std::unique_ptr delayed_reference_; + std::unique_ptr delayed_data_; }; #endif /* IVL_PTimingCheck_H */ diff --git a/elaborate.cc b/elaborate.cc index bebc6399c1..c5a530666e 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -6321,15 +6321,15 @@ void PRecRem::elaborate(Design*des, NetScope*scope) const { if (debug_elaborate) { cerr << get_fileline() << ": PRecRem::elaborate: Assigning " - << reference_event_.name + << reference_event_->name << " to " << *delayed_reference_ << endl; } - NetNet*sig = des->find_signal(scope, reference_event_.name); + NetNet*sig = des->find_signal(scope, reference_event_->name); if (sig == nullptr) { cerr << get_fileline() << ": error: Cannot find: " - << reference_event_.name << endl; + << reference_event_->name << endl; des->errors += 1; return; } @@ -6350,15 +6350,15 @@ void PRecRem::elaborate(Design*des, NetScope*scope) const { if (debug_elaborate) { cerr << get_fileline() << ": PRecRem::elaborate: Assigning " - << data_event_.name + << data_event_->name << " to " << *delayed_data_ << endl; } - NetNet*sig = des->find_signal(scope, data_event_.name); + NetNet*sig = des->find_signal(scope, data_event_->name); if (sig == nullptr) { cerr << get_fileline() << ": error: Cannot find: " - << data_event_.name << endl; + << data_event_->name << endl; des->errors += 1; return; } @@ -6388,15 +6388,15 @@ void PSetupHold::elaborate(Design*des, NetScope*scope) const { if (debug_elaborate) { cerr << get_fileline() << ": PSetupHold::elaborate: Assigning" - << reference_event_.name + << reference_event_->name << " to " << *delayed_reference_ << endl; } - NetNet*sig = des->find_signal(scope, reference_event_.name); + NetNet*sig = des->find_signal(scope, reference_event_->name); if (sig == nullptr) { cerr << get_fileline() << ": error: Cannot find: " - << reference_event_.name << endl; + << reference_event_->name << endl; des->errors += 1; return; } @@ -6417,15 +6417,15 @@ void PSetupHold::elaborate(Design*des, NetScope*scope) const { if (debug_elaborate) { cerr << get_fileline() << ": PSetupHold::elaborate: Assigning" - << reference_event_.name - << " to " << *delayed_reference_ << endl; + << data_event_->name + << " to " << *delayed_data_ << endl; } - NetNet*sig = des->find_signal(scope, data_event_.name); + NetNet*sig = des->find_signal(scope, data_event_->name); if (sig == nullptr) { cerr << get_fileline() << ": error: Cannot find: " - << data_event_.name << endl; + << data_event_->name << endl; des->errors += 1; return; } @@ -6518,10 +6518,8 @@ bool Module::elaborate(Design*des, NetScope*scope) const bool result_flag = true; // Elaborate within the generate blocks. - typedef list::const_iterator generate_it_t; - for (generate_it_t cur = generate_schemes.begin() - ; cur != generate_schemes.end() ; ++ cur ) { - (*cur)->elaborate(des, scope); + for (const auto cur : generate_schemes) { + cur->elaborate(des, scope); } // Elaborate functions. @@ -6540,10 +6538,8 @@ bool Module::elaborate(Design*des, NetScope*scope) const // complex. const list&gl = get_gates(); - for (list::const_iterator gt = gl.begin() - ; gt != gl.end() ; ++ gt ) { - - (*gt)->elaborate(des, scope); + for (const auto gt : gl) { + gt->elaborate(des, scope); } // Elaborate the variable initialization statements, making a @@ -6556,23 +6552,18 @@ bool Module::elaborate(Design*des, NetScope*scope) const result_flag &= elaborate_behaviors_(des, scope); // Elaborate the specify paths of the module. - for (list::const_iterator sp = specify_paths.begin() - ; sp != specify_paths.end() ; ++ sp ) { - - (*sp)->elaborate(des, scope); + for (const auto sp : specify_paths) { + sp->elaborate(des, scope); } // Elaborate the timing checks of the module. - for (list::const_iterator tc = timing_checks.begin() - ; tc != timing_checks.end() ; ++ tc ) { - - (*tc)->elaborate(des, scope); + for (const auto tc : timing_checks) { + tc->elaborate(des, scope); } // Elaborate the elaboration tasks. - for (list::const_iterator et = elab_tasks.begin() - ; et != elab_tasks.end() ; ++ et ) { - result_flag &= (*et)->elaborate_elab(des, scope); + for (const auto et : elab_tasks) { + result_flag &= et->elaborate_elab(des, scope); } return result_flag; diff --git a/parse.y b/parse.y index d7b63559b4..5ad95b7c0c 100644 --- a/parse.y +++ b/parse.y @@ -33,6 +33,7 @@ # include # include # include +# include using namespace std; @@ -5970,11 +5971,9 @@ specify_item cerr << endl; } - PRecRem*recrem = pform_make_recrem(@1, *$3, *$5, $7, $9, $10); - pform_module_timing_check((PTimingCheck*)recrem); + PRecRem*recrem = pform_make_recrem(@1, $3, $5, $7, $9, $10); + pform_module_timing_check(recrem); - delete $3; // spec_reference_event - delete $5; // spec_reference_event delete $10; // setuphold_recrem_opt_notifier } | K_Sremoval '(' spec_reference_event ',' spec_reference_event @@ -6009,11 +6008,9 @@ specify_item cerr << endl; } - PSetupHold*setuphold = pform_make_setuphold(@1, *$3, *$5, $7, $9, $10); - pform_module_timing_check((PTimingCheck*)setuphold); + PSetupHold*setuphold = pform_make_setuphold(@1, $3, $5, $7, $9, $10); + pform_module_timing_check(setuphold); - delete $3; // spec_reference_event - delete $5; // spec_reference_event delete $10; // setuphold_recrem_opt_notifier } | K_Sskew '(' spec_reference_event ',' spec_reference_event @@ -6267,7 +6264,7 @@ spec_reference_event event->name = *$1; event->posedge = false; event->negedge = false; - event->condition = $3; + event->condition = std::unique_ptr($3); delete $1; $$ = event; } @@ -6294,7 +6291,7 @@ spec_reference_event event->name = *$2; event->posedge = true; event->negedge = false; - event->condition = $4; + event->condition = std::unique_ptr($4); delete $2; $$ = event; } @@ -6303,7 +6300,7 @@ spec_reference_event event->name = *$2; event->posedge = false; event->negedge = true; - event->condition = $4; + event->condition = std::unique_ptr($4); delete $2; $$ = event; } @@ -6323,7 +6320,7 @@ spec_reference_event event->posedge = false; event->negedge = false; // TODO add edge descriptors - event->condition = $7; + event->condition = std::unique_ptr($7); delete $5; $$ = event; } @@ -6526,14 +6523,14 @@ timeskew_fullskew_opt_remain_active_flag spec_notifier_opt : /* empty */ - { $$ = 0; } + { $$ = nullptr; } | spec_notifier { $$ = $1; } ; spec_notifier : ',' - { $$ = 0; } + { $$ = nullptr; } | ',' hierarchy_identifier { $$ = $2; } ; diff --git a/pform.cc b/pform.cc index 7b60d15f31..3957019ed1 100644 --- a/pform.cc +++ b/pform.cc @@ -3114,8 +3114,8 @@ extern void pform_module_specify_path(PSpecPath*obj) * Timing checks. */ extern PRecRem* pform_make_recrem(const struct vlltype&li, - PTimingCheck::event_t&reference_event, - PTimingCheck::event_t&data_event, + PTimingCheck::event_t*reference_event, + PTimingCheck::event_t*data_event, PExpr*setup_limit, PExpr*hold_limit, PTimingCheck::optional_args_t* args) @@ -3139,8 +3139,8 @@ extern void pform_module_specify_path(PSpecPath*obj) return recrem; } extern PSetupHold* pform_make_setuphold(const struct vlltype&li, - PTimingCheck::event_t&reference_event, - PTimingCheck::event_t&data_event, + PTimingCheck::event_t*reference_event, + PTimingCheck::event_t*data_event, PExpr*setup_limit, PExpr*hold_limit, PTimingCheck::optional_args_t* args) @@ -3166,7 +3166,7 @@ extern PSetupHold* pform_make_setuphold(const struct vlltype&li, extern void pform_module_timing_check(PTimingCheck*obj) { - if (obj == 0) + if (!obj) return; pform_cur_module.front()->timing_checks.push_back(obj); diff --git a/pform.h b/pform.h index 51038d1b1a..7eeb936217 100644 --- a/pform.h +++ b/pform.h @@ -434,15 +434,15 @@ extern void pform_module_specify_path(PSpecPath*obj); * Functions related to timing checks. */ extern PRecRem* pform_make_recrem(const struct vlltype&li, - PTimingCheck::event_t&reference_event, - PTimingCheck::event_t&data_event, + PTimingCheck::event_t*reference_event, + PTimingCheck::event_t*data_event, PExpr*setup_limit, PExpr*hold_limit, PTimingCheck::optional_args_t* args ); extern PSetupHold* pform_make_setuphold(const struct vlltype&li, - PTimingCheck::event_t&reference_event, - PTimingCheck::event_t&data_event, + PTimingCheck::event_t*reference_event, + PTimingCheck::event_t*data_event, PExpr*setup_limit, PExpr*hold_limit, PTimingCheck::optional_args_t* args diff --git a/pform_dump.cc b/pform_dump.cc index 86ab8a62d4..4f5ba286ec 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -1718,10 +1718,8 @@ void Module::dump_timingchecks_(ostream&out, unsigned indent) const { cout << "dump_timingchecks_" << endl; - typedef list::const_iterator tcheck_iter_t; - for (tcheck_iter_t cur = timing_checks.begin() - ; cur != timing_checks.end() ; ++ cur ) { - (*cur)->dump(out, indent); + for (const auto cur : timing_checks) { + cur->dump(out, indent); } } From e0d0dff8d6040089c240f73cf03e8502841203b8 Mon Sep 17 00:00:00 2001 From: mole99 Date: Thu, 13 Jul 2023 10:15:52 +0200 Subject: [PATCH 8/9] Change timing check condition to expression for better compatibility --- PTimingCheck.cc | 8 ++++---- PTimingCheck.h | 20 ++++++++++---------- parse.y | 8 ++++---- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/PTimingCheck.cc b/PTimingCheck.cc index 42ea7219cf..49ae2ec8ac 100644 --- a/PTimingCheck.cc +++ b/PTimingCheck.cc @@ -24,8 +24,8 @@ PRecRem::PRecRem(event_t* reference_event, PExpr* setup_limit, PExpr* hold_limit, pform_name_t* notifier, - pform_name_t* timestamp_cond, - pform_name_t* timecheck_cond, + PExpr* timestamp_cond, + PExpr* timecheck_cond, pform_name_t* delayed_reference, pform_name_t* delayed_data) : @@ -50,8 +50,8 @@ PSetupHold::PSetupHold(event_t* reference_event, PExpr* setup_limit, PExpr* hold_limit, pform_name_t* notifier, - pform_name_t* timestamp_cond, - pform_name_t* timecheck_cond, + PExpr* timestamp_cond, + PExpr* timecheck_cond, pform_name_t* delayed_reference, pform_name_t* delayed_data) : diff --git a/PTimingCheck.h b/PTimingCheck.h index cf1dfda4c7..cc5a5c61ca 100644 --- a/PTimingCheck.h +++ b/PTimingCheck.h @@ -43,8 +43,8 @@ class PTimingCheck : public LineInfo { // This struct is used to parse the optional arguments struct optional_args_t { pform_name_t* notifier = nullptr; - pform_name_t* timestamp_cond = nullptr; - pform_name_t* timecheck_cond = nullptr; + PExpr* timestamp_cond = nullptr; + PExpr* timecheck_cond = nullptr; pform_name_t* delayed_reference = nullptr; pform_name_t* delayed_data = nullptr; PExpr* event_based_flag = nullptr; @@ -71,8 +71,8 @@ class PRecRem : public PTimingCheck { PExpr* setup_limit, PExpr* hold_limit, pform_name_t* notifier, - pform_name_t* timestamp_cond, - pform_name_t* timecheck_cond, + PExpr* timestamp_cond, + PExpr* timecheck_cond, pform_name_t* delayed_reference, pform_name_t* delayed_data); @@ -91,8 +91,8 @@ class PRecRem : public PTimingCheck { std::unique_ptr notifier_; - std::unique_ptr timestamp_cond_; - std::unique_ptr timecheck_cond_; + std::unique_ptr timestamp_cond_; + std::unique_ptr timecheck_cond_; std::unique_ptr delayed_reference_; std::unique_ptr delayed_data_; @@ -109,8 +109,8 @@ class PSetupHold : public PTimingCheck { PExpr* setup_limit, PExpr* hold_limit, pform_name_t* notifier, - pform_name_t* timestamp_cond, - pform_name_t* timecheck_cond, + PExpr* timestamp_cond, + PExpr* timecheck_cond, pform_name_t* delayed_reference, pform_name_t* delayed_data); @@ -129,8 +129,8 @@ class PSetupHold : public PTimingCheck { std::unique_ptr notifier_; - std::unique_ptr timestamp_cond_; - std::unique_ptr timecheck_cond_; + std::unique_ptr timestamp_cond_; + std::unique_ptr timecheck_cond_; std::unique_ptr delayed_reference_; std::unique_ptr delayed_data_; diff --git a/parse.y b/parse.y index 5ad95b7c0c..1802adc7fa 100644 --- a/parse.y +++ b/parse.y @@ -6378,7 +6378,7 @@ setuphold_recrem_opt_timestamp_cond PTimingCheck::optional_args_t* args = new PTimingCheck::optional_args_t; $$ = args; } - | ',' hierarchy_identifier // End of list + | ',' expression // End of list { PTimingCheck::optional_args_t* args = new PTimingCheck::optional_args_t; args->timestamp_cond = $2; @@ -6386,7 +6386,7 @@ setuphold_recrem_opt_timestamp_cond } | ',' setuphold_recrem_opt_timecheck_cond // Empty { $$ = $2; } - | ',' hierarchy_identifier setuphold_recrem_opt_timecheck_cond + | ',' expression setuphold_recrem_opt_timecheck_cond { $$ = $3; $$->timestamp_cond = $2; @@ -6399,7 +6399,7 @@ setuphold_recrem_opt_timecheck_cond PTimingCheck::optional_args_t* args = new PTimingCheck::optional_args_t; $$ = args; } - | ',' hierarchy_identifier // End of list + | ',' expression // End of list { PTimingCheck::optional_args_t* args = new PTimingCheck::optional_args_t; args->timecheck_cond = $2; @@ -6407,7 +6407,7 @@ setuphold_recrem_opt_timecheck_cond } | ',' setuphold_recrem_opt_delayed_reference // Empty { $$ = $2; } - | ',' hierarchy_identifier setuphold_recrem_opt_delayed_reference + | ',' expression setuphold_recrem_opt_delayed_reference { $$ = $3; $$->timecheck_cond = $2; From 13fcf2d844bf0058c6cfe1cc97cc4b05c23aad5a Mon Sep 17 00:00:00 2001 From: mole99 Date: Fri, 14 Jul 2023 08:06:06 +0200 Subject: [PATCH 9/9] Remove checks for non-NULL before deleting --- parse.y | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/parse.y b/parse.y index 1802adc7fa..c0d4fc32f8 100644 --- a/parse.y +++ b/parse.y @@ -5915,9 +5915,9 @@ specify_item delete $7; // delay_value delete $9; // delay_value - if ($10->notifier) delete $10->notifier; - if ($10->event_based_flag) delete $10->event_based_flag; - if ($10->remain_active_flag) delete $10->remain_active_flag; + delete $10->notifier; + delete $10->event_based_flag; + delete $10->remain_active_flag; delete $10; // fullskew_opt_args } @@ -5928,7 +5928,7 @@ specify_item delete $3; // spec_reference_event delete $5; // spec_reference_event delete $7; // delay_value - if($8) delete $8; // spec_notifier_opt + delete $8; // spec_notifier_opt } | K_Snochange '(' spec_reference_event ',' spec_reference_event ',' delay_value ',' delay_value spec_notifier_opt ')' ';' @@ -5938,7 +5938,7 @@ specify_item delete $5; // spec_reference_event delete $7; // delay_value delete $9; // delay_value - if($10) delete $10; // spec_notifier_opt + delete $10; // spec_notifier_opt } | K_Speriod '(' spec_reference_event ',' delay_value spec_notifier_opt ')' ';' @@ -5946,7 +5946,7 @@ specify_item cerr << @3 << ": warning: Timing checks are not supported." << endl; delete $3; // spec_reference_event delete $5; // delay_value - if($6) delete $6; // spec_notifier_opt + delete $6; // spec_notifier_opt } | K_Srecovery '(' spec_reference_event ',' spec_reference_event ',' delay_value spec_notifier_opt ')' ';' @@ -5955,7 +5955,7 @@ specify_item delete $3; // spec_reference_event delete $5; // spec_reference_event delete $7; // delay_value - if($8) delete $8; // spec_notifier_opt + delete $8; // spec_notifier_opt } | K_Srecrem '(' spec_reference_event ',' spec_reference_event ',' expr_mintypmax ',' expr_mintypmax recrem_opt_args ')' ';' @@ -5983,7 +5983,7 @@ specify_item delete $3; // spec_reference_event delete $5; // spec_reference_event delete $7; // delay_value - if($8) delete $8; // spec_notifier_opt + delete $8; // spec_notifier_opt } | K_Ssetup '(' spec_reference_event ',' spec_reference_event ',' delay_value spec_notifier_opt ')' ';' @@ -5992,7 +5992,7 @@ specify_item delete $3; // spec_reference_event delete $5; // spec_reference_event delete $7; // delay_value - if($8) delete $8; // spec_notifier_opt + delete $8; // spec_notifier_opt } | K_Ssetuphold '(' spec_reference_event ',' spec_reference_event ',' expr_mintypmax ',' expr_mintypmax setuphold_opt_args ')' ';' @@ -6020,7 +6020,7 @@ specify_item delete $3; // spec_reference_event delete $5; // spec_reference_event delete $7; // delay_value - if($8) delete $8; // spec_notifier_opt + delete $8; // spec_notifier_opt } | K_Stimeskew '(' spec_reference_event ',' spec_reference_event ',' delay_value timeskew_opt_args ')' ';' @@ -6030,9 +6030,9 @@ specify_item delete $5; // spec_reference_event delete $7; // delay_value - if ($8->notifier) delete $8->notifier; - if ($8->event_based_flag) delete $8->event_based_flag; - if ($8->remain_active_flag) delete $8->remain_active_flag; + delete $8->notifier; + delete $8->event_based_flag; + delete $8->remain_active_flag; delete $8; // timeskew_opt_args } @@ -6043,7 +6043,7 @@ specify_item delete $3; // spec_reference_event delete $5; // delay_value delete $7; // expression - if($8) delete $8; + delete $8; } | K_Swidth '(' spec_reference_event ',' delay_value ')' ';' {