diff --git a/PWire.cc b/PWire.cc index ec4161c2f..3e74a44c9 100644 --- a/PWire.cc +++ b/PWire.cc @@ -30,7 +30,7 @@ PWire::PWire(perm_string n, signed_(false), isint_(false), port_msb_(0), port_lsb_(0), port_set_(false), net_msb_(0), net_lsb_(0), net_set_(false), error_cnt_(0), - lidx_(0), ridx_(0) + lidx_(0), ridx_(0), discipline_(0) { if (t == NetNet::INTEGER) { type_ = NetNet::REG; @@ -135,19 +135,6 @@ bool PWire::get_isint() const return isint_; } -/* - * Since implicitly defined list of port declarations are no longer - * considered fully defined we no longer need this routine to force - * them to be fully defined. - * -void PWire::set_net_range() -{ - net_msb_ = port_msb_; - net_lsb_ = port_lsb_; - net_set_ = true; -} -*/ - void PWire::set_range(PExpr*m, PExpr*l, PWSRType type) { switch (type) { @@ -211,3 +198,13 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx) } } +void PWire::set_discipline(discipline_t*d) +{ + assert(discipline_ == 0); + discipline_ = d; +} + +discipline_t* PWire::get_discipline(void) const +{ + return discipline_; +} diff --git a/PWire.h b/PWire.h index 2efa9c72b..9ff597552 100644 --- a/PWire.h +++ b/PWire.h @@ -36,6 +36,7 @@ class ostream; class PExpr; class Design; +class discipline_t; /* * The different type of PWire::set_range() calls. @@ -78,10 +79,12 @@ class PWire : public LineInfo { ivl_variable_type_t get_data_type() const; void set_range(PExpr*msb, PExpr*lsb, PWSRType type); - void set_net_range(); void set_memory_idx(PExpr*ldx, PExpr*rdx); + void set_discipline(discipline_t*); + discipline_t* get_discipline(void) const; + map attributes; // Write myself to the specified stream. @@ -112,6 +115,8 @@ class PWire : public LineInfo { PExpr*lidx_; PExpr*ridx_; + discipline_t*discipline_; + private: // not implemented PWire(const PWire&); PWire& operator= (const PWire&); diff --git a/pform.cc b/pform.cc index 15aaec45f..f964a85ca 100644 --- a/pform.cc +++ b/pform.cc @@ -131,7 +131,7 @@ PBlock* pform_push_block_scope(char*name, PBlock::BL_TYPE bt) return block; } -static PWire*get_wire_in_scope(perm_string name) +PWire*pform_get_wire_in_scope(perm_string name) { /* Note that if we are processing a generate, then the scope depth will be empty because generate schemes @@ -919,7 +919,7 @@ static void pform_set_net_range(perm_string name, ivl_variable_type_t dt, PWSRType rt) { - PWire*cur = get_wire_in_scope(name); + PWire*cur = pform_get_wire_in_scope(name); if (cur == 0) { VLerror("error: name is not a valid net."); return; @@ -1338,7 +1338,7 @@ void pform_makewire(const vlltype&li, perm_string name, ivl_variable_type_t dt, svector*attr) { - PWire*cur = get_wire_in_scope(name); + PWire*cur = pform_get_wire_in_scope(name); // If this is not implicit ("implicit" meaning we don't know // what the type is yet) then set the type now. @@ -1452,7 +1452,7 @@ void pform_makewire(const vlltype&li, SR_NET); } - PWire*cur = get_wire_in_scope(first->name); + PWire*cur = pform_get_wire_in_scope(first->name); if (cur != 0) { PEIdent*lval = new PEIdent(first->name); FILE_NAME(lval, li.text, li.first_line); diff --git a/pform.h b/pform.h index f63972c13..cb3f48543 100644 --- a/pform.h +++ b/pform.h @@ -121,6 +121,13 @@ extern void pform_set_default_nettype(NetNet::Type net, const char*file, unsigned lineno); +/* + * Look for the given wire in the current lexical scope. If the wire + * (including variables of any type) cannot be found in the current + * scope, then return 0. + */ +extern PWire* pform_get_wire_in_scope(perm_string name); + /* * The parser uses startmodule and endmodule together to build up a * module as it parses it. The startmodule tells the pform code that a diff --git a/pform_disciplines.cc b/pform_disciplines.cc index fb1e444d3..f55f52b9c 100644 --- a/pform_disciplines.cc +++ b/pform_disciplines.cc @@ -47,45 +47,36 @@ void pform_end_discipline(const struct vlltype&loc) } /* - * The parser uses this function to attach a discipline to a declared wire. + * The parser uses this function to attach a discipline to a wire. The + * wire may be declared by now, or will be declared further later. If + * it is already declared, we just attach the discipline. If it is not + * declared yet, then this is the declaration and we create the signal + * in the current lexical scope. */ void pform_attach_discipline(const struct vlltype&loc, discipline_t*discipline, list*names) { - error_count += 1; - cerr << yylloc.text << ";" << yylloc.first_line << ": sorry: " - << "Net discipline declarations not supported." << endl; - for (list::iterator cur = names->begin() ; cur != names->end() ; cur ++ ) { - cerr << yylloc.text << ";" << yylloc.first_line << ": : " - << "discipline=" << discipline->name() - << ", net=" << *cur << endl; + + PWire* cur_net = pform_get_wire_in_scope(*cur); + if (cur_net == 0) { + /* Not declared yet, declare it now. */ + pform_makewire(loc, *cur, NetNet::WIRE, + NetNet::NOT_A_PORT, IVL_VT_REAL, 0); + cur_net = pform_get_wire_in_scope(*cur); + assert(cur_net); + } + + if (discipline_t*tmp = cur_net->get_discipline()) { + cerr << loc.text << ":" << loc.first_line << ": error: " + << "discipline " << discipline->name() + << " cannot override existing discipline " << tmp->name() + << " on net " << cur_net->basename() << endl; + error_count += 1; + + } else { + cur_net->set_discipline(discipline); + } } } - -void pform_dump(std::ostream&out, discipline_t*dis) -{ - out << "discipline " << dis->name() << endl; - out << " domain " << dis->domain() << ";" << endl; - out << "enddiscipline" << endl; -} - -std::ostream& operator << (std::ostream&out, ddomain_t dom) -{ - switch (dom) { - case DD_NONE: - out << "no-domain"; - break; - case DD_DISCRETE: - out << "discrete"; - break; - case DD_CONTINUOUS: - out << "continuous"; - break; - default: - assert(0); - break; - } - return out; -} diff --git a/pform_dump.cc b/pform_dump.cc index 1473865ee..7f5ea9418 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -29,6 +29,7 @@ # include "PEvent.h" # include "PGenerate.h" # include "PSpec.h" +# include "discipline.h" # include # include # include @@ -128,6 +129,26 @@ ostream& operator<< (ostream&o, const pform_name_t&that) return o; } + +std::ostream& operator << (std::ostream&out, ddomain_t dom) +{ + switch (dom) { + case DD_NONE: + out << "no-domain"; + break; + case DD_DISCRETE: + out << "discrete"; + break; + case DD_CONTINUOUS: + out << "continuous"; + break; + default: + assert(0); + break; + } + return out; +} + void PExpr::dump(ostream&out) const { out << typeid(*this).name(); @@ -300,6 +321,10 @@ void PWire::dump(ostream&out, unsigned ind) const out << " signed"; } + if (discipline_) { + out << " discipline<" << discipline_->name() << ">"; + } + if (port_set_) { if (port_msb_ == 0) { out << " port"; @@ -1123,3 +1148,10 @@ void PUdp::dump(ostream&out) const out << "endprimitive" << endl; } + +void pform_dump(std::ostream&out, discipline_t*dis) +{ + out << "discipline " << dis->name() << endl; + out << " domain " << dis->domain() << ";" << endl; + out << "enddiscipline" << endl; +}