Skip to content

Commit

Permalink
Fix for pr2924354.
Browse files Browse the repository at this point in the history
Creation of implicit nets requires knowledge of whether an identifier
has been declared before it is used. Currently implicit nets are
created during elaboration, but by this stage the order of declaration
and use is not known. This patch moves the creation of implicit nets
into the parser stage.
  • Loading branch information
martinwhitaker authored and steveicarus committed Jan 23, 2010
1 parent 9fbb12d commit f955937
Show file tree
Hide file tree
Showing 15 changed files with 146 additions and 231 deletions.
4 changes: 1 addition & 3 deletions Module.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2009 Stephen Williams ([email protected])
* Copyright (c) 1998-2010 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
Expand Down Expand Up @@ -33,7 +33,6 @@ Module::Module(perm_string n)
library_flag = false;
is_cell = false;
uc_drive = UCD_NONE;
default_nettype = NetNet::NONE;
timescale_warn_done = false;
}

Expand Down Expand Up @@ -105,4 +104,3 @@ const list<PGate*>& Module::get_gates() const
{
return gates_;
}

10 changes: 2 additions & 8 deletions Module.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef __Module_H
#define __Module_H
/*
* Copyright (c) 1998-2009 Stephen Williams ([email protected])
* Copyright (c) 1998-2010 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
Expand Down Expand Up @@ -79,8 +79,6 @@ class Module : public PScope, public LineInfo {
enum UCDriveType { UCD_NONE, UCD_PULL0, UCD_PULL1 };
UCDriveType uc_drive;

NetNet::Type default_nettype;

/* specparams are simpler then other params, in that they have
no type information. They are merely constant
expressions. */
Expand Down Expand Up @@ -118,11 +116,7 @@ class Module : public PScope, public LineInfo {
map<perm_string,PTask*> tasks;
map<perm_string,PFunction*> funcs;

/* The module has a list of genvars that may be used in
various generate schemes. */
map<perm_string,LineInfo*> genvars;

/* the module has a list of generate schemes that appear in
/* The module has a list of generate schemes that appear in
the module definition. These are used at elaboration time. */
list<PGenerate*> generate_schemes;

Expand Down
82 changes: 81 additions & 1 deletion PExpr.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2008 Stephen Williams <[email protected]>
* Copyright (c) 1998-2008,2010 Stephen Williams <[email protected]>
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
Expand All @@ -23,6 +23,7 @@

# include "compiler.h"
# include "PExpr.h"
# include "PWire.h"
# include "Module.h"
# include "netmisc.h"
# include <typeinfo>
Expand All @@ -36,6 +37,10 @@ PExpr::~PExpr()
{
}

void PExpr::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
{
}

bool PExpr::has_aa_term(Design*, NetScope*) const
{
return false;
Expand Down Expand Up @@ -70,6 +75,13 @@ PEBinary::~PEBinary()
{
}

void PEBinary::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
{
assert(left_ && right_);
left_->declare_implicit_nets(scope, type);
right_->declare_implicit_nets(scope, type);
}

bool PEBinary::has_aa_term(Design*des, NetScope*scope) const
{
assert(left_ && right_);
Expand Down Expand Up @@ -160,6 +172,13 @@ PECallFunction::~PECallFunction()
{
}

void PECallFunction::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
{
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
parms_[idx]->declare_implicit_nets(scope, type);
}
}

bool PECallFunction::has_aa_term(Design*des, NetScope*scope) const
{
bool flag = false;
Expand All @@ -179,6 +198,13 @@ PEConcat::~PEConcat()
delete repeat_;
}

void PEConcat::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
{
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
parms_[idx]->declare_implicit_nets(scope, type);
}
}

bool PEConcat::has_aa_term(Design*des, NetScope*scope) const
{
bool flag = false;
Expand Down Expand Up @@ -245,6 +271,46 @@ PEIdent::~PEIdent()
{
}

void PEIdent::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
{
/* We create an implicit wire if this is a simple identifier and
if an identifier of that name has not already been declared in
any enclosing scope. */
if ((path_.size() == 1) && (path_.front().index.size() == 0)) {
perm_string name = path_.front().name;
LexicalScope*ss = scope;
while (ss) {
if (ss->wires.find(name) != ss->wires.end())
return;
if (ss->localparams.find(name) != ss->localparams.end())
return;
if (ss->parameters.find(name) != ss->parameters.end())
return;
if (ss->genvars.find(name) != ss->genvars.end())
return;
if (ss->events.find(name) != ss->events.end())
return;
/* Strictly speaking, we should also check for name clashes
with tasks, functions, named blocks, module instances,
and generate blocks. However, this information is not
readily available. As these names would not be legal in
this context, we can declare implicit nets here and rely
on later checks for name clashes to report the error. */

ss = ss->parent_scope();
}
PWire*net = new PWire(name, type, NetNet::NOT_A_PORT, IVL_VT_LOGIC);
net->set_file(get_file());
net->set_lineno(get_lineno());
net->set_range(0, 0, SR_NET, true);
scope->wires[name] = net;
if (warn_implicit) {
cerr << get_fileline() << ": warning: implicit "
"definition of wire '" << name << "'." << endl;
}
}
}

bool PEIdent::has_aa_term(Design*des, NetScope*scope) const
{
NetNet* net = 0;
Expand Down Expand Up @@ -310,6 +376,14 @@ PETernary::~PETernary()
{
}

void PETernary::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
{
assert(expr_ && tru_ && fal_);
expr_->declare_implicit_nets(scope, type);
tru_->declare_implicit_nets(scope, type);
fal_->declare_implicit_nets(scope, type);
}

bool PETernary::has_aa_term(Design*des, NetScope*scope) const
{
assert(expr_ && tru_ && fal_);
Expand All @@ -327,6 +401,12 @@ PEUnary::~PEUnary()
{
}

void PEUnary::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
{
assert(expr_);
expr_->declare_implicit_nets(scope, type);
}

bool PEUnary::has_aa_term(Design*des, NetScope*scope) const
{
assert(expr_);
Expand Down
38 changes: 23 additions & 15 deletions PExpr.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

class Design;
class Module;
class LexicalScope;
class NetNet;
class NetExpr;
class NetScope;
Expand All @@ -47,6 +48,16 @@ class PExpr : public LineInfo {

virtual void dump(ostream&) const;

// This method tests whether the expression contains any identifiers
// that have not been previously declared in the specified scope or
// in any containing scope. Any such identifiers are added to the
// specified scope as scalar nets of the specified type.
//
// This operation must be performed by the parser, to ensure that
// subsequent declarations do not affect the decision to create an
// implicit net.
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);

// This method tests whether the expression contains any
// references to automatically allocated variables.
virtual bool has_aa_term(Design*des, NetScope*scope) const;
Expand Down Expand Up @@ -85,10 +96,6 @@ class PExpr : public LineInfo {
ivl_variable_type_t expr_type() const { return expr_type_; }
unsigned expr_width() const { return expr_width_; }

// During the elaborate_sig phase, we may need to scan
// expressions to find implicit net declarations.
virtual bool elaborate_sig(Design*des, NetScope*scope) const;

// Procedural elaboration of the expression. The expr_width is
// the width of the context of the expression (i.e. the
// l-value width of an assignment),
Expand Down Expand Up @@ -159,14 +166,15 @@ class PEConcat : public PExpr {
virtual verinum* eval_const(Design*des, NetScope*sc) const;
virtual void dump(ostream&) const;

virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);

virtual bool has_aa_term(Design*des, NetScope*scope) const;

virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag);

virtual bool elaborate_sig(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
Expand Down Expand Up @@ -257,15 +265,15 @@ class PEIdent : public PExpr {

virtual void dump(ostream&) const;

virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);

virtual bool has_aa_term(Design*des, NetScope*scope) const;

virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag);

virtual bool elaborate_sig(Design*des, NetScope*scope) const;

// Identifiers are allowed (with restrictions) is assign l-values.
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;

Expand Down Expand Up @@ -376,8 +384,6 @@ class PEIdent : public PExpr {
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
bool bidirectional_flag) const;

NetNet*make_implicit_net_(Design*des, NetScope*scope) const;

bool eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
long&midx, long&lidx) const;
};
Expand Down Expand Up @@ -449,15 +455,15 @@ class PEUnary : public PExpr {

virtual void dump(ostream&out) const;

virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);

virtual bool has_aa_term(Design*des, NetScope*scope) const;

virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag);

virtual bool elaborate_sig(Design*des, NetScope*scope) const;

virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
Expand All @@ -479,15 +485,15 @@ class PEBinary : public PExpr {

virtual void dump(ostream&out) const;

virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);

virtual bool has_aa_term(Design*des, NetScope*scope) const;

virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag);

virtual bool elaborate_sig(Design*des, NetScope*scope) const;

virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
Expand Down Expand Up @@ -613,15 +619,15 @@ class PETernary : public PExpr {

virtual void dump(ostream&out) const;

virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);

virtual bool has_aa_term(Design*des, NetScope*scope) const;

virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag);

virtual bool elaborate_sig(Design*des, NetScope*scope) const;

virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
virtual NetETernary*elaborate_pexpr(Design*des, NetScope*sc) const;
Expand Down Expand Up @@ -657,6 +663,8 @@ class PECallFunction : public PExpr {

virtual void dump(ostream &) const;

virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);

virtual bool has_aa_term(Design*des, NetScope*scope) const;

virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
Expand Down
5 changes: 5 additions & 0 deletions PScope.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ class LexicalScope {
map<perm_string,PWire*>wires;
PWire* wires_find(perm_string name);

// Genvars in the scope. These will only be present in module
// scopes, but are listed here to allow them to be found when
// creating implicit nets.
map<perm_string,LineInfo*> genvars;

// Behaviors (processes) in this scope
list<PProcess*> behaviors;
list<AProcess*> analog_behaviors;
Expand Down
3 changes: 1 addition & 2 deletions compiler.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef __compiler_H
#define __compiler_H
/*
* Copyright (c) 1999-2009 Stephen Williams ([email protected])
* Copyright (c) 1999-2010 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
Expand Down Expand Up @@ -74,7 +74,6 @@ extern unsigned recursive_mod_limit;

/* Implicit definitions of wires. */
extern bool warn_implicit;
extern bool error_implicit;

/* inherit timescales across files. */
extern bool warn_timescale;
Expand Down
16 changes: 0 additions & 16 deletions elab_expr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2114,22 +2114,6 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
}
}

if (error_implicit==false
&& sys_task_arg==false
&& path_.size()==1
&& scope->default_nettype() != NetNet::NONE) {
NetNet::Type nettype = scope->default_nettype();
net = new NetNet(scope, peek_tail_name(path_), nettype, 1);
net->data_type(IVL_VT_LOGIC);
net->set_line(*this);
if (warn_implicit) {
cerr << get_fileline() << ": warning: implicit "
"definition of wire " << scope_path(scope)
<< "." << peek_tail_name(path_) << "." << endl;
}
return elaborate_expr_net(des, scope, net, scope, sys_task_arg);
}

// At this point we've exhausted all the possibilities that
// are not scopes. If this is not a system task argument, then
// it cannot be a scope name, so give up.
Expand Down
Loading

0 comments on commit f955937

Please sign in to comment.