Merge branch 'master' of github.com:steveicarus/iverilog

This commit is contained in:
Stephen Williams 2012-12-23 12:18:05 -08:00
commit 4b3ef8a314
540 changed files with 17391 additions and 6278 deletions

1
.gitignore vendored
View File

@ -13,6 +13,7 @@ tags
TAGS
cscope.*
*.patch
*.orig
# Object files and libraries
*.[oa]

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"

View File

@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include <map>

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"

View File

@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "StringHeap.h"

View File

@ -2,7 +2,8 @@
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@ -305,7 +306,7 @@ the "copyright" line and a pointer to where the full notice is found.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
Also add information on how to contact you by electronic and paper mail.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2012 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
@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
@ -31,21 +31,19 @@ hname_t::hname_t()
}
hname_t::hname_t(perm_string text)
: name_(text)
{
name_ = text;
number_ = INT_MIN;
}
hname_t::hname_t(perm_string text, int num)
: name_(text), number_(num)
{
name_ = text;
number_ = num;
}
hname_t::hname_t(const hname_t&that)
: name_(that.name_), number_(that.number_)
{
name_ = that.name_;
number_ = that.number_;
}
hname_t& hname_t::operator = (const hname_t&that)

View File

@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include <iostream>

View File

@ -12,9 +12,8 @@
#
# You should have received a copy of the GNU Library General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc.,
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.
#
SHELL = /bin/sh
@ -87,7 +86,7 @@ GIT = @GIT@
ifeq (@srcdir@,.)
INCLUDE_PATH = -I. -Ilibmisc
else
INCLUDE_PATH = -I. -Ilibmisc -I$(srcdir) -I$(srcdir)/libmisc
INCLUDE_PATH = -I. -I$(srcdir) -I$(srcdir)/libmisc
endif
CPPFLAGS = @DEFS@ $(INCLUDE_PATH) @CPPFLAGS@
@ -95,6 +94,7 @@ CFLAGS = @WARNING_FLAGS@ @CFLAGS@
CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@
PICFLAGS = @PICFLAG@
LDFLAGS = @rdynamic@ @LDFLAGS@
CTARGETFLAGS = @CTARGETFLAGS@
# Source files in the libmisc directory
M = LineInfo.o StringHeap.o
@ -104,17 +104,20 @@ FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o
O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
elab_expr.o elaborate_analog.o elab_lval.o elab_net.o \
elab_scope.o elab_sig.o elab_sig_analog.o emit.o eval.o eval_attrib.o \
elab_scope.o elab_sig.o elab_sig_analog.o elab_type.o \
emit.o eval.o eval_attrib.o \
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
load_module.o netlist.o netmisc.o net_analog.o net_assign.o net_design.o \
netenum.o netstruct.o net_event.o net_expr.o net_func.o net_link.o net_modulo.o \
load_module.o netlist.o netmisc.o nettypes.o net_analog.o net_assign.o \
net_design.o netclass.o netdarray.o \
netenum.o netparray.o netstruct.o netvector.o net_event.o net_expr.o net_func.o \
net_func_eval.o net_link.o net_modulo.o \
net_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.o \
net_udp.o pad_to_width.o parse.o parse_misc.o pform.o pform_analog.o \
pform_disciplines.o pform_dump.o pform_pclass.o pform_struct_type.o \
pform_types.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 PScope.o PSpec.o PTask.o PUdp.o PFunction.o PWire.o \
PGenerate.o PPackage.o PScope.o PSpec.o PTask.o PUdp.o PFunction.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
@ -170,8 +173,8 @@ endif
rm -rf autom4te.cache
cppcheck: $(O:.o=.cc) $(srcdir)/dosify.c $(srcdir)/version.c
cppcheck --enable=all -f --suppressions $(srcdir)/cppcheck.sup \
$(INCLUDE_PATH) $^
cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \
--relative-paths=$(srcdir) $(INCLUDE_PATH) $^
cppcheck-all:
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) cppcheck && ) true
@ -226,6 +229,7 @@ iverilog-vpi: $(srcdir)/iverilog-vpi.sh Makefile
-e 's;@IVCXX@;$(CXX);' \
-e 's;@IVCFLAGS@;$(CFLAGS);' \
-e 's;@IVCXXFLAGS@;$(CXXFLAGS);' \
-e 's;@IVCTARGETFLAGS@;$(CTARGETFLAGS);' \
-e 's;@INCLUDEDIR@;$(includedir);' \
-e 's;@LIBDIR@;@libdir@;' $< > $@
chmod +x $@
@ -377,7 +381,7 @@ uninstall:
do rm -f "$(DESTDIR)$(bindir)/$$f"; done
for f in ivl_target.h vpi_user.h _pli_types.h sv_vpi_user.h acc_user.h veriuser.h; \
do rm -f "$(DESTDIR)$(includedir)/$$f"; done
-test X$(suffix) = X || rmdir "$(DESTDIR)/$(includedir)"
-test X$(suffix) = X || rmdir "$(DESTDIR)$(includedir)"
rm -f "$(DESTDIR)$(mandir)/man1/iverilog-vpi$(suffix).1" "$(DESTDIR)$(prefix)/iverilog-vpi$(suffix).pdf"

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
@ -27,11 +27,12 @@
list<Module::named_expr_t> Module::user_defparms;
/* n is a permallocated string. */
Module::Module(perm_string n)
: PScopeExtra(n)
Module::Module(LexicalScope*parent, perm_string n)
: PScopeExtra(n, parent)
{
library_flag = false;
is_cell = false;
program_block = false;
uc_drive = UCD_NONE;
timescale_warn_done = false;
time_unit = 0;
@ -89,6 +90,22 @@ unsigned Module::find_port(const char*name) const
return ports.size();
}
perm_string Module::get_port_name(unsigned idx) const
{
assert(idx < ports.size());
if (ports[idx] == 0) {
/* It is possible to have undeclared ports. These
are ports that are skipped in the declaration,
for example like so: module foo(x ,, y); The
port between x and y is unnamed and thus
inaccessible to binding by name. */
return perm_string::literal("");
}
return ports[idx]->name;
}
PGate* Module::get_gate(perm_string name)
{

View File

@ -1,7 +1,7 @@
#ifndef __Module_H
#define __Module_H
/*
* Copyright (c) 1998-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2010,2012 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
@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -65,7 +65,7 @@ class Module : public PScopeExtra, public LineInfo {
public:
/* The name passed here is the module name, not the instance
name. This make must be a permallocated string. */
explicit Module(perm_string name);
explicit Module(LexicalScope*parent, perm_string name);
~Module();
/* Initially false. This is set to true if the module has been
@ -76,13 +76,18 @@ class Module : public PScopeExtra, public LineInfo {
bool is_cell;
/* This is true if the module represents a program block
instead of a module/cell. Program blocks have content
restrictions and slightly modify scheduling semantics. */
bool program_block;
enum UCDriveType { UCD_NONE, UCD_PULL0, UCD_PULL1 };
UCDriveType uc_drive;
/* specparams are simpler than other params, in that they have
no type information. They are merely constant
expressions. */
map<perm_string,PExpr*>specparams;
/* 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;
/* The module also has defparam assignments which don't create
new parameters within the module, but may be used to set
@ -116,6 +121,10 @@ class Module : public PScopeExtra, public LineInfo {
the module definition. These are used at elaboration time. */
list<PGenerate*> generate_schemes;
/* Nested modules are placed here, and are not elaborated
unless they are instantiated, implicitly or explicitly. */
std::map<perm_string,Module*> nested_modules;
list<PSpecPath*> specify_paths;
// The mod_name() is the name of the module type.
@ -127,6 +136,9 @@ class Module : public PScopeExtra, public LineInfo {
const vector<PEIdent*>& get_port(unsigned idx) const;
unsigned find_port(const char*name) const;
// Return port name ("" for undeclared port)
perm_string get_port_name(unsigned idx) const;
PGate* get_gate(perm_string name);
const list<PGate*>& get_gates() const;
@ -140,6 +152,7 @@ class Module : public PScopeExtra, public LineInfo {
bool elaborate_sig(Design*, NetScope*scope) const;
private:
void dump_specparams_(ostream&out, unsigned indent) const;
list<PGate*> gates_;
private: // Not implemented

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "PClass.h"

View File

@ -16,12 +16,13 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "PScope.h"
# include "LineInfo.h"
# include "StringHeap.h"
# include <iostream>
/*
* SystemVerilog supports class declarations with their own lexical
@ -35,6 +36,10 @@ class PClass : public PScopeExtra, public LineInfo {
explicit PClass (perm_string name, LexicalScope*parent);
~PClass();
void dump(std::ostream&out, unsigned indent) const;
public:
class_type_t*type;
};
#endif

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"

View File

@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "svector.h"

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"

View File

@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "LineInfo.h"

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
@ -281,6 +281,14 @@ PExpr* PEEvent::expr() const
return expr_;
}
PENull::PENull(void)
{
}
PENull::~PENull()
{
}
PEFNumber::PEFNumber(verireal*v)
: value_(v)
{
@ -363,7 +371,7 @@ bool PEIdent::has_aa_term(Design*des, NetScope*scope) const
const NetExpr*ex1, *ex2;
scope = symbol_search(0, des, scope, path_, net, par, eve, ex1, ex2);
scope = symbol_search(this, des, scope, path_, net, par, eve, ex1, ex2);
if (scope)
return scope->is_auto();
@ -371,6 +379,24 @@ bool PEIdent::has_aa_term(Design*des, NetScope*scope) const
return false;
}
PENew::PENew(PExpr*size_expr)
: size_(size_expr)
{
}
PENew::~PENew()
{
delete size_;
}
PENewClass::PENewClass(void)
{
}
PENewClass::~PENewClass()
{
}
PENumber::PENumber(verinum*vp)
: value_(vp)
{

83
PExpr.h
View File

@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include <string>
@ -49,6 +49,7 @@ class PExpr : public LineInfo {
static const unsigned NO_FLAGS = 0x0;
static const unsigned NEED_CONST = 0x1;
static const unsigned SYS_TASK_ARG = 0x2;
static const unsigned ANNOTATABLE = 0x4;
PExpr();
virtual ~PExpr();
@ -120,6 +121,13 @@ class PExpr : public LineInfo {
// to be propagated down to any context-dependant operands.
void cast_signed(bool flag) { signed_flag_ = flag; }
// This is the more generic form of the elaborate_expr method
// below. The plan is to replace the simpler elaborate_expr
// method with this version, which can handle more advanced
// types. But for now, this is only implemented in special cases.
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
// Procedural elaboration of the expression. The expr_width is
// the required width of the expression.
//
@ -304,13 +312,15 @@ class PEIdent : public PExpr {
NetScope*scope,
bool is_force) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
unsigned flags) const;
// Elaborate the PEIdent as a port to a module. This method
// only applies to Ident expressions.
NetNet* elaborate_port(Design*des, NetScope*sc) const;
NetNet* elaborate_subport(Design*des, NetScope*sc) const;
verinum* eval_const(Design*des, NetScope*sc) const;
@ -363,9 +373,14 @@ class PEIdent : public PExpr {
bool elaborate_lval_net_part_(Design*, NetScope*, NetAssign_*) const;
bool elaborate_lval_net_idx_(Design*, NetScope*, NetAssign_*,
index_component_t::ctype_t) const;
bool elaborate_lval_net_class_member_(Design*, NetScope*,
NetAssign_*,
const perm_string&) const;
bool elaborate_lval_net_packed_member_(Design*, NetScope*,
NetAssign_*,
const perm_string&) const;
bool elaborate_lval_darray_bit_(Design*, NetScope*,
NetAssign_*) const;
private:
NetExpr*elaborate_expr_param_(Design*des,
@ -438,6 +453,59 @@ class PEIdent : public PExpr {
long&midx, long&lidx) const;
};
class PENew : public PExpr {
public:
explicit PENew (PExpr*s);
~PENew();
virtual void dump(ostream&) const;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
unsigned flags) const;
private:
PExpr*size_;
};
class PENewClass : public PExpr {
public:
explicit PENewClass ();
~PENewClass();
virtual void dump(ostream&) const;
// Class objects don't have a useful width, but the expression
// is IVL_VT_CLASS.
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
// Note that class (new) expressions only appear in context
// that uses this form of the elaborate_expr method. In fact,
// the type argument is going to be a netclas_t object.
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
private:
};
class PENull : public PExpr {
public:
explicit PENull();
~PENull();
virtual void dump(ostream&) const;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
unsigned flags) const;
};
class PENumber : public PExpr {
public:
@ -716,8 +784,17 @@ class PECallFunction : public PExpr {
bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
NetExpr* cast_to_width_(NetExpr*expr, unsigned wid) const;
NetExpr*elaborate_expr_method_(Design*des, NetScope*scope,
unsigned expr_wid) const;
#if 0
NetExpr*elaborate_expr_string_method_(Design*des, NetScope*scope) const;
NetExpr*elaborate_expr_enum_method_(Design*des, NetScope*scope,
unsigned expr_wid) const;
#endif
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope,
unsigned expr_wid,
unsigned flags) const;
@ -725,6 +802,8 @@ class PECallFunction : public PExpr {
unsigned expr_wid) const;
unsigned test_width_sfunc_(Design*des, NetScope*scope,
width_mode_t&mode);
unsigned test_width_method_(Design*des, NetScope*scope,
width_mode_t&mode);
};
/*

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
@ -260,7 +260,7 @@ const char* PGBuiltin::gate_name() const
}
PGModule::PGModule(perm_string type, perm_string name, list<PExpr*>*pins)
: PGate(name, pins), overrides_(0), pins_(0),
: PGate(name, pins), bound_type_(0), overrides_(0), pins_(0),
npins_(0), parms_(0), nparms_(0), msb_(0), lsb_(0)
{
type_ = type;
@ -268,12 +268,18 @@ PGModule::PGModule(perm_string type, perm_string name, list<PExpr*>*pins)
PGModule::PGModule(perm_string type, perm_string name,
named<PExpr*>*pins, unsigned npins)
: PGate(name, 0), overrides_(0), pins_(pins),
: PGate(name, 0), bound_type_(0), overrides_(0), pins_(pins),
npins_(npins), parms_(0), nparms_(0), msb_(0), lsb_(0)
{
type_ = type;
}
PGModule::PGModule(Module*type, perm_string name)
: PGate(name, 0), bound_type_(type), overrides_(0), pins_(0),
npins_(0), parms_(0), nparms_(0), msb_(0), lsb_(0)
{
}
PGModule::~PGModule()
{
}

View File

@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "svector.h"
@ -201,6 +201,9 @@ class PGModule : public PGate {
explicit PGModule(perm_string type, perm_string name,
named<PExpr*>*pins, unsigned npins);
// If the module type is known by design, then use this
// constructor.
explicit PGModule(Module*type, perm_string name);
~PGModule();
@ -223,6 +226,7 @@ class PGModule : public PGate {
perm_string get_type() const;
private:
Module*bound_type_;
perm_string type_;
list<PExpr*>*overrides_;
named<PExpr*>*pins_;

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "PGenerate.h"

View File

@ -1,7 +1,7 @@
#ifndef __PGenerate_H
#define __PGenerate_H
/*
* Copyright (c) 2006-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2006-2010,2012 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
@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "LineInfo.h"
@ -80,6 +80,10 @@ class PGenerate : public LineInfo, public LexicalScope {
// test value.
std::valarray<PExpr*> item_test;
// defparam assignments found in this scope.
typedef pair<pform_name_t,PExpr*> named_expr_t;
list<named_expr_t>defparms;
list<PGate*> gates;
void add_gate(PGate*);
@ -87,9 +91,6 @@ class PGenerate : public LineInfo, public LexicalScope {
map<perm_string,PTask*> tasks;
map<perm_string,PFunction*>funcs;
// genvars declared within this scheme.
map<perm_string,LineInfo*> genvars;
// Generate schemes can contain further generate schemes.
list<PGenerate*> generate_schemes;
// PGenerate*parent;

30
PPackage.cc Normal file
View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2012 Picture Elements, Inc.
* 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
* 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 "PPackage.h"
PPackage::PPackage(perm_string name, LexicalScope*parent)
: PScopeExtra(name, parent)
{
}
PPackage::~PPackage()
{
}

40
PPackage.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef __PPackage_H
#define __PPackage_H
/*
* Copyright (c) 2012 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
* 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 "PScope.h"
# include "LineInfo.h"
# include "StringHeap.h"
/*
* SystemVerilog supports class declarations with their own lexical
* scope, etc. The parser arranges for these to be created and
* collected.
*/
class PPackage : public PScopeExtra, public LineInfo {
public:
explicit PPackage (perm_string name, LexicalScope*parent);
~PPackage();
};
#endif

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "PScope.h"

View File

@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "LineInfo.h"
@ -30,6 +30,7 @@ class PExpr;
class PFunction;
class AProcess;
class PProcess;
class PClass;
class PTask;
class PWire;
@ -165,8 +166,13 @@ class PScopeExtra : public PScope {
~PScopeExtra();
/* Task definitions within this module */
map<perm_string,PTask*> tasks;
map<perm_string,PFunction*> funcs;
std::map<perm_string,PTask*> tasks;
std::map<perm_string,PFunction*> funcs;
/* class definitions within this module. */
std::map<perm_string,PClass*> classes;
protected:
void dump_classes_(ostream&out, unsigned indent) const;
};
#endif

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "PSpec.h"

View File

@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "LineInfo.h"

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"

View File

@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "LineInfo.h"

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "PUdp.h"

2
PUdp.h
View File

@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include <map>

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
@ -29,7 +29,7 @@ PWire::PWire(perm_string n,
: name_(n), type_(t), port_type_(pt), data_type_(dt),
signed_(false), isint_(false),
port_set_(false), net_set_(false), is_scalar_(false),
error_cnt_(0), lidx_(0), ridx_(0), enum_type_(0), struct_type_(0),
error_cnt_(0), set_data_type_(0),
discipline_(0)
{
if (t == NetNet::INTEGER) {
@ -242,30 +242,21 @@ void PWire::set_range(const list<pform_range_t>&rlist, PWSRType type)
}
}
void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
void PWire::set_unpacked_idx(const list<pform_range_t>&ranges)
{
if (lidx_ != 0 || ridx_ != 0) {
if (! unpacked_.empty()) {
cerr << get_fileline() << ": error: Array ``" << name_
<< "'' has already been declared." << endl;
error_cnt_ += 1;
} else {
lidx_ = ldx;
ridx_ = rdx;
unpacked_ = ranges;
}
}
void PWire::set_enumeration(enum_type_t*enum_type)
void PWire::set_data_type(data_type_t*type)
{
assert(enum_type_ == 0);
assert(struct_type_ == 0);
enum_type_ = enum_type;
}
void PWire::set_struct_type(struct_type_t*type)
{
assert(enum_type_ == 0);
assert(struct_type_ == 0);
struct_type_ = type;
assert(set_data_type_ == 0);
set_data_type_ = type;
}
void PWire::set_discipline(ivl_discipline_t d)

18
PWire.h
View File

@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "netlist.h"
@ -33,6 +33,7 @@ class ostream;
class PExpr;
class Design;
class netdarray_t;
/*
* The different type of PWire::set_range() calls.
@ -78,10 +79,9 @@ class PWire : public LineInfo {
void set_range_scalar(PWSRType type);
void set_range(const std::list<pform_range_t>&ranges, PWSRType type);
void set_memory_idx(PExpr*ldx, PExpr*rdx);
void set_unpacked_idx(const std::list<pform_range_t>&ranges);
void set_enumeration(enum_type_t*enum_type);
void set_struct_type(struct_type_t*type);
void set_data_type(data_type_t*type);
void set_discipline(ivl_discipline_t);
ivl_discipline_t get_discipline(void) const;
@ -115,12 +115,12 @@ class PWire : public LineInfo {
unsigned error_cnt_;
// If this wire is actually a memory, these indices will give
// me the size and address range of the memory.
PExpr*lidx_;
PExpr*ridx_;
// me the size and address ranges of the memory.
std::list<pform_range_t>unpacked_;
enum_type_t*enum_type_;
struct_type_t*struct_type_;
// This is the complex type of the wire. the data_type_ may
// modify how this is interpreted.
data_type_t*set_data_type_;
ivl_discipline_t discipline_;

View File

@ -64,7 +64,7 @@ on a UNIX-like system:
- termcap
The readline library in turn uses termcap.
If you are building from CVS, you will also need software to generate
If you are building from git, you will also need software to generate
the configure scripts.
- autoconf 2.53

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2008,2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2008,2010,2012 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
@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
@ -114,6 +114,13 @@ PBlock::~PBlock()
delete list_[idx];
}
void PBlock::set_join_type(PBlock::BL_TYPE type)
{
assert(bl_type_ == BL_PAR);
assert(type==BL_PAR || type==BL_JOIN_NONE || type==BL_JOIN_ANY);
bl_type_ = type;
}
void PBlock::set_statement(const vector<Statement*>&st)
{
list_ = st;

View File

@ -1,7 +1,7 @@
#ifndef __Statement_H
#define __Statement_H
/*
* Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2008,2012 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
@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include <string>
@ -106,6 +106,10 @@ class PAssign_ : public Statement {
NetAssign_* elaborate_lval(Design*, NetScope*scope) const;
NetExpr* elaborate_rval_(Design*, NetScope*, unsigned lv_width,
ivl_variable_type_t type) const;
NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t ntype) const;
NetExpr* elaborate_rval_obj_(Design*, NetScope*,
ivl_variable_type_t type) const;
PExpr* delay_;
PEventStatement*event_;
@ -165,7 +169,7 @@ class PAssignNB : public PAssign_ {
class PBlock : public PScope, public Statement {
public:
enum BL_TYPE { BL_SEQ, BL_PAR };
enum BL_TYPE { BL_SEQ, BL_PAR, BL_JOIN_NONE, BL_JOIN_ANY };
// If the block has a name, it is a scope and also has a parent.
explicit PBlock(perm_string n, LexicalScope*parent, BL_TYPE t);
@ -175,6 +179,10 @@ class PBlock : public PScope, public Statement {
BL_TYPE bl_type() const { return bl_type_; }
// If the bl_type() is BL_PAR, it is possible to replace it
// with JOIN_NONE or JOIN_ANY. This is to help the parser.
void set_join_type(BL_TYPE);
void set_statement(const std::vector<Statement*>&st);
virtual void dump(ostream&out, unsigned ind) const;
@ -183,7 +191,7 @@ class PBlock : public PScope, public Statement {
virtual void elaborate_sig(Design*des, NetScope*scope) const;
private:
const BL_TYPE bl_type_;
BL_TYPE bl_type_;
std::vector<Statement*>list_;
};
@ -203,6 +211,8 @@ class PCallTask : public Statement {
NetProc* elaborate_sys(Design*des, NetScope*scope) const;
NetProc* elaborate_usr(Design*des, NetScope*scope) const;
NetProc*elaborate_method_(Design*des, NetScope*scope) const;
pform_name_t path_;
vector<PExpr*> parms_;
};

View File

@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# undef HAVE_INTTYPES_H

View File

@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"

View File

@ -2,9 +2,9 @@
#
# This shell script exists to run autoconf on source distributions
# that are pulled from CVS. The configure scripts are not included
# in CVS, and there are several configure.in files, so it is easiest
# to just run this script to autoconf wherever needed.
# that are pulled from git The configure script is not included
# in git, so it is easiest to just run this script whenever needed
# to generate the configure script.
#
echo "Autoconf in root..."
autoconf -f

View File

@ -12,9 +12,8 @@
#
# You should have received a copy of the GNU Library General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc.,
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.
#
SHELL = /bin/sh

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include <vpi_user.h>

View File

@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#if defined(__MINGW32__)

View File

@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include <list>
@ -177,6 +177,11 @@ static inline bool gn_system_verilog(void)
return false;
}
static inline bool gn_modules_nest(void)
{
return gn_system_verilog();
}
/* The bits of these GN_KEYWORDS_* constants define non-intersecting
sets of keywords. The compiler enables groups of keywords by setting
lexor_keyword_mask with the OR of the bits for the keywords to be

View File

@ -1,7 +1,7 @@
#ifndef __config_H /* -*- c++ -*- */
#define __config_H
/*
* Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2012 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
@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#if defined(__cplusplus)
@ -53,6 +53,8 @@
/* These two are needed by the lxt and lxt2 files (copied from GTKWave). */
# undef HAVE_ALLOCA_H
# undef HAVE_FSEEKO
/* And this is needed by the fst files (copied from GTKWave). */
# undef HAVE_LIBPTHREAD
/*
* Define this if you want to compile vvp with memory freeing and

View File

@ -36,7 +36,7 @@ then
echo ""
echo "*** Warning: No suitable gperf found. ***"
echo " The gperf package is essential for building ivl from"
echo " CVS sources, or modifying the parse engine of ivl itself."
echo " git sources, or modifying the parse engine of ivl itself."
echo " You can get away without it when simply building from"
echo " snapshots or major releases."
echo ""
@ -91,6 +91,20 @@ fi
AC_LANG(C++)
AC_ARG_WITH([m32], [AC_HELP_STRING([--with-m32], [Compile 32-bit on x86_64])],
[ with_m32=yes ],[ with_m32=no ])
AS_IF( [test "x$with_m32" = xyes],
[ AC_MSG_NOTICE([Compiling for 32-bit environment - needs gcc on x86_64])
LDTARGETFLAGS="-m elf_i386"
CTARGETFLAGS="-m32"
],
[])
CFLAGS="$CTARGETFLAGS $CFLAGS"
CXXFLAGS="$CTARGETFLAGS $CXXFLAGS"
LDFLAGS="$CTARGETFLAGS $LDFLAGS"
# Check that we are using either the GNU compilers or the Sun compilers
# but not a mixture of the two (not currently supported).
AC_CHECK_DECL(__SUNPRO_CC, using_sunpro_cc=1, using_sunpro_cc=0)
@ -111,7 +125,11 @@ else
fi
fi
iverilog_temp_cxxflags="$CXXFLAGS"
CXXFLAGS="-DHAVE_DECL_BASENAME $CXXFLAGS"
AC_CHECK_HEADERS(getopt.h inttypes.h libiberty.h iosfwd sys/wait.h)
CXXFLAGS="$iverilog_temp_cxxflags"
AC_CHECK_SIZEOF(unsigned long long)
AC_CHECK_SIZEOF(unsigned long)
@ -178,6 +196,11 @@ if test -z "$DLLIB" ; then
AC_CHECK_LIB(dld,shl_load,[DLLIB=-ldld])
fi
AC_SUBST(DLLIB)
AC_SUBST(LDRELOCFLAGS)
AC_SUBST(CTARGETFLAGS)
AC_SUBST(LDTARGETFLAGS)
AC_PROG_INSTALL
@ -302,6 +325,4 @@ AC_MSG_ERROR(cannot configure white space in libdir: $libdir)
fi
AC_MSG_RESULT(ok)
# XXX disable tgt-fpga for the moment
AC_OUTPUT(Makefile ivlpp/Makefile vhdlpp/Makefile vvp/Makefile vpi/Makefile driver/Makefile driver-vpi/Makefile cadpli/Makefile libveriuser/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-vvp/Makefile tgt-vhdl/Makefile tgt-fpga/Makefile tgt-verilog/Makefile tgt-pal/Makefile tgt-vlog95/Makefile tgt-pcb/Makefile)

View File

@ -1,3 +1,3 @@
// These are correct and are used to find the base (zero) pin.
thisSubtraction:netlist.h:4169
thisSubtraction:netlist.h:4178
thisSubtraction:netlist.h:4430
thisSubtraction:netlist.h:4439

189
cprop.cc
View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2010,2012 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
@ -14,18 +14,19 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
# include <algorithm>
# include <vector>
# include <cstdlib>
# include "netlist.h"
# include "netmisc.h"
# include "functor.h"
# include "compiler.h"
# include "ivl_assert.h"
# include <vector>
/*
@ -42,11 +43,14 @@ struct cprop_functor : public functor_t {
virtual void signal(Design*des, NetNet*obj);
virtual void lpm_add_sub(Design*des, NetAddSub*obj);
virtual void lpm_compare(Design*des, NetCompare*obj);
virtual void lpm_compare_eq_(Design*des, NetCompare*obj);
virtual void lpm_concat(Design*des, NetConcat*obj);
virtual void lpm_ff(Design*des, NetFF*obj);
virtual void lpm_logic(Design*des, NetLogic*obj);
virtual void lpm_mux(Design*des, NetMux*obj);
};
virtual void lpm_part_select(Design*des, NetPartSelect*obj);
void lpm_compare_eq_(Design*des, NetCompare*obj);
};
void cprop_functor::signal(Design*, NetNet*)
{
@ -74,6 +78,45 @@ void cprop_functor::lpm_compare_eq_(Design*, NetCompare*)
{
}
void cprop_functor::lpm_concat(Design*des, NetConcat*obj)
{
verinum result (verinum::Vz, obj->width());
unsigned off = 0;
for (unsigned idx = 1 ; idx < obj->pin_count() ; idx += 1) {
Nexus*nex = obj->pin(idx).nexus();
// If there are non-constant drivers, then give up.
if (! nex->drivers_constant())
return;
verinum tmp = nex->driven_vector();
result.set(off, tmp);
off += tmp.len();
}
if (debug_optimizer)
cerr << obj->get_fileline() << ": cprop_functor::lpm_concat: "
<< "Replace NetConcat with " << result << "." << endl;
NetScope*scope = obj->scope();
// Create a NetConst object to carry the result. Give it the
// same name as the Concat object that we are replacing, and
// link the NetConst to the NetConcat object. Then delete the
// concat that is now replaced.
NetConst*result_obj = new NetConst(scope, obj->name(), result);
result_obj->set_line(*obj);
des->add_node(result_obj);
connect(obj->pin(0), result_obj->pin(0));
// Note that this will leave the const inputs to dangle. They
// will be reaped by other passes of cprop_functor.
delete obj;
count += 1;
}
void cprop_functor::lpm_ff(Design*, NetFF*obj)
{
// Look for and count unlinked FF outputs. Note that if the
@ -150,6 +193,142 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
count += 1;
}
static bool compare_base(NetPartSelect*a, NetPartSelect*b)
{
return a->base() < b->base();
}
/*
* This optimization searches for Nexa that are driven only by
* NetPartSelect(PV) outputs. These might turn from Verilog input that
* looks like this:
* wire [7:0] foo
* assign foo[7:4] = a;
* assign foo[3:0] = b;
* The idea is to convert the part selects of the above to a single
* concatenation that looks like this:
* assign foo = {a, b};
*/
void cprop_functor::lpm_part_select(Design*des, NetPartSelect*obj)
{
if (obj->dir() != NetPartSelect::PV)
return;
NetScope*scope = obj->scope();
Nexus*nex = obj->pin(1).nexus();
vector<NetPartSelect*> obj_set;
for (Link*cur = nex->first_nlink() ; cur ; cur = cur->next_nlink()) {
// If this is an input (or passive) then ignore it.
if (cur->get_dir() != Link::OUTPUT)
continue;
// Check to see if this is the output of a
// NetPartSelect::PV. If not, then give up on the blend.
NetPins*tmp_obj = cur->get_obj();
unsigned tmp_pin = cur->get_pin();
NetPartSelect*cur_obj = dynamic_cast<NetPartSelect*> (tmp_obj);
if (cur_obj == 0)
return;
if (cur_obj->dir() != NetPartSelect::PV)
return;
if (tmp_pin != 1)
return;
obj_set.push_back(cur_obj);
}
if (obj_set.size() < 2)
return;
if (debug_optimizer)
cerr << obj->get_fileline() << ": cprop::lpm_part_select: "
<< "Found " << obj_set.size() << " NetPartSelect(PV) objects."
<< endl;
// Sort by increasing base offset.
sort(obj_set.begin(), obj_set.end(), compare_base);
// Check and make sure there are no overlaps. If there are,
// then give up on this optimization.
for (size_t idx = 1 ; idx < obj_set.size() ; idx += 1) {
unsigned top = obj_set[idx-1]->base() + obj_set[idx-1]->width();
if (top > obj_set[idx]->base()) {
if (debug_optimizer)
cerr << obj->get_fileline() << ": cprop::lpm_part_select: "
<< "Range [" << obj_set[idx-1]->base()
<< " " << top << ") overlaps PV starting at "
<< obj_set[idx]->base() << ". Give up." << endl;
return;
}
}
// Check if the tail runs off the end of the target. If so it
// should be possible to replace it with a bit select to
// shorten the object for the target, but for now just give up.
unsigned sig_width = nex->vector_width();
if (obj_set.back()->base() + obj_set.back()->width() > sig_width) {
if (debug_optimizer)
cerr << obj->get_fileline() << ": cprop::lpm_part_select: "
<< "Range [" << obj_set.back()->base()
<< ":" << (obj_set.back()->base() + obj_set.back()->width() - 1)
<< "] runs off the end of target." << endl;
return;
}
// Figure out how many components we are going to need.
unsigned part_count = 0;
unsigned off = 0;
for (size_t idx = 0 ; idx < obj_set.size() ; idx += 1) {
if (obj_set[idx]->base() > off) {
off = obj_set[idx]->base();
part_count += 1;
}
off += obj_set[idx]->width();
part_count += 1;
}
if (off < sig_width)
part_count += 1;
NetConcat*concat = new NetConcat(scope, scope->local_symbol(),
sig_width, part_count);
concat->set_line(*obj);
des->add_node(concat);
connect(concat->pin(0), obj->pin(1));
off = 0;
size_t concat_pin = 1;
for (size_t idx = 0 ; idx < obj_set.size() ; idx += 1) {
NetPartSelect*cobj = obj_set[idx];
if (cobj->base() > off) {
NetNet*zzz = make_const_z(des, scope, cobj->base()-off);
connect(concat->pin(concat_pin), zzz->pin(0));
concat_pin += 1;
off = cobj->base();
}
connect(concat->pin(concat_pin), cobj->pin(0));
concat_pin += 1;
off += cobj->width();
}
if (off < sig_width) {
NetNet*zzz = make_const_z(des, scope, sig_width-off);
connect(concat->pin(concat_pin), zzz->pin(0));
concat_pin += 1;
}
ivl_assert(*obj, concat_pin == concat->pin_count());
for (size_t idx = 0 ; idx < obj_set.size() ; idx += 1) {
delete obj_set[idx];
}
count += 1;
}
/*
* This functor looks to see if the constant is connected to nothing
* but signals. If that is the case, delete the dangling constant and

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
@ -28,6 +28,8 @@
# include "netlist.h"
# include "compiler.h"
# include "discipline.h"
# include "netdarray.h"
# include "netvector.h"
# include "ivl_assert.h"
# include "PExpr.h"
@ -40,6 +42,12 @@ static ostream& operator<< (ostream&o, NetBlock::Type t)
case NetBlock::PARA:
o << "fork";
break;
case NetBlock::PARA_JOIN_NONE:
o << "fork-join_none";
break;
case NetBlock::PARA_JOIN_ANY:
o << "fork-join_any";
break;
}
return o;
}
@ -98,6 +106,12 @@ ostream& operator << (ostream&o, ivl_variable_type_t val)
case IVL_VT_STRING:
o << "string";
break;
case IVL_VT_DARRAY:
o << "darray";
break;
case IVL_VT_CLASS:
o << "class";
break;
}
return o;
}
@ -130,6 +144,24 @@ ostream& operator << (ostream&o, ivl_switch_type_t val)
return o;
}
ostream& ivl_type_s::debug_dump(ostream&o) const
{
o << typeid(*this).name();
return o;
}
ostream& netdarray_t::debug_dump(ostream&o) const
{
o << "dynamic array of " << *element_type();
return o;
}
ostream& netvector_t::debug_dump(ostream&o) const
{
o << type_ << (signed_? " signed" : " unsigned") << packed_dims_;
return o;
}
static inline void dump_scope_path(ostream&o, const NetScope*scope)
{
const NetScope*parent = scope->parent();
@ -187,11 +219,30 @@ void NetDelaySrc::dump(ostream&o, unsigned ind) const
dump_node_pins(o, ind+4);
}
ostream&operator<<(ostream&out, const list<NetNet::range_t>&rlist)
static inline ostream&operator<<(ostream&out, const netrange_t&that)
{
for (list<NetNet::range_t>::const_iterator cur = rlist.begin()
if (that.defined())
out << "[" << that.get_msb() << ":" << that.get_lsb() << "]";
else
out << "[]";
return out;
}
ostream&operator<<(ostream&out, const list<netrange_t>&rlist)
{
for (list<netrange_t>::const_iterator cur = rlist.begin()
; cur != rlist.end() ; ++cur) {
out << "[" << cur->msb << ":" << cur->lsb << "]";
out << *cur;
}
return out;
}
ostream&operator<<(ostream&out, const vector<netrange_t>&rlist)
{
for (vector<netrange_t>::const_iterator cur = rlist.begin()
; cur != rlist.end() ; ++cur) {
out << *cur;
}
return out;
}
@ -200,12 +251,10 @@ ostream&operator<<(ostream&out, const list<NetNet::range_t>&rlist)
void NetNet::dump_net(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << type() << ": " << name()
<< "[" << s0_ << ":" << e0_ << " count=" << pin_count() << "]";
<< unpacked_dims_ << " unpacked dims=" << unpacked_dimensions();
o << " pin_count=" << pin_count();
if (local_flag_)
o << " (local)";
o << " " << data_type_;
if (signed_)
o << " signed";
switch (port_type_) {
case NetNet::NOT_A_PORT:
break;
@ -229,7 +278,7 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
if (ivl_discipline_t dis = get_discipline())
o << " discipline=" << dis->name();
o << " packed dims: " << packed_dims_;
if (net_type_) o << " " << *net_type_;
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
if (scope())
@ -470,9 +519,7 @@ void NetCaseCmp::dump_node(ostream&o, unsigned ind) const
void NetConst::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "constant " << width_ << "'b";
for (unsigned idx = width_ ; idx > 0 ; idx -= 1)
o << value_[idx-1];
o << setw(ind) << "" << "constant " << value_;
o << ": " << name();
if (rise_time())
o << " #(" << *rise_time()
@ -808,6 +855,9 @@ void NetAssign_::dump_lval(ostream&o) const
{
if (sig_) {
o << sig_->name();
if (! member_.nil()) {
o << "." << member_;
}
if (word_) {
o << "[word=" << *word_ << "]";
}
@ -1059,7 +1109,7 @@ void NetFuncDef::dump(ostream&o, unsigned ind) const
if (result_sig_) {
o << setw(ind+2) << "" << "Return signal: ";
if (result_sig_->get_signed()) o << "+";
o << result_sig_->name() << result_sig_->packed_dims() << endl;
o << result_sig_->name() << endl;
}
o << setw(ind+2) << "" << "Arguments: ";
if (port_count() == 0) o << "<none>";
@ -1081,7 +1131,7 @@ void NetFuncDef::dump(ostream&o, unsigned ind) const
break;
}
if (port(idx)->get_signed()) o << "+";
o << port(idx)->name() << port(idx)->packed_dims() << endl;
o << port(idx)->name() << endl;
}
if (statement_)
statement_->dump(o, ind+2);
@ -1127,6 +1177,9 @@ void NetScope::dump(ostream&o) const
print_type(o);
if (is_auto()) o << " (automatic)";
if (is_cell()) o << " (cell)";
if (nested_module()) o << " (nested)";
if (program_block()) o << " (program)";
o << endl;
for (unsigned idx = 0 ; idx < attr_cnt() ; idx += 1)
@ -1141,7 +1194,10 @@ void NetScope::dump(ostream&o) const
map<perm_string,param_expr_t>::const_iterator pp;
for (pp = parameters.begin()
; pp != parameters.end() ; ++ pp ) {
o << " parameter ";
if ((*pp).second.is_annotatable)
o << " specparam ";
else
o << " parameter ";
o << pp->second.type << " ";
@ -1188,12 +1244,6 @@ void NetScope::dump(ostream&o) const
o << ";" << endl;
}
for (pp = localparams.begin()
; pp != localparams.end() ; ++ pp ) {
o << " localparam " << (*pp).first << " = " <<
*(*pp).second.val << ";" << endl;
}
}
/* Dump the saved defparam assignments here. */
@ -1245,27 +1295,6 @@ void NetScope::dump(ostream&o) const
cur->second->dump_net(o, 4);
}
// Dump specparams
typedef map<perm_string,spec_val_t>::const_iterator specparam_it_t;
for (specparam_it_t cur = specparams.begin()
; cur != specparams.end() ; ++ cur ) {
o << " specparam " << (*cur).first
<< " = ";
spec_val_t value = (*cur).second;
switch (value.type) {
case IVL_VT_REAL:
o << "R:" << value.real_val;
break;
case IVL_VT_BOOL:
o << "I:" << value.integer;
break;
default:
o << "<bad type>";
break;
}
o << endl;
}
switch (type_) {
case FUNC:
if (func_def())
@ -1293,12 +1322,12 @@ void NetSTask::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << name_;
if (parms_.count() > 0) {
if (! parms_.empty()) {
o << "(";
if (parms_[0])
parms_[0]->dump(o);
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) {
o << ", ";
if (parms_[idx])
parms_[idx]->dump(o);
@ -1428,7 +1457,7 @@ void NetEConcat::dump(ostream&o) const
else
o << "{";
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) {
if (parms_[idx])
o << ", " << *parms_[idx];
else
@ -1481,6 +1510,21 @@ void NetENetenum::dump(ostream&o) const
o << "<netenum=" << netenum_ << ">";
}
void NetENew::dump(ostream&o) const
{
o << "new <type>";
}
void NetENull::dump(ostream&o) const
{
o << "<null>";
}
void NetEProperty::dump(ostream&o) const
{
o << net_->name() << ".<" << pidx_ << ">";
}
void NetEScope::dump(ostream&o) const
{
o << "<scope=" << scope_path(scope_) << ">";
@ -1502,7 +1546,14 @@ void NetESelect::dump(ostream&o) const
else
o << "(0)";
o << "+:" << expr_width() << "]>";
o << "+:" << expr_width() << "]";
if (ivl_type_t nt = net_type()) {
o << " net_type=(" << *nt << ")";
} else {
o << " expr_type=" << expr_type();
}
o << ">";
}
void NetESFunc::dump(ostream&o) const
@ -1521,7 +1572,8 @@ void NetESignal::dump(ostream&o) const
o << "+";
o << name();
if (word_) o << "[word=" << *word_ << "]";
o << sig()->packed_dims();
vector<netrange_t>tmp = net_->net_type()->slice_dimensions();
o << tmp;
}
void NetETernary::dump(ostream&o) const
@ -1533,9 +1585,9 @@ void NetETernary::dump(ostream&o) const
void NetEUFunc::dump(ostream&o) const
{
o << func_->basename() << "(";
if (parms_.count() > 0) {
if (! parms_.empty()) {
parms_[0]->dump(o);
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) {
o << ", ";
parms_[idx]->dump(o);
}

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "discipline.h"

View File

@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*

View File

@ -12,9 +12,8 @@
#
# You should have received a copy of the GNU Library General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc.,
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.
#
SHELL = /bin/sh

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*

View File

@ -12,9 +12,8 @@
#
# You should have received a copy of the GNU Library General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc.,
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.
#
SHELL = /bin/sh

View File

@ -19,7 +19,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "cfparse.h"
@ -195,7 +195,6 @@ int yywrap()
void switch_to_command_file(const char *file)
{
char path[4096];
char *cp;
if (cmdfile_stack_ptr >= MAX_CMDFILE_DEPTH) {
fprintf(stderr, "Error: command files nested too deeply (%d) "
@ -213,6 +212,7 @@ void switch_to_command_file(const char *file)
* file name.
*/
if (file[0] != '/') {
char *cp;
strcpy(path, current_file);
cp = strrchr(path, '/');
if (cp == 0) strcpy(path, file); /* A base file. */

View File

@ -15,7 +15,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "globals.h"

View File

@ -17,7 +17,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*

View File

@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include <stddef.h>

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include <string.h>

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
@ -110,10 +110,10 @@ NetEBShift* NetEBShift::dup_expr() const
NetEConcat* NetEConcat::dup_expr() const
{
NetEConcat*dup = new NetEConcat(parms_.count(), repeat_);
NetEConcat*dup = new NetEConcat(parms_.size(), repeat_, expr_type_);
ivl_assert(*this, dup);
dup->set_line(*this);
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1)
if (parms_[idx]) {
NetExpr*tmp = parms_[idx]->dup_expr();
ivl_assert(*this, tmp);
@ -177,6 +177,24 @@ NetENetenum* NetENetenum::dup_expr() const
return 0;
}
NetENew* NetENew::dup_expr() const
{
ivl_assert(*this, 0);
return 0;
}
NetENull* NetENull::dup_expr() const
{
ivl_assert(*this, 0);
return 0;
}
NetEProperty* NetEProperty::dup_expr() const
{
ivl_assert(*this, 0);
return 0;
}
NetEScope* NetEScope::dup_expr() const
{
ivl_assert(*this, 0);
@ -232,9 +250,9 @@ NetETernary* NetETernary::dup_expr() const
NetEUFunc* NetEUFunc::dup_expr() const
{
NetEUFunc*tmp;
svector<NetExpr*> tmp_parms (parms_.count());
vector<NetExpr*> tmp_parms (parms_.size());
for (unsigned idx = 0 ; idx < tmp_parms.count() ; idx += 1) {
for (unsigned idx = 0 ; idx < tmp_parms.size() ; idx += 1) {
ivl_assert(*this, parms_[idx]);
tmp_parms[idx] = parms_[idx]->dup_expr();
}

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2000-2012 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / 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
@ -14,7 +15,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
@ -23,6 +24,7 @@
# include "netlist.h"
# include "netmisc.h"
# include "netstruct.h"
# include "netclass.h"
# include "compiler.h"
# include <cstdlib>
# include <iostream>
@ -163,12 +165,17 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
the search with "a.b". */
if (reg == 0 && path_.size() >= 2) {
pform_name_t use_path = path_;
method_name = peek_tail_name(use_path);
perm_string tmp_name = peek_tail_name(use_path);
use_path.pop_back();
symbol_search(this, des, scope, use_path, reg, par, eve);
if (reg && reg->struct_type() == 0) {
method_name = perm_string();
if (reg && reg->struct_type()) {
method_name = tmp_name;
} else if (reg && reg->class_type()) {
method_name = tmp_name;
} else {
reg = 0;
}
}
@ -185,7 +192,8 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
ivl_assert(*this, reg);
// We are processing the tail of a string of names. For
// example, the verilog may be "a.b.c", so we are processing
// "c" at this point.
// "c" at this point. (Note that if method_name is not nil,
// then this is "a.b.c.method" and "a.b.c" is a struct or class.)
const name_component_t&name_tail = path_.back();
// Use the last index to determine what kind of select
@ -202,7 +210,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
// slice. This is, in fact, an error in l-values. Detect the
// situation by noting if the index count is less than the
// array dimensions (unpacked).
if (reg->array_dimensions() > name_tail.index.size()) {
if (reg->unpacked_dimensions() > name_tail.index.size()) {
cerr << get_fileline() << ": error: Cannot assign to array "
<< path_ << ". Did you forget a word index?" << endl;
des->errors += 1;
@ -228,7 +236,17 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
return lv;
}
if (reg->array_dimensions() > 0)
if (reg->class_type() && !method_name.nil() && gn_system_verilog()) {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_class_member_(des, scope, lv, method_name);
return lv;
}
// Past this point, we should have taken care of the cases
// where the name is a member/method of a struct/class.
ivl_assert(*this, method_name.nil());
if (reg->unpacked_dimensions() > 0)
return elaborate_lval_net_word_(des, scope, reg);
// This must be after the array word elaboration above!
@ -257,9 +275,15 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
if (use_sel == index_component_t::SEL_BIT) {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_bit_(des, scope, lv);
return lv;
if (reg->darray_type()) {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_darray_bit_(des, scope, lv);
return lv;
} else {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_bit_(des, scope, lv);
return lv;
}
}
ivl_assert(*this, use_sel == index_component_t::SEL_NONE);
@ -278,6 +302,15 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
const name_component_t&name_tail = path_.back();
ivl_assert(*this, !name_tail.index.empty());
if (name_tail.index.size() < reg->unpacked_dimensions()) {
cerr << get_fileline() << ": error: Array " << reg->name()
<< " needs " << reg->unpacked_dimensions() << " indices,"
<< " but got only " << name_tail.index.size() << "." << endl;
des->errors += 1;
return 0;
}
// Make sure there are enough indices to address an array element.
const index_component_t&index_head = name_tail.index.front();
if (index_head.sel == index_component_t::SEL_PART) {
cerr << get_fileline() << ": error: cannot perform a part "
@ -286,47 +319,47 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
return 0;
}
ivl_assert(*this, index_head.sel == index_component_t::SEL_BIT);
ivl_assert(*this, index_head.msb != 0);
ivl_assert(*this, index_head.lsb == 0);
NetExpr*word = elab_and_eval(des, scope, index_head.msb, -1);
// Evaluate all the index expressions into an
// "unpacked_indices" array.
list<NetExpr*>unpacked_indices;
list<long> unpacked_indices_const;
bool flag = indices_to_expressions(des, scope, this,
name_tail.index, reg->unpacked_dimensions(),
false,
unpacked_indices,
unpacked_indices_const);
// If there is a non-zero base to the memory, then build an
// expression to calculate the canonical address.
if (long base = reg->array_first()) {
word = normalize_variable_array_base(word, base,
reg->array_count());
eval_expr(word);
NetExpr*canon_index = 0;
if (flag) {
ivl_assert(*this, unpacked_indices_const.size() == reg->unpacked_dimensions());
canon_index = normalize_variable_unpacked(reg, unpacked_indices_const);
if (canon_index == 0) {
cerr << get_fileline() << ": warning: "
<< "ignoring out of bounds l-value array access " << reg->name();
for (list<long>::const_iterator cur = unpacked_indices_const.begin()
; cur != unpacked_indices_const.end() ; ++cur) {
cerr << "[" << *cur << "]";
}
cerr << "." << endl;
}
} else {
ivl_assert(*this, unpacked_indices.size() == reg->unpacked_dimensions());
canon_index = normalize_variable_unpacked(reg, unpacked_indices);
}
NetAssign_*lv = new NetAssign_(reg);
lv->set_word(word);
lv->set_word(canon_index);
if (debug_elaborate)
cerr << get_fileline() << ": debug: Set array word=" << *word << endl;
cerr << get_fileline() << ": debug: Set array word=" << *canon_index << endl;
// Test for the case that the index is a constant, and is out
// of bounds. The "word" expression is the word index already
// converted to canonical address, so this just needs to check
// that the address is not too big.
if (NetEConst*word_const = dynamic_cast<NetEConst*>(word)) {
verinum word_val = word_const->value();
long index = word_val.as_long();
if (index < 0 || index >= (long) reg->array_count()) {
cerr << get_fileline() << ": warning: Constant array index "
<< (index + reg->array_first())
<< " is out of range for array "
<< reg->name() << "." << endl;
}
}
/* An array word may also have part selects applied to them. */
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
if (name_tail.index.size() > 1)
if (name_tail.index.size() > reg->unpacked_dimensions())
use_sel = name_tail.index.back().sel;
if (reg->get_scalar() &&
@ -335,7 +368,7 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
if (reg->data_type() == IVL_VT_REAL) cerr << "real";
else cerr << "scalar";
cerr << " array word: " << reg->name()
<< "[" << *word << "]" << endl;
<< "[" << *canon_index << "]" << endl;
des->errors += 1;
return 0;
}
@ -404,6 +437,22 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
lv->set_part(mux, lwid);
}
} else if (reg->data_type() == IVL_VT_STRING) {
// Special case: This is a select of a string
// variable. The target of the assignment is a character
// select of a string. Force the r-value to be an 8bit
// vector and set the "part" to be the character select
// expression. The code generator knows what to do with
// this.
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
<< "Bit select of string becomes character select." << endl;
}
if (mux)
lv->set_part(mux, 8);
else
lv->set_part(new NetEConst(verinum(lsb)), 8);
} else if (mux) {
// Non-constant bit mux. Correct the mux for the range
// of the vector, then set the l-value part select
@ -433,6 +482,26 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
return true;
}
bool PEIdent::elaborate_lval_darray_bit_(Design*des, NetScope*scope, NetAssign_*lv)const
{
const name_component_t&name_tail = path_.back();
ivl_assert(*this, !name_tail.index.empty());
// For now, only support single-dimension dynamic arrays.
ivl_assert(*this, name_tail.index.size() == 1);
const index_component_t&index_tail = name_tail.index.back();
ivl_assert(*this, index_tail.msb != 0);
ivl_assert(*this, index_tail.lsb == 0);
// Evaluate the select expression...
NetExpr*mux = elab_and_eval(des, scope, index_tail.msb, -1);
lv->set_word(mux);
return true;
}
bool PEIdent::elaborate_lval_net_part_(Design*des,
NetScope*scope,
NetAssign_*lv) const
@ -455,7 +524,7 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
NetNet*reg = lv->sig();
ivl_assert(*this, reg);
const list<NetNet::range_t>&packed = reg->packed_dims();
const vector<netrange_t>&packed = reg->packed_dims();
// Part selects cannot select slices. So there must be enough
// prefix_indices to get all the way to the final dimension.
@ -544,14 +613,14 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
long lsv = base_c->value().as_long();
long offset = 0;
// Get the signal range.
const list<NetNet::range_t>&packed = reg->packed_dims();
const vector<netrange_t>&packed = reg->packed_dims();
ivl_assert(*this, packed.size() == prefix_indices.size()+1);
// We want the last range, which is where we work.
const NetNet::range_t&rng = packed.back();
if (((rng.msb < rng.lsb) &&
const netrange_t&rng = packed.back();
if (((rng.get_msb() < rng.get_lsb()) &&
use_sel == index_component_t::SEL_IDX_UP) ||
((rng.msb > rng.lsb) &&
((rng.get_msb() > rng.get_lsb()) &&
use_sel == index_component_t::SEL_IDX_DO)) {
offset = -wid + 1;
}
@ -563,7 +632,7 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
if (warn_ob_select) {
if (rel_base < 0) {
cerr << get_fileline() << ": warning: " << reg->name();
if (reg->array_dimensions() > 0) cerr << "[]";
if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << "[" << lsv;
if (use_sel == index_component_t::SEL_IDX_UP) {
cerr << "+:";
@ -574,7 +643,7 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
}
if (rel_base + wid > reg->vector_width()) {
cerr << get_fileline() << ": warning: " << reg->name();
if (reg->array_dimensions() > 0) cerr << "[]";
if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << "[" << lsv;
if (use_sel == index_component_t::SEL_IDX_UP) {
cerr << "+:";
@ -587,7 +656,7 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
} else {
if (warn_ob_select) {
cerr << get_fileline() << ": warning: " << reg->name();
if (reg->array_dimensions() > 0) cerr << "[]";
if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << "['bx";
if (use_sel == index_component_t::SEL_IDX_UP) {
cerr << "+:";
@ -621,17 +690,49 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
return true;
}
bool PEIdent::elaborate_lval_net_packed_member_(Design*des,
NetScope*,
bool PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*,
NetAssign_*lv,
const perm_string&method_name) const
{
if (debug_elaborate) {
cerr << get_fileline() << ": elaborate_lval_net_class_member_: "
<< "l-value is property " << method_name
<< " of " << lv->sig()->name() << "." << endl;
}
netclass_t*class_type = lv->sig()->class_type();
ivl_assert(*this, class_type);
/* Make sure the property is really present in the class. If
not, then generate an error message and return an error. */
const ivl_type_s*ptype = class_type->get_property(method_name);
if (ptype == 0) {
cerr << get_fileline() << ": error: Class " << class_type->get_name()
<< " does not have a property " << method_name << "." << endl;
des->errors += 1;
return false;
}
lv->set_property(method_name);
return true;
}
bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
NetAssign_*lv,
const perm_string&member_name) const
{
NetNet*reg = lv->sig();
ivl_assert(*this, reg);
netstruct_t*struct_type = reg->struct_type();
const netstruct_t*struct_type = reg->struct_type();
ivl_assert(*this, struct_type);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: elaborate lval packed member: "
<< "path_=" << path_ << endl;
}
if (! struct_type->packed()) {
cerr << get_fileline() << ": sorry: Only packed structures "
<< "are supported in l-value." << endl;
@ -639,6 +740,27 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des,
return false;
}
// Shouldn't be seeing unpacked arrays of packed structs...
ivl_assert(*this, reg->unpacked_dimensions() == 0);
// This is a packed member, so the name is of the form
// "a.b[...].c[...]" which means that the path_ must have at
// least 2 components. We are processing "c[...]" at that
// point (otherwise known as member_name) so we'll save a
// reference to it in name_tail. We are also processing "b[]"
// so save that as name_base.
ivl_assert(*this, path_.size() >= 2);
pform_name_t::const_reverse_iterator name_idx = path_.rbegin();
ivl_assert(*this, name_idx->name == member_name);
const name_component_t&name_tail = *name_idx;
++ name_idx;
const name_component_t&name_base = *name_idx;
// Calculate the offset within the packed structure of the
// member, and any indices. We will add in the offset of the
// struct into the packed array later.
unsigned long off;
const netstruct_t::member_t* member = struct_type->packed_member(member_name, off);
@ -649,8 +771,90 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des,
return false;
}
lv->set_part(new NetEConst(verinum(off)), member->width());
return true;
unsigned long use_width = member->width();
if (name_tail.index.size() > member->packed_dims.size()) {
cerr << get_fileline() << ": error: Too many index expressions for member." << endl;
des->errors += 1;
return false;
}
// Get the index component type. At this point, we only
// support bit select or none.
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
if (!name_tail.index.empty())
use_sel = name_tail.index.back().sel;
ivl_assert(*this, use_sel == index_component_t::SEL_NONE || use_sel == index_component_t::SEL_BIT);
if (! name_tail.index.empty()) {
// Evaluate all but the last index expression, into prefix_indices.
list<long>prefix_indices;
bool rc = evaluate_index_prefix(des, scope, prefix_indices, name_tail.index);
ivl_assert(*this, rc);
// Evaluate the last index expression into a constant long.
NetExpr*texpr = elab_and_eval(des, scope, name_tail.index.back().msb, -1, true);
long tmp;
if (texpr == 0 || !eval_as_long(tmp, texpr)) {
cerr << get_fileline() << ": error: "
"Array index expressions must be constant here." << endl;
des->errors += 1;
return false;
}
delete texpr;
// Now use the prefix_to_slice function to calculate the
// offset and width of the addressed slice of the member.
long loff;
unsigned long lwid;
prefix_to_slice(member->packed_dims, prefix_indices, tmp, loff, lwid);
off += loff;
use_width = lwid;
}
// The dimenions in the expression must match the packed
// dimensions that are declared for the variable. For example,
// if foo is a packed array of struct, then this expression
// must be "b[n][m]" with the right number of dimensions to
// match the declaration of "b".
// Note that one of the packed dimensions is the packed struct
// itself.
ivl_assert(*this, name_base.index.size()+1 == reg->packed_dimensions());
// Generate an expression that takes the input array of
// expressions and generates a canonical offset into the
// packed array.
NetExpr*packed_base = 0;
if (reg->packed_dimensions() > 1) {
list<index_component_t>tmp_index = name_base.index;
index_component_t member_select;
member_select.sel = index_component_t::SEL_BIT;
member_select.msb = new PENumber(new verinum(off));
tmp_index.push_back(member_select);
packed_base = collapse_array_indices(des, scope, reg, tmp_index);
}
long tmp;
if (packed_base && eval_as_long(tmp, packed_base)) {
off = tmp;
delete packed_base;
packed_base = 0;
}
if (packed_base == 0) {
lv->set_part(new NetEConst(verinum(off)), use_width);
return true;
}
// Oops, packed_base is not fully evaluated, so I don't know
// yet what to do with it.
cerr << get_fileline() << ": internal error: "
<< "I don't know how to handle this index expression? " << *packed_base << endl;
ivl_assert(*this, 0);
return false;
}
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 1999-2012 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / 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
@ -14,7 +15,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
@ -23,6 +24,7 @@
# include "netlist.h"
# include "netmisc.h"
# include "netstruct.h"
# include "netvector.h"
# include "compiler.h"
# include <cstdlib>
@ -97,12 +99,12 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
concat operator from most significant to least significant,
which is the order they are given in the concat list. */
netvector_t*tmp2_vec = new netvector_t(nets[0]->data_type(),width-1,0);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, width);
NetNet::IMPLICIT, tmp2_vec);
/* Assume that the data types of the nets are all the same, so
we can take the data type of any, the first will do. */
osig->data_type(nets[0]->data_type());
osig->local_flag(true);
osig->set_line(*this);
@ -153,8 +155,6 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
assert(width == 0);
}
osig->data_type(nets[0]->data_type());
osig->local_flag(true);
return osig;
}
@ -208,7 +208,7 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
// Only treat as part/bit selects any index that is beyond the
// word selects for an array. This is not an array, then
// dimensions==0 and any index is treated as a select.
if (name_tail.index.size() <= sig->array_dimensions()) {
if (name_tail.index.size() <= sig->unpacked_dimensions()) {
midx = sig->vector_width()-1;
lidx = 0;
return true;
@ -247,7 +247,7 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
if (warn_ob_select) {
cerr << get_fileline() << ": warning: "
<< sig->name();
if (sig->array_dimensions() > 0) cerr << "[]";
if (sig->unpacked_dimensions() > 0) cerr << "[]";
cerr << "['bx";
if (index_tail.sel ==
index_component_t::SEL_IDX_UP) {
@ -279,7 +279,7 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
/* Warn about an indexed part select that is out of range. */
if (warn_ob_select && (lidx < 0)) {
cerr << get_fileline() << ": warning: " << sig->name();
if (sig->array_dimensions() > 0) cerr << "[]";
if (sig->unpacked_dimensions() > 0) cerr << "[]";
cerr << "[" << midx_val;
if (index_tail.sel == index_component_t::SEL_IDX_UP) {
cerr << "+:";
@ -290,7 +290,7 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
}
if (warn_ob_select && (midx >= (long)sig->vector_width())) {
cerr << get_fileline() << ": warning: " << sig->name();
if (sig->array_dimensions() > 0) {
if (sig->unpacked_dimensions() > 0) {
cerr << "[]";
}
cerr << "[" << midx_val;
@ -337,16 +337,11 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
if (midx_tmp >= (long)sig->vector_width() || lidx_tmp < 0) {
cerr << get_fileline() << ": warning: Part select "
<< sig->name();
if (sig->array_dimensions() > 0) {
if (sig->unpacked_dimensions() > 0) {
cerr << "[]";
}
cerr << "[" << msb << ":" << lsb
<< "] is out of range." << endl;
#if 0
midx_tmp = sig->vector_width() - 1;
lidx_tmp = 0;
des->errors += 1;
#endif
}
/* This is completely out side the signal so just skip it. */
if (lidx_tmp >= (long)sig->vector_width() || midx_tmp < 0) {
@ -359,20 +354,31 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
}
case index_component_t::SEL_BIT:
if (name_tail.index.size() > sig->array_dimensions()) {
if (name_tail.index.size() > sig->unpacked_dimensions()) {
long msb;
bool bit_defined_flag;
/* bool flag = */ calculate_bits_(des, scope, msb, bit_defined_flag);
ivl_assert(*this, bit_defined_flag);
midx = sig->sb_to_idx(prefix_indices, msb);
if (midx >= (long)sig->vector_width()) {
cerr << get_fileline() << ": error: Index " << sig->name()
<< "[" << msb << "] is out of range."
<< endl;
des->errors += 1;
midx = 0;
if (prefix_indices.size()+2 <= sig->packed_dims().size()) {
long tmp_loff;
unsigned long tmp_lwid;
bool rcl = sig->sb_to_slice(prefix_indices, msb,
tmp_loff, tmp_lwid);
ivl_assert(*this, rcl);
midx = tmp_loff + tmp_lwid - 1;
lidx = tmp_loff;
} else {
midx = sig->sb_to_idx(prefix_indices, msb);
if (midx >= (long)sig->vector_width()) {
cerr << get_fileline() << ": error: Index " << sig->name()
<< "[" << msb << "] is out of range."
<< endl;
des->errors += 1;
midx = 0;
}
lidx = midx;
}
lidx = midx;
} else {
cerr << get_fileline() << ": internal error: "
@ -412,18 +418,30 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
return 0;
}
// Break the path_ into the tail name and the prefix. For
// example, a name "a.b.c" is broken into name_tail="c" and
// path_prefix="a.b".
const name_component_t&path_tail = path_.back();
pform_name_t path_prefix = path_;
path_prefix.pop_back();
/* If the signal is not found, check to see if this is a
member of a struct. Take the name of the form "a.b.member",
remove the member and store it into method_name, and retry
the search with "a.b". */
if (sig == 0 && path_.size() >= 2) {
pform_name_t use_path = path_;
method_name = peek_tail_name(use_path);
use_path.pop_back();
symbol_search(this, des, scope, use_path, sig, par, eve);
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
"Symbol not found, try again with path_prefix=" << path_prefix
<< " and method_name=" << path_tail.name << endl;
}
method_name = path_tail.name;
symbol_search(this, des, scope, path_prefix, sig, par, eve);
// Whoops, not a struct signal, so give up on this avenue.
if (sig && sig->struct_type() == 0) {
cerr << get_fileline() << ": XXXXX: sig=" << sig->name()
<< " is found, but not a struct with member " << method_name << endl;
method_name = perm_string();
sig = 0;
}
@ -460,19 +478,19 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
unsigned midx = sig->vector_width()-1, lidx = 0;
// The default word select is the first.
long widx = 0;
// The widx_val is the word select as entered in the source
// code. It's used for error messages.
long widx_val = 0;
const name_component_t&name_tail = path_.back();
list<long> unpacked_indices_const;
netstruct_t*struct_type = 0;
const netstruct_t*struct_type = 0;
if ((struct_type = sig->struct_type()) && !method_name.nil()) {
// Detect the variable is a structure and there was a
// method name detected.
// method name detected. We've already found that
// the path_ is <>.sig.method_name and signal
// (NetNet). We also know that sig is struct_type(), so
// look for a method named method_name.
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
<< "Signal " << sig->name() << " is a structure, "
<< "try to match member " << method_name << endl;
@ -480,58 +498,133 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
const struct netstruct_t::member_t*member = struct_type->packed_member(method_name, member_off);
ivl_assert(*this, member);
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
<< "Member " << method_name
<< " has packed dimensions " << member->packed_dims << "." << endl;
cerr << get_fileline() << ": : "
<< "Tail name has " << path_tail.index.size() << " indices." << endl;
}
// Rewrite a member select of a packed structure as a
// part select of the base variable.
lidx = member_off;
midx = lidx + member->width() - 1;
} else if (sig->array_dimensions() > 0) {
// The dimensions of the tail of the prefix must match
// the dimensions of the signal at this point. (The sig
// has a packed dimension for the packed struct size.)
// For example, if the path_=a[<m>][<n>].member, then
// sig must have 3 packed dimenions: one for the struct
// members and two actual packed dimensions.
ivl_assert(*this, path_prefix.back().index.size()+1 == sig->packed_dimensions());
if (name_tail.index.empty()) {
cerr << get_fileline() << ": error: array " << sig->name()
<< " must be used with an index." << endl;
// Elaborate an expression from the packed indices and
// the member offset (into the structure) to get a
// canonical expression into the packed signal vector.
NetExpr*packed_base = 0;
if (sig->packed_dimensions() > 1) {
list<index_component_t>tmp_index = path_prefix.back().index;
index_component_t member_select;
member_select.sel = index_component_t::SEL_BIT;
member_select.msb = new PENumber(new verinum(member_off));
tmp_index.push_back(member_select);
packed_base = collapse_array_indices(des, scope, sig, tmp_index);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
<< "packed_base expression = " << *packed_base << endl;
}
}
long tmp;
if (packed_base && eval_as_long(tmp, packed_base)) {
lidx = tmp;
midx = lidx + member->width() - 1;
delete packed_base;
packed_base = 0;
}
// Currently, only support const dimensions here.
ivl_assert(*this, packed_base == 0);
// Now the lidx/midx values get us to the member. Next
// up, deal with bit/part selects from the member
// itself.
ivl_assert(*this, member->packed_dims.size() <= 1);
ivl_assert(*this, path_tail.index.size() <= 1);
if (! path_tail.index.empty()) {
long tmp_off;
unsigned long tmp_wid;
const index_component_t&tail_sel = path_tail.index.back();
ivl_assert(*this, tail_sel.sel == index_component_t::SEL_PART || tail_sel.sel == index_component_t::SEL_BIT);
bool rc = calculate_part(this, des, scope, tail_sel, tmp_off, tmp_wid);
ivl_assert(*this, rc);
if (debug_elaborate)
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
<< "tmp_off=" << tmp_off << ", tmp_wid=" << tmp_wid << endl;
lidx += tmp_off;
midx = lidx + tmp_wid - 1;
}
} else if (sig->unpacked_dimensions() > 0) {
// Make sure there are enough indices to address an array element.
if (path_tail.index.size() < sig->unpacked_dimensions()) {
cerr << get_fileline() << ": error: Array " << path()
<< " needs " << sig->unpacked_dimensions() << " indices,"
<< " but got only " << path_tail.index.size() << "." << endl;
des->errors += 1;
return 0;
}
const index_component_t&index_head = name_tail.index.front();
if (index_head.sel == index_component_t::SEL_PART) {
cerr << get_fileline() << ": error: cannot perform a part "
<< "select on array " << sig->name() << "." << endl;
des->errors += 1;
return 0;
}
ivl_assert(*this, index_head.sel == index_component_t::SEL_BIT);
NetExpr*tmp_ex = elab_and_eval(des, scope, index_head.msb, -1, true);
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
if (!tmp) {
// Evaluate all the index expressions into an
// "unpacked_indices" array.
list<NetExpr*>unpacked_indices;
bool flag = indices_to_expressions(des, scope, this,
path_tail.index, sig->unpacked_dimensions(),
true,
unpacked_indices,
unpacked_indices_const);
// Note that !flag includes that there were any other
// elaboration errors generating the unpacked_indices list.
if (!flag) {
cerr << get_fileline() << ": error: array " << sig->name()
<< " index must be a constant in this context." << endl;
des->errors += 1;
return 0;
}
widx_val = tmp->value().as_long();
if (sig->array_index_is_valid(widx_val))
widx = sig->array_index_to_address(widx_val);
else
NetExpr*canon_index = 0;
ivl_assert(*this, unpacked_indices_const.size() == sig->unpacked_dimensions());
canon_index = normalize_variable_unpacked(sig, unpacked_indices_const);
if (canon_index == 0) {
// Normalize detected an out-of-bounds
// index. Indicate that by setting the generated
// widx to -1.
widx = -1;
delete tmp_ex;
} else {
NetEConst*canon_const = dynamic_cast<NetEConst*>(canon_index);
ivl_assert(*this, canon_const);
widx = canon_const->value().as_long();
delete canon_index;
}
if (debug_elaborate)
cerr << get_fileline() << ": debug: Use [" << widx << "]"
<< " to index l-value array." << endl;
/* The array has a part/bit select at the end. */
if (name_tail.index.size() > sig->array_dimensions()) {
if (path_tail.index.size() > sig->unpacked_dimensions()) {
if (sig->get_scalar()) {
cerr << get_fileline() << ": error: "
<< "can not select part of ";
if (sig->data_type() == IVL_VT_REAL) cerr << "real";
else cerr << "scalar";
cerr << " array word: " << sig->name()
<< "[" << widx_val << "]" << endl;
<< as_indices(unpacked_indices_const) << endl;
des->errors += 1;
return 0;
}
@ -550,7 +643,8 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
midx = midx_tmp;
lidx = lidx_tmp;
}
} else if (!name_tail.index.empty()) {
} else if (!path_tail.index.empty()) {
if (sig->get_scalar()) {
cerr << get_fileline() << ": error: "
<< "can not select part of ";
@ -590,15 +684,16 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
if (widx < 0 || widx >= (long) sig->pin_count()) {
cerr << get_fileline() << ": warning: ignoring out of "
"bounds l-value array access "
<< sig->name() << "[" << widx_val << "]." << endl;
<< sig->name() << as_indices(unpacked_indices_const) << "." << endl;
return 0;
}
netvector_t*tmp2_vec = new netvector_t(sig->data_type(),
sig->vector_width()-1,0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
sig->type(), sig->vector_width());
sig->type(), tmp2_vec);
tmp->set_line(*this);
tmp->local_flag(true);
tmp->data_type( sig->data_type() );
connect(sig->pin(widx), tmp->pin(0));
sig = tmp;
}
@ -622,10 +717,11 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
<< " wid=" << subnet_wid <<"]"
<< endl;
netvector_t*tmp2_vec = new netvector_t(sig->data_type(),
subnet_wid-1,0);
NetNet*subsig = new NetNet(sig->scope(),
sig->scope()->local_symbol(),
NetNet::WIRE, subnet_wid);
subsig->data_type( sig->data_type() );
NetNet::WIRE, tmp2_vec);
subsig->local_flag(true);
subsig->set_line(*this);
@ -675,9 +771,9 @@ NetNet* PEIdent::elaborate_bi_net(Design*des, NetScope*scope) const
* instantiation (PGModule::elaborate_mod_) to get NetNet objects for
* the port.
*/
NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
NetNet* PEIdent::elaborate_subport(Design*des, NetScope*scope) const
{
assert(scope->type() == NetScope::MODULE);
ivl_assert(*this, scope->type() == NetScope::MODULE);
NetNet*sig = des->find_signal(scope, path_);
if (sig == 0) {
cerr << get_fileline() << ": error: no wire/reg " << path_
@ -732,17 +828,17 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
/* If this is a part select of the entire signal (or no part
select at all) then we're done. */
if ((lidx == 0) && (midx == (long)sig->vector_width()-1)) {
scope->add_module_port(sig);
scope->add_module_port_net(sig);
return sig;
}
unsigned swid = abs(midx - lidx) + 1;
ivl_assert(*this, swid > 0 && swid < sig->vector_width());
netvector_t*tmp2_vec = new netvector_t(sig->data_type(),swid-1,0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, swid);
NetNet::WIRE, tmp2_vec);
tmp->port_type(sig->port_type());
tmp->data_type(sig->data_type());
tmp->set_line(*this);
tmp->local_flag(true);
NetNode*ps = 0;
@ -779,7 +875,7 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
ps->set_line(*this);
des->add_node(ps);
scope->add_module_port(sig);
scope->add_module_port_net(sig);
return sig;
}

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
@ -33,8 +33,10 @@
*/
# include "Module.h"
# include "PEvent.h"
# include "PClass.h"
# include "PExpr.h"
# include "PEvent.h"
# include "PClass.h"
# include "PGate.h"
# include "PGenerate.h"
# include "PTask.h"
@ -42,6 +44,7 @@
# include "Statement.h"
# include "AStatement.h"
# include "netlist.h"
# include "netclass.h"
# include "netenum.h"
# include "util.h"
# include <typeinfo>
@ -51,7 +54,9 @@
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)
const LexicalScope::param_expr_t&cur,
bool is_annotatable,
bool local_flag)
{
NetScope::range_t*range_list = 0;
for (LexicalScope::range_t*range = cur.range ; range ; range = range->next) {
@ -87,8 +92,9 @@ static void collect_parm_item_(Design*des, NetScope*scope, perm_string name,
range_list = tmp;
}
scope->set_parameter(name, cur.expr, cur.type, cur.msb, cur.lsb,
cur.signed_flag, range_list, cur);
scope->set_parameter(name, is_annotatable, cur.expr, cur.type, cur.msb,
cur.lsb, cur.signed_flag, local_flag, range_list, cur);
}
static void collect_scope_parameters_(Design*des, NetScope*scope,
@ -106,7 +112,7 @@ static void collect_scope_parameters_(Design*des, NetScope*scope,
des->errors += 1;
}
collect_parm_item_(des, scope, (*cur).first, (*cur).second);
collect_parm_item_(des, scope, (*cur).first, (*cur).second, false, false);
}
}
@ -125,7 +131,26 @@ static void collect_scope_localparams_(Design*des, NetScope*scope,
des->errors += 1;
}
collect_parm_item_(des, scope, (*cur).first, (*cur).second);
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)
{
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);
}
}
@ -159,12 +184,12 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
verinum max_value (0);
if (enum_type->signed_flag) {
min_value = v_not((pow(verinum(2),
verinum(use_enum->base_width()-1)))) +
verinum(use_enum->packed_width()-1)))) +
one_value;
max_value = pow(verinum(2), verinum(use_enum->base_width()-1)) -
max_value = pow(verinum(2), verinum(use_enum->packed_width()-1)) -
one_value;
} else {
max_value = pow(verinum(2), verinum(use_enum->base_width())) -
max_value = pow(verinum(2), verinum(use_enum->packed_width())) -
one_value;
}
min_value.has_sign(true);
@ -227,15 +252,15 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
// The values are explicitly sized to the width of the
// base type of the enumeration.
verinum tmp_val (0);
if (cur_value.len() < use_enum->base_width()) {
if (cur_value.len() < (unsigned long)use_enum->packed_width()) {
// Pad the current value if it is narrower than the final
// width of the enum.
tmp_val = pad_to_width (cur_value, use_enum->base_width());
tmp_val = pad_to_width (cur_value, use_enum->packed_width());
tmp_val.has_len(true);
} else {
// Truncate an oversized value. We report out of bound
// values above. This may create duplicates.
tmp_val = verinum(cur_value, use_enum->base_width());
tmp_val = verinum(cur_value, use_enum->packed_width());
}
tmp_val.has_sign(enum_type->signed_flag);
@ -264,6 +289,30 @@ static void elaborate_scope_enumerations(Design*des, NetScope*scope,
}
}
static void elaborate_scope_class(Design*des, NetScope*scope,
PClass*pclass)
{
class_type_t*use_type = pclass->type;
netclass_t*use_class = new netclass_t(use_type->name);
for (map<perm_string, data_type_t*>::iterator cur = use_type->properties.begin()
; cur != use_type->properties.end() ; ++ cur) {
ivl_type_s*tmp = cur->second->elaborate_type(des, scope);
use_class->set_property(cur->first, tmp);
}
scope->add_class(use_class);
}
static void elaborate_scope_classes(Design*des, NetScope*scope,
const map<perm_string,PClass*>&classes)
{
for (map<perm_string,PClass*>::const_iterator cur = classes.begin()
; cur != classes.end() ; ++ cur) {
elaborate_scope_class(des, scope, cur->second);
}
}
static void replace_scope_parameters_(NetScope*scope, const LineInfo&loc,
const Module::replace_t&replacements)
{
@ -469,6 +518,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
collect_scope_localparams_(des, scope, localparams);
collect_scope_specparams_(des, scope, specparams);
// Run parameter replacements that were collected from the
// containing scope and meant for me.
@ -476,6 +527,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
elaborate_scope_enumerations(des, scope, enum_sets);
elaborate_scope_classes(des, scope, classes);
// Run through the defparams for this module and save the result
// in a table for later final override.
@ -519,6 +572,19 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
elaborate_scope_funcs(des, scope, funcs);
// Look for implicit modules and implicit gates for them.
for (map<perm_string,Module*>::iterator cur = nested_modules.begin()
; cur != nested_modules.end() ; ++cur) {
// Skip modules that must be explicitly instantiated.
if (cur->second->port_count() > 0)
continue;
PGModule*nested_gate = new PGModule(cur->second, cur->second->mod_name());
nested_gate->set_line(*cur->second);
gates_.push_back(nested_gate);
}
// Gates include modules, which might introduce new scopes, so
// scan all of them to create those scopes.
@ -708,7 +774,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
genvar_verinum);
// The file and line information should really come
// from the genvar statement, not the for loop.
scope->set_localparam(loop_index, gp, *this);
scope->set_parameter(loop_index, gp, *this);
if (debug_scopes)
cerr << get_fileline() << ": debug: "
<< "Create implicit localparam "
@ -1054,6 +1120,21 @@ void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
scope->add_genvar((*cur).first, (*cur).second);
}
// Scan the localparams in this scope, and store the information
// needed to evaluate the parameter expressions. The expressions
// will be evaluated later, once all parameter overrides for this
// module have been done.
collect_scope_localparams_(des, scope, localparams);
// Run through the defparams for this scope and save the result
// in a table for later final override.
typedef list<PGenerate::named_expr_t>::const_iterator defparms_iter_t;
for (defparms_iter_t cur = defparms.begin()
; cur != defparms.end() ; ++ cur ) {
scope->defparams.push_back(make_pair(cur->first, cur->second));
}
// Scan the generated scope for nested generate schemes,
// and *generate* new scopes, which is slightly different
// from simple elaboration.
@ -1064,12 +1145,6 @@ void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
(*cur) -> generate_scope(des, scope);
}
// Scan the localparams in this scope, and store the information
// needed to evaluate the parameter expressions. The expressions
// will be evaluated later, once all parameter overrides for this
// module have been done.
collect_scope_localparams_(des, scope, localparams);
// Scan through all the task and function declarations in this
// scope.
elaborate_scope_tasks(des, scope, tasks);
@ -1307,8 +1382,12 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
<< "." << endl;
}
// Create the new scope as a MODULE with my name.
NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE);
// Create the new scope as a MODULE with my name. Note
// that if this is a nested module, mark it thus so that
// scope searches will continue into the parent scope.
NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE,
bound_type_? true : false,
mod->program_block);
my_scope->set_line(get_file(), mod->get_file(),
get_lineno(), mod->get_lineno());
my_scope->set_module_name(mod->mod_name());
@ -1525,7 +1604,9 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
<< "Elaborate block scope " << use_name
<< " within " << scope_path(scope) << endl;
my_scope = new NetScope(scope, use_name, bl_type_==BL_PAR
// The scope type is begin-end or fork-join. The
// sub-types of fork-join are not interesting to the scope.
my_scope = new NetScope(scope, use_name, bl_type_!=BL_SEQ
? NetScope::FORK_JOIN
: NetScope::BEGIN_END);
my_scope->set_line(get_file(), get_lineno());

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2000-2012 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / 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
@ -14,11 +15,12 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
# include <typeinfo>
# include <cstdlib>
# include <iostream>
@ -32,10 +34,17 @@
# include "compiler.h"
# include "netlist.h"
# include "netmisc.h"
# include "netclass.h"
# include "netenum.h"
# include "netstruct.h"
# include "netvector.h"
# include "netdarray.h"
# include "netparray.h"
# include "util.h"
# include "ivl_assert.h"
using namespace std;
static bool get_const_argument(NetExpr*exp, verinum&res)
{
switch (exp->expr_type()) {
@ -388,7 +397,6 @@ bool PGenerate::elaborate_sig_direct_(Design*des, NetScope*container) const
; cur != generate_schemes.end() ; ++ cur ) {
PGenerate*item = *cur;
if (item->scheme_type == PGenerate::GS_CASE) {
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t icur = item->generate_schemes.begin()
; icur != item->generate_schemes.end() ; ++ icur ) {
PGenerate*case_item = *icur;
@ -479,6 +487,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
}
NetNet*ret_sig = 0;
netvector_t*ret_vec = 0;
/* Create the signals/variables of the return value and write
them into the function scope. */
@ -514,50 +523,51 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
des->errors += 1;
}
list<NetNet::range_t> packed;
packed.push_back(NetNet::range_t(mnum, lnum));
ret_sig = new NetNet(scope, fname, NetNet::REG, packed);
ret_sig->set_scalar(false);
vector<netrange_t> packed;
packed.push_back(netrange_t(mnum, lnum));
ret_vec = new netvector_t(packed, IVL_VT_LOGIC);
ret_vec->set_signed(return_type_.type == PTF_REG_S);
ret_vec->set_scalar(false);
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
} else {
ret_sig = new NetNet(scope, fname, NetNet::REG);
ret_sig->set_scalar(true);
ret_vec = new netvector_t(IVL_VT_LOGIC);
ret_vec->set_signed(return_type_.type == PTF_REG_S);
ret_vec->set_scalar(true);
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
}
ret_sig->set_line(*this);
ret_sig->set_signed(return_type_.type == PTF_REG_S);
ret_sig->port_type(NetNet::POUTPUT);
ret_sig->data_type(IVL_VT_LOGIC);
break;
case PTF_INTEGER:
ret_sig = new NetNet(scope, fname, NetNet::REG, integer_width);
ret_vec = new netvector_t(IVL_VT_LOGIC, integer_width-1,0);
ret_vec->set_signed(true);
ret_vec->set_isint(true);
ret_vec->set_scalar(false);
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
ret_sig->set_line(*this);
ret_sig->set_signed(true);
ret_sig->set_isint(true);
ret_sig->set_scalar(false);
ret_sig->port_type(NetNet::POUTPUT);
ret_sig->data_type(IVL_VT_LOGIC);
break;
case PTF_TIME:
ret_sig = new NetNet(scope, fname, NetNet::REG, 64);
ret_vec = new netvector_t(IVL_VT_LOGIC, 64-1,0);
ret_vec->set_isint(false);
ret_vec->set_scalar(false);
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
ret_sig->set_line(*this);
ret_sig->set_signed(false);
ret_sig->set_isint(false);
ret_sig->set_scalar(false);
ret_sig->port_type(NetNet::POUTPUT);
ret_sig->data_type(IVL_VT_LOGIC);
break;
case PTF_REAL:
case PTF_REALTIME:
ret_sig = new NetNet(scope, fname, NetNet::REG, 1);
ret_vec = new netvector_t(IVL_VT_REAL);
ret_vec->set_signed(true);
ret_vec->set_isint(false);
ret_vec->set_scalar(true);
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
ret_sig->set_line(*this);
ret_sig->set_signed(true);
ret_sig->set_isint(false);
ret_sig->set_scalar(true);
ret_sig->port_type(NetNet::POUTPUT);
ret_sig->data_type(IVL_VT_REAL);
break;
case PTF_ATOM2:
@ -592,13 +602,13 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
use_wid = mnum - lnum + 1;
}
ret_sig = new NetNet(scope, fname, NetNet::REG, use_wid);
ret_vec = new netvector_t(IVL_VT_BOOL, use_wid-1, 0);
ret_vec->set_isint(true);
ret_vec->set_scalar(false);
ret_vec->set_signed(return_type_.type == PTF_ATOM2_S? true : false);
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
ret_sig->set_line(*this);
ret_sig->set_signed(return_type_.type == PTF_ATOM2_S? true : false);
ret_sig->set_isint(true);
ret_sig->set_scalar(false);
ret_sig->port_type(NetNet::POUTPUT);
ret_sig->data_type(IVL_VT_BOOL);
break;
case PTF_STRING:
@ -624,7 +634,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
}
}
svector<NetNet*>ports (ports_? ports_->count() : 0);
vector<NetNet*>ports (ports_? ports_->count() : 0);
if (ports_)
for (unsigned idx = 0 ; idx < ports_->count() ; idx += 1) {
@ -813,64 +823,18 @@ void PWhile::elaborate_sig(Design*des, NetScope*scope) const
statement_->elaborate_sig(des, scope);
}
static netstruct_t* elaborate_struct_type(Design*des, NetScope*scope,
struct_type_t*struct_type)
{
netstruct_t*res = new netstruct_t;
res->packed(struct_type->packed_flag);
for (list<struct_member_t*>::iterator cur = struct_type->members->begin()
; cur != struct_type->members->end() ; ++ cur) {
struct_member_t*curp = *cur;
long use_msb = 0;
long use_lsb = 0;
if (curp->range.get() && ! curp->range->empty()) {
ivl_assert(*curp, curp->range->size() == 1);
pform_range_t&rangep = curp->range->front();
PExpr*msb_pex = rangep.first;
PExpr*lsb_pex = rangep.second;
NetExpr*tmp = elab_and_eval(des, scope, msb_pex, -2, true);
ivl_assert(*curp, tmp);
bool rc = eval_as_long(use_msb, tmp);
ivl_assert(*curp, rc);
tmp = elab_and_eval(des, scope, lsb_pex, -2, true);
ivl_assert(*curp, tmp);
rc = eval_as_long(use_lsb, tmp);
ivl_assert(*curp, rc);
}
for (list<decl_assignment_t*>::iterator name = curp->names->begin()
; name != curp->names->end() ; ++ name) {
decl_assignment_t*namep = *name;
netstruct_t::member_t memb;
memb.name = namep->name;
memb.type = curp->type;
memb.msb = use_msb;
memb.lsb = use_lsb;
res->append_member(memb);
}
}
return res;
}
static bool evaluate_ranges(Design*des, NetScope*scope,
list<NetNet::range_t>&llist,
vector<netrange_t>&llist,
const list<pform_range_t>&rlist)
{
bool bad_msb = false, bad_lsb = false;
for (list<pform_range_t>::const_iterator cur = rlist.begin()
; cur != rlist.end() ; ++cur) {
NetNet::range_t lrng;
long use_msb, use_lsb;
NetExpr*texpr = elab_and_eval(des, scope, cur->first, -1, true);
if (! eval_as_long(lrng.msb, texpr)) {
if (! eval_as_long(use_msb, texpr)) {
cerr << cur->first->get_fileline() << ": error: "
"Range expressions must be constant." << endl;
cerr << cur->first->get_fileline() << " : "
@ -883,7 +847,7 @@ static bool evaluate_ranges(Design*des, NetScope*scope,
delete texpr;
texpr = elab_and_eval(des, scope, cur->second, -1, true);
if (! eval_as_long(lrng.lsb, texpr)) {
if (! eval_as_long(use_lsb, texpr)) {
cerr << cur->second->get_fileline() << ": error: "
"Range expressions must be constant." << endl;
cerr << cur->second->get_fileline() << " : "
@ -895,23 +859,97 @@ static bool evaluate_ranges(Design*des, NetScope*scope,
delete texpr;
llist.push_back(lrng);
llist.push_back(netrange_t(use_msb, use_lsb));
}
return bad_msb | bad_lsb;
}
bool test_ranges_eeq(const list<NetNet::range_t>&lef, const list<NetNet::range_t>&rig)
static netclass_t* locate_class_type(Design*des, NetScope*scope,
class_type_t*class_type)
{
netclass_t*use_class = scope->find_class(class_type->name);
return use_class;
}
static netstruct_t* elaborate_struct_type(Design*des, NetScope*scope,
struct_type_t*struct_type)
{
netstruct_t*res = new netstruct_t;
res->packed(struct_type->packed_flag);
for (list<struct_member_t*>::iterator cur = struct_type->members->begin()
; cur != struct_type->members->end() ; ++ cur) {
vector<netrange_t>packed_dimensions;
struct_member_t*curp = *cur;
if (curp->range.get() && ! curp->range->empty()) {
bool bad_range;
bad_range = evaluate_ranges(des, scope, packed_dimensions, *curp->range);
ivl_assert(*curp, !bad_range);
} else {
packed_dimensions.push_back(netrange_t(0,0));
}
for (list<decl_assignment_t*>::iterator name = curp->names->begin()
; name != curp->names->end() ; ++ name) {
decl_assignment_t*namep = *name;
netstruct_t::member_t memb;
memb.name = namep->name;
memb.type = curp->type;
memb.packed_dims = packed_dimensions;
res->append_member(memb);
}
}
return res;
}
static ivl_type_s*elaborate_type(Design*des, NetScope*scope,
data_type_t*pform_type)
{
if (struct_type_t*struct_type = dynamic_cast<struct_type_t*>(pform_type)) {
netstruct_t*use_type = elaborate_struct_type(des, scope, struct_type);
return use_type;
}
cerr << pform_type->get_fileline() << ": sorry: I don't know how to elaborate "
<< typeid(*pform_type).name() << " here." << endl;
des->errors += 1;
return 0;
}
static netparray_t* elaborate_parray_type(Design*des, NetScope*scope,
parray_type_t*data_type)
{
vector<netrange_t>packed_dimensions;
bool bad_range = evaluate_ranges(des, scope, packed_dimensions, * data_type->packed_dims);
ivl_assert(*data_type, !bad_range);
ivl_type_s*element_type = elaborate_type(des, scope, data_type->base_type);
netparray_t*res = new netparray_t(packed_dimensions, element_type);
//res->set_line(*data_type);
return res;
}
bool test_ranges_eeq(const vector<netrange_t>&lef, const vector<netrange_t>&rig)
{
if (lef.size() != rig.size())
return false;
list<NetNet::range_t>::const_iterator lcur = lef.begin();
list<NetNet::range_t>::const_iterator rcur = rig.begin();
vector<netrange_t>::const_iterator lcur = lef.begin();
vector<netrange_t>::const_iterator rcur = rig.begin();
while (lcur != lef.end()) {
if (lcur->msb != rcur->msb)
if (lcur->get_msb() != rcur->get_msb())
return false;
if (lcur->lsb != rcur->lsb)
if (lcur->get_lsb() != rcur->get_lsb())
return false;
++ lcur;
@ -942,7 +980,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
}
unsigned wid = 1;
list<NetNet::range_t>packed_dimensions;
vector<netrange_t>packed_dimensions;
des->errors += error_cnt_;
@ -983,7 +1021,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (port_set_ || net_set_) {
bool bad_range = false;
list<NetNet::range_t> plist, nlist;
vector<netrange_t> plist, nlist;
/* If they exist get the port definition MSB and LSB */
if (port_set_ && !port_.empty()) {
bad_range |= evaluate_ranges(des, scope, plist, port_);
@ -1049,7 +1087,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
}
packed_dimensions = nlist;
wid = NetNet::vector_width(packed_dimensions);
wid = netrange_width(packed_dimensions);
}
@ -1057,19 +1095,32 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
attrib_list_t*attrib_list = evaluate_attributes(attributes, nattrib,
des, scope);
long array_s0 = 0;
long array_e0 = 0;
unsigned array_dimensions = 0;
/* If the ident has idx expressions, then this is a
memory. It can only have the idx registers after the msb
and lsb expressions are filled. And, if it has one index,
it has both. */
if (lidx_ || ridx_) {
assert(lidx_ && ridx_);
list<netrange_t>unpacked_dimensions;
netdarray_t*netarray = 0;
NetExpr*lexp = elab_and_eval(des, scope, lidx_, -1, true);
NetExpr*rexp = elab_and_eval(des, scope, ridx_, -1, true);
for (list<pform_range_t>::const_iterator cur = unpacked_.begin()
; cur != unpacked_.end() ; ++cur) {
PExpr*use_lidx = cur->first;
PExpr*use_ridx = cur->second;
// Special case: If we encounter an undefined
// dimensions, then turn this into a dynamic array and
// put all the packed dimensions there.
if (use_lidx==0 && use_ridx==0) {
netvector_t*vec = new netvector_t(packed_dimensions, data_type_);
packed_dimensions.clear();
ivl_assert(*this, netarray==0);
netarray = new netdarray_t(vec);
continue;
}
// Cannot handle dynamic arrays of arrays yet.
ivl_assert(*this, netarray==0);
ivl_assert(*this, use_lidx && use_ridx);
NetExpr*lexp = elab_and_eval(des, scope, use_lidx, -1, true);
NetExpr*rexp = elab_and_eval(des, scope, use_ridx, -1, true);
if ((lexp == 0) || (rexp == 0)) {
cerr << get_fileline() << ": internal error: There is "
@ -1086,19 +1137,21 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
delete rexp;
delete lexp;
if (!const_flag) {
long index_l, index_r;
if (! const_flag) {
cerr << get_fileline() << ": error: The indices "
<< "are not constant for array ``"
<< name_ << "''." << endl;
des->errors += 1;
/* Attempt to recover from error, */
array_s0 = 0;
array_e0 = 0;
index_l = 0;
index_r = 0;
} else {
array_s0 = lval.as_long();
array_e0 = rval.as_long();
}
array_dimensions = 1;
index_l = lval.as_long();
index_r = rval.as_long();
}
unpacked_dimensions.push_back(netrange_t(index_l, index_r));
}
if (data_type_ == IVL_VT_REAL && !packed_dimensions.empty()) {
@ -1151,10 +1204,20 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
NetNet*sig = 0;
// If this is a struct type, then build the net with the
// struct type.
if (struct_type_) {
netstruct_t*use_type = elaborate_struct_type(des, scope, struct_type_);
if (class_type_t*class_type = dynamic_cast<class_type_t*>(set_data_type_)) {
// If this is a class variable, then the class type
// should already have been elaborated. All we need to
// do right now is locate the netclass_t object for the
// class, and use that to build the net.
netclass_t*use_type = locate_class_type(des, scope, class_type);
// (No arrays of classes)
list<netrange_t> use_unpacked;
sig = new NetNet(scope, name_, wtype, use_unpacked, use_type);
} else if (struct_type_t*struct_type = dynamic_cast<struct_type_t*>(set_data_type_)) {
// If this is a struct type, then build the net with the
// struct type.
netstruct_t*use_type = elaborate_struct_type(des, scope, struct_type);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " << wtype;
if (use_type->packed())
@ -1167,54 +1230,90 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
sig = new NetNet(scope, name_, wtype, use_type);
} 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();
netenum_t*use_enum = scope->enumeration_for_name(sample_name->name);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " << wtype
<< " enumeration "
<< name_ << " in scope " << scope_path(scope)
<< " with packed_dimensions=" << packed_dimensions
<< " and packed_width=" << use_enum->packed_width() << endl;
}
ivl_assert(*this, packed_dimensions.empty());
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_enum);
} else if (netarray) {
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " << wtype
<< " dynamic array "
<< name_ << " in scope " << scope_path(scope) << endl;
}
ivl_assert(*this, packed_dimensions.empty());
ivl_assert(*this, unpacked_dimensions.empty());
sig = new NetNet(scope, name_, wtype, netarray);
} else if (parray_type_t*parray_type = dynamic_cast<parray_type_t*>(set_data_type_)) {
// The pform gives us a parray_type_t for packed arrays
// that show up in type definitions. This can be handled
// a lot like packed dimensions from other means.
// The trick here is that the parray type has an
// arbitrary sub-type, and not just a scalar bit...
netparray_t*use_type = elaborate_parray_type(des, scope, parray_type);
// Should not be getting packed dimensions other then
// through the parray type declaration.
ivl_assert(*this, packed_dimensions.empty());
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " << wtype
<< " parray=" << use_type->packed_dimensions()
<< " " << name_ << unpacked_dimensions
<< " in scope " << scope_path(scope) << endl;
}
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_type);
} else {
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " << wtype;
if (!get_scalar()) {
cerr << " " << packed_dimensions;
}
cerr << " " << name_;
if (array_dimensions > 0) {
cerr << " [" << array_s0 << ":" << array_e0 << "]" << endl;
}
cerr << " " << name_ << unpacked_dimensions;
cerr << " in scope " << scope_path(scope) << endl;
}
sig = array_dimensions > 0
? new NetNet(scope, name_, wtype, packed_dimensions, array_s0, array_e0)
: new NetNet(scope, name_, wtype, packed_dimensions);
}
ivl_variable_type_t use_data_type = data_type_;
if (use_data_type == IVL_VT_NO_TYPE) {
use_data_type = IVL_VT_LOGIC;
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
<< "Signal " << name_
<< " in scope " << scope_path(scope)
<< " defaults to data type " << use_data_type << endl;
}
}
netvector_t*vec = new netvector_t(packed_dimensions, use_data_type);
vec->set_signed(get_signed());
vec->set_isint(get_isint());
if (is_implicit_scalar) vec->set_scalar(true);
else vec->set_scalar(get_scalar());
packed_dimensions.clear();
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, vec);
// If this is an enumeration, then set the enumeration set for
// the new signal. This turns it into an enumeration.
if (enum_type_) {
ivl_assert(*this, struct_type_ == 0);
ivl_assert(*this, ! enum_type_->names->empty());
list<named_pexpr_t>::const_iterator sample_name = enum_type_->names->begin();
netenum_t*use_enum = scope->enumeration_for_name(sample_name->name);
sig->set_enumeration(use_enum);
}
if (wtype == NetNet::WIRE) sig->devirtualize_pins();
ivl_variable_type_t use_data_type = data_type_;
if (use_data_type == IVL_VT_NO_TYPE) {
use_data_type = IVL_VT_LOGIC;
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
<< "Signal " << name_
<< " in scope " << scope_path(scope)
<< " defaults to data type " << use_data_type << endl;
}
}
sig->data_type(use_data_type);
sig->set_line(*this);
sig->port_type(port_type_);
sig->set_signed(get_signed());
sig->set_isint(get_isint());
if (is_implicit_scalar) sig->set_scalar(true);
else sig->set_scalar(get_scalar());
if (ivl_discipline_t dis = get_discipline()) {
sig->set_discipline(dis);

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"

64
elab_type.cc Normal file
View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2012 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
* 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 "pform_types.h"
# include "netlist.h"
# include "netvector.h"
# include <typeinfo>
# include "ivl_assert.h"
using namespace std;
ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*) const
{
cerr << get_fileline() << ": internal error: "
<< "Elaborate method not implemented for " << typeid(*this).name()
<< "." << endl;
des->errors += 1;
return 0;
}
ivl_type_s* atom2_type_t::elaborate_type(Design*des, NetScope*) const
{
switch (type_code) {
case 32:
if (signed_flag)
return &netvector_t::atom2s32;
else
return &netvector_t::atom2u32;
case 16:
if (signed_flag)
return &netvector_t::atom2s16;
else
return &netvector_t::atom2u16;
case 8:
if (signed_flag)
return &netvector_t::atom2s8;
else
return &netvector_t::atom2u8;
default:
cerr << get_fileline() << ": internal error: "
<< "atom2_type_t type_code=" << type_code << "." << endl;
des->errors += 1;
return 0;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2012 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
@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
@ -35,6 +35,9 @@
# include "PGenerate.h"
# include "PSpec.h"
# include "netlist.h"
# include "netvector.h"
# include "netdarray.h"
# include "netclass.h"
# include "netmisc.h"
# include "util.h"
# include "parse_api.h"
@ -75,8 +78,7 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
if (debug_elaborate) {
cerr << get_fileline() << ": debug: PGAssign: elaborated l-value"
<< " width=" << lval->vector_width()
<< ", type=" << lval->data_type() << endl;
<< " width=" << lval->vector_width() << endl;
}
NetExpr*rval_expr = elaborate_rval_expr(des, scope, lval->data_type(),
@ -115,7 +117,6 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
cerr << get_fileline() << ": debug: PGAssign: elaborated r-value"
<< " width="<< rval->vector_width()
<< ", type="<< rval->data_type()
<< ", signed="<< rval->get_signed()
<< ", expr=" << *rval_expr << endl;
}
@ -164,11 +165,12 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
NetPartSelect::VP);
des->add_node(tmp);
tmp->set_line(*this);
netvector_t*osig_vec = new netvector_t(rval->data_type(),
lval->vector_width()-1,0);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::TRI, lval->vector_width());
NetNet::TRI, osig_vec);
osig->set_line(*this);
osig->local_flag(true);
osig->data_type(rval->data_type());
connect(osig->pin(0), tmp->pin(0));
rval = osig;
need_driver_flag = false;
@ -190,10 +192,11 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
connect(rval->pin(0), driver->pin(1));
netvector_t*tmp_vec = new netvector_t(rval->data_type(),
rval->vector_width()-1,0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, rval->vector_width());
NetNet::WIRE, tmp_vec);
tmp->set_line(*this);
tmp->data_type(rval->data_type());
tmp->local_flag(true);
connect(driver->pin(0), tmp->pin(0));
@ -772,7 +775,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
NetExpr* rise_time, *fall_time, *decay_time;
eval_delays(des, scope, rise_time, fall_time, decay_time);
struct attrib_list_t*attrib_list = 0;
struct attrib_list_t*attrib_list;
unsigned attrib_list_n = 0;
attrib_list = evaluate_attributes(attributes, attrib_list_n,
des, scope);
@ -868,10 +871,11 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
des->add_node(rep);
connect(rep->pin(1), sig->pin(0));
netvector_t*osig_vec = new netvector_t(IVL_VT_LOGIC,
instance_width-1,0);
sig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, instance_width);
NetNet::WIRE, osig_vec);
sig->set_line(*this);
sig->data_type(IVL_VT_LOGIC);
sig->local_flag(true);
connect(rep->pin(0), sig->pin(0));
@ -948,12 +952,12 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
unsigned dev = gdx*gate_count;
connect(cur[dev+idx]->pin(0), cc->pin(gdx+1));
netvector_t*tmp2_vec = new netvector_t(IVL_VT_LOGIC);
NetNet*tmp2 = new NetNet(scope,
scope->local_symbol(),
NetNet::WIRE, 1);
NetNet::WIRE, tmp2_vec);
tmp2->set_line(*this);
tmp2->local_flag(true);
tmp2->data_type(IVL_VT_LOGIC);
connect(cc->pin(gdx+1), tmp2->pin(0));
}
@ -965,11 +969,11 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
tmp1->set_line(*this);
des->add_node(tmp1);
connect(tmp1->pin(1), sig->pin(0));
netvector_t*tmp2_vec = new netvector_t(sig->data_type());
NetNet*tmp2 = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, 1);
NetNet::WIRE, tmp2_vec);
tmp2->set_line(*this);
tmp2->local_flag(true);
tmp2->data_type(sig->data_type());
connect(tmp1->pin(0), tmp2->pin(0));
unsigned use_idx = idx - gate_count + 1;
unsigned dev = gdx*gate_count;
@ -996,8 +1000,9 @@ NetNet*PGModule::resize_net_to_port_(Design*des, NetScope*scope,
ivl_assert(*this, dir != NetNet::NOT_A_PORT);
ivl_assert(*this, dir != NetNet::PIMPLICIT);
netvector_t*tmp_type = new netvector_t(IVL_VT_LOGIC, port_wid-1, 0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, port_wid);
NetNet::WIRE, tmp_type);
tmp->local_flag(true);
tmp->set_line(*this);
@ -1250,6 +1255,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
get_name() << "..." << endl;
for (unsigned inst = 0 ; inst < instance.size() ; inst += 1) {
rmod->elaborate(des, instance[inst]);
instance[inst]->set_num_ports( rmod->port_count() );
}
if (debug_elaborate) cerr << get_fileline() << ": debug: ...done." << endl;
@ -1329,7 +1335,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
unconnected_port = true;
}
// Inside the module, the port is zero or more signals
// Inside the module, the port connects zero or more signals
// that were already elaborated. List all those signals
// and the NetNet equivalents, for all the instances.
vector<PEIdent*> mport = rmod->get_port(idx);
@ -1349,19 +1355,24 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
// will be assembled in that order as well.
NetScope*inst_scope = instance[instance.size()-inst-1];
unsigned int prt_vector_width = 0;
PortType::Enum ptype = PortType::PIMPLICIT;
// Scan the module sub-ports for this instance...
for (unsigned ldx = 0 ; ldx < mport.size() ; ldx += 1) {
unsigned lbase = inst * mport.size();
PEIdent*pport = mport[ldx];
assert(pport);
prts[lbase + ldx]
= pport->elaborate_port(des, inst_scope);
if (prts[lbase + ldx] == 0)
NetNet *netnet = pport->elaborate_subport(des, inst_scope);
prts[lbase + ldx] = netnet;
if (netnet == 0)
continue;
assert(prts[lbase + ldx]);
prts_vector_width += prts[lbase + ldx]->vector_width();
assert(netnet);
prts_vector_width += netnet->vector_width();
prt_vector_width += netnet->vector_width();
ptype = PortType::merged(netnet->port_type(), ptype);
}
inst_scope->add_module_port_info(idx, rmod->get_port_name(idx), ptype, prt_vector_width );
}
// If I find that the port is unconnected inside the
@ -1409,6 +1420,12 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
<< "too complicated for elaboration." << endl;
continue;
}
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
<< "Elaborating INPUT port expression: " << *tmp_expr << endl;
}
sig = tmp_expr->synthesize(des, scope, tmp_expr);
if (sig == 0) {
cerr << pins[idx]->get_fileline()
@ -1426,11 +1443,12 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
des->add_node(tmp);
connect(tmp->pin(1), sig->pin(0));
netvector_t*tmp2_vec = new netvector_t(sig->data_type(),
sig->vector_width()-1,0);
NetNet*tmp2 = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, sig->vector_width());
NetNet::WIRE, tmp2_vec);
tmp2->local_flag(true);
tmp2->set_line(*this);
tmp2->data_type(sig->data_type());
connect(tmp->pin(0), tmp2->pin(0));
sig = tmp2;
}
@ -1598,7 +1616,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
assert(sig);
#ifndef NDEBUG
if ((prts.size() >= 1)
if ((! prts.empty())
&& (prts[0]->port_type() != NetNet::PINPUT)) {
assert(sig->type() != NetNet::REG);
}
@ -1922,7 +1940,7 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const
net->fall_time(fall_expr);
net->decay_time(decay_expr);
struct attrib_list_t*attrib_list = 0;
struct attrib_list_t*attrib_list;
unsigned attrib_list_n = 0;
attrib_list = evaluate_attributes(attributes, attrib_list_n,
des, scope);
@ -2068,6 +2086,10 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const
bool PGModule::elaborate_sig(Design*des, NetScope*scope) const
{
if (bound_type_) {
return elaborate_sig_mod_(des, scope, bound_type_);
}
// Look for the module type
map<perm_string,Module*>::const_iterator mod = pform_modules.find(type_);
if (mod != pform_modules.end())
@ -2087,6 +2109,11 @@ bool PGModule::elaborate_sig(Design*des, NetScope*scope) const
void PGModule::elaborate(Design*des, NetScope*scope) const
{
if (bound_type_) {
elaborate_mod_(des, bound_type_, scope);
return;
}
// Look for the module type
map<perm_string,Module*>::const_iterator mod = pform_modules.find(type_);
if (mod != pform_modules.end()) {
@ -2108,10 +2135,16 @@ void PGModule::elaborate(Design*des, NetScope*scope) const
void PGModule::elaborate_scope(Design*des, NetScope*sc) const
{
// If the module type is known by design, then go right to it.
if (bound_type_) {
elaborate_scope_mod_(des, bound_type_, sc);
return;
}
// Look for the module type
map<perm_string,Module*>::const_iterator mod = pform_modules.find(type_);
if (mod != pform_modules.end()) {
elaborate_scope_mod_(des, (*mod).second, sc);
elaborate_scope_mod_(des, mod->second, sc);
return;
}
@ -2128,7 +2161,7 @@ void PGModule::elaborate_scope(Design*des, NetScope*sc) const
// Try again to find the module type
mod = pform_modules.find(type_);
if (mod != pform_modules.end()) {
elaborate_scope_mod_(des, (*mod).second, sc);
elaborate_scope_mod_(des, mod->second, sc);
return;
}
@ -2163,6 +2196,17 @@ NetAssign_* PAssign_::elaborate_lval(Design*des, NetScope*scope) const
return lval_->elaborate_lval(des, scope, false);
}
NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
ivl_type_t net_type) const
{
ivl_assert(*this, rval_);
NetExpr*rv = rval_->elaborate_expr(des, scope, net_type, 0);
ivl_assert(*this, !is_constant_);
return rv;
}
NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
unsigned lv_width,
ivl_variable_type_t lv_type) const
@ -2297,6 +2341,18 @@ NetProc* PAssign::elaborate_compressed_(Design*des, NetScope*scope) const
return cur;
}
static bool lval_not_program_variable(const NetAssign_*lv)
{
while (lv) {
NetScope*sig_scope = lv->sig()->scope();
if (! sig_scope->program_block())
return true;
lv = lv->more;
}
return false;
}
NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
{
assert(scope);
@ -2311,14 +2367,36 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
NetAssign_*lv = elaborate_lval(des, scope);
if (lv == 0) return 0;
if (scope->program_block() && lval_not_program_variable(lv)) {
cerr << get_fileline() << ": error: Blocking assignments to "
<< "non-program variables are not allowed." << endl;
des->errors += 1;
}
/* If there is an internal delay expression, elaborate it. */
NetExpr*delay = 0;
if (delay_ != 0)
delay = elaborate_delay_expr(delay_, des, scope);
NetExpr*rv;
const ivl_type_s*lv_net_type = lv->net_type();
/* If the l-value is a compound type of some sort, then use
the newer net_type form of the elaborate_rval_ method to
handle the new types. */
if (dynamic_cast<const netclass_t*> (lv_net_type)) {
ivl_assert(*this, lv->more==0);
rv = elaborate_rval_(des, scope, lv_net_type);
} else if (dynamic_cast<const netdarray_t*> (lv_net_type)) {
ivl_assert(*this, lv->more==0);
rv = elaborate_rval_(des, scope, lv_net_type);
} else {
/* Elaborate the r-value expression, then try to evaluate it. */
rv = elaborate_rval_(des, scope, count_lval_width(lv), lv->expr_type());
}
/* Elaborate the r-value expression, then try to evaluate it. */
NetExpr*rv = elaborate_rval_(des, scope, count_lval_width(lv), lv->expr_type());
if (rv == 0) return 0;
assert(rv);
@ -2343,11 +2421,11 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
if (delay || event_) {
unsigned wid = count_lval_width(lv);
netvector_t*tmp2_vec = new netvector_t(rv->expr_type(),wid-1,0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::REG, wid);
NetNet::REG, tmp2_vec);
tmp->local_flag(true);
tmp->set_line(*this);
tmp->data_type(rv->expr_type());
NetESignal*sig = new NetESignal(tmp);
@ -2438,10 +2516,17 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
if (lv->expr_type() == IVL_VT_BOOL && rv->expr_type() != IVL_VT_BOOL) {
if (debug_elaborate)
cerr << get_fileline() << ": debug: Cast expression to int2" << endl;
cerr << get_fileline() << ": debug: "
<< "Cast expression to int2" << endl;
rv = cast_to_int2(rv);
}
if (lv->expr_type() == IVL_VT_REAL && rv->expr_type() != IVL_VT_REAL) {
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
<< "Cast expression to real." << endl;
rv = cast_to_real(rv);
}
if (lv->enumeration() && (lv->enumeration() != rv->enumeration())) {
cerr << get_fileline() << ": error: "
<< "Enumeration type mismatch in assignment." << endl;
@ -2454,6 +2539,22 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
return cur;
}
/*
* Return true if any lvalue parts are in a program block scope.
*/
static bool lval_is_program_variable(const NetAssign_*lv)
{
while (lv) {
NetScope*sig_scope = lv->sig()->scope();
if (sig_scope->program_block())
return true;
lv = lv->more;
}
return false;
}
/*
* Elaborate non-blocking assignments. The statement is of the general
* form:
@ -2490,6 +2591,14 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
NetAssign_*lv = elaborate_lval(des, scope);
if (lv == 0) return 0;
if (scope->program_block() && lval_is_program_variable(lv)) {
cerr << get_fileline() << ": error: Non-blocking assignments to "
<< "program variables are not allowed." << endl;
des->errors += 1;
// This is an error, but we can let elaboration continue
// because it would necessarily trigger other errors.
}
NetExpr*rv = elaborate_rval_(des, scope, count_lval_width(lv), lv->expr_type());
if (rv == 0) return 0;
@ -2576,9 +2685,27 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
{
assert(scope);
NetBlock::Type type = (bl_type_==PBlock::BL_PAR)
? NetBlock::PARA
: NetBlock::SEQU;
NetBlock::Type type;
switch (bl_type_) {
case PBlock::BL_SEQ:
type = NetBlock::SEQU;
break;
case PBlock::BL_PAR:
type = NetBlock::PARA;
break;
case PBlock::BL_JOIN_NONE:
type = NetBlock::PARA_JOIN_NONE;
break;
case PBlock::BL_JOIN_ANY:
type = NetBlock::PARA_JOIN_ANY;
break;
// Added to remove a "type" uninitialized compiler warning.
// This should never be reached since all the PBlock enumeration
// cases are handled above.
default:
type = NetBlock::SEQU;
assert(0);
}
NetScope*nscope = 0;
if (pscope_name() != 0) {
@ -2695,7 +2822,7 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const
a separate case for each. (Yes, the statement
will be elaborated again for each.) */
PExpr*cur_expr = *idx_expr;
NetExpr*gu = 0;
NetExpr*gu;
NetProc*st = 0;
assert(cur_expr);
gu = elab_and_eval(des, scope, cur_expr, -1);
@ -2833,7 +2960,7 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
if ((parm_count== 1) && (parms_[0] == 0))
parm_count = 0;
svector<NetExpr*>eparms (parm_count);
vector<NetExpr*>eparms (parm_count);
perm_string name = peek_tail_name(path_);
@ -2912,6 +3039,12 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
NetScope*task = des->find_task(scope, path_);
if (task == 0) {
// Maybe this is a method attached to a signal?
if (gn_system_verilog()) {
NetProc*tmp = elaborate_method_(des, scope);
if (tmp) return tmp;
}
cerr << get_fileline() << ": error: Enable of unknown task "
<< "``" << path_ << "''." << endl;
des->errors += 1;
@ -3094,6 +3227,39 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
return block;
}
NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope) const
{
pform_name_t use_path = path_;
perm_string method_name = peek_tail_name(use_path);
use_path.pop_back();
NetNet *net;
const NetExpr *par;
NetEvent *eve;
const NetExpr *ex1, *ex2;
symbol_search(this, des, scope, use_path,
net, par, eve, ex1, ex2);
if (net == 0)
return 0;
// Is this a delete method for dynamic arrays?
if (net->darray_type() && method_name=="delete") {
NetESignal*sig = new NetESignal(net);
vector<NetExpr*> argv (1);
argv[0] = sig;
NetSTask*sys = new NetSTask("$ivl_darray_method$delete",
IVL_SFUNC_AS_TASK_IGNORE, argv);
sys->set_line(*this);
return sys;
}
return 0;
}
/*
* Elaborate a procedural continuous assign. This really looks very
* much like other procedural assignments, at this point, but there
@ -4123,7 +4289,7 @@ bool PProcess::elaborate(Design*des, NetScope*scope) const
// Evaluate the attributes for this process, if there
// are any. These attributes are to be attached to the
// NetProcTop object.
struct attrib_list_t*attrib_list = 0;
struct attrib_list_t*attrib_list;
unsigned attrib_list_n = 0;
attrib_list = evaluate_attributes(attributes, attrib_list_n, des, scope);
@ -4443,53 +4609,11 @@ static void elaborate_tasks(Design*des, NetScope*scope,
* When a module is instantiated, it creates the scope then uses this
* method to elaborate the contents of the module.
*/
bool Module::elaborate(Design*des, NetScope*scope) const
{
bool result_flag = true;
// Elaborate specparams
typedef map<perm_string,PExpr*>::const_iterator specparam_it_t;
for (specparam_it_t cur = specparams.begin() ;
cur != specparams.end() ; ++ cur ) {
NetExpr*val = elab_and_eval(des, scope, (*cur).second, -1, true);
NetScope::spec_val_t value;
if (NetECReal*val_cr = dynamic_cast<NetECReal*> (val)) {
value.type = IVL_VT_REAL;
value.real_val = val_cr->value().as_double();
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Elaborate "
<< "specparam " << (*cur).first
<< " value=" << value.real_val << endl;
}
} else if (NetEConst*val_c = dynamic_cast<NetEConst*> (val)) {
value.type = IVL_VT_BOOL;
value.integer = val_c->value().as_long();
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Elaborate "
<< "specparam " << (*cur).first
<< " value=" << value.integer << endl;
}
} else {
value.type = IVL_VT_NO_TYPE;
cerr << (*cur).second->get_fileline() << ": error: "
<< "specparam " << (*cur).first
<< " value is not constant: " << *val << endl;
des->errors += 1;
}
assert(val);
delete val;
scope->specparams[(*cur).first] = value;
}
// Elaborate within the generate blocks.
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
@ -4627,7 +4751,6 @@ bool PGenerate::elaborate_direct_(Design*des, NetScope*container) const
// contain anything. Instead scan the case items, which
// are listed as sub-schemes of the item.
if (item->scheme_type == PGenerate::GS_CASE) {
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t icur = item->generate_schemes.begin()
; icur != item->generate_schemes.end() ; ++ icur ) {
PGenerate*case_item = *icur;
@ -4738,6 +4861,9 @@ class top_defparams : public elaborator_work_item_t {
virtual void elaborate_runrun()
{
if (debug_scopes) {
cerr << "debug: top_defparams::elaborate_runrun()" << endl;
}
// This method recurses through the scopes, looking for
// defparam assignments to apply to the parameters in the
// various scopes. This needs to be done after all the scopes
@ -4749,6 +4875,10 @@ class top_defparams : public elaborator_work_item_t {
// scopes and evaluate the parameters all the way down to
// constants.
des->evaluate_parameters();
if (debug_scopes) {
cerr << "debug: top_defparams::elaborate_runrun() done" << endl;
}
}
};
@ -4762,6 +4892,10 @@ class later_defparams : public elaborator_work_item_t {
virtual void elaborate_runrun()
{
if (debug_scopes) {
cerr << "debug: later_defparams::elaborate_runrun()" << endl;
}
list<NetScope*>tmp_list;
for (set<NetScope*>::iterator cur = des->defparams_later.begin()
; cur != des->defparams_later.end() ; ++ cur )
@ -4774,7 +4908,13 @@ class later_defparams : public elaborator_work_item_t {
tmp_list.pop_front();
cur->run_defparams_later(des);
}
des->evaluate_parameters();
// The overridden parameters will be evaluated later in
// a top_defparams work item.
if (debug_scopes) {
cerr << "debuf: later_defparams::elaborate_runrun() done" << endl;
}
}
};
@ -4859,7 +4999,7 @@ Design* elaborate(list<perm_string>roots)
// Make the root scope. This makes a NetScope object and
// pushes it into the list of root scopes in the Design.
NetScope*scope = des->make_root_scope(*root);
NetScope*scope = des->make_root_scope(*root, rmod->program_block);
// Collect some basic properties of this scope from the
// Module definition.
@ -4933,10 +5073,22 @@ Design* elaborate(list<perm_string>roots)
// creates all the NetNet and NetMemory objects for declared
// objects.
for (i = 0; i < root_elems.count(); i++) {
Module *rmod = root_elems[i]->mod;
NetScope *scope = root_elems[i]->scope;
scope->set_num_ports( rmod->port_count() );
if (debug_elaborate) {
cerr << "<toplevel>" << ": debug: " << rmod->mod_name()
<< ": port elaboration root "
<< rmod->port_count() << " ports" << endl;
}
if (! rmod->elaborate_sig(des, scope)) {
if (debug_elaborate) {
cerr << "<toplevel>" << ": debug: " << rmod->mod_name()
<< ": elaborate_sig failed!!!" << endl;
}
delete des;
return 0;
}
@ -4945,11 +5097,24 @@ Design* elaborate(list<perm_string>roots)
// defined for the root modules. This code does that.
for (unsigned idx = 0; idx < rmod->port_count(); idx += 1) {
vector<PEIdent*> mport = rmod->get_port(idx);
unsigned int prt_vector_width = 0;
PortType::Enum ptype = PortType::PIMPLICIT;
for (unsigned pin = 0; pin < mport.size(); pin += 1) {
// This really does more than we need and adds extra
// stuff to the design that should be cleaned later.
(void) mport[pin]->elaborate_port(des, scope);
NetNet *netnet = mport[pin]->elaborate_subport(des, scope);
if (netnet != 0) {
// Elaboration may actually fail with erroneous input source
prt_vector_width += netnet->vector_width();
ptype = PortType::merged(netnet->port_type(), ptype);
}
}
if (debug_elaborate) {
cerr << "<toplevel>" << ": debug: " << rmod->mod_name()
<< ": adding module port "
<< rmod->get_port_name(idx) << endl;
}
scope->add_module_port_info(idx, rmod->get_port_name(idx), ptype, prt_vector_width );
}
}
@ -4976,5 +5141,11 @@ Design* elaborate(list<perm_string>roots)
des = 0;
}
if (debug_elaborate) {
cerr << "<toplevel>" << ": debug: "
<< " finishing with "
<< des->find_root_scopes().size() << " root scopes " << endl;
}
return des;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008,2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008-2012 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
@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
@ -55,7 +55,7 @@ bool AProcess::elaborate(Design*des, NetScope*scope) const
// Evaluate the attributes for this process, if there
// are any. These attributes are to be attached to the
// NetProcTop object.
struct attrib_list_t*attrib_list = 0;
struct attrib_list_t*attrib_list;
unsigned attrib_list_n = 0;
attrib_list = evaluate_attributes(attributes, attrib_list_n, des, scope);

21
emit.cc
View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
@ -385,6 +385,10 @@ void NetScope::emit_scope(struct target_t*tgt) const
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_)
tgt->event(cur);
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
; cur != classes_.end() ; ++cur)
tgt->class_type(this, cur->second);
for (list<netenum_t*>::const_iterator cur = enum_sets_.begin()
; cur != enum_sets_.end() ; ++cur)
tgt->enumeration(this, *cur);
@ -551,6 +555,21 @@ void NetENetenum::expr_scan(struct expr_scan_t*tgt) const
tgt->expr_netenum(this);
}
void NetENew::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_new(this);
}
void NetENull::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_null(this);
}
void NetEProperty::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_property(this);
}
void NetEScope::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_scope(this);

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
@ -34,11 +34,11 @@ NetExpr* NetExpr::eval_tree()
return 0;
}
static bool get_real_arg_(NetExpr*expr, verireal&val)
static bool get_real_arg_(const NetExpr*expr, verireal&val)
{
switch (expr->expr_type()) {
case IVL_VT_REAL: {
NetECReal*c = dynamic_cast<NetECReal*> (expr);
const NetECReal*c = dynamic_cast<const NetECReal*> (expr);
if (c == 0) return false;
val = c->value();
break;
@ -46,13 +46,16 @@ static bool get_real_arg_(NetExpr*expr, verireal&val)
case IVL_VT_BOOL:
case IVL_VT_LOGIC: {
NetEConst*c = dynamic_cast<NetEConst*>(expr);
const NetEConst*c = dynamic_cast<const NetEConst*>(expr);
if (c == 0) return false;
verinum tmp = c->value();
val = verireal(tmp.as_double());
break;
}
case IVL_VT_DARRAY:
return false;
default:
assert(0);
}
@ -60,7 +63,7 @@ static bool get_real_arg_(NetExpr*expr, verireal&val)
return true;
}
static bool get_real_arguments(NetExpr*le, NetExpr*re,
static bool get_real_arguments(const NetExpr*le, const NetExpr*re,
double&lval, double&rval)
{
verireal val;
@ -82,15 +85,15 @@ bool NetEBinary::get_real_arguments_(verireal&lval, verireal&rval)
return true;
}
NetECReal* NetEBAdd::eval_tree_real_()
NetECReal* NetEBAdd::eval_tree_real_(const NetExpr*l, const NetExpr*r) const
{
verireal lval;
verireal rval;
double lval;
double rval;
bool flag = get_real_arguments_(lval, rval);
bool flag = get_real_arguments(l, r, lval, rval);
if (!flag) return 0;
verireal res_val;
double res_val;
switch (op()) {
case '+':
@ -103,7 +106,7 @@ NetECReal* NetEBAdd::eval_tree_real_()
ivl_assert(*this, 0);
}
NetECReal*res = new NetECReal( res_val );
NetECReal*res = new NetECReal( verireal(res_val) );
ivl_assert(*this, res);
res->set_line(*this);
@ -119,52 +122,24 @@ NetExpr* NetEBAdd::eval_tree()
eval_expr(left_);
eval_expr(right_);
if (expr_type() == IVL_VT_REAL)
return eval_tree_real_();
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
/* If both operands are constant, then replace the entire
expression with a constant value. */
if (lc != 0 && rc != 0) {
verinum lval = lc->value();
verinum rval = rc->value();
unsigned wid = expr_width();
ivl_assert(*this, wid > 0);
ivl_assert(*this, lval.len() == wid);
ivl_assert(*this, rval.len() == wid);
verinum val;
switch (op_) {
case '+':
val = verinum(lval + rval, wid);
break;
case '-':
val = verinum(lval - rval, wid);
break;
default:
return 0;
}
NetEConst *res = new NetEConst(val);
ivl_assert(*this, res);
res->set_line(*this);
if (debug_eval_tree)
cerr << get_fileline() << ": debug: Evaluated: " << *this
<< " --> " << *res << endl;
// First try to elaborate the expression completely.
NetExpr*res = eval_arguments_(left_,right_);
if (res != 0)
return res;
}
/* Try to combine a right constant value with the right
constant value of a sub-expression add. For example, the
expression (a + 2) - 1 can be rewritten as a + 1. */
// If the expression type is real, then do not attempt the
// following alternative processing.
if (expr_type() == IVL_VT_REAL)
return 0;
// The expression has not evaluated to a constant. Let's still
// try to optimize by trying to combine a right constant value
// with the right constant value of a sub-expression add. For
// example, the expression (a + 2) - 1 can be rewritten as a + 1.
NetEBAdd*se = dynamic_cast<NetEBAdd*>(left_);
lc = se? dynamic_cast<NetEConst*>(se->right_) : 0;
NetEConst*lc = se? dynamic_cast<NetEConst*>(se->right_) : 0;
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
if (lc != 0 && rc != 0) {
ivl_assert(*this, se != 0);
@ -200,11 +175,56 @@ NetExpr* NetEBAdd::eval_tree()
tmp->set_line(*right_);
delete right_;
right_ = tmp;
/* We've changed the subexpression, but the result is
still not constant, so return nil here anyhow. */
return 0;
}
// We may have changed the subexpression, but the result is
// still not constant, so return nil here anyhow.
return 0;
}
NetExpr* NetEBAdd::eval_arguments_(const NetExpr*l, const NetExpr*r) const
{
if (expr_type() == IVL_VT_REAL)
return eval_tree_real_(l,r);
const NetEConst*lc = dynamic_cast<const NetEConst*>(l);
const NetEConst*rc = dynamic_cast<const NetEConst*>(r);
/* If both operands are constant, then replace the entire
expression with a constant value. */
if (lc != 0 && rc != 0) {
verinum lval = lc->value();
verinum rval = rc->value();
unsigned wid = expr_width();
ivl_assert(*this, wid > 0);
ivl_assert(*this, lval.len() == wid);
ivl_assert(*this, rval.len() == wid);
verinum val;
switch (op_) {
case '+':
val = verinum(lval + rval, wid);
break;
case '-':
val = verinum(lval - rval, wid);
break;
default:
return 0;
}
NetEConst *res = new NetEConst(val);
ivl_assert(*this, res);
res->set_line(*this);
if (debug_eval_tree)
cerr << get_fileline() << ": debug: Evaluated: " << *this
<< " --> " << *res << endl;
return res;
}
/* Nothing more to be done, the value is not constant. */
return 0;
}
@ -276,13 +296,12 @@ NetEConst* NetEBBits::eval_tree()
return new NetEConst(res);
}
NetEConst* NetEBComp::eval_less_()
NetEConst* NetEBComp::eval_less_(const NetExpr*le, const NetExpr*re) const
{
if (right_->expr_type() == IVL_VT_REAL ||
left_->expr_type() == IVL_VT_REAL)
return eval_leeq_real_(left_, right_, false);
if (le->expr_type() == IVL_VT_REAL || re->expr_type() == IVL_VT_REAL)
return eval_leeq_real_(le, re, false);
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
const NetEConst*rc = dynamic_cast<const NetEConst*>(re);
if (rc == 0) return 0;
verinum rv = rc->value();
@ -292,12 +311,12 @@ NetEConst* NetEBComp::eval_less_()
return res;
}
if (NetEConst*tmp = must_be_leeq_(left_, rv, false)) {
if (NetEConst*tmp = must_be_leeq_(le, rv, false)) {
return tmp;
}
/* Now go on to the normal test of the values. */
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
const NetEConst*lc = dynamic_cast<const NetEConst*>(le);
if (lc == 0) return 0;
verinum lv = lc->value();
@ -318,7 +337,7 @@ NetEConst* NetEBComp::eval_less_()
}
}
NetEConst* NetEBComp::must_be_leeq_(NetExpr*le, const verinum&rv, bool eq_flag)
NetEConst* NetEBComp::must_be_leeq_(const NetExpr*le, const verinum&rv, bool eq_flag) const
{
assert(le->expr_width() > 0);
verinum lv (verinum::V1, le->expr_width());
@ -339,7 +358,7 @@ NetEConst* NetEBComp::must_be_leeq_(NetExpr*le, const verinum&rv, bool eq_flag)
return 0;
}
NetEConst* NetEBComp::eval_leeq_real_(NetExpr*le, NetExpr*re, bool eq_flag)
NetEConst* NetEBComp::eval_leeq_real_(const NetExpr*le, const NetExpr*re, bool eq_flag) const
{
double lval;
double rval;
@ -358,14 +377,13 @@ NetEConst* NetEBComp::eval_leeq_real_(NetExpr*le, NetExpr*re, bool eq_flag)
return res;
}
NetEConst* NetEBComp::eval_leeq_()
NetEConst* NetEBComp::eval_leeq_(const NetExpr*le, const NetExpr*re) const
{
if (right_->expr_type() == IVL_VT_REAL ||
left_->expr_type() == IVL_VT_REAL)
return eval_leeq_real_(left_, right_, true);
if (le->expr_type() == IVL_VT_REAL || re->expr_type() == IVL_VT_REAL)
return eval_leeq_real_(le, re, true);
// assert(expr_type() == IVL_VT_LOGIC);
NetEConst*r = dynamic_cast<NetEConst*>(right_);
const NetEConst*r = dynamic_cast<const NetEConst*>(re);
if (r == 0) return 0;
verinum rv = r->value();
@ -375,18 +393,18 @@ NetEConst* NetEBComp::eval_leeq_()
return res;
}
if (left_->expr_width() == 0) {
if (le->expr_width() == 0) {
cerr << get_fileline() << ": internal error: Something wrong "
<< "with the left side width of <= ?" << endl;
cerr << get_fileline() << ": : " << *this << endl;
}
if (NetEConst*tmp = must_be_leeq_(left_, rv, true)) {
if (NetEConst*tmp = must_be_leeq_(le, rv, true)) {
return tmp;
}
/* Now go on to the normal test of the values. */
NetEConst*l = dynamic_cast<NetEConst*>(left_);
const NetEConst*l = dynamic_cast<const NetEConst*>(le);
if (l == 0) return 0;
verinum lv = l->value();
@ -407,13 +425,12 @@ NetEConst* NetEBComp::eval_leeq_()
}
}
NetEConst* NetEBComp::eval_gt_()
NetEConst* NetEBComp::eval_gt_(const NetExpr*le, const NetExpr*re) const
{
if (right_->expr_type() == IVL_VT_REAL ||
left_->expr_type() == IVL_VT_REAL)
return eval_leeq_real_(right_, left_, false);
if (le->expr_type() == IVL_VT_REAL || re->expr_type() == IVL_VT_REAL)
return eval_leeq_real_(re, le, false);
NetEConst*l = dynamic_cast<NetEConst*>(left_);
const NetEConst*l = dynamic_cast<const NetEConst*>(le);
if (l == 0) return 0;
verinum lv = l->value();
@ -423,12 +440,12 @@ NetEConst* NetEBComp::eval_gt_()
return res;
}
if (NetEConst*tmp = must_be_leeq_(right_, lv, false)) {
if (NetEConst*tmp = must_be_leeq_(re, lv, false)) {
return tmp;
}
/* Now go on to the normal test of the values. */
NetEConst*r = dynamic_cast<NetEConst*>(right_);
const NetEConst*r = dynamic_cast<const NetEConst*>(re);
if (r == 0) return 0;
verinum rv = r->value();
@ -449,13 +466,12 @@ NetEConst* NetEBComp::eval_gt_()
}
}
NetEConst* NetEBComp::eval_gteq_()
NetEConst* NetEBComp::eval_gteq_(const NetExpr*le, const NetExpr*re) const
{
if (right_->expr_type() == IVL_VT_REAL ||
left_->expr_type() == IVL_VT_REAL)
return eval_leeq_real_(right_, left_, true);
if (le->expr_type() == IVL_VT_REAL || re->expr_type() == IVL_VT_REAL)
return eval_leeq_real_(re, le, true);
NetEConst*l = dynamic_cast<NetEConst*>(left_);
const NetEConst*l = dynamic_cast<const NetEConst*>(left_);
if (l == 0) return 0;
verinum lv = l->value();
@ -465,12 +481,12 @@ NetEConst* NetEBComp::eval_gteq_()
return res;
}
if (NetEConst*tmp = must_be_leeq_(right_, lv, true)) {
if (NetEConst*tmp = must_be_leeq_(re, lv, true)) {
return tmp;
}
/* Now go on to the normal test of the values. */
NetEConst*r = dynamic_cast<NetEConst*>(right_);
const NetEConst*r = dynamic_cast<const NetEConst*>(re);
if (r == 0) return 0;
verinum rv = r->value();
@ -498,15 +514,15 @@ NetEConst* NetEBComp::eval_gteq_()
* are equal, but there are are x/z bits, then the situation is
* ambiguous so the result is x.
*/
NetEConst* NetEBComp::eval_eqeq_real_(bool ne_flag)
NetEConst* NetEBComp::eval_eqeq_real_(bool ne_flag, const NetExpr*le, const NetExpr*re) const
{
verireal lval;
verireal rval;
double lval;
double rval;
bool flag = get_real_arguments_(lval, rval);
bool flag = get_real_arguments(le, re, lval, rval);
if (! flag) return 0;
verinum result(((lval.as_double() == rval.as_double()) ^ ne_flag) ?
verinum result(((lval == rval) ^ ne_flag) ?
verinum::V1 : verinum::V0, 1);
NetEConst*res = new NetEConst(result);
ivl_assert(*this, res);
@ -514,14 +530,14 @@ NetEConst* NetEBComp::eval_eqeq_real_(bool ne_flag)
return res;
}
NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
NetEConst* NetEBComp::eval_eqeq_(bool ne_flag, const NetExpr*le, const NetExpr*re) const
{
if (left_->expr_type() == IVL_VT_REAL ||
right_->expr_type() == IVL_VT_REAL)
return eval_eqeq_real_(ne_flag);
if (le->expr_type() == IVL_VT_REAL ||
re->expr_type() == IVL_VT_REAL)
return eval_eqeq_real_(ne_flag, le, re);
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
const NetEConst*lc = dynamic_cast<const NetEConst*>(le);
const NetEConst*rc = dynamic_cast<const NetEConst*>(re);
if (lc == 0 || rc == 0) return 0;
const verinum&lv = lc->value();
@ -631,10 +647,10 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
return result;
}
NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag)
NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr*re) const
{
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
const NetEConst*lc = dynamic_cast<const NetEConst*>(le);
const NetEConst*rc = dynamic_cast<const NetEConst*>(re);
if (lc == 0 || rc == 0) return 0;
const verinum&lv = lc->value();
@ -687,47 +703,54 @@ NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag)
return result;
}
NetEConst* NetEBComp::eval_arguments_(const NetExpr*l, const NetExpr*r) const
{
NetEConst*res = 0;
switch (op_) {
case 'E': // Case equality (===)
res = eval_eqeqeq_(false, l, r);
break;
case 'e': // Equality (==)
res = eval_eqeq_(false, l, r);
break;
case 'G': // >=
res = eval_gteq_(l, r);
break;
case 'L': // <=
res = eval_leeq_(l, r);
break;
case 'N': // Case inequality (!==)
res = eval_eqeqeq_(true, l, r);
break;
case 'n': // not-equal (!=)
res = eval_eqeq_(true, l, r);
break;
case '<': // Less than
res = eval_less_(l, r);
break;
case '>': // Greater than
res = eval_gt_(l, r);
break;
}
return res;
}
NetEConst* NetEBComp::eval_tree()
{
eval_expr(left_);
eval_expr(right_);
NetEConst*res = 0;
switch (op_) {
case 'E': // Case equality (===)
res = eval_eqeqeq_(false);
break;
case 'e': // Equality (==)
res = eval_eqeq_(false);
break;
case 'G': // >=
res = eval_gteq_();
break;
case 'L': // <=
res = eval_leeq_();
break;
case 'N': // Case inequality (!==)
res = eval_eqeqeq_(true);
break;
case 'n': // not-equal (!=)
res = eval_eqeq_(true);
break;
case '<': // Less than
res = eval_less_();
break;
case '>': // Greater than
res = eval_gt_();
break;
}
NetEConst*res = eval_arguments_(left_, right_);
if (res == 0) return 0;
res->set_line(*this);
@ -934,15 +957,15 @@ NetEConst* NetEBLogic::eval_tree()
}
NetExpr* NetEBMult::eval_tree_real_()
NetExpr* NetEBMult::eval_tree_real_(const NetExpr*l, const NetExpr*r) const
{
verireal lval;
verireal rval;
double lval;
double rval;
bool flag = get_real_arguments_(lval, rval);
bool flag = get_real_arguments(l, r, lval, rval);
if (! flag) return 0;
NetECReal*res = new NetECReal(lval * rval);
NetECReal*res = new NetECReal( verireal(lval * rval) );
ivl_assert(*this, res);
res->set_line(*this);
@ -958,11 +981,16 @@ NetExpr* NetEBMult::eval_tree()
eval_expr(left_);
eval_expr(right_);
if (expr_type() == IVL_VT_REAL) return eval_tree_real_();
return eval_arguments_(left_, right_);
}
NetExpr* NetEBMult::eval_arguments_(const NetExpr*l, const NetExpr*r) const
{
if (expr_type() == IVL_VT_REAL) return eval_tree_real_(l,r);
assert(expr_type() == IVL_VT_LOGIC);
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
const NetEConst*lc = dynamic_cast<const NetEConst*>(l);
const NetEConst*rc = dynamic_cast<const NetEConst*>(r);
if (lc == 0 || rc == 0) return 0;
verinum lval = lc->value();
@ -1043,9 +1071,13 @@ NetEConst* NetEBShift::eval_tree()
{
eval_expr(left_);
eval_expr(right_);
return eval_arguments_(left_,right_);
}
NetEConst*le = dynamic_cast<NetEConst*>(left_);
NetEConst*re = dynamic_cast<NetEConst*>(right_);
NetEConst* NetEBShift::eval_arguments_(const NetExpr*l, const NetExpr*r) const
{
const NetEConst*le = dynamic_cast<const NetEConst*>(l);
const NetEConst*re = dynamic_cast<const NetEConst*>(r);
if (le == 0 || re == 0) return 0;
NetEConst*res;
@ -1098,7 +1130,7 @@ NetEConst* NetEConcat::eval_tree()
}
unsigned gap = 0;
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
// Parameter not here? This is an error, but presumably
// already caught and we are here just to catch more.
@ -1149,7 +1181,7 @@ NetEConst* NetEConcat::eval_tree()
unsigned cur = 0;
bool is_string_flag = true;
for (unsigned idx = parms_.count() ; idx > 0 ; idx -= 1) {
for (unsigned idx = parms_.size() ; idx > 0 ; idx -= 1) {
NetEConst*expr = dynamic_cast<NetEConst*>(parms_[idx-1]);
if (expr == 0)
return 0;
@ -1314,12 +1346,18 @@ NetExpr* NetETernary::eval_tree()
eval_expr(true_val_);
eval_expr(false_val_);
NetEConst*t = dynamic_cast<NetEConst*>(true_val_);
NetEConst*f = dynamic_cast<NetEConst*>(false_val_);
return blended_arguments_(true_val_, false_val_);
}
NetExpr*NetETernary::blended_arguments_(const NetExpr*te, const NetExpr*fe) const
{
const NetEConst*t = dynamic_cast<const NetEConst*>(te);
const NetEConst*f = dynamic_cast<const NetEConst*>(fe);
if (t == 0 || f == 0) {
verireal tv, fv;
if (!get_real_arg_(true_val_, tv)) return 0;
if (!get_real_arg_(false_val_, fv)) return 0;
if (!get_real_arg_(te, tv)) return 0;
if (!get_real_arg_(te, fv)) return 0;
verireal val = verireal(0.0);
if (tv.as_double() == fv.as_double()) val = tv;
@ -1963,8 +2001,16 @@ NetExpr* NetEUFunc::eval_tree()
}
if (need_const_) {
cerr << get_fileline() << ": sorry: Constant user functions are "
"not yet supported." << endl;
NetFuncDef*def = func_->func_def();
ivl_assert(*this, def);
vector<NetExpr*>args(parms_.size());
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1)
args[idx] = parms_[idx]->dup_expr();
NetExpr*res = def->evaluate_function(*this, args);
return res;
}
return 0;
}

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*

View File

@ -14,11 +14,8 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: hello_vpi.c,v 1.5 2007/01/17 05:35:48 steve Exp $"
#endif
/*
* This file contains an example VPI module to demonstrate the tools
@ -60,22 +57,3 @@ void (*vlog_startup_routines[])() = {
my_hello_register,
0
};
/*
* $Log: hello_vpi.c,v $
* Revision 1.5 2007/01/17 05:35:48 steve
* Fix typo is hello_vpi.c example.
*
* Revision 1.4 2006/10/30 22:46:25 steve
* Updates for Cygwin portability (pr1585922)
*
* Revision 1.3 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
* Revision 1.2 2002/08/11 23:47:04 steve
* Add missing Log and Ident strings.
*
* Revision 1.1 2002/04/18 03:25:16 steve
* More examples.
*
*/

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $Id: sqrt-virtex.v,v 1.5 2007/03/22 16:08:18 steve Exp $"
*/

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $Id: sqrt.vl,v 1.5 2007/03/22 16:08:18 steve Exp $"
*/

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
// This example describes a 16x1 RAM that can be synthesized into

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2012 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
@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
@ -24,6 +24,7 @@
# include <iostream>
# include "netlist.h"
# include "netvector.h"
# include "netmisc.h"
# include "ivl_assert.h"
@ -118,11 +119,11 @@ NetNet* NetEBAdd::synthesize(Design*des, NetScope*scope, NetExpr*root)
}
perm_string path = lsig->scope()->local_symbol();
NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, width);
netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0);
osig_vec->set_signed(has_sign());
NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->local_flag(true);
osig->data_type(expr_type());
osig->set_signed(has_sign());
perm_string oname = osig->scope()->local_symbol();
NetAddSub *adder = new NetAddSub(lsig->scope(), oname, width);
@ -173,11 +174,11 @@ NetNet* NetEBBits::synthesize(Design*des, NetScope*scope, NetExpr*root)
rsig = pad_to_width(des, rsig, width, *this);
assert(lsig->vector_width() == rsig->vector_width());
netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, width);
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->local_flag(true);
osig->data_type(expr_type());
perm_string oname = scope->local_symbol();
NetLogic*gate;
@ -243,11 +244,11 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope, NetExpr*root)
rsig = pad_to_width(des, rsig, width, *this);
}
netvector_t*osig_vec = new netvector_t(IVL_VT_LOGIC);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->local_flag(true);
osig->data_type(IVL_VT_LOGIC);
// Test if the comparison is signed.
//
@ -390,11 +391,11 @@ NetNet* NetEBPow::synthesize(Design*des, NetScope*scope, NetExpr*root)
connect(powr->pin_DataA(), lsig->pin(0));
connect(powr->pin_DataB(), rsig->pin(0));
netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0);
osig_vec->set_signed(has_sign());
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, width);
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->data_type(expr_type());
osig->set_signed(has_sign());
osig->local_flag(true);
connect(powr->pin_Result(), osig->pin(0));
@ -427,11 +428,11 @@ NetNet* NetEBMult::synthesize(Design*des, NetScope*scope, NetExpr*root)
connect(mult->pin_DataA(), lsig->pin(0));
connect(mult->pin_DataB(), rsig->pin(0));
netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0);
osig_vec->set_signed(has_sign());
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, width);
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->data_type(expr_type());
osig->set_signed(has_sign());
osig->local_flag(true);
connect(mult->pin_Result(), osig->pin(0));
@ -452,11 +453,11 @@ NetNet* NetEBDiv::synthesize(Design*des, NetScope*scope, NetExpr*root)
if (real_args) width = 1;
else width = expr_width();
netvector_t*osig_vec = new netvector_t(lsig->data_type(), width-1, 0);
osig_vec->set_signed(has_sign());
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, width);
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->data_type(lsig->data_type());
osig->set_signed(has_sign());
osig->local_flag(true);
switch (op()) {
@ -530,10 +531,10 @@ NetNet* NetEBLogic::synthesize(Design*des, NetScope*scope, NetExpr*root)
return 0;
}
netvector_t*osig_tmp = new netvector_t(expr_type());
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
NetNet::IMPLICIT, osig_tmp);
osig->set_line(*this);
osig->data_type(expr_type());
osig->local_flag(true);
NetLogic*olog;
@ -597,10 +598,10 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root)
if (shift == 0)
return lsig;
netvector_t*osig_vec = new netvector_t(expr_type(), expr_width()-1,0);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->data_type(expr_type());
osig->local_flag(true);
// ushift is the amount of pad created by the shift.
@ -618,10 +619,10 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root)
psel->set_line(*this);
des->add_node(psel);
netvector_t*psig_vec = new netvector_t(expr_type(), part_width-1, 0);
NetNet*psig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, part_width);
NetNet::IMPLICIT, psig_vec);
psig->set_line(*this);
psig->data_type(expr_type());
psig->local_flag(true);
connect(psig->pin(0), psel->pin(0));
@ -646,10 +647,11 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root)
znum);
des->add_node(zcon);
netvector_t*zsig_vec = new netvector_t(osig->data_type(),
znum.len()-1, 0);
NetNet*zsig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, znum.len());
NetNet::WIRE, zsig_vec);
zsig->set_line(*this);
zsig->data_type(osig->data_type());
zsig->local_flag(true);
connect(zcon->pin(0), zsig->pin(0));
@ -676,10 +678,10 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root)
if (rsig == 0) return 0;
netvector_t*osig_vec = new netvector_t(expr_type(), expr_width()-1, 0);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->data_type(expr_type());
osig->local_flag(true);
NetCLShift*dev = new NetCLShift(scope, scope->local_symbol(),
@ -702,11 +704,11 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root)
NetNet* NetEConcat::synthesize(Design*des, NetScope*scope, NetExpr*root)
{
/* First, synthesize the operands. */
unsigned num_parms = parms_.count();
NetNet**tmp = new NetNet*[parms_.count()];
unsigned num_parms = parms_.size();
NetNet**tmp = new NetNet*[parms_.size()];
bool flag = true;
ivl_variable_type_t data_type = IVL_VT_NO_TYPE;
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
if (parms_[idx]->expr_width() == 0) {
/* We need to synthesize a replication of zero. */
tmp[idx] = parms_[idx]->synthesize(des, scope, root);
@ -739,10 +741,10 @@ NetNet* NetEConcat::synthesize(Design*des, NetScope*scope, NetExpr*root)
/* Make a NetNet object to carry the output vector. */
perm_string path = scope->local_symbol();
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, expr_width());
netvector_t*osig_vec = new netvector_t(data_type, expr_width()-1, 0);
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->local_flag(true);
osig->data_type(data_type);
NetConcat*concat = new NetConcat(scope, scope->local_symbol(),
osig->vector_width(),
@ -754,8 +756,8 @@ NetNet* NetEConcat::synthesize(Design*des, NetScope*scope, NetExpr*root)
unsigned count_input_width = 0;
unsigned cur_pin = 1;
for (unsigned rpt = 0; rpt < repeat(); rpt += 1) {
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
unsigned concat_item = parms_.count()-idx-1;
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
unsigned concat_item = parms_.size()-idx-1;
if (tmp[concat_item] == 0) continue;
connect(concat->pin(cur_pin), tmp[concat_item]->pin(0));
cur_pin += 1;
@ -785,11 +787,11 @@ NetNet* NetEConst::synthesize(Design*des, NetScope*scope, NetExpr*)
return 0;
}
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width);
netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0);
osig_vec->set_signed(has_sign());
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->local_flag(true);
osig->data_type(expr_type());
osig->set_signed(has_sign());
NetConst*con = new NetConst(scope, scope->local_symbol(), value());
con->set_line(*this);
@ -806,11 +808,11 @@ NetNet* NetECReal::synthesize(Design*des, NetScope*scope, NetExpr*)
{
perm_string path = scope->local_symbol();
NetNet*osig = new NetNet(scope, path, NetNet::WIRE, 1);
netvector_t*osig_vec = new netvector_t(IVL_VT_REAL);
osig_vec->set_signed(has_sign());
NetNet*osig = new NetNet(scope, path, NetNet::WIRE, osig_vec);
osig->set_line(*this);
osig->local_flag(true);
osig->data_type(IVL_VT_REAL);
osig->set_signed(has_sign());
NetLiteral*con = new NetLiteral(scope, scope->local_symbol(), value_);
con->set_line(*this);
@ -839,10 +841,10 @@ NetNet* NetEUBits::synthesize(Design*des, NetScope*scope, NetExpr*root)
}
unsigned width = isig->vector_width();
netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, width);
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->data_type(expr_type());
osig->local_flag(true);
perm_string oname = scope->local_symbol();
@ -882,11 +884,12 @@ NetNet* NetEUnary::synthesize(Design*des, NetScope*scope, NetExpr*root)
if (expr_->has_sign() == false)
return sub;
netvector_t*sig_vec = new netvector_t(sub->data_type(),
sub->vector_width()-1, 0);
NetNet*sig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, sub->vector_width());
NetNet::WIRE, sig_vec);
sig->set_line(*this);
sig->local_flag(true);
sig->data_type(sub->data_type());
NetAbs*tmp = new NetAbs(scope, scope->local_symbol(), sub->vector_width());
tmp->set_line(*this);
@ -956,10 +959,10 @@ NetNet* NetEUReduce::synthesize(Design*des, NetScope*scope, NetExpr*root)
gate->set_line(*this);
des->add_node(gate);
netvector_t*osig_vec = new netvector_t(expr_type());
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->data_type(expr_type());
osig->local_flag(true);
connect(gate->pin(0), osig->pin(0));
@ -1006,8 +1009,6 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
if (sub == 0) return 0;
NetNet*off = 0;
// Detect the special case that there is a base expression and
// it is constant. In this case we can generate fixed part selects.
if (NetEConst*base_const = dynamic_cast<NetEConst*>(base_)) {
@ -1064,10 +1065,12 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
NetPartSelect::VP);
des->add_node(sel);
ivl_assert(*this, select_width > 0);
netvector_t*tmp_vec = new netvector_t(sub->data_type(),
select_width-1, 0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, select_width);
NetNet::WIRE, tmp_vec);
tmp->set_line(*this);
tmp->data_type(sub->data_type());
tmp->local_flag(true);
connect(sel->pin(0), tmp->pin(0));
@ -1091,10 +1094,10 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
connect(cat->pin(concat_count), above->pin(0));
}
tmp_vec = new netvector_t(sub->data_type(), expr_width()-1, 0);
tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, expr_width());
NetNet::WIRE, tmp_vec);
tmp->set_line(*this);
tmp->data_type(sub->data_type());
tmp->local_flag(true);
connect(cat->pin(0), tmp->pin(0));
}
@ -1105,16 +1108,17 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
// actual part/bit select. Generate a NetPartSelect object to
// do the work, and replace "sub" with the selected output.
if (base_ != 0) {
off = base_->synthesize(des, scope, root);
NetNet*off = base_->synthesize(des, scope, root);
NetPartSelect*sel = new NetPartSelect(sub, off, expr_width(),
base_->has_sign());
sel->set_line(*this);
des->add_node(sel);
netvector_t*tmp_vec = new netvector_t(sub->data_type(),
expr_width()-1, 0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
tmp->data_type(sub->data_type());
NetNet::IMPLICIT, tmp_vec);
tmp->local_flag(true);
tmp->set_line(*this);
sub = tmp;
@ -1135,10 +1139,11 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
// extension or 0 extension, depending on the has_sign() mode
// of the expression.
netvector_t*net_vec = new netvector_t(expr_type(), expr_width()-1, 0);
net_vec->set_signed(has_sign());
NetNet*net = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
NetNet::IMPLICIT, net_vec);
net->set_line(*this);
net->data_type(expr_type());
net->local_flag(true);
if (has_sign()) {
NetSignExtend*pad = new NetSignExtend(scope,
@ -1149,7 +1154,6 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
connect(pad->pin(1), sub->pin(0));
connect(pad->pin(0), net->pin(0));
net->set_signed(true);
} else {
@ -1166,10 +1170,10 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
con->set_line(*this);
des->add_node(con);
netvector_t*tmp_vec = new netvector_t(expr_type(), pad_width-1, 0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, pad_width);
NetNet::IMPLICIT, tmp_vec);
tmp->set_line(*this);
tmp->data_type(expr_type());
tmp->local_flag(true);
connect(tmp->pin(0), con->pin(0));
@ -1221,9 +1225,9 @@ NetNet* NetETernary::synthesize(Design *des, NetScope*scope, NetExpr*root)
ivl_assert(*this, csig->vector_width() == 1);
unsigned width=expr_width();
NetNet*osig = new NetNet(csig->scope(), path, NetNet::IMPLICIT, width);
netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0);
NetNet*osig = new NetNet(csig->scope(), path, NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->data_type(expr_type());
osig->local_flag(true);
/* Make sure the types match. */
@ -1266,11 +1270,12 @@ NetNet* NetESignal::synthesize(Design*des, NetScope*scope, NetExpr*root)
if (word_ == 0)
return net_;
netvector_t*tmp_vec = new netvector_t(net_->data_type(),
net_->vector_width()-1, 0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, net_->vector_width());
NetNet::IMPLICIT, tmp_vec);
tmp->set_line(*this);
tmp->local_flag(true);
tmp->data_type(net_->data_type());
// For NetExpr objects, the word index is already converted to
// a canonical (lsb==0) address. Just use the index directly.
@ -1355,12 +1360,12 @@ NetNet* NetESFunc::synthesize(Design*des, NetScope*scope, NetExpr*root)
net->set_line(*this);
des->add_node(net);
netvector_t*osig_vec = new netvector_t(def->type, def->wid-1, 0);
osig_vec->set_signed(def->type==IVL_VT_REAL? true : false);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, def->wid);
NetNet::WIRE, osig_vec);
osig->set_line(*this);
osig->local_flag(true);
osig->set_signed(def->type==IVL_VT_REAL? true : false);
osig->data_type(def->type);
connect(net->pin(0), osig->pin(0));
@ -1386,11 +1391,11 @@ NetNet* NetESFunc::synthesize(Design*des, NetScope*scope, NetExpr*root)
NetNet* NetEUFunc::synthesize(Design*des, NetScope*scope, NetExpr*root)
{
svector<NetNet*> eparms (parms_.count());
vector<NetNet*> eparms (parms_.size());
/* Synthesize the arguments. */
bool errors = false;
for (unsigned idx = 0; idx < eparms.count(); idx += 1) {
for (unsigned idx = 0; idx < eparms.size(); idx += 1) {
if (dynamic_cast<NetEEvent*> (parms_[idx])) {
errors = true;
continue;
@ -1423,16 +1428,17 @@ NetNet* NetEUFunc::synthesize(Design*des, NetScope*scope, NetExpr*root)
des->add_node(net);
/* Create an output signal and connect it to the function. */
netvector_t*osig_vec = new netvector_t(result_sig_->expr_type(),
result_sig_->vector_width()-1, 0);
NetNet*osig = new NetNet(scope_, scope_->local_symbol(), NetNet::WIRE,
result_sig_->vector_width());
osig_vec);
osig->set_line(*this);
osig->local_flag(true);
osig->data_type(result_sig_->expr_type());
connect(net->pin(0), osig->pin(0));
/* Connect the pins to the arguments. */
NetFuncDef*def = func_->func_def();
for (unsigned idx = 0; idx < eparms.count(); idx += 1) {
for (unsigned idx = 0; idx < eparms.size(); idx += 1) {
unsigned width = def->port(idx)->vector_width();
NetNet*tmp;
if (eparms[idx]->get_signed()) {

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "config.h"
@ -24,6 +24,8 @@
# include "functor.h"
# include "netlist.h"
using namespace std;
functor_t::~functor_t()
{
}
@ -52,6 +54,10 @@ void functor_t::lpm_compare(Design*, NetCompare*)
{
}
void functor_t::lpm_concat(Design*, NetConcat*)
{
}
void functor_t::lpm_const(Design*, NetConst*)
{
}
@ -84,6 +90,10 @@ void functor_t::lpm_mux(Design*, NetMux*)
{
}
void functor_t::lpm_part_select(Design*, NetPartSelect*)
{
}
void functor_t::lpm_pow(Design*, NetPow*)
{
}
@ -185,6 +195,11 @@ void NetCompare::functor_node(Design*des, functor_t*fun)
fun->lpm_compare(des, this);
}
void NetConcat::functor_node(Design*des, functor_t*fun)
{
fun->lpm_concat(des, this);
}
void NetConst::functor_node(Design*des, functor_t*fun)
{
fun->lpm_const(des, this);
@ -225,6 +240,11 @@ void NetMux::functor_node(Design*des, functor_t*fun)
fun->lpm_mux(des, this);
}
void NetPartSelect::functor_node(Design*des, functor_t*fun)
{
fun->lpm_part_select(des, this);
}
void NetPow::functor_node(Design*des, functor_t*fun)
{
fun->lpm_pow(des, this);

View File

@ -1,7 +1,7 @@
#ifndef __functor_H
#define __functor_H
/*
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2008,2012 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
@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*
@ -57,6 +57,9 @@ struct functor_t {
/* This method is called for each structural comparator. */
virtual void lpm_compare(class Design*des, class NetCompare*);
/* This method is called for each structural concatenation. */
virtual void lpm_concat(class Design*des, class NetConcat*);
/* This method is called for each structural constant. */
virtual void lpm_const(class Design*des, class NetConst*);
@ -81,6 +84,8 @@ struct functor_t {
/* This method is called for each MUX. */
virtual void lpm_mux(class Design*des, class NetMux*);
virtual void lpm_part_select(class Design*des, class NetPartSelect*);
/* This method is called for each power. */
virtual void lpm_pow(class Design*des, class NetPow*);

View File

@ -14,7 +14,7 @@
# You should have received a copy of the GNU Library General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc.,
# 59 Temple Place - Suite 330
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# Boston, MA 02111-1307, USA
#
@ -28,7 +28,7 @@ SUFFIX=@SUFFIX@
# These are used for linking...
LD=$CC
LDFLAGS="@SHARED@ -L@LIBDIR@"
LDFLAGS="@IVCTARGETFLAGS@ @SHARED@ -L@LIBDIR@"
LDLIBS="-lveriuser$SUFFIX -lvpi$SUFFIX"
CCSRC=

42
ivl.def
View File

@ -63,6 +63,7 @@ ivl_expr_file
ivl_expr_lineno
ivl_expr_name
ivl_expr_nature
ivl_expr_net_type
ivl_expr_opcode
ivl_expr_oper1
ivl_expr_oper2
@ -70,6 +71,7 @@ ivl_expr_oper3
ivl_expr_parameter
ivl_expr_parm
ivl_expr_parms
ivl_expr_property_idx
ivl_expr_repeat
ivl_expr_scope
ivl_expr_sel_type
@ -140,6 +142,7 @@ ivl_lpm_width
ivl_lval_idx
ivl_lval_mux
ivl_lval_part_off
ivl_lval_property_idx
ivl_lval_sel_type
ivl_lval_sig
ivl_lval_width
@ -166,6 +169,7 @@ ivl_parameter_basename
ivl_parameter_expr
ivl_parameter_file
ivl_parameter_lineno
ivl_parameter_local
ivl_path_condit
ivl_path_delay
@ -175,10 +179,21 @@ ivl_path_source
ivl_path_source_negedge
ivl_path_source_posedge
ivl_process_analog
ivl_process_attr_cnt
ivl_process_attr_val
ivl_process_file
ivl_process_lineno
ivl_process_scope
ivl_process_stmt
ivl_process_type
ivl_scope_attr_cnt
ivl_scope_attr_val
ivl_scope_basename
ivl_scope_children
ivl_scope_class
ivl_scope_classes
ivl_scope_def
ivl_scope_def_file
ivl_scope_def_lineno
@ -194,6 +209,10 @@ ivl_scope_logs
ivl_scope_log
ivl_scope_lpms
ivl_scope_lpm
ivl_scope_mod_module_ports
ivl_scope_mod_module_port_name
ivl_scope_mod_module_port_type
ivl_scope_mod_module_port_width
ivl_scope_mod_port
ivl_scope_name
ivl_scope_param
@ -228,6 +247,7 @@ ivl_signal_local
ivl_signal_lsb
ivl_signal_msb
ivl_signal_name
ivl_signal_net_type
ivl_signal_nex
ivl_signal_npath
ivl_signal_packed_dimensions
@ -240,18 +260,6 @@ ivl_signal_signed
ivl_signal_type
ivl_signal_width
ivl_path_delay
ivl_path_source
ivl_process_analog
ivl_process_attr_cnt
ivl_process_attr_val
ivl_process_file
ivl_process_lineno
ivl_process_scope
ivl_process_stmt
ivl_process_type
ivl_statement_type
ivl_stmt_block_count
@ -296,6 +304,16 @@ ivl_switch_scope
ivl_switch_type
ivl_switch_width
ivl_type_base
ivl_type_element
ivl_type_name
ivl_type_packed_dimensions
ivl_type_packed_lsb
ivl_type_packed_msb
ivl_type_prop_name
ivl_type_prop_type
ivl_type_properties
ivl_udp_init
ivl_udp_file
ivl_udp_lineno

View File

@ -14,7 +14,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __ivl_assert_h

View File

@ -1,7 +1,7 @@
#ifndef __ivl_target_H
#define __ivl_target_H
/*
* Copyright (c) 2000-2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2012 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
@ -16,17 +16,24 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include <inttypes.h>
/* Re the _CLASS define: clang++ wants this to be class to match the
* definition, but clang (the C) compiler needs it to be a struct
* since class is not defined in C. They are effecively both pointers
* to an object so everything works out. */
#ifdef __cplusplus
#define _BEGIN_DECL extern "C" {
#define _END_DECL }
#define _CLASS class
#else
#define _BEGIN_DECL
#define _END_DECL
#define _CLASS struct
#endif
#ifndef __GNUC__
@ -157,21 +164,8 @@ typedef struct ivl_array_s *ivl_array_t;
typedef struct ivl_branch_s *ivl_branch_t;
typedef struct ivl_delaypath_s*ivl_delaypath_t;
typedef struct ivl_design_s *ivl_design_t;
/* clang++ wants this to be class to match the definition, but clang
* (the C) compiler needs it to be a struct since class is not defined
* in C. They are effecively both pointers to an object so everything
* works out. */
#ifdef __cplusplus
typedef class ivl_discipline_s*ivl_discipline_t;
#else
typedef struct ivl_discipline_s*ivl_discipline_t;
#endif
/* See the comments above. */
#ifdef __cplusplus
typedef class netenum_t *ivl_enumtype_t;
#else
typedef struct netenum_t *ivl_enumtype_t;
#endif
typedef _CLASS ivl_discipline_s*ivl_discipline_t;
typedef _CLASS netenum_t *ivl_enumtype_t;
typedef struct ivl_event_s *ivl_event_t;
typedef struct ivl_expr_s *ivl_expr_t;
typedef struct ivl_island_s *ivl_island_t;
@ -180,12 +174,7 @@ typedef struct ivl_lval_s *ivl_lval_t;
typedef struct ivl_net_const_s*ivl_net_const_t;
typedef struct ivl_net_logic_s*ivl_net_logic_t;
typedef struct ivl_udp_s *ivl_udp_t;
/* See the comments above. */
#ifdef __cplusplus
typedef class ivl_nature_s *ivl_nature_t;
#else
typedef struct ivl_nature_s *ivl_nature_t;
#endif
typedef _CLASS ivl_nature_s *ivl_nature_t;
typedef struct ivl_net_probe_s*ivl_net_probe_t;
typedef struct ivl_nexus_s *ivl_nexus_t;
typedef struct ivl_nexus_ptr_s*ivl_nexus_ptr_t;
@ -193,9 +182,11 @@ typedef struct ivl_parameter_s*ivl_parameter_t;
typedef struct ivl_process_s *ivl_process_t;
typedef struct ivl_scope_s *ivl_scope_t;
typedef struct ivl_signal_s *ivl_signal_t;
typedef struct ivl_port_info_s*ivl_port_info_t;
typedef struct ivl_switch_s *ivl_switch_t;
typedef struct ivl_memory_s *ivl_memory_t; //XXXX __attribute__((deprecated));
typedef struct ivl_statement_s*ivl_statement_t;
typedef const _CLASS ivl_type_s*ivl_type_t;
/*
* These are types that are defined as enumerations. These have
@ -233,7 +224,10 @@ typedef enum ivl_expr_type_e {
IVL_EX_ENUMTYPE = 21,
IVL_EX_EVENT = 17,
IVL_EX_MEMORY = 4,
IVL_EX_NEW = 23,
IVL_EX_NULL = 22,
IVL_EX_NUMBER = 5,
IVL_EX_PROPERTY = 24,
IVL_EX_REALNUM = 16,
IVL_EX_SCOPE = 6,
IVL_EX_SELECT = 7,
@ -363,7 +357,7 @@ typedef enum ivl_scope_type_e {
/* Signals (ivl_signal_t) that are ports into the scope that contains
them have a port type. Otherwise, they are port IVL_SIP_NONE. */
typedef enum ivl_signal_port_e {
typedef enum OUT {
IVL_SIP_NONE = 0,
IVL_SIP_INPUT = 1,
IVL_SIP_OUTPUT= 2,
@ -406,6 +400,8 @@ typedef enum ivl_statement_type_e {
IVL_ST_FORCE = 14,
IVL_ST_FOREVER = 15,
IVL_ST_FORK = 16,
IVL_ST_FORK_JOIN_ANY = 28,
IVL_ST_FORK_JOIN_NONE = 29,
IVL_ST_FREE = 26,
IVL_ST_RELEASE = 17,
IVL_ST_REPEAT = 18,
@ -432,6 +428,8 @@ typedef enum ivl_variable_type_e {
IVL_VT_BOOL = 3,
IVL_VT_LOGIC = 4,
IVL_VT_STRING = 5,
IVL_VT_DARRAY = 6, /* Array (esp. dynamic array) */
IVL_VT_CLASS = 7, /* SystemVerilog class instances */
IVL_VT_VECTOR = IVL_VT_LOGIC /* For compatibility */
} ivl_variable_type_t;
@ -770,6 +768,11 @@ extern unsigned ivl_event_lineno(ivl_event_t net);
* Get the data type of the expression node. This uses the variable
* type enum to express the type of the expression node.
*
* ivl_expr_net_type
* This is used in some cases to carry more advanced type
* descriptions. Over the long run, all type informatino will be
* moved into the ivl_type_t type description method.
*
* ivl_expr_width
* This method returns the bit width of the expression at this
* node. It can be applied to any expression node, and returns the
@ -802,6 +805,22 @@ extern unsigned ivl_event_lineno(ivl_event_t net);
*
* - IVL_EX_BINARY
*
* - IVL_EX_PROPERTY
* This expression represents the property select from a class
* type, for example "foo.property" where "foo" is a class handle and
* "property" is the name of one of the properties of the class. The
* ivl_expr_signal function returns the ivl_signal_t for "foo" and the
* data_type for the signal will be IVL_VT_CLASS.
*
* The ivl_signal_net_type(sig) for the "foo" signal will be a class
* type and from there you can get access to the type information.
*
* Elaboration reduces the properties of a class to a vector numbered
* from 0 to the number of properties. The ivl_expr_property_idx()
* function gets the index of the selected property into the property
* table. That number can be passed to ivl_type_prop_*() functions to
* get details about the property.
*
* - IVL_EX_SELECT
* This expression takes two operands, oper1 is the expression to
* select from, and oper2 is the selection base. The ivl_expr_width
@ -810,6 +829,14 @@ extern unsigned ivl_event_lineno(ivl_event_t net);
* conversion from signal units to vector units, so the result of
* ivl_expr_oper1 should range from 0 to ivl_expr_width().
*
* This exprsesion is also used to implement string substrings. If the
* sub-expression (oper1) is IVL_VT_STRING, then the base expression
* (oper2) is a charaster address, with 0 the first address of the
* string, 1 the second, and so on. This is OPPOSITE how a part select
* of a string cast to a vector works, to be aware. The size of the
* expression is an even multiple of 8, and is 8 times the number of
* characters to pick.
*
* - IVL_EX_SIGNAL
* This expression references a signal vector. The ivl_expr_signal
* function gets a handle for the signal that is referenced. The
@ -839,6 +866,7 @@ extern unsigned ivl_event_lineno(ivl_event_t net);
*/
extern ivl_expr_type_t ivl_expr_type(ivl_expr_t net);
extern ivl_type_t ivl_expr_net_type(ivl_expr_t net);
extern ivl_variable_type_t ivl_expr_value(ivl_expr_t net);
extern const char*ivl_expr_file(ivl_expr_t net);
extern unsigned ivl_expr_lineno(ivl_expr_t net);
@ -855,7 +883,7 @@ extern uint64_t ivl_expr_delay_val(ivl_expr_t net);
extern double ivl_expr_dvalue(ivl_expr_t net);
/* IVL_EX_ENUMTYPE */
extern ivl_enumtype_t ivl_expr_enumtype(ivl_expr_t net);
/* IVL_EX_SIGNAL, IVL_EX_SFUNC, IVL_EX_VARIABLE */
/* IVL_EX_PROPERTY IVL_EX_SIGNAL IVL_EX_SFUNC IVL_EX_VARIABLE */
extern const char* ivl_expr_name(ivl_expr_t net);
/* IVL_EX_BACCESS */
extern ivl_nature_t ivl_expr_nature(ivl_expr_t net);
@ -879,9 +907,11 @@ extern unsigned ivl_expr_repeat(ivl_expr_t net);
extern ivl_select_type_t ivl_expr_sel_type(ivl_expr_t net);
/* IVL_EX_EVENT */
extern ivl_event_t ivl_expr_event(ivl_expr_t net);
/* IVL_EX_PROPERTY */
extern int ivl_expr_property_idx(ivl_expr_t net);
/* IVL_EX_SCOPE */
extern ivl_scope_t ivl_expr_scope(ivl_expr_t net);
/* IVL_EX_SIGNAL */
/* IVL_EX_PROPERTY IVL_EX_SIGNAL */
extern ivl_signal_t ivl_expr_signal(ivl_expr_t net);
/* any expression */
extern int ivl_expr_signed(ivl_expr_t net);
@ -1419,6 +1449,11 @@ extern const char*ivl_lpm_string(ivl_lpm_t net);
* ivl_expr_t that represents the index expression. Otherwise, it
* returns 0.
*
* ivl_lval_property_idx
* If the l-value is a class object, this is the name of a property
* to select from the object. If this property is not present (<0)
* then the l-value represents the class object itself.
*
* SEMANTIC NOTES
* The ivl_lval_width is not necessarily the same as the width of the
* signal or memory word it represents. It is the width of the vector
@ -1444,6 +1479,7 @@ extern ivl_expr_t ivl_lval_mux(ivl_lval_t net); /* XXXX Obsolete? */
extern ivl_expr_t ivl_lval_idx(ivl_lval_t net);
extern ivl_expr_t ivl_lval_part_off(ivl_lval_t net);
extern ivl_select_type_t ivl_lval_sel_type(ivl_lval_t net);
extern int ivl_lval_property_idx(ivl_lval_t net);
extern ivl_signal_t ivl_lval_sig(ivl_lval_t net);
@ -1566,6 +1602,10 @@ extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net);
* Return the value of the parameter. This should be a simple
* constant expression, an IVL_EX_STRING or IVL_EX_NUMBER.
*
* ivl_parameter_local
* Return whether parameter was local (localparam, implicit genvar etc)
* or not.
*
* ivl_parameter_file
* ivl_parameter_lineno
* Returns the file and line where this parameter is defined
@ -1573,7 +1613,7 @@ extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net);
extern const char* ivl_parameter_basename(ivl_parameter_t net);
extern ivl_scope_t ivl_parameter_scope(ivl_parameter_t net);
extern ivl_expr_t ivl_parameter_expr(ivl_parameter_t net);
extern int ivl_parameter_local(ivl_parameter_t net);
extern const char* ivl_parameter_file(ivl_parameter_t net);
extern unsigned ivl_parameter_lineno(ivl_parameter_t net);
@ -1719,6 +1759,8 @@ extern ivl_statement_t ivl_scope_def(ivl_scope_t net);
extern const char* ivl_scope_def_file(ivl_scope_t net);
extern unsigned ivl_scope_def_lineno(ivl_scope_t net);
extern unsigned ivl_scope_classes(ivl_scope_t net);
extern ivl_type_t ivl_scope_class(ivl_scope_t net, unsigned idx);
extern unsigned ivl_scope_enumerates(ivl_scope_t net);
extern ivl_enumtype_t ivl_scope_enumerate(ivl_scope_t net, unsigned idx);
extern unsigned ivl_scope_events(ivl_scope_t net);
@ -1736,6 +1778,12 @@ extern const char* ivl_scope_basename(ivl_scope_t net);
extern unsigned ivl_scope_params(ivl_scope_t net);
extern ivl_parameter_t ivl_scope_param(ivl_scope_t net, unsigned idx);
extern ivl_scope_t ivl_scope_parent(ivl_scope_t net);
extern unsigned ivl_scope_mod_module_ports(ivl_scope_t net);
extern const char *ivl_scope_mod_module_port_name(ivl_scope_t net, unsigned idx );
extern ivl_signal_port_t ivl_scope_mod_module_port_type(ivl_scope_t net, unsigned idx );
extern unsigned ivl_scope_mod_module_port_width(ivl_scope_t net, unsigned idx );
extern unsigned ivl_scope_ports(ivl_scope_t net);
extern ivl_signal_t ivl_scope_port(ivl_scope_t net, unsigned idx);
extern ivl_nexus_t ivl_scope_mod_port(ivl_scope_t net, unsigned idx);
@ -1876,6 +1924,7 @@ extern int ivl_signal_msb(ivl_signal_t net) __attribute__((deprecated));
extern int ivl_signal_lsb(ivl_signal_t net) __attribute__((deprecated));
extern unsigned ivl_signal_width(ivl_signal_t net);
extern ivl_signal_port_t ivl_signal_port(ivl_signal_t net);
extern int ivl_signal_module_port_index(ivl_signal_t net);
extern int ivl_signal_signed(ivl_signal_t net);
extern int ivl_signal_integer(ivl_signal_t net);
extern int ivl_signal_local(ivl_signal_t net);
@ -1884,6 +1933,7 @@ extern unsigned ivl_signal_npath(ivl_signal_t net);
extern ivl_delaypath_t ivl_signal_path(ivl_signal_t net, unsigned idx);
extern ivl_signal_type_t ivl_signal_type(ivl_signal_t net);
extern ivl_variable_type_t ivl_signal_data_type(ivl_signal_t net);
extern ivl_type_t ivl_signal_net_type(ivl_signal_t net);
extern const char* ivl_signal_name(ivl_signal_t net);
extern const char* ivl_signal_basename(ivl_signal_t net);
extern const char* ivl_signal_attr(ivl_signal_t net, const char*key);
@ -1971,7 +2021,7 @@ extern unsigned ivl_stmt_lineno(ivl_statement_t net);
* Statements that have event arguments (TRIGGER and WAIT) make
* those event objects available through these methods.
*
* ivl_stmt_lval
* ivl_stmt_lval
* ivl_stmt_lvals
* Return the number of l-values for an assignment statement, or
* the specific l-value. If there is more than 1 l-value, then the
@ -2069,11 +2119,11 @@ extern unsigned ivl_stmt_lineno(ivl_statement_t net);
* triggers. The statement waits even if the sub-statement is nul.
*/
/* IVL_ST_BLOCK, IVL_ST_FORK */
/* IVL_ST_BLOCK, IVL_ST_FORK, IVL_ST_FORK_JOIN_ANY, IVL_ST_FORK_JOIN_NONE */
extern unsigned ivl_stmt_block_count(ivl_statement_t net);
/* IVL_ST_BLOCK, IVL_ST_FORK */
/* IVL_ST_BLOCK, IVL_ST_FORK, IVL_ST_FORK_JOIN_ANY, IVL_ST_FORK_JOIN_NONE */
extern ivl_scope_t ivl_stmt_block_scope(ivl_statement_t net);
/* IVL_ST_BLOCK, IVL_ST_FORK */
/* IVL_ST_BLOCK, IVL_ST_FORK, IVL_ST_FORK_JOIN_ANY, IVL_ST_FORK_JOIN_NONE */
extern ivl_statement_t ivl_stmt_block_stmt(ivl_statement_t net, unsigned i);
/* IVL_ST_UTASK IVL_ST_DISABLE */
extern ivl_scope_t ivl_stmt_call(ivl_statement_t net);
@ -2172,6 +2222,31 @@ extern ivl_attribute_t ivl_switch_attr_val(ivl_switch_t net, unsigned idx);
extern const char* ivl_switch_file(ivl_switch_t net);
extern unsigned ivl_switch_lineno(ivl_switch_t net);
/* TYPES
*
* ivl_type_base
* This returns the base type for the type. See the
* ivl_variable_type_t definition for the various base types.
*
* ivl_type_element
* Return the type of the element of an array. This is only valid
* for array types.
*
* SEMANTIC NOTES
*
* Class types have names and properties.
*/
extern ivl_variable_type_t ivl_type_base(ivl_type_t net);
extern ivl_type_t ivl_type_element(ivl_type_t net);
extern unsigned ivl_type_packed_dimensions(ivl_type_t net);
extern int ivl_type_packed_lsb(ivl_type_t net, unsigned dim);
extern int ivl_type_packed_msb(ivl_type_t net, unsigned dim);
extern const char* ivl_type_name(ivl_type_t net);
extern int ivl_type_properties(ivl_type_t net);
extern const char* ivl_type_prop_name(ivl_type_t net, int idx);
extern ivl_type_t ivl_type_prop_type(ivl_type_t net, int idx);
#if defined(__MINGW32__) || defined (__CYGWIN32__)
# define DLLEXPORT __declspec(dllexport)
#else

View File

@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "ivl_target.h"

View File

@ -14,9 +14,8 @@
#
# You should have received a copy of the GNU Library General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc.,
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.
#
SHELL = /bin/sh

View File

@ -16,7 +16,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include <stdio.h>

Some files were not shown because too many files have changed in this diff Show More