Parse/decorate sequential statements.

Get to the point where our sample program parses completely, and
the sequential statements generate SequentialStmt objects and a
process object in the architecture.

Also add a few missing expression types.
This commit is contained in:
Stephen Williams 2011-05-08 16:40:35 -07:00
parent 7afd4210db
commit 3e419dc854
11 changed files with 364 additions and 34 deletions

View File

@ -60,7 +60,7 @@ LIBS = @LIBS@ @EXTRALIBS@
M = StringHeap.o LineInfo.o M = StringHeap.o LineInfo.o
O = main.o architec.o architec_elaborate.o compiler.o entity.o entity_elaborate.o \ O = main.o architec.o architec_elaborate.o compiler.o entity.o entity_elaborate.o \
expression.o package.o scope.o vsignal.o vtype.o vtype_elaborate.o \ expression.o package.o scope.o sequential.o vsignal.o vtype.o vtype_elaborate.o \
lexor.o lexor_keyword.o parse.o \ lexor.o lexor_keyword.o parse.o \
parse_misc.o library.o vhdlreal.o vhdlint.o debug.o \ parse_misc.o library.o vhdlreal.o vhdlint.o debug.o \
architec_emit.o entity_emit.o expression_emit.o vtype_emit.o \ architec_emit.o entity_emit.o expression_emit.o vtype_emit.o \

View File

@ -70,3 +70,12 @@ ComponentInstantiation::ComponentInstantiation(perm_string i, perm_string c,
ComponentInstantiation::~ComponentInstantiation() ComponentInstantiation::~ComponentInstantiation()
{ {
} }
ProcessStatement::ProcessStatement(perm_string iname)
: iname_(iname)
{
}
ProcessStatement::~ProcessStatement()
{
}

View File

@ -122,4 +122,15 @@ class ComponentInstantiation : public Architecture::Statement {
std::map<perm_string,Expression*> port_map_; std::map<perm_string,Expression*> port_map_;
}; };
class ProcessStatement : public Architecture::Statement {
public:
ProcessStatement(perm_string iname);
~ProcessStatement();
private:
perm_string iname_;
};
#endif #endif

View File

@ -213,12 +213,25 @@ void ExpArithmetic::dump(ostream&out, int indent) const
dump_operands(out, indent+4); dump_operands(out, indent+4);
} }
void ExpAttribute::dump(ostream&out, int indent) const
{
out << setw(indent) << "" << "Attribute " << name_
<< " at " << get_fileline() << endl;
base_->dump(out, indent+4);
}
void ExpBinary::dump_operands(ostream&out, int indent) const void ExpBinary::dump_operands(ostream&out, int indent) const
{ {
operand1_->dump(out, indent); operand1_->dump(out, indent);
operand2_->dump(out, indent); operand2_->dump(out, indent);
} }
void ExpCharacter::dump(ostream&out, int indent) const
{
out << setw(indent) << "" << "Character '" << value_ << "'"
<< " at " << get_fileline() << endl;
}
void ExpInteger::dump(ostream&out, int indent) const void ExpInteger::dump(ostream&out, int indent) const
{ {
out << setw(indent) << "" << "Integer " << value_ out << setw(indent) << "" << "Integer " << value_
@ -262,6 +275,33 @@ void ExpName::dump(ostream&out, int indent) const
index_->dump(out, indent+6); index_->dump(out, indent+6);
} }
void ExpRelation::dump(ostream&out, int indent) const
{
out << setw(indent) << "" << "Relation ";
switch (fun_) {
case EQ:
out << "=";
break;
case LT:
out << "<";
break;
case GT:
out << ">";
break;
case NEQ:
out << "/=";
break;
case LE:
out << "<=";
break;
case GE:
out << ">=";
break;
}
out << endl;
dump_operands(out, indent+4);
}
void ExpUAbs::dump(ostream&out, int indent) const void ExpUAbs::dump(ostream&out, int indent) const
{ {
out << setw(indent) << "" << "abs() at " << get_fileline() << endl; out << setw(indent) << "" << "abs() at " << get_fileline() << endl;

View File

@ -36,6 +36,16 @@ bool Expression::evaluate(ScopeBase*, int64_t&) const
return false; return false;
} }
ExpAttribute::ExpAttribute(ExpName*bas, perm_string nam)
: base_(bas), name_(nam)
{
}
ExpAttribute::~ExpAttribute()
{
delete base_;
}
ExpBinary::ExpBinary(Expression*op1, Expression*op2) ExpBinary::ExpBinary(Expression*op1, Expression*op2)
: operand1_(op1), operand2_(op2) : operand1_(op1), operand2_(op2)
{ {
@ -118,6 +128,15 @@ bool ExpArithmetic::evaluate(ScopeBase*scope, int64_t&val) const
return true; return true;
} }
ExpCharacter::ExpCharacter(char val)
: value_(val)
{
}
ExpCharacter::~ExpCharacter()
{
}
ExpInteger::ExpInteger(int64_t val) ExpInteger::ExpInteger(int64_t val)
: value_(val) : value_(val)
{ {
@ -176,6 +195,15 @@ bool ExpName::evaluate(ScopeBase*scope, int64_t&val) const
return exp->evaluate(scope, val); return exp->evaluate(scope, val);
} }
ExpRelation::ExpRelation(ExpRelation::fun_t ty, Expression*op1, Expression*op2)
: ExpBinary(op1, op2), fun_(ty)
{
}
ExpRelation::~ExpRelation()
{
}
ExpUAbs::ExpUAbs(Expression*op1) ExpUAbs::ExpUAbs(Expression*op1)
: ExpUnary(op1) : ExpUnary(op1)
{ {

View File

@ -27,6 +27,8 @@ class Entity;
class Architecture; class Architecture;
class ScopeBase; class ScopeBase;
class ExpName;
/* /*
* The Expression class represents parsed expressions from the parsed * The Expression class represents parsed expressions from the parsed
* VHDL input. The Expression class is a virtual class that holds more * VHDL input. The Expression class is a virtual class that holds more
@ -122,6 +124,34 @@ class ExpArithmetic : public ExpBinary {
fun_t fun_; fun_t fun_;
}; };
class ExpAttribute : public Expression {
public:
ExpAttribute(ExpName*base, perm_string name);
~ExpAttribute();
int emit(ostream&out, Entity*ent, Architecture*arc);
void dump(ostream&out, int indent = 0) const;
private:
ExpName*base_;
perm_string name_;
};
class ExpCharacter : public Expression {
public:
ExpCharacter(char val);
~ExpCharacter();
int emit(ostream&out, Entity*ent, Architecture*arc);
bool is_primary(void) const;
void dump(ostream&out, int indent = 0) const;
private:
char value_;
};
class ExpInteger : public Expression { class ExpInteger : public Expression {
public: public:
@ -176,6 +206,22 @@ class ExpName : public Expression {
Expression*index_; Expression*index_;
}; };
class ExpRelation : public ExpBinary {
public:
enum fun_t { EQ, LT, GT, NEQ, LE, GE };
public:
ExpRelation(ExpRelation::fun_t ty, Expression*op1, Expression*op2);
~ExpRelation();
int emit(ostream&out, Entity*ent, Architecture*arc);
void dump(ostream&out, int indent = 0) const;
private:
fun_t fun_;
};
class ExpUAbs : public ExpUnary { class ExpUAbs : public ExpUnary {
public: public:

View File

@ -63,6 +63,15 @@ int ExpUnary::emit_operand1(ostream&out, Entity*ent, Architecture*arc)
return errors; return errors;
} }
int ExpAttribute::emit(ostream&out, Entity*ent, Architecture*arc)
{
int errors = 0;
out << "$ivl_attribute(";
errors += base_->emit(out, ent, arc);
out << ", \"" << name_ << "\")";
return errors;
}
int ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc) int ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc)
{ {
int errors = 0; int errors = 0;
@ -98,6 +107,17 @@ int ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc)
return errors; return errors;
} }
int ExpCharacter::emit(ostream&out, Entity*, Architecture*)
{
out << "\"" << value_ << "\"";
return 0;
}
bool ExpCharacter::is_primary(void) const
{
return true;
}
int ExpInteger::emit(ostream&out, Entity*, Architecture*) int ExpInteger::emit(ostream&out, Entity*, Architecture*)
{ {
out << value_; out << value_;
@ -160,6 +180,36 @@ bool ExpName::is_primary(void) const
return true; return true;
} }
int ExpRelation::emit(ostream&out, Entity*ent, Architecture*arc)
{
int errors = 0;
errors += emit_operand1(out, ent, arc);
switch (fun_) {
case EQ:
out << " == ";
break;
case LT:
out << " < ";
break;
case GT:
out << " > ";
break;
case NEQ:
out << " != ";
break;
case LE:
out << " <= ";
break;
case GE:
out << " >= ";
break;
}
errors += emit_operand2(out, ent, arc);
return errors;
}
int ExpUAbs::emit(ostream&out, Entity*ent, Architecture*arc) int ExpUAbs::emit(ostream&out, Entity*ent, Architecture*arc)
{ {
int errors = 0; int errors = 0;

View File

@ -27,6 +27,7 @@
# include "parse_misc.h" # include "parse_misc.h"
# include "architec.h" # include "architec.h"
# include "expression.h" # include "expression.h"
# include "sequential.h"
# include "package.h" # include "package.h"
# include "vsignal.h" # include "vsignal.h"
# include "vtype.h" # include "vtype.h"
@ -122,6 +123,9 @@ const VType*parse_type_by_name(perm_string name)
Expression*expr; Expression*expr;
std::list<Expression*>* expr_list; std::list<Expression*>* expr_list;
SequentialStmt* sequ;
std::list<SequentialStmt*>*sequ_list;
named_expr_t*named_expr; named_expr_t*named_expr;
std::list<named_expr_t*>*named_expr_list; std::list<named_expr_t*>*named_expr_list;
entity_aspect_t* entity_aspect; entity_aspect_t* entity_aspect;
@ -204,6 +208,9 @@ const VType*parse_type_by_name(perm_string name)
%type <compound_name> prefix selected_name %type <compound_name> prefix selected_name
%type <compound_name_list> selected_names use_clause %type <compound_name_list> selected_names use_clause
%type <sequ_list> sequence_of_statements if_statement_else
%type <sequ> sequential_statement if_statement signal_assignment_statement
%% %%
/* The design_file is the root for the VHDL parse. */ /* The design_file is the root for the VHDL parse. */
@ -748,28 +755,38 @@ if_statement
: K_if expression K_then sequence_of_statements : K_if expression K_then sequence_of_statements
if_statement_else if_statement_else
K_end K_if ';' K_end K_if ';'
{ IfSequential*tmp = new IfSequential($2, $4, $5);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| K_if error K_then sequence_of_statements | K_if error K_then sequence_of_statements
if_statement_else if_statement_else
K_end K_if ';' K_end K_if ';'
{ errormsg(@2, "Error in if_statement condition expression.\n"); { errormsg(@2, "Error in if_statement condition expression.\n");
yyerrok; yyerrok;
$$ = 0;
delete $4;
} }
| K_if expression K_then error K_end K_if ';' | K_if expression K_then error K_end K_if ';'
{ errormsg(@2, "Too many errors in sequence within if_statement.\n"); { errormsg(@2, "Too many errors in sequence within if_statement.\n");
yyerrok; yyerrok;
$$ = 0;
} }
| K_if error K_end K_if ';' | K_if error K_end K_if ';'
{ errormsg(@2, "Too many errors in if_statement.\n"); { errormsg(@2, "Too many errors in if_statement.\n");
yyerrok; yyerrok;
$$ = 0;
} }
; ;
if_statement_else if_statement_else
: K_else sequence_of_statements : K_else sequence_of_statements
{ $$ = $2; }
| |
{ $$ = 0; }
; ;
instantiation_list instantiation_list
@ -1008,13 +1025,14 @@ primary
: name : name
{ $$ = $1; } { $$ = $1; }
| name '\'' IDENTIFIER | name '\'' IDENTIFIER
{ sorrymsg(@3, "Identifier attributes not supported.\n"); { perm_string name = lex_strings.make($3);
ExpName*base = dynamic_cast<ExpName*> ($1);
ExpAttribute*tmp = new ExpAttribute(base, name);
delete[]$3; delete[]$3;
$$ = $1; $$ = tmp;
} }
| CHARACTER_LITERAL | CHARACTER_LITERAL
{ sorrymsg(@1, "Character literals not supported.\n"); { ExpCharacter*tmp = new ExpCharacter($1[0]);
ExpInteger*tmp = new ExpInteger($1[0]);
FILE_NAME(tmp,@1); FILE_NAME(tmp,@1);
delete[]$1; delete[]$1;
$$ = tmp; $$ = tmp;
@ -1037,10 +1055,19 @@ primary_unit
process_statement process_statement
: IDENTIFIER ':' K_postponed_opt K_process : IDENTIFIER ':' K_postponed_opt K_process
process_sensitivity_list_opt K_is_opt process_sensitivity_list_opt K_is_opt
K_begin process_statement_part K_begin sequence_of_statements
K_end K_postponed_opt K_process identifier_opt ';' K_end K_postponed_opt K_process identifier_opt ';'
{ sorrymsg(@4, "Concurrent processes not implemented yet.\n"); { perm_string iname = lex_strings.make($1);
$$ = 0; if ($12) {
if (iname != $12)
errormsg(@12, "Process name %s does not match opening name %s.\n",
$12, $1);
delete[]$12;
}
ProcessStatement*tmp = new ProcessStatement(iname);
FILE_NAME(tmp, @4);
$$ = tmp;
} }
| IDENTIFIER ':' K_postponed_opt K_process | IDENTIFIER ':' K_postponed_opt K_process
@ -1053,11 +1080,6 @@ process_statement
} }
; ;
process_statement_part
: process_statement_part sequential_statement
| sequential_statement
;
process_sensitivity_list_opt process_sensitivity_list_opt
: '(' process_sensitivity_list ')' : '(' process_sensitivity_list ')'
| '(' error ')' | '(' error ')'
@ -1074,34 +1096,34 @@ relation
: shift_expression : shift_expression
{ $$ = $1; } { $$ = $1; }
| shift_expression '=' shift_expression | shift_expression '=' shift_expression
{ sorrymsg(@2, "Expression operator '=' not implemented.\n"); { ExpRelation*tmp = new ExpRelation(ExpRelation::EQ, $1, $3);
delete $3; FILE_NAME(tmp, @2);
$$ = $1; $$ = tmp;
} }
| shift_expression '<' shift_expression | shift_expression '<' shift_expression
{ sorrymsg(@2, "Expression operator '<' not implemented.\n"); { ExpRelation*tmp = new ExpRelation(ExpRelation::LT, $1, $3);
delete $3; FILE_NAME(tmp, @2);
$$ = $1; $$ = tmp;
} }
| shift_expression '>' shift_expression | shift_expression '>' shift_expression
{ sorrymsg(@2, "Expression operator '>' not implemented.\n"); { ExpRelation*tmp = new ExpRelation(ExpRelation::GT, $1, $3);
delete $3; FILE_NAME(tmp, @2);
$$ = $1; $$ = tmp;
} }
| shift_expression LEQ shift_expression | shift_expression LEQ shift_expression
{ sorrymsg(@2, "Expression operator '<=' not implemented.\n"); { ExpRelation*tmp = new ExpRelation(ExpRelation::LE, $1, $3);
delete $3; FILE_NAME(tmp, @2);
$$ = $1; $$ = tmp;
} }
| shift_expression GEQ shift_expression | shift_expression GEQ shift_expression
{ sorrymsg(@2, "Expression operator '>=' not implemented.\n"); { ExpRelation*tmp = new ExpRelation(ExpRelation::GE, $1, $3);
delete $3; FILE_NAME(tmp, @2);
$$ = $1; $$ = tmp;
} }
| shift_expression NE shift_expression | shift_expression NE shift_expression
{ sorrymsg(@2, "Expression operator '/=' not implemented.\n"); { ExpRelation*tmp = new ExpRelation(ExpRelation::NEQ, $1, $3);
delete $3; FILE_NAME(tmp, @2);
$$ = $1; $$ = tmp;
} }
; ;
@ -1165,12 +1187,20 @@ selected_names_use
sequence_of_statements sequence_of_statements
: sequence_of_statements sequential_statement : sequence_of_statements sequential_statement
{ std::list<SequentialStmt*>*tmp = $1;
tmp->push_back($2);
$$ = tmp;
}
| sequential_statement | sequential_statement
{ std::list<SequentialStmt*>*tmp = new std::list<SequentialStmt*>;
tmp->push_back($1);
$$ = tmp;
}
; ;
sequential_statement sequential_statement
: if_statement : if_statement { $$ = $1; }
| signal_assignment_statement | signal_assignment_statement { $$ = $1; }
; ;
shift_expression : simple_expression { $$ = $1; } ; shift_expression : simple_expression { $$ = $1; } ;
@ -1192,7 +1222,11 @@ simple_expression
signal_assignment_statement signal_assignment_statement
: name LEQ waveform ';' : name LEQ waveform ';'
{ sorrymsg(@1, "Signal assignment statements not implemented.\n"); } { SignalSeqAssignment*tmp = new SignalSeqAssignment($1, $3);
FILE_NAME(tmp, @1);
delete $3;
$$ = tmp;
}
; ;
subtype_declaration subtype_declaration

View File

@ -30,6 +30,7 @@
# include "vhdlreal.h" # include "vhdlreal.h"
# include "architec.h" # include "architec.h"
# include "expression.h" # include "expression.h"
# include "sequential.h"
# include "parse_types.h" # include "parse_types.h"
class VType; class VType;

53
vhdlpp/sequential.cc Normal file
View File

@ -0,0 +1,53 @@
/*
* 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"
SequentialStmt::SequentialStmt()
{
}
SequentialStmt::~SequentialStmt()
{
}
IfSequential::IfSequential(Expression*cond, std::list<SequentialStmt*>*tr,
std::list<SequentialStmt*>*fa)
{
cond_ = cond;
if (tr) if_.splice(if_.end(), *tr);
if (fa) else_.splice(else_.end(), *fa);
}
IfSequential::~IfSequential()
{
delete cond_;
}
SignalSeqAssignment::SignalSeqAssignment(Expression*sig, std::list<Expression*>*wav)
{
lval_ = sig;
if (wav) waveform_.splice(waveform_.end(), *wav);
}
SignalSeqAssignment::~SignalSeqAssignment()
{
delete lval_;
}

58
vhdlpp/sequential.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef __sequential_H
#define __sequential_H
/*
* 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 "LineInfo.h"
# include <list>
class Expression;
class SequentialStmt : public LineInfo {
public:
SequentialStmt();
~SequentialStmt();
};
class IfSequential : public SequentialStmt {
public:
IfSequential(Expression*cond, std::list<SequentialStmt*>*tr,
std::list<SequentialStmt*>*fa);
~IfSequential();
private:
Expression*cond_;
std::list<SequentialStmt*> if_;
std::list<SequentialStmt*> else_;
};
class SignalSeqAssignment : public SequentialStmt {
public:
SignalSeqAssignment(Expression*sig, std::list<Expression*>*wav);
~SignalSeqAssignment();
private:
Expression*lval_;
std::list<Expression*> waveform_;
};
#endif