From fc25ccde06ef4b98797ef8583ddbae2be1adcc47 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 15 May 2011 11:07:42 -0700 Subject: [PATCH] Basic emit of sequential code Infrastructure for debug and emit of sequential statements in processes. This does not properly handle the actual semantics of the behavioral code, but it provides an infrastructure where we can handle all the tricky elaboration to come. --- vhdlpp/Makefile.in | 4 +- vhdlpp/architec.cc | 10 ++++- vhdlpp/architec.h | 9 ++++- vhdlpp/architec_debug.cc | 17 +++++++++ vhdlpp/architec_emit.cc | 32 ++++++++++++++++ vhdlpp/debug.cc | 5 +++ vhdlpp/expression.h | 14 ++++++- vhdlpp/parse.y | 34 ++++++++++++++++- vhdlpp/sequential.h | 15 +++++++- vhdlpp/sequential_debug.cc | 63 ++++++++++++++++++++++++++++++++ vhdlpp/sequential_emit.cc | 75 ++++++++++++++++++++++++++++++++++++++ 11 files changed, 268 insertions(+), 10 deletions(-) create mode 100644 vhdlpp/sequential_debug.cc create mode 100644 vhdlpp/sequential_emit.cc 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; +}