Permalink
Browse files

Reword how we enforce program block constraints

Making the scope type NESTED_MODULE was just plain wrong, because
it didn't really encapsulate the meaning of program blocks OR
nested modules. So instead create nested_module() and program_block()
flags and use those to test scope constraints.
  • Loading branch information...
1 parent dfe7bee commit 8154ce2a4a797fd29bc5e4dfa3fb555247c3e220 @steveicarus committed May 14, 2012
Showing with 77 additions and 37 deletions.
  1. +3 −0 design_dump.cc
  2. +1 −1 elab_net.cc
  3. +4 −2 elab_scope.cc
  4. +3 −3 elab_sig.cc
  5. +43 −2 elaborate.cc
  6. +3 −2 net_design.cc
  7. +7 −10 net_scope.cc
  8. +12 −4 netlist.h
  9. +0 −1 nodangle.cc
  10. +0 −10 parse.y
  11. +1 −1 symbol_search.cc
  12. +0 −1 t-dll.cc
View
@@ -1136,6 +1136,9 @@ void NetScope::dump(ostream&o) const
print_type(o);
if (is_auto()) o << " (automatic)";
if (is_cell()) o << " (cell)";
+ if (nested_module()) o << " (nested)";
+ if (program_block()) o << " (program)";
+
o << endl;
for (unsigned idx = 0 ; idx < attr_cnt() ; idx += 1)
View
@@ -693,7 +693,7 @@ NetNet* PEIdent::elaborate_bi_net(Design*des, NetScope*scope) const
*/
NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
{
- assert(scope->type_is_module());
+ ivl_assert(*this, scope->type() == NetScope::MODULE);
NetNet*sig = des->find_signal(scope, path_);
if (sig == 0) {
cerr << get_fileline() << ": error: no wire/reg " << path_
View
@@ -1225,7 +1225,7 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
continue;
}
- if (! scn->type_is_module()) continue;
+ if (scn->type() != NetScope::MODULE) continue;
if (strcmp(mod->mod_name(), scn->module_name()) != 0) continue;
@@ -1345,7 +1345,9 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
// Create the new scope as a MODULE with my name. Note
// that if this is a nested module, mark it thus so that
// scope searches will continue into the parent scope.
- NetScope*my_scope = new NetScope(sc, use_name, bound_type_? NetScope::NESTED_MODULE : NetScope::MODULE);
+ NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE,
+ bound_type_? true : false,
+ mod->program_block);
my_scope->set_line(get_file(), mod->get_file(),
get_lineno(), mod->get_lineno());
my_scope->set_module_name(mod->mod_name());
View
@@ -98,7 +98,7 @@ bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
reg, then report an error. */
if (sig && (sig->scope() == scope)
- && (scope->type_is_module())
+ && (scope->type() == NetScope::MODULE)
&& (sig->port_type() == NetNet::PINPUT)
&& (sig->type() == NetNet::REG)) {
@@ -110,7 +110,7 @@ bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
}
if (sig && (sig->scope() == scope)
- && (scope->type_is_module())
+ && (scope->type() == NetScope::MODULE)
&& (sig->port_type() == NetNet::PINOUT)
&& (sig->type() == NetNet::REG)) {
@@ -122,7 +122,7 @@ bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
}
if (sig && (sig->scope() == scope)
- && scope->type_is_module()
+ && (scope->type() == NetScope::MODULE)
&& (sig->port_type() == NetNet::PINOUT)
&& (sig->data_type() == IVL_VT_REAL)) {
View
@@ -2312,6 +2312,18 @@ NetProc* PAssign::elaborate_compressed_(Design*des, NetScope*scope) const
return cur;
}
+static bool lval_not_program_variable(const NetAssign_*lv)
+{
+ while (lv) {
+ NetScope*sig_scope = lv->sig()->scope();
+ if (! sig_scope->program_block())
+ return true;
+
+ lv = lv->more;
+ }
+ return false;
+}
+
NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
{
assert(scope);
@@ -2326,6 +2338,12 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
NetAssign_*lv = elaborate_lval(des, scope);
if (lv == 0) return 0;
+ if (scope->program_block() && lval_not_program_variable(lv)) {
+ cerr << get_fileline() << ": error: Blocking assignments to "
+ << "non-program variables are not allowed." << endl;
+ des->errors += 1;
+ }
+
/* If there is an internal delay expression, elaborate it. */
NetExpr*delay = 0;
if (delay_ != 0)
@@ -2470,6 +2488,22 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
}
/*
+ * Return true if any lvalue parts are in a program block scope.
+ */
+static bool lval_is_program_variable(const NetAssign_*lv)
+{
+ while (lv) {
+ NetScope*sig_scope = lv->sig()->scope();
+ if (sig_scope->program_block())
+ return true;
+
+ lv = lv->more;
+ }
+
+ return false;
+}
+
+/*
* Elaborate non-blocking assignments. The statement is of the general
* form:
*
@@ -2505,6 +2539,14 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
NetAssign_*lv = elaborate_lval(des, scope);
if (lv == 0) return 0;
+ if (scope->program_block() && lval_is_program_variable(lv)) {
+ cerr << get_fileline() << ": error: Non-blocking assignments to "
+ << "program variables are not allowed." << endl;
+ des->errors += 1;
+ // This is an error, but we can let elaboration continue
+ // because it would necessarily trigger other errors.
+ }
+
NetExpr*rv = elaborate_rval_(des, scope, count_lval_width(lv), lv->expr_type());
if (rv == 0) return 0;
@@ -3256,7 +3298,6 @@ NetProc* PDisable::elaborate(Design*des, NetScope*scope) const
return 0;
case NetScope::MODULE:
- case NetScope::NESTED_MODULE:
cerr << get_fileline() << ": error: Cannot disable modules." << endl;
des->errors += 1;
return 0;
@@ -4849,7 +4890,7 @@ Design* elaborate(list<perm_string>roots)
// Make the root scope. This makes a NetScope object and
// pushes it into the list of root scopes in the Design.
- NetScope*scope = des->make_root_scope(*root);
+ NetScope*scope = des->make_root_scope(*root, rmod->program_block);
// Collect some basic properties of this scope from the
// Module definition.
View
@@ -101,10 +101,11 @@ uint64_t Design::scale_to_precision(uint64_t val,
return val;
}
-NetScope* Design::make_root_scope(perm_string root)
+NetScope* Design::make_root_scope(perm_string root, bool program_block)
{
NetScope *root_scope_;
- root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE);
+ root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE,
+ false, program_block);
/* This relies on the fact that the basename return value is
permallocated. */
root_scope_->set_module_name(root_scope_->basename());
View
@@ -38,8 +38,8 @@ class PExpr;
* in question.
*/
-NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t)
-: type_(t), name_(n), up_(up)
+NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest, bool prog)
+: type_(t), name_(n), nested_module_(nest), program_block_(prog), up_(up)
{
events_ = 0;
lcounter_ = 0;
@@ -302,9 +302,6 @@ void NetScope::print_type(ostream&stream) const
case FUNC:
stream << "function";
break;
- case NESTED_MODULE:
- stream << "nested_module <" << (module_name_ ? module_name_.str() : "")
- << "> instance";
case MODULE:
stream << "module <" << (module_name_ ? module_name_.str() : "")
<< "> instance";
@@ -363,31 +360,31 @@ const NetFuncDef* NetScope::func_def() const
void NetScope::set_module_name(perm_string n)
{
- assert(type_ == MODULE || type_ == NESTED_MODULE);
+ assert(type_ == MODULE);
module_name_ = n; /* NOTE: n must have been permallocated. */
}
perm_string NetScope::module_name() const
{
- assert(type_ == MODULE || type_ == NESTED_MODULE);
+ assert(type_ == MODULE);
return module_name_;
}
void NetScope::add_module_port(NetNet*port)
{
- assert(type_ == MODULE || type_ == NESTED_MODULE);
+ assert(type_ == MODULE);
ports_.push_back(port);
}
unsigned NetScope::module_ports() const
{
- assert(type_ == MODULE || type_ == NESTED_MODULE);
+ assert(type_ == MODULE);
return ports_.size();
}
NetNet* NetScope::module_port(unsigned idx) const
{
- assert(type_ == MODULE || type_ == NESTED_MODULE);
+ assert(type_ == MODULE);
assert(idx < ports_.size());
return ports_[idx];
}
View
@@ -724,11 +724,11 @@ extern std::ostream&operator << (std::ostream&out, const std::list<netrange_t>&r
class NetScope : public Attrib {
public:
- enum TYPE { MODULE, NESTED_MODULE, TASK, FUNC, BEGIN_END, FORK_JOIN, GENBLOCK };
+ enum TYPE { MODULE, TASK, FUNC, BEGIN_END, FORK_JOIN, GENBLOCK };
/* Create a new scope, and attach it to the given parent. The
name is expected to have been permallocated. */
- NetScope(NetScope*up, const hname_t&name, TYPE t);
+ NetScope(NetScope*up, const hname_t&name, TYPE t, bool nest=false, bool prog=false);
~NetScope();
/* Rename the scope using the name generated by inserting as
@@ -805,8 +805,11 @@ class NetScope : public Attrib {
const NetScope* parent() const { return up_; }
const NetScope* child(const hname_t&name) const;
+ // Nested modules have slightly different scope search rules.
+ inline bool nested_module() const { return nested_module_; }
+ // Program blocks have elaboration constraints.
+ inline bool program_block() const { return program_block_; }
TYPE type() const;
- bool type_is_module() const { return type()==MODULE || type()==NESTED_MODULE; }
void print_type(ostream&) const;
void set_task_def(NetTaskDef*);
@@ -989,6 +992,11 @@ class NetScope : public Attrib {
TYPE type_;
hname_t name_;
+ // True if the scope is a nested module/program block
+ bool nested_module_;
+ // True if the scope is a program block
+ bool program_block_;
+
perm_string file_;
perm_string def_file_;
unsigned lineno_;
@@ -4012,7 +4020,7 @@ class Design {
const char* get_flag(const string&key) const;
- NetScope* make_root_scope(perm_string name);
+ NetScope* make_root_scope(perm_string name, bool program_block);
NetScope* find_root_scope();
list<NetScope*> find_root_scopes();
View
@@ -136,7 +136,6 @@ void nodangle_f::signal(Design*, NetNet*sig)
if ((sig->port_type() != NetNet::NOT_A_PORT) &&
((sig->scope()->type() == NetScope::TASK) ||
(sig->scope()->type() == NetScope::FUNC) ||
- (sig->scope()->type() == NetScope::NESTED_MODULE) ||
(sig->scope()->type() == NetScope::MODULE)))
return;
View
10 parse.y
@@ -5489,15 +5489,11 @@ statement_item /* This is roughly statement_item in the LRM */
{ PAssignNB*tmp = new PAssignNB($1,$3);
FILE_NAME(tmp, @1);
$$ = tmp;
- if (pform_in_program_block())
- yyerror(@2, "Non-blocking assignments not permitted in program blocks.");
}
| error K_LE expression ';'
{ yyerror(@2, "Syntax in assignment statement l-value.");
yyerrok;
$$ = new PNoop;
- if (pform_in_program_block())
- yyerror(@2, "Non-blocking assignments not permitted in program blocks.");
}
| lpvalue '=' delay1 expression ';'
{ PExpr*del = $3->front(); $3->pop_front();
@@ -5512,8 +5508,6 @@ statement_item /* This is roughly statement_item in the LRM */
PAssignNB*tmp = new PAssignNB($1,del,$4);
FILE_NAME(tmp, @1);
$$ = tmp;
- if (pform_in_program_block())
- yyerror(@2, "Non-blocking assignments not permitted in program blocks.");
}
| lpvalue '=' event_control expression ';'
{ PAssign*tmp = new PAssign($1,0,$3,$4);
@@ -5530,15 +5524,11 @@ statement_item /* This is roughly statement_item in the LRM */
{ PAssignNB*tmp = new PAssignNB($1,0,$3,$4);
FILE_NAME(tmp, @1);
$$ = tmp;
- if (pform_in_program_block())
- yyerror(@2, "Non-blocking assignments not permitted in program blocks.");
}
| lpvalue K_LE K_repeat '(' expression ')' event_control expression ';'
{ PAssignNB*tmp = new PAssignNB($1,$5,$7,$8);
FILE_NAME(tmp, @1);
$$ = tmp;
- if (pform_in_program_block())
- yyerror(@2, "Non-blocking assignments not permitted in program blocks.");
}
/* The IEEE1800 standard defines dynamic_array_new assignment as a
View
@@ -79,7 +79,7 @@ NetScope*symbol_search(const LineInfo*li, Design*des, NetScope*scope,
/* We can't look up if we are at the enclosing module scope
* or if a hierarchical path was given. */
- if ((scope->type() == NetScope::MODULE) || hier_path)
+ if ((scope->type()==NetScope::MODULE && !scope->nested_module()) || hier_path)
scope = 0;
else
scope = scope->parent();
View
@@ -2297,7 +2297,6 @@ void dll_target::scope(const NetScope*net)
switch (net->type()) {
case NetScope::MODULE:
- case NetScope::NESTED_MODULE:
scop->type_ = IVL_SCT_MODULE;
scop->tname_ = net->module_name();
scop->ports = net->module_ports();

0 comments on commit 8154ce2

Please sign in to comment.