diff --git a/vhdlpp/Makefile.in b/vhdlpp/Makefile.in index 3622fd413..9742eb764 100644 --- a/vhdlpp/Makefile.in +++ b/vhdlpp/Makefile.in @@ -63,8 +63,8 @@ O = main.o architec.o architec_elaborate.o compiler.o entity.o entity_elaborate. expression.o package.o scope.o sequential.o vsignal.o vtype.o vtype_elaborate.o \ lexor.o lexor_keyword.o parse.o \ parse_misc.o library.o vhdlreal.o vhdlint.o \ - architec_emit.o entity_emit.o expression_emit.o vtype_emit.o \ - debug.o architec_debug.o \ + architec_emit.o entity_emit.o expression_emit.o sequential_emit.o vtype_emit.o \ + debug.o architec_debug.o sequential_debug.o \ $M all: dep vhdlpp@EXEEXT@ diff --git a/vhdlpp/architec.cc b/vhdlpp/architec.cc index 4c1f93aa6..b034d4346 100644 --- a/vhdlpp/architec.cc +++ b/vhdlpp/architec.cc @@ -71,9 +71,15 @@ ComponentInstantiation::~ComponentInstantiation() { } -ProcessStatement::ProcessStatement(perm_string iname) - : iname_(iname) +ProcessStatement::ProcessStatement(perm_string iname, + std::list*sensitivity_list, + std::list*statements_list) +: iname_(iname) { + if (sensitivity_list) + sensitivity_list_.splice(sensitivity_list_.end(), *sensitivity_list); + if (statements_list) + statements_list_.splice(statements_list_.end(), *statements_list); } ProcessStatement::~ProcessStatement() diff --git a/vhdlpp/architec.h b/vhdlpp/architec.h index 858b3e760..34b67e23a 100644 --- a/vhdlpp/architec.h +++ b/vhdlpp/architec.h @@ -29,6 +29,7 @@ class ComponentBase; class Entity; class Expression; class ExpName; +class SequentialStmt; class Signal; class named_expr_t; @@ -125,15 +126,21 @@ class ComponentInstantiation : public Architecture::Statement { class ProcessStatement : public Architecture::Statement { public: - ProcessStatement(perm_string iname); + ProcessStatement(perm_string iname, + std::list*sensitivity_list, + std::list*statement_list); ~ProcessStatement(); virtual int elaborate(Entity*ent, Architecture*arc); + virtual int emit(ostream&out, Entity*entity, Architecture*arc); virtual void dump(ostream&out, int indent =0) const; private: perm_string iname_; + std::list sensitivity_list_; + std::list statements_list_; + }; #endif diff --git a/vhdlpp/architec_debug.cc b/vhdlpp/architec_debug.cc index 020328800..29771e08e 100644 --- a/vhdlpp/architec_debug.cc +++ b/vhdlpp/architec_debug.cc @@ -19,10 +19,13 @@ # include "architec.h" # include "expression.h" +# include "sequential.h" # include # include # include +using namespace std; + void Architecture::dump(ostream&out, perm_string of_entity, int indent) const { out << setw(indent) << "" << "architecture " << name_ @@ -70,4 +73,18 @@ void ProcessStatement::dump(ostream&out, int indent) const { out << setw(indent) << "" << "ProcessStatement name_=" << iname_ << " file=" << get_fileline() << endl; + + out << setw(indent+3) << "" << "Sensitivity_list:" << endl; + + for (list::const_iterator cur = sensitivity_list_.begin() + ; cur != sensitivity_list_.end() ; ++cur) { + (*cur)->dump(out, indent+4); + } + + out << setw(indent+3) << "" << "sequence of statements:" << endl; + + for (list::const_iterator cur = statements_list_.begin() + ; cur != statements_list_.end() ; ++cur) { + (*cur)->dump(out, indent+4); + } } diff --git a/vhdlpp/architec_emit.cc b/vhdlpp/architec_emit.cc index 7380bbea7..c55472d5b 100644 --- a/vhdlpp/architec_emit.cc +++ b/vhdlpp/architec_emit.cc @@ -20,6 +20,7 @@ # include "architec.h" # include "entity.h" # include "expression.h" +# include "sequential.h" # include "vsignal.h" # include # include @@ -104,3 +105,34 @@ int ComponentInstantiation::emit(ostream&out, Entity*ent, Architecture*arc) return errors; } + +int ProcessStatement::emit(ostream&out, Entity*ent, Architecture*arc) +{ + int errors = 0; + + out << "always"; + + if (sensitivity_list_.size() > 0) { + out << " @("; + const char*comma = 0; + for (list::iterator cur = sensitivity_list_.begin() + ; cur != sensitivity_list_.end() ; ++cur) { + + if (comma) out << comma; + errors += (*cur)->emit(out, ent, arc); + comma = ", "; + } + out << ")"; + } + + out << " begin" << endl; + + for (list::iterator cur = statements_list_.begin() + ; cur != statements_list_.end() ; ++cur) { + (*cur)->emit(out, ent, arc); + } + + out << "end" << endl; + return errors; + +} diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index 6ca175f0e..66bfab0cf 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -232,6 +232,11 @@ void ExpName::dump(ostream&out, int indent) const index_->dump(out, indent+6); } +void ExpNameALL::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "ExpNameALL at " << get_fileline() << endl; +} + void ExpRelation::dump(ostream&out, int indent) const { out << setw(indent) << "" << "Relation "; diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 311518806..3ab4ce6cc 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -185,12 +185,13 @@ class ExpLogical : public ExpBinary { /* * The ExpName class represents an expression that is an identifier or - * other sort of name. + * other sort of name. The ExpNameALL is a special case of ExpName + * that represents the "all" keyword is contexts that can handle it. */ class ExpName : public Expression { public: - ExpName(perm_string nn); + explicit ExpName(perm_string nn); ExpName(perm_string nn, Expression*index); ~ExpName(); @@ -206,6 +207,15 @@ class ExpName : public Expression { Expression*index_; }; +class ExpNameALL : public ExpName { + + public: + ExpNameALL() : ExpName(perm_string()) { } + + public: + void dump(ostream&out, int indent =0) const; +}; + class ExpRelation : public ExpBinary { public: diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index a9378b6e7..78b97b7e2 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -196,6 +196,8 @@ const VType*parse_type_by_name(perm_string name) %type shift_expression simple_expression term waveform_element %type waveform waveform_elements +%type name_list +%type process_sensitivity_list process_sensitivity_list_opt %type association_element %type association_list port_map_aspect port_map_aspect_opt @@ -894,7 +896,15 @@ name /* Handle name lists as lists of expressions. */ name_list : name_list ',' name + { std::list*tmp = $1; + tmp->push_back($3); + $$ = tmp; + } | name + { std::list*tmp = new std::list; + tmp->push_back($1); + $$ = tmp; + } ; package_declaration @@ -1028,6 +1038,7 @@ primary { perm_string name = lex_strings.make($3); ExpName*base = dynamic_cast ($1); ExpAttribute*tmp = new ExpAttribute(base, name); + FILE_NAME(tmp, @3); delete[]$3; $$ = tmp; } @@ -1065,8 +1076,10 @@ process_statement delete[]$12; } - ProcessStatement*tmp = new ProcessStatement(iname); + ProcessStatement*tmp = new ProcessStatement(iname, $5, $8); FILE_NAME(tmp, @4); + delete $5; + delete $8; $$ = tmp; } @@ -1080,16 +1093,33 @@ process_statement } ; +/* + * A process_sentitivity_list is: + * if the list is not present, or + * or a non-empty list of actual expressions. + */ process_sensitivity_list_opt : '(' process_sensitivity_list ')' + { $$ = $2; } | '(' error ')' - { errormsg(@2, "Error in process sensitivity list\n"); } + { errormsg(@2, "Error in process sensitivity list\n"); + yyerrok; + $$ = 0; + } | + { $$ = 0; } ; process_sensitivity_list : K_all + { std::list*tmp = new std::list; + ExpName*all = new ExpNameALL; + FILE_NAME(all, @1); + tmp->push_back(all); + $$ = tmp; + } | name_list + { $$ = $1; } ; relation diff --git a/vhdlpp/sequential.h b/vhdlpp/sequential.h index 577567138..1a6fe9474 100644 --- a/vhdlpp/sequential.h +++ b/vhdlpp/sequential.h @@ -22,14 +22,19 @@ # include "LineInfo.h" # include +class Architecture; +class Entity; class Expression; class SequentialStmt : public LineInfo { public: SequentialStmt(); - ~SequentialStmt(); + virtual ~SequentialStmt() =0; + public: + virtual int emit(ostream&out, Entity*entity, Architecture*arc); + virtual void dump(ostream&out, int indent) const; }; class IfSequential : public SequentialStmt { @@ -39,6 +44,10 @@ class IfSequential : public SequentialStmt { std::list*fa); ~IfSequential(); + public: + int emit(ostream&out, Entity*entity, Architecture*arc); + void dump(ostream&out, int indent) const; + private: Expression*cond_; std::list if_; @@ -50,6 +59,10 @@ class SignalSeqAssignment : public SequentialStmt { SignalSeqAssignment(Expression*sig, std::list*wav); ~SignalSeqAssignment(); + public: + int emit(ostream&out, Entity*entity, Architecture*arc); + void dump(ostream&out, int indent) const; + private: Expression*lval_; std::list waveform_; diff --git a/vhdlpp/sequential_debug.cc b/vhdlpp/sequential_debug.cc new file mode 100644 index 000000000..8dc688878 --- /dev/null +++ b/vhdlpp/sequential_debug.cc @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2011 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 "sequential.h" +# include "expression.h" +# include +# include +# include + +using namespace std; + +void SequentialStmt::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "SequentialStmt[" << typeid(*this).name() << "]" + << " at file=" << get_fileline() << endl; +} + +void IfSequential::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "IfSequential at file=" << get_fileline() << endl; + out << setw(indent+3) << "" << "Condition:" << endl; + cond_->dump(out, indent+4); + + out << setw(indent+3) << "" << "TRUE clause (" << if_.size() << "):" << endl; + for (list::const_iterator cur = if_.begin() + ; cur != if_.end() ; ++cur) + (*cur)->dump(out, indent+4); + + out << setw(indent+3) << "" << "FALSE clause (" << else_.size() << "):" << endl; + for (list::const_iterator cur = else_.begin() + ; cur != else_.end() ; ++cur) + (*cur)->dump(out, indent+4); + +} + +void SignalSeqAssignment::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "SignalSeqAssignment at file=" << get_fileline() << endl; + + out << setw(indent+3) << "" << "l-value:" << endl; + lval_->dump(out, indent+4); + + out << setw(indent+3) << "" << "r-values (" << waveform_.size() << "):" << endl; + for (list::const_iterator cur = waveform_.begin() + ; cur != waveform_.end() ; ++cur) + (*cur)->dump(out, indent+4); +} diff --git a/vhdlpp/sequential_emit.cc b/vhdlpp/sequential_emit.cc new file mode 100644 index 000000000..e2f792124 --- /dev/null +++ b/vhdlpp/sequential_emit.cc @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2011 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 "sequential.h" +# include "expression.h" +# include +# include + +int SequentialStmt::emit(ostream&out, Entity*ent, Architecture*arc) +{ + out << " // " << get_fileline() << ": internal error: " + << "I don't know how to emit this sequential statement! " + << "type=" << typeid(*this).name() << endl; + return 1; +} + +int IfSequential::emit(ostream&out, Entity*ent, Architecture*arc) +{ + int errors = 0; + out << "if ("; + errors += cond_->emit(out, ent, arc); + out << ") begin" << endl; + + for (list::iterator cur = if_.begin() + ; cur != if_.end() ; ++cur) + (*cur)->emit(out, ent, arc); + + if (else_.size() > 0) { + out << "end else begin" << endl; + + for (list::iterator cur = else_.begin() + ; cur != else_.end() ; ++cur) + (*cur)->emit(out, ent, arc); + + } + + out << "end" << endl; + return errors; +} + +int SignalSeqAssignment::emit(ostream&out, Entity*ent, Architecture*arc) +{ + int errors = 0; + + errors += lval_->emit(out, ent, arc); + + if (waveform_.size() != 1) { + out << "/* Confusing waveform? */;" << endl; + errors += 1; + + } else { + Expression*tmp = waveform_.front(); + out << " <= "; + tmp->emit(out, ent, arc); + out << ";" << endl; + } + + return errors; +}