diff --git a/elab_lval.cc b/elab_lval.cc index 51e674be9..c12250d6b 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -1132,6 +1132,12 @@ NetAssign_* PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*scope // part of the sig, as the l-value. NetNet*psig = class_type->find_static_property(method_name); ivl_assert(*this, psig); + if (psig->get_const()) { + cerr << get_fileline() << ": error: Assignment to const signal `" + << psig->name() << "` is not allowed." << endl; + des->errors++; + return nullptr; + } lv = new NetAssign_(psig); return lv; diff --git a/elab_sig.cc b/elab_sig.cc index dfb2a44c2..f023e0dbb 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -419,6 +419,14 @@ void netclass_t::elaborate_sig(Design*des, PClass*pclass) auto sig = new NetNet(class_scope_, cur->first, NetNet::REG, use_type); sig->set_line(cur->second); + sig->set_const(cur->second.qual.test_const()); + + if (cur->second.qual.test_const() && + cur->second.has_initializer) { + int pidx = property_idx_from_name(cur->first); + ivl_assert(cur->second, pidx >= 0); + set_prop_initialized(pidx); + } } for (map::iterator cur = pclass->funcs.begin() diff --git a/pform_pclass.cc b/pform_pclass.cc index e9276a49a..2e6694677 100644 --- a/pform_pclass.cc +++ b/pform_pclass.cc @@ -87,13 +87,14 @@ void pform_class_property(const struct vlltype&loc, } pform_cur_class->type->properties[curp->name.first] - = class_type_t::prop_info_t(property_qual,use_type); + = class_type_t::prop_info_t(property_qual, use_type, + curp->expr != nullptr); FILE_NAME(&pform_cur_class->type->properties[curp->name.first], loc); if (PExpr*rval = curp->expr.release()) { PExpr*lval = new PEIdent(curp->name.first, curp->name.second); FILE_NAME(lval, loc); - PAssign*tmp = new PAssign(lval, rval); + auto tmp = new PAssign(lval, rval, false, true); FILE_NAME(tmp, loc); if (property_qual.test_static()) diff --git a/pform_types.h b/pform_types.h index 021229e53..f0ff20ada 100644 --- a/pform_types.h +++ b/pform_types.h @@ -401,11 +401,14 @@ struct class_type_t : public data_type_t { // This is a map of the properties. Map the name to the type. struct prop_info_t : public LineInfo { inline prop_info_t() : qual(property_qualifier_t::make_none()) { } - inline prop_info_t(property_qualifier_t q, data_type_t*t) : qual(q), type(t) { } + inline prop_info_t(property_qualifier_t q, data_type_t *t, + bool init) + : qual(q), type(t), has_initializer(init) { } prop_info_t(prop_info_t&&) = default; prop_info_t& operator=(prop_info_t&&) = default; property_qualifier_t qual; std::unique_ptr type; + bool has_initializer = false; }; std::map properties;