Elaboration of r-value expressions
R-value expressions are more general then L-value expressions, in that the expression type may be a bit more complex. If the R-value expression is part of an assignment, then elaborate with the constrained type from the L-value. In other cases, where the expression type is not as obvious, use expression type probes to figure out the type of the expression and elaborate using that calculated type.
This commit is contained in:
parent
da0fb1666f
commit
22ab8e4a76
|
|
@ -145,8 +145,6 @@ int ProcessStatement::rewrite_as_always_edge_(Entity*ent, Architecture*arc)
|
|||
// And we can convert it to:
|
||||
// always @(<N>edge <se>) ...
|
||||
|
||||
cerr << get_fileline() << ": XXXX: Found an always @(posedge) pattern?" << endl;
|
||||
|
||||
// Replace the sensitivity expression with an edge expression.
|
||||
ExpEdge*edge = new ExpEdge(op2b->value()=='1'? ExpEdge::POSEDGE : ExpEdge::NEGEDGE, se);
|
||||
assert(sensitivity_list_.size() == 1);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,12 @@ Expression::~Expression()
|
|||
{
|
||||
}
|
||||
|
||||
void Expression::set_type(const VType*typ)
|
||||
{
|
||||
assert(type_ == 0);
|
||||
type_ = typ;
|
||||
}
|
||||
|
||||
bool Expression::evaluate(ScopeBase*, int64_t&) const
|
||||
{
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
class Entity;
|
||||
class Architecture;
|
||||
class ScopeBase;
|
||||
class VType;
|
||||
|
||||
class ExpName;
|
||||
|
||||
|
|
@ -47,6 +48,22 @@ class Expression : public LineInfo {
|
|||
// flags needed to indicate their status as writable variables.
|
||||
virtual int elaborate_lval(Entity*ent, Architecture*arc);
|
||||
|
||||
// This virtual method probes the expression to get the most
|
||||
// constrained type for the expression. For a given instance,
|
||||
// this may be called before the elaborate_expr method.
|
||||
virtual const VType*probe_type(Entity*ent, Architecture*arc) const;
|
||||
|
||||
// This virtual method elaborates an expression. The ltype is
|
||||
// the type of the lvalue expression, if known, and can be
|
||||
// used to calculate the type for the expression being
|
||||
// elaborated.
|
||||
virtual int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
|
||||
// Return the type that this expression would be if it were an
|
||||
// l-value. This should only be called after elaborate_lval is
|
||||
// called and only if elaborate_lval succeeded.
|
||||
inline const VType*peek_type(void) const { return type_; }
|
||||
|
||||
// The emit virtual method is called by architecture emit to
|
||||
// output the generated code for the expression. The derived
|
||||
// class fills in the details of what exactly happened.
|
||||
|
|
@ -72,7 +89,11 @@ class Expression : public LineInfo {
|
|||
// Debug dump of the expression.
|
||||
virtual void dump(ostream&out, int indent = 0) const =0;
|
||||
|
||||
protected:
|
||||
void set_type(const VType*);
|
||||
|
||||
private:
|
||||
const VType*type_;
|
||||
|
||||
private: // Not implemented
|
||||
Expression(const Expression&);
|
||||
|
|
@ -108,6 +129,7 @@ class ExpBinary : public Expression {
|
|||
|
||||
protected:
|
||||
|
||||
int elaborate_exprs(Entity*, Architecture*, const VType*);
|
||||
int emit_operand1(ostream&out, Entity*ent, Architecture*arc);
|
||||
int emit_operand2(ostream&out, Entity*ent, Architecture*arc);
|
||||
|
||||
|
|
@ -161,6 +183,7 @@ class ExpCharacter : public Expression {
|
|||
ExpCharacter(char val);
|
||||
~ExpCharacter();
|
||||
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
bool is_primary(void) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
|
@ -240,6 +263,8 @@ class ExpName : public Expression {
|
|||
|
||||
public: // Base methods
|
||||
int elaborate_lval(Entity*ent, Architecture*arc);
|
||||
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);
|
||||
bool is_primary(void) const;
|
||||
bool evaluate(ScopeBase*scope, int64_t&val) const;
|
||||
|
|
@ -259,6 +284,7 @@ class ExpNameALL : public ExpName {
|
|||
|
||||
public:
|
||||
int elaborate_lval(Entity*ent, Architecture*arc);
|
||||
const VType* probe_type(Entity*ent, Architecture*arc) const;
|
||||
void dump(ostream&out, int indent =0) const;
|
||||
};
|
||||
|
||||
|
|
@ -273,6 +299,8 @@ class ExpRelation : public ExpBinary {
|
|||
ExpRelation(ExpRelation::fun_t ty, Expression*op1, Expression*op2);
|
||||
~ExpRelation();
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,10 @@
|
|||
# include "expression.h"
|
||||
# include "architec.h"
|
||||
# include "entity.h"
|
||||
# include "vsignal.h"
|
||||
# include <iostream>
|
||||
# include <typeinfo>
|
||||
# include <cassert>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
|
@ -31,6 +34,11 @@ int Expression::elaborate_lval(Entity*, Architecture*)
|
|||
return 1;
|
||||
}
|
||||
|
||||
const VType* Expression::probe_type(Entity*, Architecture*) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ExpName::elaborate_lval(Entity*ent, Architecture*arc)
|
||||
{
|
||||
int errors = 0;
|
||||
|
|
@ -43,6 +51,7 @@ int ExpName::elaborate_lval(Entity*ent, Architecture*arc)
|
|||
}
|
||||
|
||||
ent->set_declaration_l_value(name_, true);
|
||||
set_type(cur->type);
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
|
@ -53,6 +62,7 @@ int ExpName::elaborate_lval(Entity*ent, Architecture*arc)
|
|||
return errors + 1;
|
||||
}
|
||||
|
||||
set_type(sig->peek_type());
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
|
@ -60,3 +70,81 @@ int ExpNameALL::elaborate_lval(Entity*ent, Architecture*arc)
|
|||
{
|
||||
return Expression::elaborate_lval(ent, arc);
|
||||
}
|
||||
|
||||
int Expression::elaborate_expr(Entity*, Architecture*, const VType*)
|
||||
{
|
||||
cerr << get_fileline() << ": internal error: I don't know how to elaborate expression type=" << typeid(*this).name() << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ExpBinary::elaborate_exprs(Entity*ent, Architecture*arc, const VType*ltype)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
errors += operand1_->elaborate_expr(ent, arc, ltype);
|
||||
errors += operand2_->elaborate_expr(ent, arc, ltype);
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpCharacter::elaborate_expr(Entity*, Architecture*, const VType*ltype)
|
||||
{
|
||||
assert(ltype != 0);
|
||||
set_type(ltype);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const VType* ExpName::probe_type(Entity*ent, Architecture*arc) const
|
||||
{
|
||||
if (const InterfacePort*cur = ent->find_port(name_))
|
||||
return cur->type;
|
||||
|
||||
if (Signal*sig = arc->find_signal(name_))
|
||||
return sig->peek_type();
|
||||
|
||||
cerr << get_fileline() << ": error: Signal/variable " << name_
|
||||
<< " not found in this context." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ExpName::elaborate_expr(Entity*, Architecture*, const VType*ltype)
|
||||
{
|
||||
assert(ltype != 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const VType* ExpNameALL::probe_type(Entity*, Architecture*) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const VType* ExpRelation::probe_type(Entity*ent, Architecture*arc) const
|
||||
{
|
||||
const VType*type1 = peek_operand1()->probe_type(ent, arc);
|
||||
const VType*type2 = peek_operand2()->probe_type(ent, arc);
|
||||
|
||||
if (type1 == type2)
|
||||
return type1;
|
||||
|
||||
if (type1 && !type2)
|
||||
return type1;
|
||||
|
||||
if (type2 && !type1)
|
||||
return type2;
|
||||
|
||||
cerr << get_fileline() << ": error: Type mismatch in relation expression." << endl;
|
||||
return type1;
|
||||
}
|
||||
|
||||
int ExpRelation::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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "expression.h"
|
||||
# include "expression.h"
|
||||
# include "vtype.h"
|
||||
# include <typeinfo>
|
||||
# include <iostream>
|
||||
|
||||
|
|
@ -109,6 +110,37 @@ int ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc)
|
|||
|
||||
int ExpCharacter::emit(ostream&out, Entity*, Architecture*)
|
||||
{
|
||||
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;
|
||||
|
||||
case VTypePrimitive::STDLOGIC:
|
||||
switch (value_) {
|
||||
case '0':
|
||||
case '1':
|
||||
out << "1'b" << value_;
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
out << "\"" << value_ << "\"";
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ int IfSequential::elaborate(Entity*ent, Architecture*arc)
|
|||
{
|
||||
int errors = 0;
|
||||
|
||||
errors += cond_->elaborate_expr(ent, arc, 0);
|
||||
|
||||
for (list<SequentialStmt*>::iterator cur = if_.begin()
|
||||
; cur != if_.end() ; ++cur) {
|
||||
errors += (*cur)->elaborate(ent, arc);
|
||||
|
|
@ -46,7 +48,24 @@ int SignalSeqAssignment::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;
|
||||
}
|
||||
|
||||
// Elaborate the r-value expressions.
|
||||
for (list<Expression*>::iterator cur = waveform_.begin()
|
||||
; cur != waveform_.end() ; ++cur) {
|
||||
|
||||
errors += (*cur)->elaborate_expr(ent, arc, lval_type);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ class Signal : public LineInfo {
|
|||
Signal(perm_string name, const VType*type);
|
||||
~Signal();
|
||||
|
||||
const VType* peek_type(void) const { return type_; }
|
||||
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
|
|
|||
Loading…
Reference in New Issue