commit
a79533ddc9
5
pform.cc
5
pform.cc
|
|
@ -2354,6 +2354,11 @@ void pform_module_define_port(const struct vlltype&li,
|
|||
signed_flag = false;
|
||||
prange = 0;
|
||||
|
||||
} else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(vtype)) {
|
||||
data_type = enum_type->base_type;
|
||||
signed_flag = enum_type->signed_flag;
|
||||
prange = enum_type->range.get();
|
||||
|
||||
} else if (vtype) {
|
||||
VLerror(li, "sorry: Given type %s not supported here (%s:%d).",
|
||||
typeid(*vtype).name(), __FILE__, __LINE__);
|
||||
|
|
|
|||
|
|
@ -98,9 +98,8 @@ int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc)
|
|||
// exists in the component declaration
|
||||
const InterfacePort*iparm = base->find_generic(cur->first);
|
||||
if (iparm == 0) {
|
||||
cerr << get_fileline() << ": error: No generic " << cur->first
|
||||
cerr << get_fileline() << ": warning: No generic " << cur->first
|
||||
<< " in component " << cname_ << "." << endl;
|
||||
errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -370,9 +369,7 @@ int SignalAssignment::elaborate(Entity*ent, Architecture*arc)
|
|||
|
||||
for (list<Expression*>::iterator cur = rval_.begin()
|
||||
; cur != rval_.end() ; ++cur) {
|
||||
(*cur)->elaborate_expr(ent, arc, lval_type);
|
||||
|
||||
// Handle functions that return unbounded arrays
|
||||
errors += (*cur)->elaborate_expr(ent, arc, lval_type);
|
||||
}
|
||||
|
||||
return errors;
|
||||
|
|
|
|||
|
|
@ -70,12 +70,12 @@ int Architecture::emit(ostream&out, Entity*entity)
|
|||
// of the full definition.
|
||||
|
||||
typedef_context_t typedef_ctx;
|
||||
for (map<perm_string,const VType*>::iterator cur = use_types_.begin()
|
||||
; cur != use_types_.end() ; ++cur) {
|
||||
//for (map<perm_string,const VType*>::iterator cur = use_types_.begin()
|
||||
//; cur != use_types_.end() ; ++cur) {
|
||||
|
||||
if(const VTypeDef*def = dynamic_cast<const VTypeDef*>(cur->second))
|
||||
errors += def->emit_typedef(out, typedef_ctx);
|
||||
}
|
||||
//if(const VTypeDef*def = dynamic_cast<const VTypeDef*>(cur->second))
|
||||
//errors += def->emit_typedef(out, typedef_ctx);
|
||||
//}
|
||||
for (map<perm_string,const VType*>::iterator cur = cur_types_.begin()
|
||||
; cur != cur_types_.end() ; ++cur) {
|
||||
|
||||
|
|
|
|||
|
|
@ -494,6 +494,11 @@ ExpRelation::~ExpRelation()
|
|||
{
|
||||
}
|
||||
|
||||
ExpShift::ExpShift(ExpShift::shift_t op, Expression*op1, Expression*op2)
|
||||
: ExpBinary(op1, op2), shift_(op)
|
||||
{
|
||||
}
|
||||
|
||||
ExpString::ExpString(const char* value)
|
||||
: value_(strlen(value))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -692,6 +692,27 @@ class ExpRelation : public ExpBinary {
|
|||
fun_t fun_;
|
||||
};
|
||||
|
||||
class ExpShift : public ExpBinary {
|
||||
public:
|
||||
enum shift_t { SRL, SLL, SRA, SLA, ROL, ROR };
|
||||
|
||||
public:
|
||||
ExpShift(ExpShift::shift_t op, Expression*op1, Expression*op2);
|
||||
|
||||
Expression*clone() const {
|
||||
return new ExpShift(shift_, peek_operand1()->clone(), peek_operand2()->clone());
|
||||
}
|
||||
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
virtual bool evaluate(ScopeBase*scope, int64_t&val) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
shift_t shift_;
|
||||
};
|
||||
|
||||
class ExpString : public Expression {
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -82,3 +82,33 @@ void ExpNew::dump(ostream&out, int indent) const
|
|||
out << "New dynamic array size: ";
|
||||
size_->dump(out, indent);
|
||||
}
|
||||
|
||||
void ExpShift::dump(ostream&out, int indent) const
|
||||
{
|
||||
const char*fun_name = "?";
|
||||
switch (shift_) {
|
||||
case SRL:
|
||||
fun_name = "srl";
|
||||
break;
|
||||
case SLL:
|
||||
fun_name = "sll";
|
||||
break;
|
||||
case SLA:
|
||||
fun_name = "sla";
|
||||
break;
|
||||
case SRA:
|
||||
fun_name = "sra";
|
||||
break;
|
||||
case ROR:
|
||||
fun_name = "ror";
|
||||
break;
|
||||
case ROL:
|
||||
fun_name = "rol";
|
||||
break;
|
||||
}
|
||||
|
||||
out << setw(indent) << "" << "Shift " << fun_name
|
||||
<< " at " << get_fileline() << endl;
|
||||
dump_operands(out, indent+4);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -570,7 +570,7 @@ const VType* ExpAttribute::probe_type(Entity*ent, ScopeBase*scope) const
|
|||
base_->probe_type(ent, scope);
|
||||
|
||||
if (name_ == "length" || name_ == "left" || name_ == "right") {
|
||||
return &primitive_INTEGER;
|
||||
return &primitive_NATURAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -906,6 +906,10 @@ const VType* ExpName::probe_type(Entity*ent, ScopeBase*scope) const
|
|||
if (arc && (gtype = arc->probe_genvar_type(name_))) {
|
||||
return gtype;
|
||||
}
|
||||
|
||||
if (scope->is_enum_name(name_)) {
|
||||
return &primitive_INTEGER;
|
||||
}
|
||||
}
|
||||
|
||||
cerr << get_fileline() << ": error: Signal/variable " << name_
|
||||
|
|
@ -918,13 +922,87 @@ const VType* ExpName::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*)co
|
|||
return probe_type(ent, scope);
|
||||
}
|
||||
|
||||
int ExpName::elaborate_expr(Entity*, ScopeBase*, const VType*ltype)
|
||||
int ExpName::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
|
||||
{
|
||||
const VType*type = NULL;
|
||||
Expression*exp = NULL;
|
||||
|
||||
if (ltype) {
|
||||
ivl_assert(*this, ltype != 0);
|
||||
set_type(ltype);
|
||||
}
|
||||
|
||||
// Currently constant arrays of vectors are flattened to single one-dimensional
|
||||
// localparams. If the user wants to access a particular word, then it is
|
||||
// necessary to extract the adequate part of the localparam.
|
||||
// e.g.
|
||||
// declarations:
|
||||
// == VHDL ==
|
||||
// type uns_array is array (natural range <>) of unsigned(7 downto 0);
|
||||
// constant const_array : uns_array(2 downto 0) :=
|
||||
// (0 => "00110011", 1 => "101010101", 2=> "00001111");
|
||||
// == SystemVerilog ==
|
||||
// localparam const_array = { 8'b00110011, 8'b10101010, 8'b00001111 };
|
||||
//
|
||||
// access:
|
||||
// == VHDL ==
|
||||
// target_var := const_array(1);
|
||||
// == SystemVerilog ==
|
||||
// target_var = const_array[15:8]; // <- indices adjusted to pick the word
|
||||
|
||||
if(index_ && scope) {
|
||||
if(!scope->find_constant(name_, type, exp))
|
||||
return 0;
|
||||
|
||||
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type);
|
||||
ivl_assert(*this, arr); // if there is an index, it should be an array, right?
|
||||
|
||||
const VType*element = arr->element_type();
|
||||
const VTypeArray*arr_element = dynamic_cast<const VTypeArray*>(element);
|
||||
if(!arr_element) {
|
||||
// index adjustments are not necessary, it is not an array of vectors
|
||||
return 0;
|
||||
}
|
||||
|
||||
ivl_assert(*this, arr_element->dimensions() == 1);
|
||||
if(arr_element->dimensions() != 1) {
|
||||
cerr << get_fileline() << ": Sorry, only one-dimensional constant arrays are handled." << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int64_t start_val;
|
||||
bool start_rc = arr_element->dimension(0).msb()->evaluate(ent, scope, start_val);
|
||||
|
||||
int64_t finish_val;
|
||||
bool finish_rc = arr_element->dimension(0).lsb()->evaluate(ent, scope, finish_val);
|
||||
|
||||
if(!start_rc || !finish_rc) {
|
||||
cerr << get_fileline() << ": Could not evaluate the word size." << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int word_size = abs(start_val - finish_val) + 1;
|
||||
|
||||
ExpInteger*size = new ExpInteger(word_size);
|
||||
Expression*new_index, *new_lsb;
|
||||
|
||||
// new indices = [index_ * word_size + word_size : lsb_ * word_size]
|
||||
if(lsb_) {
|
||||
ExpArithmetic*tmp = new ExpArithmetic(ExpArithmetic::MULT, index_->clone(), size->clone());
|
||||
new_index = new ExpArithmetic(ExpArithmetic::PLUS, tmp, size->clone());
|
||||
new_lsb = new ExpArithmetic(ExpArithmetic::MULT, lsb_->clone(), size->clone());
|
||||
} else {
|
||||
new_lsb = new ExpArithmetic(ExpArithmetic::MULT, index_->clone(), size->clone());
|
||||
new_index = new ExpArithmetic(ExpArithmetic::PLUS, new_lsb->clone(), size->clone());
|
||||
}
|
||||
delete index_;
|
||||
delete lsb_;
|
||||
delete size;
|
||||
|
||||
index_ = new_index;
|
||||
lsb_ = new_lsb;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -957,6 +1035,19 @@ int ExpRelation::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
|
|||
return errors;
|
||||
}
|
||||
|
||||
int ExpShift::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if (ltype == 0) {
|
||||
ltype = probe_type(ent, scope);
|
||||
}
|
||||
|
||||
ivl_assert(*this, ltype != 0);
|
||||
errors += elaborate_exprs(ent, scope, ltype);
|
||||
return errors;
|
||||
}
|
||||
|
||||
/*
|
||||
* When a string appears in a concatenation, then the type of the
|
||||
* string is an array with the same element type of the concatenation,
|
||||
|
|
|
|||
|
|
@ -552,7 +552,12 @@ int ExpFunc::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
|||
{
|
||||
int errors = 0;
|
||||
|
||||
if (name_ == "unsigned" && argv_.size()==1) {
|
||||
// SystemVerilog takes care of signs, depending on the lvalue
|
||||
if (name_ == "to_integer" && argv_.size()==1) {
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
}
|
||||
|
||||
else if (name_ == "unsigned" && argv_.size()==1) {
|
||||
// Handle the special case that this is a cast to
|
||||
// unsigned. This function is brought in as part of the
|
||||
// std numeric library, but we interpret it as the same
|
||||
|
|
@ -625,7 +630,7 @@ int ExpFunc::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
|||
|
||||
int ExpInteger::emit(ostream&out, Entity*, ScopeBase*)
|
||||
{
|
||||
out << value_;
|
||||
out << "32'd" << value_;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -766,6 +771,36 @@ int ExpRelation::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
|||
return errors;
|
||||
}
|
||||
|
||||
int ExpShift::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
errors += emit_operand1(out, ent, scope);
|
||||
|
||||
switch (shift_) {
|
||||
case SRL:
|
||||
out << " >> ";
|
||||
break;
|
||||
case SLL:
|
||||
out << " << ";
|
||||
break;
|
||||
case SRA:
|
||||
out << " >>> ";
|
||||
break;
|
||||
case SLA:
|
||||
out << " <<< ";
|
||||
break;
|
||||
case ROR:
|
||||
case ROL:
|
||||
out << " /* ?ror/rol? */ ";
|
||||
break;
|
||||
}
|
||||
|
||||
errors += emit_operand2(out, ent, scope);
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
bool ExpString::is_primary(void) const
|
||||
{
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -216,3 +216,37 @@ bool ExpName::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
|
|||
|
||||
return evaluate(scope, val);
|
||||
}
|
||||
|
||||
bool ExpShift::evaluate(ScopeBase*scope, int64_t&val) const
|
||||
{
|
||||
int64_t val1, val2;
|
||||
bool rc;
|
||||
|
||||
rc = eval_operand1(scope, val1);
|
||||
if (rc == false)
|
||||
return false;
|
||||
|
||||
rc = eval_operand2(scope, val2);
|
||||
if (rc == false)
|
||||
return false;
|
||||
|
||||
switch (shift_) {
|
||||
case SRL:
|
||||
val = (uint64_t)val1 >> (uint64_t)val2;
|
||||
break;
|
||||
case SLL:
|
||||
val = (uint64_t)val1 << (uint64_t)val2;
|
||||
break;
|
||||
case SRA:
|
||||
val = (int64_t)val1 >> (int64_t)val2;
|
||||
break;
|
||||
case SLA:
|
||||
val = (int64_t)val1 << (int64_t)val2;
|
||||
break;
|
||||
case ROR:
|
||||
case ROL:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -236,6 +236,39 @@ void ExpRelation::write_to_stream(ostream&fd) const
|
|||
peek_operand2()->write_to_stream(fd);
|
||||
}
|
||||
|
||||
void ExpShift::write_to_stream(ostream&out) const
|
||||
{
|
||||
out << "(";
|
||||
write_to_stream_operand1(out);
|
||||
out << ")";
|
||||
|
||||
switch (shift_) {
|
||||
case SRL:
|
||||
out << "srl";
|
||||
break;
|
||||
case SLL:
|
||||
out << "sll";
|
||||
break;
|
||||
case SLA:
|
||||
out << "sla";
|
||||
break;
|
||||
case SRA:
|
||||
out << "sra";
|
||||
break;
|
||||
case ROR:
|
||||
out << "ror";
|
||||
break;
|
||||
case ROL:
|
||||
out << "rol";
|
||||
break;
|
||||
}
|
||||
|
||||
out << "(";
|
||||
write_to_stream_operand2(out);
|
||||
out << ")";
|
||||
}
|
||||
|
||||
|
||||
void ExpString::write_to_stream(ostream&fd) const
|
||||
{
|
||||
fd << "\"";
|
||||
|
|
|
|||
|
|
@ -387,12 +387,11 @@ static void import_std_use(const YYLTYPE&loc, ActiveScope*/*res*/, perm_string p
|
|||
const VTypePrimitive primitive_BOOLEAN(VTypePrimitive::BOOLEAN, true);
|
||||
const VTypePrimitive primitive_BIT(VTypePrimitive::BIT, true);
|
||||
const VTypePrimitive primitive_INTEGER(VTypePrimitive::INTEGER);
|
||||
const VTypePrimitive primitive_NATURAL(VTypePrimitive::NATURAL);
|
||||
const VTypePrimitive primitive_REAL(VTypePrimitive::REAL);
|
||||
const VTypePrimitive primitive_STDLOGIC(VTypePrimitive::STDLOGIC, true);
|
||||
const VTypePrimitive primitive_CHARACTER(VTypePrimitive::CHARACTER);
|
||||
|
||||
const VTypeRange primitive_NATURAL(&primitive_INTEGER, INT64_MAX, 0);
|
||||
|
||||
static const VTypeArray primitive_BIT_VECTOR(&primitive_BIT, vector<VTypeArray::range_t> (1));
|
||||
static const VTypeArray primitive_BOOL_VECTOR(&primitive_BOOLEAN, vector<VTypeArray::range_t> (1));
|
||||
static const VTypeArray primitive_STRING(&primitive_CHARACTER, vector<VTypeArray::range_t> (1));
|
||||
|
|
@ -417,10 +416,13 @@ bool is_global_type(perm_string name)
|
|||
if (name == "integer") return true;
|
||||
if (name == "real") return true;
|
||||
if (name == "std_logic") return true;
|
||||
if (name == "std_logic_vector") return true;
|
||||
if (name == "character") return true;
|
||||
if (name == "bit_vector") return true;
|
||||
if (name == "string") return true;
|
||||
if (name == "natural") return true;
|
||||
if (name == "signed") return true;
|
||||
if (name == "unsigned") return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -73,12 +73,6 @@ void Package::write_to_stream(ostream&fd) const
|
|||
// Do not include global types in types dump
|
||||
if (is_global_type(cur->first))
|
||||
continue;
|
||||
if (cur->first == "std_logic_vector")
|
||||
continue;
|
||||
if (cur->first == "signed")
|
||||
continue;
|
||||
if (cur->first == "unsigned")
|
||||
continue;
|
||||
|
||||
fd << "type " << cur->first << " is ";
|
||||
cur->second->write_type_to_stream(fd);
|
||||
|
|
@ -90,8 +84,6 @@ void Package::write_to_stream(ostream&fd) const
|
|||
// Do not include global types in types dump
|
||||
if (is_global_type(cur->first))
|
||||
continue;
|
||||
if (cur->first == "std_logic_vector")
|
||||
continue;
|
||||
|
||||
fd << "type " << cur->first << " is ";
|
||||
cur->second->write_type_to_stream(fd);
|
||||
|
|
|
|||
|
|
@ -32,26 +32,22 @@ int Package::emit_package(ostream&fd) const
|
|||
if (cur_types_.empty() && cur_constants_.empty() && cur_subprograms_.empty())
|
||||
return 0;
|
||||
|
||||
// If this package was imported from a library, then do not
|
||||
// emit it again.
|
||||
if (from_library_.str() != 0) {
|
||||
fd << "/* Suppress package " << name()
|
||||
<< " from library " << from_library_ << " */" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int errors = 0;
|
||||
|
||||
fd << "package \\" << name() << " ;" << endl;
|
||||
fd << "`ifndef package_" << name() << endl;
|
||||
fd << "`define package_" << name() << endl;
|
||||
|
||||
// Only emit types that were defined within this package. Skip
|
||||
// the types that were imported from elsewhere.
|
||||
typedef_context_t typedef_ctx;
|
||||
for (map<perm_string,const VType*>::const_iterator cur = cur_types_.begin()
|
||||
; cur != cur_types_.end() ; ++ cur) {
|
||||
fd << "typedef ";
|
||||
errors += cur->second->emit_def(fd,
|
||||
dynamic_cast<const VTypeDef*>(cur->second) ? empty_perm_string : cur->first);
|
||||
fd << " ;" << endl;
|
||||
if(const VTypeDef*def = dynamic_cast<const VTypeDef*>(cur->second))
|
||||
errors += def->emit_typedef(fd, typedef_ctx);
|
||||
//fd << "typedef ";
|
||||
//errors += cur->second->emit_def(fd,
|
||||
//dynamic_cast<const VTypeDef*>(cur->second) ? empty_perm_string : cur->first);
|
||||
//fd << " ;" << endl;
|
||||
}
|
||||
|
||||
//for (map<perm_string,struct const_t*>::const_iterator cur = use_constants_.begin()
|
||||
|
|
@ -67,14 +63,19 @@ int Package::emit_package(ostream&fd) const
|
|||
//fd << ";" << endl;
|
||||
//}
|
||||
|
||||
fd << "package \\" << name() << " ;" << endl;
|
||||
for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin()
|
||||
; cur != cur_subprograms_.end() ; ++ cur) {
|
||||
// Do not emit unbounded functions, we will just need fixed instances later
|
||||
if(!cur->second->unbounded())
|
||||
errors += cur->second->emit_package(fd);
|
||||
else
|
||||
fd << "/* function " << cur->second->name() <<
|
||||
" has to be instantiated, skipping */" << endl;
|
||||
}
|
||||
|
||||
fd << "endpackage" << endl;
|
||||
fd << "endpackage /* " << name() << " */" << endl;
|
||||
fd << "`endif" << endl;
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
|
|
|||
101
vhdlpp/parse.y
101
vhdlpp/parse.y
|
|
@ -314,7 +314,7 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
|
|||
|
||||
%type <arch_statement> concurrent_statement component_instantiation_statement
|
||||
%type <arch_statement> concurrent_conditional_signal_assignment
|
||||
%type <arch_statement> concurrent_signal_assignment_statement
|
||||
%type <arch_statement> concurrent_signal_assignment_statement concurrent_simple_signal_assignment
|
||||
%type <arch_statement> for_generate_statement generate_statement if_generate_statement
|
||||
%type <arch_statement> process_statement
|
||||
%type <arch_statement_list> architecture_statement_part generate_statement_body
|
||||
|
|
@ -348,14 +348,14 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
|
|||
|
||||
%type <text> architecture_body_start package_declaration_start
|
||||
%type <text> package_body_start
|
||||
%type <text> identifier_opt identifier_colon_opt logical_name suffix
|
||||
%type <text> identifier_opt identifier_colon_opt logical_name suffix instantiated_unit
|
||||
%type <name_list> logical_name_list identifier_list
|
||||
%type <name_list> enumeration_literal_list enumeration_literal
|
||||
|
||||
%type <sequ_list> if_statement_else sequence_of_statements subprogram_statement_part
|
||||
%type <sequ> sequential_statement if_statement signal_assignment_statement
|
||||
%type <sequ> sequential_statement if_statement signal_assignment signal_assignment_statement
|
||||
%type <sequ> case_statement procedure_call procedure_call_statement
|
||||
%type <sequ> loop_statement variable_assignment_statement
|
||||
%type <sequ> loop_statement variable_assignment variable_assignment_statement
|
||||
%type <sequ> return_statement
|
||||
|
||||
%type <range> range
|
||||
|
|
@ -677,22 +677,27 @@ component_declaration
|
|||
}
|
||||
;
|
||||
|
||||
instantiated_unit
|
||||
: IDENTIFIER
|
||||
| K_component IDENTIFIER { $$ = $2; }
|
||||
;
|
||||
|
||||
component_instantiation_statement
|
||||
: IDENTIFIER ':' K_component_opt IDENTIFIER generic_map_aspect_opt port_map_aspect_opt ';'
|
||||
: IDENTIFIER ':' instantiated_unit generic_map_aspect_opt port_map_aspect_opt ';'
|
||||
{ perm_string iname = lex_strings.make($1);
|
||||
perm_string cname = lex_strings.make($4);
|
||||
ComponentInstantiation*tmp = new ComponentInstantiation(iname, cname, $5, $6);
|
||||
perm_string cname = lex_strings.make($3);
|
||||
ComponentInstantiation*tmp = new ComponentInstantiation(iname, cname, $4, $5);
|
||||
delete $4;
|
||||
delete $5;
|
||||
delete $6;
|
||||
FILE_NAME(tmp, @1);
|
||||
delete[]$1;
|
||||
delete[]$4;
|
||||
delete[]$3;
|
||||
$$ = tmp;
|
||||
}
|
||||
| IDENTIFIER ':' K_component_opt IDENTIFIER error ';'
|
||||
| IDENTIFIER ':' instantiated_unit error ';'
|
||||
{ errormsg(@4, "Errors in component instantiation.\n");
|
||||
delete[]$1;
|
||||
delete[]$4;
|
||||
delete[]$3;
|
||||
$$ = 0;
|
||||
}
|
||||
;
|
||||
|
|
@ -726,7 +731,6 @@ composite_type_definition
|
|||
{ $$ = $1; }
|
||||
;
|
||||
|
||||
|
||||
/* The when...else..when...else syntax is not a general expression
|
||||
in VHDL but a specific sort of assignment statement model. We
|
||||
create Exppression objects for it, but the parser will only
|
||||
|
|
@ -763,6 +767,17 @@ concurrent_conditional_signal_assignment /* IEEE 1076-2008 P11.6 */
|
|||
}
|
||||
;
|
||||
|
||||
concurrent_simple_signal_assignment
|
||||
: name LEQ waveform ';'
|
||||
{ ExpName*name = dynamic_cast<ExpName*> ($1);
|
||||
assert(name);
|
||||
SignalAssignment*tmp = new SignalAssignment(name, *$3);
|
||||
FILE_NAME(tmp, @1);
|
||||
|
||||
$$ = tmp;
|
||||
delete $3;
|
||||
}
|
||||
|
||||
else_when_waveforms
|
||||
: else_when_waveforms else_when_waveform
|
||||
{ list<ExpConditional::else_t*>*tmp = $1;
|
||||
|
|
@ -790,18 +805,14 @@ else_when_waveform
|
|||
;
|
||||
|
||||
concurrent_signal_assignment_statement /* IEEE 1076-2008 P11.6 */
|
||||
: name LEQ waveform ';'
|
||||
{ ExpName*name = dynamic_cast<ExpName*> ($1);
|
||||
assert(name);
|
||||
SignalAssignment*tmp = new SignalAssignment(name, *$3);
|
||||
FILE_NAME(tmp, @1);
|
||||
: concurrent_simple_signal_assignment
|
||||
|
||||
$$ = tmp;
|
||||
delete $3;
|
||||
}
|
||||
| IDENTIFIER ':' concurrent_simple_signal_assignment { $$ = $3; }
|
||||
|
||||
| concurrent_conditional_signal_assignment
|
||||
|
||||
| IDENTIFIER ':' concurrent_conditional_signal_assignment { $$ = $3; }
|
||||
|
||||
| name LEQ error ';'
|
||||
{ errormsg(@2, "Syntax error in signal assignment waveform.\n");
|
||||
delete $1;
|
||||
|
|
@ -2128,7 +2139,41 @@ sequential_statement
|
|||
}
|
||||
;
|
||||
|
||||
shift_expression : simple_expression { $$ = $1; } ;
|
||||
shift_expression
|
||||
: simple_expression
|
||||
| simple_expression K_srl simple_expression
|
||||
{ ExpShift*tmp = new ExpShift(ExpShift::SRL, $1, $3);
|
||||
FILE_NAME(tmp, @2);
|
||||
$$ = tmp;
|
||||
}
|
||||
| simple_expression K_sll simple_expression
|
||||
{ ExpShift*tmp = new ExpShift(ExpShift::SLL, $1, $3);
|
||||
FILE_NAME(tmp, @2);
|
||||
$$ = tmp;
|
||||
}
|
||||
| simple_expression K_sra simple_expression
|
||||
{ ExpShift*tmp = new ExpShift(ExpShift::SRA, $1, $3);
|
||||
FILE_NAME(tmp, @2);
|
||||
$$ = tmp;
|
||||
}
|
||||
| simple_expression K_sla simple_expression
|
||||
{ ExpShift*tmp = new ExpShift(ExpShift::SLA, $1, $3);
|
||||
FILE_NAME(tmp, @2);
|
||||
$$ = tmp;
|
||||
}
|
||||
| simple_expression K_ror simple_expression
|
||||
{ sorrymsg(@2, "ROR is not supported.\n");
|
||||
ExpShift*tmp = new ExpShift(ExpShift::ROR, $1, $3);
|
||||
FILE_NAME(tmp, @2);
|
||||
$$ = tmp;
|
||||
}
|
||||
| simple_expression K_rol simple_expression
|
||||
{ sorrymsg(@2, "ROL is not supported.\n");
|
||||
ExpShift*tmp = new ExpShift(ExpShift::ROL, $1, $3);
|
||||
FILE_NAME(tmp, @2);
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
sign
|
||||
: '+'
|
||||
|
|
@ -2206,7 +2251,7 @@ simple_expression_terms
|
|||
}
|
||||
;
|
||||
|
||||
signal_assignment_statement
|
||||
signal_assignment
|
||||
: name LEQ waveform ';'
|
||||
{ SignalSeqAssignment*tmp = new SignalSeqAssignment($1, $3);
|
||||
FILE_NAME(tmp, @1);
|
||||
|
|
@ -2221,6 +2266,10 @@ signal_assignment_statement
|
|||
}
|
||||
;
|
||||
|
||||
signal_assignment_statement
|
||||
: signal_assignment
|
||||
| IDENTIFIER ':' signal_assignment { $$ = $3; }
|
||||
|
||||
subprogram_body_start
|
||||
: subprogram_specification K_is
|
||||
{ assert(!active_sub);
|
||||
|
|
@ -2393,6 +2442,9 @@ type_declaration
|
|||
tmp->set_definition($4);
|
||||
active_scope->incomplete_types.erase(cur);
|
||||
}
|
||||
if(const VTypeEnum*enum_type = dynamic_cast<const VTypeEnum*>($4)) {
|
||||
active_scope->use_enum(enum_type);
|
||||
}
|
||||
}
|
||||
delete[]$2;
|
||||
}
|
||||
|
|
@ -2449,6 +2501,10 @@ use_clauses_opt
|
|||
;
|
||||
|
||||
variable_assignment_statement /* IEEE 1076-2008 P10.6.1 */
|
||||
: variable_assignment
|
||||
| IDENTIFIER ':' variable_assignment { $$ = $3; }
|
||||
|
||||
variable_assignment
|
||||
: name VASSIGN expression ';'
|
||||
{ VariableSeqAssignment*tmp = new VariableSeqAssignment($1, $3);
|
||||
FILE_NAME(tmp, @1);
|
||||
|
|
@ -2515,7 +2571,6 @@ waveform_element
|
|||
/* Some keywords are optional in some contexts. In all such cases, a
|
||||
similar rule is used, as described here. */
|
||||
K_architecture_opt : K_architecture | ;
|
||||
K_component_opt : K_component | ;
|
||||
K_configuration_opt: K_configuration| ;
|
||||
K_entity_opt : K_entity | ;
|
||||
K_is_opt : K_is | ;
|
||||
|
|
|
|||
|
|
@ -59,6 +59,8 @@ ScopeBase::ScopeBase(const ActiveScope&ref)
|
|||
use_subprograms_ = ref.use_subprograms_;
|
||||
cur_subprograms_ = ref.cur_subprograms_;
|
||||
|
||||
use_enums_ = ref.use_enums_;
|
||||
|
||||
// This constructor is invoked when the parser is finished with
|
||||
// an active scope and is making the actual scope. At this point
|
||||
// we know that "this" is the parent scope for the subprograms,
|
||||
|
|
@ -102,8 +104,11 @@ const VType*ScopeBase::find_type(perm_string by_name)
|
|||
return cur->second;
|
||||
}
|
||||
|
||||
bool ScopeBase::find_constant(perm_string by_name, const VType*&typ, Expression*&exp)
|
||||
bool ScopeBase::find_constant(perm_string by_name, const VType*&typ, Expression*&exp) const
|
||||
{
|
||||
typ = NULL;
|
||||
exp = NULL;
|
||||
|
||||
map<perm_string,struct const_t*>::const_iterator cur = cur_constants_.find(by_name);
|
||||
if (cur == cur_constants_.end()) {
|
||||
cur = use_constants_.find(by_name);
|
||||
|
|
@ -119,6 +124,8 @@ bool ScopeBase::find_constant(perm_string by_name, const VType*&typ, Expression*
|
|||
exp = cur->second->val;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Signal* ScopeBase::find_signal(perm_string by_name) const
|
||||
|
|
@ -181,6 +188,17 @@ Subprogram* ScopeBase::find_subprogram(perm_string name) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool ScopeBase::is_enum_name(perm_string name) const
|
||||
{
|
||||
for(list<const VTypeEnum*>::const_iterator it = use_enums_.begin();
|
||||
it != use_enums_.end(); ++it) {
|
||||
if((*it)->has_name(name))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method is only used by the ActiveScope derived class to import
|
||||
* definition from another scope.
|
||||
|
|
@ -219,6 +237,8 @@ void ScopeBase::do_use_from(const ScopeBase*that)
|
|||
; cur != that->cur_constants_.end() ; ++ cur) {
|
||||
use_constants_[cur->first] = cur->second;
|
||||
}
|
||||
|
||||
use_enums_ = that->use_enums_;
|
||||
}
|
||||
|
||||
void ScopeBase::transfer_from(ScopeBase&ref)
|
||||
|
|
@ -266,6 +286,11 @@ bool ActiveScope::is_vector_name(perm_string name) const
|
|||
if (find_variable(name))
|
||||
return true;
|
||||
|
||||
const VType*dummy_type;
|
||||
Expression*dummy_exp;
|
||||
if (find_constant(name, dummy_type, dummy_exp))
|
||||
return true;
|
||||
|
||||
if (context_entity_ && context_entity_->find_port(name))
|
||||
return true;
|
||||
|
||||
|
|
|
|||
|
|
@ -53,11 +53,12 @@ class ScopeBase {
|
|||
virtual ~ScopeBase() =0;
|
||||
|
||||
const VType* find_type(perm_string by_name);
|
||||
bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp);
|
||||
bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp) const;
|
||||
Signal* find_signal(perm_string by_name) const;
|
||||
Variable* find_variable(perm_string by_name) const;
|
||||
virtual const InterfacePort* find_param(perm_string by_name) const;
|
||||
Subprogram* find_subprogram(perm_string by_name) const;
|
||||
bool is_enum_name(perm_string name) const;
|
||||
// Moves all signals, variables and components from another scope to
|
||||
// this one. After the transfer new_* maps are emptied in the another scope.
|
||||
void transfer_from(ScopeBase&ref);
|
||||
|
|
@ -114,6 +115,8 @@ class ScopeBase {
|
|||
std::map<perm_string, Subprogram*> use_subprograms_; //imported
|
||||
std::map<perm_string, Subprogram*> cur_subprograms_; //current
|
||||
|
||||
std::list<const VTypeEnum*> use_enums_;
|
||||
|
||||
void do_use_from(const ScopeBase*that);
|
||||
};
|
||||
|
||||
|
|
@ -199,6 +202,9 @@ class ActiveScope : public ScopeBase {
|
|||
cur_types_[name] = t;
|
||||
}
|
||||
|
||||
inline void use_enum(const VTypeEnum* t)
|
||||
{ use_enums_.push_back(t); }
|
||||
|
||||
inline void use_name(perm_string name, const VType* t)
|
||||
{ use_types_[name] = t; }
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
# include <map>
|
||||
# include <typeinfo>
|
||||
# include <cassert>
|
||||
# include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
|
@ -66,11 +67,14 @@ void VTypePrimitive::show(ostream&out) const
|
|||
case INTEGER:
|
||||
out << "INTEGER";
|
||||
break;
|
||||
case NATURAL:
|
||||
out << "NATURAL";
|
||||
break;
|
||||
case REAL:
|
||||
out << "REAL";
|
||||
break;
|
||||
case STDLOGIC:
|
||||
out << "std_logic";
|
||||
out << "STD_LOGIC";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -251,6 +255,11 @@ void VTypeEnum::show(ostream&out) const
|
|||
out << ")";
|
||||
}
|
||||
|
||||
bool VTypeEnum::has_name(perm_string name) const
|
||||
{
|
||||
return std::find(names_.begin(), names_.end(), name) != names_.end();
|
||||
}
|
||||
|
||||
VTypeRecord::VTypeRecord(std::list<element_t*>*elements)
|
||||
: elements_(elements->size())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ class VTypeERROR : public VType {
|
|||
class VTypePrimitive : public VType {
|
||||
|
||||
public:
|
||||
enum type_t { BOOLEAN, BIT, INTEGER, REAL, STDLOGIC, CHARACTER };
|
||||
enum type_t { BOOLEAN, BIT, INTEGER, NATURAL, REAL, STDLOGIC, CHARACTER };
|
||||
|
||||
public:
|
||||
VTypePrimitive(type_t tt, bool packed = false);
|
||||
|
|
@ -177,6 +177,7 @@ class VTypePrimitive : public VType {
|
|||
extern const VTypePrimitive primitive_BOOLEAN;
|
||||
extern const VTypePrimitive primitive_BIT;
|
||||
extern const VTypePrimitive primitive_INTEGER;
|
||||
extern const VTypePrimitive primitive_NATURAL;
|
||||
extern const VTypePrimitive primitive_REAL;
|
||||
extern const VTypePrimitive primitive_STDLOGIC;
|
||||
extern const VTypePrimitive primitive_CHARACTER;
|
||||
|
|
@ -295,6 +296,9 @@ class VTypeEnum : public VType {
|
|||
void show(std::ostream&) const;
|
||||
int emit_def(std::ostream&out, perm_string name) const;
|
||||
|
||||
// Checks if the name is stored in the enum.
|
||||
bool has_name(perm_string name) const;
|
||||
|
||||
private:
|
||||
std::vector<perm_string>names_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -154,6 +154,9 @@ int VTypePrimitive::emit_primitive_type(ostream&out) const
|
|||
case STDLOGIC:
|
||||
out << "logic";
|
||||
break;
|
||||
case NATURAL:
|
||||
out << "int unsigned";
|
||||
break;
|
||||
case INTEGER:
|
||||
out << "int";
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -140,6 +140,9 @@ void VTypePrimitive::write_to_stream(ostream&fd) const
|
|||
case INTEGER:
|
||||
fd << "integer";
|
||||
break;
|
||||
case NATURAL:
|
||||
fd << "natural";
|
||||
break;
|
||||
case REAL:
|
||||
fd << "real";
|
||||
break;
|
||||
|
|
|
|||
Loading…
Reference in New Issue