Merge branch 'master' into vec4-stack

Conflicts:
	elab_lval.cc
	netmisc.cc
	tgt-vvp/eval_object.c
	tgt-vvp/vvp_process.c
	vvp/codes.h
	vvp/compile.cc
	vvp/opcodes.txt
	vvp/vpi_tasks.cc
	vvp/vpi_vthr_vector.cc
	vvp/vthread.cc
This commit is contained in:
Stephen Williams 2014-10-21 09:12:02 -07:00
commit a98f21aa65
396 changed files with 15677 additions and 6331 deletions

View File

@ -1,7 +1,7 @@
#ifndef __AStatement_H
#define __AStatement_H
#ifndef IVL_AStatement_H
#define IVL_AStatement_H
/*
* Copyright (c) 2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008-2014 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
@ -82,4 +82,4 @@ class AProcess : public LineInfo {
AProcess& operator= (const AProcess&);
};
#endif
#endif /* IVL_AStatement_H */

View File

@ -1,7 +1,7 @@
#ifndef __Attrib_H
#define __Attrib_H
#ifndef IVL_Attrib_H
#define IVL_Attrib_H
/*
* Copyright (c) 2000-2009 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2014 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
@ -57,4 +57,4 @@ class Attrib {
Attrib& operator= (const Attrib&);
};
#endif
#endif /* IVL_Attrib_H */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -22,22 +22,26 @@
# include <iostream>
# include <cstring>
# include <cstdlib>
# include <climits>
using namespace std;
hname_t::hname_t()
{
number_ = INT_MIN;
}
hname_t::hname_t(perm_string text)
: name_(text)
{
number_ = INT_MIN;
}
hname_t::hname_t(perm_string text, int num)
: name_(text), number_(num)
: name_(text), number_(1)
{
number_[0] = num;
}
hname_t::hname_t(perm_string text, vector<int>&nums)
: name_(text), number_(nums)
{
}
@ -53,24 +57,50 @@ hname_t& hname_t::operator = (const hname_t&that)
return *this;
}
bool operator < (const hname_t&l, const hname_t&r)
bool hname_t::operator < (const hname_t&r) const
{
int cmp = strcmp(l.peek_name(), r.peek_name());
int cmp = strcmp(name_, r.name_);
if (cmp < 0) return true;
if (cmp > 0) return false;
if (l.has_number() && r.has_number())
return l.peek_number() < r.peek_number();
else
return false;
// The text parts are equal, so compare then number
// parts. Finish as soon as we find one to be less or more
// than the other.
size_t idx = 0;
while (number_.size() > idx || r.number_.size() > idx) {
// Ran out of l numbers, so less.
if (number_.size() <= idx)
return true;
// Ran out of r numbers, so greater.
if (r.number_.size() <= idx)
return false;
if (number_[idx] < r.number_[idx])
return true;
if (number_[idx] > r.number_[idx])
return false;
idx += 1;
}
// Fall-through means that we are equal, including all the
// number parts, so not less.
return false;
}
bool operator == (const hname_t&l, const hname_t&r)
bool hname_t::operator == (const hname_t&r) const
{
if (l.peek_name() == r.peek_name()) {
if (l.has_number() && r.has_number())
return l.peek_number() == r.peek_number();
else
return true;
if (name_ == r.name_) {
if (number_.size() != r.number_.size())
return false;
for (size_t idx = 0 ; idx < number_.size() ; idx += 1)
if (number_[idx] != r.number_[idx]) return false;
return true;
}
return false;
@ -84,8 +114,8 @@ ostream& operator<< (ostream&out, const hname_t&that)
}
out << that.peek_name();
if (that.has_number())
out << "[" << that.peek_number() << "]";
for (size_t idx = 0 ; idx < that.number_.size() ; idx += 1)
out << "[" << that.number_[idx] << "]";
return out;
}

40
HName.h
View File

@ -1,7 +1,7 @@
#ifndef __HName_H
#define __HName_H
#ifndef IVL_HName_H
#define IVL_HName_H
/*
* Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -21,13 +21,10 @@
# include <iostream>
# include <list>
# include <vector>
# include "StringHeap.h"
# include <climits>
#ifdef __GNUC__
#if __GNUC__ > 2
using namespace std;
#endif
#endif
# include <cassert>
/*
* This class represents a component of a Verilog hierarchical name. A
@ -39,27 +36,33 @@ using namespace std;
class hname_t {
friend ostream& operator<< (ostream&out, const hname_t&that);
public:
hname_t ();
explicit hname_t (perm_string text);
explicit hname_t (perm_string text, int num);
explicit hname_t (perm_string text, std::vector<int>&nums);
hname_t (const hname_t&that);
~hname_t();
hname_t& operator= (const hname_t&);
bool operator == (const hname_t&that) const;
bool operator < (const hname_t&that) const;
// Return the string part of the hname_t.
perm_string peek_name(void) const;
bool has_number() const;
int peek_number() const;
size_t has_numbers() const;
int peek_number(size_t idx) const;
private:
perm_string name_;
// If the number is anything other than INT_MIN, then this is
// the numeric part of the name. Otherwise, it is not part of
// the name at all.
int number_;
std::vector<int> number_;
private: // not implemented
};
@ -73,18 +76,17 @@ inline perm_string hname_t::peek_name(void) const
return name_;
}
inline int hname_t::peek_number() const
inline int hname_t::peek_number(size_t idx) const
{
return number_;
assert(number_.size() > idx);
return number_[idx];
}
inline bool hname_t::has_number() const
inline size_t hname_t::has_numbers() const
{
return number_ != INT_MIN;
return number_.size();
}
extern bool operator < (const hname_t&, const hname_t&);
extern bool operator == (const hname_t&, const hname_t&);
extern ostream& operator<< (ostream&, const hname_t&);
inline bool operator != (const hname_t&l, const hname_t&r)
@ -102,4 +104,4 @@ inline ostream& operator<< (ostream&out, const list<hname_t>&ll)
return out;
}
#endif
#endif /* IVL_HName_H */

View File

@ -68,7 +68,7 @@ dllib=@DLLIB@
# For a cross compile these defines will need to be set accordingly.
HOSTCC = @CC@
HOSTCFLAGS = @WARNING_FLAGS@ @CFLAGS@
HOSTCFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
CC = @CC@
CXX = @CXX@
@ -90,7 +90,7 @@ INCLUDE_PATH = -I. -I$(srcdir) -I$(srcdir)/libmisc
endif
CPPFLAGS = @DEFS@ $(INCLUDE_PATH) @CPPFLAGS@
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@
PICFLAGS = @PICFLAG@
LDFLAGS = @rdynamic@ @LDFLAGS@
@ -109,7 +109,7 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.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 netscalar.o netstruct.o netvector.o \
netenum.o netparray.o netqueue.o netscalar.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 \
@ -175,6 +175,8 @@ endif
cppcheck: $(O:.o=.cc) $(srcdir)/dosify.c $(srcdir)/version.c
cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \
-UYYPARSE_PARAM -UYYPRINT -Ushort -Usize_t -Uyyoverflow \
-UYYTYPE_INT8 -UYYTYPE_INT16 -UYYTYPE_UINT8 -UYYTYPE_UINT16 \
--relative-paths=$(srcdir) $(INCLUDE_PATH) $^
cppcheck-all:

View File

@ -1,7 +1,7 @@
#ifndef __Module_H
#define __Module_H
#ifndef IVL_Module_H
#define IVL_Module_H
/*
* Copyright (c) 1998-2010,2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2014 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
@ -160,4 +160,4 @@ class Module : public PScopeExtra, public LineInfo {
Module& operator= (const Module&);
};
#endif
#endif /* IVL_Module_H */

View File

@ -1,7 +1,7 @@
#ifndef __PClass_H
#define __PClass_H
#ifndef IVL_PClass_H
#define IVL_PClass_H
/*
* Copyright (c) 2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-2014 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
@ -44,4 +44,4 @@ class PClass : public PScopeExtra, public LineInfo {
class_type_t*type;
};
#endif
#endif /* IVL_PClass_H */

View File

@ -1,7 +1,7 @@
#ifndef __PDelays_H
#define __PDelays_H
#ifndef IVL_PDelays_H
#define IVL_PDelays_H
/*
* Copyright (c) 1999-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2014 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
@ -72,4 +72,4 @@ class PDelays {
ostream& operator << (ostream&o, const PDelays&);
#endif
#endif /* IVL_PDelays_H */

View File

@ -1,7 +1,7 @@
#ifndef __PEvent_H
#define __PEvent_H
#ifndef IVL_PEvent_H
#define IVL_PEvent_H
/*
* Copyright (c) 2000-2004 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2014 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
@ -51,4 +51,4 @@ class PEvent : public LineInfo {
PEvent& operator= (const PEvent&);
};
#endif
#endif /* IVL_PEvent_H */

31
PExpr.h
View File

@ -1,7 +1,7 @@
#ifndef __PExpr_H
#define __PExpr_H
#ifndef IVL_PExpr_H
#define IVL_PExpr_H
/*
* Copyright (c) 1998-2013 Stephen Williams <steve@icarus.com>
* Copyright (c) 1998-2014 Stephen Williams <steve@icarus.com>
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -245,6 +245,10 @@ class PEConcat : public PExpr {
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
unsigned flags) const;
@ -366,6 +370,11 @@ class PEIdent : public PExpr {
// only applies to Ident expressions.
NetNet* elaborate_subport(Design*des, NetScope*sc) const;
// Elaborate the identifier allowing for unpacked arrays. This
// method only applies to Ident expressions because only Ident
// expressions can can be unpacked arrays.
NetNet* elaborate_unpacked_net(Design*des, NetScope*sc) const;
verinum* eval_const(Design*des, NetScope*sc) const;
virtual bool is_collapsible_net(Design*des, NetScope*scope) const;
@ -500,12 +509,23 @@ class PEIdent : public PExpr {
NetESignal*net,
NetScope*found,
bool need_const) const;
NetExpr*elaborate_expr_net_bit_last_(Design*des,
NetScope*scope,
NetESignal*net,
NetScope*found,
bool need_const) const;
NetExpr*elaborate_expr_class_member_(Design*des,
NetScope*scope,
unsigned expr_wid,
unsigned flags) const;
unsigned test_width_method_(Design*des, NetScope*scope, width_mode_t&mode);
NetExpr*elaborate_expr_method_(Design*des,
NetScope*scope,
unsigned expr_wid,
unsigned flags) const;
private:
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
bool bidirectional_flag) const;
@ -916,7 +936,8 @@ class PECallFunction : public PExpr {
NetExpr*elaborate_expr_pkg_(Design*des, NetScope*scope,
unsigned expr_wid, unsigned flags)const;
NetExpr*elaborate_expr_method_(Design*des, NetScope*scope,
unsigned expr_wid) const;
unsigned expr_wid,
bool add_this_flag = false) const;
#if 0
NetExpr*elaborate_expr_string_method_(Design*des, NetScope*scope) const;
NetExpr*elaborate_expr_enum_method_(Design*des, NetScope*scope,
@ -980,4 +1001,4 @@ class PEVoid : public PExpr {
unsigned flags) const;
};
#endif
#endif /* IVL_PExpr_H */

View File

@ -1,7 +1,7 @@
#ifndef __PGate_H
#define __PGate_H
#ifndef IVL_PGate_H
#define IVL_PGate_H
/*
* Copyright (c) 1998-2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2014 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
@ -124,6 +124,7 @@ class PGAssign : public PGate {
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
private:
void elaborate_unpacked_array_(Design*des, NetScope*scope, NetNet*lval) const;
};
@ -259,4 +260,4 @@ class PGModule : public PGate {
NetNet::PortType dir, bool as_signed) const;
};
#endif
#endif /* IVL_PGate_H */

View File

@ -1,7 +1,7 @@
#ifndef __PGenerate_H
#define __PGenerate_H
#ifndef IVL_PGenerate_H
#define IVL_PGenerate_H
/*
* Copyright (c) 2006-2010,2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 2006-2014 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
@ -139,4 +139,4 @@ class PGenerate : public LineInfo, public LexicalScope {
extern std::ostream& operator << (std::ostream&, PGenerate::scheme_t);
#endif
#endif /* IVL_PGenerate_H */

View File

@ -1,7 +1,7 @@
#ifndef __PPackage_H
#define __PPackage_H
#ifndef IVL_PPackage_H
#define IVL_PPackage_H
/*
* Copyright (c) 2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -44,4 +44,4 @@ class PPackage : public PScopeExtra, public LineInfo {
void pform_dump(std::ostream&out) const;
};
#endif
#endif /* IVL_PPackage_H */

View File

@ -31,6 +31,9 @@ PScope::PScope(perm_string n)
PScope::~PScope()
{
for(map<perm_string, data_type_t*>::iterator it = typedefs.begin();
it != typedefs.end(); ++it)
delete it->second;
}
PWire* LexicalScope::wires_find(perm_string name)

View File

@ -1,7 +1,7 @@
#ifndef __PScope_H
#define __PScope_H
#ifndef IVL_PScope_H
#define IVL_PScope_H
/*
* Copyright (c) 2008,2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008-2014 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
@ -187,4 +187,4 @@ class PScopeExtra : public PScope {
void dump_funcs_(ostream&out, unsigned indent) const;
};
#endif
#endif /* IVL_PScope_H */

View File

@ -1,7 +1,7 @@
#ifndef __PSpec_H
#define __PSpec_H
#ifndef IVL_PSpec_H
#define IVL_PSpec_H
/*
* Copyright (c) 2006-2011 Stephen Williams <steve@icarus.com>
* Copyright (c) 2006-2014 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
@ -84,4 +84,4 @@ class PSpecPath : public LineInfo {
std::vector<class PExpr*>delays;
};
#endif
#endif /* IVL_PSpec_H */

14
PTask.h
View File

@ -1,7 +1,7 @@
#ifndef __PTask_H
#define __PTask_H
#ifndef IVL_PTask_H
#define IVL_PTask_H
/*
* Copyright (c) 1999-2008,2010,2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2014 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
@ -49,6 +49,12 @@ class PTaskFunc : public PScope, public LineInfo {
// to the class type.
inline class_type_t* method_of() const { return this_type_; }
virtual void elaborate_sig(Design*des, NetScope*scope) const =0;
virtual void elaborate(Design*des, NetScope*scope) const =0;
virtual void dump(std::ostream&, unsigned) const =0;
protected:
// Elaborate the ports list. Write into the ports vector the
// NetNet pointers for the ports, and write into the pdefs the
@ -146,4 +152,4 @@ class PFunction : public PTaskFunc {
bool is_auto_;
};
#endif
#endif /* IVL_PTask_H */

8
PUdp.h
View File

@ -1,7 +1,7 @@
#ifndef __PUdp_H
#define __PUdp_H
#ifndef IVL_PUdp_H
#define IVL_PUdp_H
/*
* Copyright (c) 1998-2011 Stephen Williams (steve@picturel.com)
* Copyright (c) 1998-2014 Stephen Williams (steve@picturel.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
@ -76,4 +76,4 @@ class PUdp : public LineInfo {
PUdp& operator= (const PUdp&);
};
#endif
#endif /* IVL_PUdp_H */

View File

@ -1,7 +1,7 @@
#ifndef __PWire_H
#define __PWire_H
#ifndef IVL_PWire_H
#define IVL_PWire_H
/*
* Copyright (c) 1998-2009,2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2014 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
@ -129,4 +129,4 @@ class PWire : public LineInfo {
PWire& operator= (const PWire&);
};
#endif
#endif /* IVL_PWire_H */

View File

@ -336,6 +336,20 @@ PForce::~PForce()
delete expr_;
}
PForeach::PForeach(perm_string av, const list<perm_string>&ix, Statement*s)
: array_var_(av), index_vars_(ix.size()), statement_(s)
{
size_t idx = 0;
for (list<perm_string>::const_iterator cur = ix.begin()
; cur != ix.end() ; ++cur)
index_vars_[idx++] = *cur;
}
PForeach::~PForeach()
{
delete statement_;
}
PForever::PForever(Statement*s)
: statement_(s)
{

View File

@ -1,7 +1,7 @@
#ifndef __Statement_H
#define __Statement_H
#ifndef IVL_Statement_H
#define IVL_Statement_H
/*
* Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2014 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
@ -224,12 +224,16 @@ 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;
NetProc*elaborate_method_(Design*des, NetScope*scope,
bool add_this_flag = false) const;
NetProc*elaborate_function_(Design*des, NetScope*scope) const;
NetProc*elaborate_build_call_(Design*des, NetScope*scope,
NetScope*task, NetExpr*use_this) const;
NetProc*elaborate_sys_task_method_(Design*des, NetScope*scope,
NetNet*net,
perm_string method_name,
const char*sys_task_name) const;
bool test_task_calls_ok_(Design*des, NetScope*scope) const;
PPackage*package_;
@ -440,6 +444,26 @@ class PForce : public Statement {
PExpr*expr_;
};
class PForeach : public Statement {
public:
explicit PForeach(perm_string var, const std::list<perm_string>&ix, Statement*stmt);
~PForeach();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
NetProc* elaborate_static_array_(Design*des, NetScope*scope,
const std::vector<netrange_t>&dims) const;
private:
perm_string array_var_;
std::vector<perm_string> index_vars_;
Statement*statement_;
};
class PForever : public Statement {
public:
explicit PForever(Statement*s);
@ -558,4 +582,4 @@ class PWhile : public Statement {
Statement*statement_;
};
#endif
#endif /* IVL_Statement_H */

View File

@ -1,7 +1,7 @@
#ifndef PLI_TYPES
#define PLI_TYPES
#ifndef PLI_TYPES_H
#define PLI_TYPES_H
/*
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
* Copyright (c) 2003-2014 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
@ -85,4 +85,4 @@ typedef char PLI_BYTE8;
typedef unsigned char PLI_UBYTE8;
#endif
#endif
#endif /* PLI_TYPES_H */

View File

@ -1,7 +1,7 @@
#ifndef __acc_user_H
#define __acc_user_H
#ifndef ACC_USER_H
#define ACC_USER_H
/*
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-2014 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
@ -228,6 +228,7 @@ extern PLI_INT32 acc_fetch_size(handle obj);
extern PLI_INT32 acc_fetch_type(handle obj);
extern PLI_INT32 acc_fetch_fulltype(handle obj);
extern PLI_INT32 acc_fetch_paramtype(handle obj);
extern PLI_INT32 acc_fetch_range(handle object, int *msb, int *lsb);
extern const char* acc_fetch_type_str(PLI_INT32 type);
@ -270,4 +271,4 @@ extern char* acc_version(void);
EXTERN_C_END
#endif
#endif /* ACC_USER_H */

11
aclocal.m4 vendored
View File

@ -218,17 +218,6 @@ AC_SUBST(strip_dynamic)
# AC_MSG_RESULT($strip_dynamic)
])# AX_LD_RDYNAMIC
# AX_CPP_PRECOMP
# --------------
AC_DEFUN([AX_CPP_PRECOMP],
[# Darwin requires -no-cpp-precomp
case "${host}" in
*-*-darwin*)
CPPFLAGS="-no-cpp-precomp $CPPFLAGS"
CFLAGS="-no-cpp-precomp $CFLAGS"
;;
esac
])# AX_CPP_PRECOMP
# AX_C99_STRTOD
# -------------

View File

@ -50,8 +50,8 @@ bool NetEvWait::is_asynchronous()
level sensitive, but the nex_async_ method takes care of
that test. */
NexusSet*sense = new NexusSet;
for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) {
NexusSet*tmp = event(idx)->nex_async_();
for (unsigned idx = 0 ; idx < events_.size() ; idx += 1) {
NexusSet*tmp = events_[idx]->nex_async_();
if (tmp == 0) {
delete sense;
return false;

View File

@ -43,7 +43,7 @@ INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
endif
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
LDFLAGS = @LDFLAGS@
O = cadpli.o

View File

@ -79,7 +79,7 @@ static void thunker_register(void)
}
}
void (*vlog_startup_routines[])() = {
void (*vlog_startup_routines[])(void) = {
thunker_register,
0
};

View File

@ -1,7 +1,7 @@
#ifndef __ivl_dlfcn_H
#define __ivl_dlfcn_H
#ifndef IVL_ivl_dlfcn_H
#define IVL_ivl_dlfcn_H
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2014 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
@ -91,4 +91,4 @@ static __inline__ const char*dlerror(void)
{ return strerror( errno ); }
#endif
#endif
#endif /* IVL_ivl_dlfcn_H */

View File

@ -1,5 +1,5 @@
#ifndef __compiler_H
#define __compiler_H
#ifndef IVL_compiler_H
#define IVL_compiler_H
/*
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
*
@ -283,4 +283,4 @@ extern void cleanup_sys_func_table();
*/
extern ivl_sfunc_as_task_t def_sfunc_as_task;
#endif
#endif /* IVL_compiler_H */

View File

@ -1,7 +1,7 @@
#ifndef __config_H /* -*- c++ -*- */
#define __config_H
#ifndef IVL_config_H /* -*- c++ -*- */
#define IVL_config_H
/*
* Copyright (c) 2001-2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2014 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
@ -62,4 +62,4 @@
*/
# undef CHECK_WITH_VALGRIND
#endif /* __config_H */
#endif /* IVL_config_H */

View File

@ -14,10 +14,6 @@ AC_CANONICAL_HOST
dnl Checks for programs.
AC_PROG_CC
# AC_PROG_CC_C99 is only available in autoconf version 2.60 and later.
# If you must use an older version then comment out the following two
# lines, but be warned that there could be issues with finding the
# nan(), etc. functions. It is really best to upgrade to a supported
# version of autoconf.
AC_PREREQ([2.60])
AC_PROG_CC_C99
AC_PROG_CXX
@ -85,8 +81,9 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
CFLAGS="$iverilog_temp_cflags"
AC_SUBST(DEPENDENCY_FLAG, [-MD])
AC_SUBST(WARNING_FLAGS, ["-Wall -Wshadow"])
AC_SUBST(WARNING_FLAGS_CXX, ["$iverilog_wextra_flag"])
AC_SUBST(WARNING_FLAGS, ["-Wall $iverilog_wextra_flag -Wshadow"])
AC_SUBST(WARNING_FLAGS_CC, [""])
AC_SUBST(WARNING_FLAGS_CXX, [""])
fi
AC_LANG(C++)
@ -217,9 +214,6 @@ AX_LD_EXTRALIBS
# CFLAGS inherited by cadpli/Makefile?
AX_C_PICFLAG
# may modify CPPFLAGS and CFLAGS
AX_CPP_PRECOMP
# may modify LDFLAGS
AX_C99_STRTOD

View File

@ -1,3 +1,3 @@
// These are correct and are used to find the base (zero) pin.
thisSubtraction:netlist.h:4589
thisSubtraction:netlist.h:4598
thisSubtraction:netlist.h:4938
thisSubtraction:netlist.h:4947

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2014 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
@ -30,6 +30,7 @@
# include "discipline.h"
# include "netclass.h"
# include "netdarray.h"
# include "netqueue.h"
# include "netvector.h"
# include "ivl_assert.h"
# include "PExpr.h"
@ -113,6 +114,9 @@ ostream& operator << (ostream&o, ivl_variable_type_t val)
case IVL_VT_CLASS:
o << "class";
break;
case IVL_VT_QUEUE:
o << "queue";
break;
}
return o;
}
@ -145,18 +149,87 @@ ostream& operator << (ostream&o, ivl_switch_type_t val)
return o;
}
ostream& operator << (ostream&fd, PortType::Enum val)
{
switch (val) {
case PortType::NOT_A_PORT:
fd << "NOT_A_PORT";
break;
case PortType::PIMPLICIT:
fd << "PIMPLICIT";
break;
case PortType::PINPUT:
fd << "PINPUT";
break;
case PortType::POUTPUT:
fd << "POUTPUT";
break;
case PortType::PINOUT:
fd << "PINOUT";
break;
case PortType::PREF:
fd << "PREF";
break;
default:
fd << "PortType::Enum::?";
break;
}
return fd;
}
ostream& operator << (ostream&fd, NetCaseCmp::kind_t that)
{
switch (that) {
case NetCaseCmp::EEQ:
fd << "===";
break;
case NetCaseCmp::NEQ:
fd << "!==";
break;
case NetCaseCmp::XEQ:
fd << "==?";
break;
case NetCaseCmp::ZEQ:
fd << "==z?";
break;
}
return fd;
}
ostream& ivl_type_s::debug_dump(ostream&o) const
{
o << typeid(*this).name();
return o;
}
ostream& netclass_t::debug_dump(ostream&fd) const
{
fd << "class " << name_ << "{";
for (size_t idx = 0 ; idx < property_table_.size() ; idx += 1) {
if (idx != 0) fd << "; ";
if (property_table_[idx].type)
property_table_[idx].type->debug_dump(fd);
else
fd << "NO_TYPE";
fd << " " << property_table_[idx].name;
}
fd << "}";
return fd;
}
ostream& netdarray_t::debug_dump(ostream&o) const
{
o << "dynamic array of " << *element_type();
return o;
}
ostream& netqueue_t::debug_dump(ostream&fd) const
{
fd << "queue of " << *element_type();
return fd;
}
ostream& netvector_t::debug_dump(ostream&o) const
{
o << type_ << (signed_? " signed" : " unsigned") << packed_dims_;
@ -170,10 +243,7 @@ static inline void dump_scope_path(ostream&o, const NetScope*scope)
dump_scope_path(o, parent);
o << ".";
}
const hname_t name = scope->fullname();
o << name.peek_name();
if (name.has_number())
o << "[" << name.peek_number() << "]";
o << scope->fullname();
}
ostream& operator <<(ostream&o, struct __ScopePathManip marg)
@ -192,6 +262,68 @@ ostream& operator <<(ostream&o, struct __ObjectPathManip marg)
return o;
}
ostream& operator <<(ostream&fd, Link::DIR dir)
{
switch (dir) {
case Link::PASSIVE:
fd << "PASSIVE";
break;
case Link::INPUT:
fd << "INPUT";
break;
case Link::OUTPUT:
fd << "OUTPUT";
break;
default:
fd << "<" << (int)dir << ">";
break;
}
return fd;
}
void NetPins::show_type(ostream&fd) const
{
fd << typeid(*this).name();
}
void NetObj::show_type(ostream&fd) const
{
fd << typeid(*this).name() << "[" << scope_path(scope_) << "." << name_ << "]";
}
struct __ShowTypeManip { const NetPins*pins; };
inline __ShowTypeManip show_type(const NetPins*pins)
{ __ShowTypeManip tmp; tmp.pins = pins; return tmp; }
inline ostream& operator << (ostream&fd, __ShowTypeManip man)
{
if (man.pins == 0)
fd << "NexusSet";
else
man.pins->show_type(fd);
return fd;
}
void Link::dump_link(ostream&fd, unsigned ind) const
{
const Link*cur;
const Nexus*nex = nexus();
if (nex == 0) {
fd << setw(ind) << "" << "<unlinked>" << endl;
return;
}
for (cur = nex->first_nlink() ; cur; cur = cur->next_nlink()) {
const NetPins*obj = cur->get_obj();
unsigned pin = cur->get_pin();
fd << setw(ind) << "" << "Pin " << pin
<< " of " << show_type(obj)
<< ", dir=" << cur->dir_ << endl;
}
}
void NetBranch::dump(ostream&o, unsigned ind) const
{
static const char*pin_names[2] = {
@ -523,10 +655,7 @@ void NetBUFZ::dump_node(ostream&o, unsigned ind) const
void NetCaseCmp::dump_node(ostream&o, unsigned ind) const
{
if (eeq_)
o << setw(ind) << "" << "case compare === : " << name() << endl;
else
o << setw(ind) << "" << "case compare !== : " << name() << endl;
o << setw(ind) << "" << "case compare " << kind_ << ": " << name() << endl;
dump_node_pins(o, ind+4);
}
@ -674,6 +803,21 @@ void NetPartSelect::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetSubstitute::dump_node(ostream&fd, unsigned ind) const
{
fd << setw(ind) << "" << "NetSubstitute: "
<< name();
if (rise_time())
fd << " #(" << *rise_time()
<< "," << *fall_time()
<< "," << *decay_time() << ")";
else
fd << " #(.,.,.)";
fd << " width=" << wid_ << " base=" << off_ <<endl;
dump_node_pins(fd, ind+4);
dump_obj_attr(fd, ind+4);
}
void NetReplicate::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "NetReplicate: "
@ -977,7 +1121,7 @@ void NetCase::dump(ostream&o, unsigned ind) const
break;
}
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
for (unsigned idx = 0 ; idx < items_.size() ; idx += 1) {
o << setw(ind+2) << "";
if (items_[idx].guard)
o << *items_[idx].guard << ":";
@ -1138,6 +1282,13 @@ void NetForever::dump(ostream&o, unsigned ind) const
statement_->dump(o, ind+2);
}
void NetForLoop::dump(ostream&fd, unsigned ind) const
{
fd << setw(ind) << "" << "FOR LOOP index=" << index_->name() << endl;
statement_->dump(fd, ind+4);
step_statement_->dump(fd, ind+4);
}
void NetFree::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "// free storage : " << scope_path(scope_) << endl;
@ -1568,6 +1719,11 @@ void NetEEvent::dump(ostream&o) const
o << "<event=" << event_->name() << ">";
}
void NetELast::dump(ostream&fd) const
{
fd << "<last of " << sig_->name() << ">";
}
void NetENetenum::dump(ostream&o) const
{
o << "<netenum=" << netenum_ << ">";
@ -1593,6 +1749,8 @@ void NetENull::dump(ostream&o) const
void NetEProperty::dump(ostream&o) const
{
o << net_->name() << ".<" << pidx_ << ">";
if (index_)
o << "[" << *index_ << "]";
}
void NetEScope::dump(ostream&o) const
@ -1721,6 +1879,18 @@ void Design::dump(ostream&o) const
cur->second->dump(o);
}
o << "$ROOT CLASSESS:" << endl;
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
; cur != classes_.end() ; ++cur) {
cur->second->dump_scope(o);
}
o << "$ROOT TASKS/FUNCTIONS:" << endl;
for (map<NetScope*,PTaskFunc*>::const_iterator cur = root_tasks_.begin()
; cur != root_tasks_.end() ; ++ cur) {
cur->first->dump(o);
}
o << "SCOPES:" << endl;
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
scope != root_scopes_.end(); ++ scope ) {

View File

@ -1,7 +1,7 @@
#ifndef __discipline_H
#define __discipline_H
#ifndef IVL_discipline_H
#define IVL_discipline_H
/*
* Copyright (c) 2008-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008-2014 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
@ -74,4 +74,4 @@ extern map<perm_string,ivl_discipline_t> disciplines;
// Map access function name to the nature that it accesses.
extern map<perm_string,ivl_nature_t> access_function_nature;
#endif
#endif /* IVL_discipline_H */

View File

@ -48,7 +48,7 @@ INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
endif
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
LDFLAGS = @LDFLAGS@
O = main.o res.o

View File

@ -49,7 +49,7 @@ INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
endif
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
LDFLAGS = @LDFLAGS@
O = main.o substit.o cflexor.o cfparse.o
@ -67,7 +67,11 @@ distclean: clean
rm -f Makefile config.log
cppcheck: $(O:.o=.c)
cppcheck --enable=all -f $(INCLUDE_PATH) $^
cppcheck --enable=all -f \
-UYY_USER_INIT \
-UYYPARSE_PARAM -UYYPRINT -Ushort -Uyyoverflow \
-UYYTYPE_INT8 -UYYTYPE_INT16 -UYYTYPE_UINT8 -UYYTYPE_UINT16 \
$(INCLUDE_PATH) $^
Makefile: $(srcdir)/Makefile.in ../config.status
cd ..; ./config.status --file=driver/$@

View File

@ -247,7 +247,7 @@ void cfreset(FILE*fd, const char*path)
/*
* Modern version of flex (>=2.5.9) can clean up the scanner data.
*/
void destroy_lexor()
void destroy_lexor(void)
{
# ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5

View File

@ -221,7 +221,7 @@ item
}
| error
{ fprintf(stderr, "Error: unable to parse line %d in "
{ fprintf(stderr, "Error: unable to parse line %u in "
"%s.\n", cflloc.first_line, current_file);
return 1;
}
@ -270,5 +270,6 @@ skip_arg : TOK_PLUSARG
int yyerror(const char*msg)
{
(void)msg; /* Parameter is not used. */
return 0;
}

View File

@ -1,7 +1,7 @@
#ifndef __cfparse_misc_H
#define __cfparse_misc_H
#ifndef IVL_cfparse_misc_H
#define IVL_cfparse_misc_H
/*
* Copyright (c) 2001-2009 Picture Elements, Inc.
* Copyright (c) 2001-2014 Picture Elements, Inc.
* Stephen Williams (steve@picturel.com)
*
* This source code is free software; you can redistribute it
@ -38,7 +38,7 @@ int cflex(void);
int cferror(const char *);
int cfparse(void);
void switch_to_command_file(const char *);
void destroy_lexor();
void destroy_lexor(void);
char *current_file;
#endif
#endif /* IVL_cfparse_misc_H */

View File

@ -1,5 +1,5 @@
#ifndef __globals_H
#define __globals_H
#ifndef IVL_globals_H
#define IVL_globals_H
/*
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
*
@ -54,4 +54,4 @@ extern void process_parameter(const char*name);
/* Set the default timescale for the simulator. */
extern void process_timescale(const char*ts_string);
#endif
#endif /* IVL_globals_H */

View File

@ -71,7 +71,7 @@ const char HELP[] =
#endif
#include <fcntl.h>
#if HAVE_GETOPT_H
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
@ -188,7 +188,7 @@ static const char** defparm_base = 0;
static int defparm_size = 0;
/* Function to add a command file name to the FIFO. */
void add_cmd_file(const char* filename)
static void add_cmd_file(const char* filename)
{
p_command_file new;
@ -205,7 +205,7 @@ void add_cmd_file(const char* filename)
}
/* Function to return the top command file name from the FIFO. */
char *get_cmd_file()
static char *get_cmd_file(void)
{
char *filename;
@ -402,7 +402,7 @@ static int t_preprocess_only(void)
* needed to run the command from the configuration file (which is
* already parsed for us) so we can handle must of the generic cases.
*/
static int t_compile()
static int t_compile(void)
{
unsigned rc;
@ -625,7 +625,7 @@ void process_file_name(const char*name, int lib_flag)
}
}
int process_generation(const char*name)
static int process_generation(const char*name)
{
if (strcmp(name,"1995") == 0)
generation = "1995";
@ -750,7 +750,7 @@ int process_generation(const char*name)
return 0;
}
int process_depfile(const char*name)
static int process_depfile(const char*name)
{
const char*cp = strchr(name, '=');
if (cp) {
@ -784,7 +784,7 @@ int process_depfile(const char*name)
/*
* If it exists add the SFT file for the given module.
*/
void add_sft_file(const char *module)
static void add_sft_file(const char *module)
{
char *file;
@ -799,7 +799,7 @@ int main(int argc, char **argv)
{
int e_flag = 0;
int version_flag = 0;
int opt, idx;
int opt;
#ifdef __MINGW32__
/* Calculate the ivl_root from the path to the command. This
@ -907,7 +907,7 @@ int main(int argc, char **argv)
}
}
while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hI:M:m:N::o:P:p:Ss:T:t:vVW:y:Y:")) != EOF) {
while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hI:M:m:N:o:P:p:Ss:T:t:vVW:y:Y:")) != EOF) {
switch (opt) {
case 'B':
@ -1142,7 +1142,7 @@ int main(int argc, char **argv)
vhdlpp_work = "ivl_vhdl_work";
fprintf(defines_file, "vhdlpp:%s%cvhdlpp\n", vhdlpp_dir, sep);
fprintf(defines_file, "vhdlpp-work:%s\n", vhdlpp_work);
for (idx = 0 ; idx < vhdlpp_libdir_cnt ; idx += 1)
for (unsigned idx = 0 ; idx < vhdlpp_libdir_cnt ; idx += 1)
fprintf(defines_file, "vhdlpp-libdir:%s\n", vhdlpp_libdir[idx]);
/* Process parameter definition from command line. The last
@ -1156,7 +1156,7 @@ int main(int argc, char **argv)
/* Finally, process all the remaining words on the command
line as file names. */
for (idx = optind ; idx < argc ; idx += 1)
for (int idx = optind ; idx < argc ; idx += 1)
process_file_name(argv[idx], 0);
/* If the use of a default include directory is not

View File

@ -21,6 +21,7 @@
# include <stdlib.h>
# include <stdio.h>
# include "ivl_alloc.h"
# include "globals.h"
char* substitutions(const char*str)

View File

@ -182,6 +182,14 @@ NetEEvent* NetEEvent::dup_expr() const
return 0;
}
NetELast* NetELast::dup_expr() const
{
NetELast*tmp = new NetELast(sig_);
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetENetenum* NetENetenum::dup_expr() const
{
ivl_assert(*this, 0);
@ -249,6 +257,7 @@ NetESignal* NetESignal::dup_expr() const
NetESignal*tmp = new NetESignal(net_, word_);
ivl_assert(*this, tmp);
tmp->expr_width(expr_width());
tmp->cast_signed(has_sign());
tmp->set_line(*this);
return tmp;
}

View File

@ -30,6 +30,7 @@
# include "netlist.h"
# include "netclass.h"
# include "netenum.h"
# include "netparray.h"
# include "netvector.h"
# include "discipline.h"
# include "netmisc.h"
@ -106,6 +107,7 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type,
int context_wid = -1;
switch (lv_type) {
case IVL_VT_DARRAY:
case IVL_VT_QUEUE:
// For these types, use a different elab_and_eval that
// uses the lv_net_type. We should eventually transition
// all the types to this new form.
@ -309,7 +311,7 @@ unsigned PEBinary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
case '%':
case '/':
min_width_ = max(min_width_, expr_width_);
min_width_ = UINT_MAX; // disable width pruning
break;
case 'l': // << Should be handled by PEBShift
@ -530,7 +532,7 @@ NetExpr* PEBinary::elaborate_expr_base_mult_(Design*,
if (NetEConst*rp_const = dynamic_cast<NetEConst*> (rp)) {
verinum rp_val = rp_const->value();
if (! rp_val.is_defined()) {
if (!rp_val.is_defined() && (lp->expr_type() == IVL_VT_LOGIC)) {
NetEConst*tmp = make_const_x(expr_wid);
tmp->cast_signed(signed_flag_);
tmp->set_line(*this);
@ -538,7 +540,7 @@ NetExpr* PEBinary::elaborate_expr_base_mult_(Design*,
return tmp;
}
if (rp_val.is_zero() && (lp->expr_type() != IVL_VT_LOGIC)) {
if (rp_val.is_zero() && (lp->expr_type() == IVL_VT_BOOL)) {
NetEConst*tmp = make_const_0(expr_wid);
tmp->cast_signed(signed_flag_);
tmp->set_line(*this);
@ -815,7 +817,7 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
if (op_ == 'l')
min_width_ = left_->min_width();
else
min_width_ = expr_width_;
min_width_ = UINT_MAX; // disable width pruning
return fix_width_(mode);
}
@ -1296,10 +1298,27 @@ unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope,
return expr_width_;
}
if (use_darray && (method_name == "pop_back" || method_name=="pop_front")) {
if (debug_elaborate) {
cerr << get_fileline() << ": PECallFunction::test_width_method_: "
<< "Detected " << method_name << " method"
<< " of dynamic arrays." << endl;
}
expr_type_ = use_darray->element_base_type();
expr_width_ = use_darray->element_width();
min_width_ = expr_width_;
signed_flag_= false;
return expr_width_;
}
if (const netclass_t*class_type = net->class_type()) {
cerr << get_fileline() << ": PECallFunction::test_width_method_: "
<< "Try to find method " << method_name
<< " of class " << class_type->get_name() << endl;
if (debug_elaborate) {
cerr << get_fileline() << ": PECallFunction::test_width_method_: "
<< "Try to find method " << method_name
<< " of class " << class_type->get_name() << endl;
}
NetScope*func = class_type->method_from_name(method_name);
if (func == 0) {
@ -1768,6 +1787,14 @@ static const netstruct_t::member_t*get_struct_member(const LineInfo*li,
bool calculate_part(const LineInfo*li, Design*des, NetScope*scope,
const index_component_t&index, long&off, unsigned long&wid)
{
if (index.sel == index_component_t::SEL_BIT_LAST) {
cerr << li->get_fileline() << ": sorry: "
<< "Last element select expression "
<< "not supported." << endl;
des->errors += 1;
return false;
}
// Evaluate the last index expression into a constant long.
NetExpr*texpr = elab_and_eval(des, scope, index.msb, -1, true);
long msb;
@ -1809,6 +1836,11 @@ bool calculate_part(const LineInfo*li, Design*des, NetScope*scope,
}
return true;
case index_component_t::SEL_IDX_UP:
wid = lsb;
off = msb;
break;
default:
ivl_assert(*li, 0);
break;
@ -2051,11 +2083,24 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
des->errors += 1;
return 0;
}
ivl_assert(*this, def);
ivl_assert(*this, def);
NetScope*dscope = def->scope();
ivl_assert(*this, dscope);
/* In SystemVerilog a method calling another method in the
* current class needs to be elaborated as a method with an
* implicit this added. */
if (gn_system_verilog() && (path_.size() == 1)) {
const NetScope *c_scope = scope->get_class_scope();
if (c_scope && (c_scope == dscope->get_class_scope())) {
NetExpr*tmp = elaborate_expr_method_(des, scope, expr_wid,
true);
assert(tmp);
return tmp;
}
}
bool need_const = NEED_CONST & flags;
// It is possible to get here before the called function has been
@ -2249,17 +2294,22 @@ unsigned PECallFunction::elaborate_arguments_(Design*des, NetScope*scope,
}
NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
unsigned expr_wid) const
unsigned expr_wid,
bool add_this_flag) const
{
pform_name_t use_path = path_;
perm_string method_name = peek_tail_name(use_path);
use_path.pop_back();
/* Add the implicit this reference when requested. */
if (add_this_flag) {
assert(use_path.empty());
use_path.push_front(name_component_t(perm_string::literal("@")));
}
// If there is no object to the left of the method name, then
// give up on the idea of looking for an object method.
if (use_path.empty()) {
return 0;
}
if (use_path.empty()) return 0;
NetNet *net = 0;
const NetExpr *par;
@ -2323,12 +2373,31 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
if (net->darray_type()) {
if (method_name == "size") {
NetESFunc*sys_expr = new NetESFunc("$ivl_darray_method$size",
NetESFunc*sys_expr = new NetESFunc("$size",
IVL_VT_BOOL, 32, 1);
sys_expr->parm(0, new NetESignal(net));
sys_expr->set_line(*this);
return sys_expr;
}
if (method_name == "pop_back") {
NetESFunc*sys_expr = new NetESFunc("$ivl_darray_method$pop_back",
expr_type_,
expr_width_, 1);
sys_expr->parm(0, new NetESignal(net));
sys_expr->set_line(*this);
return sys_expr;
}
if (method_name == "pop_front") {
NetESFunc*sys_expr = new NetESFunc("$ivl_darray_method$pop_front",
expr_type_,
expr_width_, 1);
sys_expr->parm(0, new NetESignal(net));
sys_expr->set_line(*this);
return sys_expr;
}
}
if (const netclass_t*class_type = net->class_type()) {
@ -2466,6 +2535,24 @@ unsigned PEConcat::test_width(Design*des, NetScope*scope, width_mode_t&)
// Keep track of the concatenation/repeat depth.
static int concat_depth = 0;
NetExpr* PEConcat::elaborate_expr(Design*, NetScope*,
ivl_type_t type, unsigned /*flags*/) const
{
switch (type->base_type()) {
case IVL_VT_QUEUE:
if (parms_.size() == 0) {
NetENull*tmp = new NetENull;
tmp->set_line(*this);
return tmp;
}
default:
cerr << get_fileline() << ": internal error: "
<< "I don't know how to elaborate(ivl_type_t)"
<< " this expression: " << *this << endl;
return 0;
}
}
NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, unsigned flags) const
{
@ -2604,6 +2691,7 @@ bool PEIdent::calculate_packed_indices_(Design*des, NetScope*scope, NetNet*net,
{
list<index_component_t> index;
index = path_.back().index;
ivl_assert(*this, index.size() >= net->unpacked_dimensions());
for (size_t idx = 0 ; idx < net->unpacked_dimensions() ; idx += 1)
index.pop_front();
@ -2787,6 +2875,48 @@ bool PEIdent::calculate_param_range_(Design*, NetScope*,
return true;
}
unsigned PEIdent::test_width_method_(Design*des, NetScope*scope, width_mode_t&)
{
if (!gn_system_verilog())
return 0;
if (path_.size() < 2)
return 0;
pform_name_t use_path = path_;
perm_string member_name = peek_tail_name(path_);
use_path.pop_back();
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::test_width_method_: "
<< "Try to find method=" << member_name
<< " of signal " << use_path << endl;
}
NetNet*net = 0;
const NetExpr*par = 0;
NetEvent*eve = 0;
const NetExpr*ex1 = 0, *ex2 = 0;
symbol_search(this, des, scope, use_path, net, par, eve, ex1, ex2);
if (net == 0) {
if (debug_elaborate)
cerr << get_fileline() << ": PEIdent::test_width_method_: "
<< "Only nets can have methods, so give up here." << endl;
return 0;
}
if (/*const netdarray_t*dtype =*/ net->darray_type()) {
if (member_name == "size") {
expr_type_ = IVL_VT_BOOL;
expr_width_ = 32;
min_width_ = 32;
signed_flag_= true;
return 32;
}
}
return 0;
}
unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
{
NetNet* net = 0;
@ -2801,6 +2931,10 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
ivl_assert(*this, use_scope);
}
if (unsigned tmp = test_width_method_(des, scope, mode)) {
return tmp;
}
NetScope*found_in = symbol_search(this, des, use_scope, path_,
net, par, eve,
ex1, ex2);
@ -2845,23 +2979,38 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
const index_component_t&index_tail = name_tail.index.back();
ivl_assert(*this, index_tail.msb);
}
use_width = 1;
// If we have a net in hand, then we can predict what the
// slice width will be. If not, then assume it will be a
// simple bit select. If the net only has a single dimension
// then this is still a simple bit select.
if ((net == 0) || (net->packed_dimensions() <= 1))
use_width = 1;
break;
case index_component_t::SEL_BIT_LAST:
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::test_width: "
<< "Queue/Darray last index ($)" << endl;
}
break;
default:
ivl_assert(*this, 0);
}
if (const netdarray_t*darray = net? net->darray_type() : 0) {
if (use_sel == index_component_t::SEL_BIT) {
switch (use_sel) {
case index_component_t::SEL_BIT:
case index_component_t::SEL_BIT_LAST:
expr_type_ = darray->element_base_type();
expr_width_ = darray->element_width();
min_width_ = expr_width_;
signed_flag_ = net->get_signed();
} else {
break;
default:
expr_type_ = net->data_type();
expr_width_ = net->vector_width();
min_width_ = expr_width_;
signed_flag_ = net->get_signed();
break;
}
return expr_width_;
}
@ -2877,15 +3026,35 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
// The width of a signal expression is the width of the signal.
if (net != 0) {
size_t use_depth = name_tail.index.size();
// Account for unpacked dimensions by assuming that the
// unpacked dimensions are consumed first, so subtract
// the unpacked dimensions from the dimension depth
// useable for making the slice.
if (use_depth >= net->unpacked_dimensions()) {
use_depth -= net->unpacked_dimensions();
} else {
// In this case, we have a slice of an unpacked
// array. This likely handled as an array instead
// of a slice. Hmm...
use_depth = 0;
}
expr_type_ = net->data_type();
expr_width_ = net->vector_width();
expr_width_ = net->slice_width(use_depth);
min_width_ = expr_width_;
signed_flag_ = net->get_signed();
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::test_width: "
<< net->name() << " is a net, "
<< "type=" << expr_type_
<< ", width=" << expr_width_ << endl;
<< ", width=" << expr_width_
<< ", signed_=" << (signed_flag_?"true":"false")
<< ", use_depth=" << use_depth
<< ", packed_dimensions=" << net->packed_dimensions()
<< ", unpacked_dimensions=" << net->unpacked_dimensions()
<< endl;
}
return expr_width_;
}
@ -3000,8 +3169,10 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
ivl_type_t ntype, unsigned) const
ivl_type_t ntype, unsigned flags) const
{
bool need_const = NEED_CONST & flags;
NetNet* net = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
@ -3013,6 +3184,10 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
ivl_assert(*this, use_scope);
}
if (NetExpr* tmp = elaborate_expr_class_member_(des, scope, 0, flags)) {
return tmp;
}
/* NetScope*found_in = */ symbol_search(this, des, use_scope, path_,
net, par, eve,
ex1, ex2);
@ -3072,7 +3247,69 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
}
ivl_assert(*this, ntype->type_compatible(net->net_type()));
NetESignal*tmp = new NetESignal(net);
const name_component_t&use_comp = path_.back();
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
<< "Typed ident " << net->name()
<< " with " << use_comp.index.size() << " indices"
<< " and " << net->unpacked_dimensions() << " expected."
<< endl;
}
if (net->unpacked_dimensions() != use_comp.index.size()) {
cerr << get_fileline() << ": sorry: "
<< "Net " << net->name()
<< " expects " << net->unpacked_dimensions()
<< ", but got " << use_comp.index.size() << "."
<< endl;
des->errors += 1;
NetESignal*tmp = new NetESignal(net);
tmp->set_line(*this);
return tmp;
}
if (net->unpacked_dimensions() == 0) {
NetESignal*tmp = new NetESignal(net);
tmp->set_line(*this);
return tmp;
}
// Convert a set of index expressions to a single expression
// that addresses the canonical element.
list<NetExpr*>unpacked_indices;
list<long> unpacked_indices_const;
indices_flags idx_flags;
indices_to_expressions(des, scope, this,
use_comp.index, net->unpacked_dimensions(),
need_const, net->unpacked_count(),
idx_flags,
unpacked_indices,
unpacked_indices_const);
NetExpr*canon_index = 0;
if (idx_flags.invalid) {
// Nothing to do
} else if (idx_flags.undefined) {
cerr << get_fileline() << ": warning: "
<< "returning 'bx for undefined array access "
<< net->name() << as_indices(unpacked_indices)
<< "." << endl;
} else if (idx_flags.variable) {
ivl_assert(*this, unpacked_indices.size() == net->unpacked_dimensions());
canon_index = normalize_variable_unpacked(net, unpacked_indices);
} else {
ivl_assert(*this, unpacked_indices_const.size() == net->unpacked_dimensions());
canon_index = normalize_variable_unpacked(net, unpacked_indices_const);
}
ivl_assert(*this, canon_index);
NetESignal*tmp = new NetESignal(net, canon_index);
tmp->set_line(*this);
return tmp;
@ -3094,19 +3331,24 @@ NetExpr* PEIdent::elaborate_expr_class_member_(Design*des, NetScope*scope,
if (path_.size() != 1)
return 0;
const netclass_t*class_type = scope->parent()->class_def();
const netclass_t*class_type = find_class_containing_scope(*this, scope);
if (class_type == 0)
return 0;
perm_string member_name = peek_tail_name(path_);
const name_component_t&name_comp = path_.back();
perm_string member_name = name_comp.name;
int pidx = class_type->property_idx_from_name(member_name);
if (pidx < 0)
return 0;
NetNet*this_net = scope->find_signal(perm_string::literal("@"));
NetScope*scope_method = find_method_containing_scope(*this, scope);
ivl_assert(*this, scope_method);
NetNet*this_net = scope_method->find_signal(perm_string::literal("@"));
if (this_net == 0) {
cerr << get_fileline() << ": internal error: "
<< "Unable to find 'this' port of " << scope_path(scope)
<< "Unable to find 'this' port of " << scope_path(scope_method)
<< "." << endl;
return 0;
}
@ -3116,7 +3358,8 @@ NetExpr* PEIdent::elaborate_expr_class_member_(Design*des, NetScope*scope,
<< "Found member " << member_name
<< " is a member of class " << class_type->get_name()
<< ", context scope=" << scope_path(scope)
<< ", so synthesizing a NetEProperty." << endl;
<< ", type=" << *class_type->get_prop_type(pidx)
<< ", so making a NetEProperty." << endl;
}
property_qualifier_t qual = class_type->get_prop_qual(pidx);
@ -3132,11 +3375,98 @@ NetExpr* PEIdent::elaborate_expr_class_member_(Design*des, NetScope*scope,
return class_static_property_expression(this, class_type, member_name);
}
NetEProperty*tmp = new NetEProperty(this_net, member_name);
NetExpr*canon_index = 0;
ivl_type_t tmp_type = class_type->get_prop_type(pidx);
if (const netuarray_t*tmp_ua = dynamic_cast<const netuarray_t*>(tmp_type)) {
const std::vector<netrange_t>&dims = tmp_ua->static_dimensions();
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_expr_class_member_: "
<< "Property " << class_type->get_prop_name(pidx)
<< " has " << dims.size() << " dimensions, "
<< " got " << name_comp.index.size() << " indices." << endl;
}
if (dims.size() != name_comp.index.size()) {
cerr << get_fileline() << ": error: "
<< "Got " << name_comp.index.size() << " indices, "
<< "expecting " << dims.size()
<< " to index the property " << class_type->get_prop_name(pidx) << "." << endl;
des->errors += 1;
} else {
canon_index = make_canonical_index(des, scope, this,
name_comp.index, tmp_ua, false);
}
}
if (debug_elaborate && canon_index) {
cerr << get_fileline() << ": PEIdent::elaborate_expr_class_member_: "
<< "Property " << class_type->get_prop_name(pidx)
<< " canonical index: " << *canon_index << endl;
}
NetEProperty*tmp = new NetEProperty(this_net, member_name, canon_index);
tmp->set_line(*this);
return tmp;
}
NetExpr* PEIdent::elaborate_expr_method_(Design*des, NetScope*scope,
unsigned, unsigned) const
{
if (!gn_system_verilog())
return 0;
if (path_.size() < 2)
return 0;
pform_name_t use_path = path_;
perm_string member_name = peek_tail_name(path_);
use_path.pop_back();
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_expr_method_: "
<< "Try to find method=" << member_name
<< " of signal " << use_path << endl;
}
NetNet*net = 0;
const NetExpr*par = 0;
NetEvent*eve = 0;
const NetExpr*ex1 = 0, *ex2 = 0;
symbol_search(this, des, scope, use_path, net, par, eve, ex1, ex2);
if (net == 0) {
if (debug_elaborate)
cerr << get_fileline() << ": PEIdent::elaborate_expr_method_: "
<< "Only nets can have methods, so give up here." << endl;
return 0;
}
if (net->darray_type()) {
if (member_name == "size") {
NetESFunc*fun = new NetESFunc("$size", IVL_VT_BOOL, 32, 1);
fun->set_line(*this);
NetESignal*arg = new NetESignal(net);
arg->set_line(*net);
fun->parm(0, arg);
return fun;
}
return 0;
}
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_expr_method_: "
<< "Give up trying to find method " << member_name
<< " of " << path_ << "." << endl;
}
return 0;
}
/*
* Elaborate an identifier in an expression. The identifier can be a
* parameter name, a signal name or a memory name. It can also be a
@ -3197,6 +3527,14 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
ivl_assert(*this, use_scope);
}
// Special case: Detect the special situation that the name is
// a method of an object (including built-in methods) that has
// no arguments. For example, "foo.size" is the call to the
// size() method if foo is an array type.
if (NetExpr*tmp = elaborate_expr_method_(des, scope, expr_wid, flags)) {
return tmp;
}
NetScope*found_in = symbol_search(this, des, use_scope, path_,
net, par, eve,
ex1, ex2);
@ -3241,6 +3579,13 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
if (!tmp) return 0;
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
<< "Expression as net. expr_wid=" << expr_wid
<< ", tmp->expr_width()=" << tmp->expr_width()
<< ", tmp=" << *tmp << endl;
}
tmp = pad_to_width(tmp, expr_wid, *this);
tmp->cast_signed(signed_flag_);
@ -3898,6 +4243,8 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
return 0;
}
ivl_assert(*this, use_sel != index_component_t::SEL_BIT_LAST);
if (use_sel == index_component_t::SEL_BIT)
return elaborate_expr_param_bit_(des, scope, par, found_in,
par_msb, par_lsb, need_const);
@ -3988,7 +4335,7 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
if (name_tail.index.empty()) {
cerr << get_fileline() << ": error: Array " << path()
<< " Needs an array index here." << endl;
<< " needs an array index here." << endl;
des->errors += 1;
return 0;
}
@ -4458,6 +4805,15 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
// making a mux part in the netlist.
if (NetEConst*msc = dynamic_cast<NetEConst*> (mux)) {
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_expr_net_bit_: "
<< "mux is constant=" << *msc
<< ", packed_dims()=" << net->sig()->packed_dims()
<< ", packed_dims().size()=" << net->sig()->packed_dims().size()
<< ", prefix_indices.size()=" << prefix_indices.size()
<< endl;
}
// Special case: The bit select expression is constant
// x/z. The result of the expression is 1'bx.
if (! msc->value().is_defined()) {
@ -4475,6 +4831,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
<< endl;
}
// FIXME: Should I be using slice_width() here?
NetEConst*tmp = make_const_x(1);
tmp->set_line(*this);
delete mux;
@ -4566,6 +4923,12 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
if (net->vector_width() == 1)
return net;
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_expr_net_bit_: "
<< "Make bit select idx=" << idx
<< endl;
}
// Make an expression out of the index
NetEConst*idx_c = new NetEConst(verinum(idx));
idx_c->set_line(*net);
@ -4610,6 +4973,29 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
return ss;
}
NetExpr* PEIdent::elaborate_expr_net_bit_last_(Design*, NetScope*,
NetESignal*net,
NetScope* /* found_in */,
bool need_const) const
{
if (need_const) {
cerr << get_fileline() << ": error: "
<< "Expression with \"[$]\" is not constant." << endl;
return 0;
}
unsigned use_width = 1;
if (const netdarray_t*darray = net->sig()->darray_type()) {
use_width = darray->element_width();
}
NetELast*mux = new NetELast(net->sig());
mux->set_line(*this);
NetESelect*ss = new NetESelect(net, mux, use_width);
ss->set_line(*this);
return ss;
}
NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
NetNet*net, NetScope*found_in,
unsigned expr_wid,
@ -4662,6 +5048,10 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
return elaborate_expr_net_bit_(des, scope, node, found_in,
need_const);
if (use_sel == index_component_t::SEL_BIT_LAST)
return elaborate_expr_net_bit_last_(des, scope, node, found_in,
need_const);
// It's not anything else, so this must be a simple identifier
// expression with no part or bit select. Return the signal
// itself as the expression.
@ -4740,6 +5130,8 @@ NetExpr* PENewClass::elaborate_expr_constructor_(Design*des, NetScope*scope,
const netclass_t*ctype,
NetExpr*obj, unsigned /*flags*/) const
{
ivl_assert(*this, ctype);
// If there is an initializer function, then pass the object
// through that function first. Note that the initializer
// function has no arguments other than the object itself.
@ -4777,6 +5169,12 @@ NetExpr* PENewClass::elaborate_expr_constructor_(Design*des, NetScope*scope,
NetFuncDef*def = new_scope->func_def();
if (def == 0) {
cerr << get_fileline() << ": internal error: "
<< "Scope " << scope_path(new_scope)
<< " is missing constructor definition." << endl;
des->errors += 1;
}
ivl_assert(*this, def);
// Are there too many arguments passed to the function. If so,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -27,6 +27,7 @@
# include "netstruct.h"
# include "netclass.h"
# include "netdarray.h"
# include "netparray.h"
# include "netvector.h"
# include "compiler.h"
# include <cstdlib>
@ -397,23 +398,49 @@ NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des,
if (path_.size() != 1)
return 0;
const netclass_t*class_type = scope->parent()->class_def();
const netclass_t*class_type = find_class_containing_scope(*this, scope);
if (class_type == 0)
return 0;
perm_string member_name = peek_tail_name(path_);
const name_component_t&name_comp = path_.back();
perm_string member_name = name_comp.name;
int pidx = class_type->property_idx_from_name(member_name);
if (pidx < 0)
return 0;
NetNet*this_net = scope->find_signal(perm_string::literal("@"));
NetScope*scope_method = find_method_containing_scope(*this, scope);
ivl_assert(*this, scope_method);
NetNet*this_net = scope_method->find_signal(perm_string::literal("@"));
if (this_net == 0) {
cerr << get_fileline() << ": internal error: "
<< "Unable to find 'this' port of " << scope_path(scope)
<< "Unable to find 'this' port of " << scope_path(scope_method)
<< "." << endl;
return 0;
}
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_method_class_member_: "
<< "Ident " << member_name
<< " is a property of class " << class_type->get_name() << endl;
}
NetExpr*canon_index = 0;
if (! name_comp.index.empty()) {
ivl_type_t property_type = class_type->get_prop_type(pidx);
if (const netsarray_t* stype = dynamic_cast<const netsarray_t*> (property_type)) {
canon_index = make_canonical_index(des, scope, this,
name_comp.index, stype, false);
} else {
cerr << get_fileline() << ": error: "
<< "Index expressions don't apply to this type of property." << endl;
des->errors += 1;
}
}
// Detect assignment to constant properties. Note that the
// initializer constructor MAY assign to constant properties,
// as this is how the property gets its value.
@ -448,8 +475,34 @@ NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des,
}
}
ivl_type_t tmp_type = class_type->get_prop_type(pidx);
if (const netuarray_t*tmp_ua = dynamic_cast<const netuarray_t*>(tmp_type)) {
const std::vector<netrange_t>&dims = tmp_ua->static_dimensions();
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_method_class_member_: "
<< "Property " << class_type->get_prop_name(pidx)
<< " has " << dims.size() << " dimensions, "
<< " got " << name_comp.index.size() << " indices." << endl;
if (canon_index) {
cerr << get_fileline() << ": PEIdent::elaborate_lval_method_class_member_: "
<< "Canonical index is:" << *canon_index << endl;
};
}
if (dims.size() != name_comp.index.size()) {
cerr << get_fileline() << ": error: "
<< "Got " << name_comp.index.size() << " indices, "
<< "expecting " << dims.size()
<< " to index the property " << class_type->get_prop_name(pidx) << "." << endl;
des->errors += 1;
}
}
NetAssign_*this_lval = new NetAssign_(this_net);
this_lval->set_property(member_name);
if (canon_index) this_lval->set_word(canon_index);
return this_lval;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -501,6 +501,10 @@ 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;
// Set this to true if we calculate the word index. This is
// used to distinguish between unpacked array assignment and
// array word assignment.
bool widx_flag = false;
list<long> unpacked_indices_const;
@ -555,8 +559,9 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
packed_base = collapse_array_indices(des, scope, sig, tmp_index);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
<< "packed_base expression = " << *packed_base << endl;
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
<< "packed_base=" << *packed_base
<< ", member_off=" << member_off << endl;
}
}
@ -590,13 +595,31 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
midx = lidx + tmp_wid - 1;
}
} else if (gn_system_verilog() && sig->unpacked_dimensions() > 0 && path_tail.index.empty()) {
// In this case, we are doing a continuous assignment to
// an unpacked array. The NetNet representation is a
// NetNet with a pin for each array element, so there is
// nothing more needed here.
//
// This can come up from code like this:
// logic [...] data [0:3];
// assign data = ...;
// In this case, "sig" is "data", and sig->pin_count()
// is 4 to account for the unpacked size.
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
<< "Net assign to unpacked array \"" << sig->name()
<< "\" with " << sig->pin_count() << " elements." << endl;
}
} 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;
<< " but got only " << path_tail.index.size() << ". (net)" << endl;
des->errors += 1;
return 0;
}
@ -627,6 +650,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
<< sig->name() << as_indices(unpacked_indices)
<< "." << endl;
widx = -1;
widx_flag = true;
} else {
NetExpr*canon_index = 0;
@ -639,12 +663,14 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
<< sig->name() << as_indices(unpacked_indices_const)
<< "." << endl;
widx = -1;
widx_flag = true;
} else {
NetEConst*canon_const = dynamic_cast<NetEConst*>(canon_index);
ivl_assert(*this, canon_const);
widx = canon_const->value().as_long();
widx_flag = true;
delete canon_index;
}
}
@ -682,6 +708,16 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
}
} else if (!path_tail.index.empty()) {
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
<< "path_tail.index.size()=" << path_tail.index.size()
<< endl;
}
// There are index expressions on the name, so this is a
// bit/slice select of the name. Calculate a canonical
// part select.
if (sig->get_scalar()) {
cerr << get_fileline() << ": error: "
<< "can not select part of ";
@ -710,14 +746,21 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
unsigned subnet_wid = midx-lidx+1;
/* Check if the l-value bits are double-driven. */
if (sig->type() == NetNet::UNRESOLVED_WIRE && sig->test_and_set_part_driver(midx,lidx)) {
if (sig->type() == NetNet::UNRESOLVED_WIRE && sig->test_and_set_part_driver(midx,lidx, widx_flag? widx : 0)) {
cerr << get_fileline() << ": error: Unresolved net/uwire "
<< sig->name() << " cannot have multiple drivers." << endl;
if (debug_elaborate) {
cerr << get_fileline() << ": : Overlap in "
<< "[" << midx << ":" << lidx << "] (canonical)"
<< ", widx=" << (widx_flag? widx : 0)
<< ", vector width=" << sig->vector_width()
<< endl;
}
des->errors += 1;
return 0;
}
if (sig->pin_count() > 1) {
if (sig->pin_count() > 1 && widx_flag) {
if (widx < 0 || widx >= (long) sig->pin_count())
return 0;
@ -729,6 +772,13 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
tmp->local_flag(true);
connect(sig->pin(widx), tmp->pin(0));
sig = tmp;
} else if (sig->pin_count() > 1) {
// If this turns out to be an l-value unpacked array,
// then let the caller handle it. It will probably be
// converted into an array of assignments.
return sig;
}
/* If the desired l-value vector is narrower than the
@ -851,6 +901,33 @@ NetNet* PEIdent::elaborate_subport(Design*des, NetScope*scope) const
long midx;
long lidx;
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_subport: "
<< "path_ = \"" << path_
<< "\", unpacked_dimensions=" << sig->unpacked_dimensions()
<< ", port_type()=" << sig->port_type() << endl;
}
if (sig->unpacked_dimensions() && !gn_system_verilog()) {
cerr << get_fileline() << ": error: "
<< "Ports cannot be unpacked arrays. Try enabling SystemVerilog support." << endl;
des->errors += 1;
return 0;
}
// There cannot be parts to an unpacked array, so process this
// simply as an unpacked array.
if (sig->unpacked_dimensions()) {
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_subport: "
<< "path_=\"" << path_
<< "\" is an unpacked array with " << sig->pin_count()
<< " elements." << endl;
}
scope->add_module_port_net(sig);
return sig;
}
/* Evaluate the part/bit select expressions, to get the part
select of the signal that attaches to the port. Also handle
range and direction checking here. */
@ -912,6 +989,20 @@ NetNet* PEIdent::elaborate_subport(Design*des, NetScope*scope) const
return sig;
}
NetNet*PEIdent::elaborate_unpacked_net(Design*des, NetScope*scope) const
{
NetNet* sig = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
perm_string method_name;
symbol_search(this, des, scope, path_, sig, par, eve);
ivl_assert(*this, sig);
return sig;
}
bool PEIdent::is_collapsible_net(Design*des, NetScope*scope) const
{
assert(scope);

View File

@ -425,6 +425,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
netclass_t*use_base_class = 0;
if (base_class) {
ivl_assert(*pclass, scope);
use_base_class = scope->find_class(base_class->name);
if (use_base_class == 0) {
cerr << pclass->get_fileline() << ": error: "
@ -436,6 +437,9 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
netclass_t*use_class = new netclass_t(use_type->name, use_base_class);
ivl_assert(*pclass, use_type->save_elaborated_type == 0);
use_type->save_elaborated_type = use_class;
// Class scopes have no parent scope, because references are
// not allowed to escape a class method.
NetScope*class_scope = new NetScope(0, hname_t(pclass->pscope_name()),
@ -443,18 +447,22 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
class_scope->set_line(pclass);
class_scope->set_class_def(use_class);
use_class->set_class_scope(class_scope);
use_class->set_definition_scope(scope);
// Collect the properties, elaborate them, and add them to the
// elaborated class definition.
for (map<perm_string, class_type_t::prop_info_t>::iterator cur = use_type->properties.begin()
; cur != use_type->properties.end() ; ++ cur) {
if (debug_scopes) {
cerr << pclass->get_fileline() << ": elaborate_scope_class: "
<< " Property " << cur->first << endl;
}
ivl_type_s*tmp = cur->second.type->elaborate_type(des, scope);
ivl_assert(*pclass, tmp);
if (debug_scopes) {
cerr << pclass->get_fileline() << ": elaborate_scope_class: "
<< " Property " << cur->first
<< " type=" << *tmp << endl;
}
use_class->set_property(cur->first, cur->second.qual, tmp);
}
for (map<perm_string,PTask*>::iterator cur = pclass->tasks.begin()
@ -493,7 +501,12 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
cur->second->elaborate_scope(des, method_scope);
}
scope->add_class(use_class);
if (scope) {
scope->add_class(use_class);
} else {
des->add_class(use_class, pclass);
}
}
static void elaborate_scope_classes(Design*des, NetScope*scope,
@ -505,6 +518,18 @@ static void elaborate_scope_classes(Design*des, NetScope*scope,
}
}
void elaborate_rootscope_classes(Design*des)
{
if (pform_classes.empty())
return;
for (map<perm_string,PClass*>::iterator cur = pform_classes.begin()
; cur != pform_classes.end() ; ++ cur) {
blend_class_constructors(cur->second);
elaborate_scope_class(des, 0, cur->second);
}
}
static void replace_scope_parameters_(NetScope*scope, const LineInfo&loc,
const Module::replace_t&replacements)
{
@ -546,6 +571,25 @@ static void elaborate_scope_events_(Design*des, NetScope*scope,
}
}
static void elaborate_scope_task(Design*des, NetScope*scope, PTask*task)
{
hname_t use_name( task->pscope_name() );
NetScope*task_scope = new NetScope(scope, use_name, NetScope::TASK);
task_scope->is_auto(task->is_auto());
task_scope->set_line(task);
if (scope==0)
des->add_root_task(task_scope, task);
if (debug_scopes) {
cerr << task->get_fileline() << ": elaborate_scope_task: "
<< "Elaborate task scope " << scope_path(task_scope) << endl;
}
task->elaborate_scope(des, task_scope);
}
static void elaborate_scope_tasks(Design*des, NetScope*scope,
const map<perm_string,PTask*>&tasks)
{
@ -587,19 +631,30 @@ static void elaborate_scope_tasks(Design*des, NetScope*scope,
des->errors += 1;
}
NetScope*task_scope = new NetScope(scope, use_name,
NetScope::TASK);
task_scope->is_auto((*cur).second->is_auto());
task_scope->set_line((*cur).second);
if (debug_scopes)
cerr << cur->second->get_fileline() << ": debug: "
<< "Elaborate task scope " << scope_path(task_scope) << endl;
(*cur).second->elaborate_scope(des, task_scope);
elaborate_scope_task(des, scope, cur->second);
}
}
static void elaborate_scope_func(Design*des, NetScope*scope, PFunction*task)
{
hname_t use_name( task->pscope_name() );
NetScope*task_scope = new NetScope(scope, use_name, NetScope::FUNC);
task_scope->is_auto(task->is_auto());
task_scope->set_line(task);
if (scope==0)
des->add_root_task(task_scope, task);
if (debug_scopes) {
cerr << task->get_fileline() << ": elaborate_scope_func: "
<< "Elaborate task scope " << scope_path(task_scope) << endl;
}
task->elaborate_scope(des, task_scope);
}
static void elaborate_scope_funcs(Design*des, NetScope*scope,
const map<perm_string,PFunction*>&funcs)
{
@ -642,19 +697,33 @@ static void elaborate_scope_funcs(Design*des, NetScope*scope,
des->errors += 1;
}
NetScope*func_scope = new NetScope(scope, use_name,
NetScope::FUNC);
func_scope->is_auto((*cur).second->is_auto());
func_scope->set_line((*cur).second);
if (debug_scopes)
cerr << cur->second->get_fileline() << ": debug: "
<< "Elaborate function scope " << scope_path(func_scope) << endl;
(*cur).second->elaborate_scope(des, func_scope);
elaborate_scope_func(des, scope, cur->second);
}
}
void elaborate_rootscope_tasks(Design*des)
{
for (map<perm_string,PTaskFunc*>::iterator cur = pform_tasks.begin()
; cur != pform_tasks.end() ; ++ cur) {
if (PTask*task = dynamic_cast<PTask*> (cur->second)) {
elaborate_scope_task(des, 0, task);
continue;
}
if (PFunction*func = dynamic_cast<PFunction*>(cur->second)) {
elaborate_scope_func(des, 0, func);
continue;
}
cerr << cur->second->get_fileline() << ": internal error: "
<< "elabortae_rootscope_tasks does not understand "
<< "this object," << endl;
des->errors += 1;
}
}
class generate_schemes_work_item_t : public elaborator_work_item_t {
public:
generate_schemes_work_item_t(Design*des__, NetScope*scope, Module*mod)
@ -690,12 +759,14 @@ class generate_schemes_work_item_t : public elaborator_work_item_t {
bool PPackage::elaborate_scope(Design*des, NetScope*scope)
{
if (debug_scopes) {
cerr << get_fileline() << ": debug: Elaborate package scope "
<< scope_path(scope) << "." << endl;
cerr << get_fileline() << ": PPackage::elaborate_scope: "
<< "Elaborate package " << scope_path(scope) << "." << endl;
}
collect_scope_parameters_(des, scope, parameters);
collect_scope_localparams_(des, scope, localparams);
elaborate_scope_enumerations(des, scope, enum_sets);
elaborate_scope_classes(des, scope, classes_lexical);
elaborate_scope_funcs(des, scope, funcs);
elaborate_scope_tasks(des, scope, tasks);
return true;
@ -705,8 +776,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
const replace_t&replacements)
{
if (debug_scopes) {
cerr << get_fileline() << ": debug: Elaborate scope "
<< scope_path(scope) << "." << endl;
cerr << get_fileline() << ": Module::elaborate_scope: "
<< "Elaborate " << scope_path(scope) << "." << endl;
}
// Add the genvars to the scope.
@ -892,8 +963,10 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
// Check the generate block name.
// A generate "loop" can not have the same name as another scope object.
const NetScope *child = container->child(hname_t(scope_name));
// A generate "loop" can not have the same name as another
// scope object. Find any scope with this name, not just an
// exact match scope.
const NetScope *child = container->child_byname(scope_name);
if (child) {
cerr << get_fileline() << ": error: generate \"loop\" and ";
child->print_type(cerr);
@ -1897,6 +1970,18 @@ void PEventStatement::elaborate_scope(Design*des, NetScope*scope) const
statement_ -> elaborate_scope(des, scope);
}
/*
* The standard says that we create an implicit scope for foreach
* loops, but that is just to hold the index variables, and we'll
* handle them by creating unique names. So just jump into the
* contained statement for scope elaboration.
*/
void PForeach::elaborate_scope(Design*des, NetScope*scope) const
{
if (statement_)
statement_ -> elaborate_scope(des, scope);
}
/*
* Statements that contain a further statement but do not
* intrinsically add a scope need to elaborate_scope the contained

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -41,6 +41,7 @@
# include "netvector.h"
# include "netdarray.h"
# include "netparray.h"
# include "netqueue.h"
# include "util.h"
# include "ivl_assert.h"
@ -206,6 +207,11 @@ bool PPackage::elaborate_sig(Design*des, NetScope*scope) const
{
bool flag = true;
if (debug_elaborate) {
cerr << get_fileline() << ": PPackage::elaborate_sig: "
<< "Start package scope=" << scope_path(scope) << endl;
}
flag = elaborate_sig_wires_(des, scope) && flag;
// After all the wires are elaborated, we are free to
@ -214,6 +220,13 @@ bool PPackage::elaborate_sig(Design*des, NetScope*scope) const
elaborate_sig_funcs(des, scope, funcs);
elaborate_sig_tasks(des, scope, tasks);
elaborate_sig_classes(des, scope, classes);
if (debug_elaborate) {
cerr << get_fileline() << ": PPackage::elaborate_sig: "
<< "Done package scope=" << scope_path(scope)
<< ", flag=" << flag << endl;
}
return flag;
}
@ -563,7 +576,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
// Special case: this is a constructor, so the return
// signal is also the first argument. For example, the
// source code for the definition may be:
// function new(...);
// function new(...);
// endfunction
// In this case, the "@" port is the synthetic "this"
// argument and we also use it as a return value at the
@ -594,6 +607,11 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
}
if (ret_type) {
if (debug_elaborate) {
cerr << get_fileline() << ": PFunction::elaborate_sig: "
<< "return type: " << *ret_type << endl;
return_type_->pform_dump(cerr, 8);
}
list<netrange_t> ret_unpacked;
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_unpacked, ret_type);
@ -615,9 +633,10 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
NetFuncDef*def = new NetFuncDef(scope, ret_sig, ports, pdef);
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
<< "Attach function definition to scope "
<< scope_path(scope) << "." << endl;
cerr << get_fileline() << ": PFunction::elaborate_sig: "
<< "Attach function definition " << scope_path(scope)
<< " with ret_sig width=" << (ret_sig? ret_sig->vector_width() : 0)
<< "." << endl;
scope->set_func_def(def);
@ -799,6 +818,12 @@ void PEventStatement::elaborate_sig(Design*des, NetScope*scope) const
statement_->elaborate_sig(des, scope);
}
void PForeach::elaborate_sig(Design*des, NetScope*scope) const
{
if (statement_)
statement_->elaborate_sig(des, scope);
}
void PForever::elaborate_sig(Design*des, NetScope*scope) const
{
if (statement_)
@ -823,55 +848,6 @@ void PWhile::elaborate_sig(Design*des, NetScope*scope) const
statement_->elaborate_sig(des, scope);
}
static bool evaluate_ranges(Design*des, NetScope*scope,
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) {
long use_msb, use_lsb;
NetExpr*texpr = elab_and_eval(des, scope, cur->first, -1, true);
if (! eval_as_long(use_msb, texpr)) {
cerr << cur->first->get_fileline() << ": error: "
"Range expressions must be constant." << endl;
cerr << cur->first->get_fileline() << " : "
"This MSB expression violates the rule: "
<< *cur->first << endl;
des->errors += 1;
bad_msb = true;
}
delete texpr;
texpr = elab_and_eval(des, scope, cur->second, -1, true);
if (! eval_as_long(use_lsb, texpr)) {
cerr << cur->second->get_fileline() << ": error: "
"Range expressions must be constant." << endl;
cerr << cur->second->get_fileline() << " : "
"This LSB expression violates the rule: "
<< *cur->second << endl;
des->errors += 1;
bad_lsb = true;
}
delete texpr;
llist.push_back(netrange_t(use_msb, use_lsb));
}
return bad_msb | bad_lsb;
}
static netclass_t* locate_class_type(Design*, NetScope*scope,
class_type_t*class_type)
{
netclass_t*use_class = scope->find_class(class_type->name);
return use_class;
}
static ivl_type_s*elaborate_type(Design*des, NetScope*scope,
data_type_t*pform_type)
{
@ -949,7 +925,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
des->errors += error_cnt_;
// A signal can not have the same name as a scope object.
const NetScope *child = scope->child(hname_t(name_));
const NetScope *child = scope->child_byname(name_);
if (child) {
cerr << get_fileline() << ": error: signal and ";
child->print_type(cerr);
@ -1078,7 +1054,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
list<netrange_t>unpacked_dimensions;
netdarray_t*netarray = 0;
netdarray_t*netdarray = 0;
for (list<pform_range_t>::const_iterator cur = unpacked_.begin()
; cur != unpacked_.end() ; ++cur) {
@ -1091,13 +1067,23 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
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);
ivl_assert(*this, netdarray==0);
netdarray = new netdarray_t(vec);
continue;
}
// Special case: Detect the mark for a QUEUE
// declaration, which is the dimensions [null:<nil>].
if (use_ridx==0 && dynamic_cast<PENull*>(use_lidx)) {
netvector_t*vec = new netvector_t(packed_dimensions, data_type_);
packed_dimensions.clear();
ivl_assert(*this, netdarray==0);
netdarray = new netqueue_t(vec);
continue;
}
// Cannot handle dynamic arrays of arrays yet.
ivl_assert(*this, netarray==0);
ivl_assert(*this, netdarray==0);
ivl_assert(*this, use_lidx && use_ridx);
NetExpr*lexp = elab_and_eval(des, scope, use_lidx, -1, true);
@ -1190,22 +1176,11 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
// 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);
if (use_type == 0) {
cerr << get_fileline() << ": internal error: "
<< "Class " << class_type->name
<< " isn't elaborated in scope=" << scope_path(scope) << endl;
des->errors += 1;
}
ivl_assert(*this, use_type);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
<< "Create class instance signal " << wtype
<< " " << name_ << endl;
}
// (No arrays of classes)
list<netrange_t> use_unpacked;
sig = new NetNet(scope, name_, wtype, use_unpacked, use_type);
ivl_assert(*this, class_type->save_elaborated_type);
netclass_t*use_type = class_type->save_elaborated_type;
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, 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
@ -1226,7 +1201,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
} else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(set_data_type_)) {
list<named_pexpr_t>::const_iterator sample_name = enum_type->names->begin();
const netenum_t*use_enum = scope->enumeration_for_name(sample_name->name);
const netenum_t*use_enum = scope->find_enumeration_for_name(sample_name->name);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " << wtype
@ -1240,7 +1215,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_enum);
} else if (netarray) {
} else if (netdarray) {
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " << wtype
@ -1250,7 +1225,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
ivl_assert(*this, packed_dimensions.empty());
ivl_assert(*this, unpacked_dimensions.empty());
sig = new NetNet(scope, name_, wtype, netarray);
sig = new NetNet(scope, name_, wtype, netdarray);
} 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
@ -1266,7 +1241,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " << wtype
<< " parray=" << use_type->packed_dimensions()
<< " parray=" << use_type->static_dimensions()
<< " " << name_ << unpacked_dimensions
<< " in scope " << scope_path(scope) << endl;
}
@ -1321,3 +1296,27 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
return sig;
}
void Design::root_elaborate_sig(void)
{
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
; cur != classes_.end() ; ++ cur) {
netclass_t*cur_class = cur->second;
PClass*cur_pclass = class_to_pclass_[cur_class];
cur_class->elaborate_sig(this, cur_pclass);
}
for (map<NetScope*,PTaskFunc*>::iterator cur = root_tasks_.begin()
; cur != root_tasks_.end() ; ++ cur) {
if (debug_elaborate) {
cerr << cur->second->get_fileline() << ": root_elaborate_sig: "
<< "Elaborate_sig for root task/func " << scope_path(cur->first) << endl;
}
cur->second->elaborate_sig(this, cur->first);
}
}

View File

@ -22,6 +22,7 @@
# include "netclass.h"
# include "netdarray.h"
# include "netenum.h"
# include "netparray.h"
# include "netscalar.h"
# include "netstruct.h"
# include "netvector.h"
@ -31,6 +32,25 @@
using namespace std;
/*
* Elaborations of types may vary depending on the scope that it is
* done in, so keep a per-scope cache of the results.
*/
ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*scope)
{
Definitions*use_definitions = scope;
if (use_definitions == 0)
use_definitions = des;
map<Definitions*,ivl_type_s*>::iterator pos = cache_type_elaborate_.lower_bound(use_definitions);
if (pos->first == use_definitions)
return pos->second;
ivl_type_s*tmp = elaborate_type_raw(des, scope);
cache_type_elaborate_.insert(pos, pair<NetScope*,ivl_type_s*>(scope, tmp));
return tmp;
}
ivl_type_s* data_type_t::elaborate_type_raw(Design*des, NetScope*) const
{
cerr << get_fileline() << ": internal error: "
@ -75,9 +95,10 @@ ivl_type_s* atom2_type_t::elaborate_type_raw(Design*des, NetScope*) const
}
}
ivl_type_s* class_type_t::elaborate_type_raw(Design*, NetScope*scope) const
ivl_type_s* class_type_t::elaborate_type_raw(Design*, NetScope*) const
{
return scope->find_class(name);
ivl_assert(*this, save_elaborated_type);
return save_elaborated_type;
}
/*
@ -188,9 +209,27 @@ ivl_type_s* uarray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
ivl_type_t btype = base_type->elaborate_type(des, scope);
assert(dims->size() == 1);
assert(dims->size() >= 1);
list<pform_range_t>::const_iterator cur = dims->begin();
assert(cur->first == 0 && cur->second==0);
ivl_type_s*res = new netdarray_t(btype);
// Special case: if the dimension is nil:nil, this is a
// dynamic array. Note that we only know how to handle dynamic
// arrays with 1 dimension at a time.
if (cur->first==0 && cur->second==0) {
assert(dims->size()==1);
ivl_type_s*res = new netdarray_t(btype);
return res;
}
vector<netrange_t> dimensions;
bool bad_range = evaluate_ranges(des, scope, dimensions, *dims);
if (bad_range) {
cerr << get_fileline() << " : warning: "
<< "Bad dimensions for type here." << endl;
}
ivl_assert(*this, btype);
ivl_type_s*res = new netuarray_t(dimensions, btype);
return res;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -40,6 +40,7 @@
# include "netlist.h"
# include "netvector.h"
# include "netdarray.h"
# include "netparray.h"
# include "netclass.h"
# include "netmisc.h"
# include "util.h"
@ -77,11 +78,19 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
return;
}
// If this turns out to be an assignment to an unpacked array,
// then handle that special case elsewhere.
if (lval->pin_count() > 1) {
elaborate_unpacked_array_(des, scope, lval);
return;
}
ivl_assert(*this, lval->pin_count() == 1);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: PGAssign: elaborated l-value"
<< " width=" << lval->vector_width() << endl;
cerr << get_fileline() << ": PGAssign::elaborate: elaborated l-value"
<< " width=" << lval->vector_width()
<< ", pin_count=" << lval->pin_count() << endl;
}
NetExpr*rval_expr = elaborate_rval_expr(des, scope, lval->net_type(),
@ -211,6 +220,18 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
}
void PGAssign::elaborate_unpacked_array_(Design*des, NetScope*scope, NetNet*lval) const
{
PEIdent*rval_pident = dynamic_cast<PEIdent*> (pin(1));
ivl_assert(*this, rval_pident);
NetNet*rval_net = rval_pident->elaborate_unpacked_net(des, scope);
ivl_assert(*this, rval_net->pin_count() == lval->pin_count());
assign_unpacked_with_bufz(des, scope, this, lval, rval_net);
}
unsigned PGBuiltin::calculate_array_count_(Design*des, NetScope*scope,
long&high, long&low) const
{
@ -1287,6 +1308,10 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
perm_string pname = peek_tail_name(mport[0]->path());
NetNet*tmp = instance[0]->find_signal(pname);
// Handle the error case where there is no internal
// signal connected to the port.
if (!tmp) continue;
assert(tmp);
if (tmp->port_type() == NetNet::PINPUT) {
@ -1350,18 +1375,22 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
unsigned int prt_vector_width = 0;
PortType::Enum ptype = PortType::PIMPLICIT;
// Scan the module sub-ports for this instance...
// (Sub-ports are concatenated ports that form the
// single port for the instance. This is not a
// commonly used feature.)
for (unsigned ldx = 0 ; ldx < mport.size() ; ldx += 1) {
unsigned lbase = inst * mport.size();
PEIdent*pport = mport[ldx];
assert(pport);
ivl_assert(*this, pport);
NetNet *netnet = pport->elaborate_subport(des, inst_scope);
prts[lbase + ldx] = netnet;
if (netnet == 0)
continue;
assert(netnet);
prts_vector_width += netnet->vector_width();
prt_vector_width += netnet->vector_width();
ivl_assert(*this, netnet);
unsigned port_width = netnet->vector_width() * netnet->pin_count();
prts_vector_width += port_width;
prt_vector_width += port_width;
ptype = PortType::merged(netnet->port_type(), ptype);
}
inst_scope->add_module_port_info(idx, rmod->get_port_name(idx), ptype, prt_vector_width );
@ -1392,9 +1421,25 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
// module[s] port. sig is the thing outside the module
// that connects to the port.
NetNet*sig;
NetNet*sig = 0;
if (prts.empty() || (prts[0]->port_type() == NetNet::PINPUT)) {
// Special case: If the input port is an unpacked
// array, then there should be no sub-ports and
// the r-value expression is processed
// differently.
if (prts.size() >= 1 && prts[0]->pin_count()>1) {
ivl_assert(*this, prts.size()==1);
PEIdent*rval_pident = dynamic_cast<PEIdent*> (pins[idx]);
ivl_assert(*this, rval_pident);
NetNet*rval_net = rval_pident->elaborate_unpacked_net(des, scope);
ivl_assert(*this, rval_net->pin_count() == prts[0]->pin_count());
assign_unpacked_with_bufz(des, scope, this, prts[0], rval_net);
continue;
}
/* Input to module. elaborate the expression to
the desired width. If this in an instance
array, then let the net determine its own
@ -1471,6 +1516,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
} else if (prts[0]->port_type() == NetNet::PINOUT) {
// For now, do not support unpacked array outputs.
ivl_assert(*this, prts[0]->unpacked_dimensions()==0);
/* Inout to/from module. This is a more
complicated case, where the expression must be
an lnet, but also an r-value net.
@ -1530,6 +1578,28 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
/* Port type must be OUTPUT here. */
ivl_assert(*this, prts[0]->port_type() == NetNet::POUTPUT);
// Special case: If the output port is an unpacked
// array, then there should be no sub-ports and
// the passed pexxpression is processed
// differently. Note that we are calling it the
// "r-value" expression, but since this is an
// output port, we assign to it from the internal object.
if (prts[0]->pin_count() > 1) {
ivl_assert(*this, prts.size()==1);
PEIdent*rval_pident = dynamic_cast<PEIdent*>(pins[idx]);
ivl_assert(*this, rval_pident);
NetNet*rval_net = rval_pident->elaborate_unpacked_net(des, scope);
ivl_assert(*this, rval_net->pin_count() == prts[0]->pin_count());
assign_unpacked_with_bufz(des, scope, this, rval_net, prts[0]);
continue;
}
// At this point, arrays are handled.
ivl_assert(*this, prts[0]->unpacked_dimensions()==0);
/* Output from module. Elaborate the port
expression as the l-value of a continuous
assignment, as the port will continuous assign
@ -2221,6 +2291,14 @@ NetAssign_* PAssign_::elaborate_lval(Design*des, NetScope*scope) const
NetAssign_*lv = new NetAssign_(tmp);
return lv;
}
if (debug_elaborate) {
cerr << get_fileline() << ": PAssign_::elaborate_lval: "
<< "lval_ = " << *lval_ << endl;
cerr << get_fileline() << ": PAssign_::elaborate_lval: "
<< "lval_ expr type = " << typeid(*lval_).name() << endl;
}
return lval_->elaborate_lval(des, scope, false, false);
}
@ -2451,6 +2529,23 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
rv = elaborate_rval_(des, scope, use_lv_type);
} else if (const netuarray_t*utype = dynamic_cast<const netuarray_t*>(lv_net_type)) {
ivl_assert(*this, lv->more==0);
if (debug_elaborate) {
if (lv->word())
cerr << get_fileline() << ": PAssign::elaborate: "
<< "lv->word() = " << *lv->word() << endl;
else
cerr << get_fileline() << ": PAssign::elaborate: "
<< "lv->word() = <nil>" << endl;
}
ivl_type_t use_lv_type = lv_net_type;
ivl_assert(*this, lv->word());
use_lv_type = utype->element_type();
ivl_assert(*this, use_lv_type);
rv = elaborate_rval_(des, scope, use_lv_type);
} else {
/* Elaborate the r-value expression, then try to evaluate it. */
rv = elaborate_rval_(des, scope, lv_net_type, lv->expr_type(), count_lval_width(lv));
@ -3118,7 +3213,6 @@ NetProc* PChainConstructor::elaborate(Design*des, NetScope*scope) const
NetBlock*tmp = new NetBlock(NetBlock::SEQU, 0);
tmp->set_line(*this);
return tmp;
return 0;
}
NetProc* PCondit::elaborate(Design*des, NetScope*scope) const
@ -3345,6 +3439,17 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
}
assert(def);
/* In SystemVerilog a method calling another method in the
* current class needs to be elaborated as a method with an
* implicit this added. */
if (gn_system_verilog() && (path_.size() == 1)) {
const NetScope *c_scope = scope->get_class_scope();
if (c_scope && (c_scope == task->get_class_scope())) {
NetProc *tmp = elaborate_method_(des, scope, true);
assert(tmp);
return tmp;
}
}
unsigned parm_count = def->port_count();
@ -3359,7 +3464,45 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
return elaborate_build_call_(des, scope, task, 0);
}
NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope) const
/*
* This private method is called to elaborate built-in methods. The
* method_name is the detected name of the built-in method, and the
* sys_task_name is the internal system-task name to use.
*/
NetProc* PCallTask::elaborate_sys_task_method_(Design*des, NetScope*scope,
NetNet*net,
perm_string method_name,
const char*sys_task_name) const
{
NetESignal*sig = new NetESignal(net);
sig->set_line(*this);
/* If there is a single NULL argument then ignore it since it is
* left over from the parser and is not needed by the method. */
unsigned nparms = parms_.size();
if ((nparms == 1) && (parms_[0] == 0)) nparms = 0;
vector<NetExpr*>argv (1 + nparms);
argv[0] = sig;
for (unsigned idx = 0 ; idx < nparms ; idx += 1) {
PExpr*ex = parms_[idx];
if (ex != 0) {
argv[idx+1] = elab_sys_task_arg(des, scope,
method_name,
idx, ex);
} else {
argv[idx+1] = 0;
}
}
NetSTask*sys = new NetSTask(sys_task_name, IVL_SFUNC_AS_TASK_IGNORE, argv);
sys->set_line(*this);
return sys;
}
NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
bool add_this_flag) const
{
pform_name_t use_path = path_;
perm_string method_name = peek_tail_name(use_path);
@ -3370,6 +3513,12 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope) const
NetEvent *eve;
const NetExpr *ex1, *ex2;
/* Add the implicit this reference when requested. */
if (add_this_flag) {
assert(use_path.empty());
use_path.push_front(name_component_t(perm_string::literal("@")));
}
// There is no signal to search for so this cannot be a method.
if (use_path.empty()) return 0;
@ -3385,15 +3534,20 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope) const
// Is this a delete method for dynamic arrays?
if (net->darray_type() && method_name=="delete") {
NetESignal*sig = new NetESignal(net);
return elaborate_sys_task_method_(des, scope, net,
method_name,
"$ivl_darray_method$delete");
}
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;
if (net->queue_type()) {
if (method_name=="push_back")
return elaborate_sys_task_method_(des, scope, net,
method_name,
"$ivl_queue_method$push_back");
if (method_name=="push_front")
return elaborate_sys_task_method_(des, scope, net,
method_name,
"$ivl_queue_method$push_front");
}
if (const netclass_t*class_type = net->class_type()) {
@ -4470,6 +4624,222 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const
return dev;
}
static void find_property_in_class(const LineInfo&loc, const NetScope*scope, perm_string name, const netclass_t*&found_in, int&property)
{
found_in = find_class_containing_scope(loc, scope);
property = -1;
if (found_in==0) return;
property = found_in->property_idx_from_name(name);
if (property < 0) {
found_in = 0;
return;
}
}
/*
* The foreach statement can be written as a for statement like so:
*
* for (<idx> = $low(<array>) ; <idx> <= $high(<array>) ; <idx> += 1)
* <statement_>
*
* The <idx> variable is already known to be in the containing named
* block scope, which was created by the parser.
*/
NetProc* PForeach::elaborate(Design*des, NetScope*scope) const
{
// Locate the signal for the array variable
pform_name_t array_name;
array_name.push_back(name_component_t(array_var_));
NetNet*array_sig = des->find_signal(scope, array_name);
// And if necessary, look for the class property that is
// referenced.
const netclass_t*class_scope = 0;
int class_property = -1;
if (array_sig == 0)
find_property_in_class(*this, scope, array_var_, class_scope, class_property);
if (debug_elaborate && array_sig) {
cerr << get_fileline() << ": PForeach::elaborate: "
<< "Found array_sig in " << scope_path(array_sig->scope()) << "." << endl;
}
if (debug_elaborate && class_scope) {
cerr << get_fileline() << ": PForeach::elaborate: "
<< "Found array_sig property (" << class_property
<< ") in class " << class_scope->get_name()
<< " as " << *class_scope->get_prop_type(class_property) << "." << endl;
}
if (class_scope!=0 && class_property >= 0) {
ivl_type_t ptype = class_scope->get_prop_type(class_property);
const netsarray_t*atype = dynamic_cast<const netsarray_t*> (ptype);
if (atype == 0) {
cerr << get_fileline() << ": error: "
<< "I can't handle the type of " << array_var_
<< " as a foreach loop." << endl;
des->errors += 1;
return 0;
}
const std::vector<netrange_t>&dims = atype->static_dimensions();
if (dims.size() < index_vars_.size()) {
cerr << get_fileline() << ": error: "
<< "class " << class_scope->get_name()
<< " property " << array_var_
<< " has too few dimensions for foreach dimension list." << endl;
des->errors += 1;
return 0;
}
return elaborate_static_array_(des, scope, dims);
}
if (array_sig == 0) {
cerr << get_fileline() << ": error:"
<< " Unable to find foreach array " << array_name
<< " in scope " << scope_path(scope)
<< "." << endl;
des->errors += 1;
return 0;
}
ivl_assert(*this, array_sig);
if (debug_elaborate) {
cerr << get_fileline() << ": PForeach::elaborate: "
<< "Scan array " << array_sig->name()
<< " of " << array_sig->data_type()
<< " with " << array_sig->unpacked_dimensions() << " unpacked"
<< " and " << array_sig->packed_dimensions()
<< " packed dimensions." << endl;
}
// Classic arrays are processed this way.
if (array_sig->data_type()==IVL_VT_BOOL)
return elaborate_static_array_(des, scope, array_sig->unpacked_dims());
if (array_sig->data_type()==IVL_VT_LOGIC)
return elaborate_static_array_(des, scope, array_sig->unpacked_dims());
if (array_sig->unpacked_dimensions() >= index_vars_.size())
return elaborate_static_array_(des, scope, array_sig->unpacked_dims());
// At this point, we know that the array is dynamic so we
// handle that slightly differently, using run-time tests.
if (index_vars_.size() != 1) {
cerr << get_fileline() << ": sorry: "
<< "Multi-index foreach loops not supported." << endl;
des->errors += 1;
}
// Get the signal for the index variable.
pform_name_t index_name;
index_name.push_back(name_component_t(index_vars_[0]));
NetNet*idx_sig = des->find_signal(scope, index_name);
ivl_assert(*this, idx_sig);
NetESignal*array_exp = new NetESignal(array_sig);
array_exp->set_line(*this);
NetESignal*idx_exp = new NetESignal(idx_sig);
idx_exp->set_line(*this);
// Make an initialization expression for the index.
NetESFunc*init_expr = new NetESFunc("$low", IVL_VT_BOOL, 32, 1);
init_expr->set_line(*this);
init_expr->parm(0, array_exp);
// Make a condition expression: idx <= $high(array)
NetESFunc*high_exp = new NetESFunc("$high", IVL_VT_BOOL, 32, 1);
high_exp->set_line(*this);
high_exp->parm(0, array_exp);
NetEBComp*cond_expr = new NetEBComp('L', idx_exp, high_exp);
cond_expr->set_line(*this);
/* Elaborate the statement that is contained in the foreach
loop. */
NetProc*sub = statement_->elaborate(des, scope);
/* Make a step statement: idx += 1 */
NetAssign_*idx_lv = new NetAssign_(idx_sig);
NetEConst*step_val = make_const_val(1);
NetAssign*step = new NetAssign(idx_lv, '+', step_val);
step->set_line(*this);
NetForLoop*stmt = new NetForLoop(idx_sig, init_expr, cond_expr, sub, step);
stmt->set_line(*this);
stmt->wrap_up();
return stmt;
}
/*
* This is a variant of the PForeach::elaborate() method that handles
* the case that the array has static dimensions. We can use constants
* and possibly do some optimizations.
*/
NetProc* PForeach::elaborate_static_array_(Design*des, NetScope*scope,
const vector<netrange_t>&dims) const
{
if (debug_elaborate) {
cerr << get_fileline() << ": PForeach::elaborate_static_array_: "
<< "Handle as array with static dimensions." << endl;
}
ivl_assert(*this, index_vars_.size() > 0);
ivl_assert(*this, dims.size() == index_vars_.size());
NetProc*sub = statement_->elaborate(des, scope);
NetForLoop*stmt = 0;
for (int idx_idx = index_vars_.size()-1 ; idx_idx >= 0 ; idx_idx -= 1) {
const netrange_t&idx_range = dims[idx_idx];
// Get the $high and $low constant values for this slice
// of the array.
NetEConst*hig_expr = make_const_val_s(idx_range.get_msb());
NetEConst*low_expr = make_const_val_s(idx_range.get_lsb());
if (idx_range.get_msb() < idx_range.get_lsb()) {
NetEConst*tmp = hig_expr;
hig_expr = low_expr;
low_expr = tmp;
}
hig_expr->set_line(*this);
low_expr->set_line(*this);
pform_name_t idx_name;
idx_name.push_back(name_component_t(index_vars_[idx_idx]));
NetNet*idx_sig = des->find_signal(scope, idx_name);
ivl_assert(*this, idx_sig);
// Make the condition expression <idx> <= $high(slice)
NetESignal*idx_expr = new NetESignal(idx_sig);
idx_expr->set_line(*this);
NetEBComp*cond_expr = new NetEBComp('L', idx_expr, hig_expr);
cond_expr->set_line(*this);
// Make the step statement: <idx> += 1
NetAssign_*idx_lv = new NetAssign_(idx_sig);
NetEConst*step_val = make_const_val_s(1);
NetAssign*step = new NetAssign(idx_lv, '+', step_val);
step->set_line(*this);
stmt = new NetForLoop(idx_sig, low_expr, cond_expr, sub, step);
stmt->set_line(*this);
stmt->wrap_up();
sub = stmt;
}
return stmt? stmt : sub;
}
/*
* elaborate the for loop as the equivalent while loop. This eases the
* task for the target code generator. The structure is:
@ -4484,15 +4854,12 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const
*/
NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
{
NetExpr*etmp;
NetExpr*initial_expr;
assert(scope);
const PEIdent*id1 = dynamic_cast<const PEIdent*>(name1_);
assert(id1);
NetBlock*top = new NetBlock(NetBlock::SEQU, 0);
top->set_line(*this);
/* make the expression, and later the initial assignment to
the condition variable. The statement in the for loop is
very specifically an assignment. */
@ -4504,34 +4871,23 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
return 0;
}
assert(sig);
NetAssign_*lv = new NetAssign_(sig);
/* Make the r-value of the initial assignment, and size it
properly. Then use it to build the assignment statement. */
etmp = elaborate_rval_expr(des, scope, sig->net_type(),
lv->expr_type(), lv->lwidth(),
expr1_);
initial_expr = elaborate_rval_expr(des, scope, sig->net_type(),
sig->data_type(), sig->vector_width(),
expr1_);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: FOR initial assign: "
<< sig->name() << " = " << *etmp << endl;
<< sig->name() << " = " << *initial_expr << endl;
}
NetAssign*init = new NetAssign(lv, etmp);
init->set_line(*this);
top->append(init);
NetBlock*body = new NetBlock(NetBlock::SEQU, 0);
body->set_line(*this);
/* Elaborate the statement that is contained in the for
loop. If there is an error, this will return 0 and I should
skip the append. No need to worry, the error has been
reported so it's OK that the netlist is bogus. */
NetProc*tmp = statement_->elaborate(des, scope);
if (tmp)
body->append(tmp);
NetProc*sub = statement_->elaborate(des, scope);
/* Now elaborate the for_step statement. I really should do
@ -4539,20 +4895,19 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
really does step the variable. */
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Elaborate for_step statement "
<< sig->name() << " = " << *etmp << endl;
<< sig->name() << " = " << *initial_expr << endl;
}
NetProc*step = step_->elaborate(des, scope);
body->append(step);
/* Elaborate the condition expression. Try to evaluate it too,
in case it is a constant. This is an interesting case
worthy of a warning. */
NetExpr*ce = elab_and_eval(des, scope, cond_, -1);
if (ce == 0) {
delete top;
delete sub;
delete step;
return 0;
}
@ -4564,10 +4919,10 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
/* All done, build up the loop. */
NetWhile*loop = new NetWhile(ce, body);
NetForLoop*loop = new NetForLoop(sig, initial_expr, ce, sub, step);
loop->set_line(*this);
top->append(loop);
return top;
loop->wrap_up();
return loop;
}
/*
@ -5199,6 +5554,9 @@ bool PPackage::elaborate(Design*des, NetScope*scope) const
// Elaborate task methods.
elaborate_tasks(des, scope, tasks);
// Elaborate class definitions.
elaborate_classes(des, scope, classes);
return result_flag;
}
@ -5626,6 +5984,28 @@ bool Design::check_proc_delay() const
return result_flag;
}
void Design::root_elaborate(void)
{
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
; cur != classes_.end() ; ++ cur) {
netclass_t*cur_class = cur->second;
PClass*cur_pclass = class_to_pclass_[cur_class];
cur_class->elaborate(this, cur_pclass);
}
for (map<NetScope*,PTaskFunc*>::iterator cur = root_tasks_.begin()
; cur != root_tasks_.end() ; ++ cur) {
if (debug_elaborate) {
cerr << cur->second->get_fileline() << ": Design::root_elaborate: "
<< "Elaborate for root task/func " << scope_path(cur->first) << endl;
}
cur->second->elaborate(this, cur->first);
}
}
/*
* This function is the root of all elaboration. The input is the list
* of root module names. The function locates the Module definitions
@ -5657,12 +6037,19 @@ Design* elaborate(list<perm_string>roots)
// Elaborate enum sets in $root scope.
elaborate_rootscope_enumerations(des);
// Elaborate tasks and functions in $root scope.
elaborate_rootscope_tasks(des);
// Elaborate classes in $root scope.
elaborate_rootscope_classes(des);
// Elaborate the packages. Package elaboration is simpler
// because there are fewer sub-scopes involved.
i = 0;
for (map<perm_string,PPackage*>::iterator pac = pform_packages.begin()
; pac != pform_packages.end() ; ++ pac) {
ivl_assert(*pac->second, pac->first == pac->second->pscope_name());
NetScope*scope = des->make_package_scope(pac->first);
scope->set_line(pac->second);
@ -5754,6 +6141,11 @@ Design* elaborate(list<perm_string>roots)
}
}
if (debug_elaborate) {
cerr << "<toplevel>: elaborate: "
<< "elaboration work list done. Start processing residual defparams." << endl;
}
// Look for residual defparams (that point to a non-existent
// scope) and clean them out.
des->residual_defparams();
@ -5763,6 +6155,11 @@ Design* elaborate(list<perm_string>roots)
if (des->errors > 0)
return des;
if (debug_elaborate) {
cerr << "<toplevel>: elaborate: "
<< "Start calling Package elaborate_sig methods." << endl;
}
// With the parameters evaluated down to constants, we have
// what we need to elaborate signals and memories. This pass
// creates all the NetNet and NetMemory objects for declared
@ -5781,6 +6178,18 @@ Design* elaborate(list<perm_string>roots)
}
}
if (debug_elaborate) {
cerr << "<toplevel>: elaborate: "
<< "Start calling $root elaborate_sig methods." << endl;
}
des->root_elaborate_sig();
if (debug_elaborate) {
cerr << "<toplevel>: elaborate: "
<< "Start calling root module elaborate_sig methods." << endl;
}
for (i = 0; i < root_elems.size(); i++) {
Module *rmod = root_elems[i].mod;
NetScope *scope = root_elems[i].scope;
@ -5812,7 +6221,9 @@ Design* elaborate(list<perm_string>roots)
// stuff to the design that should be cleaned later.
NetNet *netnet = mport[pin]->elaborate_subport(des, scope);
if (netnet != 0) {
// Elaboration may actually fail with erroneous input source
// Elaboration may actually fail with
// erroneous input source
ivl_assert(*mport[pin], netnet->pin_count()==1);
prt_vector_width += netnet->vector_width();
ptype = PortType::merged(netnet->port_type(), ptype);
}
@ -5835,6 +6246,8 @@ Design* elaborate(list<perm_string>roots)
rc &= pkg->elaborate(des, scope);
}
des->root_elaborate();
for (i = 0; i < root_elems.size(); i++) {
Module *rmod = root_elems[i].mod;
NetScope *scope = root_elems[i].scope;

45
emit.cc
View File

@ -167,6 +167,11 @@ bool NetSignExtend::emit_node(struct target_t*tgt) const
return tgt->sign_extend(this);
}
bool NetSubstitute::emit_node(struct target_t*tgt) const
{
return tgt->substitute(this);
}
bool NetUReduce::emit_node(struct target_t*tgt) const
{
return tgt->ureduce(this);
@ -283,6 +288,11 @@ bool NetForever::emit_proc(struct target_t*tgt) const
return true;
}
bool NetForLoop::emit_proc(struct target_t*tgt) const
{
return tgt->proc_block(as_block_);
}
bool NetFree::emit_proc(struct target_t*tgt) const
{
tgt->proc_free(this);
@ -399,14 +409,13 @@ void NetRepeat::emit_recurse(struct target_t*tgt) const
void netclass_t::emit_scope(struct target_t*tgt) const
{
class_scope_->emit_scope(tgt);
class_scope_->emit_defs(tgt);
}
void NetScope::emit_scope(struct target_t*tgt) const
{
if (debug_emit) {
cerr << "NetScope::emit_scope: "
<< "Emit scope basename=" << basename() << endl;
<< "Emit scope " << scope_path(this) << endl;
}
tgt->scope(this);
@ -451,12 +460,20 @@ bool NetScope::emit_defs(struct target_t*tgt) const
{
bool flag = true;
if (debug_emit) {
cerr << "NetScope::emit_defs: "
<< "Emit definitions for " << scope_path(this) << endl;
}
switch (type_) {
case PACKAGE:
case MODULE:
for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
; cur != children_.end() ; ++ cur )
flag &= cur->second->emit_defs(tgt);
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
; cur != classes_.end() ; ++ cur)
flag &= cur->second->emit_defs(tgt);
break;
case FUNC:
@ -475,6 +492,11 @@ bool NetScope::emit_defs(struct target_t*tgt) const
return flag;
}
bool netclass_t::emit_defs(struct target_t*tgt) const
{
return class_scope_->emit_defs(tgt);
}
int Design::emit(struct target_t*tgt) const
{
int rc = 0;
@ -482,12 +504,26 @@ int Design::emit(struct target_t*tgt) const
if (tgt->start_design(this) == false)
return -2;
for (map<NetScope*,PTaskFunc*>::const_iterator scope = root_tasks_.begin()
; scope != root_tasks_.end() ; ++ scope) {
scope->first->emit_scope(tgt);
scope->first->emit_defs(tgt);
}
// enumerate package scopes
for (map<perm_string,NetScope*>::const_iterator scope = packages_.begin()
; scope != packages_.end() ; ++ scope) {
scope->second->emit_scope(tgt);
}
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
; cur != classes_.end() ; ++cur) {
const NetScope*use_scope = cur->second->class_scope();
cur->second->emit_scope(tgt);
tgt->class_type(use_scope, cur->second);
cur->second->emit_defs(tgt);
}
// enumerate root scopes
for (list<NetScope*>::const_iterator scope = root_scopes_.begin()
; scope != root_scopes_.end(); ++ scope ) {
@ -600,6 +636,11 @@ void NetEEvent::expr_scan(struct expr_scan_t*tgt) const
tgt->expr_event(this);
}
void NetELast::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_last(this);
}
void NetENetenum::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_netenum(this);

View File

@ -44,6 +44,14 @@ verinum* PEBinary::eval_const(Design*des, NetScope*scope) const
verinum*res;
switch (op_) {
case 'p': {
if (l->is_defined() && r->is_defined()) {
res = new verinum(pow(*l, *r));
} else {
res = new verinum(verinum::Vx, l->len());
}
break;
}
case '+': {
if (l->is_defined() && r->is_defined()) {
res = new verinum(*l + *r);

View File

@ -1384,6 +1384,7 @@ NetExpr*NetETernary::blended_arguments_(const NetExpr*te, const NetExpr*fe) cons
if (tv == fv) val.set(idx, tv);
else val.set(idx, verinum::Vx);
}
val.has_sign(has_sign());
if (debug_eval_tree) {
cerr << get_fileline() << ": debug: Evaluate ternary with "
@ -2015,6 +2016,7 @@ static bool get_array_info(const NetExpr*arg, long dim,
/* A string or dynamic array must be handled by the run time. */
switch (sig->data_type()) {
case IVL_VT_DARRAY:
case IVL_VT_QUEUE:
case IVL_VT_STRING:
defer = true;
return true;

View File

@ -274,7 +274,7 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope, NetExpr*root)
if (op_ == 'E' || op_ == 'N') {
NetCaseCmp*gate = new NetCaseCmp(scope, scope->local_symbol(),
width, op_=='E'?true:false);
width, op_=='E'?NetCaseCmp::EEQ:NetCaseCmp::NEQ);
gate->set_line(*this);
connect(gate->pin(0), osig->pin(0));
connect(gate->pin(1), lsig->pin(0));
@ -1271,6 +1271,22 @@ NetNet* NetETernary::synthesize(Design *des, NetScope*scope, NetExpr*root)
*/
NetNet* NetESignal::synthesize(Design*des, NetScope*scope, NetExpr*root)
{
// If this is a synthesis with a specific value for the
// signal, then replace it (here) with a constant value.
if (net_->scope()==scope && net_->name()==scope->genvar_tmp) {
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, tmp_vec);
verinum tmp_val ((uint64_t)scope->genvar_tmp_val, net_->vector_width());
NetConst*tmp_const = new NetConst(scope, scope->local_symbol(), tmp_val);
tmp_const->set_line(*this);
des->add_node(tmp_const);
connect(tmp->pin(0), tmp_const->pin(0));
return tmp;
}
if (word_ == 0)
return net_;
@ -1440,6 +1456,12 @@ NetNet* NetEUFunc::synthesize(Design*des, NetScope*scope, NetExpr*root)
osig->local_flag(true);
connect(net->pin(0), osig->pin(0));
if (debug_synth2) {
cerr << get_fileline() << ": NetEUFunc::synthesize: "
<< "result_sig_->vector_width()=" << result_sig_->vector_width()
<< ", osig->vector_width()=" << osig->vector_width() << endl;
}
/* Connect the pins to the arguments. */
NetFuncDef*def = func_->func_def();
for (unsigned idx = 0; idx < eparms.size(); idx += 1) {

View File

@ -1,7 +1,7 @@
#ifndef __functor_H
#define __functor_H
#ifndef IVL_functor_H
#define IVL_functor_H
/*
* Copyright (c) 1999-2008,2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2014 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
@ -105,4 +105,4 @@ struct proc_match_t {
virtual int block(class NetBlock*);
};
#endif
#endif /* IVL_functor_H */

View File

@ -1,7 +1,7 @@
#ifndef __ivl_alloc_H
#define __ivl_alloc_H
#ifndef IVL_ivl_alloc_H
#define IVL_ivl_alloc_H
/*
* Copyright (C) 2010 Cary R. (cygcary@yahoo.com)
* Copyright (C) 2010-2014 Cary R. (cygcary@yahoo.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -83,4 +83,4 @@
__ivl_rtn; \
})
#endif
#endif /* IVL_ivl_alloc_H */

View File

@ -1,5 +1,7 @@
#ifndef IVL_ivl_assert_H
#define IVL_ivl_assert_H
/*
* Copyright (c) 2007-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2007-2014 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
@ -17,9 +19,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __ivl_assert_h
#define __ivl_assert_h
# include <cstdlib>
#define ivl_assert(tok, expression) \
@ -32,4 +31,4 @@
} \
} while (0)
#endif
#endif /* IVL_ivl_assert_H */

View File

@ -1,7 +1,7 @@
#ifndef __ivl_target_H
#define __ivl_target_H
#ifndef IVL_ivl_target_H
#define IVL_ivl_target_H
/*
* Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2014 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
@ -300,6 +300,8 @@ typedef enum ivl_lpm_type_e {
IVL_LPM_CONCAT = 16,
IVL_LPM_CONCATZ = 36, /* Transparent concat */
IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */
IVL_LPM_CMP_EQX= 37, /* Windcard EQ (==?) */
IVL_LPM_CMP_EQZ= 38, /* casez EQ */
IVL_LPM_CMP_EQ = 10,
IVL_LPM_CMP_GE = 1,
IVL_LPM_CMP_GT = 2,
@ -326,6 +328,7 @@ typedef enum ivl_lpm_type_e {
IVL_LPM_SHIFTR = 7,
IVL_LPM_SIGN_EXT=27,
IVL_LPM_SUB = 8,
IVL_LPM_SUBSTITUTE=39,
/* IVL_LPM_RAM = 9, / obsolete */
IVL_LPM_UFUNC = 14
} ivl_lpm_type_t;
@ -437,6 +440,7 @@ typedef enum ivl_variable_type_e {
IVL_VT_STRING = 5,
IVL_VT_DARRAY = 6, /* Array (esp. dynamic array) */
IVL_VT_CLASS = 7, /* SystemVerilog class instances */
IVL_VT_QUEUE = 8, /* SystemVerilog queue instances */
IVL_VT_VECTOR = IVL_VT_LOGIC /* For compatibility */
} ivl_variable_type_t;
@ -828,6 +832,10 @@ extern unsigned ivl_event_lineno(ivl_event_t net);
* table. That number can be passed to ivl_type_prop_*() functions to
* get details about the property.
*
* If the property is an array, then the ivl_expr_oper1() function
* returns the canonical expression for accessing the element of the
* property.
*
* - IVL_EX_NEW
* This expression takes one or two operands. The first operand,
* returned by ivl_expr_oper1() is the number of elements to create
@ -1265,7 +1273,7 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
* width of the part. The ivl_lpm_q is the part end, and the
* ivl_lpm_data(0) is the non-part end.
*
* - Comparisons (IVL_LPM_CMP_GT/GE/EQ/NE/EEQ/NEE)
* - Comparisons (IVL_LPM_CMP_GT/GE/EQ/NE/EEQ/NEE/EQX/EQZ)
* These devices have two inputs, available by the ivl_lpm_data()
* function, and one output available by the ivl_lpm_q function. The
* output width is always 1, but the ivl_lpm_width() returns the width
@ -1277,6 +1285,11 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
* magnitude compare, the signedness does matter. In any case, the
* result of the compare is always unsigned.
*
* The EQX and EQZ nodes are windcard compares, where xz bits (EQX) or
* z bits (EQZ) in the data(1) operand are treated as windcards. no
* bits in the data(0) operand are wild. This matches the
* SystemVerilog convention for the ==? operator.
*
* - Mux Device (IVL_LPM_MUX)
* The MUX device has a q output, a select input, and a number of data
* inputs. The ivl_lpm_q output and the ivl_lpm_data inputs all have
@ -1402,7 +1415,7 @@ extern ivl_nexus_t ivl_lpm_sync_set(ivl_lpm_t net);
extern ivl_expr_t ivl_lpm_sset_value(ivl_lpm_t net);
/* IVL_LPM_ARRAY */
extern ivl_signal_t ivl_lpm_array(ivl_lpm_t net);
/* IVL_LPM_PART */
/* IVL_LPM_PART IVL_LPM_SUBSTITUTE */
extern unsigned ivl_lpm_base(ivl_lpm_t net);
/* IVL_LPM_FF */
extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
@ -1412,12 +1425,14 @@ extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
/* IVL_LPM_ADD IVL_LPM_CONCAT IVL_LPM_FF IVL_LPM_PART IVL_LPM_MULT
IVL_LPM_MUX IVL_LPM_POW IVL_LPM_SHIFTL IVL_LPM_SHIFTR IVL_LPM_SUB
IVL_LPM_UFUNC */
IVL_LPM_UFUNC IVL_LPM_SUBSTITUTE */
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_POW IVL_LPM_SUB */
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_POW IVL_LPM_SUB IVL_LPM_CMP_EQ
IVL_LPM_CMP_EEQ IVL_LPM_CMP_EQX IVL_LPM_CMP_EQZ IVL_LPM_CMP_NEE */
extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART IVL_LPM_POW
IVL_LPM_SUB IVL_LPM_UFUNC */
IVL_LPM_SUB IVL_LPM_UFUNC IVL_LPM_CMP_EEQ IVL_LPM_CMP_EQX
IVL_LPM_CMP_EQZ IVL_LPM_CMP_NEE IVL_LPM_SUBSTITUTE */
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net);
extern ivl_drive_t ivl_lpm_drive0(ivl_lpm_t net);
extern ivl_drive_t ivl_lpm_drive1(ivl_lpm_t net);
@ -1488,6 +1503,11 @@ extern const char*ivl_lpm_string(ivl_lpm_t net);
* then the ivl_lval_idx expression must *not* be present.
*
* For array words, the ivl_lval_width is the width of the word.
*
* - Arrayed properties
* If the l-value is a class property, then the ivl_lval_idx function
* will return an expression if the property is in fact arrayed. The
* expression is the canonical index for elements in the property.
*/
extern unsigned ivl_lval_width(ivl_lval_t net);
@ -2322,4 +2342,4 @@ typedef const char* (*target_query_f) (const char*key);
_END_DECL
#endif
#endif /* IVL_ivl_target_H */

View File

@ -1,7 +1,7 @@
#ifndef __ivl_target_priv_H
#define __ivl_target_priv_H
#ifndef IVL_ivl_target_priv_H
#define IVL_ivl_target_priv_H
/*
* Copyright (c) 2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008-2014 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
@ -52,6 +52,7 @@ struct ivl_design_s {
// Keep arrays of root scopes.
std::map<const NetScope*,ivl_scope_t> classes;
std::map<const NetScope*,ivl_scope_t> root_tasks;
std::vector<ivl_scope_t> packages;
std::vector<ivl_scope_t> roots;
@ -90,4 +91,4 @@ struct ivl_island_s {
extern std::ostream& operator << (std::ostream&o, ivl_drive_t str);
#endif
#endif /* IVL_ivl_target_priv_H */

View File

@ -44,7 +44,7 @@ INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
endif
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
LDFLAGS = @LDFLAGS@
O = main.o lexor.o

View File

@ -1,7 +1,7 @@
#ifndef __globals_H
#define __globals_H
#ifndef IVL_globals_H
#define IVL_globals_H
/*
* Copyright (c) 1999-2009 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -22,11 +22,11 @@
# include <stdio.h>
extern void reset_lexor(FILE*out, char*paths[]);
extern void destroy_lexor();
extern void destroy_lexor(void);
extern void load_precompiled_defines(FILE*src);
extern void define_macro(const char*name, const char*value, int keyword,
int argc);
extern void free_macros();
extern void free_macros(void);
extern void dump_precompiled_defines(FILE*out);
/* These variables contain the include directories to be searched when
@ -54,6 +54,6 @@ extern char dep_mode;
extern int verbose_flag;
/* This is the entry to the lexer. */
extern int yylex();
extern int yylex(void);
#endif
#endif /* IVL_globals_H */

View File

@ -1,7 +1,7 @@
%option prefix="yy"
%{
/*
* Copyright (c) 1999-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2014 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
@ -30,29 +30,29 @@
# include "globals.h"
# include "ivl_alloc.h"
static void output_init();
static void output_init(void);
#define YY_USER_INIT output_init()
static void def_start();
static void def_add_arg();
static void def_finish();
static void def_undefine();
static void do_define();
static int def_is_done();
static void def_start(void);
static void def_add_arg(void);
static void def_finish(void);
static void def_undefine(void);
static void do_define(void);
static int def_is_done(void);
static int is_defined(const char*name);
static int macro_needs_args(const char*name);
static void macro_start_args();
static void macro_start_args(void);
static void macro_add_to_arg(int is_whitespace);
static void macro_finish_arg();
static void macro_finish_arg(void);
static void do_expand(int use_args);
static const char* do_magic(const char*name);
static const char* macro_name();
static const char* macro_name(void);
static void include_filename();
static void do_include();
static void include_filename(void);
static void do_include(void);
static int load_next_input();
static int load_next_input(void);
struct include_stack_t
{
@ -804,7 +804,7 @@ static /* inline */ char* def_argv(int arg)
return def_buf + def_argo[arg];
}
static void check_for_max_args()
static void check_for_max_args(void)
{
if (def_argc == MAX_DEF_ARG)
{
@ -825,14 +825,14 @@ static void def_buf_grow_to_fit(int length)
}
}
static void def_start()
static void def_start(void)
{
def_buf_free = def_buf_size;
def_argc = 0;
def_add_arg();
}
static void def_add_arg()
static void def_add_arg(void)
{
int length = yyleng;
@ -852,7 +852,7 @@ static void def_add_arg()
char*arg = yytext;
char*val;
int val_length;
int val_length = 0;
/* Break into ARG = value. This happens if the source specifies
a default value for the formal argument. In that case, the
@ -979,7 +979,7 @@ static void free_macro(struct define_t* def)
free(def);
}
void free_macros()
void free_macros(void)
{
free_macro(def_table);
}
@ -1052,7 +1052,7 @@ static char *find_arg(char*ptr, char*head, char*arg)
* continuation, then return 1 and this function may be called again
* to collect another line of the definition.
*/
static void do_define()
static void do_define(void)
{
char* cp;
char* head;
@ -1202,7 +1202,7 @@ static void do_define()
* Return true if the definition text is done. This is the opposite of
* the define_continue_flag.
*/
static int def_is_done()
static int def_is_done(void)
{
return !define_continue_flag;
}
@ -1212,7 +1212,7 @@ static int def_is_done()
* assigned value to the parsed name. If there is no value, then
* assign the string "" (empty string.)
*/
static void def_finish()
static void def_finish(void)
{
define_continue_flag = 0;
@ -1234,7 +1234,7 @@ static void def_finish()
def_argc = 0;
}
static void def_undefine()
static void def_undefine(void)
{
struct define_t* cur;
struct define_t* tail;
@ -1360,7 +1360,7 @@ static int macro_needs_args(const char*text)
}
}
static const char* macro_name()
static const char* macro_name(void)
{
return cur_macro ? cur_macro->name : "";
}
@ -1402,7 +1402,7 @@ static void macro_add_to_arg(int is_white_space)
def_buf_free -= length;
}
static void macro_finish_arg()
static void macro_finish_arg(void)
{
char* tail = &def_buf[def_buf_size - def_buf_free];
@ -1443,7 +1443,7 @@ static void exp_buf_grow_to_fit(int length)
}
}
static void expand_using_args()
static void expand_using_args(void)
{
char* head;
char* tail;
@ -1634,7 +1634,8 @@ static const char* do_magic(const char*name)
int actual_len = snprintf(magic_text, desired_cnt,
"%u", get_line(istack));
assert(actual_len < desired_cnt);
assert(actual_len >= 0);
assert((unsigned) actual_len < desired_cnt);
return magic_text;
}
else if(!strcmp(name, "__FILE__"))
@ -1654,7 +1655,9 @@ static const char* do_magic(const char*name)
int actual_len = snprintf(magic_text, desired_cnt,
"\"%s\"", path);
assert(actual_len < desired_cnt);
assert(actual_len >= 0);
assert((unsigned) actual_len < (unsigned)desired_cnt);
return magic_text;
}
}
@ -1684,13 +1687,13 @@ static const char* do_magic(const char*name)
* parsing resumes.
*/
static void output_init()
static void output_init(void)
{
if (line_direct_flag)
fprintf(yyout, "`line 1 \"%s\" 0\n", istack->path);
}
static void include_filename()
static void include_filename(void)
{
if(standby) {
emit_pathline(istack);
@ -1709,7 +1712,7 @@ static void include_filename()
standby->comment = NULL;
}
static void do_include()
static void do_include(void)
{
/* standby is defined by include_filename() */
if (standby->path[0] == '/') {
@ -1832,7 +1835,7 @@ static void emit_pathline(struct include_stack_t* isp)
fprintf(stderr, "%s:%u: ", isp->path, isp->lineno+1);
}
static void lexor_done()
static void lexor_done(void)
{
while (ifdef_stack)
{
@ -1920,7 +1923,7 @@ static void open_input_file(struct include_stack_t*isp)
* end of a base file, in which case the next base source file is
* opened.
*/
static int load_next_input()
static int load_next_input(void)
{
int line_mask_flag = 0;
struct include_stack_t* isp = istack;
@ -2190,7 +2193,7 @@ void reset_lexor(FILE* out, char* paths[])
/*
* Modern version of flex (>=2.5.9) can clean up the scanner data.
*/
void destroy_lexor()
void destroy_lexor(void)
{
# ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5

View File

@ -4,7 +4,7 @@
%{
/*
* Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2014 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
@ -134,9 +134,17 @@ TU [munpf]
\n { yylloc.first_line += 1; }
/* C++ style comments start with / / and run to the end of the
current line. These are very easy to handle. */
current line. These are very easy to handle. The meta-comments
format is a little more tricky to handle, but do what we can. */
"//".* { comment_enter = YY_START; BEGIN(LCOMMENT); }
/* The lexor detects "// synthesis translate_on/off" meta-comments,
we handle them here by turning on/off a flag. The pform uses
that flag to attach implicit attributes to "initial" and
"always" statements. */
"//"{W}*"synthesis"{W}+"translate_on"{W}*\n { pform_mc_translate_on(true); }
"//"{W}*"synthesis"{W}+"translate_off"{W}*\n { pform_mc_translate_on(false); }
"//" { comment_enter = YY_START; BEGIN(LCOMMENT); }
<LCOMMENT>. { yymore(); }
<LCOMMENT>\n { yylloc.first_line += 1; BEGIN(comment_enter); }
@ -325,8 +333,8 @@ TU [munpf]
if (in_package_scope) {
if (rc == IDENTIFIER) {
if (data_type_t*type = pform_test_type_identifier(in_package_scope, yylval.text)) {
delete[]yylval.text;
yylval.data_type = type;
yylval.type_identifier.text = yylval.text;
yylval.type_identifier.type = type;
rc = TYPE_IDENTIFIER;
}
}
@ -361,8 +369,8 @@ TU [munpf]
return this as a TYPE_IDENTIFIER instead. */
if (rc == IDENTIFIER && gn_system_verilog()) {
if (data_type_t*type = pform_test_type_identifier(yylval.text)) {
delete[]yylval.text;
yylval.data_type = type;
yylval.type_identifier.text = yylval.text;
yylval.type_identifier.type = type;
rc = TYPE_IDENTIFIER;
}
}
@ -382,8 +390,8 @@ TU [munpf]
}
if (gn_system_verilog()) {
if (data_type_t*type = pform_test_type_identifier(yylval.text)) {
delete[]yylval.text;
yylval.data_type = type;
yylval.type_identifier.text = yylval.text;
yylval.type_identifier.type = type;
return TYPE_IDENTIFIER;
}
}
@ -649,14 +657,14 @@ TU [munpf]
|GN_KEYWORDS_1364_2005
|GN_KEYWORDS_VAMS_2_3;
} else {
fprintf(stderr, "%s:%u: Ignoring unknown keywords string: %s\n",
fprintf(stderr, "%s:%d: Ignoring unknown keywords string: %s\n",
yylloc.text, yylloc.first_line, word);
}
BEGIN(0);
}
<PPBEGIN_KEYWORDS>.* {
fprintf(stderr, "%s:%u: Malformed keywords specification: %s\n",
fprintf(stderr, "%s:%d: Malformed keywords specification: %s\n",
yylloc.text, yylloc.first_line, yytext);
BEGIN(0);
}
@ -666,7 +674,7 @@ TU [munpf]
lexor_keyword_mask = keyword_mask_stack.front();
keyword_mask_stack.pop_front();
} else {
fprintf(stderr, "%s:%u: Mismatched end_keywords directive\n",
fprintf(stderr, "%s:%d: Mismatched end_keywords directive\n",
yylloc.text, yylloc.first_line);
}
}

View File

@ -1,7 +1,7 @@
#ifndef __lexor_keyword_H
#define __lexor_keyword_H
#ifndef IVL_lexor_keyword_H
#define IVL_lexor_keyword_H
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -21,4 +21,4 @@
extern int lexor_keyword_code (const char*str, unsigned len);
#endif
#endif /* IVL_lexor_keyword_H */

View File

@ -1,7 +1,7 @@
#ifndef __LineInfo_H
#define __LineInfo_H
#ifndef IVL_LineInfo_H
#define IVL_LineInfo_H
/*
* Copyright (c) 1999-2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2014 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
@ -54,4 +54,4 @@ class LineInfo {
unsigned lineno_;
};
#endif
#endif /* IVL_LineInfo_H */

View File

@ -210,3 +210,5 @@ ostream& operator << (ostream&out, perm_string that)
out << that.str();
return out;
}
const perm_string empty_perm_string = perm_string::literal("");

View File

@ -1,7 +1,7 @@
#ifndef __StringHeap_H
#define __StringHeap_H
#ifndef IVL_StringHeap_H
#define IVL_StringHeap_H
/*
* Copyright (c) 2002-2009 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-2014 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
@ -52,6 +52,7 @@ class perm_string {
const char*text_;
};
extern const perm_string empty_perm_string;
extern bool operator == (perm_string a, perm_string b);
extern bool operator == (perm_string a, const char* b);
extern bool operator != (perm_string a, perm_string b);
@ -120,4 +121,4 @@ class StringHeapLex : private StringHeap {
StringHeapLex& operator= (const StringHeapLex&);
};
#endif
#endif /* IVL_StringHeap_H */

View File

@ -48,7 +48,7 @@ LDRELOCFLAGS = @LDRELOCFLAGS@
LDTARGETFLAGS = @LDTARGETFLAGS@
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
A = a_close.o a_compare_handles.o a_configure.o a_fetch_argc.o \
a_fetch_argv.o a_fetch_dir.o a_fetch_fullname.o a_fetch_location.o \

View File

@ -69,9 +69,13 @@ int acc_configure(PLI_INT32 config_param, const char*value)
fprintf(pli_trace, "acc_configure(config=%d, %s)\n",
(int)config_param, value);
}
#if 0
vpi_printf("XXXX acc_configure(%d, %s)\n", (int)config_param,
value);
#else
/* Parameter is not necessarily a string. */
vpi_printf("XXXX acc_configure(%d, ...)\n", (int)config_param);
#endif
rc = 0;
break;
}

View File

@ -19,6 +19,7 @@
# include <vpi_user.h>
# include <veriuser.h>
# include <acc_user.h>
/*
* acc_fetch_argc implemented using VPI interface

View File

@ -19,6 +19,7 @@
# include <vpi_user.h>
# include <veriuser.h>
# include <acc_user.h>
/*
* acc_fetch_argv implemented using VPI interface

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003 Stephen Williams (steve@picturel.com)
* Copyright (c) 2003-2014 Stephen Williams (steve@picturel.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
@ -25,6 +25,7 @@
PLI_INT32 acc_fetch_direction(handle obj)
{
(void)obj; /* Parameter is not used. */
if (pli_trace) {
fprintf(pli_trace, "acc_fetch_direction: enter.\n");
fflush(pli_trace);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
* Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -22,6 +22,7 @@
int acc_fetch_location(p_location loc, handle obj)
{
(void)obj; /* Parameter is not used. */
loc->line_no = 0;
loc->filename = "<filename>";
return 1;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2003-2014 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
@ -40,3 +40,12 @@ const char* acc_fetch_type_str(PLI_INT32 type)
vpi_printf("acc_fetch_type_str: type %d is what accType?\n", (int)type);
return "acc_fetch_type_str(unknown)";
}
/*
* FIXME: What does this do? How should it be declared in acc_user.h?
*/
PLI_INT32 acc_fetch_paramtype(handle obj)
{
(void)obj; /* Parameter is not used. */
return 0;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003 Stephen Williams (steve@picturel.com)
* Copyright (c) 2003-2014 Stephen Williams (steve@picturel.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
@ -25,6 +25,7 @@
handle acc_handle_hiconn(handle obj)
{
(void)obj; /* Parameter is not used. */
if (pli_trace) {
fprintf(pli_trace, "acc_handle_hiconn: enter.\n");
fflush(pli_trace);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003 Stephen Williams (steve@picturel.com)
* Copyright (c) 2003-2014 Stephen Williams (steve@picturel.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
@ -25,6 +25,8 @@
handle acc_next_bit(handle ref, handle bit)
{
(void)ref; /* Parameter is not used. */
(void)bit; /* Parameter is not used. */
if (pli_trace) {
fprintf(pli_trace, "acc_next_bit: enter.\n");
fflush(pli_trace);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
* Copyright (c) 2003-2014 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
@ -25,6 +25,8 @@
handle acc_next_port(handle ref, handle bit)
{
(void)ref; /* Parameter is not used. */
(void)bit; /* Parameter is not used. */
if (pli_trace) {
fprintf(pli_trace, "acc_next_port: enter.\n");
fflush(pli_trace);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2003-2014 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
@ -162,6 +162,7 @@ void acc_vcl_add(handle obj, PLI_INT32(*consumer)(p_vc_record),
switch (vpi_get(vpiType, obj)) {
case vpiNet:
case vpiReg:
cur = malloc(sizeof (struct vcl_record));
cur->obj = obj;
cur->consumer = consumer;
@ -195,5 +196,9 @@ void acc_vcl_add(handle obj, PLI_INT32(*consumer)(p_vc_record),
void acc_vcl_delete(handle obj, PLI_INT32(*consumer)(p_vc_record),
void*data, PLI_INT32 vcl_flag)
{
(void)obj; /* Parameter is not used. */
(void)consumer; /* Parameter is not used. */
(void)data; /* Parameter is not used. */
(void)vcl_flag; /* Parameter is not used. */
vpi_printf("XXXX acc_vcl_delete(...)\n");
}

View File

@ -1,7 +1,7 @@
#ifndef __config_H
#define __config_H
#ifndef IVL_config_H
#define IVL_config_H
/*
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
* Copyright (c) 2003-2014 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
@ -37,4 +37,4 @@ typedef unsigned long ivl_u64_t;
# endif
#endif
#endif
#endif /* IVL_config_H */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
* Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -24,6 +24,7 @@
static PLI_INT32 delay_callback(struct t_cb_data*cb)
{
(void)cb; /* Parameter is not used. */
vpi_printf("XXXX delay_callback called.\n");
return 0;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
* Copyright (c) 2003-2014 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
@ -25,6 +25,8 @@
struct t_tfexprinfo* tf_exprinfo(PLI_INT32 a, struct t_tfexprinfo*ip)
{
(void)a; /* Parameter is not used. */
(void)ip; /* Parameter is not used. */
if (pli_trace) {
fprintf(pli_trace, "tf_exprinfo: enter.\n");
fflush(pli_trace);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2011 Michael Ruff (mruff at chiaro.com)
* Copyright (c) 2002-2014 Michael Ruff (mruff at chiaro.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
@ -39,14 +39,36 @@ static ivl_u64_t pow10u(PLI_INT32 val)
}
static ivl_u64_t
scale(int high, int low, void*obj) {
vpiHandle hand = vpi_handle(vpiScope, vpi_handle(vpiSysTfCall,0));
scale(int high, int low, void*obj)
{
ivl_u64_t scaled;
vpiHandle use_obj = obj;
if (use_obj == 0) {
/* If object is not passed in, then use current scope. */
vpiHandle hand = vpi_handle(vpiScope, vpi_handle(vpiSysTfCall,0));
use_obj = hand;
} else {
/* If object IS passed in, make sure it is a scope. If
it is not, then get the scope of the object. We need
a scope handle to go on. */
switch (vpi_get(vpiType,use_obj)) {
case vpiModule:
case vpiGenScope:
case vpiFunction:
case vpiTask:
case vpiNamedBegin:
case vpiNamedFork:
break;
default:
use_obj = vpi_handle(vpiScope, use_obj);
break;
}
}
scaled = high;
scaled = (scaled << 32) | low;
scaled /= pow10u(vpi_get(vpiTimeUnit,obj ? (vpiHandle)obj : hand) -
vpi_get(vpiTimePrecision,0));
scaled /= pow10u(vpi_get(vpiTimeUnit, use_obj) - vpi_get(vpiTimePrecision,0));
return scaled;
}
@ -125,6 +147,8 @@ void tf_unscale_longdelay(void*obj, PLI_INT32 low, PLI_INT32 high,
ivl_u64_t unscaled;
vpiHandle hand = vpi_handle(vpiScope, vpi_handle(vpiSysTfCall,0));
(void)obj; /* Parameter is not used. */
unscaled = high;
unscaled = (unscaled << 32) | low;
unscaled *= pow(10, vpi_get(vpiTimeUnit, hand) -
@ -138,6 +162,8 @@ void tf_scale_realdelay(void*obj, double real, double *areal)
{
vpiHandle hand = vpi_handle(vpiScope, vpi_handle(vpiSysTfCall,0));
(void)obj; /* Parameter is not used. */
*areal = real / pow(10, vpi_get(vpiTimeUnit, hand) -
vpi_get(vpiTimePrecision, 0));
}
@ -146,6 +172,8 @@ void tf_unscale_realdelay(void*obj, double real, double *areal)
{
vpiHandle hand = vpi_handle(vpiScope, vpi_handle(vpiSysTfCall,0));
(void)obj; /* Parameter is not used. */
*areal = real * pow(10, vpi_get(vpiTimeUnit, hand) -
vpi_get(vpiTimePrecision, 0));
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002 Michael Ruff (mruff at chiaro.com)
* Copyright (c) 2002-2014 Michael Ruff (mruff at chiaro.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
@ -58,6 +58,8 @@ PLI_INT32 tf_message(PLI_INT32 level, char*facility,
{
va_list ap;
(void)level; /* Parameter is not used. */
vpi_printf("%s[%s] ", facility, messno);
va_start(ap, fmt);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
* Copyright (c) 2003-2014 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
@ -23,8 +23,11 @@
# include <vpi_user.h>
# include "priv.h"
struct t_tfnoeinfo* tf_nodeinfo(PLI_INT32 a, struct t_tfnodeinfo*ip)
/* XXX Not declared or used anywhere? */
struct t_tfnodeinfo* tf_nodeinfo(PLI_INT32 a, struct t_tfnodeinfo*ip)
{
(void)a; /* Parameter is not used. */
(void)ip; /* Parameter is not used. */
if (pli_trace) {
fprintf(pli_trace, "tf_nodeinfo: enter.\n");
fflush(pli_trace);

View File

@ -19,6 +19,7 @@
#include <vpi_user.h>
#include <stdio.h>
#include "veriuser.h"
/*
* tf_nump implemented using VPI interface

View File

@ -1,7 +1,7 @@
#ifndef __priv_H
#define __priv_H
#ifndef IVL_priv_H
#define IVL_priv_H
/*
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
* Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -33,4 +33,4 @@ extern char* __acc_newstring(const char*txt);
*/
FILE* pli_trace;
#endif
#endif /* IVL_priv_H */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2013 Michael Ruff (mruff at chiaro.com)
* Copyright (c) 2002-2014 Michael Ruff (mruff at chiaro.com)
* Michael Runyan (mrunyan at chiaro.com)
*
* This source code is free software; you can redistribute it
@ -57,6 +57,8 @@ static PLI_INT32 sys_end_of_simulation(p_cb_data cb_data)
{
unsigned idx;
(void)cb_data; /* Parameter is not used. */
for (idx = 0; idx < udata_count; idx += 1) {
free(udata_store[idx]);
}
@ -370,7 +372,7 @@ PLI_INT32 tf_irosynchronize(void*obj)
vpiHandle sys = (vpiHandle)obj;
p_pli_data pli = vpi_get_userdata(sys);
s_cb_data cb;
s_vpi_time ti = {vpiSuppressTime, 0, 0};
s_vpi_time ti = {vpiSuppressTime, 0, 0, 0.0};
cb.reason = cbReadOnlySynch;
cb.cb_rtn = callback;
@ -397,7 +399,7 @@ PLI_INT32 tf_isetrealdelay(double dly, void*obj)
vpiHandle sys = (vpiHandle)obj;
p_pli_data pli = vpi_get_userdata(sys);
s_cb_data cb;
s_vpi_time ti = {vpiSimTime};
s_vpi_time ti = {vpiSimTime, 0, 0, 0.0};
/* Scale delay to SimTime */
ivl_u64_t delay = ((dly

View File

@ -232,3 +232,58 @@ verinum Nexus::driven_vector() const
return val;
}
/*
* Calculate a vector that represent all the bits of the vector, with
* each driven bit set to true, otherwise false.
*/
vector<bool> Nexus::driven_mask(void) const
{
vector<bool> mask (vector_width());
for (const Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
Link::DIR link_dir = cur->get_dir();
if (link_dir==Link::PASSIVE)
continue;
if (link_dir==Link::INPUT)
continue;
const NetPins*obj = cur->get_obj();
// If the link is to a variable (REG or INTEGER) then
// the variable is driving all the bits. We have our
// complete answer, mark all the bits as driven and
// finish. Otherwise, we are not going to get new
// information from this node, move on.
if (const NetNet*sig = dynamic_cast<const NetNet*> (obj)) {
NetNet::Type sig_type = sig->type();
if (sig_type==NetNet::INTEGER || sig_type==NetNet::REG) {
for (size_t idx = 0 ; idx < mask.size() ; idx += 1)
mask[idx] = true;
return mask;
}
continue;
}
const NetPartSelect*obj_ps = dynamic_cast<const NetPartSelect*>(obj);
if (obj_ps && obj_ps->dir()==NetPartSelect::VP)
continue;
if (obj_ps && cur->get_pin()!=1)
continue;
if (obj_ps) {
for (unsigned idx = 0 ; idx < obj_ps->width() ; idx += 1) {
size_t bit = idx + obj_ps->base();
ivl_assert(*obj, bit < mask.size());
mask[bit] = true;
}
continue;
}
for (size_t idx = 0 ; idx < mask.size() ; idx += 1)
mask[idx] = true;
return mask;
}
return mask;
}

16
main.cc
View File

@ -1019,6 +1019,16 @@ int main(int argc, char*argv[])
; cur != disciplines.end() ; ++ cur ) {
pform_dump(out, (*cur).second);
}
out << "PFORM DUMP $ROOT TASKS/FUNCTIONS:" << endl;
for (map<perm_string,PTaskFunc*>::iterator cur = pform_tasks.begin()
; cur != pform_tasks.end() ; ++ cur) {
pform_dump(out, cur->second);
}
out << "PFORM DUMP $ROOT CLASSES:" << endl;
for (map<perm_string,PClass*>::iterator cur = pform_classes.begin()
; cur != pform_classes.end() ; ++ cur) {
pform_dump(out, cur->second);
}
out << "PFORM DUMP PACKAGES:" << endl;
for (map<perm_string,PPackage*>::iterator pac = pform_packages.begin()
; pac != pform_packages.end() ; ++ pac) {
@ -1142,6 +1152,12 @@ int main(int argc, char*argv[])
(*idx).second = 0;
}
for(map<perm_string,data_type_t*>::iterator it = pform_typedefs.begin()
; it != pform_typedefs.end() ; ++it) {
delete (*it).second;
(*it).second = 0;
}
if (verbose_flag) {
if (times_flag) {
times(cycles+2);

View File

@ -1,7 +1,7 @@
#ifndef __named_H
#define __named_H
#ifndef IVL_named_H
#define IVL_named_H
/*
* Copyright (c) 2000-2004 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2014 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
@ -31,4 +31,4 @@ template <class T> struct named {
T parm;
};
#endif
#endif /* IVL_named_H */

View File

@ -134,6 +134,21 @@ NetScope* Design::make_package_scope(perm_string name)
return scope;
}
void Design::add_class(netclass_t*cl, PClass*pclass)
{
Definitions::add_class(cl);
class_to_pclass_[cl] = pclass;
}
netclass_t* Design::find_class(perm_string name) const
{
map<perm_string,netclass_t*>::const_iterator cur = classes_.find(name);
if (cur != classes_.end())
return cur->second;
return 0;
}
NetScope* Design::find_package(perm_string name) const
{
map<perm_string,NetScope*>::const_iterator cur = packages_.find(name);
@ -154,6 +169,17 @@ list<NetScope*> Design::find_package_scopes() const
return res;
}
list<NetScope*> Design::find_roottask_scopes() const
{
list<NetScope*>res;
for (map<NetScope*,PTaskFunc*>::const_iterator cur = root_tasks_.begin()
; cur != root_tasks_.end() ; ++ cur) {
res.push_back (cur->first);
}
return res;
}
/*
* This method locates a scope in the design, given its rooted
* hierarchical name. Each component of the key is used to scan one
@ -182,7 +208,25 @@ NetScope* Design::find_scope(const std::list<hname_t>&path) const
tmp.pop_front();
}
}
for (map<NetScope*,PTaskFunc*>::const_iterator root = root_tasks_.begin()
; root != root_tasks_.end() ; ++ root) {
NetScope*cur = root->first;
if (path.front() != cur->fullname())
continue;
std::list<hname_t> tmp = path;
tmp.pop_front();
while (cur) {
if (tmp.empty()) return cur;
cur = cur->child( tmp.front() );
tmp.pop_front();
}
}
return 0;
@ -821,6 +865,11 @@ NetScope* Design::find_task(NetScope*scope, const pform_name_t&name)
return 0;
}
void Design::add_root_task(NetScope*tscope, PTaskFunc*tf)
{
root_tasks_[tscope] = tf;
}
void Design::add_node(NetNode*net)
{
assert(net->design_ == 0);

View File

@ -20,6 +20,7 @@
# include "config.h"
# include "compiler.h"
# include "netlist.h"
# include "ivl_assert.h"
/*
* NOTE: The name_ is perm-allocated by the caller.
@ -316,6 +317,10 @@ void NetEvProbe::find_similar_probes(list<NetEvProbe*>&plist)
for (Link*lcur = nex->first_nlink(); lcur; lcur = lcur->next_nlink()) {
NetPins*obj = lcur->get_obj();
// Skip NexusSet objects
if (obj == 0)
continue;
if (obj->pin_count() != pin_count())
continue;
@ -340,14 +345,14 @@ void NetEvProbe::find_similar_probes(list<NetEvProbe*>&plist)
}
NetEvWait::NetEvWait(NetProc*pr)
: statement_(pr), nevents_(0), events_(0)
: statement_(pr)
{
}
NetEvWait::~NetEvWait()
{
if (events_) {
for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) {
if (! events_.empty()) {
for (unsigned idx = 0 ; idx < events_.size() ; idx += 1) {
NetEvent*tgt = events_[idx];
tgt->waitref_ -= 1;
@ -365,7 +370,7 @@ NetEvWait::~NetEvWait()
delete tmp;
}
}
delete[]events_;
events_.clear();
}
delete statement_;
}
@ -374,29 +379,12 @@ void NetEvWait::add_event(NetEvent*tgt)
{
/* A wait fork is an empty event. */
if (! tgt) {
assert(nevents_ == 0);
nevents_ = 1;
events_ = new NetEvent*[1];
events_[0] = 0;
assert(events_.empty());
events_.push_back(0);
return;
}
if (nevents_ == 0) {
events_ = new NetEvent*[1];
} else {
assert(events_[0]);
NetEvent**tmp = new NetEvent*[nevents_+1];
for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) {
tmp[idx] = events_[idx];
assert(tmp[idx] != tgt);
}
delete[]events_;
events_ = tmp;
}
events_[nevents_] = tgt;
nevents_ += 1;
events_.push_back(tgt);
// Remember to tell the NetEvent that there is someone
// pointing to it.
@ -411,14 +399,14 @@ void NetEvWait::add_event(NetEvent*tgt)
void NetEvWait::replace_event(NetEvent*src, NetEvent*repl)
{
unsigned idx;
for (idx = 0 ; idx < nevents_ ; idx += 1) {
for (idx = 0 ; idx < events_.size() ; idx += 1) {
if (events_[idx] == src)
break;
}
assert(idx < nevents_);
assert(idx < events_.size());
/* First, remove me from the list held by the src NetEvent. */
// First, remove me from the list held by the src NetEvent.
assert(src->waitref_ > 0);
src->waitref_ -= 1;
struct NetEvent::wcell_*tmp = src->wlist_;
@ -435,6 +423,7 @@ void NetEvWait::replace_event(NetEvent*src, NetEvent*repl)
delete tmp;
}
// Replace the src pointer with the repl pointer.
events_[idx] = repl;
// Remember to tell the replacement NetEvent that there is
@ -448,23 +437,6 @@ void NetEvWait::replace_event(NetEvent*src, NetEvent*repl)
}
unsigned NetEvWait::nevents() const
{
return nevents_;
}
const NetEvent* NetEvWait::event(unsigned idx) const
{
assert(idx < nevents_);
return events_[idx];
}
NetEvent* NetEvWait::event(unsigned idx)
{
assert(idx < nevents_);
return events_[idx];
}
NetProc* NetEvWait::statement()
{
return statement_;

View File

@ -321,6 +321,20 @@ const NetScope* NetECRealParam::scope() const
}
NetELast::NetELast(NetNet*s)
: sig_(s)
{
}
NetELast::~NetELast()
{
}
ivl_variable_type_t NetELast::expr_type() const
{
return IVL_VT_BOOL;
}
NetENetenum::NetENetenum(const netenum_t*s)
: netenum_(s)
{
@ -362,8 +376,8 @@ NetENull::~NetENull()
{
}
NetEProperty::NetEProperty(NetNet*net, perm_string pnam)
: net_(net)
NetEProperty::NetEProperty(NetNet*net, perm_string pnam, NetExpr*idx)
: net_(net), index_(idx)
{
const netclass_t*use_type = dynamic_cast<const netclass_t*>(net->net_type());
assert(use_type);

View File

@ -416,8 +416,8 @@ bool NetCase::evaluate_function_vect_(const LineInfo&loc,
NetProc*default_statement = 0;
for (unsigned cnt = 0 ; cnt < nitems_ ; cnt += 1) {
Item*item = &items_[cnt];
for (unsigned cnt = 0 ; cnt < items_.size() ; cnt += 1) {
const Item*item = &items_[cnt];
if (item->guard == 0) {
default_statement = item->statement;
@ -478,8 +478,8 @@ bool NetCase::evaluate_function_real_(const LineInfo&loc,
NetProc*default_statement = 0;
for (unsigned cnt = 0 ; cnt < nitems_ ; cnt += 1) {
Item*item = &items_[cnt];
for (unsigned cnt = 0 ; cnt < items_.size() ; cnt += 1) {
const Item*item = &items_[cnt];
if (item->guard == 0) {
default_statement = item->statement;
@ -628,6 +628,16 @@ bool NetForever::evaluate_function(const LineInfo&loc,
return flag;
}
/*
* For now, resort to the block form of the statement until we learn
* to do this directly.
*/
bool NetForLoop::evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&context_map) const
{
return as_block_->evaluate_function(loc, context_map);
}
bool NetRepeat::evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&context_map) const
{

View File

@ -90,13 +90,19 @@ void Nexus::connect(Link&r)
void connect(Link&l, Link&r)
{
Nexus*tmp;
assert(&l != &r);
if (l.nexus_ != 0) {
connect(l.nexus_, r);
} else if (r.nexus_ != 0) {
connect(r.nexus_, l);
// If either the l or r link already are part of a Nexus, then
// re-use that nexus. Go through some effort so that we are
// not gratuitously creating Nexus object.
if (l.next_ && (tmp=l.find_nexus_())) {
connect(tmp, r);
} else if (r.next_ && (tmp=r.find_nexus_())) {
connect(tmp, l);
} else {
Nexus*tmp = new Nexus(l);
// No existing Nexus (both links are so far unconnected)
// so start one.
tmp = new Nexus(l);
tmp->connect(r);
}
}
@ -105,6 +111,8 @@ Link::Link()
: dir_(PASSIVE), drive0_(IVL_DR_STRONG), drive1_(IVL_DR_STRONG),
next_(0), nexus_(0)
{
node_ = 0;
pin_zero_ = true;
}
Link::~Link()
@ -222,9 +230,11 @@ bool Link::is_linked() const
bool Link::is_linked(const Link&that) const
{
if (next_ == 0)
// If this or that link is linked to nothing, then they cannot
// be linked to each other.
if (! this->is_linked())
return false;
if (that.next_ == 0)
if (! that.is_linked())
return false;
const Link*cur = next_;
@ -504,16 +514,24 @@ const char* Nexus::name() const
<< obj->name() << " pin " << pin
<< " type=" << typeid(*obj).name() << "?" << endl;
}
assert(sig);
ostringstream tmp;
tmp << scope_path(sig->scope()) << "." << sig->name();
if (sig->pin_count() > 1)
tmp << "<" << pin << ">";
ostringstream tmp;
tmp << "nex=" << this << ends;
const string tmps = tmp.str();
name_ = new char[strlen(tmps.c_str()) + 1];
strcpy(name_, tmps.c_str());
} else {
assert(sig);
ostringstream tmp;
tmp << scope_path(sig->scope()) << "." << sig->name();
if (sig->pin_count() > 1)
tmp << "<" << pin << ">";
tmp << ends;
const string tmps = tmp.str();
name_ = new char[strlen(tmps.c_str()) + 1];
strcpy(name_, tmps.c_str());
}
const string tmps = tmp.str();
name_ = new char[strlen(tmps.c_str()) + 1];
strcpy(name_, tmps.c_str());
return name_;
}

View File

@ -106,6 +106,11 @@ NexusSet* NetEEvent::nex_input(bool)
return new NexusSet;
}
NexusSet* NetELast::nex_input(bool)
{
return new NexusSet;
}
NexusSet* NetENetenum::nex_input(bool)
{
return new NexusSet;
@ -340,7 +345,7 @@ NexusSet* NetCase::nex_input(bool rem_out)
if (result == 0)
return 0;
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
for (size_t idx = 0 ; idx < items_.size() ; idx += 1) {
/* Skip cases that have empty statements. */
if (items_[idx].statement == 0)
@ -406,6 +411,25 @@ NexusSet* NetForce::nex_input(bool)
return new NexusSet;
}
NexusSet* NetForLoop::nex_input(bool rem_out)
{
NexusSet*result = init_expr_->nex_input(rem_out);
NexusSet*tmp = condition_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
tmp = statement_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
tmp = step_statement_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
return result;
}
NexusSet* NetForever::nex_input(bool rem_out)
{
NexusSet*result = statement_->nex_input(rem_out);

View File

@ -60,19 +60,18 @@ void NetAssign_::nex_output(NexusSet&out)
}
Nexus*nex = sig_->pin(use_word).nexus();
if (base_) {
long tmp = 0;
bool flag = eval_as_long(tmp, base_);
if (!flag) {
// Unable to evaluate the bit/part select of
// the l-value, so this is a mux. Pretty
// sure I don't know how to handle this yet
// in synthesis, so punt for now.
use_base = 0;
use_wid = nex->vector_width();
} else {
use_base = tmp;
}
// Unable to evaluate the bit/part select of
// the l-value, so this is a mux. Pretty
// sure I don't know how to handle this yet
// in synthesis, so punt for now.
// Even with constant bit/part select, we want to
// return the entire signal as an output. The
// context will need to sort out which bits are
// actually assigned.
use_base = 0;
use_wid = nex->vector_width();
}
out.add(nex, use_base, use_wid);
}
@ -102,7 +101,7 @@ void NetBlock::nex_output(NexusSet&out)
void NetCase::nex_output(NexusSet&out)
{
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
for (size_t idx = 0 ; idx < items_.size() ; idx += 1) {
// Empty statements clearly have no output.
if (items_[idx].statement == 0)
@ -134,6 +133,11 @@ void NetEvWait::nex_output(NexusSet&out)
statement_->nex_output(out);
}
void NetForLoop::nex_output(NexusSet&out)
{
if (statement_) statement_->nex_output(out);
}
void NetPDelay::nex_output(NexusSet&out)
{
if (statement_) statement_->nex_output(out);

View File

@ -71,23 +71,18 @@ const NetProc* NetBlock::proc_next(const NetProc*cur) const
}
NetCase::NetCase(NetCase::TYPE c, NetExpr*ex, unsigned cnt)
: type_(c), expr_(ex), nitems_(cnt)
: type_(c), expr_(ex), items_(cnt)
{
assert(expr_);
items_ = new Item[nitems_];
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
items_[idx].statement = 0;
}
}
NetCase::~NetCase()
{
delete expr_;
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
for (size_t idx = 0 ; idx < items_.size() ; idx += 1) {
delete items_[idx].guard;
if (items_[idx].statement) delete items_[idx].statement;
}
delete[]items_;
}
NetCase::TYPE NetCase::type() const
@ -97,7 +92,7 @@ NetCase::TYPE NetCase::type() const
void NetCase::set_case(unsigned idx, NetExpr*e, NetProc*p)
{
assert(idx < nitems_);
assert(idx < items_.size());
items_[idx].guard = e;
items_[idx].statement = p;
}
@ -126,6 +121,43 @@ NetForever::~NetForever()
delete statement_;
}
NetForLoop::NetForLoop(NetNet*ind, NetExpr*iexpr, NetExpr*cond, NetProc*sub, NetProc*step)
: index_(ind), init_expr_(iexpr), condition_(cond), statement_(sub), step_statement_(step)
{
}
void NetForLoop::wrap_up()
{
NetBlock*top = new NetBlock(NetBlock::SEQU, 0);
top->set_line(*this);
NetAssign_*lv = new NetAssign_(index_);
NetAssign*set_stmt = new NetAssign(lv, init_expr_);
set_stmt->set_line(*init_expr_);
top->append(set_stmt);
NetBlock*internal_block = new NetBlock(NetBlock::SEQU, 0);
internal_block->set_line(*this);
if (statement_) internal_block->append(statement_);
internal_block->append(step_statement_);
NetWhile*wloop = new NetWhile(condition_, internal_block);
wloop->set_line(*this);
top->append(wloop);
as_block_ = top;
}
NetForLoop::~NetForLoop()
{
delete init_expr_;
delete condition_;
delete statement_;
delete step_statement_;
}
NetPDelay::NetPDelay(uint64_t d, NetProc*st)
: delay_(d), expr_(0), statement_(st)
{

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2014 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
@ -96,6 +96,11 @@ const NetExpr* Definitions::enumeration_expr(perm_string key)
}
}
void Definitions::add_class(netclass_t*net_class)
{
classes_[net_class->get_name()] = net_class;
}
/*
* The NetScope class keeps a scope tree organized. Each node of the
* scope tree points to its parent, its right sibling and its leftmost
@ -130,7 +135,6 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest, bo
time_unit_ = 0;
time_prec_ = 0;
time_from_timescale_ = false;
assert(t==MODULE || t==PACKAGE || t==CLASS);
}
switch (t) {
@ -189,6 +193,22 @@ void NetScope::set_line(perm_string file, perm_string def_file,
def_lineno_ = def_lineno;
}
/*
* Look for the enumeration in the current scope and any parent scopes.
*/
const netenum_t*NetScope::find_enumeration_for_name(perm_string name)
{
NetScope *cur_scope = this;
while (cur_scope) {
NetEConstEnum*tmp = cur_scope->enum_names_[name];
if (tmp) break;
cur_scope = cur_scope->parent();
}
assert(cur_scope);
return cur_scope->enum_names_[name]->enumeration();
}
void NetScope::set_parameter(perm_string key, bool is_annotatable,
PExpr*val, ivl_variable_type_t type__,
PExpr*msb, PExpr*lsb, bool signed_flag,
@ -616,14 +636,9 @@ NetNet* NetScope::find_signal(perm_string key)
return 0;
}
void NetScope::add_class(netclass_t*net_class)
{
classes_[net_class->get_name()] = net_class;
}
netclass_t*NetScope::find_class(perm_string name)
{
// Special class: The scope itself is the class that we are
// Special case: The scope itself is the class that we are
// looking for. This may happen for example when elaborating
// methods within the class.
if (type_==CLASS && name_==hname_t(name))
@ -638,6 +653,13 @@ netclass_t*NetScope::find_class(perm_string name)
if (type_==MODULE)
return 0;
if (up_==0 && type_==CLASS) {
assert(class_def_);
NetScope*def_parent = class_def_->definition_scope();
return def_parent->find_class(name);
}
// If there is no further to look, ...
if (up_ == 0)
return 0;
@ -668,6 +690,47 @@ const NetScope* NetScope::child(const hname_t&name) const
return cur->second;
}
/* Helper function to see if the given scope is defined in a class and if
* so return the class scope. */
const NetScope* NetScope::get_class_scope() const
{
const NetScope*scope = this;
while (scope) {
switch(scope->type()) {
case NetScope::CLASS:
return scope;
case NetScope::TASK:
case NetScope::FUNC:
case NetScope::BEGIN_END:
case NetScope::FORK_JOIN:
break;
case NetScope::MODULE:
case NetScope::GENBLOCK:
case NetScope::PACKAGE:
return 0;
default:
assert(0);
}
scope = scope->parent();
}
return scope;
}
const NetScope* NetScope::child_byname(perm_string name) const
{
hname_t hname (name);
map<hname_t,NetScope*>::const_iterator cur = children_.lower_bound(hname);
if (cur == children_.end())
return 0;
if (cur->first.peek_name() == name)
return cur->second;
return 0;
}
perm_string NetScope::local_symbol()
{
ostringstream res;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -24,7 +24,7 @@
using namespace std;
netclass_t::netclass_t(perm_string name, netclass_t*sup)
: name_(name), super_(sup), class_scope_(0)
: name_(name), super_(sup), class_scope_(0), definition_scope_(0)
{
}
@ -50,10 +50,16 @@ bool netclass_t::set_property(perm_string pname, property_qualifier_t qual, ivl_
return true;
}
void netclass_t::set_class_scope(NetScope*class_scope)
void netclass_t::set_class_scope(NetScope*class_scope__)
{
assert(class_scope_ == 0);
class_scope_ = class_scope;
class_scope_ = class_scope__;
}
void netclass_t::set_definition_scope(NetScope*use_definition_scope)
{
assert(definition_scope_ == 0);
definition_scope_ = use_definition_scope;
}
ivl_variable_type_t netclass_t::base_type() const

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