Merge branch 'package-imports-rework'

This commit is contained in:
Martin Whitaker 2019-10-01 23:04:23 +01:00
commit 9bb2147fb5
41 changed files with 868 additions and 899 deletions

View File

@ -118,9 +118,9 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
pform_disciplines.o pform_dump.o pform_package.o pform_pclass.o \
pform_class_type.o pform_string_type.o pform_struct_type.o pform_types.o \
symbol_search.o sync.o sys_funcs.o verinum.o verireal.o target.o \
Attrib.o HName.o Module.o PClass.o PDelays.o PEvent.o PExpr.o PGate.o \
PGenerate.o PModport.o PPackage.o PScope.o PSpec.o PTask.o PUdp.o \
PFunction.o PWire.o Statement.o AStatement.o $M $(FF) $(TT)
Attrib.o HName.o Module.o PClass.o PDelays.o PEvent.o PExpr.o PFunction.o \
PGate.o PGenerate.o PModport.o PNamedItem.o PPackage.o PScope.o PSpec.o \
PTask.o PUdp.o PWire.o Statement.o AStatement.o $M $(FF) $(TT)
all: dep config.h _pli_types.h version_tag.h ivl@EXEEXT@ version.exe iverilog-vpi.man
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -122,3 +122,13 @@ const list<PGate*>& Module::get_gates() const
{
return gates_;
}
PNamedItem::SymbolType Module::symbol_type() const
{
if (program_block)
return PROGRAM;
if (is_interface)
return INTERFACE;
return MODULE;
}

View File

@ -1,7 +1,7 @@
#ifndef IVL_Module_H
#define IVL_Module_H
/*
* Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -28,7 +28,7 @@
# include "HName.h"
# include "named.h"
# include "PScope.h"
# include "LineInfo.h"
# include "PNamedItem.h"
# include "netlist.h"
# include "pform_types.h"
class PExpr;
@ -54,7 +54,7 @@ class NetScope;
* these containers as well.
*/
class Module : public PScopeExtra, public LineInfo {
class Module : public PScopeExtra, public PNamedItem {
/* The module ports are in general a vector of port_t
objects. Each port has a name and an ordered list of
@ -97,7 +97,7 @@ class Module : public PScopeExtra, public LineInfo {
/* specparams are simpler than other parameters, in that they
can have a range, but not an explicit type. The restrictions
are enforced by the parser. */
map<perm_string,param_expr_t>specparams;
map<perm_string,param_expr_t*>specparams;
/* The module also has defparam assignments which don't create
new parameters within the module, but may be used to set
@ -160,6 +160,8 @@ class Module : public PScopeExtra, public LineInfo {
bool elaborate_sig(Design*, NetScope*scope) const;
SymbolType symbol_type() const;
private:
void dump_specparams_(ostream&out, unsigned indent) const;
list<PGate*> gates_;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -28,3 +28,8 @@ PClass::PClass(perm_string name, LexicalScope*parent)
PClass::~PClass()
{
}
PNamedItem::SymbolType PClass::symbol_type() const
{
return CLASS;
}

View File

@ -1,7 +1,7 @@
#ifndef IVL_PClass_H
#define IVL_PClass_H
/*
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -20,7 +20,7 @@
*/
# include "PScope.h"
# include "LineInfo.h"
# include "PNamedItem.h"
# include "StringHeap.h"
# include <iostream>
@ -32,7 +32,7 @@ class PChainConstructor;
* collected.
*/
class PClass : public PScopeExtra, public LineInfo {
class PClass : public PScopeExtra, public PNamedItem {
public:
explicit PClass (perm_string name, LexicalScope*parent);
@ -40,6 +40,8 @@ class PClass : public PScopeExtra, public LineInfo {
void dump(std::ostream&out, unsigned indent) const;
SymbolType symbol_type() const;
public:
class_type_t*type;
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004 Stephen Williams (steve@icarus.com)
* Copyright (c) 2004-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -35,3 +35,7 @@ perm_string PEvent::name() const
return name_;
}
PNamedItem::SymbolType PEvent::symbol_type() const
{
return EVENT;
}

View File

@ -1,7 +1,7 @@
#ifndef IVL_PEvent_H
#define IVL_PEvent_H
/*
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -19,7 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "LineInfo.h"
# include "PNamedItem.h"
# include "StringHeap.h"
# include <string>
@ -31,7 +31,7 @@ class NetScope;
* are declared in Verilog as ``event foo;'' The name passed to the
* constructor is the "foo" part of the declaration.
*/
class PEvent : public LineInfo {
class PEvent : public PNamedItem {
public:
// The name is a perm-allocated string. It is the simple name
@ -43,6 +43,8 @@ class PEvent : public LineInfo {
void elaborate_scope(Design*des, NetScope*scope) const;
SymbolType symbol_type() const;
private:
perm_string name_;

View File

@ -1,7 +1,7 @@
#ifndef IVL_PExpr_H
#define IVL_PExpr_H
/*
* Copyright (c) 1998-2016 Stephen Williams <steve@icarus.com>
* Copyright (c) 1998-2019 Stephen Williams <steve@icarus.com>
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -379,6 +379,8 @@ class PEIdent : public PExpr {
virtual bool is_collapsible_net(Design*des, NetScope*scope) const;
const PPackage* package() const { return package_; }
const pform_name_t& path() const { return path_; }
private:

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -83,3 +83,8 @@ PChainConstructor* PFunction::extract_chain_constructor()
return res;
}
PNamedItem::SymbolType PFunction::symbol_type() const
{
return FUNCTION;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -117,6 +117,11 @@ unsigned PGate::delay_count() const
return delay_.delay_count();
}
PNamedItem::SymbolType PGate::symbol_type() const
{
return INSTANCE;
}
PGAssign::PGAssign(list<PExpr*>*pins)
: PGate(perm_string(), pins)
{

View File

@ -1,7 +1,7 @@
#ifndef IVL_PGate_H
#define IVL_PGate_H
/*
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -22,7 +22,7 @@
# include "svector.h"
# include "StringHeap.h"
# include "named.h"
# include "LineInfo.h"
# include "PNamedItem.h"
# include "PDelays.h"
# include "netlist.h"
# include <map>
@ -47,7 +47,7 @@ class Module;
* single strength pair. There is a strength of the 0 drive, and a
* strength of the 1 drive.
*/
class PGate : public LineInfo {
class PGate : public PNamedItem {
public:
explicit PGate(perm_string name, list<PExpr*>*pins,
@ -88,6 +88,8 @@ class PGate : public LineInfo {
virtual void elaborate_scope(Design*des, NetScope*sc) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
SymbolType symbol_type() const;
protected:
const vector<PExpr*>& get_pins() const { return pins_; }

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 2006-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -112,3 +112,8 @@ ostream& operator << (ostream&out, PGenerate::scheme_t type)
}
return out;
}
PNamedItem::SymbolType PGenerate::symbol_type() const
{
return GENBLOCK;
}

View File

@ -1,7 +1,7 @@
#ifndef IVL_PGenerate_H
#define IVL_PGenerate_H
/*
* Copyright (c) 2006-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2006-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -19,7 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "LineInfo.h"
# include "PNamedItem.h"
# include "StringHeap.h"
# include "HName.h"
# include "PScope.h"
@ -50,7 +50,7 @@ class PWire;
* The parent points to the GS_CASE that contains this item.
* the loop_test is compared with the parent->loop_test expression.
*/
class PGenerate : public LineInfo, public LexicalScope {
class PGenerate : public PNamedItem, public LexicalScope {
public:
explicit PGenerate(LexicalScope*parent, unsigned id_number);
@ -107,6 +107,8 @@ class PGenerate : public LineInfo, public LexicalScope {
void dump(ostream&out, unsigned indent) const;
SymbolType symbol_type() const;
private:
bool generate_scope_loop_(Design*des, NetScope*container);
bool generate_scope_condit_(Design*des, NetScope*container, bool else_flag);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2015-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -29,3 +29,8 @@ PModport::PModport(perm_string n)
PModport::~PModport()
{
}
PNamedItem::SymbolType PModport::symbol_type() const
{
return MODPORT;
}

View File

@ -1,7 +1,7 @@
#ifndef IVL_PModport_H
#define IVL_PModport_H
/*
* Copyright (c) 2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2015-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -19,7 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "LineInfo.h"
# include "PNamedItem.h"
# include "PScope.h"
# include "StringHeap.h"
# include "netlist.h"
@ -28,7 +28,7 @@
/*
* The PModport class represents a parsed SystemVerilog modport list.
*/
class PModport : public LineInfo {
class PModport : public PNamedItem {
public:
// The name is a perm-allocated string. It is the simple name
@ -41,6 +41,8 @@ class PModport : public LineInfo {
typedef pair <NetNet::PortType,PExpr*> simple_port_t;
map<perm_string,simple_port_t> simple_ports;
SymbolType symbol_type() const;
private:
perm_string name_;

116
PNamedItem.cc Normal file
View File

@ -0,0 +1,116 @@
/*
* Copyright (c) 2019 Martin Whitaker (icarus@martin-whitaker.me.uk)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "PNamedItem.h"
# include <ostream>
PNamedItem::PNamedItem()
{
}
PNamedItem::~PNamedItem()
{
}
PNamedItem::SymbolType PNamedItem::symbol_type() const
{
return ANY;
}
std::ostream& operator << (std::ostream&o, PNamedItem::SymbolType st)
{
switch (st) {
case PNamedItem::ANY:
o << "a symbol";
break;
case PNamedItem::PARAM:
o << "a parameter";
break;
case PNamedItem::NET:
o << "a net";
break;
case PNamedItem::VAR:
o << "a variable";
break;
case PNamedItem::GENVAR:
o << "a genvar";
break;
case PNamedItem::EVENT:
o << "an event";
break;
case PNamedItem::TYPE:
o << "a type";
break;
case PNamedItem::ENUM:
o << "an enum type or value";
break;
case PNamedItem::CLASS:
o << "a class";
break;
case PNamedItem::FUNCTION:
o << "a function";
break;
case PNamedItem::TASK:
o << "a task";
break;
case PNamedItem::BLOCK:
o << "a named block";
break;
case PNamedItem::GENBLOCK:
o << "a generate block";
break;
case PNamedItem::MODPORT:
o << "a modport";
break;
case PNamedItem::PACKAGE:
o << "a package";
break;
case PNamedItem::MODULE:
o << "a module";
break;
case PNamedItem::PROGRAM:
o << "a program";
break;
case PNamedItem::INTERFACE:
o << "an interface";
break;
case PNamedItem::PRIMITIVE:
o << "a primitive";
break;
case PNamedItem::INSTANCE:
o << "an instance name";
break;
default:
break;
}
return o;
}
PGenvar::PGenvar()
{
}
PGenvar::~PGenvar()
{
}
PNamedItem::SymbolType PGenvar::symbol_type() const
{
return GENVAR;
}

57
PNamedItem.h Normal file
View File

@ -0,0 +1,57 @@
#ifndef IVL_PNamedItem_H
#define IVL_PNamedItem_H
/*
* Copyright (c) 2019 Martin Whitaker (icarus@martin-whitaker.me.uk)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "LineInfo.h"
/*
* The PNamedItem class is the base class for all items that can be added
* to a scope's local symbol map.
*/
class PNamedItem : virtual public LineInfo {
public:
enum SymbolType { ANY, PARAM, NET, VAR, GENVAR, EVENT, TYPE, ENUM,
CLASS, FUNCTION, TASK, BLOCK, GENBLOCK, MODPORT,
PACKAGE, MODULE, PROGRAM, INTERFACE, PRIMITIVE,
INSTANCE };
explicit PNamedItem();
virtual ~PNamedItem();
virtual SymbolType symbol_type() const;
};
extern std::ostream& operator << (std::ostream&, PNamedItem::SymbolType);
/*
* The PGenvar class represents a genvar. This is only used to represent
* genvar in a scope's local symbol map.
*/
class PGenvar : public PNamedItem {
public:
explicit PGenvar();
virtual ~PGenvar();
SymbolType symbol_type() const;
};
#endif /* IVL_PNamedItem_H */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008-2017 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -33,6 +33,11 @@ PWire* LexicalScope::wires_find(perm_string name)
return (*cur).second;
}
PNamedItem::SymbolType LexicalScope::param_expr_t::symbol_type() const
{
return PARAM;
}
PScope::PScope(perm_string n, LexicalScope*parent)
: LexicalScope(parent), name_(n)
{

View File

@ -1,7 +1,7 @@
#ifndef IVL_PScope_H
#define IVL_PScope_H
/*
* Copyright (c) 2008-2017 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -19,7 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "LineInfo.h"
# include "PNamedItem.h"
# include "StringHeap.h"
# include "pform_types.h"
# include "ivl_target.h"
@ -61,6 +61,24 @@ class LexicalScope {
lifetime_t default_lifetime;
// Symbols that are defined or declared in this scope.
std::map<perm_string,PNamedItem*>local_symbols;
// Symbols that are explicitly imported. Bind the imported name
// to the package from which the name is imported.
std::map<perm_string,PPackage*>explicit_imports;
// Packages that are wildcard imported. When identifiers from
// these packages are referenced, they will be added to the
// explicit imports (IEEE 1800-2012 26.3).
std::set<PPackage*>potential_imports;
// A task or function call may reference a task or function defined
// later in the scope. So here we stash the potential imports for
// task and function calls. They will be added to the explicit
// imports if we don't find a local definition.
std::map<perm_string,PPackage*>possible_imports;
struct range_t {
// True if this is an exclude
bool exclude_flag;
@ -79,7 +97,7 @@ class LexicalScope {
/* The scope has parameters that are evaluated when the scope
is elaborated. During parsing, I put the parameters into
this map. */
struct param_expr_t : public LineInfo {
struct param_expr_t : public PNamedItem {
param_expr_t() : type(IVL_VT_NO_TYPE), msb(0), lsb(0), signed_flag(false), expr(0), range(0) { }
// Type information
ivl_variable_type_t type;
@ -90,9 +108,11 @@ class LexicalScope {
PExpr*expr;
// If there are range constraints, list them here
range_t*range;
SymbolType symbol_type() const;
};
map<perm_string,param_expr_t>parameters;
map<perm_string,param_expr_t>localparams;
map<perm_string,param_expr_t*>parameters;
map<perm_string,param_expr_t*>localparams;
// Defined types in the scope.
map<perm_string,data_type_t*>typedefs;
@ -100,10 +120,6 @@ class LexicalScope {
// Named events in the scope.
map<perm_string,PEvent*>events;
// Symbols that are imported. Bind the imported name to the
// package from which the name is imported.
std::map<perm_string,PPackage*>imports;
// Nets and variables (wires) in the scope
map<perm_string,PWire*>wires;
PWire* wires_find(perm_string name);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2008,2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -73,3 +73,8 @@ void PTask::set_statement(Statement*s)
assert(statement_ == 0);
statement_ = s;
}
PNamedItem::SymbolType PTask::symbol_type() const
{
return TASK;
}

10
PTask.h
View File

@ -1,7 +1,7 @@
#ifndef IVL_PTask_H
#define IVL_PTask_H
/*
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -19,8 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "LineInfo.h"
# include "PScope.h"
# include "PNamedItem.h"
# include "StringHeap.h"
# include <string>
# include <vector>
@ -35,7 +35,7 @@ class Statement;
class PExpr;
class PTaskFunc : public PScope, public LineInfo {
class PTaskFunc : public PScope, public PNamedItem {
public:
PTaskFunc(perm_string name, LexicalScope*parent);
@ -99,6 +99,8 @@ class PTask : public PTaskFunc {
void dump(ostream&, unsigned) const;
SymbolType symbol_type() const;
private:
Statement*statement_;
bool is_auto_;
@ -148,6 +150,8 @@ class PFunction : public PTaskFunc {
void dump(ostream&, unsigned) const;
SymbolType symbol_type() const;
private:
data_type_t* return_type_;
Statement *statement_;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -283,3 +283,15 @@ ivl_discipline_t PWire::get_discipline(void) const
{
return discipline_;
}
PNamedItem::SymbolType PWire::symbol_type() const
{
switch (type_) {
case NetNet::IMPLICIT_REG:
case NetNet::INTEGER:
case NetNet::REG:
return VAR;
default:
return NET;
}
}

View File

@ -1,7 +1,7 @@
#ifndef IVL_PWire_H
#define IVL_PWire_H
/*
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -20,7 +20,7 @@
*/
# include "netlist.h"
# include "LineInfo.h"
# include "PNamedItem.h"
# include <list>
# include <map>
# include "StringHeap.h"
@ -51,7 +51,7 @@ enum PWSRType {SR_PORT, SR_NET, SR_BOTH};
* from that perspective, sub-scopes within the module are a part of
* the wire name.
*/
class PWire : public LineInfo {
class PWire : public PNamedItem {
public:
PWire(perm_string name,
@ -93,6 +93,8 @@ class PWire : public LineInfo {
NetNet* elaborate_sig(Design*, NetScope*scope) const;
SymbolType symbol_type() const;
private:
perm_string name_;
NetNet::Type type_;

View File

@ -158,6 +158,11 @@ void PBlock::push_statement_front(Statement*that)
list_[0] = that;
}
PNamedItem::SymbolType PBlock::symbol_type() const
{
return BLOCK;
}
PCallTask::PCallTask(const pform_name_t&n, const list<PExpr*>&p)
: package_(0), path_(n), parms_(p.size())
{
@ -411,8 +416,8 @@ PReturn::~PReturn()
delete expr_;
}
PTrigger::PTrigger(const pform_name_t&e)
: event_(e)
PTrigger::PTrigger(PPackage*pkg, const pform_name_t&e)
: package_(pkg), event_(e)
{
}

View File

@ -75,7 +75,7 @@ class PProcess : public LineInfo {
* fact, the Statement class is abstract and represents all the
* possible kinds of statements that exist in Verilog.
*/
class Statement : public LineInfo {
class Statement : virtual public LineInfo {
public:
Statement() { }
@ -170,7 +170,7 @@ class PAssignNB : public PAssign_ {
* statements before constructing this object, so it knows a priori
* what is contained.
*/
class PBlock : public PScope, public Statement {
class PBlock : public PScope, public Statement, public PNamedItem {
public:
enum BL_TYPE { BL_SEQ, BL_PAR, BL_JOIN_NONE, BL_JOIN_ANY };
@ -205,6 +205,8 @@ class PBlock : public PScope, public Statement {
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
SymbolType symbol_type() const;
private:
BL_TYPE bl_type_;
std::vector<Statement*>list_;
@ -561,13 +563,14 @@ class PReturn : public Statement {
class PTrigger : public Statement {
public:
explicit PTrigger(const pform_name_t&ev);
explicit PTrigger(PPackage*pkg, const pform_name_t&ev);
~PTrigger();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
PPackage*package_;
pform_name_t event_;
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2019 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -63,7 +63,7 @@ void set_scope_timescale(Design*des, NetScope*scope, PScope*pscope)
des->set_precision(pscope->time_precision);
}
typedef map<perm_string,LexicalScope::param_expr_t>::const_iterator mparm_it_t;
typedef map<perm_string,LexicalScope::param_expr_t*>::const_iterator mparm_it_t;
static void collect_parm_item_(Design*des, NetScope*scope, perm_string name,
const LexicalScope::param_expr_t&cur,
@ -110,59 +110,32 @@ static void collect_parm_item_(Design*des, NetScope*scope, perm_string name,
}
static void collect_scope_parameters_(Design*des, NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t>&parameters)
const map<perm_string,LexicalScope::param_expr_t*>&parameters)
{
for (mparm_it_t cur = parameters.begin()
; cur != parameters.end() ; ++ cur ) {
// A parameter can not have the same name as a genvar.
if (scope->find_genvar((*cur).first)) {
cerr << cur->second.get_fileline()
<< ": error: parameter and genvar in '"
<< scope->fullname() << "' have the same name '"
<< (*cur).first << "'." << endl;
des->errors += 1;
}
collect_parm_item_(des, scope, (*cur).first, (*cur).second, false, false);
collect_parm_item_(des, scope, cur->first, *(cur->second), false, false);
}
}
static void collect_scope_localparams_(Design*des, NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t>&localparams)
const map<perm_string,LexicalScope::param_expr_t*>&localparams)
{
for (mparm_it_t cur = localparams.begin()
; cur != localparams.end() ; ++ cur ) {
// A localparam can not have the same name as a genvar.
if (scope->find_genvar((*cur).first)) {
cerr << cur->second.get_fileline()
<< ": error: localparam and genvar in '"
<< scope->fullname() << "' have the same name '"
<< (*cur).first << "'." << endl;
des->errors += 1;
}
collect_parm_item_(des, scope, (*cur).first, (*cur).second, false, true);
collect_parm_item_(des, scope, cur->first, *(cur->second), false, true);
}
}
static void collect_scope_specparams_(Design*des, NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t>&specparams)
const map<perm_string,LexicalScope::param_expr_t*>&specparams)
{
for (mparm_it_t cur = specparams.begin()
; cur != specparams.end() ; ++ cur ) {
// A specparam can not have the same name as a genvar.
if (scope->find_genvar((*cur).first)) {
cerr << cur->second.get_fileline()
<< ": error: specparam and genvar in '"
<< scope->fullname() << "' have the same name '"
<< (*cur).first << "'." << endl;
des->errors += 1;
}
collect_parm_item_(des, scope, (*cur).first, (*cur).second, true, false);
collect_parm_item_(des, scope, cur->first, *(cur->second), true, false);
}
}
@ -556,6 +529,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
// Task methods are always automatic...
method_scope->is_auto(true);
method_scope->set_line(cur->second);
method_scope->add_imports(&cur->second->explicit_imports);
if (debug_scopes) {
cerr << cur->second->get_fileline() << ": elaborate_scope_class: "
@ -574,6 +548,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
// Function methods are always automatic...
method_scope->is_auto(true);
method_scope->set_line(cur->second);
method_scope->add_imports(&cur->second->explicit_imports);
if (debug_scopes) {
cerr << cur->second->get_fileline() << ": elaborate_scope_class: "
@ -644,6 +619,7 @@ static void elaborate_scope_task(Design*des, NetScope*scope, PTask*task)
NetScope*task_scope = new NetScope(scope, use_name, NetScope::TASK);
task_scope->is_auto(task->is_auto());
task_scope->set_line(task);
task_scope->add_imports(&task->explicit_imports);
if (debug_scopes) {
cerr << task->get_fileline() << ": elaborate_scope_task: "
@ -661,39 +637,6 @@ static void elaborate_scope_tasks(Design*des, NetScope*scope,
for (tasks_it_t cur = tasks.begin()
; cur != tasks.end() ; ++ cur ) {
hname_t use_name( (*cur).first );
// A task can not have the same name as another scope object.
const NetScope *child = scope->child(use_name);
if (child) {
cerr << cur->second->get_fileline() << ": error: task and ";
child->print_type(cerr);
cerr << " in '" << scope->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
continue;
}
// A task can not have the same name as a genvar.
if (scope->find_genvar((*cur).first)) {
cerr << cur->second->get_fileline()
<< ": error: task and genvar in '"
<< scope->fullname() << "' have the same name '"
<< (*cur).first << "'." << endl;
des->errors += 1;
}
// A task can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter(des, (*cur).first,
ex_msb, ex_lsb);
if (parm) {
cerr << cur->second->get_fileline()
<< ": error: task and parameter in '"
<< scope->fullname() << "' have the same name '"
<< (*cur).first << "'." << endl;
des->errors += 1;
}
elaborate_scope_task(des, scope, cur->second);
}
@ -706,6 +649,7 @@ static void elaborate_scope_func(Design*des, NetScope*scope, PFunction*task)
NetScope*task_scope = new NetScope(scope, use_name, NetScope::FUNC);
task_scope->is_auto(task->is_auto());
task_scope->set_line(task);
task_scope->add_imports(&task->explicit_imports);
if (debug_scopes) {
cerr << task->get_fileline() << ": elaborate_scope_func: "
@ -723,40 +667,6 @@ static void elaborate_scope_funcs(Design*des, NetScope*scope,
for (funcs_it_t cur = funcs.begin()
; cur != funcs.end() ; ++ cur ) {
hname_t use_name( (*cur).first );
// A function can not have the same name as another scope object.
const NetScope *child = scope->child(use_name);
if (child) {
cerr << cur->second->get_fileline()
<< ": error: function and ";
child->print_type(cerr);
cerr << " in '" << scope->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
continue;
}
// A function can not have the same name as a genvar.
if (scope->find_genvar((*cur).first)) {
cerr << cur->second->get_fileline()
<< ": error: function and genvar in '"
<< scope->fullname() << "' have the same name '"
<< (*cur).first << "'." << endl;
des->errors += 1;
}
// A function can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter(des, (*cur).first,
ex_msb, ex_lsb);
if (parm) {
cerr << cur->second->get_fileline()
<< ": error: function and parameter in '"
<< scope->fullname() << "' have the same name '"
<< (*cur).first << "'." << endl;
des->errors += 1;
}
elaborate_scope_func(des, scope, cur->second);
}
@ -815,6 +725,7 @@ bool PPackage::elaborate_scope(Design*des, NetScope*scope)
elaborate_scope_classes(des, scope, classes_lexical);
elaborate_scope_funcs(des, scope, funcs);
elaborate_scope_tasks(des, scope, tasks);
elaborate_scope_events_(des, scope, events);
return true;
}
@ -1013,56 +924,6 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
return false;
}
// Check the generate block name.
// A generate "loop" can not have the same name as another
// scope object. Find any scope with this name, not just an
// exact match scope.
const NetScope *child = container->child_byname(scope_name);
if (child) {
cerr << get_fileline() << ": error: generate \"loop\" and ";
child->print_type(cerr);
cerr << " in '" << container->fullname()
<< "' have the same name '" << scope_name << "'." << endl;
des->errors += 1;
return false;
}
// A generate "loop" can not have the same name as a genvar.
if (container->find_genvar(scope_name)) {
cerr << get_fileline() << ": error: generate \"loop\" and "
"genvar in '" << container->fullname()
<< "' have the same name '" << scope_name << "'." << endl;
des->errors += 1;
}
// A generate "loop" can not have the same name as a named event.
const NetEvent *event = container->find_event(scope_name);
if (event) {
cerr << get_fileline() << ": error: generate \"loop\" and "
"named event in '" << container->fullname()
<< "' have the same name '" << scope_name << "'." << endl;
des->errors += 1;
}
// A generate "loop" can not have the same name as a parameter.
const NetExpr*tmsb;
const NetExpr*tlsb;
const NetExpr*texpr = container->get_parameter(des, scope_name,
tmsb, tlsb);
if (texpr != 0) {
cerr << get_fileline() << ": error: generate \"loop\" and "
"parameter in '" << container->fullname()
<< "' have the same name '" << scope_name << "'." << endl;
des->errors += 1;
}
// These have all been checked so we just need to skip the actual
// generation for these name conflicts. Not skipping these two will
// cause the compiler to have problems (assert, inf. loop, etc.).
if (container->get_parameter(des, loop_index, tmsb, tlsb)) return false;
if (container->find_event(loop_index)) return false;
genvar = init->value().as_long();
delete init_ex;
@ -1093,6 +954,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
scope->add_imports(&explicit_imports);
// Set in the scope a localparam for the value of the
// genvar within this instance of the generate
@ -1169,45 +1031,6 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
}
hname_t use_name (scope_name);
// A generate "if" can not have the same name as another scope object.
const NetScope *child = container->child(use_name);
if (child) {
cerr << get_fileline() << ": error: generate \"if\" and ";
child->print_type(cerr);
cerr << " in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
return false;
}
// A generate "if" can not have the same name as a genvar.
if (container->find_genvar(scope_name)) {
cerr << get_fileline() << ": error: generate \"if\" and "
"genvar in '" << container->fullname()
<< "' have the same name '" << scope_name << "'." << endl;
des->errors += 1;
}
// A generate "if" can not have the same name as a named event.
const NetEvent *event = container->find_event(scope_name);
if (event) {
cerr << get_fileline() << ": error: generate \"if\" and "
"named event in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
// A generate "if" can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = container->get_parameter(des, scope_name,
ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: generate \"if\" and "
"parameter in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
if (debug_scopes)
cerr << get_fileline() << ": debug: Generate condition "
<< (else_flag? "(else)" : "(if)")
@ -1228,6 +1051,7 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
// for myself. That is what I will pass to the subscope.
NetScope*scope = new NetScope(container, use_name, NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
scope->add_imports(&explicit_imports);
elaborate_subscope_(des, scope);
@ -1311,44 +1135,6 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
// The name of the scope to generate, whatever that item is.
hname_t use_name (item->scope_name);
// A generate "case" can not have the same name as another scope object.
const NetScope *child = container->child(use_name);
if (child) {
cerr << get_fileline() << ": error: generate \"case\" and ";
child->print_type(cerr);
cerr << " in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
return false;
}
// A generate "case" can not have the same name as a genvar.
if (container->find_genvar(item->scope_name)) {
cerr << get_fileline() << ": error: generate \"case\" and "
"genvar in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
// A generate "case" can not have the same name as a named event.
const NetEvent *event = container->find_event(item->scope_name);
if (event) {
cerr << get_fileline() << ": error: generate \"case\" and "
"named event in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
// A generate "case" can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = container->get_parameter(des, item->scope_name,
ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: generate \"case\" and "
"parameter in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
item->probe_for_direct_nesting_();
if (item->direct_nested_) {
@ -1368,6 +1154,8 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
scope->add_imports(&explicit_imports);
item->elaborate_subscope_(des, scope);
return true;
@ -1376,46 +1164,6 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
bool PGenerate::generate_scope_nblock_(Design*des, NetScope*container)
{
hname_t use_name (scope_name);
// A generate "block" can not have the same name as another scope
// object.
const NetScope *child = container->child(use_name);
if (child) {
cerr << get_fileline() << ": error: generate \"block\" and ";
child->print_type(cerr);
cerr << " in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
return false;
}
// A generate "block" can not have the same name as a genvar.
if (container->find_genvar(scope_name)) {
cerr << get_fileline() << ": error: generate \"block\" and "
"genvar in '" << container->fullname()
<< "' have the same name '" << scope_name << "'." << endl;
des->errors += 1;
}
// A generate "block" can not have the same name as a named event.
const NetEvent *event = container->find_event(scope_name);
if (event) {
cerr << get_fileline() << ": error: generate \"block\" and "
"named event in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
// A generate "block" can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = container->get_parameter(des, scope_name,
ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: generate \"block\" and "
"parameter in '" << container->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
if (debug_scopes)
cerr << get_fileline() << ": debug: Generate named block "
<< ": Generate scope=" << use_name << endl;
@ -1423,6 +1171,7 @@ bool PGenerate::generate_scope_nblock_(Design*des, NetScope*container)
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
scope->add_imports(&explicit_imports);
elaborate_subscope_(des, scope);
@ -1554,36 +1303,6 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
// Missing module instance names have already been rejected.
assert(get_name() != "");
// A module instance can not have the same name as another scope object.
const NetScope *child = sc->child(hname_t(get_name()));
if (child) {
cerr << get_fileline() << ": error: module <" << mod->mod_name()
<< "> instance and ";
child->print_type(cerr);
cerr << " in '" << sc->fullname()
<< "' have the same name '" << get_name() << "'." << endl;
des->errors += 1;
return;
}
// A module instance can not have the same name as a genvar.
if (sc->find_genvar(get_name())) {
cerr << get_fileline() << ": error: module <" << mod->mod_name()
<< "> instance and genvar in '" << sc->fullname()
<< "' have the same name '" << get_name() << "'." << endl;
des->errors += 1;
}
// A module instance can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = sc->get_parameter(des, get_name(), ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: module <" << mod->mod_name()
<< "> instance and parameter in '" << sc->fullname()
<< "' have the same name '" << get_name() << "'." << endl;
des->errors += 1;
}
// check for recursive instantiation by scanning the current
// scope and its parents. Look for a module instantiation of
// the same module, but farther up in the scope.
@ -1728,6 +1447,7 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
my_scope->set_line(get_file(), mod->get_file(),
get_lineno(), mod->get_lineno());
my_scope->set_module_name(mod->mod_name());
my_scope->add_imports(&mod->explicit_imports);
for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1)
my_scope->attribute(attrib_list[adx].key, attrib_list[adx].val);
@ -1809,36 +1529,8 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
* no hierarchy, but neither does the NetEvent, until it is stored in
* the NetScope object.
*/
void PEvent::elaborate_scope(Design*des, NetScope*scope) const
void PEvent::elaborate_scope(Design*, NetScope*scope) const
{
// A named event can not have the same name as another scope object.
const NetScope *child = scope->child(hname_t(name_));
if (child) {
cerr << get_fileline() << ": error: named event and ";
child->print_type(cerr);
cerr << " in '" << scope->fullname()
<< "' have the same name '" << name_ << "'." << endl;
des->errors += 1;
}
// A named event can not have the same name as a genvar.
if (scope->find_genvar(name_)) {
cerr << get_fileline() << ": error: named event and "
<< "genvar in '" << scope->fullname()
<< "' have the same name '" << name_ << "'." << endl;
des->errors += 1;
}
// A named event can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter(des, name_, ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: named event and "
<< "parameter in '" << scope->fullname()
<< "' have the same name '" << name_ << "'." << endl;
des->errors += 1;
}
NetEvent*ev = new NetEvent(name_);
ev->set_line(*this);
scope->add_event(ev);
@ -1909,37 +1601,6 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
if (pscope_name() != 0) {
hname_t use_name(pscope_name());
// A named block can not have the same name as another scope
// object.
const NetScope *child = scope->child(use_name);
if (child) {
cerr << get_fileline() << ": error: named block and ";
child->print_type(cerr);
cerr << " in '" << scope->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
return;
}
// A named block can not have the same name as a genvar.
if (scope->find_genvar(pscope_name())) {
cerr << get_fileline() << ": error: named block and "
"genvar in '" << scope->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
// A named block can not have the same name as a parameter.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter(des, pscope_name(),
ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: named block and "
"parameter in '" << scope->fullname()
<< "' have the same name '" << use_name << "'." << endl;
des->errors += 1;
}
if (debug_scopes)
cerr << get_fileline() << ": debug: "
<< "Elaborate block scope " << use_name
@ -1952,6 +1613,7 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
: NetScope::BEGIN_END);
my_scope->set_line(get_file(), get_lineno());
my_scope->is_auto(scope->is_auto());
my_scope->add_imports(&explicit_imports);
// Scan the parameters in the scope, and store the information
// needed to evaluate the parameter expressions.

View File

@ -942,44 +942,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
des->errors += error_cnt_;
// A signal can not have the same name as a scope object.
const NetScope *child = scope->child_byname(name_);
if (child) {
cerr << get_fileline() << ": error: signal and ";
child->print_type(cerr);
cerr << " in '" << scope->fullname()
<< "' have the same name '" << name_ << "'." << endl;
des->errors += 1;
}
// A signal can not have the same name as a genvar.
const LineInfo *genvar = scope->find_genvar(name_);
if (genvar) {
cerr << get_fileline() << ": error: signal and genvar in '"
<< scope->fullname() << "' have the same name '" << name_
<< "'." << endl;
des->errors += 1;
}
// A signal can not have the same name as a parameter. Note
// that we treat enumeration literals similar to parameters,
// so if the name matches an enumeration literal, it will be
// caught here.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter(des, name_, ex_msb, ex_lsb);
if (parm) {
cerr << get_fileline() << ": error: signal and parameter in '"
<< scope->fullname() << "' have the same name '" << name_
<< "'." << endl;
des->errors += 1;
}
// A signal can not have the same name as a named event.
const NetEvent *event = scope->find_event(name_);
if (event) {
cerr << get_fileline() << ": error: signal and named event in '"
<< scope->fullname() << "' have the same name '" << name_
<< "'." << endl;
des->errors += 1;
}
if (port_set_ || net_set_) {
if (warn_implicit_dimensions
@ -1214,7 +1176,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
} else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(set_data_type_)) {
list<named_pexpr_t>::const_iterator sample_name = enum_type->names->begin();
const netenum_t*use_enum = scope->find_enumeration_for_name(sample_name->name);
const netenum_t*use_enum = scope->find_enumeration_for_name(des, sample_name->name);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " << wtype

View File

@ -4322,7 +4322,13 @@ cerr << endl;
const NetExpr*par = 0;
NetEvent* eve = 0;
NetScope*found_in = symbol_search(this, des, scope,
NetScope*use_scope = scope;
if (id->package()) {
use_scope = des->find_package(id->package()->pscope_name());
ivl_assert(*this, use_scope);
}
NetScope*found_in = symbol_search(this, des, use_scope,
id->path(),
sig, par, eve);
@ -4368,8 +4374,9 @@ cerr << endl;
NetExpr*tmp = elab_and_eval(des, scope, expr_[idx]->expr(), -1);
if (tmp == 0) {
expr_[idx]->dump(cerr);
cerr << endl;
cerr << get_fileline() << ": error: "
"Failed to evaluate event expression '"
<< *expr_[idx] << "'." << endl;
des->errors += 1;
continue;
}
@ -5348,11 +5355,17 @@ NetProc* PTrigger::elaborate(Design*des, NetScope*scope) const
{
assert(scope);
NetScope*use_scope = scope;
if (package_) {
use_scope = des->find_package(package_->pscope_name());
ivl_assert(*this, use_scope);
}
NetNet* sig = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
NetScope*found_in = symbol_search(this, des, scope, event_,
NetScope*found_in = symbol_search(this, des, use_scope, event_,
sig, par, eve);
if (found_in == 0) {
@ -6609,6 +6622,7 @@ Design* elaborate(list<perm_string>roots)
PPackage*unit = pform_units[i];
NetScope*scope = des->make_package_scope(unit->pscope_name(), 0, true);
scope->set_line(unit);
scope->add_imports(&unit->explicit_imports);
set_scope_timescale(des, scope, unit);
elaborator_work_item_t*es = new elaborate_package_t(des, scope, unit);
@ -6633,6 +6647,7 @@ Design* elaborate(list<perm_string>roots)
NetScope*unit_scope = unit_scopes[pac->second->parent_scope()];
NetScope*scope = des->make_package_scope(pac->first, unit_scope, false);
scope->set_line(pac->second);
scope->add_imports(&pac->second->explicit_imports);
set_scope_timescale(des, scope, pac->second);
elaborator_work_item_t*es = new elaborate_package_t(des, scope, pac->second);
@ -6674,6 +6689,7 @@ Design* elaborate(list<perm_string>roots)
// Collect some basic properties of this scope from the
// Module definition.
scope->set_line(rmod);
scope->add_imports(&rmod->explicit_imports);
set_scope_timescale(des, scope, rmod);
// Save this scope, along with its definition, in the

View File

@ -4,7 +4,7 @@
%{
/*
* Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -362,7 +362,7 @@ TU [munpf]
/* If this identifier names a previously declared type, then
return this as a TYPE_IDENTIFIER instead. */
if (rc == IDENTIFIER && gn_system_verilog()) {
if (data_type_t*type = pform_test_type_identifier(yylval.text)) {
if (data_type_t*type = pform_test_type_identifier(yylloc, yylval.text)) {
yylval.type_identifier.text = yylval.text;
yylval.type_identifier.type = type;
rc = TYPE_IDENTIFIER;
@ -383,7 +383,7 @@ TU [munpf]
}
}
if (gn_system_verilog()) {
if (data_type_t*type = pform_test_type_identifier(yylval.text)) {
if (data_type_t*type = pform_test_type_identifier(yylloc, yylval.text)) {
yylval.type_identifier.text = yylval.text;
yylval.type_identifier.type = type;
return TYPE_IDENTIFIER;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -244,7 +244,13 @@ NetScope* Design::find_scope_(NetScope*scope, const std::list<hname_t>&path,
/* Up references may match module name */
} else {
scope = scope->child( key );
NetScope*found_scope = scope->child(key);
if (found_scope == 0) {
found_scope = scope->find_import(this, key.peek_name());
if (found_scope)
found_scope = found_scope->child(key);
}
scope = found_scope;
if (scope == 0) break;
}
tmp.pop_front();
@ -319,7 +325,13 @@ NetScope* Design::find_scope_(NetScope*scope, const hname_t&path,
/* Up references may match module name */
return scope;
}
return scope->child( path );
NetScope*found_scope = scope->child(path);
if (found_scope == 0) {
found_scope = scope->find_import(this, path.peek_name());
if (found_scope)
found_scope = found_scope->child(path);
}
return found_scope;
}
/*
@ -864,6 +876,11 @@ NetNet* Design::find_signal(NetScope*scope, pform_name_t path)
if (NetNet*net = scope->find_signal(key))
return net;
if (NetScope*import_scope = scope->find_import(this, key)) {
scope = import_scope;
continue;
}
if (scope->type() == NetScope::MODULE)
break;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2019 Stephen Williams (steve@icarus.com)
* Copyright (c) 2016 CERN Michele Castellana (michele.castellana@cern.ch)
*
* This source code is free software; you can redistribute it
@ -25,6 +25,7 @@
# include "netclass.h"
# include "netenum.h"
# include "netvector.h"
# include "PPackage.h"
# include <cstring>
# include <cstdlib>
# include <sstream>
@ -117,6 +118,7 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, NetScope*in_u
: type_(t), name_(n), nested_module_(nest), program_block_(program),
is_interface_(interface), is_unit_(compilation_unit), unit_(in_unit), up_(up)
{
imports_ = 0;
events_ = 0;
lcounter_ = 0;
is_auto_ = false;
@ -205,16 +207,38 @@ void NetScope::set_line(perm_string file, perm_string def_file,
def_lineno_ = def_lineno;
}
void NetScope::add_imports(const map<perm_string,PPackage*>*imports)
{
if (!imports->empty())
imports_ = imports;
}
NetScope*NetScope::find_import(const Design*des, perm_string name)
{
if (imports_ == 0)
return 0;
map<perm_string,PPackage*>::const_iterator cur = imports_->find(name);
if (cur != imports_->end()) {
return des->find_package(cur->second->pscope_name());
} else
return 0;
}
/*
* Look for the enumeration in the current scope and any parent scopes.
*/
const netenum_t*NetScope::find_enumeration_for_name(perm_string name)
const netenum_t*NetScope::find_enumeration_for_name(const Design*des, perm_string name)
{
NetScope *cur_scope = this;
while (cur_scope) {
NetEConstEnum*tmp = cur_scope->enum_names_[name];
if (tmp) break;
cur_scope = cur_scope->parent();
NetScope*import_scope = cur_scope->find_import(des, name);
if (import_scope)
cur_scope = import_scope;
else
cur_scope = cur_scope->parent();
if (cur_scope == 0)
cur_scope = unit_;
}

View File

@ -77,6 +77,7 @@ class NetEvWait;
class PClass;
class PExpr;
class PFunction;
class PPackage;
class PTaskFunc;
struct enum_type_t;
class netclass_t;
@ -942,9 +943,12 @@ class NetScope : public Definitions, public Attrib {
if a unique name couldn't be generated. */
bool auto_name(const char* prefix, char pad, const char* suffix);
void add_imports(const map<perm_string,PPackage*>*imports);
NetScope*find_import(const Design*des, perm_string name);
/* Routine to search for the enumeration given a name. It basically
* does what enumeration_for_name() does but searched the hierarchy. */
const netenum_t*find_enumeration_for_name(perm_string name);
const netenum_t*find_enumeration_for_name(const Design*des, perm_string name);
/* Parameters exist within a scope, and these methods allow
one to manipulate the set. In these cases, the name is the
@ -1269,6 +1273,8 @@ class NetScope : public Definitions, public Attrib {
signed char time_unit_, time_prec_;
bool time_from_timescale_;
const map<perm_string,PPackage*>*imports_;
NetEvent *events_;
map<perm_string,LineInfo*> genvars_;

86
parse.y
View File

@ -819,12 +819,14 @@ class_declaration_endlabel_opt
class_declaration_extends_opt /* IEEE1800-2005: A.1.2 */
: K_extends TYPE_IDENTIFIER
{ $$.type = $2.type;
{ pform_set_type_referenced(@2, $2.text);
$$.type = $2.type;
$$.exprs= 0;
delete[]$2.text;
}
| K_extends TYPE_IDENTIFIER '(' expression_list_with_nuls ')'
{ $$.type = $2.type;
{ pform_set_type_referenced(@2, $2.text);
$$.type = $2.type;
$$.exprs = $4;
delete[]$2.text;
}
@ -1056,6 +1058,9 @@ data_declaration /* IEEE1800-2005: A.2.1.3 */
}
pform_makewire(@2, 0, str_strength, $3, NetNet::IMPLICIT_REG, data_type);
}
| attribute_list_opt K_event event_variable_list ';'
{ if ($3) pform_make_events($3, @2.text, @2.first_line);
}
;
data_type /* IEEE1800-2005: A.2.2.1 */
@ -1103,7 +1108,8 @@ data_type /* IEEE1800-2005: A.2.2.1 */
$$ = tmp;
}
| TYPE_IDENTIFIER dimensions_opt
{ if ($2) {
{ pform_set_type_referenced(@1, $1.text);
if ($2) {
parray_type_t*tmp = new parray_type_t($1.type, $2);
FILE_NAME(tmp, @1);
$$ = tmp;
@ -1422,8 +1428,7 @@ loop_statement /* IEEE1800-2005: A.6.8 */
char for_block_name [64];
snprintf(for_block_name, sizeof for_block_name, "$ivl_for_loop%u", for_counter);
for_counter += 1;
PBlock*tmp = pform_push_block_scope(for_block_name, PBlock::BL_SEQ);
FILE_NAME(tmp, @1);
PBlock*tmp = pform_push_block_scope(@1, for_block_name, PBlock::BL_SEQ);
current_block_stack.push(tmp);
list<decl_assignment_t*>assign_list;
@ -1436,7 +1441,7 @@ loop_statement /* IEEE1800-2005: A.6.8 */
{ pform_name_t tmp_hident;
tmp_hident.push_back(name_component_t(lex_strings.make($4)));
PEIdent*tmp_ident = pform_new_ident(tmp_hident);
PEIdent*tmp_ident = pform_new_ident(@4, tmp_hident);
FILE_NAME(tmp_ident, @4);
PForStatement*tmp_for = new PForStatement(tmp_ident, $6, $8, $10, $13);
@ -1484,8 +1489,7 @@ loop_statement /* IEEE1800-2005: A.6.8 */
snprintf(for_block_name, sizeof for_block_name, "$ivl_foreach%u", foreach_counter);
foreach_counter += 1;
PBlock*tmp = pform_push_block_scope(for_block_name, PBlock::BL_SEQ);
FILE_NAME(tmp, @1);
PBlock*tmp = pform_push_block_scope(@1, for_block_name, PBlock::BL_SEQ);
current_block_stack.push(tmp);
pform_make_foreach_declarations(@1, $5);
@ -1989,7 +1993,8 @@ simple_type_or_string /* IEEE1800-2005: A.2.2.1 */
$$ = tmp;
}
| TYPE_IDENTIFIER
{ $$ = $1.type;
{ pform_set_type_referenced(@1, $1.text);
$$ = $1.type;
delete[]$1.text;
}
| PACKAGE_IDENTIFIER K_SCOPE_RES
@ -2547,6 +2552,10 @@ block_item_decl
| type_declaration
/* Blocks can have imports. */
| package_import_declaration
/* Recover from errors that happen within variable lists. Use the
trailing semi-colon to resync the parser. */
@ -3176,7 +3185,8 @@ clocking_event_opt /* */
event_control /* A.K.A. clocking_event */
: '@' hierarchy_identifier
{ PEIdent*tmpi = new PEIdent(*$2);
{ PEIdent*tmpi = pform_new_ident(@2, *$2);
FILE_NAME(tmpi, @2);
PEEvent*tmpe = new PEEvent(PEEvent::ANYEDGE, tmpi);
PEventStatement*tmps = new PEventStatement(tmpe);
FILE_NAME(tmps, @1);
@ -3559,7 +3569,8 @@ expr_primary_or_typename
/* There are a few special cases (notably $bits argument) where the
expression may be a type name. Let the elaborator sort this out. */
| TYPE_IDENTIFIER
{ PETypename*tmp = new PETypename($1.type);
{ pform_set_type_referenced(@1, $1.text);
PETypename*tmp = new PETypename($1.type);
FILE_NAME(tmp,@1);
$$ = tmp;
delete[]$1.text;
@ -3612,7 +3623,7 @@ expr_primary
indexed arrays and part selects */
| hierarchy_identifier
{ PEIdent*tmp = pform_new_ident(*$1);
{ PEIdent*tmp = pform_new_ident(@1, *$1);
FILE_NAME(tmp, @1);
$$ = tmp;
delete $1;
@ -4508,7 +4519,7 @@ atom2_type
rule to reflect the rules for assignment l-values. */
lpvalue
: hierarchy_identifier
{ PEIdent*tmp = pform_new_ident(*$1);
{ PEIdent*tmp = pform_new_ident(@1, *$1);
FILE_NAME(tmp, @1);
$$ = tmp;
delete $1;
@ -5048,29 +5059,27 @@ module_item
IDENTIFIER '=' expression ')'
{ pform_start_generate_for(@1, $3, $5, $7, $9, $11); }
generate_block
{ pform_endgenerate(); }
{ pform_endgenerate(false); }
| generate_if
generate_block_opt
K_else
{ pform_start_generate_else(@1); }
generate_block
{ pform_endgenerate(); }
{ pform_endgenerate(true); }
| generate_if
generate_block_opt %prec less_than_K_else
{ pform_endgenerate(); }
{ pform_endgenerate(true); }
| K_case '(' expression ')'
{ pform_start_generate_case(@1, $3); }
generate_case_items
K_endcase
{ pform_endgenerate(); }
{ pform_endgenerate(true); }
| modport_declaration
| package_import_declaration
/* 1364-2001 and later allow specparam declarations outside specify blocks. */
| attribute_list_opt K_specparam
@ -5162,9 +5171,9 @@ generate_case_items
generate_case_item
: expression_list_proper ':' { pform_generate_case_item(@1, $1); } generate_block_opt
{ pform_endgenerate(); }
{ pform_endgenerate(false); }
| K_default ':' { pform_generate_case_item(@1, 0); } generate_block_opt
{ pform_endgenerate(); }
{ pform_endgenerate(false); }
;
generate_item
@ -5185,7 +5194,7 @@ generate_item
warn_count += 1;
cerr << @1 << ": warning: Anachronistic use of named begin/end to surround generate schemes." << endl;
}
pform_endgenerate();
pform_endgenerate(false);
}
;
@ -5318,7 +5327,8 @@ param_type
param_active_type = IVL_VT_BOOL;
}
| TYPE_IDENTIFIER
{ pform_set_param_from_type(@1, $1.type, $1.text, param_active_range,
{ pform_set_type_referenced(@1, $1.text);
pform_set_param_from_type(@1, $1.type, $1.text, param_active_range,
param_active_signed, param_active_type);
delete[]$1.text;
}
@ -6260,8 +6270,7 @@ statement_item /* This is roughly statement_item in the LRM */
}
/* In SystemVerilog an unnamed block can contain variable declarations. */
| K_begin
{ PBlock*tmp = pform_push_block_scope(0, PBlock::BL_SEQ);
FILE_NAME(tmp, @1);
{ PBlock*tmp = pform_push_block_scope(@1, 0, PBlock::BL_SEQ);
current_block_stack.push(tmp);
}
block_item_decls_opt
@ -6295,8 +6304,7 @@ statement_item /* This is roughly statement_item in the LRM */
$$ = tmp;
}
| K_begin ':' IDENTIFIER
{ PBlock*tmp = pform_push_block_scope($3, PBlock::BL_SEQ);
FILE_NAME(tmp, @1);
{ PBlock*tmp = pform_push_block_scope(@1, $3, PBlock::BL_SEQ);
current_block_stack.push(tmp);
}
block_item_decls_opt
@ -6333,8 +6341,7 @@ statement_item /* This is roughly statement_item in the LRM */
}
/* In SystemVerilog an unnamed block can contain variable declarations. */
| K_fork
{ PBlock*tmp = pform_push_block_scope(0, PBlock::BL_PAR);
FILE_NAME(tmp, @1);
{ PBlock*tmp = pform_push_block_scope(@1, 0, PBlock::BL_PAR);
current_block_stack.push(tmp);
}
block_item_decls_opt
@ -6369,8 +6376,7 @@ statement_item /* This is roughly statement_item in the LRM */
$$ = tmp;
}
| K_fork ':' IDENTIFIER
{ PBlock*tmp = pform_push_block_scope($3, PBlock::BL_PAR);
FILE_NAME(tmp, @1);
{ PBlock*tmp = pform_push_block_scope(@1, $3, PBlock::BL_PAR);
current_block_stack.push(tmp);
}
block_item_decls_opt
@ -6408,12 +6414,18 @@ statement_item /* This is roughly statement_item in the LRM */
FILE_NAME(tmp, @1);
$$ = tmp;
}
| K_TRIGGER hierarchy_identifier ';'
{ PTrigger*tmp = new PTrigger(*$2);
FILE_NAME(tmp, @1);
delete $2;
$$ = tmp;
}
| K_TRIGGER hierarchy_identifier ';'
{ PTrigger*tmp = pform_new_trigger(@2, 0, *$2);
FILE_NAME(tmp, @1);
delete $2;
$$ = tmp;
}
| K_TRIGGER PACKAGE_IDENTIFIER K_SCOPE_RES hierarchy_identifier
{ PTrigger*tmp = pform_new_trigger(@4, $2, *$4);
FILE_NAME(tmp, @1);
delete $4;
$$ = tmp;
}
| procedural_assertion_statement { $$ = $1; }

View File

@ -1,7 +1,7 @@
#ifndef IVL_parse_misc_H
#define IVL_parse_misc_H
/*
* Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -88,7 +88,7 @@ extern void lex_in_package_scope(PPackage*pkg);
* parser detects typedefs and marks the typedef'ed identifiers as
* type names.
*/
extern data_type_t* pform_test_type_identifier(const char*txt);
extern data_type_t* pform_test_type_identifier(const YYLTYPE&loc, const char*txt);
extern data_type_t* pform_test_type_identifier(PPackage*pkg, const char*txt);
extern bool pform_test_type_identifier_local(perm_string txt);

575
pform.cc
View File

@ -349,6 +349,13 @@ static unsigned scope_generate_counter = 1;
always within a module. */
static PGenerate*pform_cur_generate = 0;
/* Blocks within the same conditional generate construct may have
the same name. Here we collect the set of names used in each
construct, so they can be added to the local scope without
conflicting with each other. Generate constructs may nest, so
we need a stack. */
static list<set<perm_string>> conditional_block_names;
/* This tracks the current modport list being processed. This is
always within an interface. */
static PModport*pform_cur_modport = 0;
@ -400,8 +407,17 @@ LexicalScope* pform_peek_scope(void)
void pform_pop_scope()
{
assert(lexical_scope);
lexical_scope = lexical_scope->parent_scope();
LexicalScope*scope = lexical_scope;
assert(scope);
map<perm_string,PPackage*>::const_iterator cur;
for (cur = scope->possible_imports.begin(); cur != scope->possible_imports.end(); ++cur) {
if (scope->local_symbols.find(cur->first) == scope->local_symbols.end())
scope->explicit_imports[cur->first] = cur->second;
}
scope->possible_imports.clear();
lexical_scope = scope->parent_scope();
assert(lexical_scope);
}
@ -423,6 +439,89 @@ static PScopeExtra* find_nearest_scopex(LexicalScope*scope)
return scopex;
}
static void add_local_symbol(LexicalScope*scope, perm_string name, PNamedItem*item)
{
assert(scope);
// Check for conflict with another local symbol.
map<perm_string,PNamedItem*>::const_iterator cur_sym
= scope->local_symbols.find(name);
if (cur_sym != scope->local_symbols.end()) {
cerr << item->get_fileline() << ": error: "
"'" << name << "' has already been declared "
"in this scope." << endl;
cerr << cur_sym->second->get_fileline() << ": : "
"It was declared here as "
<< cur_sym->second->symbol_type() << "." << endl;
error_count += 1;
return;
}
// Check for conflict with an explicit import.
map<perm_string,PPackage*>::const_iterator cur_pkg
= scope->explicit_imports.find(name);
if (cur_pkg != scope->explicit_imports.end()) {
cerr << item->get_fileline() << ": error: "
"'" << name << "' has already been "
"imported into this scope from package '"
<< cur_pkg->second->pscope_name() << "'." << endl;
error_count += 1;
return;
}
scope->local_symbols[name] = item;
}
static PPackage*find_potential_import(const struct vlltype&loc, LexicalScope*scope,
perm_string name, bool tf_call, bool make_explicit)
{
assert(scope);
PPackage*found_pkg = 0;
for (set<PPackage*>::const_iterator cur_pkg = scope->potential_imports.begin();
cur_pkg != scope->potential_imports.end(); ++cur_pkg) {
PPackage*search_pkg = *cur_pkg;
map<perm_string,PNamedItem*>::const_iterator cur_sym
= search_pkg->local_symbols.find(name);
if (cur_sym != search_pkg->local_symbols.end()) {
if (found_pkg && make_explicit) {
cerr << loc.get_fileline() << ": error: "
"Ambiguous use of '" << name << "'. "
"It is exported by both '"
<< found_pkg->pscope_name()
<< "' and by '"
<< search_pkg->pscope_name()
<< "'." << endl;
error_count += 1;
} else {
found_pkg = search_pkg;
if (make_explicit) {
if (tf_call)
scope->possible_imports[name] = found_pkg;
else
scope->explicit_imports[name] = found_pkg;
}
}
}
}
return found_pkg;
}
static void check_potential_imports(const struct vlltype&loc, perm_string name, bool tf_call)
{
LexicalScope*scope = lexical_scope;
while (scope) {
if (scope->local_symbols.find(name) != scope->local_symbols.end())
return;
if (scope->explicit_imports.find(name) != scope->explicit_imports.end())
return;
if (find_potential_import(loc, scope, name, tf_call, true))
return;
scope = scope->parent_scope();
}
}
/*
* Set the local time unit/precision. This version is used for setting
* the time scale for design elements (modules, packages, etc.) and is
@ -516,12 +615,6 @@ PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name,
pform_set_scope_timescale(class_scope, scopex);
if (scopex->classes.find(name) != scopex->classes.end()) {
cerr << class_scope->get_fileline() << ": error: duplicate "
"definition for class '" << name << "' in '"
<< scopex->pscope_name() << "'." << endl;
error_count += 1;
}
scopex->classes[name] = class_scope;
scopex->classes_lexical .push_back(class_scope);
@ -566,25 +659,11 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name,
pform_set_scope_timescale(task, scopex);
if (pform_cur_generate) {
// Check if the task is already in the dictionary.
if (pform_cur_generate->tasks.find(task->pscope_name()) !=
pform_cur_generate->tasks.end()) {
cerr << task->get_fileline() << ": error: duplicate "
"definition for task '" << name << "' in '"
<< pform_cur_module.front()->mod_name() << "' (generate)."
<< endl;
error_count += 1;
}
pform_cur_generate->tasks[task->pscope_name()] = task;
add_local_symbol(pform_cur_generate, task_name, task);
pform_cur_generate->tasks[task_name] = task;
} else {
// Check if the task is already in the dictionary.
if (scopex->tasks.find(task->pscope_name()) != scopex->tasks.end()) {
cerr << task->get_fileline() << ": error: duplicate "
"definition for task '" << name << "' in '"
<< scopex->pscope_name() << "'." << endl;
error_count += 1;
}
scopex->tasks[task->pscope_name()] = task;
add_local_symbol(scopex, task_name, task);
scopex->tasks[task_name] = task;
}
lexical_scope = task;
@ -615,26 +694,12 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name,
pform_set_scope_timescale(func, scopex);
if (pform_cur_generate) {
// Check if the function is already in the dictionary.
if (pform_cur_generate->funcs.find(func->pscope_name()) !=
pform_cur_generate->funcs.end()) {
cerr << func->get_fileline() << ": error: duplicate "
"definition for function '" << name << "' in '"
<< pform_cur_module.front()->mod_name() << "' (generate)."
<< endl;
error_count += 1;
}
pform_cur_generate->funcs[func->pscope_name()] = func;
add_local_symbol(pform_cur_generate, func_name, func);
pform_cur_generate->funcs[func_name] = func;
} else {
// Check if the function is already in the dictionary.
if (scopex->funcs.find(func->pscope_name()) != scopex->funcs.end()) {
cerr << func->get_fileline() << ": error: duplicate "
"definition for function '" << name << "' in '"
<< scopex->pscope_name() << "'." << endl;
error_count += 1;
}
scopex->funcs[func->pscope_name()] = func;
add_local_symbol(scopex, func_name, func);
scopex->funcs[func_name] = func;
}
lexical_scope = func;
@ -642,7 +707,8 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name,
return func;
}
PBlock* pform_push_block_scope(char*name, PBlock::BL_TYPE bt)
PBlock* pform_push_block_scope(const struct vlltype&loc, char*name,
PBlock::BL_TYPE bt)
{
perm_string block_name;
if (name) block_name = lex_strings.make(name);
@ -656,26 +722,34 @@ PBlock* pform_push_block_scope(char*name, PBlock::BL_TYPE bt)
}
PBlock*block = new PBlock(block_name, lexical_scope, bt);
FILE_NAME(block, loc);
block->default_lifetime = find_lifetime(LexicalScope::INHERITED);
if (name) add_local_symbol(lexical_scope, block_name, block);
lexical_scope = block;
return block;
}
/*
* Create a new identifier. Check if this is an imported name.
* Create a new identifier.
*/
PEIdent* pform_new_ident(const pform_name_t&name)
PEIdent* pform_new_ident(const struct vlltype&loc, const pform_name_t&name)
{
LexicalScope*scope = pform_peek_scope();
map<perm_string,PPackage*>::const_iterator pkg = scope->imports.find(name.front().name);
if (pkg == scope->imports.end())
return new PEIdent(name);
if (gn_system_verilog())
check_potential_imports(loc, name.front().name, false);
// XXXX For now, do not support indexed imported names.
assert(name.back().index.size() == 0);
return new PEIdent(name);
}
return new PEIdent(pkg->second, name);
PTrigger* pform_new_trigger(const struct vlltype&loc, PPackage*pkg,
const pform_name_t&name)
{
if (gn_system_verilog())
check_potential_imports(loc, name.front().name, false);
PTrigger*tmp = new PTrigger(pkg, name);
FILE_NAME(tmp, loc);
return tmp;
}
PGenerate* pform_parent_generate(void)
@ -729,15 +803,33 @@ PWire*pform_get_wire_in_scope(perm_string name)
static void pform_put_wire_in_scope(perm_string name, PWire*net)
{
add_local_symbol(lexical_scope, name, net);
lexical_scope->wires[name] = net;
}
static void pform_put_enum_type_in_scope(enum_type_t*enum_set)
{
if (lexical_scope->enum_sets.count(enum_set))
return;
set<perm_string> enum_names;
list<named_pexpr_t>::const_iterator cur;
for (cur = enum_set->names->begin(); cur != enum_set->names->end(); ++cur) {
if (enum_names.count(cur->name)) {
cerr << enum_set->get_fileline() << ": error: "
"Duplicate enumeration name '"
<< cur->name << "'." << endl;
error_count += 1;
} else {
add_local_symbol(lexical_scope, cur->name, enum_set);
enum_names.insert(cur->name);
}
}
lexical_scope->enum_sets.insert(enum_set);
}
PWire*pform_get_make_wire_in_scope(const struct vlltype&li, perm_string name,
PWire*pform_get_make_wire_in_scope(const struct vlltype&, perm_string name,
NetNet::Type net_type, NetNet::PortType port_type,
ivl_variable_type_t vt_type)
{
@ -745,15 +837,11 @@ PWire*pform_get_make_wire_in_scope(const struct vlltype&li, perm_string name,
// If the wire already exists and is fully defined, this
// must be a redeclaration. Start again with a new wire.
if (cur && cur->get_data_type() != IVL_VT_NO_TYPE) {
LineInfo tloc;
FILE_NAME(&tloc, li);
cerr << tloc.get_fileline() << ": error: duplicate declaration "
"for net or variable '" << name << "'." << endl;
error_count += 1;
delete cur;
// The error will be reported when we add the new wire
// to the scope. Do not delete the old wire - it will
// remain in the local symbol map.
if (cur && cur->get_data_type() != IVL_VT_NO_TYPE)
cur = 0;
}
if (cur == 0) {
cur = new PWire(name, net_type, port_type, vt_type);
@ -773,17 +861,24 @@ void pform_set_typedef(perm_string name, data_type_t*data_type, std::list<pform_
if(unp_ranges)
data_type = new uarray_type_t(data_type, unp_ranges);
add_local_symbol(lexical_scope, name, data_type);
data_type_t*&ref = lexical_scope->typedefs[name];
ivl_assert(*data_type, ref == 0);
ref = data_type;
if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(data_type)) {
if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(data_type))
pform_put_enum_type_in_scope(enum_type);
}
}
data_type_t* pform_test_type_identifier(const char*txt)
void pform_set_type_referenced(const struct vlltype&loc, const char*name)
{
perm_string lex_name = lex_strings.make(name);
check_potential_imports(loc, lex_name, false);
}
data_type_t* pform_test_type_identifier(const struct vlltype&loc, const char*txt)
{
perm_string name = lex_strings.make(txt);
@ -798,8 +893,8 @@ data_type_t* pform_test_type_identifier(const char*txt)
// the name has at least shadowed any other possible
// meaning for this name.
map<perm_string,PPackage*>::iterator cur_pkg;
cur_pkg = cur_scope->imports.find(name);
if (cur_pkg != cur_scope->imports.end()) {
cur_pkg = cur_scope->explicit_imports.find(name);
if (cur_pkg != cur_scope->explicit_imports.end()) {
PPackage*pkg = cur_pkg->second;
cur = pkg->typedefs.find(name);
if (cur != pkg->typedefs.end())
@ -813,6 +908,16 @@ data_type_t* pform_test_type_identifier(const char*txt)
if (cur != cur_scope->typedefs.end())
return cur->second;
PPackage*pkg = find_potential_import(loc, cur_scope, name, false, false);
if (pkg) {
cur = pkg->typedefs.find(name);
if (cur != cur_scope->typedefs.end())
return cur->second;
// Not a type. Give up.
return 0;
}
cur_scope = cur_scope->parent_scope();
} while (cur_scope);
@ -841,29 +946,10 @@ PECallFunction* pform_make_call_function(const struct vlltype&loc,
const pform_name_t&name,
const list<PExpr*>&parms)
{
PECallFunction*tmp = 0;
// First try to get the function name from a package. Check
// the imports, and if the name is there, make the function as
// a package member.
do {
if (name.size() != 1)
break;
perm_string use_name = peek_tail_name(name);
map<perm_string,PPackage*>::iterator cur_pkg;
cur_pkg = lexical_scope->imports.find(use_name);
if (cur_pkg == lexical_scope->imports.end())
break;
tmp = new PECallFunction(cur_pkg->second, use_name, parms);
} while(0);
if (tmp == 0) {
tmp = new PECallFunction(name, parms);
}
if (gn_system_verilog())
check_potential_imports(loc, name.front().name, true);
PECallFunction*tmp = new PECallFunction(name, parms);
FILE_NAME(tmp, loc);
return tmp;
}
@ -872,26 +958,10 @@ PCallTask* pform_make_call_task(const struct vlltype&loc,
const pform_name_t&name,
const list<PExpr*>&parms)
{
PCallTask*tmp = 0;
do {
if (name.size() != 1)
break;
perm_string use_name = peek_tail_name(name);
map<perm_string,PPackage*>::iterator cur_pkg;
cur_pkg = lexical_scope->imports.find(use_name);
if (cur_pkg == lexical_scope->imports.end())
break;
tmp = new PCallTask(cur_pkg->second, name, parms);
} while (0);
if (tmp == 0) {
tmp = new PCallTask(name, parms);
}
if (gn_system_verilog())
check_potential_imports(loc, name.front().name, true);
PCallTask*tmp = new PCallTask(name, parms);
FILE_NAME(tmp, loc);
return tmp;
}
@ -1273,6 +1343,8 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
allow_timeunit_decl = true;
allow_timeprec_decl = true;
add_local_symbol(lexical_scope, lex_name, cur_module);
lexical_scope = cur_module;
/* The generate scheme numbering starts with *1*, not
@ -1356,31 +1428,20 @@ void pform_endmodule(const char*name, bool inside_celldefine,
pform_pop_scope();
}
static void pform_add_genvar(const struct vlltype&li, const perm_string&name,
map<perm_string,LineInfo*>&genvars)
{
LineInfo*lni = new LineInfo();
FILE_NAME(lni, li);
if (genvars.find(name) != genvars.end()) {
cerr << lni->get_fileline() << ": error: genvar '"
<< name << "' has already been declared." << endl;
cerr << genvars[name]->get_fileline()
<< ": the previous declaration is here." << endl;
error_count += 1;
delete lni;
} else {
genvars[name] = lni;
}
}
void pform_genvars(const struct vlltype&li, list<perm_string>*names)
{
list<perm_string>::const_iterator cur;
for (cur = names->begin(); cur != names->end() ; *cur++) {
if (pform_cur_generate)
pform_add_genvar(li, *cur, pform_cur_generate->genvars);
else
pform_add_genvar(li, *cur, pform_cur_module.front()->genvars);
PGenvar*genvar = new PGenvar();
FILE_NAME(genvar, li);
if (pform_cur_generate) {
add_local_symbol(pform_cur_generate, *cur, genvar);
pform_cur_generate->genvars[*cur] = genvar;
} else {
add_local_symbol(pform_cur_module.front(), *cur, genvar);
pform_cur_module.front()->genvars[*cur] = genvar;
}
}
delete names;
@ -1423,6 +1484,8 @@ void pform_start_generate_if(const struct vlltype&li, PExpr*test)
pform_cur_generate->loop_init = 0;
pform_cur_generate->loop_test = test;
pform_cur_generate->loop_step = 0;
conditional_block_names.push_front(set<perm_string>());
}
void pform_start_generate_else(const struct vlltype&li)
@ -1431,7 +1494,7 @@ void pform_start_generate_else(const struct vlltype&li)
assert(pform_cur_generate->scheme_type == PGenerate::GS_CONDIT);
PGenerate*cur = pform_cur_generate;
pform_endgenerate();
pform_endgenerate(false);
PGenerate*gen = new PGenerate(lexical_scope, scope_generate_counter++);
lexical_scope = gen;
@ -1465,6 +1528,8 @@ void pform_start_generate_case(const struct vlltype&li, PExpr*expr)
pform_cur_generate->loop_init = 0;
pform_cur_generate->loop_test = expr;
pform_cur_generate->loop_step = 0;
conditional_block_names.push_front(set<perm_string>());
}
/*
@ -1487,6 +1552,10 @@ void pform_start_generate_nblock(const struct vlltype&li, char*name)
pform_cur_generate->scope_name = lex_strings.make(name);
delete[]name;
add_local_symbol(pform_cur_generate->parent_scope(),
pform_cur_generate->scope_name,
pform_cur_generate);
}
/*
@ -1528,14 +1597,36 @@ void pform_generate_block_name(char*name)
{
assert(pform_cur_generate != 0);
assert(pform_cur_generate->scope_name == 0);
pform_cur_generate->scope_name = lex_strings.make(name);
perm_string scope_name = lex_strings.make(name);
pform_cur_generate->scope_name = scope_name;
if (pform_cur_generate->scheme_type == PGenerate::GS_CONDIT
|| pform_cur_generate->scheme_type == PGenerate::GS_ELSE
|| pform_cur_generate->scheme_type == PGenerate::GS_CASE_ITEM) {
if (conditional_block_names.front().count(scope_name))
return;
conditional_block_names.front().insert(scope_name);
}
LexicalScope*parent_scope = pform_cur_generate->parent_scope();
assert(parent_scope);
if (pform_cur_generate->scheme_type == PGenerate::GS_CASE_ITEM)
// Skip over the PGenerate::GS_CASE container.
parent_scope = parent_scope->parent_scope();
add_local_symbol(parent_scope, scope_name, pform_cur_generate);
}
void pform_endgenerate()
void pform_endgenerate(bool end_conditional)
{
assert(pform_cur_generate != 0);
assert(! pform_cur_module.empty());
if (end_conditional)
conditional_block_names.pop_front();
// If there is no explicit block name then generate a temporary
// name. This will be replaced by the correct name later, once
// we know all the explicit names in the surrounding scope. If
@ -2024,18 +2115,10 @@ static void pform_set_net_range(list<perm_string>*names,
*/
static void pform_make_event(perm_string name, const char*fn, unsigned ln)
{
// Check if the named event is already in the dictionary.
if (lexical_scope->events.find(name) != lexical_scope->events.end()) {
LineInfo tloc;
FILE_NAME(&tloc, fn, ln);
cerr << tloc.get_fileline() << ": error: duplicate definition "
"for named event '" << name << "' in '"
<< pform_cur_module.front()->mod_name() << "'." << endl;
error_count += 1;
}
PEvent*event = new PEvent(name);
FILE_NAME(event, fn, ln);
add_local_symbol(lexical_scope, name, event);
lexical_scope->events[name] = event;
}
@ -2089,10 +2172,13 @@ static void pform_makegate(PGBuiltin::Type type,
cur->strength1(str.str1);
FILE_NAME(cur, info.file, info.lineno);
if (pform_cur_generate)
if (pform_cur_generate) {
if (dev_name != "") add_local_symbol(pform_cur_generate, dev_name, cur);
pform_cur_generate->add_gate(cur);
else
} else {
if (dev_name != "") add_local_symbol(pform_cur_module.front(), dev_name, cur);
pform_cur_module.front()->add_gate(cur);
}
}
void pform_makegates(const struct vlltype&loc,
@ -2169,10 +2255,13 @@ static void pform_make_modgate(perm_string type,
cur->set_parameters(overrides->by_order);
}
if (pform_cur_generate)
if (pform_cur_generate) {
if (name != "") add_local_symbol(pform_cur_generate, name, cur);
pform_cur_generate->add_gate(cur);
else
} else {
if (name != "") add_local_symbol(pform_cur_module.front(), name, cur);
pform_cur_module.front()->add_gate(cur);
}
pform_bind_attributes(cur->attributes, attr);
}
@ -2214,11 +2303,13 @@ static void pform_make_modgate(perm_string type,
cur->set_parameters(overrides->by_order);
}
if (pform_cur_generate)
if (pform_cur_generate) {
add_local_symbol(pform_cur_generate, name, cur);
pform_cur_generate->add_gate(cur);
else
} else {
add_local_symbol(pform_cur_module.front(), name, cur);
pform_cur_module.front()->add_gate(cur);
}
pform_bind_attributes(cur->attributes, attr);
}
@ -2554,20 +2645,15 @@ static PWire* pform_get_or_make_wire(const vlltype&li, perm_string name,
// If the wire already exists and is fully defined, this
// must be a redeclaration. Start again with a new wire.
if (cur) {
LineInfo tloc;
FILE_NAME(&tloc, li);
cerr << tloc.get_fileline() << ": error: duplicate declaration "
"for net or variable '" << name << "' in '"
<< pform_cur_module.front()->mod_name() << "'." << endl;
error_count += 1;
delete cur;
}
// The error will be reported when we add the new wire
// to the scope. Do not delete the old wire - it will
// remain in the local symbol map.
cur = new PWire(name, type, ptype, dtype);
FILE_NAME(cur, li.text, li.first_line);
pform_put_wire_in_scope(name, cur);
return cur;
}
@ -3021,63 +3107,33 @@ void pform_set_parameter(const struct vlltype&loc,
VLerror("parameter declarations are not permitted in generate blocks");
return;
}
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
assert(scopex);
// Check if the parameter name is already in the dictionary.
if (scope->parameters.find(name) != scope->parameters.end()) {
LineInfo tloc;
FILE_NAME(&tloc, loc);
cerr << tloc.get_fileline() << ": error: duplicate definition "
"for parameter '" << name << "' in '"
<< scopex->pscope_name() << "'." << endl;
error_count += 1;
}
if (scope->localparams.find(name) != scope->localparams.end()) {
LineInfo tloc;
FILE_NAME(&tloc, loc);
cerr << tloc.get_fileline() << ": error: localparam and "
<< "parameter in '" << scopex->pscope_name()
<< "' have the same name '" << name << "'." << endl;
error_count += 1;
}
// Only a Module scope has specparams.
if ((dynamic_cast<Module*> (scope)) &&
(scope == pform_cur_module.front()) &&
(pform_cur_module.front()->specparams.find(name) !=
pform_cur_module.front()->specparams.end())) {
LineInfo tloc;
FILE_NAME(&tloc, loc);
cerr << tloc.get_fileline() << ": error: specparam and "
"parameter in '" << scopex->pscope_name()
<< "' have the same name '" << name << "'." << endl;
error_count += 1;
}
assert(expr);
Module::param_expr_t&parm = scope->parameters[name];
FILE_NAME(&parm, loc);
Module::param_expr_t*parm = new Module::param_expr_t();
FILE_NAME(parm, loc);
parm.expr = expr;
add_local_symbol(scope, name, parm);
scope->parameters[name] = parm;
parm.type = type;
parm->expr = expr;
parm->type = type;
if (range) {
assert(range->size() == 1);
pform_range_t&rng = range->front();
assert(rng.first);
assert(rng.second);
parm.msb = rng.first;
parm.lsb = rng.second;
parm->msb = rng.first;
parm->lsb = rng.second;
} else {
parm.msb = 0;
parm.lsb = 0;
parm->msb = 0;
parm->lsb = 0;
}
parm.signed_flag = signed_flag;
parm.range = value_range;
parm->signed_flag = signed_flag;
parm->range = value_range;
// Only a Module keeps the position of the parameter.
if ((dynamic_cast<Module*> (scope)) &&
(scope == pform_cur_module.front()))
if ((dynamic_cast<Module*>(scope)) && (scope == pform_cur_module.front()))
pform_cur_module.front()->param_names.push_back(name);
}
@ -3090,58 +3146,30 @@ void pform_set_localparam(const struct vlltype&loc,
VLerror(loc, "error: localparam declarations must be contained within a module.");
return;
}
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
assert(scopex);
// Check if the localparam name is already in the dictionary.
if (scope->localparams.find(name) != scope->localparams.end()) {
LineInfo tloc;
FILE_NAME(&tloc, loc);
cerr << tloc.get_fileline() << ": error: duplicate definition "
"for localparam '" << name << "' in '"
<< scopex->pscope_name() << "'." << endl;
error_count += 1;
}
if (scope->parameters.find(name) != scope->parameters.end()) {
LineInfo tloc;
FILE_NAME(&tloc, loc);
cerr << tloc.get_fileline() << ": error: parameter and "
<< "localparam in '" << scopex->pscope_name()
<< "' have the same name '" << name << "'." << endl;
error_count += 1;
}
if ((! pform_cur_module.empty()) &&
(scope == pform_cur_module.front()) &&
(pform_cur_module.front()->specparams.find(name) != pform_cur_module.front()->specparams.end())) {
LineInfo tloc;
FILE_NAME(&tloc, loc);
cerr << tloc.get_fileline() << ": error: specparam and "
"localparam in '" << scopex->pscope_name()
<< "' have the same name '" << name << "'." << endl;
error_count += 1;
}
assert(expr);
Module::param_expr_t&parm = scope->localparams[name];
FILE_NAME(&parm, loc);
Module::param_expr_t*parm = new Module::param_expr_t();
FILE_NAME(parm, loc);
parm.expr = expr;
add_local_symbol(scope, name, parm);
scope->localparams[name] = parm;
parm.type = type;
parm->expr = expr;
parm->type = type;
if (range) {
assert(range->size() == 1);
pform_range_t&rng = range->front();
assert(rng.first);
assert(rng.second);
parm.msb = rng.first;
parm.lsb = rng.second;
parm->msb = rng.first;
parm->lsb = rng.second;
} else {
parm.msb = 0;
parm.lsb = 0;
parm->msb = 0;
parm->lsb = 0;
}
parm.signed_flag = signed_flag;
parm.range = 0;
parm->signed_flag = signed_flag;
parm->range = 0;
}
void pform_set_specparam(const struct vlltype&loc, perm_string name,
@ -3151,55 +3179,30 @@ void pform_set_specparam(const struct vlltype&loc, perm_string name,
Module*scope = pform_cur_module.front();
assert(scope == lexical_scope);
// Check if the specparam name is already in the dictionary.
if (pform_cur_module.front()->specparams.find(name) !=
pform_cur_module.front()->specparams.end()) {
LineInfo tloc;
FILE_NAME(&tloc, loc);
cerr << tloc.get_fileline() << ": error: duplicate definition "
"for specparam '" << name << "' in '"
<< pform_cur_module.front()->mod_name() << "'." << endl;
error_count += 1;
}
if (scope->parameters.find(name) != scope->parameters.end()) {
LineInfo tloc;
FILE_NAME(&tloc, loc);
cerr << tloc.get_fileline() << ": error: parameter and "
"specparam in '" << pform_cur_module.front()->mod_name()
<< "' have the same name '" << name << "'." << endl;
error_count += 1;
}
if (scope->localparams.find(name) != scope->localparams.end()) {
LineInfo tloc;
FILE_NAME(&tloc, loc);
cerr << tloc.get_fileline() << ": error: localparam and "
"specparam in '" << pform_cur_module.front()->mod_name()
<< "' have the same name '" << name << "'." << endl;
error_count += 1;
}
assert(expr);
Module::param_expr_t*parm = new Module::param_expr_t();
FILE_NAME(parm, loc);
Module::param_expr_t&parm = pform_cur_module.front()->specparams[name];
FILE_NAME(&parm, loc);
add_local_symbol(scope, name, parm);
pform_cur_module.front()->specparams[name] = parm;
parm.expr = expr;
parm->expr = expr;
if (range) {
assert(range->size() == 1);
pform_range_t&rng = range->front();
assert(rng.first);
assert(rng.second);
parm.type = IVL_VT_LOGIC;
parm.msb = rng.first;
parm.lsb = rng.second;
parm->type = IVL_VT_LOGIC;
parm->msb = rng.first;
parm->lsb = rng.second;
} else {
parm.type = IVL_VT_NO_TYPE;
parm.msb = 0;
parm.lsb = 0;
parm->type = IVL_VT_NO_TYPE;
parm->msb = 0;
parm->lsb = 0;
}
parm.signed_flag = false;
parm.range = 0;
parm->signed_flag = false;
parm->range = 0;
}
void pform_set_defparam(const pform_name_t&name, PExpr*expr)
@ -3621,12 +3624,10 @@ void pform_start_modport_item(const struct vlltype&loc, const char*name)
perm_string use_name = lex_strings.make(name);
pform_cur_modport = new PModport(use_name);
FILE_NAME(pform_cur_modport, loc);
if (scope->modports.find(use_name) != scope->modports.end()) {
cerr << loc << ": error: duplicate declaration for modport '"
<< name << "' in '" << scope->mod_name() << "'." << endl;
error_count += 1;
}
add_local_symbol(scope, use_name, pform_cur_modport);
scope->modports[use_name] = pform_cur_modport;
delete[] name;
}

17
pform.h
View File

@ -1,7 +1,7 @@
#ifndef IVL_pform_H
#define IVL_pform_H
/*
* Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -246,7 +246,10 @@ extern void pform_add_modport_port(const struct vlltype&loc,
* This creates an identifier aware of names that may have been
* imported from other packages.
*/
extern PEIdent* pform_new_ident(const pform_name_t&name);
extern PEIdent* pform_new_ident(const struct vlltype&loc, const pform_name_t&name);
extern PTrigger* pform_new_trigger(const struct vlltype&loc, PPackage*pkg,
const pform_name_t&name);
/*
* Enter/exit name scopes. The push_scope function pushes the scope
@ -274,7 +277,8 @@ extern PTask*pform_push_task_scope(const struct vlltype&loc, char*name,
extern PFunction*pform_push_function_scope(const struct vlltype&loc, const char*name,
LexicalScope::lifetime_t lifetime);
extern PBlock*pform_push_block_scope(char*name, PBlock::BL_TYPE tt);
extern PBlock*pform_push_block_scope(const struct vlltype&loc, char*name,
PBlock::BL_TYPE tt);
extern void pform_put_behavior_in_scope(AProcess*proc);
@ -299,7 +303,7 @@ extern void pform_start_generate_case(const struct vlltype&lp, PExpr*test);
extern void pform_start_generate_nblock(const struct vlltype&lp, char*name);
extern void pform_generate_case_item(const struct vlltype&lp, list<PExpr*>*test);
extern void pform_generate_block_name(char*name);
extern void pform_endgenerate();
extern void pform_endgenerate(bool end_conditional);
/*
* This function returns the lexically containing generate scheme, if
@ -311,9 +315,10 @@ extern PGenerate* pform_parent_generate(void);
extern void pform_set_typedef(perm_string name, data_type_t*data_type,
std::list<pform_range_t>*unp_ranges);
extern void pform_set_type_referenced(const struct vlltype&loc, const char*name);
/*
* This function makes a PECallFunction of the named function. Decide
* if this function is in the scope or is imported from a package.
* This function makes a PECallFunction of the named function.
*/
extern PECallFunction* pform_make_call_function(const struct vlltype&loc,
const pform_name_t&name,

View File

@ -1359,22 +1359,22 @@ void LexicalScope::dump_typedefs_(ostream&out, unsigned indent) const
void LexicalScope::dump_parameters_(ostream&out, unsigned indent) const
{
typedef map<perm_string,param_expr_t>::const_iterator parm_iter_t;
typedef map<perm_string,param_expr_t*>::const_iterator parm_iter_t;
for (parm_iter_t cur = parameters.begin()
; cur != parameters.end() ; ++ cur ) {
out << setw(indent) << "" << "parameter "
<< (*cur).second.type << " ";
if ((*cur).second.signed_flag)
<< (*cur).second->type << " ";
if ((*cur).second->signed_flag)
out << "signed ";
if ((*cur).second.msb)
out << "[" << *(*cur).second.msb << ":"
<< *(*cur).second.lsb << "] ";
if ((*cur).second->msb)
out << "[" << *(*cur).second->msb << ":"
<< *(*cur).second->lsb << "] ";
out << (*cur).first << " = ";
if ((*cur).second.expr)
out << *(*cur).second.expr;
if ((*cur).second->expr)
out << *(*cur).second->expr;
else
out << "/* ERROR */";
for (LexicalScope::range_t*tmp = (*cur).second.range
for (LexicalScope::range_t*tmp = (*cur).second->range
; tmp ; tmp = tmp->next) {
if (tmp->exclude_flag)
out << " exclude ";
@ -1408,16 +1408,16 @@ void LexicalScope::dump_parameters_(ostream&out, unsigned indent) const
void LexicalScope::dump_localparams_(ostream&out, unsigned indent) const
{
typedef map<perm_string,param_expr_t>::const_iterator parm_iter_t;
typedef map<perm_string,param_expr_t*>::const_iterator parm_iter_t;
for (parm_iter_t cur = localparams.begin()
; cur != localparams.end() ; ++ cur ) {
out << setw(indent) << "" << "localparam ";
if ((*cur).second.msb)
out << "[" << *(*cur).second.msb << ":"
<< *(*cur).second.lsb << "] ";
if ((*cur).second->msb)
out << "[" << *(*cur).second->msb << ":"
<< *(*cur).second->lsb << "] ";
out << (*cur).first << " = ";
if ((*cur).second.expr)
out << *(*cur).second.expr << ";" << endl;
if ((*cur).second->expr)
out << *(*cur).second->expr << ";" << endl;
else
out << "/* ERROR */;" << endl;
}
@ -1513,16 +1513,16 @@ void PClass::dump(ostream&out, unsigned indent) const
void Module::dump_specparams_(ostream&out, unsigned indent) const
{
typedef map<perm_string,param_expr_t>::const_iterator parm_iter_t;
typedef map<perm_string,param_expr_t*>::const_iterator parm_iter_t;
for (parm_iter_t cur = specparams.begin()
; cur != specparams.end() ; ++ cur ) {
out << setw(indent) << "" << "specparam ";
if ((*cur).second.msb)
out << "[" << *(*cur).second.msb << ":"
<< *(*cur).second.lsb << "] ";
if ((*cur).second->msb)
out << "[" << *(*cur).second->msb << ":"
<< *(*cur).second->lsb << "] ";
out << (*cur).first << " = ";
if ((*cur).second.expr)
out << *(*cur).second.expr << ";" << endl;
if ((*cur).second->expr)
out << *(*cur).second->expr << ";" << endl;
else
out << "/* ERROR */;" << endl;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-2019 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -72,98 +72,58 @@ void pform_end_package_declaration(const struct vlltype&loc)
* package is declared in pform ahead of time (it is) and that we can
* simply transfer definitions to the current scope (we can).
*/
void pform_package_import(const struct vlltype&, PPackage*pkg, const char*ident)
void pform_package_import(const struct vlltype&loc, PPackage*pkg, const char*ident)
{
LexicalScope*scope = pform_peek_scope();
if (ident) {
perm_string use_ident = lex_strings.make(ident);
map<perm_string,LexicalScope::param_expr_t>::const_iterator cur
= pkg->parameters.find(use_ident);
if (cur != pkg->parameters.end()) {
scope->imports[cur->first] = pkg;
// Check that the requested symbol is available.
map<perm_string,PNamedItem*>::const_iterator cur_sym
= pkg->local_symbols.find(use_ident);
if (cur_sym == pkg->local_symbols.end()) {
cerr << loc.get_fileline() << ": error: "
"'" << use_ident << "' is not exported by '"
<< pkg->pscope_name() << "'." << endl;
error_count += 1;
return;
}
cur = pkg->localparams.find(use_ident);
if (cur != pkg->localparams.end()) {
scope->imports[cur->first] = pkg;
// Check for conflict with local symbol.
cur_sym = scope->local_symbols.find(use_ident);
if (cur_sym != scope->local_symbols.end()) {
cerr << loc.get_fileline() << ": error: "
"'" << use_ident << "' has already been declared "
"in this scope." << endl;
cerr << cur_sym->second->get_fileline() << ": : "
"It was declared here as "
<< cur_sym->second->symbol_type() << "." << endl;
error_count += 1;
return;
}
map<perm_string,data_type_t*>::const_iterator tcur;
tcur = pkg->typedefs.find(use_ident);
if (tcur != pkg->typedefs.end()) {
scope->imports[tcur->first] = pkg;
// Check for conflict with previous import.
map<perm_string,PPackage*>::const_iterator cur_pkg
= scope->explicit_imports.find(use_ident);
if (cur_pkg != scope->explicit_imports.end()) {
if (cur_pkg->second != pkg) {
cerr << loc.get_fileline() << ": error: "
"'" << use_ident << "' has already been "
"imported into this scope from package '"
<< cur_pkg->second->pscope_name() << "'." << endl;
error_count += 1;
}
return;
}
map<perm_string,PFunction*>::const_iterator fcur;
fcur = pkg->funcs.find(use_ident);
if (fcur != pkg->funcs.end()) {
scope->imports[fcur->first] = pkg;
return;
}
map<perm_string,PTask*>::const_iterator ttcur;
ttcur = pkg->tasks.find(use_ident);
if (ttcur != pkg->tasks.end()) {
scope->imports[ttcur->first] = pkg;
return;
}
map<perm_string,PWire*>::const_iterator wcur;
wcur = pkg->wires.find(use_ident);
if (wcur != pkg->wires.end()) {
scope->imports[wcur->first] = pkg;
return;
}
ostringstream msg;
msg << "Symbol " << use_ident
<< " not found in package " << pkg->pscope_name() << "." << ends;
VLerror(msg.str().c_str());
return;
scope->explicit_imports[use_ident] = pkg;
} else {
// Handle the pkg::* case by importing everything from
// the package.
for (map<perm_string,LexicalScope::param_expr_t>::const_iterator cur = pkg->parameters.begin()
; cur != pkg->parameters.end() ; ++cur) {
scope->imports[cur->first] = pkg;
}
for (map<perm_string,LexicalScope::param_expr_t>::const_iterator cur = pkg->localparams.begin()
; cur != pkg->localparams.end() ; ++cur) {
scope->imports[cur->first] = pkg;
}
for (map<perm_string,data_type_t*>::const_iterator cur = pkg->typedefs.begin()
; cur != pkg->typedefs.end() ; ++cur) {
scope->imports[cur->first] = pkg;
}
for (map<perm_string,PFunction*>::const_iterator cur = pkg->funcs.begin()
; cur != pkg->funcs.end() ; ++cur) {
scope->imports[cur->first] = pkg;
}
for (map<perm_string,PWire*>::const_iterator cur = pkg->wires.begin()
; cur != pkg->wires.end() ; ++cur) {
scope->imports[cur->first] = pkg;
}
for (set<enum_type_t*>::const_iterator cur = pkg->enum_sets.begin()
; cur != pkg->enum_sets.end() ; ++ cur) {
scope->enum_sets.insert(*cur);
}
set<PPackage*>::const_iterator cur_pkg
= scope->potential_imports.find(pkg);
if (cur_pkg == scope->potential_imports.end())
scope->potential_imports.insert(pkg);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2007-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -24,6 +24,11 @@ data_type_t::~data_type_t()
{
}
PNamedItem::SymbolType data_type_t::symbol_type() const
{
return TYPE;
}
string_type_t::~string_type_t()
{
}
@ -44,3 +49,13 @@ ivl_variable_type_t vector_type_t::figure_packed_base_type(void) const
}
atom2_type_t size_type (32, true);
PNamedItem::SymbolType enum_type_t::symbol_type() const
{
return ENUM;
}
PNamedItem::SymbolType class_type_t::symbol_type() const
{
return CLASS;
}

View File

@ -1,7 +1,7 @@
#ifndef IVL_pform_types_H
#define IVL_pform_types_H
/*
* Copyright (c) 2007-2018 Stephen Williams (steve@icarus.com)
* Copyright (c) 2007-2019 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -21,7 +21,7 @@
// This for the perm_string type.
# include "StringHeap.h"
# include "LineInfo.h"
# include "PNamedItem.h"
# include "verinum.h"
# include "named.h"
# include "netstruct.h"
@ -137,7 +137,7 @@ struct pform_tf_port_t {
* "data_type" rule in the parse rule. We make the type virtual so
* that dynamic types will work.
*/
class data_type_t : public LineInfo {
class data_type_t : public PNamedItem {
public:
inline explicit data_type_t() { }
virtual ~data_type_t() = 0;
@ -149,6 +149,8 @@ class data_type_t : public LineInfo {
ivl_type_s* elaborate_type(Design*des, NetScope*scope);
virtual SymbolType symbol_type() const;
private:
// Elaborate the type to an ivl_type_s type.
virtual ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const;
@ -171,6 +173,8 @@ struct enum_type_t : public data_type_t {
// Return the elaborated version of the type.
virtual ivl_type_s*elaborate_type_raw(Design*des, NetScope*scope) const;
SymbolType symbol_type() const;
ivl_variable_type_t base_type;
bool signed_flag;
bool integer_flag; // True if "integer" was used
@ -335,6 +339,8 @@ struct class_type_t : public data_type_t {
// type. The elaborate_type_raw() method uses this pointer,
// and it is used in some other situations as well.
netclass_t* save_elaborated_type;
virtual SymbolType symbol_type() const;
};
/*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003-2017 Stephen Williams (steve@icarus.com)
* Copyright (c) 2003-2019 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -132,6 +132,11 @@ static bool symbol_search(const LineInfo*li, Design*des, NetScope*scope,
return true;
}
if (NetScope*import_scope = scope->find_import(des, path_tail.name)) {
scope = import_scope;
continue;
}
if (recurse_flag) {
bool flag = false;
hname_t path_item = eval_path_component(des, start_scope, path_tail, flag);