Prevent non-blocking writes to fields of automatic structs

The `PEIdent::has_aa_term()` method still uses the old `symbol_search()`
and will fail to find the variable if part of the identifier path is a
member select of a variable.

As a result such writes to fields of automatic structs can be classified as
static and it is possible to do non-blocking assignments to them. E.g.

```
task automatic t;
  struct packed {
    logic x;
  } s;
  s <= ...; // This fails
  s.x <= ...; // This works, but should fail
endtask
```

Switch to the new symbol search to make sure this case is handled
correctly. The new symbol search will correctly handle identifier paths
that have a trailing item after the variable, while the old symbol search
will always return an error in that case.

Note that while it is not allowed to do a non-blocking write to a class
object automatic variable, it is allowed to do a non-blocking write to a
property of a class object that is stored in an automatic variable, as the
non-blocking write is supposed to capture a reference to the object and not
reference the variable. E.g.

```
class C;
  int x;
endclass

task automatic t;
  C c;
  c <= ...; // Not allowed
  c.x <= ...; // Allowed
endtask
```

Non-blocking access to class properties is not yet support in
Icarus in general, but the error handling for that needs to be done
somewhere else.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
Lars-Peter Clausen 2022-09-25 13:08:10 +02:00
parent 3b711ed785
commit e7d3e7440d
1 changed files with 9 additions and 11 deletions

View File

@ -446,19 +446,17 @@ void PEIdent::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
bool PEIdent::has_aa_term(Design*des, NetScope*scope) const
{
NetNet* net = 0;
ivl_type_t cls_val;
const NetExpr*par = 0;
ivl_type_t par_type;
NetEvent* eve = 0;
scope = symbol_search(this, des, scope, path_, net, par, eve,
par_type, cls_val);
if (scope)
return scope->is_auto();
else
symbol_search_results sr;
if (!symbol_search(this, des, scope, path_, &sr))
return false;
// Class properties are not considered automatic since a non-blocking
// assignment to an object stored in an automatic variable is supposed to
// capture a reference to the object, not the variable.
if (!sr.path_tail.empty() && sr.net && sr.net->class_type())
return false;
return sr.scope->is_auto();
}
PENewArray::PENewArray(PExpr*size_expr, PExpr*init_expr)