From 5b273178f5f81e1424ca3b9ac82c03e483da805b Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 11 May 2008 12:00:11 -0700 Subject: [PATCH] Parse disciplines and contribution statements Parse discipline declarations, net discipline declarations, and analog contribution statements. Don't yet do anything useful with these, just give a sorry message where they are encountered. --- Makefile.in | 4 +- discipline.cc | 29 ++++++++++++++ discipline.h | 51 +++++++++++++++++++++++++ lexor.lex | 14 +++++++ main.cc | 6 +++ parse.y | 58 +++++++++++++++++++--------- parse_misc.h | 8 ++++ pform.cc | 8 +--- pform.h | 15 ++++++++ pform_disciplines.cc | 91 ++++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 257 insertions(+), 27 deletions(-) create mode 100644 discipline.cc create mode 100644 discipline.h create mode 100644 pform_disciplines.cc diff --git a/Makefile.in b/Makefile.in index 9e92fa070..6e4c96ab3 100644 --- a/Makefile.in +++ b/Makefile.in @@ -99,7 +99,7 @@ distclean: clean TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o -O = main.o async.o design_dump.o dup_expr.o elaborate.o elab_expr.o \ +O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o elab_expr.o \ elab_lval.o elab_net.o elab_pexpr.o elab_scope.o \ elab_sig.o emit.o eval.o eval_attrib.o \ eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \ @@ -107,7 +107,7 @@ load_module.o netlist.o netmisc.o net_assign.o \ net_design.o net_event.o net_expr.o net_force.o net_func.o \ net_link.o net_modulo.o net_nex_input.o net_nex_output.o \ net_proc.o net_scope.o net_udp.o pad_to_width.o \ -parse.o parse_misc.o pform.o pform_dump.o pform_types.o \ +parse.o parse_misc.o pform.o pform_disciplines.o pform_dump.o pform_types.o \ set_width.o symbol_search.o sync.o sys_funcs.o \ verinum.o verireal.o target.o targets.o \ Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \ diff --git a/discipline.cc b/discipline.cc new file mode 100644 index 000000000..42b77352d --- /dev/null +++ b/discipline.cc @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2008 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 + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +# include "discipline.h" + +discipline_t::discipline_t(perm_string name, ddomain_t domain) +: name_(name), domain_(domain) +{ +} + +discipline_t::~discipline_t() +{ +} diff --git a/discipline.h b/discipline.h new file mode 100644 index 000000000..e43365834 --- /dev/null +++ b/discipline.h @@ -0,0 +1,51 @@ +#ifndef __discipline_H +#define __discipline_H +/* + * Copyright (c) 2008 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 + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +/* + * The discipline types include the discipline, nature and other + * related types for managing declared and used disciplines in a + * Verilog-AMS program. + */ + +# include "StringHeap.h" +# include +# include +# include "LineInfo.h" + +typedef enum { DD_NONE, DD_DISCRETE, DD_CONTINUOUS } ddomain_t; +extern std::ostream& operator << (std::ostream&, ddomain_t); + +class discipline_t : public LineInfo { + public: + explicit discipline_t (perm_string name, ddomain_t dom); + ~discipline_t(); + + perm_string name() const { return name_; } + ddomain_t domain() const { return domain_; } + + private: + perm_string name_; + ddomain_t domain_; +}; + +extern map disciplines; + +#endif diff --git a/lexor.lex b/lexor.lex index b902bb50e..d0dfa7980 100644 --- a/lexor.lex +++ b/lexor.lex @@ -34,6 +34,7 @@ # include # include # include "lexor_keyword.h" +# include "discipline.h" # include # define YY_USER_INIT reset_lexor(); @@ -152,6 +153,7 @@ S [afpnumkKMGT] "->" { return K_TRIGGER; } "+:" { return K_PO_POS; } "-:" { return K_PO_NEG; } +"<+" { return K_CONTRIBUTE; } /* Watch out for the tricky case of (*). Cannot parse this as "(*" and ")", but since I know that this is really ( * ), replace it @@ -230,6 +232,18 @@ S [afpnumkKMGT] break; } + /* If this identifier names a discipline, then return this as + a DISCIPLINE_IDENTIFIER and return the discipline as the + value instead. */ + if (rc == IDENTIFIER && gn_verilog_ams_flag) { + perm_string tmp = lex_strings.make(yylval.text); + map::iterator cur = disciplines.find(tmp); + if (cur != disciplines.end()) { + yylval.discipline = (*cur).second; + rc = DISCIPLINE_IDENTIFIER; + } + } + return rc; } diff --git a/main.cc b/main.cc index 6e6bcfb25..5027b9de1 100644 --- a/main.cc +++ b/main.cc @@ -57,6 +57,7 @@ const char NOTICE[] = # include "netlist.h" # include "target.h" # include "compiler.h" +# include "discipline.h" #if defined(__MINGW32__) && !defined(HAVE_GETOPT_H) extern "C" int getopt(int argc, char*argv[], const char*fmt); @@ -683,6 +684,11 @@ int main(int argc, char*argv[]) if (pf_path) { ofstream out (pf_path); + out << "PFORM DUMP DISCIPLINES:" << endl; + for (map::iterator cur = disciplines.begin() + ; cur != disciplines.end() ; cur ++ ) { + pform_dump(out, (*cur).second); + } out << "PFORM DUMP MODULES:" << endl; for (map::iterator mod = pform_modules.begin() ; mod != pform_modules.end() diff --git a/parse.y b/parse.y index 38d716337..4d91bf448 100644 --- a/parse.y +++ b/parse.y @@ -94,12 +94,6 @@ static list* list_from_identifier(list*tmp, char*id) return tmp; } -static inline void FILE_NAME(LineInfo*tmp, const struct vlltype&where) -{ - tmp->set_lineno(where.first_line); - tmp->set_file(filename_strings.make(where.text)); -} - static svector* copy_range(svector* orig) { svector*copy = 0; @@ -147,6 +141,8 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2) list*perm_strings; pform_name_t*pform_name; + discipline_t*discipline; + hname_t*hier; list*strings; @@ -196,10 +192,13 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2) }; %token IDENTIFIER SYSTEM_IDENTIFIER STRING +%token DISCIPLINE_IDENTIFIER %token PATHPULSE_IDENTIFIER %token BASED_NUMBER DEC_NUMBER %token REALTIME %token K_LE K_GE K_EG K_EQ K_NE K_CEQ K_CNE K_LS K_RS K_RSS K_SG + /* K_CONTRIBUTE is <+, the contribution assign. */ +%token K_CONTRIBUTE %token K_PO_POS K_PO_NEG K_POW %token K_PSTAR K_STARP %token K_LOR K_LAND K_NAND K_NOR K_NXOR K_TRIGGER @@ -674,8 +673,10 @@ description ; discipline_declaration - : K_discipline IDENTIFIER discipline_items K_enddiscipline - { delete[]$2; } + : K_discipline IDENTIFIER + { pform_start_discipline($2); } + discipline_items K_enddiscipline + { pform_end_discipline(@1); delete[] $2; } ; discipline_items @@ -822,6 +823,15 @@ event_expression } ; + /* A branch probe expression applies a probe function (potential or + flow) to a branch. The branch may be implicit as a pair of nets + or explicit as a named branch. Elaboration will check that the + function name really is a nature attribute identifier. */ +branch_probe_expression + : IDENTIFIER '(' IDENTIFIER ',' IDENTIFIER ')' + | IDENTIFIER '(' IDENTIFIER ')' + ; + expression : expr_primary { $$ = $1; } @@ -1951,6 +1961,12 @@ module_item yyerrok; } + /* Maybe this is a discipline declaration? If so, then the lexor + will see the discipline name as an identifier. We match it to the + discipline or type name semantically. */ + | DISCIPLINE_IDENTIFIER list_of_identifiers ';' + { pform_attach_discipline(@1, $1, $2); } + /* block_item_decl rule is shared with task blocks and named begin/end. */ @@ -2030,16 +2046,16 @@ module_item /* Always and initial items are behavioral processes. */ - | attribute_list_opt K_always statement - { PProcess*tmp = pform_make_behavior(PProcess::PR_ALWAYS, - $3, $1); - FILE_NAME(tmp, @2); - } - | attribute_list_opt K_initial statement - { PProcess*tmp = pform_make_behavior(PProcess::PR_INITIAL, - $3, $1); - FILE_NAME(tmp, @2); - } + | attribute_list_opt K_always statement + { PProcess*tmp = pform_make_behavior(PProcess::PR_ALWAYS, $3, $1); + FILE_NAME(tmp, @2); + } + | attribute_list_opt K_initial statement + { PProcess*tmp = pform_make_behavior(PProcess::PR_INITIAL, $3, $1); + FILE_NAME(tmp, @2); + } + + | attribute_list_opt K_analog analog_statement /* The task declaration rule matches the task declaration header, then pushes the function scope. This causes the @@ -3541,6 +3557,12 @@ statement_or_null | ';' { $$ = 0; } ; + +analog_statement + : branch_probe_expression K_CONTRIBUTE expression ';' + { yyerror(@1, "sorry: Analog contribution statements not supported."); } + ; + /* Task items are, other than the statement, task port items and other block items. */ task_item diff --git a/parse_misc.h b/parse_misc.h index 9f3274689..3960f1176 100644 --- a/parse_misc.h +++ b/parse_misc.h @@ -23,6 +23,7 @@ #endif # include +# include "compiler.h" # include "pform.h" /* @@ -39,6 +40,13 @@ struct vlltype { }; # define YYLTYPE struct vlltype +class LineInfo; +inline void FILE_NAME(LineInfo*tmp, const struct vlltype&where) +{ + tmp->set_lineno(where.first_line); + tmp->set_file(filename_strings.make(where.text)); +} + /* This for compatibility with new and older bison versions. */ #ifndef yylloc # define yylloc VLlloc diff --git a/pform.cc b/pform.cc index 295262eed..15aaec45f 100644 --- a/pform.cc +++ b/pform.cc @@ -27,6 +27,7 @@ # include "PUdp.h" # include "PGenerate.h" # include "PSpec.h" +# include "discipline.h" # include # include # include @@ -38,7 +39,6 @@ # include "ivl_assert.h" - map pform_modules; map pform_primitives; @@ -82,12 +82,6 @@ static inline void FILE_NAME(LineInfo*obj, const char*file, unsigned lineno) obj->set_file(filename_strings.make(file)); } -static inline void FILE_NAME(LineInfo*tmp, const struct vlltype&where) -{ - tmp->set_lineno(where.first_line); - tmp->set_file(filename_strings.make(where.text)); -} - /* * The lexical_scope keeps track of the current lexical scope that is * being parsed. The lexical scope may stack, so the current scope may diff --git a/pform.h b/pform.h index ed953cb99..f63972c13 100644 --- a/pform.h +++ b/pform.h @@ -115,6 +115,7 @@ struct lgate { unsigned lineno; }; + /* The lexor calls this function to change the default nettype. */ extern void pform_set_default_nettype(NetNet::Type net, const char*file, @@ -350,4 +351,18 @@ extern void pform_dump(ostream&out, Module*mod); */ extern void pform_error_nested_modules(); +/* ** pform_discipline.cc + * Functions for handling the parse of natures and disciplines. These + * functions are in pform_disciplines.cc + */ +class discipline_t; + +extern void pform_start_discipline(const char*name); +extern void pform_end_discipline(const struct vlltype&loc); + +extern void pform_attach_discipline(const struct vlltype&loc, + discipline_t*discipline, list*names); + +extern void pform_dump(ostream&out, discipline_t*); + #endif diff --git a/pform_disciplines.cc b/pform_disciplines.cc new file mode 100644 index 000000000..fb1e444d3 --- /dev/null +++ b/pform_disciplines.cc @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2008 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 + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +# include "config.h" +# include "compiler.h" +# include "pform.h" +# include "parse_misc.h" +# include "discipline.h" + +map disciplines; + +static perm_string discipline_name; +static ddomain_t discipline_domain = DD_NONE; + +void pform_start_discipline(const char*name) +{ + discipline_name = lex_strings.make(name); + discipline_domain = DD_NONE; +} + +void pform_end_discipline(const struct vlltype&loc) +{ + discipline_t*tmp = new discipline_t(discipline_name, discipline_domain); + disciplines[discipline_name] = tmp; + + FILE_NAME(tmp, loc); + + /* Clear the static variables for the next item. */ + discipline_name = perm_string::perm_string(); + discipline_domain = DD_NONE; +} + +/* + * The parser uses this function to attach a discipline to a declared wire. + */ +void pform_attach_discipline(const struct vlltype&loc, + discipline_t*discipline, list*names) +{ + error_count += 1; + cerr << yylloc.text << ";" << yylloc.first_line << ": sorry: " + << "Net discipline declarations not supported." << endl; + + for (list::iterator cur = names->begin() + ; cur != names->end() ; cur ++ ) { + cerr << yylloc.text << ";" << yylloc.first_line << ": : " + << "discipline=" << discipline->name() + << ", net=" << *cur << endl; + } +} + +void pform_dump(std::ostream&out, discipline_t*dis) +{ + out << "discipline " << dis->name() << endl; + out << " domain " << dis->domain() << ";" << endl; + out << "enddiscipline" << endl; +} + +std::ostream& operator << (std::ostream&out, ddomain_t dom) +{ + switch (dom) { + case DD_NONE: + out << "no-domain"; + break; + case DD_DISCRETE: + out << "discrete"; + break; + case DD_CONTINUOUS: + out << "continuous"; + break; + default: + assert(0); + break; + } + return out; +}