Conditional statements and expressions
Elaborate and emit a variety of conditional constructs. Fix up type handling for some expression types Elaborate continuous signal assignments.
This commit is contained in:
parent
2e28782af3
commit
bf40c8ecc5
|
|
@ -48,6 +48,12 @@ SignalAssignment::SignalAssignment(ExpName*name, list<Expression*>&rv)
|
|||
rval_.splice(rval_.end(), rv);
|
||||
}
|
||||
|
||||
SignalAssignment::SignalAssignment(ExpName*name, Expression*rv)
|
||||
: lval_(name)
|
||||
{
|
||||
rval_.push_back(rv);
|
||||
}
|
||||
|
||||
SignalAssignment::~SignalAssignment()
|
||||
{
|
||||
for (list<Expression*>::iterator cur = rval_.begin()
|
||||
|
|
|
|||
|
|
@ -95,8 +95,10 @@ class SignalAssignment : public Architecture::Statement {
|
|||
|
||||
public:
|
||||
SignalAssignment(ExpName*target, std::list<Expression*>&rval);
|
||||
SignalAssignment(ExpName*target, Expression*rval);
|
||||
~SignalAssignment();
|
||||
|
||||
virtual int elaborate(Entity*ent, Architecture*arc);
|
||||
virtual int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
virtual void dump(ostream&out, int ident =0) const;
|
||||
|
||||
|
|
@ -137,6 +139,7 @@ class ProcessStatement : public Architecture::Statement {
|
|||
|
||||
private:
|
||||
int rewrite_as_always_edge_(Entity*ent, Architecture*arc);
|
||||
int extract_anyedge_(Entity*ent, Architecture*arc);;
|
||||
|
||||
private:
|
||||
perm_string iname_;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ int Architecture::Statement::elaborate(Entity*, Architecture*)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc)
|
||||
int ComponentInstantiation::elaborate(Entity*, Architecture*arc)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc)
|
|||
* always-@(n-edge <expr>) version of the same statement. This makes
|
||||
* for a more natural translation to verilog, if it comes to that.
|
||||
*/
|
||||
int ProcessStatement::rewrite_as_always_edge_(Entity*ent, Architecture*arc)
|
||||
int ProcessStatement::rewrite_as_always_edge_(Entity*, Architecture*)
|
||||
{
|
||||
// If thare are multiple sensitivity expressions, I give up.
|
||||
if (sensitivity_list_.size() != 1)
|
||||
|
|
@ -93,6 +93,10 @@ int ProcessStatement::rewrite_as_always_edge_(Entity*ent, Architecture*arc)
|
|||
if (stmt == 0)
|
||||
return -1;
|
||||
|
||||
// If the "if" statement has a false clause, then give up.
|
||||
if (stmt->false_size() != 0)
|
||||
return -1;
|
||||
|
||||
const Expression*ce_raw = stmt->peek_condition();
|
||||
|
||||
// We expect the condition to be <name>'event AND <name>='1'.
|
||||
|
|
@ -145,31 +149,58 @@ int ProcessStatement::rewrite_as_always_edge_(Entity*ent, Architecture*arc)
|
|||
// And we can convert it to:
|
||||
// always @(<N>edge <se>) ...
|
||||
|
||||
// Replace the sensitivity expression with an edge expression.
|
||||
// Replace the sensitivity expression with an edge
|
||||
// expression. The ExpEdge expression signals that this is an
|
||||
// always-@(edge) statement.
|
||||
ExpEdge*edge = new ExpEdge(op2b->value()=='1'? ExpEdge::POSEDGE : ExpEdge::NEGEDGE, se);
|
||||
assert(sensitivity_list_.size() == 1);
|
||||
sensitivity_list_.pop_front();
|
||||
sensitivity_list_.push_front(edge);
|
||||
|
||||
// Replace the statement with the body of the always
|
||||
// statement, which is the true clause of the top "if"
|
||||
// statement. There should be no "else" clause.
|
||||
assert(statements_list_.size() == 1);
|
||||
statements_list_.pop_front();
|
||||
|
||||
stmt->extract_true(statements_list_);
|
||||
|
||||
std::list<SequentialStmt*> tmp;
|
||||
stmt->extract_false(tmp);
|
||||
assert(tmp.size() == 0);
|
||||
|
||||
delete stmt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the "process (<expr>) <stmt>" into "always @(<expr>) ..."
|
||||
*/
|
||||
int ProcessStatement::extract_anyedge_(Entity*, Architecture*)
|
||||
{
|
||||
|
||||
vector<Expression*> se;
|
||||
while (! sensitivity_list_.empty()) {
|
||||
se.push_back(sensitivity_list_.front());
|
||||
sensitivity_list_.pop_front();
|
||||
}
|
||||
|
||||
for (size_t idx = 0 ; idx < se.size() ; idx += 1) {
|
||||
ExpEdge*edge = new ExpEdge(ExpEdge::ANYEDGE, se[idx]);
|
||||
FILE_NAME(edge, se[idx]);
|
||||
sensitivity_list_.push_back(edge);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ProcessStatement::elaborate(Entity*ent, Architecture*arc)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
rewrite_as_always_edge_(ent, arc);
|
||||
if (rewrite_as_always_edge_(ent, arc) >= 0) {
|
||||
|
||||
} else if (extract_anyedge_(ent, arc) >= 0) {
|
||||
|
||||
} else {
|
||||
}
|
||||
|
||||
for (list<SequentialStmt*>::iterator cur = statements_list_.begin()
|
||||
; cur != statements_list_.end() ; ++cur) {
|
||||
|
|
@ -178,3 +209,27 @@ int ProcessStatement::elaborate(Entity*ent, Architecture*arc)
|
|||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int SignalAssignment::elaborate(Entity*ent, Architecture*arc)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
// Elaborate the l-value expression.
|
||||
errors += lval_->elaborate_lval(ent, arc);
|
||||
|
||||
// The elaborate_lval should have resolved the type of the
|
||||
// l-value expression. We'll use that type to elaborate the
|
||||
// r-value.
|
||||
const VType*lval_type = lval_->peek_type();
|
||||
if (lval_type == 0) {
|
||||
if (errors == 0) errors += 1;
|
||||
return errors;
|
||||
}
|
||||
|
||||
for (list<Expression*>::const_iterator cur = rval_.begin()
|
||||
; cur != rval_.end() ; ++cur) {
|
||||
(*cur)->elaborate_expr(ent, arc, lval_type);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ void ExpBitstring::dump(ostream&out, int indent) const
|
|||
for (size_t idx = value_.size() ; idx > 0 ; idx -= 1) {
|
||||
out << value_[idx-1];
|
||||
}
|
||||
out << "\"";
|
||||
out << "\"" << endl;
|
||||
}
|
||||
|
||||
void ExpCharacter::dump(ostream&out, int indent) const
|
||||
|
|
@ -202,6 +202,25 @@ void ExpCharacter::dump(ostream&out, int indent) const
|
|||
<< " at " << get_fileline() << endl;
|
||||
}
|
||||
|
||||
void ExpConditional::dump(ostream&out, int indent) const
|
||||
{
|
||||
out << setw(indent) << "" << "Conditional expression at "<< get_fileline() << endl;
|
||||
out << setw(indent) << "" << " when:" << endl;
|
||||
cond_->dump(out, indent+4);
|
||||
|
||||
out << setw(indent) << "" << " do:" << endl;
|
||||
for (list<Expression*>::const_iterator cur = true_clause_.begin()
|
||||
; cur != true_clause_.end() ; ++cur) {
|
||||
(*cur)->dump(out, indent+4);
|
||||
}
|
||||
|
||||
out << setw(indent) << "" << " else:" << endl;
|
||||
for (list<Expression*>::const_iterator cur = else_clause_.begin()
|
||||
; cur != else_clause_.end() ; ++cur) {
|
||||
(*cur)->dump(out, indent+4);
|
||||
}
|
||||
}
|
||||
|
||||
void ExpEdge::dump(ostream&out, int indent) const
|
||||
{
|
||||
out << setw(indent) << "";
|
||||
|
|
|
|||
|
|
@ -192,6 +192,28 @@ ExpCharacter::~ExpCharacter()
|
|||
{
|
||||
}
|
||||
|
||||
ExpConditional::ExpConditional(Expression*co, list<Expression*>*tru, list<Expression*>*els)
|
||||
: cond_(co)
|
||||
{
|
||||
if (tru) true_clause_.splice(true_clause_.end(), *tru);
|
||||
if (els) else_clause_.splice(else_clause_.end(), *els);
|
||||
}
|
||||
|
||||
ExpConditional::~ExpConditional()
|
||||
{
|
||||
delete cond_;
|
||||
while (! true_clause_.empty()) {
|
||||
Expression*tmp = true_clause_.front();
|
||||
true_clause_.pop_front();
|
||||
delete tmp;
|
||||
}
|
||||
while (! else_clause_.empty()) {
|
||||
Expression*tmp = else_clause_.front();
|
||||
else_clause_.pop_front();
|
||||
delete tmp;
|
||||
}
|
||||
}
|
||||
|
||||
ExpEdge::ExpEdge(ExpEdge::fun_t typ, Expression*op)
|
||||
: ExpUnary(op), fun_(typ)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -22,12 +22,14 @@
|
|||
# include "StringHeap.h"
|
||||
# include "LineInfo.h"
|
||||
# include <inttypes.h>
|
||||
# include <list>
|
||||
# include <vector>
|
||||
|
||||
class Entity;
|
||||
class Architecture;
|
||||
class ScopeBase;
|
||||
class VType;
|
||||
class VTypePrimitive;
|
||||
|
||||
class ExpName;
|
||||
|
||||
|
|
@ -101,6 +103,11 @@ class Expression : public LineInfo {
|
|||
Expression& operator = (const Expression&);
|
||||
};
|
||||
|
||||
static inline void FILE_NAME(Expression*tgt, const LineInfo*src)
|
||||
{
|
||||
tgt->set_line(*src);
|
||||
}
|
||||
|
||||
class ExpUnary : public Expression {
|
||||
|
||||
public:
|
||||
|
|
@ -128,6 +135,8 @@ class ExpBinary : public Expression {
|
|||
const Expression* peek_operand1(void) const { return operand1_; }
|
||||
const Expression* peek_operand2(void) const { return operand2_; }
|
||||
|
||||
const VType*probe_type(Entity*ent, Architecture*arc) const;
|
||||
|
||||
protected:
|
||||
|
||||
int elaborate_exprs(Entity*, Architecture*, const VType*);
|
||||
|
|
@ -153,10 +162,14 @@ class ExpArithmetic : public ExpBinary {
|
|||
ExpArithmetic(ExpArithmetic::fun_t op, Expression*op1, Expression*op2);
|
||||
~ExpArithmetic();
|
||||
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
virtual bool evaluate(ScopeBase*scope, int64_t&val) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
int emit_concat_(ostream&out, Entity*ent, Architecture*arc);
|
||||
|
||||
private:
|
||||
fun_t fun_;
|
||||
};
|
||||
|
|
@ -170,6 +183,7 @@ class ExpAttribute : public Expression {
|
|||
inline perm_string peek_attribute() const { return name_; }
|
||||
inline const ExpName* peek_base() const { return base_; }
|
||||
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
|
|
@ -184,6 +198,7 @@ class ExpBitstring : public Expression {
|
|||
explicit ExpBitstring(const char*);
|
||||
~ExpBitstring();
|
||||
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
|
|
@ -204,10 +219,37 @@ class ExpCharacter : public Expression {
|
|||
|
||||
char value() const { return value_; }
|
||||
|
||||
private:
|
||||
int emit_primitive_bit_(ostream&out, Entity*ent, Architecture*arc,
|
||||
const VTypePrimitive*etype);
|
||||
|
||||
private:
|
||||
char value_;
|
||||
};
|
||||
|
||||
/*
|
||||
* The conditional expression represents the VHDL when-else
|
||||
* expressions. Note that by the VHDL syntax rules, these cannot show
|
||||
* up other then at the root of an expression.
|
||||
*/
|
||||
class ExpConditional : public Expression {
|
||||
|
||||
public:
|
||||
ExpConditional(Expression*cond, std::list<Expression*>*tru,
|
||||
std::list<Expression*>*els);
|
||||
~ExpConditional();
|
||||
|
||||
const VType*probe_type(Entity*ent, Architecture*arc) const;
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
Expression*cond_;
|
||||
std::list<Expression*> true_clause_;
|
||||
std::list<Expression*> else_clause_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This is a special expression type that represents posedge/negedge
|
||||
* expressions in sensitivity lists.
|
||||
|
|
@ -256,6 +298,7 @@ class ExpLogical : public ExpBinary {
|
|||
|
||||
inline fun_t logic_fun() const { return fun_; }
|
||||
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,23 @@ int Expression::elaborate_expr(Entity*, Architecture*, const VType*)
|
|||
return 1;
|
||||
}
|
||||
|
||||
const VType* ExpBinary::probe_type(Entity*ent, Architecture*arc) const
|
||||
{
|
||||
const VType*t1 = operand1_->probe_type(ent, arc);
|
||||
const VType*t2 = operand2_->probe_type(ent, arc);
|
||||
|
||||
if (t1 == 0)
|
||||
return t2;
|
||||
if (t2 == 0)
|
||||
return t1;
|
||||
|
||||
if (t1 == t2)
|
||||
return t1;
|
||||
|
||||
cerr << get_fileline() << ": internal error: I don't know how to resolve types of generic binary expressions." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ExpBinary::elaborate_exprs(Entity*ent, Architecture*arc, const VType*ltype)
|
||||
{
|
||||
int errors = 0;
|
||||
|
|
@ -86,6 +103,33 @@ int ExpBinary::elaborate_exprs(Entity*ent, Architecture*arc, const VType*ltype)
|
|||
return errors;
|
||||
}
|
||||
|
||||
int ExpArithmetic::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if (ltype == 0) {
|
||||
ltype = probe_type(ent, arc);
|
||||
}
|
||||
|
||||
assert(ltype != 0);
|
||||
errors += elaborate_exprs(ent, arc, ltype);
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpAttribute::elaborate_expr(Entity*ent, Architecture*arc, const VType*)
|
||||
{
|
||||
int errors = 0;
|
||||
const VType*sub_type = base_->probe_type(ent, arc);
|
||||
errors += base_->elaborate_expr(ent, arc, sub_type);
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpBitstring::elaborate_expr(Entity*, Architecture*, const VType*)
|
||||
{
|
||||
int errors = 0;
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpCharacter::elaborate_expr(Entity*, Architecture*, const VType*ltype)
|
||||
{
|
||||
assert(ltype != 0);
|
||||
|
|
@ -93,6 +137,52 @@ int ExpCharacter::elaborate_expr(Entity*, Architecture*, const VType*ltype)
|
|||
return 0;
|
||||
}
|
||||
|
||||
const VType* ExpConditional::probe_type(Entity*, Architecture*) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ExpConditional::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if (ltype == 0)
|
||||
ltype = probe_type(ent, arc);
|
||||
|
||||
assert(ltype);
|
||||
|
||||
set_type(ltype);
|
||||
|
||||
/* Note that the type for the condition expression need not
|
||||
have anything to do with the type of this expression. */
|
||||
errors += cond_->elaborate_expr(ent, arc, 0);
|
||||
|
||||
for (list<Expression*>::const_iterator cur = true_clause_.begin()
|
||||
; cur != true_clause_.end() ; ++cur) {
|
||||
errors += (*cur)->elaborate_expr(ent, arc, ltype);
|
||||
}
|
||||
|
||||
for (list<Expression*>::const_iterator cur = else_clause_.begin()
|
||||
; cur != else_clause_.end() ; ++cur) {
|
||||
errors += (*cur)->elaborate_expr(ent, arc, ltype);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpLogical::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if (ltype == 0) {
|
||||
ltype = probe_type(ent, arc);
|
||||
}
|
||||
|
||||
assert(ltype != 0);
|
||||
errors += elaborate_exprs(ent, arc, ltype);
|
||||
return errors;
|
||||
}
|
||||
|
||||
const VType* ExpName::probe_type(Entity*ent, Architecture*arc) const
|
||||
{
|
||||
if (const InterfacePort*cur = ent->find_port(name_))
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
# include "vtype.h"
|
||||
# include <typeinfo>
|
||||
# include <iostream>
|
||||
# include <cassert>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
|
@ -77,6 +78,9 @@ int ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc)
|
|||
{
|
||||
int errors = 0;
|
||||
|
||||
if (fun_ == CONCAT)
|
||||
return emit_concat_(out, ent, arc);
|
||||
|
||||
errors += emit_operand1(out, ent, arc);
|
||||
|
||||
switch (fun_) {
|
||||
|
|
@ -111,43 +115,70 @@ int ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc)
|
|||
return errors;
|
||||
}
|
||||
|
||||
int ExpBitstring::emit(ostream&out, Entity*, Architecture*)
|
||||
int ExpArithmetic::emit_concat_(ostream&out, Entity*ent, Architecture*arc)
|
||||
{
|
||||
int errors = 0;
|
||||
errors += 1;
|
||||
out << "{";
|
||||
errors += emit_operand1(out, ent, arc);
|
||||
out << ", ";
|
||||
errors += emit_operand2(out, ent, arc);
|
||||
out << "}";
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpCharacter::emit(ostream&out, Entity*, Architecture*)
|
||||
int ExpBitstring::emit(ostream&out, Entity*, Architecture*)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
out << value_.size() << "'b";
|
||||
for (size_t idx = 0 ; idx < value_.size() ; idx += 1)
|
||||
out << value_[value_.size()-idx-1];
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpCharacter::emit_primitive_bit_(ostream&out, Entity*ent, Architecture*arc,
|
||||
const VTypePrimitive*etype)
|
||||
{
|
||||
switch (etype->type()) {
|
||||
case VTypePrimitive::BOOLEAN:
|
||||
case VTypePrimitive::BIT:
|
||||
switch (value_) {
|
||||
case '0':
|
||||
case '1':
|
||||
out << "1'b" << value_;
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case VTypePrimitive::STDLOGIC:
|
||||
switch (value_) {
|
||||
case '0':
|
||||
case '1':
|
||||
out << "1'b" << value_;
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int ExpCharacter::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
{
|
||||
const VType*etype = peek_type();
|
||||
|
||||
if (const VTypePrimitive*use_type = dynamic_cast<const VTypePrimitive*>(etype)) {
|
||||
switch (use_type->type()) {
|
||||
case VTypePrimitive::BOOLEAN:
|
||||
case VTypePrimitive::BIT:
|
||||
switch (value_) {
|
||||
case '0':
|
||||
case '1':
|
||||
out << "1'b" << value_;
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
return emit_primitive_bit_(out, ent, arc, use_type);
|
||||
}
|
||||
|
||||
case VTypePrimitive::STDLOGIC:
|
||||
switch (value_) {
|
||||
case '0':
|
||||
case '1':
|
||||
out << "1'b" << value_;
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return 1;
|
||||
if (const VTypeArray*array = dynamic_cast<const VTypeArray*>(etype)) {
|
||||
if (const VTypePrimitive*use_type = dynamic_cast<const VTypePrimitive*>(array->element_type())) {
|
||||
return emit_primitive_bit_(out, ent, arc, use_type);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -160,6 +191,36 @@ bool ExpCharacter::is_primary(void) const
|
|||
return true;
|
||||
}
|
||||
|
||||
int ExpConditional::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
{
|
||||
int errors = 0;
|
||||
out << "(";
|
||||
errors += cond_->emit(out, ent, arc);
|
||||
out << ")? (";
|
||||
|
||||
if (true_clause_.size() > 1) {
|
||||
cerr << get_fileline() << ": sorry: Multiple expressions not supported here." << endl;
|
||||
errors += 1;
|
||||
}
|
||||
|
||||
Expression*tmp = true_clause_.front();
|
||||
errors += tmp->emit(out, ent, arc);
|
||||
|
||||
out << ") : (";
|
||||
|
||||
if (else_clause_.size() > 1) {
|
||||
cerr << get_fileline() << ": sorry: Multiple expressions not supported here." << endl;
|
||||
errors += 1;
|
||||
}
|
||||
|
||||
tmp = else_clause_.front();
|
||||
errors += tmp->emit(out, ent, arc);
|
||||
|
||||
out << ")";
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpEdge::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
{
|
||||
int errors = 0;
|
||||
|
|
@ -170,9 +231,7 @@ int ExpEdge::emit(ostream&out, Entity*ent, Architecture*arc)
|
|||
case POSEDGE:
|
||||
out << "posedge ";
|
||||
break;
|
||||
default:
|
||||
out << "INVALIDedge ";
|
||||
errors += 1;
|
||||
case ANYEDGE:
|
||||
break;
|
||||
}
|
||||
errors += emit_operand1(out, ent, arc);
|
||||
|
|
|
|||
|
|
@ -126,6 +126,9 @@ const VType*parse_type_by_name(perm_string name)
|
|||
SequentialStmt* sequ;
|
||||
std::list<SequentialStmt*>*sequ_list;
|
||||
|
||||
IfSequential::Elsif*elsif;
|
||||
std::list<IfSequential::Elsif*>*elsif_list;
|
||||
|
||||
named_expr_t*named_expr;
|
||||
std::list<named_expr_t*>*named_expr_list;
|
||||
entity_aspect_t* entity_aspect;
|
||||
|
|
@ -213,6 +216,9 @@ const VType*parse_type_by_name(perm_string name)
|
|||
%type <sequ_list> sequence_of_statements if_statement_else
|
||||
%type <sequ> sequential_statement if_statement signal_assignment_statement
|
||||
|
||||
%type <elsif> if_statement_elsif
|
||||
%type <elsif_list> if_statement_elsif_list if_statement_elsif_list_opt
|
||||
|
||||
%%
|
||||
|
||||
/* The design_file is the root for the VHDL parse. */
|
||||
|
|
@ -346,7 +352,7 @@ block_declarative_item
|
|||
| component_declaration
|
||||
|
||||
| constant_declaration
|
||||
{ sorrymsg(@1, "constant declarations not supported here.\n"); }
|
||||
|
||||
| use_clause_lib
|
||||
|
||||
/* Various error handling rules for block_declarative_item... */
|
||||
|
|
@ -453,14 +459,17 @@ concurrent_signal_assignment_statement
|
|||
delete $3;
|
||||
}
|
||||
| name LEQ waveform K_when expression K_else waveform ';'
|
||||
{ ExpName*name = dynamic_cast<ExpName*> ($1);
|
||||
assert(name);
|
||||
SignalAssignment*tmp = new SignalAssignment(name, *$3);
|
||||
FILE_NAME(tmp, @1);
|
||||
|
||||
$$ = tmp;
|
||||
{ ExpConditional*tmp = new ExpConditional($5, $3, $7);
|
||||
FILE_NAME(tmp, @3);
|
||||
delete $3;
|
||||
sorrymsg(@4, "Conditional signal assignment not supported here.\n");
|
||||
delete $7;
|
||||
|
||||
ExpName*name = dynamic_cast<ExpName*> ($1);
|
||||
assert(name);
|
||||
SignalAssignment*tmpa = new SignalAssignment(name, tmp);
|
||||
FILE_NAME(tmpa, @1);
|
||||
|
||||
$$ = tmpa;
|
||||
}
|
||||
| name LEQ error ';'
|
||||
{ errormsg(@2, "Syntax error in signal assignment waveform.\n");
|
||||
|
|
@ -776,8 +785,11 @@ if_statement
|
|||
: K_if expression K_then sequence_of_statements
|
||||
if_statement_elsif_list_opt if_statement_else
|
||||
K_end K_if ';'
|
||||
{ IfSequential*tmp = new IfSequential($2, $4, $6);
|
||||
{ IfSequential*tmp = new IfSequential($2, $4, $5, $6);
|
||||
FILE_NAME(tmp, @1);
|
||||
delete $4;
|
||||
delete $5;
|
||||
delete $6;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
|
|
@ -804,21 +816,34 @@ if_statement
|
|||
;
|
||||
|
||||
if_statement_elsif_list_opt
|
||||
: if_statement_elsif_list
|
||||
|
|
||||
: if_statement_elsif_list { $$ = $1; }
|
||||
| { $$ = 0; }
|
||||
;
|
||||
|
||||
if_statement_elsif_list
|
||||
: if_statement_elsif_list if_statement_elsif
|
||||
{ list<IfSequential::Elsif*>*tmp = $1;
|
||||
tmp->push_back($2);
|
||||
$$ = tmp;
|
||||
}
|
||||
| if_statement_elsif
|
||||
{ list<IfSequential::Elsif*>*tmp = new list<IfSequential::Elsif*>;
|
||||
tmp->push_back($1);
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
if_statement_elsif
|
||||
: K_elsif expression K_then sequence_of_statements
|
||||
{ sorrymsg(@1, "elsif sub-statements are not supported.\n"); }
|
||||
{ IfSequential::Elsif*tmp = new IfSequential::Elsif($2, $4);
|
||||
FILE_NAME(tmp, @1);
|
||||
delete $4;
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_elsif expression K_then error
|
||||
{ errormsg(@4, "Too many errors in elsif sub-statements.\n");
|
||||
yyerrok;
|
||||
$$ = 0;
|
||||
}
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -29,10 +29,12 @@ SequentialStmt::~SequentialStmt()
|
|||
}
|
||||
|
||||
IfSequential::IfSequential(Expression*cond, std::list<SequentialStmt*>*tr,
|
||||
std::list<IfSequential::Elsif*>*el,
|
||||
std::list<SequentialStmt*>*fa)
|
||||
{
|
||||
cond_ = cond;
|
||||
if (tr) if_.splice(if_.end(), *tr);
|
||||
if (el) elsif_.splice(elsif_.end(), *el);
|
||||
if (fa) else_.splice(else_.end(), *fa);
|
||||
}
|
||||
|
||||
|
|
@ -44,6 +46,11 @@ IfSequential::~IfSequential()
|
|||
if_.pop_front();
|
||||
delete cur;
|
||||
}
|
||||
while (elsif_.size() > 0) {
|
||||
IfSequential::Elsif*cur = elsif_.front();
|
||||
elsif_.pop_front();
|
||||
delete cur;
|
||||
}
|
||||
while (else_.size() > 0) {
|
||||
SequentialStmt*cur = else_.front();
|
||||
else_.pop_front();
|
||||
|
|
@ -68,6 +75,22 @@ void IfSequential::extract_false(std::list<SequentialStmt*>&that)
|
|||
}
|
||||
}
|
||||
|
||||
IfSequential::Elsif::Elsif(Expression*cond, std::list<SequentialStmt*>*tr)
|
||||
: cond_(cond)
|
||||
{
|
||||
if (tr) if_.splice(if_.end(), *tr);
|
||||
}
|
||||
|
||||
IfSequential::Elsif::~Elsif()
|
||||
{
|
||||
delete cond_;
|
||||
while (if_.size() > 0) {
|
||||
SequentialStmt*cur = if_.front();
|
||||
if_.pop_front();
|
||||
delete cur;
|
||||
}
|
||||
}
|
||||
|
||||
SignalSeqAssignment::SignalSeqAssignment(Expression*sig, std::list<Expression*>*wav)
|
||||
{
|
||||
lval_ = sig;
|
||||
|
|
|
|||
|
|
@ -40,8 +40,25 @@ class SequentialStmt : public LineInfo {
|
|||
|
||||
class IfSequential : public SequentialStmt {
|
||||
|
||||
public:
|
||||
class Elsif : public LineInfo {
|
||||
public:
|
||||
Elsif(Expression*cond, std::list<SequentialStmt*>*tr);
|
||||
~Elsif();
|
||||
|
||||
void dump(ostream&out, int indent) const;
|
||||
|
||||
private:
|
||||
Expression*cond_;
|
||||
std::list<SequentialStmt*>if_;
|
||||
private: // not implemented
|
||||
Elsif(const Elsif&);
|
||||
Elsif& operator =(const Elsif&);
|
||||
};
|
||||
|
||||
public:
|
||||
IfSequential(Expression*cond, std::list<SequentialStmt*>*tr,
|
||||
std::list<IfSequential::Elsif*>*elsif,
|
||||
std::list<SequentialStmt*>*fa);
|
||||
~IfSequential();
|
||||
|
||||
|
|
@ -52,6 +69,8 @@ class IfSequential : public SequentialStmt {
|
|||
|
||||
const Expression*peek_condition() const { return cond_; }
|
||||
|
||||
size_t false_size() const { return else_.size(); }
|
||||
|
||||
// These method extract (and remove) the sub-statements from
|
||||
// the true or false clause.
|
||||
void extract_true(std::list<SequentialStmt*>&that);
|
||||
|
|
@ -60,6 +79,7 @@ class IfSequential : public SequentialStmt {
|
|||
private:
|
||||
Expression*cond_;
|
||||
std::list<SequentialStmt*> if_;
|
||||
std::list<IfSequential::Elsif*> elsif_;
|
||||
std::list<SequentialStmt*> else_;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,10 @@ void IfSequential::dump(ostream&out, int indent) const
|
|||
; cur != if_.end() ; ++cur)
|
||||
(*cur)->dump(out, indent+4);
|
||||
|
||||
for (list<IfSequential::Elsif*>::const_iterator cur = elsif_.begin()
|
||||
; cur != elsif_.end() ; ++cur)
|
||||
(*cur)->dump(out, indent);
|
||||
|
||||
out << setw(indent+3) << "" << "FALSE clause (" << else_.size() << "):" << endl;
|
||||
for (list<SequentialStmt*>::const_iterator cur = else_.begin()
|
||||
; cur != else_.end() ; ++cur)
|
||||
|
|
@ -49,6 +53,18 @@ void IfSequential::dump(ostream&out, int indent) const
|
|||
|
||||
}
|
||||
|
||||
void IfSequential::Elsif::dump(ostream&out, int indent) const
|
||||
{
|
||||
out << setw(indent+3) << "" << "Elsif Condition at " << get_fileline() << ":" << endl;
|
||||
cond_->dump(out, indent+4);
|
||||
|
||||
out << setw(indent+3) << "" << "ELSIF TRUE clause (" << if_.size() << "):" << endl;
|
||||
for (list<SequentialStmt*>::const_iterator cur = if_.begin()
|
||||
; cur != if_.end() ; ++cur)
|
||||
(*cur)->dump(out, indent+4);
|
||||
|
||||
}
|
||||
|
||||
void SignalSeqAssignment::dump(ostream&out, int indent) const
|
||||
{
|
||||
out << setw(indent) << "" << "SignalSeqAssignment at file=" << get_fileline() << endl;
|
||||
|
|
|
|||
Loading…
Reference in New Issue