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
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 \
parse_misc.o library.o vhdlreal.o vhdlint.o debug.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()
{
}
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_;
};
class ProcessStatement : public Architecture::Statement {
public:
ProcessStatement(perm_string iname);
~ProcessStatement();
private:
perm_string iname_;
};
#endif

View File

@ -213,12 +213,25 @@ void ExpArithmetic::dump(ostream&out, int indent) const
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
{
operand1_->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
{
out << setw(indent) << "" << "Integer " << value_
@ -262,6 +275,33 @@ void ExpName::dump(ostream&out, int indent) const
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
{
out << setw(indent) << "" << "abs() at " << get_fileline() << endl;

View File

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

View File

@ -27,6 +27,8 @@ class Entity;
class Architecture;
class ScopeBase;
class ExpName;
/*
* The Expression class represents parsed expressions from the parsed
* VHDL input. The Expression class is a virtual class that holds more
@ -122,6 +124,34 @@ class ExpArithmetic : public ExpBinary {
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 {
public:
@ -176,6 +206,22 @@ class ExpName : public Expression {
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 {
public:

View File

@ -63,6 +63,15 @@ int ExpUnary::emit_operand1(ostream&out, Entity*ent, Architecture*arc)
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 errors = 0;
@ -98,6 +107,17 @@ int ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc)
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*)
{
out << value_;
@ -160,6 +180,36 @@ bool ExpName::is_primary(void) const
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 errors = 0;

View File

@ -27,6 +27,7 @@
# include "parse_misc.h"
# include "architec.h"
# include "expression.h"
# include "sequential.h"
# include "package.h"
# include "vsignal.h"
# include "vtype.h"
@ -122,6 +123,9 @@ const VType*parse_type_by_name(perm_string name)
Expression*expr;
std::list<Expression*>* expr_list;
SequentialStmt* sequ;
std::list<SequentialStmt*>*sequ_list;
named_expr_t*named_expr;
std::list<named_expr_t*>*named_expr_list;
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_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. */
@ -748,28 +755,38 @@ if_statement
: K_if expression K_then sequence_of_statements
if_statement_else
K_end K_if ';'
{ IfSequential*tmp = new IfSequential($2, $4, $5);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| K_if error K_then sequence_of_statements
if_statement_else
K_end K_if ';'
{ errormsg(@2, "Error in if_statement condition expression.\n");
yyerrok;
$$ = 0;
delete $4;
}
| K_if expression K_then error K_end K_if ';'
{ errormsg(@2, "Too many errors in sequence within if_statement.\n");
yyerrok;
$$ = 0;
}
| K_if error K_end K_if ';'
{ errormsg(@2, "Too many errors in if_statement.\n");
yyerrok;
$$ = 0;
}
;
if_statement_else
: K_else sequence_of_statements
{ $$ = $2; }
|
{ $$ = 0; }
;
instantiation_list
@ -1008,13 +1025,14 @@ primary
: name
{ $$ = $1; }
| 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;
$$ = $1;
$$ = tmp;
}
| CHARACTER_LITERAL
{ sorrymsg(@1, "Character literals not supported.\n");
ExpInteger*tmp = new ExpInteger($1[0]);
{ ExpCharacter*tmp = new ExpCharacter($1[0]);
FILE_NAME(tmp,@1);
delete[]$1;
$$ = tmp;
@ -1037,10 +1055,19 @@ primary_unit
process_statement
: IDENTIFIER ':' K_postponed_opt K_process
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 ';'
{ sorrymsg(@4, "Concurrent processes not implemented yet.\n");
$$ = 0;
{ perm_string iname = lex_strings.make($1);
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
@ -1053,11 +1080,6 @@ process_statement
}
;
process_statement_part
: process_statement_part sequential_statement
| sequential_statement
;
process_sensitivity_list_opt
: '(' process_sensitivity_list ')'
| '(' error ')'
@ -1074,34 +1096,34 @@ relation
: shift_expression
{ $$ = $1; }
| shift_expression '=' shift_expression
{ sorrymsg(@2, "Expression operator '=' not implemented.\n");
delete $3;
$$ = $1;
{ ExpRelation*tmp = new ExpRelation(ExpRelation::EQ, $1, $3);
FILE_NAME(tmp, @2);
$$ = tmp;
}
| shift_expression '<' shift_expression
{ sorrymsg(@2, "Expression operator '<' not implemented.\n");
delete $3;
$$ = $1;
{ ExpRelation*tmp = new ExpRelation(ExpRelation::LT, $1, $3);
FILE_NAME(tmp, @2);
$$ = tmp;
}
| shift_expression '>' shift_expression
{ sorrymsg(@2, "Expression operator '>' not implemented.\n");
delete $3;
$$ = $1;
{ ExpRelation*tmp = new ExpRelation(ExpRelation::GT, $1, $3);
FILE_NAME(tmp, @2);
$$ = tmp;
}
| shift_expression LEQ shift_expression
{ sorrymsg(@2, "Expression operator '<=' not implemented.\n");
delete $3;
$$ = $1;
{ ExpRelation*tmp = new ExpRelation(ExpRelation::LE, $1, $3);
FILE_NAME(tmp, @2);
$$ = tmp;
}
| shift_expression GEQ shift_expression
{ sorrymsg(@2, "Expression operator '>=' not implemented.\n");
delete $3;
$$ = $1;
{ ExpRelation*tmp = new ExpRelation(ExpRelation::GE, $1, $3);
FILE_NAME(tmp, @2);
$$ = tmp;
}
| shift_expression NE shift_expression
{ sorrymsg(@2, "Expression operator '/=' not implemented.\n");
delete $3;
$$ = $1;
{ ExpRelation*tmp = new ExpRelation(ExpRelation::NEQ, $1, $3);
FILE_NAME(tmp, @2);
$$ = tmp;
}
;
@ -1165,12 +1187,20 @@ selected_names_use
sequence_of_statements
: sequence_of_statements sequential_statement
{ std::list<SequentialStmt*>*tmp = $1;
tmp->push_back($2);
$$ = tmp;
}
| sequential_statement
{ std::list<SequentialStmt*>*tmp = new std::list<SequentialStmt*>;
tmp->push_back($1);
$$ = tmp;
}
;
sequential_statement
: if_statement
| signal_assignment_statement
: if_statement { $$ = $1; }
| signal_assignment_statement { $$ = $1; }
;
shift_expression : simple_expression { $$ = $1; } ;
@ -1192,7 +1222,11 @@ simple_expression
signal_assignment_statement
: 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

View File

@ -30,6 +30,7 @@
# include "vhdlreal.h"
# include "architec.h"
# include "expression.h"
# include "sequential.h"
# include "parse_types.h"
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