Compare commits

..
Author SHA1 Message Date
Stephen Williams afa2478801 Merge branch 'master' of ssh://[email protected]/home/u/icarus/steve/git/verilog 2008-06-09 16:58:21 -07:00
Stephen Williams 79feb44f10 Turn of concat output scheduling.
We really want lazy processing of concatenation because it has multiple
inputs and lazy processing should (in theory) prevent redundant and
useless propagations through the net.

But enabling it seems to cause many tests in the regression test suite
to fail to compare their results. There are races in many tests that
are interacting badly with this feature. So for now, ifdef it out.
2008-06-09 16:57:51 -07:00
Stephen Williams c03d76a0d7 Do not do lazy processing of part selects.
It doesn't really make any sense to do lazy processing of part selects,
but it is possible to use the part select position to more toroughly
check for changes in output and suppress non-changes. In particular,
we only need to check that the output part actually changes, and by the
way we only need to save those bits for the next go-round.

We do want to make sure that the very first input causes an output,
though, so that time-0 values get propagated.
2008-06-09 16:46:06 -07:00
Stephen Williams d0f303463d ASSIGN transfer data to scheduler efficiently/permalloc vvp_net_t objects.
The vvp_net_t objects are never deleted, so overload the new operator
to do a more space efficient permanent allocation.

The %assign/v instruction copied the vvp_vector4_t object needlessly
on its way to the scheduler. Eliminate that duplication.
2008-06-06 19:50:44 -07:00
Stephen Williams 35fe8fae00 Have vvp_vector8_t avoid allocating tiny scalar arrays. 2008-06-06 16:36:43 -07:00
Stephen Williams 2e95a740da Rework scheduling of concat, part, buf/not and resolv for efficiency.
The concat and resolv functors are best evaluated lazily, because each
evaluation is costly and there is a high probability that an evaluation
will be invalidated when new input comes in.

Also optimization the recv_vec4_pv method of the resolver, which is
commonly used, and adjust the order of handling of vvp_fun_part to
work more efficiently.
2008-06-06 15:31:22 -07:00
Stephen Williams 2f4e5bf5b6 Obvious optimizations of vvp_vector8_t handling.
The vvp_vector8_t constructor and destructor involve memory allocation
so it is best to pass these objects by reference as much as possible.

Also rework the resolver functor to only perform resolution after inputs
are in so that it doesn't get needlessly repeated. This eliminates many
resolve function calls, as well as activations throughout the net.

Also have the islands take more care not to perform resolution if the
inputs aren't really different.
2008-06-06 11:12:07 -07:00
209 changed files with 5304 additions and 13593 deletions
-41
View File
@@ -1,41 +0,0 @@
/*
* Copyright (c) 2008 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "config.h"
# include "AStatement.h"
AStatement::~AStatement()
{
}
AContrib::AContrib(PExpr*lv, PExpr*rv)
: lval_(lv), rval_(rv)
{
}
AContrib::~AContrib()
{
delete lval_;
delete rval_;
}
AProcess::~AProcess()
{
}
-89
View File
@@ -1,89 +0,0 @@
#ifndef __AStatement_H
#define __AStatement_H
/*
* Copyright (c) 2008 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include <map>
# include "StringHeap.h"
# include "LineInfo.h"
# include "PExpr.h"
class PExpr;
class AStatement : public LineInfo {
public:
AStatement() { }
virtual ~AStatement() =0;
virtual void dump(ostream&out, unsigned ind) const;
private: // not implemented
AStatement(const AStatement&);
AStatement& operator= (const AStatement&);
};
/*
* A contribution statement is like an assignment: there is an l-value
* expression and an r-value expression. The l-value is a branch probe
* expression.
*/
class AContrib : public AStatement {
public:
AContrib(PExpr*lval, PExpr*rval);
~AContrib();
virtual void dump(ostream&out, unsigned ind) const;
private:
PExpr*lval_;
PExpr*rval_;
};
/*
* An analog process is not a statement, but contains an analog
* statement. The process is where we attach process characteristics
* such as initial vs. always, attributes....
*/
class AProcess : public LineInfo {
public:
enum Type { PR_INITIAL, PR_ALWAYS };
AProcess(Type t, AStatement*st)
: type_(t), statement_(st) { }
~AProcess();
map<perm_string,PExpr*> attributes;
// Dump the analog process
void dump(ostream&out, unsigned ind) const;
private:
Type type_;
AStatement*statement_;
private: // not implemented
AProcess(const AProcess&);
AProcess& operator= (const AProcess&);
};
#endif
+31 -15
View File
@@ -1,7 +1,7 @@
#ifndef __HName_H
#define __HName_H
/*
* Copyright (c) 2001-2008 Stephen Williams ([email protected])
* Copyright (c) 2001-2007 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -18,9 +18,11 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: HName.h,v 1.7 2007/06/02 03:42:12 steve Exp $"
#endif
# include <iostream>
# include <list>
# include "StringHeap.h"
#ifdef __GNUC__
#if __GNUC__ > 2
@@ -55,7 +57,7 @@ class hname_t {
private:
perm_string name_;
// If the number is anything other than INT_MIN, then this is
// If the number is anything other then INT_MIN, then this is
// the numeric part of the name. Otherwise, it is not part of
// the name at all.
int number_;
@@ -68,16 +70,30 @@ 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 ostream& operator<< (ostream&out, const list<hname_t>&ll)
{
list<hname_t>::const_iterator cur = ll.begin();
out << *cur;
cur ++;
while (cur != ll.end()) {
out << "." << *cur;
cur ++;
}
return out;
}
/*
* $Log: HName.h,v $
* Revision 1.7 2007/06/02 03:42:12 steve
* Properly evaluate scope path expressions.
*
* Revision 1.6 2007/05/16 19:12:33 steve
* Fix hname_t use of space for 1 perm_string.
*
* Revision 1.5 2007/04/26 03:06:21 steve
* Rework hname_t to use perm_strings.
*
* Revision 1.4 2002/11/02 03:27:51 steve
* Allow named events to be referenced by
* hierarchical names.
*
* Revision 1.3 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.2 2002/06/14 03:25:51 steve
* Compiler portability.
*
* Revision 1.1 2001/12/03 04:47:14 steve
* Parser and pform use hierarchical names as hname_t
* objects instead of encoded strings.
*
*/
#endif
+14 -7
View File
@@ -104,16 +104,15 @@ elab_lval.o elab_net.o elab_pexpr.o elab_scope.o \
elab_sig.o emit.o eval.o eval_attrib.o \
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
load_module.o netlist.o netmisc.o net_assign.o \
net_design.o net_event.o net_expr.o net_func.o \
net_design.o net_event.o net_expr.o net_force.o net_func.o \
net_link.o net_modulo.o net_nex_input.o net_nex_output.o \
net_proc.o net_scope.o net_tran.o net_udp.o pad_to_width.o \
parse.o parse_misc.o pform.o pform_analog.o pform_disciplines.o \
pform_dump.o pform_types.o \
parse.o parse_misc.o pform.o pform_disciplines.o pform_dump.o pform_types.o \
set_width.o symbol_search.o sync.o sys_funcs.o \
verinum.o verireal.o target.o targets.o \
Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \
PExpr.o PGate.o PGenerate.o PScope.o PSpec.o \
PTask.o PUdp.o PFunction.o PWire.o Statement.o AStatement.o StringHeap.o \
PTask.o PUdp.o PFunction.o PWire.o Statement.o StringHeap.o \
$(FF) $(TT)
Makefile: Makefile.in config.h.in config.status
@@ -230,6 +229,8 @@ else
WIN32_INSTALL = $(bindir)/iverilog-vpi
endif
XNF_INSTALL = $(libdir)/ivl/xnf.conf $(libdir)/ivl/xnf-s.conf
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/include/constants.vams $(libdir)/ivl/include/disciplines.vams $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for dir in vpi ivlpp driver; \
@@ -242,10 +243,16 @@ $(libdir)/ivl/ivl@EXEEXT@: ./ivl@EXEEXT@
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(DESTDIR)$(libdir)/ivl/ivl@EXEEXT@
$(libdir)/ivl/include/constants.vams: $(srcdir)/constants.vams
$(INSTALL_DATA) $(srcdir)/constants.vams $(DESTDIR)$(libdir)/ivl/include/constants.vams
$(INSTALL_DATA) $(srcdir)/constants.vams $@
$(libdir)/ivl/include/disciplines.vams: $(srcdir)/disciplines.vams
$(INSTALL_DATA) $(srcdir)/disciplines.vams $(DESTDIR)$(libdir)/ivl/include/disciplines.vams
$(INSTALL_DATA) $(srcdir)/disciplines.vams $@
$(libdir)/ivl/xnf-s.conf: $(srcdir)/xnf-s.conf
$(INSTALL_DATA) $(srcdir)/xnf-s.conf $(DESTDIR)$(libdir)/ivl/xnf-s.conf
$(libdir)/ivl/xnf.conf: $(srcdir)/xnf.conf
$(INSTALL_DATA) $(srcdir)/xnf.conf $(DESTDIR)$(libdir)/ivl/xnf.conf
$(includedir)/ivl_target.h: $(srcdir)/ivl_target.h
$(INSTALL_DATA) $(srcdir)/ivl_target.h $(DESTDIR)$(includedir)/ivl_target.h
@@ -296,7 +303,7 @@ uninstall:
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for dir in vpi ivlpp driver; \
do (cd $$dir ; $(MAKE) $@); done
for f in ivl@EXEEXT@ include/constants.vams include/disciplines.vams; \
for f in xnf.conf xnf-s.conf ivl@EXEEXT@ include/constants.vams include/disciplines.vams; \
do rm -f $(DESTDIR)$(libdir)/ivl/$$f; done
-rmdir $(DESTDIR)$(libdir)/ivl/include
-rmdir $(DESTDIR)$(libdir)/ivl
+11 -1
View File
@@ -26,7 +26,7 @@
/* n is a permallocated string. */
Module::Module(perm_string n)
: PScope(n)
: PScope(n, 0)
{
library_flag = false;
default_nettype = NetNet::NONE;
@@ -41,6 +41,16 @@ void Module::add_gate(PGate*gate)
gates_.push_back(gate);
}
void Module::add_task(perm_string name, PTask*task)
{
tasks_[name] = task;
}
void Module::add_function(perm_string name, PFunction *func)
{
funcs_[name] = func;
}
unsigned Module::port_count() const
{
return ports.count();
+7 -9
View File
@@ -22,7 +22,6 @@
# include <list>
# include <map>
# include <utility>
# include "svector.h"
# include "StringHeap.h"
# include "HName.h"
@@ -103,7 +102,7 @@ class Module : public PScope, public LineInfo {
bool signed_flag;
// Value expression
PExpr*expr;
// If there are range constraints, list them here
// If there are range constrants, list them here
range_t*range;
};
map<perm_string,param_expr_t>parameters;
@@ -119,8 +118,7 @@ class Module : public PScope, public LineInfo {
new parameters within the module, but may be used to set
values within this module (when instantiated) or in other
instantiated modules. */
typedef pair<pform_name_t,PExpr*> named_expr_t;
list<named_expr_t>defparms;
map<pform_name_t,PExpr*>defparms;
/* Parameters may be overridden at instantiation time;
the overrides do not contain explicit parameter names,
@@ -140,10 +138,6 @@ class Module : public PScope, public LineInfo {
set by the `timescale directive. */
int time_unit, time_precision;
/* Task definitions within this module */
map<perm_string,PTask*> tasks;
map<perm_string,PFunction*> funcs;
/* The module has a list of genvars that may be used in
various generate schemes. */
map<perm_string,LineInfo*> genvars;
@@ -158,6 +152,8 @@ class Module : public PScope, public LineInfo {
perm_string mod_name() const { return pscope_name(); }
void add_gate(PGate*gate);
void add_task(perm_string name, PTask*def);
void add_function(perm_string name, PFunction*def);
unsigned port_count() const;
const svector<PEIdent*>& get_port(unsigned idx) const;
@@ -171,12 +167,14 @@ class Module : public PScope, public LineInfo {
bool elaborate(Design*, NetScope*scope) const;
typedef map<perm_string,NetExpr*> replace_t;
bool elaborate_scope(Design*, NetScope*scope, const replace_t&rep);
bool elaborate_scope(Design*, NetScope*scope, const replace_t&rep) const;
bool elaborate_sig(Design*, NetScope*scope) const;
private:
list<PGate*> gates_;
map<perm_string,PTask*> tasks_;
map<perm_string,PFunction*> funcs_;
static void elaborate_parm_item_(perm_string name, const param_expr_t&cur,
Design*des, NetScope*scope);
+4 -93
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2008 Stephen Williams <[email protected]>
* Copyright (c) 1998-2007 Stephen Williams <[email protected]>
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -21,7 +21,6 @@
# include <iostream>
# include "compiler.h"
# include "PExpr.h"
# include "Module.h"
# include <typeinfo>
@@ -91,7 +90,7 @@ PEBShift::~PEBShift()
{
}
PECallFunction::PECallFunction(const pform_name_t&n, const vector<PExpr *> &parms)
PECallFunction::PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms)
: path_(n), parms_(parms)
{
}
@@ -104,7 +103,7 @@ static pform_name_t pn_from_ps(perm_string n)
return tmp;
}
PECallFunction::PECallFunction(perm_string n, const vector<PExpr*>&parms)
PECallFunction::PECallFunction(perm_string n, const svector<PExpr*>&parms)
: path_(pn_from_ps(n)), parms_(parms)
{
}
@@ -114,99 +113,10 @@ PECallFunction::PECallFunction(perm_string n)
{
}
// NOTE: Anachronism. Try to work all use of svector out.
PECallFunction::PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms)
: path_(n), parms_(vector_from_svector(parms))
{
}
PECallFunction::PECallFunction(perm_string n, const svector<PExpr*>&parms)
: path_(pn_from_ps(n)), parms_(vector_from_svector(parms))
{
}
PECallFunction::~PECallFunction()
{
}
bool PECallFunction::is_constant(Module*mod) const
{
/* Only $clog2 and the builtin mathematical functions can
* be a constant system function. */
perm_string name = peek_tail_name(path_);
if (name[0] == '$' && (generation_flag >= GN_VER2005 ||
gn_icarus_misc_flag || gn_verilog_ams_flag)) {
if (name == "$clog2" ||
name == "$ln" ||
name == "$log10" ||
name == "$exp" ||
name == "$sqrt" ||
name == "$floor" ||
name == "$ceil" ||
name == "$sin" ||
name == "$cos" ||
name == "$tan" ||
name == "$asin" ||
name == "$acos" ||
name == "$atan" ||
name == "$sinh" ||
name == "$cosh" ||
name == "$tanh" ||
name == "$asinh" ||
name == "$acosh" ||
name == "$atanh") {
if (parms_.size() != 1 || parms_[0] == 0) {
cerr << get_fileline() << ": error: " << name
<< " takes a single argument." << endl;
return false;
}
/* If the argument is constant the function is constant. */
return parms_[0]->is_constant(mod);
}
if (name == "$pow" ||
name == "$atan2" ||
name == "$hypot") {
if (parms_.size() != 2 || parms_[0] == 0 || parms_[1] == 0) {
cerr << get_fileline() << ": error: " << name
<< " takes two arguments." << endl;
return false;
/* If the arguments are constant the function is constant. */
return parms_[0]->is_constant(mod) &&
parms_[1]->is_constant(mod);
}
}
/* These are only available with verilog-ams or icarus-misc. */
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
(name == "$log" || name == "$abs")) {
if (parms_.size() != 1 || parms_[0] == 0) {
cerr << get_fileline() << ": error: " << name
<< " takes a single argument." << endl;
return false;
}
/* If the argument is constant the function is constant. */
return parms_[0]->is_constant(mod);
}
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
(name == "$min" || name == "$max")) {
if (parms_.size() != 2 || parms_[0] == 0 || parms_[1] == 0) {
cerr << get_fileline() << ": error: " << name
<< " takes two arguments." << endl;
return false;
/* If the arguments are constant the function is constant. */
return parms_[0]->is_constant(mod) &&
parms_[1]->is_constant(mod);
}
}
return false; /* The other system functions are not constant. */
}
/* Checking for constant user functions goes here. */
return false;
}
PEConcat::PEConcat(const svector<PExpr*>&p, PExpr*r)
: parms_(p), repeat_(r)
{
@@ -389,3 +299,4 @@ bool PEUnary::is_constant(Module*m) const
{
return expr_->is_constant(m);
}
+3 -13
View File
@@ -315,7 +315,6 @@ class PEIdent : public PExpr {
private:
NetAssign_*elaborate_lval_net_word_(Design*, NetScope*, NetNet*) const;
bool elaborate_lval_net_bit_(Design*, NetScope*, NetAssign_*) const;
bool elaborate_lval_net_part_(Design*, NetScope*, NetAssign_*) const;
bool elaborate_lval_net_idx_(Design*, NetScope*, NetAssign_*,
index_component_t::ctype_t) const;
@@ -697,19 +696,12 @@ class PETernary : public PExpr {
*/
class PECallFunction : public PExpr {
public:
explicit PECallFunction(const pform_name_t&n, const vector<PExpr *> &parms);
// Call of system function (name is not hierarchical)
explicit PECallFunction(perm_string n, const vector<PExpr *> &parms);
explicit PECallFunction(perm_string n);
// svector versions. Should be removed!
explicit PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms);
// Call of system function (name is not hierarchical)
explicit PECallFunction(perm_string n, const svector<PExpr *> &parms);
explicit PECallFunction(perm_string n);
~PECallFunction();
virtual bool is_constant(Module*) const;
virtual void dump(ostream &) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
@@ -721,7 +713,6 @@ class PECallFunction : public PExpr {
Link::strength_t drive1) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
int expr_wid, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
@@ -729,12 +720,11 @@ class PECallFunction : public PExpr {
private:
pform_name_t path_;
vector<PExpr *> parms_;
svector<PExpr *> parms_;
bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope, int expr_wid) const;
NetExpr* elaborate_access_func_(Design*des, NetScope*scope, int expr_wid) const;
NetNet* elaborate_net_sfunc_(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
+1 -2
View File
@@ -21,10 +21,9 @@
#include "PTask.h"
PFunction::PFunction(perm_string name, PScope*parent, bool is_auto)
PFunction::PFunction(perm_string name, PScope*parent)
: PScope(name, parent), ports_(0), statement_(0)
{
is_auto_ = is_auto;
return_type_.type = PTF_NONE;
}
+4 -3
View File
@@ -1,7 +1,7 @@
#ifndef __PGate_H
#define __PGate_H
/*
* Copyright (c) 1998-2008 Stephen Williams ([email protected])
* Copyright (c) 1998-2004 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -18,6 +18,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PGate.h,v 1.32 2006/04/10 00:37:42 steve Exp $"
#endif
# include "svector.h"
# include "StringHeap.h"
@@ -229,11 +232,9 @@ class PGModule : public PGate {
PExpr*msb_;
PExpr*lsb_;
friend class delayed_elaborate_scope_mod_instances;
void elaborate_mod_(Design*, Module*mod, NetScope*scope) const;
void elaborate_udp_(Design*, PUdp *udp, NetScope*scope) const;
void elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const;
void elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*sc) const;
bool elaborate_sig_mod_(Design*des, NetScope*scope, Module*mod) const;
bool elaborate_sig_udp_(Design*des, NetScope*scope, PUdp*udp) const;
+14 -1
View File
@@ -27,14 +27,27 @@ PGenerate::PGenerate(unsigned id)
: id_number(id)
{
parent = 0;
lexical_scope = 0;
}
PGenerate::~PGenerate()
{
}
PWire* PGenerate::get_wire(perm_string name) const
{
map<perm_string,PWire*>::const_iterator obj = wires.find(name);
if (obj == wires.end())
return 0;
else
return (*obj).second;
}
void PGenerate::add_gate(PGate*gate)
{
gates.push_back(gate);
}
void PGenerate::add_behavior(PProcess*proc)
{
behaviors.push_back(proc);
}
+11 -16
View File
@@ -1,7 +1,7 @@
#ifndef __PGenerate_H
#define __PGenerate_H
/*
* Copyright (c) 2006-2008 Stephen Williams ([email protected])
* Copyright (c) 2006 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -18,11 +18,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PGenerate.h,v 1.4 2007/06/02 03:42:12 steve Exp $"
#endif
# include "LineInfo.h"
# include "StringHeap.h"
# include "HName.h"
# include "PScope.h"
# include <list>
# include <map>
# include "pform_types.h"
@@ -30,9 +32,7 @@
class Design;
class NetScope;
class PExpr;
class PFunction;
class PProcess;
class PTask;
class PGate;
class PWire;
@@ -49,10 +49,10 @@ class PWire;
* The parent points to the GS_CASE that contains this item.
* the loop_test is compared with the parent->loop_test expression.
*/
class PGenerate : public LineInfo, public LexicalScope {
class PGenerate : public LineInfo {
public:
explicit PGenerate(unsigned id_number);
PGenerate(unsigned id_number);
~PGenerate();
// Generate schemes have an ID number, for when the scope is
@@ -60,10 +60,6 @@ class PGenerate : public LineInfo, public LexicalScope {
const unsigned id_number;
perm_string scope_name;
// This is used during parsing to stack lexical scopes within
// this generate scheme.
PScope*lexical_scope;
enum scheme_t {GS_NONE, GS_LOOP, GS_CONDIT, GS_ELSE,
GS_CASE, GS_CASE_ITEM};
scheme_t scheme_type;
@@ -75,17 +71,16 @@ class PGenerate : public LineInfo, public LexicalScope {
PExpr*loop_test;
PExpr*loop_step;
map<perm_string,PWire*>wires;
PWire* get_wire(perm_string name) const;
list<PGate*> gates;
void add_gate(PGate*);
list<PProcess*> behaviors;
void add_behavior(PProcess*behave);
// Tasks instantiated within this scheme.
map<perm_string,PTask*> tasks;
map<perm_string,PFunction*>funcs;
// Generate schemes can contain further generate schemes.
list<PGenerate*> generate_schemes;
list<PGenerate*> generates;
PGenerate*parent;
// This method is called by the elaboration of a module to
+3 -8
View File
@@ -19,13 +19,8 @@
# include "PScope.h"
PScope::PScope(perm_string n, PScope*parent)
: name_(n), parent_(parent)
{
}
PScope::PScope(perm_string n)
: name_(n), parent_(0)
PScope::PScope(perm_string n, PScope*p)
: name_(n), parent_(p)
{
}
@@ -33,7 +28,7 @@ PScope::~PScope()
{
}
PWire* LexicalScope::wires_find(perm_string name)
PWire* PScope::wires_find(perm_string name)
{
map<perm_string,PWire*>::const_iterator cur = wires.find(name);
if (cur == wires.end())
+8 -22
View File
@@ -24,7 +24,6 @@
# include <map>
class PEvent;
class AProcess;
class PProcess;
class PWire;
@@ -39,26 +38,7 @@ class NetScope;
* NOTE: This is note the same concept as the "scope" of an elaborated
* hierarchy. That is represented by NetScope objects after elaboration.
*/
class LexicalScope {
public:
explicit LexicalScope() { }
// A virtual destructor is so that dynamic_cast can work.
virtual ~LexicalScope() { }
// Nets an variables (wires) in the scope
map<perm_string,PWire*>wires;
PWire* wires_find(perm_string name);
// Behaviors (processes) in this scope
list<PProcess*> behaviors;
list<AProcess*> analog_behaviors;
private:
};
class PScope : public LexicalScope {
class PScope {
public:
// When created, a scope has a name and a parent. The name is
@@ -70,15 +50,21 @@ class PScope : public LexicalScope {
// modules. Scopes for tasks and functions point to their
// containing module.
PScope(perm_string name, PScope*parent);
PScope(perm_string name);
virtual ~PScope();
perm_string pscope_name() const { return name_; }
PScope* pscope_parent() { return parent_; }
// Nets an variables (wires) in the scope
map<perm_string,PWire*>wires;
PWire* wires_find(perm_string name);
// Named events in the scope.
map<perm_string,PEvent*>events;
// Behaviors (processes) in this scope
list<PProcess*> behaviors;
protected:
void dump_wires_(ostream&out, unsigned indent) const;
+29 -2
View File
@@ -21,10 +21,9 @@
# include "PTask.h"
PTask::PTask(perm_string name, PScope*parent, bool is_auto)
PTask::PTask(perm_string name, PScope*parent)
: PScope(name, parent), ports_(0), statement_(0)
{
is_auto_ = is_auto;
}
PTask::~PTask()
@@ -42,3 +41,31 @@ void PTask::set_statement(Statement*s)
assert(statement_ == 0);
statement_ = s;
}
/*
* $Log: PTask.cc,v $
* Revision 1.7 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.6 2001/07/25 03:10:48 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.5 2001/04/19 03:04:47 steve
* Spurious assert of empty statemnt.
*
* Revision 1.4 2001/01/13 22:20:08 steve
* Parse parameters within nested scopes.
*
* Revision 1.3 2000/02/23 02:56:53 steve
* Macintosh compilers do not support ident.
*
* Revision 1.2 1999/07/24 02:11:19 steve
* Elaborate task input ports.
*
* Revision 1.1 1999/07/03 02:12:51 steve
* Elaborate user defined tasks.
*
*/
+2 -8
View File
@@ -51,7 +51,7 @@ struct PTaskFuncArg {
class PTask : public PScope, public LineInfo {
public:
explicit PTask(perm_string name, PScope*parent, bool is_auto);
explicit PTask(perm_string name, PScope*parent);
~PTask();
void set_ports(svector<PWire *>*p);
@@ -69,14 +69,11 @@ class PTask : public PScope, public LineInfo {
// Elaborate the statement to finish off the task definition.
void elaborate(Design*des, NetScope*scope) const;
bool is_auto() const { return is_auto_; };
void dump(ostream&, unsigned) const;
private:
svector<PWire*>*ports_;
Statement*statement_;
bool is_auto_;
private: // Not implemented
PTask(const PTask&);
@@ -93,7 +90,7 @@ class PTask : public PScope, public LineInfo {
class PFunction : public PScope, public LineInfo {
public:
explicit PFunction(perm_string name, PScope*parent, bool is_auto);
explicit PFunction(perm_string name, PScope*parent);
~PFunction();
void set_ports(svector<PWire *>*p);
@@ -108,15 +105,12 @@ class PFunction : public PScope, public LineInfo {
/* Elaborate the behavioral statement. */
void elaborate(Design *des, NetScope*) const;
bool is_auto() const { return is_auto_; };
void dump(ostream&, unsigned) const;
private:
PTaskFuncArg return_type_;
svector<PWire *> *ports_;
Statement *statement_;
bool is_auto_;
};
#endif
+4 -1
View File
@@ -12,7 +12,10 @@ home page at <http://www.icarus.com/eda/verilog>.
Icarus Verilog is not aimed at being a simulator in the traditional
sense, but a compiler that generates code employed by back-end
tools.
tools. These back-end tools currently include a simulator engine
called VVP, an XNF (Xilinx Netlist Format) generator and an EDIF FPGA
netlist generator. In the future, backends are expected for EDIF/LPM,
structural Verilog, VHDL, etc.
For instructions on how to run Icarus Verilog,
see the ``iverilog'' man page.
+46 -13
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2008 Stephen Williams ([email protected])
* Copyright (c) 1998-1999 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -16,6 +16,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: Statement.cc,v 1.30 2007/05/24 04:07:11 steve Exp $"
#endif
# include "config.h"
@@ -27,19 +30,19 @@ Statement::~Statement()
}
PAssign_::PAssign_(PExpr*lval, PExpr*ex)
: event_(0), count_(0), lval_(lval), rval_(ex)
: event_(0), lval_(lval), rval_(ex)
{
delay_ = 0;
}
PAssign_::PAssign_(PExpr*lval, PExpr*de, PExpr*ex)
: event_(0), count_(0), lval_(lval), rval_(ex)
: event_(0), lval_(lval), rval_(ex)
{
delay_ = de;
}
PAssign_::PAssign_(PExpr*lval, PExpr*cnt, PEventStatement*ev, PExpr*ex)
: event_(ev), count_(cnt), lval_(lval), rval_(ex)
PAssign_::PAssign_(PExpr*lval, PEventStatement*ev, PExpr*ex)
: event_(ev), lval_(lval), rval_(ex)
{
delay_ = 0;
}
@@ -60,8 +63,8 @@ PAssign::PAssign(PExpr*lval, PExpr*d, PExpr*ex)
{
}
PAssign::PAssign(PExpr*lval, PExpr*cnt, PEventStatement*d, PExpr*ex)
: PAssign_(lval, cnt, d, ex)
PAssign::PAssign(PExpr*lval, PEventStatement*d, PExpr*ex)
: PAssign_(lval, d, ex)
{
}
@@ -79,11 +82,6 @@ PAssignNB::PAssignNB(PExpr*lval, PExpr*d, PExpr*ex)
{
}
PAssignNB::PAssignNB(PExpr*lval, PExpr*cnt, PEventStatement*d, PExpr*ex)
: PAssign_(lval, cnt, d, ex)
{
}
PAssignNB::~PAssignNB()
{
}
@@ -94,7 +92,7 @@ PBlock::PBlock(perm_string n, PScope*parent, BL_TYPE t)
}
PBlock::PBlock(BL_TYPE t)
: PScope(perm_string()), bl_type_(t)
: PScope(perm_string(),0), bl_type_(t)
{
}
@@ -300,3 +298,38 @@ PWhile::~PWhile()
delete cond_;
delete statement_;
}
/*
* $Log: Statement.cc,v $
* Revision 1.30 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.29 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items.
*
* Revision 1.28 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
* Revision 1.27 2002/04/21 22:31:02 steve
* Redo handling of assignment internal delays.
* Leave it possible for them to be calculated
* at run time.
*
* Revision 1.26 2002/04/21 04:59:07 steve
* Add support for conbinational events by finding
* the inputs to expressions and some statements.
* Get case and assignment statements working.
*
* Revision 1.25 2001/12/03 04:47:14 steve
* Parser and pform use hierarchical names as hname_t
* objects instead of encoded strings.
*
* Revision 1.24 2001/11/22 06:20:59 steve
* Use NetScope instead of string for scope path.
*
* Revision 1.23 2001/07/25 03:10:48 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*/
+2 -11
View File
@@ -82,8 +82,6 @@ class Statement : public LineInfo {
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;
map<perm_string,PExpr*> attributes;
};
/*
@@ -95,7 +93,7 @@ class PAssign_ : public Statement {
public:
explicit PAssign_(PExpr*lval, PExpr*ex);
explicit PAssign_(PExpr*lval, PExpr*de, PExpr*ex);
explicit PAssign_(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
explicit PAssign_(PExpr*lval, PEventStatement*de, PExpr*ex);
virtual ~PAssign_() =0;
const PExpr* lval() const { return lval_; }
@@ -106,7 +104,6 @@ class PAssign_ : public Statement {
PExpr* delay_;
PEventStatement*event_;
PExpr* count_;
private:
PExpr* lval_;
@@ -118,7 +115,7 @@ class PAssign : public PAssign_ {
public:
explicit PAssign(PExpr*lval, PExpr*ex);
explicit PAssign(PExpr*lval, PExpr*de, PExpr*ex);
explicit PAssign(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
explicit PAssign(PExpr*lval, PEventStatement*de, PExpr*ex);
~PAssign();
virtual void dump(ostream&out, unsigned ind) const;
@@ -132,7 +129,6 @@ class PAssignNB : public PAssign_ {
public:
explicit PAssignNB(PExpr*lval, PExpr*ex);
explicit PAssignNB(PExpr*lval, PExpr*de, PExpr*ex);
explicit PAssignNB(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
~PAssignNB();
virtual void dump(ostream&out, unsigned ind) const;
@@ -337,9 +333,6 @@ class PEventStatement : public Statement {
void set_statement(Statement*st);
virtual void dump(ostream&out, unsigned ind) const;
// Call this with a NULL statement only. It is used to print
// the event expression for inter-assignment event controls.
virtual void dump_inline(ostream&out) const;
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;
@@ -355,8 +348,6 @@ class PEventStatement : public Statement {
Statement*statement_;
};
ostream& operator << (ostream&o, const PEventStatement&obj);
class PForce : public Statement {
public:
+1 -1
View File
@@ -9,7 +9,7 @@
echo "Autoconf in root..."
autoconf -f
for dir in vpip vpi vvp tgt-vvp tgt-fpga tgt-stub tgt-vhdl libveriuser cadpli
for dir in vpip vpi vvp tgt-vvp tgt-fpga tgt-stub libveriuser cadpli
do
echo "Autoconf in $dir..."
( cd ./$dir ; autoconf -f --include=.. )
+3 -3
View File
@@ -76,13 +76,13 @@ distclean: clean
install: all installdirs $(vpidir)/cadpli.vpl $(INSTALL32)
$(vpidir)/cadpli.vpl: ./cadpli.vpl
$(INSTALL_PROGRAM) ./cadpli.vpl $(DESTDIR)$(vpidir)/cadpli.vpl
$(INSTALL_PROGRAM) ./cadpli.vpl $(vpidir)/cadpli.vpl
installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(DESTDIR)$(vpidir)
$(srcdir)/../mkinstalldirs $(vpidir)
uninstall: $(UNINSTALL32)
rm -f $(DESTDIR)$(vpidir)/cadpli.vpl
rm -f $(vpidir)/cadpli.vpl
uninstall32:
+2 -2
View File
@@ -122,6 +122,6 @@ AX_C_UNDERSCORES_TRAILING
AX_CPP_IDENT
# XXX disable tgt-fpga for the moment
AC_CONFIG_SUBDIRS(vvp vpi tgt-stub tgt-null tgt-vvp tgt-vhdl libveriuser cadpli)
AC_CONFIG_SUBDIRS(vvp vpi tgt-stub tgt-null tgt-vvp libveriuser cadpli)
AC_OUTPUT(Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-verilog/Makefile tgt-pal/Makefile tgt-vhdl/Makefile)
AC_OUTPUT(Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
+1 -1
View File
@@ -3,7 +3,7 @@
`ifdef CONSTANTS_VAMS
`else
`define CONSTANTS_VAMS 1
// M_ is a mathematical constant
`define M_E 2.7182818284590452354
`define M_LOG2E 1.4426950408889634074
+2 -2
View File
@@ -897,7 +897,7 @@ void cprop_dc_functor::lpm_const(Design*des, NetConst*obj)
for (Link*clnk = nex->first_nlink()
; clnk ; clnk = clnk->next_nlink()) {
NetPins*cur;
NetObj*cur;
unsigned pin;
clnk->cur_link(cur, pin);
@@ -923,7 +923,7 @@ void cprop_dc_functor::lpm_const(Design*des, NetConst*obj)
for (Link*clnk = nex->first_nlink()
; clnk ; clnk = clnk->next_nlink()) {
NetPins*cur;
NetObj*cur;
unsigned pin;
clnk->cur_link(cur, pin);
+2 -47
View File
@@ -27,7 +27,6 @@
# include <iomanip>
# include "netlist.h"
# include "compiler.h"
# include "discipline.h"
# include "ivl_assert.h"
static ostream& operator<< (ostream&o, NetBlock::Type t)
@@ -188,10 +187,6 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
o << " inout";
break;
}
if (discipline_t*dis = get_discipline())
o << " discipline=" << dis->name();
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
if (scope())
o << " scope=" << scope_path(scope());
@@ -241,7 +236,7 @@ void NetNode::dump_node(ostream&o, unsigned ind) const
/* This is the generic dumping of all the signals connected to each
pin of the object. The "this" object is not printed, only the
signals connected to this. */
void NetPins::dump_node_pins(ostream&o, unsigned ind) const
void NetObj::dump_node_pins(ostream&o, unsigned ind) const
{
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
o << setw(ind) << "" << idx << " " << pin(idx).get_name()
@@ -307,22 +302,6 @@ void NetArrayDq::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetCastInt::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Cast to int. (NetCastInt): " <<
name() << " width=" << width() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetCastReal::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Cast to real (NetCastReal): " <<
name() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetCLShift::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Combinatorial shift (NetCLShift): " <<
@@ -1003,7 +982,6 @@ void NetScope::dump(ostream&o) const
o << " generate block";
break;
}
if (is_auto()) o << " (automatic)";
o << endl;
for (unsigned idx = 0 ; idx < attr_cnt() ; idx += 1)
@@ -1020,8 +998,6 @@ void NetScope::dump(ostream&o) const
; pp != parameters.end() ; pp ++) {
o << " parameter ";
o << pp->second.type << " ";
if ((*pp).second.signed_flag)
o << "signed ";
@@ -1071,7 +1047,7 @@ void NetScope::dump(ostream&o) const
/* Dump the saved defparam assignments here. */
{
list<pair<pform_name_t,NetExpr*> >::const_iterator pp;
map<pform_name_t,NetExpr*>::const_iterator pp;
for (pp = defparams.begin()
; pp != defparams.end() ; pp ++ ) {
o << " defparam " << (*pp).first << " = " <<
@@ -1079,15 +1055,6 @@ void NetScope::dump(ostream&o) const
}
}
{
list<pair<list<hname_t>,NetExpr*> >::const_iterator pp;
for (pp = defparams_later.begin()
; pp != defparams_later.end() ; pp ++ ) {
o << " defparam(later) " << pp->first << " = " <<
*(pp->second) << ";" << endl;
}
}
/* Dump the events in this scope. */
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_) {
o << " event " << cur->name() << "; nprobe="
@@ -1190,18 +1157,6 @@ void NetExpr::dump(ostream&o) const
o << "(?" << typeid(*this).name() << "?)";
}
void NetEAccess::dump(ostream&o) const
{
o << nature_->name() << "." << nature_->access() << "(";
assert(branch_);
if (branch_->pin(0).is_linked())
o << branch_->pin(0).nexus()->name();
o << ", ";
if (branch_->pin(1).is_linked())
o << branch_->pin(1).nexus()->name();
o << ")";
}
void NetEBinary::dump(ostream&o) const
{
if (op_ == 'm' || op_ == 'M') {
-2
View File
@@ -71,7 +71,5 @@ class discipline_t : public LineInfo {
extern map<perm_string,nature_t*> natures;
extern map<perm_string,discipline_t*> disciplines;
// Map access function name to the nature that it accesses.
extern map<perm_string,nature_t*> access_function_nature;
#endif
+5 -5
View File
@@ -100,17 +100,17 @@ endif
install: all installdirs $(bindir)/iverilog@EXEEXT@ $(INSTALL_DOC)
$(bindir)/iverilog@EXEEXT@: ./iverilog@EXEEXT@
$(INSTALL_PROGRAM) ./iverilog@EXEEXT@ $(DESTDIR)$(bindir)/iverilog@EXEEXT@
$(INSTALL_PROGRAM) ./iverilog@EXEEXT@ $(bindir)/iverilog@EXEEXT@
$(mandir)/man1/iverilog.1: $(srcdir)/iverilog.man
$(INSTALL_DATA) $(srcdir)/iverilog.man $(DESTDIR)$(mandir)/man1/iverilog.1
$(INSTALL_DATA) $(srcdir)/iverilog.man $(mandir)/man1/iverilog.1
$(prefix)/iverilog.pdf: iverilog.pdf
$(INSTALL_DATA) iverilog.pdf $(prefix)/iverilog.pdf
installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(DESTDIR)$(bindir) $(DESTDIR)$(INSTALL_DOCDIR)
$(srcdir)/../mkinstalldirs $(bindir) $(INSTALL_DOCDIR)
uninstall:
rm -f $(DESTDIR)$(bindir)/iverilog@EXEEXT@
rm -f $(DESTDIR)$(mandir)/man1/iverilog.1 $(DESTDIR)$(prefix)/iverilog.pdf
rm -f $(bindir)/iverilog@EXEEXT@
rm -f $(mandir)/man1/iverilog.1 $(prefix)/iverilog.pdf
+1 -1
View File
@@ -149,7 +149,7 @@ int cmdfile_stack_ptr = 0;
cflval.text = trim_trailing_white(yytext, 0);
BEGIN(0);
return TOK_STRING; }
/* Fallback match. */
. { return yytext[0]; }
+11 -7
View File
@@ -14,7 +14,7 @@ iverilog - Icarus Verilog compiler
\fIiverilog\fP is a compiler that translates Verilog source code into
executable programs for simulation, or other netlist formats for
further processing. The currently supported targets are \fIvvp\fP for
simulation, and \fIfpga\fP for synthesis. Other target
simulation, and \fIxnf\fP and \fIfpga\fP for synthesis. Other target
types are added as code generators are implemented.
.SH OPTIONS
@@ -212,18 +212,17 @@ This is the default. The vvp target generates code for the vvp
runtime. The output is a complete program that simulates the design
but must be run by the \fBvvp\fP command.
.TP 8
.B xnf
This is the Xilinx Netlist Format used by many tools for placing
devices in FPGAs or other programmable devices. This target is
obsolete, use the \fBfpga\fP target instead.
.TP 8
.B fpga
This is a synthesis target that supports a variety of fpga devices,
mostly by EDIF format output. The Icarus Verilog fpga code generator
can generate complete designs or EDIF macros that can in turn be
imported into larger designs by other tools. The \fBfpga\fP target
implies the synthesis \fB-S\fP flag.
.TP 8
.B vhdl
This target produces a VHDL translation of the Verilog netlist. The
output is a single file containing VHDL entities corresponding to
the modules in the Verilog source code. Note that only a subset of
the Verilog language is supported. See the wiki for more information.
.SH "WARNING TYPES"
These are the types of warnings that can be selected by the \fB-W\fP
@@ -413,6 +412,11 @@ To compile and run explicitly using the vvp runtime:
iverilog -ohello.vvp -tvvp hello.v
To compile hello.v to a file in XNF-format called hello.xnf
iverilog -txnf -ohello.xnf hello.v
.SH "AUTHOR"
.nf
Steve Williams ([email protected])
+21 -30
View File
@@ -106,7 +106,7 @@ const char*npath = 0;
const char*targ = "vvp";
const char*depfile = 0;
const char*generation = "2005";
const char*generation = "2x";
const char*gen_specify = "specify";
const char*gen_xtypes = "xtypes";
const char*gen_icarus = "icarus-misc";
@@ -328,24 +328,23 @@ static int t_default(char*cmd, unsigned ncmd)
remove(compiled_defines_path);
}
#ifdef __MINGW32__ /* MinGW just returns the exit status, so return it! */
free(cmd);
return rc;
#else
int rtn = 0;
if (rc != 0) {
if (rc == 127) {
fprintf(stderr, "Failed to execute: %s\n", cmd);
rtn = 1;
} else if (WIFEXITED(rc)) {
rtn = WEXITSTATUS(rc);
} else {
fprintf(stderr, "Command signaled: %s\n", cmd);
rtn = -1;
return 1;
}
if (WIFEXITED(rc))
return WEXITSTATUS(rc);
fprintf(stderr, "Command signaled: %s\n", cmd);
return -1;
}
free(cmd);
return rtn;
return 0;
#endif
}
@@ -506,7 +505,7 @@ int process_generation(const char*name)
" 2005 -- IEEE1364-2005\n"
"Other generation flags:\n"
" specify | no-specify\n"
" verilog-ams | no-verilog-ams\n"
" verilog-ams | no-verinlog-ams\n"
" std-include | no-std-include\n"
" xtypes | no-xtypes\n"
" icarus-misc | no-icarus-misc\n"
@@ -523,7 +522,7 @@ int process_generation(const char*name)
void add_sft_file(const char *module)
{
char *file;
file = (char *) malloc(strlen(base)+1+strlen(module)+4+1);
sprintf(file, "%s%c%s.sft", base, sep, module);
if (access(file, R_OK) == 0)
@@ -654,7 +653,7 @@ int main(int argc, char **argv)
case 'c':
case 'f':
add_cmd_file(optarg);
break;
break;
case 'D':
process_define(optarg);
break;
@@ -673,9 +672,9 @@ int main(int argc, char **argv)
if (rc != 0)
return -1;
break;
case 'h':
fprintf(stderr, "%s\n", HELP);
return 1;
case 'h':
fprintf(stderr, "%s\n", HELP);
return 1;
case 'I':
process_include_dir(optarg);
@@ -765,18 +764,9 @@ int main(int argc, char **argv)
how to handle them. */
fprintf(iconfig_file, "sys_func:%s%csystem.sft\n", base, sep);
/* If verilog-2005 is enabled or icarus-misc or verilog-ams,
* then include the v2005_math library. */
if (strcmp(generation, "2005") == 0 ||
strcmp(gen_icarus, "icarus-misc") == 0 ||
strcmp(gen_verilog_ams, "verilog-ams") == 0) {
fprintf(iconfig_file, "sys_func:%s%cv2005_math.sft\n", base, sep);
fprintf(iconfig_file, "module:v2005_math\n");
}
/* If verilog-ams or icarus_misc is enabled, then include the
* va_math module as well. */
if (strcmp(gen_verilog_ams,"verilog-ams") == 0 ||
strcmp(gen_icarus, "icarus-misc") == 0) {
/* If verilog-ams is enabled, then include the va_math module
as well. */
if (strcmp(gen_verilog_ams,"verilog-ams") == 0) {
fprintf(iconfig_file, "sys_func:%s%cva_math.sft\n", base, sep);
fprintf(iconfig_file, "module:va_math\n");
}
@@ -881,7 +871,6 @@ int main(int argc, char **argv)
}
fprintf(stderr, "Command signaled: %s\n", cmd);
free(cmd);
return -1;
}
@@ -900,4 +889,6 @@ int main(int argc, char **argv)
fclose(iconfig_file);
return t_default(cmd, ncmd);
return 0;
}
-10
View File
@@ -21,16 +21,6 @@
# include "netlist.h"
# include <cassert>
# include <stdlib.h>
# include "ivl_assert.h"
NetEAccess* NetEAccess::dup_expr() const
{
NetEAccess*tmp = new NetEAccess(branch_, nature_);
ivl_assert(*this, tmp);
tmp->set_line(*this);
return tmp;
}
NetEBComp* NetEBComp::dup_expr() const
{
+72 -79
View File
@@ -25,7 +25,6 @@
# include "pform.h"
# include "netlist.h"
# include "discipline.h"
# include "netmisc.h"
# include "util.h"
# include "ivl_assert.h"
@@ -450,7 +449,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, int expr_w
and makes it into a signed expression. No bits are changed,
it just changes the interpretation. */
if (strcmp(peek_tail_name(path_), "$signed") == 0) {
if ((parms_.size() != 1) || (parms_[0] == 0)) {
if ((parms_.count() != 1) || (parms_[0] == 0)) {
cerr << get_fileline() << ": error: The $signed() function "
<< "takes exactly one(1) argument." << endl;
des->errors += 1;
@@ -464,7 +463,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, int expr_w
}
/* add $unsigned to match $signed */
if (strcmp(peek_tail_name(path_), "$unsigned") == 0) {
if ((parms_.size() != 1) || (parms_[0] == 0)) {
if ((parms_.count() != 1) || (parms_[0] == 0)) {
cerr << get_fileline() << ": error: The $unsigned() function "
<< "takes exactly one(1) argument." << endl;
des->errors += 1;
@@ -487,7 +486,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, int expr_w
deleted. */
if ((strcmp(peek_tail_name(path_), "$sizeof") == 0)
|| (strcmp(peek_tail_name(path_), "$bits") == 0)) {
if ((parms_.size() != 1) || (parms_[0] == 0)) {
if ((parms_.count() != 1) || (parms_[0] == 0)) {
cerr << get_fileline() << ": error: The $bits() function "
<< "takes exactly one(1) argument." << endl;
des->errors += 1;
@@ -504,14 +503,14 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, int expr_w
/* Elaborate the sub-expression to get its
self-determined width, and save that width. Then
delete the expression because we don't really want
the expression itself. */
the expression itself. */
long sub_expr_width = 0;
if (NetExpr*tmp = expr->elaborate_expr(des, scope, -1, true)) {
sub_expr_width = tmp->expr_width();
delete tmp;
}
verinum val ( (uint64_t)sub_expr_width, 8*sizeof(unsigned));
verinum val (sub_expr_width, 8*sizeof(unsigned));
NetEConst*sub = new NetEConst(val);
sub->set_line(*this);
@@ -523,7 +522,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, int expr_w
otherwise. The subexpression is elaborated but not
evaluated. */
if (strcmp(peek_tail_name(path_), "$is_signed") == 0) {
if ((parms_.size() != 1) || (parms_[0] == 0)) {
if ((parms_.count() != 1) || (parms_[0] == 0)) {
cerr << get_fileline() << ": error: The $is_signed() function "
<< "takes exactly one(1) argument." << endl;
des->errors += 1;
@@ -559,7 +558,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, int expr_w
Functions cannot really take empty parameters, but the
case ``func()'' is the same as no parameters at all. So
catch that special case here. */
unsigned nparms = parms_.size();
unsigned nparms = parms_.count();
if ((nparms == 1) && (parms_[0] == 0))
nparms = 0;
@@ -602,55 +601,6 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, int expr_w
return fun;
}
NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope,
int expr_wid) const
{
// Hierarchical names cannot be access functions.
if (path_.size() != 1)
return 0;
perm_string access_name = peek_tail_name(path_);
nature_t*nature = access_function_nature[access_name];
// If the name doesn't match any access functions, then give up.
if (nature == 0)
return 0;
// An access function must have 1 or 2 arguments.
ivl_assert(*this, parms_.size()==2 || parms_.size()==1);
NetBranch*branch = 0;
if (parms_.size() == 1) {
PExpr*arg1 = parms_[0];
PEIdent*arg_ident = dynamic_cast<PEIdent*> (arg1);
ivl_assert(*this, arg_ident);
const pform_name_t&path = arg_ident->path();
ivl_assert(*this, path.size()==1);
perm_string name = peek_tail_name(path);
NetNet*sig = scope->find_signal(name);
ivl_assert(*this, sig);
discipline_t*dis = sig->get_discipline();
ivl_assert(*this, dis);
ivl_assert(*this, nature == dis->potential() || nature == dis->flow());
branch = new NetBranch(dis);
branch->set_line(*this);
connect(branch->pin(0), sig->pin(0));
} else {
ivl_assert(*this, 0);
}
NetEAccess*tmp = new NetEAccess(branch, nature);
tmp->set_line(*this);
return tmp;
}
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
int expr_wid, bool) const
{
@@ -659,26 +609,20 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
NetFuncDef*def = des->find_function(scope, path_);
if (def == 0) {
// Not a user defined function. Maybe it is an access
// function for a nature? If so then elaborate it that way.
NetExpr*tmp = elaborate_access_func_(des, scope, expr_wid);
if (tmp != 0)
return tmp;
cerr << get_fileline() << ": error: No function " << path_ <<
" in this context (" << scope_path(scope) << ")." << endl;
des->errors += 1;
return 0;
}
ivl_assert(*this, def);
assert(def);
NetScope*dscope = def->scope();
ivl_assert(*this, dscope);
assert(dscope);
if (! check_call_matches_definition_(des, dscope))
return 0;
unsigned parms_count = parms_.size();
unsigned parms_count = parms_.count();
if ((parms_count == 1) && (parms_[0] == 0))
parms_count = 0;
@@ -1238,12 +1182,12 @@ NetExpr* PEIdent::elaborate_expr_param_part_(Design*des, NetScope*scope,
if (!flag)
return 0;
// Notice that the par_msv is not used in this function other
// than for this test. It is used to tell the direction that
// Notice that the par_msv is not used is this function other
// then for this test. It is used to tell the direction that
// the bits are numbers, so that we can make sure the
// direction matches the part select direction. After that,
// we only need the par_lsv.
if ((msv>lsv && par_msv<par_lsv) || (msv<lsv && par_msv>=par_lsv)) {
if (msv>lsv && par_msv<par_lsv || msv<lsv && par_msv>=par_lsv) {
cerr << get_fileline() << ": error: Part select "
<< "[" << msv << ":" << lsv << "] is out of order." << endl;
des->errors += 1;
@@ -1429,7 +1373,7 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
par_mv = par_me->value().as_long();
par_lv = par_le->value().as_long();
}
/* Convert the index to canonical bit address. */
/* Convert the index to cannonical bit address. */
long ridx = rv.as_long();
if (par_mv >= par_lv) {
ridx -= par_lv;
@@ -1550,7 +1494,7 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
// Recalculate the constant address with the adjusted base.
unsigned use_addr = net->array_index_to_address(addr);
if (addr < 0 || use_addr != (unsigned long)addr) {
verinum val ( (uint64_t)use_addr, 8*sizeof(use_addr));
verinum val (use_addr, 8*sizeof(use_addr));
NetEConst*tmp = new NetEConst(val);
tmp->set_line(*this);
delete word_index;
@@ -1623,11 +1567,9 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
// If the part select covers exactly the entire
// vector, then do not bother with it. Return the
// signal itself, casting to unsigned if necessary.
if (sb_lsb == 0 && wid == net->vector_width()) {
net->cast_signed(false);
// signal itself.
if (sb_lsb == 0 && wid == net->vector_width())
return net;
}
// If the part select covers NONE of the vector, then return a
// constant X.
@@ -1638,10 +1580,61 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
return tmp;
}
NetExpr*ex = new NetEConst(verinum(sb_lsb));
NetESelect*ss = new NetESelect(net, ex, wid);
ss->set_line(*this);
return ss;
// If the part select is entirely within the vector, then make
// a simple part select.
if (sb_lsb >= 0 && sb_msb < (signed)net->vector_width()) {
NetExpr*ex = new NetEConst(verinum(sb_lsb));
NetESelect*ss = new NetESelect(net, ex, wid);
ss->set_line(*this);
return ss;
}
// Now the hard stuff. The part select is falling off at least
// one end. We're going to need a NetEConcat to mix the
// selection with overrun.
NetEConst*bot = 0;
if (sb_lsb < 0) {
bot = make_const_x( 0-sb_lsb );
bot->set_line(*this);
sb_lsb = 0;
}
NetEConst*top = 0;
if (sb_msb >= (signed)net->vector_width()) {
top = make_const_x( 1+sb_msb-net->vector_width() );
top->set_line(*this);
sb_msb = net->vector_width()-1;
}
unsigned concat_count = 1;
if (bot) concat_count += 1;
if (top) concat_count += 1;
NetEConcat*concat = new NetEConcat(concat_count);
concat->set_line(*this);
if (bot) {
concat_count -= 1;
concat->set(concat_count, bot);
}
if (sb_lsb == 0 && sb_msb+1 == (signed)net->vector_width()) {
concat_count -= 1;
concat->set(concat_count, net);
} else {
NetExpr*ex = new NetEConst(verinum(sb_lsb));
ex->set_line(*this);
NetESelect*ss = new NetESelect(net, ex, 1+sb_msb-sb_lsb);
ss->set_line(*this);
concat_count -= 1;
concat->set(concat_count, ss);
}
if (top) {
concat_count -= 1;
concat->set(concat_count, top);
}
ivl_assert(*this, concat_count==0);
return concat;
}
/*
+102 -71
View File
@@ -208,18 +208,101 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
return 0;
}
long msb, lsb;
NetExpr*mux;
if (use_sel == index_component_t::SEL_BIT) {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_bit_(des, scope, lv);
return lv;
const index_component_t&index_tail = name_tail.index.back();
ivl_assert(*this, index_tail.msb != 0);
ivl_assert(*this, index_tail.lsb == 0);
/* If there is only a single select expression, it is a
bit select. Evaluate the constant value and treat it
as a part select with a bit width of 1. If the
expression it not constant, then return the
expression as a mux. */
NetExpr*index_expr = elab_and_eval(des, scope, index_tail.msb, -1);
if (NetEConst*index_con = dynamic_cast<NetEConst*> (index_expr)) {
msb = index_con->value().as_long();
lsb = index_con->value().as_long();
mux = 0;
} else {
msb = 0;
lsb = 0;
mux = index_expr;
}
} else {
/* No select expressions, so presume a part select the
width of the register. */
msb = reg->msb();
lsb = reg->lsb();
mux = 0;
}
ivl_assert(*this, use_sel == index_component_t::SEL_NONE);
/* No select expressions. */
NetAssign_*lv;
if (mux) {
/* If there is a non-constant bit select, make a
NetAssign_ to the target reg and attach a
bmux to select the target bit. */
lv = new NetAssign_(reg);
/* Correct the mux for the range of the vector. */
if (reg->msb() < reg->lsb())
mux = make_sub_expr(reg->lsb(), mux);
else if (reg->lsb() != 0)
mux = make_add_expr(mux, - reg->lsb());
lv->set_part(mux, 1);
} else if (msb == reg->msb() && lsb == reg->lsb()) {
/* No bit select, and part select covers the entire
vector. Simplest case. */
lv = new NetAssign_(reg);
} else {
/* If the bit/part select is constant, then make the
NetAssign_ only as wide as it needs to be and connect
only to the selected bits of the reg. */
unsigned loff = reg->sb_to_idx(lsb);
unsigned moff = reg->sb_to_idx(msb);
unsigned wid = moff - loff + 1;
if (moff < loff) {
cerr << get_fileline() << ": error: part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is reversed." << endl;
des->errors += 1;
return 0;
}
/* If the part select extends beyond the extreme of the
variable, then report an error. Note that loff is
converted to normalized form so is relative the
variable pins. */
if ((wid + loff) > reg->vector_width()) {
cerr << get_fileline() << ": error: bit/part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is out of range." << endl;
des->errors += 1;
return 0;
}
lv = new NetAssign_(reg);
lv->set_part(new NetEConst(verinum(loff)), wid);
}
NetAssign_*lv = new NetAssign_(reg);
return lv;
}
@@ -291,67 +374,10 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
return lv;
}
bool PEIdent::elaborate_lval_net_bit_(Design*des,
NetScope*scope,
NetAssign_*lv) const
{
const name_component_t&name_tail = path_.back();
const index_component_t&index_tail = name_tail.index.back();
ivl_assert(*this, index_tail.msb != 0);
ivl_assert(*this, index_tail.lsb == 0);
NetNet*reg = lv->sig();
// Bit selects have a single select expression. Evaluate the
// constant value and treat it as a part select with a bit
// width of 1.
NetExpr*mux = elab_and_eval(des, scope, index_tail.msb, -1);
long lsb = 0;
if (NetEConst*index_con = dynamic_cast<NetEConst*> (mux)) {
lsb = index_con->value().as_long();
mux = 0;
}
if (mux) {
// Non-constant bit mux. Correct the mux for the range
// of the vector, then set the l-value part select expression.
if (reg->msb() < reg->lsb())
mux = make_sub_expr(reg->lsb(), mux);
else if (reg->lsb() != 0)
mux = make_add_expr(mux, - reg->lsb());
lv->set_part(mux, 1);
} else if (lsb == reg->msb() && lsb == reg->lsb()) {
// Constant bit mux that happens to select the only bit
// of the l-value. Don't bother with any select at all.
} else {
// Constant bit select that does something useful.
long loff = reg->sb_to_idx(lsb);
if (loff < 0 || loff >= (long)reg->vector_width()) {
cerr << get_fileline() << ": error: bit select "
<< reg->name() << "[" <<lsb<<"]"
<< " is out of range." << endl;
des->errors += 1;
return 0;
}
lv->set_part(new NetEConst(verinum(loff)), 1);
}
return true;
}
bool PEIdent::elaborate_lval_net_part_(Design*des,
NetScope*scope,
NetAssign_*lv) const
{
// The range expressions of a part select must be
// constant. The calculate_parts_ function calculates the
// values into msb and lsb.
long msb, lsb;
bool flag = calculate_parts_(des, scope, msb, lsb);
if (!flag)
@@ -362,14 +388,17 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
if (msb == reg->msb() && lsb == reg->lsb()) {
/* Part select covers the entire vector. Simplest case. */
/* No bit select, and part select covers the entire
vector. Simplest case. */
} else {
/* Get the canonical offsets into the vector. */
long loff = reg->sb_to_idx(lsb);
long moff = reg->sb_to_idx(msb);
long wid = moff - loff + 1;
/* If the bit/part select is constant, then make the
NetAssign_ only as wide as it needs to be and connect
only to the selected bits of the reg. */
unsigned loff = reg->sb_to_idx(lsb);
unsigned moff = reg->sb_to_idx(msb);
unsigned wid = moff - loff + 1;
if (moff < loff) {
cerr << get_fileline() << ": error: part select "
@@ -379,15 +408,17 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
return false;
}
/* If the part select extends beyond the extremes of the
/* If the part select extends beyond the extreme of the
variable, then report an error. Note that loff is
converted to normalized form so is relative the
variable pins. */
if (loff < 0 || moff >= (signed)reg->vector_width()) {
cerr << get_fileline() << ": warning: Part select "
if ((wid + loff) > reg->vector_width()) {
cerr << get_fileline() << ": error: bit/part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is out of range." << endl;
des->errors += 1;
return false;
}
lv->set_part(new NetEConst(verinum(loff)), wid);
+28 -59
View File
@@ -137,7 +137,7 @@ NetNet* PEBinary::elaborate_net_add_(Design*des, NetScope*scope,
const NetExpr* decay) const
{
NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0),
*rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
*rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
if (lsig == 0 || rsig == 0) return 0;
@@ -394,7 +394,7 @@ static NetNet* compare_eq_constant(Design*des, NetScope*scope,
if (zeros > 0) {
type = op_code == 'e'? NetUReduce::NOR : NetUReduce::OR;
if (debug_elaborate)
if (debug_elaborate)
cerr << lsig->get_fileline() << ": debug: "
<< "Replace net==" << val << " equality with "
<< zeros << "-input reduction [N]OR gate." << endl;
@@ -402,7 +402,7 @@ static NetNet* compare_eq_constant(Design*des, NetScope*scope,
} else {
type = op_code == 'e'? NetUReduce::AND : NetUReduce::NAND;
if (debug_elaborate)
if (debug_elaborate)
cerr << lsig->get_fileline() << ": debug: "
<< "Replace net==" << val << " equality with "
<< ones << "-input reduction AND gate." << endl;
@@ -449,21 +449,26 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
const NetExpr* fall,
const NetExpr* decay) const
{
/* Elaborate the operands of the compare first as expressions
(so that the eval_tree method can reduce constant
expressions, including parameters) then turn those results
into synthesized nets. */
NetExpr*lexp = elab_and_eval(des, scope, left_, -1),
*rexp = elab_and_eval(des, scope, right_, -1);
NetExpr*lexp = elab_and_eval(des, scope, left_, lwidth),
*rexp = elab_and_eval(des, scope, right_, lwidth);
if (lexp == 0 || rexp == 0) return 0;
bool real_arg = true;
if (lexp->expr_type() != IVL_VT_REAL &&
rexp->expr_type() != IVL_VT_REAL) {
unsigned operand_width;
bool real_arg = false;
if (lexp->expr_type() == IVL_VT_REAL ||
rexp->expr_type() == IVL_VT_REAL) {
operand_width = 1;
real_arg = true;
} else {
/* Choose the operand width to be the width of the widest
self-determined operand. */
unsigned operand_width = lexp->expr_width();
operand_width = lexp->expr_width();
if (rexp->expr_width() > operand_width)
operand_width = rexp->expr_width();
@@ -471,8 +476,6 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
lexp = pad_to_width(lexp, operand_width);
rexp->set_width(operand_width);
rexp = pad_to_width(rexp, operand_width);
real_arg = false;
}
NetNet*lsig = 0;
@@ -716,16 +719,6 @@ NetNet* PEBinary::elaborate_net_div_(Design*des, NetScope*scope,
unsigned rwidth = lwidth;
// If either operand is IVL_VT_REAL, then cast the other to
// IVL_VT_REAL so that the division can become IVL_VT_REAL.
if (lsig->data_type()==IVL_VT_REAL || rsig->data_type()==IVL_VT_REAL) {
if (lsig->data_type() != IVL_VT_REAL)
lsig = cast_to_real(des, scope, lsig);
if (rsig->data_type() != IVL_VT_REAL)
rsig = cast_to_real(des, scope, rsig);
}
if (rwidth == 0) {
rwidth = lsig->vector_width();
if (rsig->vector_width() > rwidth)
@@ -797,8 +790,8 @@ NetNet* PEBinary::elaborate_net_mod_(Design*des, NetScope*scope,
const NetExpr* fall,
const NetExpr* decay) const
{
NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0),
*rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
NetNet*lsig = left_->elaborate_net(des, scope, 0, 0, 0, 0),
*rsig = right_->elaborate_net(des, scope, 0, 0, 0, 0);
if (lsig == 0 || rsig == 0) return 0;
@@ -1227,8 +1220,8 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
}
/* If all data bits get shifted away, connect the zero or
* padding bits directly to output, and stop before building the
* concatenation. */
* padding bits directly to output, and stop before building the
* concatenation. */
if (dist >= lwidth) {
connect(osig->pin(0), zero->pin(0));
return osig;
@@ -1466,7 +1459,7 @@ NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope,
forces it to be a signed result. Otherwise, it is as if the
$signed did not exist. */
if (strcmp(name, "$signed") == 0) {
if ((parms_.size() != 1) || (parms_[0] == 0)) {
if ((parms_.count() != 1) || (parms_[0] == 0)) {
cerr << get_fileline() << ": error: The $signed() function "
<< "takes exactly one(1) argument." << endl;
des->errors += 1;
@@ -1482,7 +1475,7 @@ NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope,
/* handle $unsigned like $signed */
if (strcmp(name, "$unsigned") == 0) {
if ((parms_.size() != 1) || (parms_[0] == 0)) {
if ((parms_.count() != 1) || (parms_[0] == 0)) {
cerr << get_fileline() << ": error: The $unsigned() function "
<< "takes exactly one(1) argument." << endl;
des->errors += 1;
@@ -1514,7 +1507,7 @@ NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope,
}
NetSysFunc*net = new NetSysFunc(scope, scope->local_symbol(),
def, 1+parms_.size());
def, 1+parms_.count());
net->set_line(*this);
net->rise_time(rise);
net->fall_time(fall);
@@ -1531,7 +1524,7 @@ NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope,
connect(net->pin(0), osig->pin(0));
unsigned errors = 0;
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
NetNet*tmp = parms_[idx]->elaborate_net(des, scope, 0,
0, 0, 0,
Link::STRONG, Link::STRONG);
@@ -1794,32 +1787,8 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
that connects to a signal with the correct name. */
if (par != 0) {
// Detect and handle the special case that we have a
// real valued parameter. Return a NetLiteral and a
// properly typed net.
if (const NetECReal*pc = dynamic_cast<const NetECReal*>(par)) {
NetLiteral*tmp = new NetLiteral(scope, scope->local_symbol(),
pc->value());
des->add_node(tmp);
tmp->set_line(*par);
sig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT);
sig->set_line(*tmp);
sig->data_type(tmp->data_type());
sig->local_flag(true);
connect(tmp->pin(0), sig->pin(0));
return sig;
}
const NetEConst*pc = dynamic_cast<const NetEConst*>(par);
if (pc == 0) {
cerr << get_fileline() << ": internal error: "
<< "Non-consant parameter value?: " << *par << endl;
cerr << get_fileline() << ": : "
<< "Expression type is " << par->expr_type() << endl;
}
ivl_assert(*this, pc);
assert(pc);
verinum pvalue = pc->value();
/* If the parameter has declared dimensions, then apply
@@ -1829,7 +1798,7 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
if (id_msb || id_lsb) {
assert(id_msb && id_lsb);
const NetEConst*tmp = dynamic_cast<const NetEConst*>(id_msb);
ivl_assert(*this, tmp);
ivl_assert(*this, tmp);
msb = tmp->value().as_long();
tmp = dynamic_cast<const NetEConst*>(id_lsb);
@@ -2327,7 +2296,7 @@ NetNet* PEIdent::elaborate_net_array_(Design*des, NetScope*scope,
} while (0);
#else
if (name_tail.index.size() > sig->array_dimensions())
tmp = process_select_(des, scope, tmp);
tmp = process_select_(des, scope, sig);
#endif
return tmp;
@@ -2997,7 +2966,7 @@ NetNet* PENumber::elaborate_net(Design*des, NetScope*scope,
if (value_->get(width-1) != verinum::V0)
break;
width -= 1;
}
} else if (value_->has_sign() == false) {
@@ -3406,7 +3375,7 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
tmp->decay_time(decay);
connect(tmp->pin(1), sub_sig->pin(0));
connect(tmp->pin(0), sig->pin(0));
connect(tmp->pin(0), sig->pin(0));
}
break;
@@ -3662,7 +3631,7 @@ NetNet* PEUnary::elab_net_unary_real_(Design*des, NetScope*scope,
" for real values." << endl;
des->errors += 1;
break;
case 'm': { // abs()
NetAbs*tmp = new NetAbs(scope, scope->local_symbol(), 1);
tmp->set_line(*this);
-137
View File
@@ -267,140 +267,3 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
return tmp;
}
/* Reuse these routines from eval_tree.cc. */
NetExpr* evaluate_clog2(NetExpr*arg);
NetExpr* evaluate_math_one_arg(NetExpr*arg, const char*name);
NetExpr* evaluate_math_two_args(NetExpr*arg0, NetExpr*arg1, const char*name);
NetExpr* evaluate_abs(NetExpr*arg);
NetExpr* evaluate_min_max(NetExpr*arg0, NetExpr*arg1, const char*name);
NetExpr* PECallFunction::elaborate_pexpr(Design*des, NetScope*scope) const
{
/* Only $clog2 and the builtin mathematical functions can
* be a constant system function. */
perm_string name = peek_tail_name(path_);
if (name[0] == '$' && (generation_flag >= GN_VER2005 ||
gn_icarus_misc_flag || gn_verilog_ams_flag)) {
if (name == "$clog2" ||
name == "$ln" ||
name == "$log10" ||
name == "$exp" ||
name == "$sqrt" ||
name == "$floor" ||
name == "$ceil" ||
name == "$sin" ||
name == "$cos" ||
name == "$tan" ||
name == "$asin" ||
name == "$acos" ||
name == "$atan" ||
name == "$sinh" ||
name == "$cosh" ||
name == "$tanh" ||
name == "$asinh" ||
name == "$acosh" ||
name == "$atanh") {
if (parms_.size() != 1 || parms_[0] == 0) {
cerr << get_fileline() << ": error: " << name
<< " takes a single argument." << endl;
des->errors += 1;
return 0;
}
NetExpr*arg = parms_[0]->elaborate_pexpr(des, scope);
if (arg == 0) return 0;
eval_expr(arg);
NetExpr*rtn;
if (peek_tail_name(path_) == "$clog2") {
rtn = evaluate_clog2(arg);
} else {
rtn = evaluate_math_one_arg(arg, name.str());
}
delete arg;
if (rtn != 0) {
rtn->set_line(*this);
return rtn;
}
}
if (name == "$pow" ||
name == "$atan2" ||
name == "$hypot") {
if (parms_.size() != 2 || parms_[0] == 0 || parms_[1] == 0) {
cerr << get_fileline() << ": error: " << name
<< " takes two arguments." << endl;
des->errors += 1;
return 0;
}
NetExpr*arg0 = parms_[0]->elaborate_pexpr(des, scope);
NetExpr*arg1 = parms_[1]->elaborate_pexpr(des, scope);
if (arg0 == 0 || arg1 == 0) return 0;
eval_expr(arg0);
eval_expr(arg1);
NetExpr*rtn = evaluate_math_two_args(arg0, arg1, name.str());
delete arg0;
delete arg1;
if (rtn != 0) {
rtn->set_line(*this);
return rtn;
}
}
/* These are only available with verilog-ams or icarus-misc. */
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
(name == "$log" || name == "$abs")) {
if (parms_.size() != 1 || parms_[0] == 0) {
cerr << get_fileline() << ": error: " << name
<< " takes a single argument." << endl;
des->errors += 1;
return 0;
}
NetExpr*arg = parms_[0]->elaborate_pexpr(des, scope);
if (arg == 0) return 0;
eval_expr(arg);
NetExpr*rtn;
if (peek_tail_name(path_) == "$log") {
rtn = evaluate_math_one_arg(arg, name.str());
} else {
rtn = evaluate_abs(arg);
}
delete arg;
if (rtn != 0) {
rtn->set_line(*this);
return rtn;
}
}
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
(name == "$min" || name == "$max")) {
if (parms_.size() != 2 || parms_[0] == 0 || parms_[1] == 0) {
cerr << get_fileline() << ": error: " << name
<< " takes two arguments." << endl;
des->errors += 1;
return 0;
}
NetExpr*arg0 = parms_[0]->elaborate_pexpr(des, scope);
NetExpr*arg1 = parms_[1]->elaborate_pexpr(des, scope);
if (arg0 == 0 || arg1 == 0) return 0;
eval_expr(arg0);
eval_expr(arg1);
NetExpr*rtn = evaluate_min_max(arg0, arg1, name.str());
delete arg0;
delete arg1;
if (rtn != 0) {
rtn->set_line(*this);
return rtn;
}
}
cerr << get_fileline() << ": error: this is not a constant "
"system function (" << *this << ")." << endl;
des->errors += 1;
return 0;
}
/* Constant user function code goes here. */
cerr << get_fileline() << ": sorry: constant user functions are not "
"currently supported." << endl;
des->errors += 1;
return 0;
}
+82 -239
View File
@@ -53,7 +53,7 @@ void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur,
assert(ex);
NetExpr*val = ex->elaborate_pexpr(des, scope);
if (val == 0) return;
NetExpr*msb = 0;
NetExpr*lsb = 0;
bool signed_flag = cur.signed_flag;
@@ -71,6 +71,19 @@ void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur,
assert(lsb);
}
if (signed_flag) {
/* If explicitly signed, then say so. */
val->cast_signed(true);
} else if (cur.msb) {
/* If there is a range, then the signedness comes
from the type and not the expression. */
val->cast_signed(signed_flag);
} else {
/* otherwise, let the expression describe
itself. */
signed_flag = val->has_sign();
}
NetScope::range_t*range_list = 0;
for (Module::range_t*range = cur.range ; range ; range = range->next) {
NetScope::range_t*tmp = new NetScope::range_t;
@@ -105,126 +118,13 @@ void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur,
range_list = tmp;
}
/* Set the parameter expression to 0 if the evaluation failed. */
if (val == 0) {
val = scope->set_parameter(name, val, cur.type, msb, lsb,
signed_flag, range_list, cur);
delete val;
return;
}
if (signed_flag) {
/* If explicitly signed, then say so. */
val->cast_signed(true);
} else if (cur.msb) {
/* If there is a range, then the signedness comes
from the type and not the expression. */
val->cast_signed(signed_flag);
} else {
/* otherwise, let the expression describe
itself. */
signed_flag = val->has_sign();
}
val = scope->set_parameter(name, val, cur.type, msb, lsb, signed_flag,
range_list, cur);
val = scope->set_parameter(name, val, cur.type, msb, lsb, signed_flag, range_list, cur);
assert(val);
delete val;
}
static void elaborate_scope_tasks(Design*des, NetScope*scope,
const LineInfo&loc,
const map<perm_string,PTask*>&tasks)
{
typedef map<perm_string,PTask*>::const_iterator tasks_it_t;
for (tasks_it_t cur = tasks.begin()
; cur != tasks.end() ; cur ++ ) {
hname_t use_name( (*cur).first );
if (scope->child(use_name)) {
cerr << loc.get_fileline() << ": error: task/scope name "
<< use_name << " already used in this context."
<< endl;
des->errors += 1;
continue;
}
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);
}
}
static void elaborate_scope_funcs(Design*des, NetScope*scope,
const LineInfo&loc,
const map<perm_string,PFunction*>&funcs)
{
typedef map<perm_string,PFunction*>::const_iterator funcs_it_t;
for (funcs_it_t cur = funcs.begin()
; cur != funcs.end() ; cur ++ ) {
hname_t use_name( (*cur).first );
if (scope->child(use_name)) {
cerr << loc.get_fileline() << ": error: function/scope name "
<< use_name << " already used in this context."
<< endl;
des->errors += 1;
continue;
}
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);
}
}
class generate_schemes_work_item_t : public elaborator_work_item_t {
public:
generate_schemes_work_item_t(Design*des, NetScope*scope, Module*mod)
: elaborator_work_item_t(des), scope_(scope), mod_(mod)
{ }
void elaborate_runrun()
{
if (debug_scopes)
cerr << mod_->get_fileline() << ": debug: "
<< "Processing generate schemes for "
<< scope_path(scope_) << endl;
// Generate schemes can create new scopes in the form of
// generated code. Scan the generate schemes, and *generate*
// new scopes, which is slightly different from simple
// elaboration.
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = mod_->generate_schemes.begin()
; cur != mod_->generate_schemes.end() ; cur ++ ) {
(*cur) -> generate_scope(des, scope_);
}
}
private:
// The scope_ is the scope that contains the generate scheme
// we are to work on. the mod_ is the Module definition for
// that scope, and contains the parsed generate schemes.
NetScope*scope_;
Module*mod_;
};
bool Module::elaborate_scope(Design*des, NetScope*scope,
const replace_t&replacements)
const replace_t&replacements) const
{
if (debug_scopes) {
cerr << get_fileline() << ": debug: Elaborate scope "
@@ -243,6 +143,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
// place of the elaborated expression.
typedef map<perm_string,param_expr_t>::const_iterator mparm_it_t;
typedef map<pform_name_t,PExpr*>::const_iterator pform_parm_it_t;
// This loop scans the parameters in the module, and creates
// stub parameter entries in the scope for the parameter name.
@@ -326,17 +228,15 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
// here because the parameter receiving the assignment may be
// in a scope not discovered by this pass.
typedef list<Module::named_expr_t>::const_iterator defparms_iter_t;
for (defparms_iter_t cur = defparms.begin()
; cur != defparms.end() ; cur ++) {
for (pform_parm_it_t cur = defparms.begin()
; cur != defparms.end() ; cur ++ ) {
PExpr*ex = cur->second;
PExpr*ex = (*cur).second;
assert(ex);
NetExpr*val = ex->elaborate_pexpr(des, scope);
if (val == 0) continue;
scope->defparams.push_back(make_pair(cur->first, val));
scope->defparams[(*cur).first] = val;
}
// Evaluate the attributes. Evaluate them in the scope of the
@@ -349,29 +249,66 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
delete[]attr;
// Generate schemes need to have their scopes elaborated, but
// we cannot do that until defparams are run, so push it off
// into an elaborate work item.
if (debug_scopes)
cerr << get_fileline() << ": debug: "
<< "Schedule generates within " << scope_path(scope)
<< " for elaboration after defparams." << endl;
// Generate schemes can create new scopes in the form of
// generated code. Scan the generate schemes, and *generate*
// new scopes, which is slightly different from simple
// elaboration.
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++ ) {
(*cur) -> generate_scope(des, scope);
}
des->elaboration_work_list.push_back(new generate_schemes_work_item_t(des, scope, this));
// Tasks introduce new scopes, so scan the tasks in this
// module. Create a scope for the task and pass that to the
// elaborate_scope method of the PTask for detailed
// processing.
elaborate_scope_tasks(des, scope, *this, tasks);
typedef map<perm_string,PTask*>::const_iterator tasks_it_t;
for (tasks_it_t cur = tasks_.begin()
; cur != tasks_.end() ; cur ++ ) {
hname_t use_name( (*cur).first );
if (scope->child(use_name)) {
cerr << get_fileline() << ": error: task/scope name "
<< use_name << " already used in this context."
<< endl;
des->errors += 1;
continue;
}
NetScope*task_scope = new NetScope(scope, use_name,
NetScope::TASK);
task_scope->set_line((*cur).second);
(*cur).second->elaborate_scope(des, task_scope);
}
// Functions are very similar to tasks, at least from the
// perspective of scopes. So handle them exactly the same
// way.
elaborate_scope_funcs(des, scope, *this, funcs);
typedef map<perm_string,PFunction*>::const_iterator funcs_it_t;
for (funcs_it_t cur = funcs_.begin()
; cur != funcs_.end() ; cur ++ ) {
hname_t use_name( (*cur).first );
if (scope->child(use_name)) {
cerr << get_fileline() << ": error: function/scope name "
<< use_name << " already used in this context."
<< endl;
des->errors += 1;
continue;
}
NetScope*func_scope = new NetScope(scope, use_name,
NetScope::FUNC);
func_scope->set_line((*cur).second);
(*cur).second->elaborate_scope(des, func_scope);
}
// Gates include modules, which might introduce new scopes, so
// scan all of them to create those scopes.
@@ -485,12 +422,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
container->genvar_tmp_val = genvar;
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
NetEConst*test = dynamic_cast<NetEConst*>(test_ex);
if (test == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar"
<< " conditional expression: " << *loop_test << endl;
des->errors += 1;
return false;
}
assert(test);
while (test->value().as_long()) {
// The actual name of the scope includes the genvar so
@@ -537,12 +469,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
// Calculate the step for the loop variable.
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
if (step == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar"
<< " step expression: " << *loop_step << endl;
des->errors += 1;
return false;
}
assert(step);
if (debug_scopes)
cerr << get_fileline() << ": debug: genvar step from "
<< genvar << " to " << step->value().as_long() << endl;
@@ -567,12 +494,7 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
{
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
NetEConst*test = dynamic_cast<NetEConst*> (test_ex);
if (test == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar"
<< " conditional expression: " << *loop_test << endl;
des->errors += 1;
return false;
}
assert(test);
// If the condition evaluates as false, then do not create the
// scope.
@@ -614,12 +536,10 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
{
NetExpr*case_value_ex = elab_and_eval(des, container, loop_test, -1);
NetEConst*case_value_co = dynamic_cast<NetEConst*>(case_value_ex);
if (case_value_co == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar case"
<< " expression: " << *loop_test << endl;
des->errors += 1;
return false;
}
assert(case_value_co);
// The name of the scope to generate, whatever that item is.
hname_t use_name (scope_name);
if (debug_scopes)
cerr << get_fileline() << ": debug: Generate case "
@@ -628,8 +548,8 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
PGenerate*default_item = 0;
typedef list<PGenerate*>::const_iterator generator_it_t;
generator_it_t cur = generate_schemes.begin();
while (cur != generate_schemes.end()) {
generator_it_t cur = generates.begin();
while (cur != generates.end()) {
PGenerate*item = *cur;
assert( item->scheme_type == PGenerate::GS_CASE_ITEM );
@@ -658,7 +578,7 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
delete case_value_co;
case_value_co = 0;
PGenerate*item = (cur == generate_schemes.end())? default_item : *cur;
PGenerate*item = (cur == generates.end())? default_item : *cur;
if (item == 0) {
cerr << get_fileline() << ": debug: "
<< "No generate items found" << endl;
@@ -670,9 +590,6 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
<< "Generate case matches item at "
<< item->get_fileline() << endl;
// The name of the scope to generate, whatever that item is.
hname_t use_name (item->scope_name);
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
scope->set_line(get_file(), get_lineno());
@@ -688,14 +605,11 @@ void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
// from simple elaboration.
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++ ) {
for (generate_it_t cur = generates.begin()
; cur != generates.end() ; cur ++ ) {
(*cur) -> generate_scope(des, scope);
}
elaborate_scope_tasks(des, scope, *this, tasks);
elaborate_scope_funcs(des, scope, *this, funcs);
// Scan the generated scope for gates that may create
// their own scopes.
typedef list<PGate*>::const_iterator pgate_list_it_t;
@@ -704,51 +618,10 @@ void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
(*cur) ->elaborate_scope(des, scope);
}
typedef list<PProcess*>::const_iterator proc_it_t;
for (proc_it_t cur = behaviors.begin()
; cur != behaviors.end() ; cur ++ ) {
(*cur) -> statement() -> elaborate_scope(des, scope);
}
// Save the scope that we created, for future use.
scope_list_.push_back(scope);
}
class delayed_elaborate_scope_mod_instances : public elaborator_work_item_t {
public:
delayed_elaborate_scope_mod_instances(Design*des,
const PGModule*obj,
Module*mod,
NetScope*sc)
: elaborator_work_item_t(des), obj_(obj), mod_(mod), sc_(sc)
{ }
~delayed_elaborate_scope_mod_instances() { }
virtual void elaborate_runrun();
private:
const PGModule*obj_;
Module*mod_;
NetScope*sc_;
};
void delayed_elaborate_scope_mod_instances::elaborate_runrun()
{
if (debug_scopes)
cerr << obj_->get_fileline() << ": debug: "
<< "Resume scope elaboration of instances of "
<< mod_->mod_name() << "." << endl;
obj_->elaborate_scope_mod_instances_(des, mod_, sc_);
}
/*
* Here we handle the elaborate scope of a module instance. The caller
* has already figured out that this "gate" is a module, and has found
* the module definition. The "sc" argument is the scope that will
* contain this instance.
*/
void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
{
if (get_name() == "") {
@@ -795,36 +668,6 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
return;
}
if (msb_ || lsb_) {
// If there are expressions to evaluate in order to know
// the actual number of instances that will be
// instantiated, then we have to delay further scope
// elaboration until after defparams (above me) are
// run. Do that by appending a work item to the
// elaboration work list.
if (debug_scopes)
cerr << get_fileline() << ": debug: delay elaborate_scope"
<< " of array of " << get_name()
<< " in scope " << scope_path(sc) << "." << endl;
elaborator_work_item_t*tmp
= new delayed_elaborate_scope_mod_instances(des, this, mod, sc);
des->elaboration_work_list.push_back(tmp);
} else {
// If there are no expressions that need to be evaluated
// to elaborate the scope of this next instances, then
// get right to it.
elaborate_scope_mod_instances_(des, mod, sc);
}
}
/*
* This method is called to process a module instantiation after basic
* sanity testing is already complete.
*/
void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*sc) const
{
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1) : 0;
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1) : 0;
NetEConst*msb = dynamic_cast<NetEConst*> (mse);
+38 -66
View File
@@ -108,42 +108,6 @@ bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
return flag;
}
static void elaborate_sig_funcs(Design*des, NetScope*scope,
const map<perm_string,PFunction*>&funcs)
{
typedef map<perm_string,PFunction*>::const_iterator mfunc_it_t;
for (mfunc_it_t cur = funcs.begin()
; cur != funcs.end() ; cur ++) {
hname_t use_name ( (*cur).first );
NetScope*fscope = scope->child(use_name);
if (scope == 0) {
cerr << (*cur).second->get_fileline() << ": internal error: "
<< "Child scope for function " << (*cur).first
<< " missing in " << scope_path(scope) << "." << endl;
des->errors += 1;
continue;
}
(*cur).second->elaborate_sig(des, fscope);
}
}
static void elaborate_sig_tasks(Design*des, NetScope*scope,
const map<perm_string,PTask*>&tasks)
{
typedef map<perm_string,PTask*>::const_iterator mtask_it_t;
for (mtask_it_t cur = tasks.begin()
; cur != tasks.end() ; cur ++) {
NetScope*tscope = scope->child( hname_t((*cur).first) );
assert(tscope);
(*cur).second->elaborate_sig(des, tscope);
}
}
bool Module::elaborate_sig(Design*des, NetScope*scope) const
{
bool flag = true;
@@ -218,12 +182,38 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
flag &= (*gt)->elaborate_sig(des, scope);
}
typedef map<perm_string,PFunction*>::const_iterator mfunc_it_t;
for (mfunc_it_t cur = funcs_.begin()
; cur != funcs_.end() ; cur ++) {
hname_t use_name ( (*cur).first );
NetScope*fscope = scope->child(use_name);
if (scope == 0) {
cerr << (*cur).second->get_fileline() << ": internal error: "
<< "Child scope for function " << (*cur).first
<< " missing in " << scope_path(scope) << "." << endl;
des->errors += 1;
continue;
}
(*cur).second->elaborate_sig(des, fscope);
}
// After all the wires are elaborated, we are free to
// elaborate the ports of the tasks defined within this
// module. Run through them now.
elaborate_sig_funcs(des, scope, funcs);
elaborate_sig_tasks(des, scope, tasks);
typedef map<perm_string,PTask*>::const_iterator mtask_it_t;
for (mtask_it_t cur = tasks_.begin()
; cur != tasks_.end() ; cur ++) {
NetScope*tscope = scope->child( hname_t((*cur).first) );
assert(tscope);
(*cur).second->elaborate_sig(des, tscope);
}
// initial and always blocks may contain begin-end and
// fork-join blocks that can introduce scopes. Therefore, I
@@ -361,7 +351,7 @@ bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
continue;
flag = tmp->elaborate_sig(des, scope) && flag;
}
NetScope::scope_vec_t instance = scope->instance_arrays[get_name()];
@@ -425,8 +415,8 @@ bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
<< scope_path(container) << "." << endl;
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++) {
for (generate_it_t cur = generates.begin()
; cur != generates.end() ; cur ++) {
PGenerate*item = *cur;
if (! item->scope_list_.empty()) {
flag &= item->elaborate_sig(des, container);
@@ -471,12 +461,9 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
cur->elaborate_sig(des, scope);
}
elaborate_sig_funcs(des, scope, funcs);
elaborate_sig_tasks(des, scope, tasks);
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++ ) {
for (generate_it_t cur = generates.begin()
; cur != generates.end() ; cur ++ ) {
(*cur) -> elaborate_sig(des, scope);
}
@@ -589,17 +576,9 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
break;
default:
if (ports_) {
cerr << get_fileline() << ": internal error: I don't know "
<< "how to deal with return type of function "
<< scope->basename() << "." << endl;
} else {
/* If we do not have any ports or a return type this
* is probably a bad function definition. */
cerr << get_fileline() << ": error: Bad definition for "
<< "function " << scope->basename() << "?" << endl;
return;
}
cerr << get_fileline() << ": internal error: I don't know how "
<< "to deal with return type of function "
<< scope->basename() << "." << endl;
}
svector<NetNet*>ports (ports_? ports_->count() : 0);
@@ -1011,11 +990,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal "
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name_;
if (array_dimensions > 0) {
cerr << " [" << array_s0 << ":" << array_e0 << "]" << endl;
}
cerr << " in scope " << scope_path(scope) << endl;
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name_
<< " in scope " << scope_path(scope) << endl;
}
@@ -1040,10 +1016,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
sig->set_signed(get_signed());
sig->set_isint(get_isint());
if (discipline_t*dis = get_discipline()) {
sig->set_discipline(dis);
}
if (pull)
connect(sig->pin(0), pull->pin(0));
+113 -335
View File
@@ -94,7 +94,7 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
assert(lval->pin_count() == 1);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: PGAssign: elaborated l-value"
cerr << get_fileline() << ": debug: PGassign: elaborated l-value"
<< " width=" << lval->vector_width()
<< ", type=" << lval->data_type() << endl;
}
@@ -113,13 +113,14 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
return;
}
/* Cast the right side when needed. */
if ((lval->data_type() == IVL_VT_REAL &&
rid->data_type() != IVL_VT_REAL)) {
rid = cast_to_real(des, scope, rid);
} else if ((lval->data_type() != IVL_VT_REAL &&
rid->data_type() == IVL_VT_REAL)) {
rid = cast_to_int(des, scope, rid, lval->vector_width());
/* If either lval or rid are real then both must be real. */
if ((lval->data_type() == IVL_VT_REAL ||
rid->data_type() == IVL_VT_REAL) &&
lval->data_type() != rid->data_type()) {
cerr << get_fileline() << ": sorry: Both the r-value and "
"the l-value must be real in this context." << endl;
des->errors += 1;
return;
}
ivl_assert(*this, rid);
@@ -286,13 +287,14 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
assert(lval && rval);
assert(rval->pin_count() == 1);
/* Cast the right side when needed. */
if ((lval->data_type() == IVL_VT_REAL &&
rval->data_type() != IVL_VT_REAL)) {
rval = cast_to_real(des, scope, rval);
} else if ((lval->data_type() != IVL_VT_REAL &&
rval->data_type() == IVL_VT_REAL)) {
rval = cast_to_int(des, scope, rval, lval->vector_width());
/* If either lval or rval are real then both must be real. */
if ((lval->data_type() == IVL_VT_REAL ||
rval->data_type() == IVL_VT_REAL) &&
lval->data_type() != rval->data_type()) {
cerr << get_fileline() << ": sorry: Both the r-value and "
"the l-value must be real in this context." << endl;
des->errors += 1;
return;
}
/* If the r-value insists on being smaller then the l-value
@@ -384,7 +386,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
high = msb.as_long();
if (debug_elaborate) {
cerr << get_fileline() << ": debug: PGBuiltin: Make array "
cerr << get_fileline() << ": debug: PGBuiltin: Make arrray "
<< "[" << high << ":" << low << "]"
<< " of " << count << " gates for " << name << endl;
}
@@ -944,17 +946,6 @@ NetNet*PGModule::resize_net_to_port_(Design*des, NetScope*scope,
return tmp;
}
static bool need_bufz_for_input_port(const svector<NetNet*>&prts)
{
if (prts[0]->port_type() != NetNet::PINPUT)
return false;
if (prts[0]->pin(0).nexus()->drivers_present())
return true;
return false;
}
/*
* Instantiate a module by recursively elaborating it. Set the path of
* the recursive elaboration so that signal names get properly
@@ -1169,11 +1160,11 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
/* Input to module. elaborate the expression to
the desired width. If this in an instance
array, then let the net determine its own
array, then let the net determine it's own
width. We use that, then, to decide how to hook
it up.
v NOTE that this also handles the case that the
NOTE that this also handles the case that the
port is actually empty on the inside. We assume
in that case that the port is input. */
@@ -1187,21 +1178,6 @@ v NOTE that this also handles the case that the
continue;
}
if (need_bufz_for_input_port(prts)) {
NetBUFZ*tmp = new NetBUFZ(scope, scope->local_symbol(),
sig->vector_width());
des->add_node(tmp);
connect(tmp->pin(1), sig->pin(0));
NetNet*tmp2 = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, sig->vector_width());
tmp2->local_flag(true);
tmp2->set_line(*this);
tmp2->data_type(sig->data_type());
connect(tmp->pin(0), tmp2->pin(0));
sig = tmp2;
}
} else if (prts[0]->port_type() == NetNet::PINOUT) {
/* Inout to/from module. This is a more
@@ -1213,8 +1189,8 @@ v NOTE that this also handles the case that the
identifier elaborates to the same NetNet in
both cases so the extra elaboration has no
effect. But if the expression passed to the
inout port is a part select, a special part
select must be created that can pass data in
inout port is a part select, aspecial part
select must be created that can paqss data in
both directions.
Use the elaborate_bi_net method to handle all
@@ -1803,7 +1779,6 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
if (rv == 0) return 0;
assert(rv);
if (count_) assert(event_);
/* Rewrite delayed assignments as assignments that are
delayed. For example, a = #<d> b; becomes:
@@ -1856,58 +1831,19 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
/* Generate the delay statement with the final
assignment attached to it. If this is an event delay,
elaborate the PEventStatement. Otherwise, create the
right NetPDelay object. For a repeat event control
repeat the event and then do the final assignment. */
right NetPDelay object. */
NetProc*st;
if (event_) {
if (count_) {
NetExpr*count = elab_and_eval(des, scope, count_, -1);
if (count == 0) {
cerr << get_fileline() << ": Unable to "
"elaborate repeat expression." << endl;
des->errors += 1;
return 0;
}
st = event_->elaborate(des, scope);
if (st == 0) {
cerr << event_->get_fileline() << ": error: "
"unable to elaborate event expression."
<< endl;
des->errors += 1;
return 0;
}
// If the expression is a constant, handle
// certain special iteration counts.
if (NetEConst*ce = dynamic_cast<NetEConst*>(count)) {
long val = ce->value().as_long();
// We only need the real statement.
if (val <= 0) {
delete count;
delete st;
st = 0;
// We don't need the repeat statement.
} else if (val == 1) {
delete count;
// We need a repeat statement.
} else {
st = new NetRepeat(count, st);
}
} else {
st = new NetRepeat(count, st);
}
} else {
st = event_->elaborate_st(des, scope, a2);
if (st == 0) {
cerr << event_->get_fileline() << ": error: "
"unable to elaborate event expression."
<< endl;
des->errors += 1;
return 0;
}
st = event_->elaborate_st(des, scope, a2);
if (st == 0) {
cerr << event_->get_fileline() << ": error: "
"unable to elaborate event expression."
<< endl;
des->errors += 1;
return 0;
}
assert(st);
} else {
NetPDelay*de = new NetPDelay(delay, a2);
de->set_line(*this);
@@ -1917,8 +1853,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
/* And build up the complex statement. */
NetBlock*bl = new NetBlock(NetBlock::SEQU, 0);
bl->append(a1);
if (st) bl->append(st);
if (count_) bl->append(a2);
bl->append(st);
return bl;
}
@@ -1989,34 +1924,6 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
if (delay_ != 0)
delay = elaborate_delay_expr(delay_, des, scope);
if (count_ != 0 || event_ != 0) {
NetExpr*count = 0;
if (count_ != 0) {
assert(event_ != 0);
count = elab_and_eval(des, scope, count_, -1);
if (count == 0) {
cerr << get_fileline() << ": Unable to elaborate "
"repeat expression." << endl;
des->errors += 1;
// return 0;
}
}
NetProc* event = event_->elaborate(des, scope);
if (event == 0) {
cerr << get_fileline() << ": unable to elaborate "
"event expression." << endl;
des->errors += 1;
// return 0;
}
cerr << get_fileline() << ": sorry: non blocking ";
if (count_) cerr << "repeat ";
cerr << "event controls are not supported." << endl;
des->errors += 1;
return 0;
}
/* All done with this node. Mark its line number and check it in. */
NetAssignNB*cur = new NetAssignNB(lv, rv);
cur->set_delay(delay);
@@ -2045,7 +1952,7 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
if (nscope == 0) {
cerr << get_fileline() << ": internal error: "
"unable to find block scope " << scope_path(scope)
<< "." << pscope_name() << endl;
<< "<" << pscope_name() << ">" << endl;
des->errors += 1;
return 0;
}
@@ -2718,8 +2625,8 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
}
NexusSet*nset = enet->nex_input(rem_out);
if (nset == 0) {
cerr << get_fileline() << ": error: Unable to elaborate:"
<< endl;
cerr << get_fileline() << ": internal error: No NexusSet"
<< " from statement." << endl;
enet->dump(cerr, 6);
des->errors += 1;
return enet;
@@ -3049,7 +2956,7 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const
dev = new NetForce(lval, rexp);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Elaborate force,"
cerr << get_fileline() << ": debug: ELaborate force,"
<< " lval width=" << lval->lwidth()
<< " rval width=" << rexp->expr_width()
<< " rval=" << *rexp
@@ -3148,7 +3055,7 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
sig = des->find_signal(scope, id2->path());
if (sig == 0) {
cerr << get_fileline() << ": error: Unable to find variable "
<< id2->path() << " in for-loop increment expression." << endl;
<< id2->path() << " in for-loop increment expressin." << endl;
des->errors += 1;
return body;
}
@@ -3264,14 +3171,17 @@ NetProc* PRepeat::elaborate(Design*des, NetScope*scope) const
// If the expression is a constant, handle certain special
// iteration counts.
if (NetEConst*ce = dynamic_cast<NetEConst*>(expr)) {
long val = ce->value().as_long();
if (val <= 0) {
verinum val = ce->value();
switch (val.as_ulong()) {
case 0:
delete expr;
delete stat;
return new NetBlock(NetBlock::SEQU, 0);
} else if (val == 1) {
case 1:
delete expr;
return stat;
default:
break;
}
}
@@ -3447,6 +3357,29 @@ bool PProcess::elaborate(Design*des, NetScope*scope) const
verinum(1));
} while (0);
/* If this is an always block and we have no or zero delay then
* a runtime infinite loop will happen. If we possible have some
* delay then print a warning that an infinite loop is possible.
*/
if (type() == PProcess::PR_ALWAYS) {
DelayType dly_type = top->statement()->delay_type();
if (dly_type == NO_DELAY || dly_type == ZERO_DELAY) {
cerr << get_fileline() << ": error: always statement"
<< " does not have any delay." << endl;
cerr << get_fileline() << ": : A runtime infinite"
<< " loop will occur." << endl;
des->errors += 1;
return false;
} else if (dly_type == POSSIBLE_DELAY && warn_inf_loop) {
cerr << get_fileline() << ": warning: always statement"
<< " may not have any delay." << endl;
cerr << get_fileline() << ": : A runtime infinite"
<< " loop may be possible." << endl;
}
}
return true;
}
@@ -3623,34 +3556,6 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
}
static void elaborate_functions(Design*des, NetScope*scope,
const map<perm_string,PFunction*>&funcs)
{
typedef map<perm_string,PFunction*>::const_iterator mfunc_it_t;
for (mfunc_it_t cur = funcs.begin()
; cur != funcs.end() ; cur ++) {
hname_t use_name ( (*cur).first );
NetScope*fscope = scope->child(use_name);
assert(fscope);
(*cur).second->elaborate(des, fscope);
}
}
static void elaborate_tasks(Design*des, NetScope*scope,
const map<perm_string,PTask*>&tasks)
{
typedef map<perm_string,PTask*>::const_iterator mtask_it_t;
for (mtask_it_t cur = tasks.begin()
; cur != tasks.end() ; cur ++) {
hname_t use_name ( (*cur).first );
NetScope*tscope = scope->child(use_name);
assert(tscope);
(*cur).second->elaborate(des, tscope);
}
}
/*
* When a module is instantiated, it creates the scope then uses this
* method to elaborate the contents of the module.
@@ -3710,12 +3615,28 @@ bool Module::elaborate(Design*des, NetScope*scope) const
}
// Elaborate functions.
elaborate_functions(des, scope, funcs);
typedef map<perm_string,PFunction*>::const_iterator mfunc_it_t;
for (mfunc_it_t cur = funcs_.begin()
; cur != funcs_.end() ; cur ++) {
hname_t use_name ( (*cur).first );
NetScope*fscope = scope->child(use_name);
assert(fscope);
(*cur).second->elaborate(des, fscope);
}
// Elaborate the task definitions. This is done before the
// behaviors so that task calls may reference these, and after
// the signals so that the tasks can reference them.
elaborate_tasks(des, scope, tasks);
typedef map<perm_string,PTask*>::const_iterator mtask_it_t;
for (mtask_it_t cur = tasks_.begin()
; cur != tasks_.end() ; cur ++) {
hname_t use_name ( (*cur).first );
NetScope*tscope = scope->child(use_name);
assert(tscope);
(*cur).second->elaborate(des, tscope);
}
// Get all the gates of the module and elaborate them by
// connecting them to the signals. The gate may be simple or
@@ -3760,8 +3681,8 @@ bool PGenerate::elaborate(Design*des, NetScope*container) const
<< scope_path(container) << "." << endl;
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++) {
for (generate_it_t cur = generates.begin()
; cur != generates.end() ; cur ++) {
PGenerate*item = *cur;
if (! item->scope_list_.empty()) {
flag &= item->elaborate(des, container);
@@ -3803,9 +3724,6 @@ bool PGenerate::elaborate(Design*des, NetScope*container) const
bool PGenerate::elaborate_(Design*des, NetScope*scope) const
{
elaborate_functions(des, scope, funcs);
elaborate_tasks(des, scope, tasks);
typedef list<PGate*>::const_iterator gates_it_t;
for (gates_it_t cur = gates.begin() ; cur != gates.end() ; cur ++ )
(*cur)->elaborate(des, scope);
@@ -3815,8 +3733,8 @@ bool PGenerate::elaborate_(Design*des, NetScope*scope) const
(*cur)->elaborate(des, scope);
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++ ) {
for (generate_it_t cur = generates.begin()
; cur != generates.end() ; cur ++ ) {
(*cur)->elaborate(des, scope);
}
@@ -3844,113 +3762,6 @@ struct root_elem {
NetScope *scope;
};
class elaborate_root_scope_t : public elaborator_work_item_t {
public:
elaborate_root_scope_t(Design*des, NetScope*scope, Module*rmod)
: elaborator_work_item_t(des), scope_(scope), rmod_(rmod)
{ }
~elaborate_root_scope_t() { }
virtual void elaborate_runrun()
{
Module::replace_t stub;
if (! rmod_->elaborate_scope(des, scope_, stub))
des->errors += 1;
}
private:
NetScope*scope_;
Module*rmod_;
};
class top_defparams : public elaborator_work_item_t {
public:
top_defparams(Design*des)
: elaborator_work_item_t(des)
{ }
~top_defparams() { }
virtual void elaborate_runrun()
{
// This method recurses through the scopes, looking for
// defparam assignments to apply to the parameters in the
// various scopes. This needs to be done after all the scopes
// and basic parameters are taken care of because the defparam
// can assign to a parameter declared *after* it.
des->run_defparams();
// At this point, all parameter overrides are done. Scan the
// scopes and evaluate the parameters all the way down to
// constants.
des->evaluate_parameters();
}
};
class later_defparams : public elaborator_work_item_t {
public:
later_defparams(Design*des)
: elaborator_work_item_t(des)
{ }
~later_defparams() { }
virtual void elaborate_runrun()
{
list<NetScope*>tmp_list;
for (set<NetScope*>::iterator cur = des->defparams_later.begin()
; cur != des->defparams_later.end() ; cur ++ )
tmp_list.push_back(*cur);
des->defparams_later.clear();
while (! tmp_list.empty()) {
NetScope*cur = tmp_list.front();
tmp_list.pop_front();
cur->run_defparams_later(des);
}
des->evaluate_parameters();
}
};
bool Design::check_always_delay() const
{
bool result_flag = true;
for (const NetProcTop*pr = procs_ ; pr ; pr = pr->next_) {
/* If this is an always block and we have no or zero delay then
* a runtime infinite loop will happen. If we possible have some
* delay then print a warning that an infinite loop is possible.
*/
if (pr->type() == NetProcTop::KALWAYS) {
DelayType dly_type = pr->statement()->delay_type();
if (dly_type == NO_DELAY || dly_type == ZERO_DELAY) {
cerr << pr->get_fileline() << ": error: always"
<< " statement does not have any delay." << endl;
cerr << pr->get_fileline() << ": : A runtime"
<< " infinite loop will occur." << endl;
result_flag = false;
} else if (dly_type == POSSIBLE_DELAY && warn_inf_loop) {
cerr << pr->get_fileline() << ": warning: always"
<< " statement may not have any delay." << endl;
cerr << pr->get_fileline() << ": : A runtime"
<< " infinite loop may be possible." << endl;
}
}
}
return result_flag;
}
/*
* This function is the root of all elaboration. The input is the list
* of root module names. The function locates the Module definitions
* for each root, does the whole elaboration sequence, and fills in
* the resulting Design.
*/
Design* elaborate(list<perm_string>roots)
{
svector<root_elem*> root_elems(roots.size());
@@ -3961,7 +3772,7 @@ Design* elaborate(list<perm_string>roots)
// module and elaborate what I find.
Design*des = new Design;
// Scan the root modules by name, and elaborate their scopes.
// Scan the root modules, and elaborate their scopes.
for (list<perm_string>::const_iterator root = roots.begin()
; root != roots.end()
; root++) {
@@ -3980,74 +3791,47 @@ Design* elaborate(list<perm_string>roots)
// Get the module definition for this root instance.
Module *rmod = (*mod).second;
// Make the root scope. This makes a NetScope object and
// pushes it into the list of root scopes in the Design.
// Make the root scope.
NetScope*scope = des->make_root_scope(*root);
// Collect some basic properties of this scope from the
// Module definition.
scope->set_line(rmod);
scope->time_unit(rmod->time_unit);
scope->time_precision(rmod->time_precision);
scope->default_nettype(rmod->default_nettype);
des->set_precision(rmod->time_precision);
Module::replace_t stub;
// Recursively elaborate from this root scope down. This
// does a lot of the grunt work of creating sub-scopes, etc.
if (! rmod->elaborate_scope(des, scope, stub)) {
delete des;
return 0;
}
// Save this scope, along with its definition, in the
// "root_elems" list for later passes.
struct root_elem *r = new struct root_elem;
r->mod = rmod;
r->scope = scope;
root_elems[i++] = r;
// Arrange for these scopes to be elaborated as root
// scopes. Create an "elaborate_root_scope" object to
// contain the work item, and append it to the scope
// elaborations work list.
elaborator_work_item_t*es = new elaborate_root_scope_t(des, scope, rmod);
des->elaboration_work_list.push_back(es);
}
// After the work items for the root scope elaboration, push a
// work item to process the defparams.
des->elaboration_work_list.push_back(new top_defparams(des));
// Run the work list of scope elaborations until the list is
// empty. This list is initially populated above where the
// initial root scopes are primed.
while (! des->elaboration_work_list.empty()) {
// Transfer the queue to a temporary queue.
list<elaborator_work_item_t*> cur_queue;
while (! des->elaboration_work_list.empty()) {
cur_queue.push_back(des->elaboration_work_list.front());
des->elaboration_work_list.pop_front();
}
// Run from the temporary queue. If the temporary queue
// items create new work queue items, they will show up
// in the elaboration_work_list and then we get to run
// through them in the next pass.
while (! cur_queue.empty()) {
elaborator_work_item_t*tmp = cur_queue.front();
cur_queue.pop_front();
tmp->elaborate_runrun();
delete tmp;
}
if (! des->elaboration_work_list.empty()) {
des->elaboration_work_list.push_back(new later_defparams(des));
}
}
// Look for residual defparams (that point to a non-existent
// scope) and clean them out.
des->residual_defparams();
// Errors already? Probably missing root modules. Just give up
// now and return nothing.
if (des->errors > 0)
return des;
// This method recurses through the scopes, looking for
// defparam assignments to apply to the parameters in the
// various scopes. This needs to be done after all the scopes
// and basic parameters are taken care of because the defparam
// can assign to a parameter declared *after* it.
des->run_defparams();
// At this point, all parameter overrides are done. Scan the
// scopes and evaluate the parameters all the way down to
// constants.
des->evaluate_parameters();
// 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
@@ -4071,14 +3855,8 @@ Design* elaborate(list<perm_string>roots)
rc &= rmod->elaborate(des, scope);
}
if (rc == false) {
delete des;
return 0;
}
// Now that everything is fully elaborated verify that we do
// not have an always block with no delay (an infinite loop).
if (des->check_always_delay() == false) {
if (rc == false) {
delete des;
des = 0;
}
+3 -17
View File
@@ -72,16 +72,6 @@ bool NetCaseCmp::emit_node(struct target_t*tgt) const
return true;
}
bool NetCastInt::emit_node(struct target_t*tgt) const
{
return tgt->lpm_cast_int(this);
}
bool NetCastReal::emit_node(struct target_t*tgt) const
{
return tgt->lpm_cast_real(this);
}
bool NetCLShift::emit_node(struct target_t*tgt) const
{
tgt->lpm_clshift(this);
@@ -198,7 +188,8 @@ bool NetProc::emit_proc(struct target_t*tgt) const
bool NetAssign::emit_proc(struct target_t*tgt) const
{
return tgt->proc_assign(this);
tgt->proc_assign(this);
return true;
}
bool NetAssignNB::emit_proc(struct target_t*tgt) const
@@ -371,7 +362,7 @@ void NetScope::emit_scope(struct target_t*tgt) const
/* Run the signals again, but this time to connect the
delay paths. This is done as a second pass because
the paths reference other signals that may be later
in the list. We can do it here because delay paths are
in the list. We can do it here becase delay paths are
always connected within the scope. */
cur = signals_->sig_next_;
do {
@@ -460,11 +451,6 @@ int Design::emit(struct target_t*tgt) const
return rc;
}
void NetEAccess::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_access_func(this);
}
void NetEBinary::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_binary(this);
+42 -353
View File
@@ -22,8 +22,6 @@
# include <iostream>
# include <cstdlib>
# include <cstring>
# include <math.h>
# include "netlist.h"
# include "ivl_assert.h"
@@ -340,15 +338,19 @@ NetEConst* NetEBComp::eval_leeq_real_(NetExpr*le, NetExpr*ri, bool eq_flag)
switch (le->expr_type()) {
case IVL_VT_REAL:
rtmp = dynamic_cast<NetECReal*> (le);
if (rtmp == 0) return 0;
if (rtmp == 0)
return 0;
lv = rtmp->value().as_double();
break;
case IVL_VT_LOGIC:
case IVL_VT_BOOL:
vtmp = dynamic_cast<NetEConst*> (le);
if (vtmp == 0) return 0;
lv = vtmp->value().as_double();
if (vtmp == 0)
return 0;
lv = vtmp->value().as_long();
break;
default:
@@ -357,18 +359,23 @@ NetEConst* NetEBComp::eval_leeq_real_(NetExpr*le, NetExpr*ri, bool eq_flag)
assert(0);
}
switch (ri->expr_type()) {
case IVL_VT_REAL:
rtmp = dynamic_cast<NetECReal*> (ri);
if (rtmp == 0) return 0;
if (rtmp == 0)
return 0;
rv = rtmp->value().as_double();
break;
case IVL_VT_LOGIC:
case IVL_VT_BOOL:
vtmp = dynamic_cast<NetEConst*> (ri);
if (vtmp == 0) return 0;
rv = vtmp->value().as_double();
if (vtmp == 0)
return 0;
rv = vtmp->value().as_long();
break;
default:
@@ -472,6 +479,19 @@ NetEConst* NetEBComp::eval_gt_()
return tmp;
}
/* Compare with a real value. Do it as double precision. */
if (right_->expr_type() == IVL_VT_REAL) {
NetECReal*tmp = dynamic_cast<NetECReal*>(right_);
if (tmp == 0)
return 0;
double rr = tmp->value().as_double();
double ll = lv.has_sign()? lv.as_long() : lv.as_ulong();
verinum result ((ll > rr)? verinum::V1 : verinum::V0, 1, true);
return new NetEConst(result);
}
/* Now go on to the normal test of the values. */
NetEConst*r = dynamic_cast<NetEConst*>(right_);
if (r == 0) return 0;
@@ -510,6 +530,19 @@ NetEConst* NetEBComp::eval_gteq_()
return tmp;
}
/* Compare with a real value. Do it as double precision. */
if (right_->expr_type() == IVL_VT_REAL) {
NetECReal*tmp = dynamic_cast<NetECReal*>(right_);
if (tmp == 0)
return 0;
double rr = tmp->value().as_double();
double ll = lv.has_sign()? lv.as_long() : lv.as_ulong();
verinum result ((ll >= rr)? verinum::V1 : verinum::V0, 1, true);
return new NetEConst(result);
}
/* Now go on to the normal test of the values. */
NetEConst*r = dynamic_cast<NetEConst*>(right_);
if (r == 0) return 0;
@@ -528,66 +561,8 @@ NetEConst* NetEBComp::eval_gteq_()
}
}
NetEConst* NetEBComp::eval_eqeq_real_(NetExpr*le, NetExpr*ri, bool ne_flag)
{
NetEConst*vtmp;
NetECReal*rtmp;
double lv, rv;
switch (le->expr_type()) {
case IVL_VT_REAL:
rtmp = dynamic_cast<NetECReal*> (le);
if (rtmp == 0) return 0;
lv = rtmp->value().as_double();
break;
case IVL_VT_LOGIC:
case IVL_VT_BOOL:
vtmp = dynamic_cast<NetEConst*> (le);
if (vtmp == 0) return 0;
lv = vtmp->value().as_double();
break;
default:
cerr << get_fileline() << ": internal error: "
<< "Unexpected expression type? " << le->expr_type() << endl;
assert(0);
}
switch (ri->expr_type()) {
case IVL_VT_REAL:
rtmp = dynamic_cast<NetECReal*> (ri);
if (rtmp == 0) return 0;
rv = rtmp->value().as_double();
break;
case IVL_VT_LOGIC:
case IVL_VT_BOOL:
vtmp = dynamic_cast<NetEConst*> (ri);
if (vtmp == 0) return 0;
rv = vtmp->value().as_double();
break;
default:
cerr << get_fileline() << ": internal error: "
<< "Unexpected expression type? " << ri->expr_type() << endl;
assert(0);
}
verinum result(((lv == rv) ^ ne_flag) ? verinum::V1 : verinum::V0, 1);
vtmp = new NetEConst(result);
vtmp->set_line(*this);
return vtmp;
}
NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
{
if (right_->expr_type() == IVL_VT_REAL)
return eval_eqeq_real_(right_, left_, ne_flag);
if (left_->expr_type() == IVL_VT_REAL)
return eval_eqeq_real_(right_, left_, ne_flag);
NetEConst*l = dynamic_cast<NetEConst*>(left_);
if (l == 0) return 0;
NetEConst*r = dynamic_cast<NetEConst*>(right_);
@@ -1364,7 +1339,7 @@ NetExpr* NetETernary::eval_tree(int prune_to_width)
case C_0:
eval_expr(false_val_);
if (debug_eval_tree) {
cerr << get_fileline() << ": debug: Evaluate ternary with "
<< "constant condition value: ";
print_ternary_cond(cond_);
@@ -1632,289 +1607,3 @@ NetEConst* NetEUReduce::eval_tree(int prune_to_width)
return new NetEConst(verinum(res, 1));
}
NetExpr* evaluate_clog2(NetExpr*arg)
{
NetEConst*tmpi = dynamic_cast<NetEConst *>(arg);
NetECReal*tmpr = dynamic_cast<NetECReal *>(arg);
if (tmpi || tmpr) {
verinum arg;
if (tmpi) {
arg = tmpi->value();
} else {
arg = verinum(tmpr->value().as_double(), true);
}
/* If we have an x in the verinum we return 32'bx. */
if (!arg.is_defined()) {
verinum tmp (verinum::Vx, 32);
tmp.has_sign(true);
NetEConst*rtn = new NetEConst(tmp);
return rtn;
}
bool is_neg = false;
uint64_t res = 0;
if (arg.is_negative()) {
is_neg = true;
// If the length is not defined, then work with
// the trimmed version of the number.
if (! arg.has_len())
arg = trim_vnum(arg);
}
arg.has_sign(false); // $unsigned()
if (!arg.is_zero()) {
arg = arg - verinum((uint64_t)1, 1);
while (!arg.is_zero()) {
res += 1;
arg = arg >> 1;
}
}
if (is_neg && res < integer_width)
res = integer_width;
verinum tmp (res, 32);
NetEConst*rtn = new NetEConst(tmp);
return rtn;
}
return 0;
}
NetExpr* evaluate_math_one_arg(NetExpr*arg, const char*name)
{
NetEConst*tmpi = dynamic_cast<NetEConst *>(arg);
NetECReal*tmpr = dynamic_cast<NetECReal *>(arg);
if (tmpi || tmpr) {
double arg;
if (tmpi) {
arg = tmpi->value().as_double();
} else {
arg = tmpr->value().as_double();
}
if (strcmp(name, "$ln") == 0) {
return new NetECReal(verireal(log(arg)));
} else if (strcmp(name, "$log") == 0) {
return new NetECReal(verireal(log10(arg)));
} else if (strcmp(name, "$log10") == 0) {
return new NetECReal(verireal(log10(arg)));
} else if (strcmp(name, "$exp") == 0) {
return new NetECReal(verireal(exp(arg)));
} else if (strcmp(name, "$sqrt") == 0) {
return new NetECReal(verireal(sqrt(arg)));
} else if (strcmp(name, "$floor") == 0) {
return new NetECReal(verireal(floor(arg)));
} else if (strcmp(name, "$ceil") == 0) {
return new NetECReal(verireal(ceil(arg)));
} else if (strcmp(name, "$sin") == 0) {
return new NetECReal(verireal(sin(arg)));
} else if (strcmp(name, "$cos") == 0) {
return new NetECReal(verireal(cos(arg)));
} else if (strcmp(name, "$tan") == 0) {
return new NetECReal(verireal(tan(arg)));
} else if (strcmp(name, "$asin") == 0) {
return new NetECReal(verireal(asin(arg)));
} else if (strcmp(name, "$acos") == 0) {
return new NetECReal(verireal(acos(arg)));
} else if (strcmp(name, "$atan") == 0) {
return new NetECReal(verireal(atan(arg)));
} else if (strcmp(name, "$sinh") == 0) {
return new NetECReal(verireal(sinh(arg)));
} else if (strcmp(name, "$cosh") == 0) {
return new NetECReal(verireal(cosh(arg)));
} else if (strcmp(name, "$tanh") == 0) {
return new NetECReal(verireal(tanh(arg)));
} else if (strcmp(name, "$asinh") == 0) {
return new NetECReal(verireal(asinh(arg)));
} else if (strcmp(name, "$acosh") == 0) {
return new NetECReal(verireal(acosh(arg)));
} else if (strcmp(name, "$atanh") == 0) {
return new NetECReal(verireal(atanh(arg)));
}
}
return 0;
}
NetExpr* evaluate_math_two_args(NetExpr*arg0, NetExpr*arg1, const char*name)
{
NetEConst*tmpi0 = dynamic_cast<NetEConst *>(arg0);
NetECReal*tmpr0 = dynamic_cast<NetECReal *>(arg0);
NetEConst*tmpi1 = dynamic_cast<NetEConst *>(arg1);
NetECReal*tmpr1 = dynamic_cast<NetECReal *>(arg1);
if ((tmpi0 || tmpr0) && (tmpi1 || tmpr1)) {
double arg0, arg1;
if (tmpi0) {
arg0 = tmpi0->value().as_double();
} else {
arg0 = tmpr0->value().as_double();
}
if (tmpi1) {
arg1 = tmpi1->value().as_double();
} else {
arg1 = tmpr1->value().as_double();
}
if (strcmp(name, "$pow") == 0) {
return new NetECReal(verireal(pow(arg0, arg1)));
} else if (strcmp(name, "$atan2") == 0) {
return new NetECReal(verireal(atan2(arg0, arg1)));
} else if (strcmp(name, "$hypot") == 0) {
return new NetECReal(verireal(hypot(arg0, arg1)));
}
}
return 0;
}
NetExpr* evaluate_abs(NetExpr*arg)
{
NetEConst*tmpi = dynamic_cast<NetEConst *>(arg);
if (tmpi) {
verinum arg = tmpi->value();
if (arg.is_negative()) {
arg = v_not(arg) + verinum(1);
}
return new NetEConst(arg);
}
NetECReal*tmpr = dynamic_cast<NetECReal *>(arg);
if (tmpr) {
double arg = tmpr->value().as_double();
return new NetECReal(verireal(fabs(arg)));
}
return 0;
}
NetExpr* evaluate_min_max(NetExpr*arg0, NetExpr*arg1, const char*name)
{
NetEConst*tmpi0 = dynamic_cast<NetEConst *>(arg0);
NetECReal*tmpr0 = dynamic_cast<NetECReal *>(arg0);
NetEConst*tmpi1 = dynamic_cast<NetEConst *>(arg1);
NetECReal*tmpr1 = dynamic_cast<NetECReal *>(arg1);
if (tmpi0 && tmpi1) {
verinum arg0 = tmpi0->value();
verinum arg1 = tmpi1->value();
if (strcmp(name, "$min") == 0) {
return new NetEConst( arg0 < arg1 ? arg0 : arg1);
} else if (strcmp(name, "$max") == 0) {
return new NetEConst( arg0 < arg1 ? arg1 : arg0);
}
}
if ((tmpi0 || tmpr0) && (tmpi1 || tmpr1)) {
double arg0, arg1;
if (tmpi0) {
arg0 = tmpi0->value().as_double();
} else {
arg0 = tmpr0->value().as_double();
}
if (tmpi1) {
arg1 = tmpi1->value().as_double();
} else {
arg1 = tmpr1->value().as_double();
}
if (strcmp(name, "$min") == 0) {
return new NetECReal(verireal(arg0 < arg1 ? arg0 : arg1));
} else if (strcmp(name, "$max") == 0) {
return new NetECReal(verireal(arg0 < arg1 ? arg1 : arg0));
}
}
return 0;
}
NetExpr* NetESFunc::eval_tree(int prune_to_width)
{
/* If we are not targeting at least Verilog-2005, Verilog-AMS
* or using the Icarus misc flag then we do not support these
* functions as constant. */
if (generation_flag < GN_VER2005 &&
!gn_icarus_misc_flag && !gn_verilog_ams_flag) {
return 0;
}
const char*nm = name();
NetExpr*rtn = 0;
/* Only $clog2 and the builtin mathematical functions can
* be a constant system function. */
if (strcmp(nm, "$clog2") == 0 ||
strcmp(nm, "$ln") == 0 ||
strcmp(nm, "$log10") == 0 ||
strcmp(nm, "$exp") == 0 ||
strcmp(nm, "$sqrt") == 0 ||
strcmp(nm, "$floor") == 0 ||
strcmp(nm, "$ceil") == 0 ||
strcmp(nm, "$sin") == 0 ||
strcmp(nm, "$cos") == 0 ||
strcmp(nm, "$tan") == 0 ||
strcmp(nm, "$asin") == 0 ||
strcmp(nm, "$acos") == 0 ||
strcmp(nm, "$atan") == 0 ||
strcmp(nm, "$sinh") == 0 ||
strcmp(nm, "$cosh") == 0 ||
strcmp(nm, "$tanh") == 0 ||
strcmp(nm, "$asinh") == 0 ||
strcmp(nm, "$acosh") == 0 ||
strcmp(nm, "$atanh") == 0) {
if (nparms() != 1 || parm(0) == 0) {
cerr << get_fileline() << ": error: " << nm
<< " takes a single argument." << endl;
return 0;
}
if (strcmp(nm, "$clog2") == 0) {
rtn = evaluate_clog2(parm(0));
} else {
rtn = evaluate_math_one_arg(parm(0), nm);
}
}
if (strcmp(nm, "$pow") == 0 ||
strcmp(nm, "$atan2") == 0 ||
strcmp(nm, "$hypot") == 0) {
if (nparms() != 2 || parm(0) == 0 || parm(1) == 0) {
cerr << get_fileline() << ": error: " << nm
<< " takes two arguments." << endl;
return 0;
}
rtn = evaluate_math_two_args(parm(0), parm(1), nm);
}
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
(strcmp(nm, "$log") == 0 || strcmp(nm, "$abs") == 0)) {
if (nparms() != 1 || parm(0) == 0) {
cerr << get_fileline() << ": error: " << nm
<< " takes a single argument." << endl;
return 0;
}
if (strcmp(nm, "$log") == 0) {
rtn = evaluate_math_one_arg(parm(0), nm);
} else {
rtn = evaluate_abs(parm(0));
}
}
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
(strcmp(nm, "$min") == 0 || strcmp(nm, "$max") == 0)) {
if (nparms() != 2 || parm(0) == 0 || parm(1) == 0) {
cerr << get_fileline() << ": error: " << nm
<< " takes two arguments." << endl;
return 0;
}
rtn = evaluate_min_max(parm(0), parm(1), nm);
}
if (rtn != 0) {
rtn->set_line(*this);
if (debug_eval_tree) {
cerr << get_fileline() << ": debug: Evaluate constant "
<< nm << "." << endl;
}
}
return rtn;
}
+1 -1
View File
@@ -154,7 +154,7 @@
*
* The POST_MAP compiler directive causes the GSR manipulations
* included in the test bench to be compiled in, to simulate the chip
* startup. Other than that, the test bench runs the post-map design
* startup. Other then that, the test bench runs the post-map design
* the same way the pre-synthesis design works.
*
* Run this design with the command:
+2 -2
View File
@@ -459,7 +459,7 @@ NetNet* NetEBDiv::synthesize(Design*des)
default: {
cerr << get_fileline() << ": internal error: "
<< "NetEBDiv has unexpected op() code: "
<< "NetEBDiv has unexpeced op() code: "
<< op() << endl;
des->errors += 1;
@@ -1103,7 +1103,7 @@ NetNet* NetEUFunc::synthesize(Design*des)
/* Connect the pins to the arguments. */
NetFuncDef*def = func_->func_def();
for (unsigned idx = 0; idx < eparms.count(); idx += 1) {
NetNet*tmp = pad_to_width(des, eparms[idx],
NetNet*tmp = pad_to_width(des, eparms[idx],
def->port(idx)->vector_width());
connect(net->pin(idx+1), tmp->pin(0));
}
-3
View File
@@ -143,7 +143,6 @@ ivl_scope_def_lineno
ivl_scope_event
ivl_scope_events
ivl_scope_file
ivl_scope_is_auto
ivl_scope_lineno
ivl_scope_logs
ivl_scope_log
@@ -192,8 +191,6 @@ ivl_path_source
ivl_process_attr_cnt
ivl_process_attr_val
ivl_process_file
ivl_process_lineno
ivl_process_scope
ivl_process_stmt
ivl_process_type
-10
View File
@@ -193,7 +193,6 @@ typedef enum ivl_drive_e {
typedef enum ivl_expr_type_e {
IVL_EX_NONE = 0,
IVL_EX_ARRAY = 18,
IVL_EX_BACCESS= 19,
IVL_EX_BINARY = 2,
IVL_EX_CONCAT = 3,
IVL_EX_EVENT = 17,
@@ -255,8 +254,6 @@ typedef enum ivl_lpm_type_e {
IVL_LPM_ABS = 32,
IVL_LPM_ADD = 0,
IVL_LPM_ARRAY = 30,
IVL_LPM_CAST_INT = 34,
IVL_LPM_CAST_REAL = 33,
IVL_LPM_CONCAT = 16,
IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */
IVL_LPM_CMP_EQ = 10,
@@ -1448,9 +1445,6 @@ extern unsigned ivl_parameter_lineno(ivl_parameter_t net);
* ivl_scope_lineno
* Returns the instantiation file and line for this scope.
*
* ivl_scope_is_auto
* Is the task or function declared to be automatic?
*
* ivl_scope_var
* ivl_scope_vars
* REMOVED
@@ -1527,7 +1521,6 @@ extern unsigned ivl_scope_def_lineno(ivl_scope_t net);
extern unsigned ivl_scope_events(ivl_scope_t net);
extern ivl_event_t ivl_scope_event(ivl_scope_t net, unsigned idx);
extern const char* ivl_scope_file(ivl_scope_t net);
extern unsigned ivl_scope_is_auto(ivl_scope_t net);
extern unsigned ivl_scope_lineno(ivl_scope_t net);
extern unsigned ivl_scope_logs(ivl_scope_t net);
extern ivl_net_logic_t ivl_scope_log(ivl_scope_t net, unsigned idx);
@@ -1700,9 +1693,6 @@ extern ivl_statement_t ivl_process_stmt(ivl_process_t net);
extern unsigned ivl_process_attr_cnt(ivl_process_t net);
extern ivl_attribute_t ivl_process_attr_val(ivl_process_t net, unsigned idx);
extern const char* ivl_process_file(ivl_process_t net);
extern unsigned ivl_process_lineno(ivl_process_t net);
/*
* These functions manage statements of various type. This includes
* all the different kinds of statements (as enumerated in
+3 -3
View File
@@ -63,13 +63,13 @@ lexor.c: lexor.lex
install: all installdirs $(libdir)/ivl/ivlpp@EXEEXT@
$(libdir)/ivl/ivlpp@EXEEXT@: ivlpp@EXEEXT@
$(INSTALL_PROGRAM) ./ivlpp@EXEEXT@ $(DESTDIR)$(libdir)/ivl/ivlpp@EXEEXT@
$(INSTALL_PROGRAM) ./ivlpp@EXEEXT@ $(libdir)/ivl/ivlpp@EXEEXT@
installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(DESTDIR)$(libdir)/ivl
$(srcdir)/../mkinstalldirs $(libdir)/ivl
uninstall:
rm -f $(DESTDIR)$(libdir)/ivl/ivlpp@EXEEXT@
rm -f $(libdir)/ivl/ivlpp@EXEEXT@
lexor.o: lexor.c globals.h
main.o: main.c globals.h
+6 -16
View File
@@ -115,7 +115,7 @@ static void ifdef_enter(void)
struct ifdef_stack_t*cur;
cur = (struct ifdef_stack_t*) calloc(1, sizeof(struct ifdef_stack_t));
if (istack->path) cur->path = strdup(istack->path);
cur->path = strdup(istack->path);
cur->lineno = istack->lineno;
cur->next = ifdef_stack;
@@ -131,10 +131,8 @@ static void ifdef_leave(void)
cur = ifdef_stack;
ifdef_stack = cur->next;
/* If either path is from a non-file context e.g.(macro expansion)
* we assume that the non-file part is from this file. */
if (istack->path != NULL && cur->path != NULL &&
strcmp(istack->path,cur->path) != 0) {
if (strcmp(istack->path,cur->path) != 0)
{
fprintf
(
stderr,
@@ -858,7 +856,6 @@ static int define_continue_flag = 0;
static char *find_arg(char*ptr, char*head, char*arg)
{
char *cp = ptr;
size_t len = strlen(arg);
while (1) {
/* Look for a candidate match, just return if none is found. */
@@ -869,8 +866,7 @@ static char *find_arg(char*ptr, char*head, char*arg)
* match is not in the middle of another identifier.
*/
if (cp != head &&
(isalnum(*(cp-1)) || *(cp-1) == '_' || *(cp-1) == '$' ||
isalnum(*(cp+len)) || *(cp+len) == '_' || *(cp+len) == '$')) {
(isalnum(*(cp-1)) || *(cp-1) == '_' || *(cp-1) == '$')) {
cp++;
continue;
}
@@ -945,7 +941,7 @@ static void do_define()
}
/* Detect the continuation sequence. If I find it, remove it
* and the white space that precedes it, then replace all that
* and the white space that preceeds it, then replace all that
* with a single newline.
*/
if ((cp > yytext) && (cp[-1] == '\\'))
@@ -1472,7 +1468,7 @@ static void do_include()
fprintf(depend_file, "%s\n", standby->path);
if (line_direct_flag)
fprintf(yyout, "\n`line 1 \"%s\" 1\n", standby->path);
fprintf(yyout, "\n`line %u \"%s\" 1\n", istack->lineno+1, standby->path);
standby->next = istack;
standby->stringify_flag = 0;
@@ -1588,12 +1584,6 @@ static int load_next_input()
if(depend_file)
fprintf(depend_file, "%s\n", istack->path);
/* This works around an issue in flex yyrestart() where it
* uses yyin to create a new buffer when one does not exist.
* I would have assumed that it would use the file argument.
* The problem is that we have deleted the buffer and freed
* yyin (isp->file) above. */
yyin = 0;
yyrestart(istack->file);
return 1;
}
+1 -1
View File
@@ -282,7 +282,7 @@ int main(int argc, char*argv[])
fclose(src);
break;
}
case 'v':
fprintf(stderr, "Icarus Verilog Preprocessor version %s\n",
VERSION);
+1 -1
View File
@@ -843,7 +843,7 @@ static verinum*make_unsized_dec(const char*ptr)
if (ptr[0] == '\'') {
/* The number has decorations of the form 'sd<digits>,
possibly with space between the d and the <digits>.
Also, the 's' is optional, and marks the number as
Also, the 's' is optional, and markes the number as
signed. */
ptr += 1;
-1
View File
@@ -25,7 +25,6 @@ assign, GN_KEYWORDS_1364_1995, K_assign
atan, GN_KEYWORDS_VAMS_2_3, K_atan
atan2, GN_KEYWORDS_VAMS_2_3, K_atan2
atanh, GN_KEYWORDS_VAMS_2_3, K_atanh
automatic, GN_KEYWORDS_1364_2001, K_automatic
begin, GN_KEYWORDS_1364_1995, K_begin
bool, GN_KEYWORDS_ICARUS, K_bool
buf, GN_KEYWORDS_1364_1995, K_buf
+3 -3
View File
@@ -89,12 +89,12 @@ distclean: clean
install:: all installdirs $(libdir)/libveriuser.a $(INSTALL32)
$(libdir)/libveriuser.a: ./libveriuser.a
$(INSTALL_DATA) ./libveriuser.a $(DESTDIR)$(libdir)/libveriuser.a
$(INSTALL_DATA) ./libveriuser.a $(libdir)/libveriuser.a
installdirs: mkinstalldirs
$(srcdir)/mkinstalldirs $(DESTDIR)$(includedir) $(DESTDIR)$(libdir)
$(srcdir)/mkinstalldirs $(includedir) $(libdir)
uninstall::
rm -f $(DESTDIR)$(libdir)/libveriuser.a
rm -f $(libdir)/libveriuser.a
-include $(patsubst %.o, dep/%.d, $O)
+1 -1
View File
@@ -35,7 +35,7 @@ int acc_object_of_type(handle object, PLI_INT32 type)
if (pli_trace) {
fprintf(pli_trace, "acc_object_of_type(%p \"%s\", %d)",
object, vpi_get_str(vpiName, object), type);
object, vpi_get_str(vpiName, object), type);
fflush(pli_trace);
}
+2 -3
View File
@@ -60,9 +60,8 @@ bool Nexus::drivers_constant() const
if (cur_dir == Link::PASSIVE) {
const NetPins*obj = cur->get_obj();
const NetObj*as_obj = dynamic_cast<const NetObj*>(obj);
if (as_obj == 0 || as_obj->scope()->parent() != 0)
const NetObj*obj = cur->get_obj();
if (obj->scope()->parent() != 0)
continue;
sig = dynamic_cast<const NetNet*>(cur->get_obj());
+19 -46
View File
@@ -54,7 +54,6 @@ const char NOTICE[] =
#endif
# include "pform.h"
# include "parse_api.h"
# include "PGenerate.h"
# include "netlist.h"
# include "target.h"
# include "compiler.h"
@@ -161,6 +160,9 @@ extern void synth(Design*des);
extern void synth2(Design*des);
extern void syn_rules(Design*des);
extern void nodangle(Design*des);
#ifdef WITH_T_XNF
extern void xnfio(Design*des);
#endif
typedef void (*net_func)(Design*);
static struct net_func_map {
@@ -172,6 +174,9 @@ static struct net_func_map {
{ "synth", &synth },
{ "synth2", &synth2 },
{ "syn-rules", &syn_rules },
#ifdef WITH_T_XNF
{ "xnfio", &xnfio },
#endif
{ 0, 0 }
};
@@ -230,16 +235,16 @@ static void process_generation_flag(const char*gen)
} else if (strcmp(gen,"specify") == 0) {
gn_specify_blocks_flag = true;
} else if (strcmp(gen,"no-specify") == 0) {
gn_specify_blocks_flag = false;
} else if (strcmp(gen,"verilog-ams") == 0) {
gn_verilog_ams_flag = true;
} else if (strcmp(gen,"no-verilog-ams") == 0) {
gn_verilog_ams_flag = false;
} else if (strcmp(gen,"io-range-error") == 0) {
gn_io_range_error_flag = true;
@@ -267,9 +272,6 @@ static void parm_to_flagmap(const string&flag)
flags[key] = value;
}
static void find_module_mention(map<perm_string,bool>&check_map, Module*m);
static void find_module_mention(map<perm_string,bool>&check_map, PGenerate*s);
/*
* Read the contents of a config file. This file is a temporary
* configuration file made by the compiler driver to carry the bulky
@@ -727,7 +729,15 @@ int main(int argc, char*argv[])
for (mod = pform_modules.begin()
; mod != pform_modules.end()
; mod++) {
find_module_mention(mentioned_p, mod->second);
list<PGate*> gates = (*mod).second->get_gates();
list<PGate*>::const_iterator gate;
for (gate = gates.begin(); gate != gates.end(); gate++) {
PGModule *mod = dynamic_cast<PGModule*>(*gate);
if (mod) {
// Note that this module has been instantiated
mentioned_p[mod->get_type()] = true;
}
}
}
for (mod = pform_modules.begin()
@@ -897,40 +907,3 @@ int main(int argc, char*argv[])
return des? des->errors : 1;
}
static void find_module_mention(map<perm_string,bool>&check_map, Module*mod)
{
list<PGate*> gates = mod->get_gates();
list<PGate*>::const_iterator gate;
for (gate = gates.begin(); gate != gates.end(); gate++) {
PGModule*tmp = dynamic_cast<PGModule*>(*gate);
if (tmp) {
// Note that this module has been instantiated
check_map[tmp->get_type()] = true;
}
}
list<PGenerate*>::const_iterator cur;
for (cur = mod->generate_schemes.begin()
; cur != mod->generate_schemes.end() ; cur ++) {
find_module_mention(check_map, *cur);
}
}
static void find_module_mention(map<perm_string,bool>&check_map, PGenerate*schm)
{
list<PGate*>::const_iterator gate;
for (gate = schm->gates.begin(); gate != schm->gates.end(); gate++) {
PGModule*tmp = dynamic_cast<PGModule*>(*gate);
if (tmp) {
// Note that this module has been instantiated
check_map[tmp->get_type()] = true;
}
}
list<PGenerate*>::const_iterator cur;
for (cur = schm->generate_schemes.begin()
; cur != schm->generate_schemes.end() ; cur ++) {
find_module_mention(check_map, *cur);
}
}
+9 -118
View File
@@ -20,7 +20,6 @@
# include "config.h"
# include <iostream>
# include <set>
# include <cstdlib>
/*
@@ -209,12 +208,10 @@ void NetScope::run_defparams(Design*des)
}
}
while (! defparams.empty()) {
pair<pform_name_t,NetExpr*> pp = defparams.front();
defparams.pop_front();
pform_name_t path = pp.first;
NetExpr*val = pp.second;
map<pform_name_t,NetExpr*>::const_iterator pp;
for (pp = defparams.begin() ; pp != defparams.end() ; pp ++ ) {
NetExpr*val = (*pp).second;
pform_name_t path = (*pp).first;
perm_string perm_name = peek_tail_name(path);
path.pop_back();
@@ -225,20 +222,11 @@ void NetScope::run_defparams(Design*des)
is the current scope. */
NetScope*targ_scope = des->find_scope(this, eval_path);
if (targ_scope == 0) {
// Push the defparam onto a list for retry
// later. It is possible for the scope lookup to
// fail if the scope being defparam'd into is
// generated by an index array for generate.
eval_path.push_back(hname_t(perm_name));
defparams_later.push_back(make_pair(eval_path,val));
cerr << val->get_fileline() << ": warning: scope of " <<
path << "." << perm_name << " not found." << endl;
continue;
}
// Once placed in the parameter map, the expression may
// be deleted when evaluated, so give it a copy of this
// expression, not the original.
val = val->dup_expr();
bool flag = targ_scope->replace_parameter(perm_name, val);
if (! flag) {
cerr << val->get_fileline() << ": warning: parameter "
@@ -247,66 +235,6 @@ void NetScope::run_defparams(Design*des)
}
}
// If some of the defparams didn't find a scope in the name,
// then try again later. It may be that the target scope is
// created later by generate scheme or instance array.
if (! defparams_later.empty())
des->defparams_later.insert(this);
}
void NetScope::run_defparams_later(Design*des)
{
set<NetScope*> target_scopes;
list<pair<list<hname_t>,NetExpr*> > defparams_even_later;
while (! defparams_later.empty()) {
pair<list<hname_t>,NetExpr*> cur = defparams_later.front();
defparams_later.pop_front();
list<hname_t>eval_path = cur.first;
perm_string name = eval_path.back().peek_name();
eval_path.pop_back();
NetExpr*val = cur.second;
NetScope*targ_scope = des->find_scope(this, eval_path);
if (targ_scope == 0) {
// If a scope in the target path is not found,
// then push this defparam for handling even
// later. Maybe a later generate scheme or
// instance array will create the scope.
defparams_even_later.push_back(cur);
continue;
}
// Once placed in the parameter map, the expression may
// be deleted when evaluated, so give it a copy of this
// expression, not the original.
val = val->dup_expr();
bool flag = targ_scope->replace_parameter(name, val);
if (! flag) {
cerr << val->get_fileline() << ": warning: parameter "
<< name << " not found in "
<< scope_path(targ_scope) << "." << endl;
}
// We'll need to re-evaluate parameters in this scope
target_scopes.insert(targ_scope);
}
// All the scopes that this defparam set touched should have
// their parameters re-evaluated.
for (set<NetScope*>::iterator cur = target_scopes.begin()
; cur != target_scopes.end() ; cur ++ )
(*cur)->evaluate_parameters(des);
// If there are some scopes that still have missing scopes,
// then sav them back into the defparams_later list for a
// later pass.
defparams_later = defparams_even_later;
if (! defparams_later.empty())
des->defparams_later.insert(this);
}
void Design::evaluate_parameters()
@@ -357,11 +285,11 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
/* Evaluate the parameter expression, if necessary. */
NetExpr*expr = (*cur).second.expr;
if (expr == NULL) return; // This is an invalid parameter so return.
assert(expr);
eval_expr(expr);
/* The eval_expr may delete and replace the expr pointer, so the
/* The eval_expr may delete any replace the expr pointer, so the
second.expr value cannot be relied on. Might as well replace
it now with the expression that we evaluated. */
(*cur).second.expr = expr;
@@ -407,14 +335,6 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
unsigned long wid = (msb >= lsb)? msb - lsb : lsb - msb;
wid += 1;
/* If we have a real value convert it to an integer. */
if(NetECReal*tmp = dynamic_cast<NetECReal*>(expr)) {
verinum nval(tmp->value().as_long64());
expr = new NetEConst(nval);
expr->set_line(*((*cur).second.expr));
(*cur).second.expr = expr;
}
NetEConst*val = dynamic_cast<NetEConst*>(expr);
assert(val);
@@ -428,7 +348,7 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
tmp.has_sign ( (*cur).second.signed_flag );
delete val;
val = new NetEConst(tmp);
(*cur).second.expr = expr = val;
expr = val;
}
}
@@ -586,9 +506,6 @@ void NetScope::evaluate_parameters(Design*des)
cur = cur->sib_;
}
if (debug_scopes)
cerr << ":0" << ": debug: "
<< "Evaluate parameters in " << scope_path(this) << endl;
// Evaluate the parameter values. The parameter expressions
// have already been elaborated and replaced by the scope
@@ -623,32 +540,6 @@ void NetScope::evaluate_parameters(Design*des)
}
void Design::residual_defparams()
{
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
scope != root_scopes_.end(); scope++)
(*scope)->residual_defparams(this);
}
void NetScope::residual_defparams(Design*des)
{
// Clean out the list of defparams that never managed to match
// a scope. Print a warning for each.
while (! defparams_later.empty()) {
pair<list<hname_t>,NetExpr*> cur = defparams_later.front();
defparams_later.pop_front();
cerr << cur.second->get_fileline() << ": warning: "
<< "Scope of " << cur.first << " not found." << endl;
}
NetScope*cur = sub_;
while (cur) {
cur->residual_defparams(des);
cur = cur->sib_;
}
}
const char* Design::get_flag(const string&key) const
{
map<string,const char*>::const_iterator tmp = flags_.find(key);
+1 -1
View File
@@ -299,7 +299,7 @@ void NetEvProbe::find_similar_probes(list<NetEvProbe*>&plist)
Nexus*nex = pin(0).nexus();
for (Link*lcur = nex->first_nlink(); lcur; lcur = lcur->next_nlink()) {
NetPins*obj = lcur->get_obj();
NetObj*obj = lcur->get_obj();
if (obj->pin_count() != pin_count())
continue;
-14
View File
@@ -588,17 +588,3 @@ ivl_variable_type_t NetESFunc::expr_type() const
{
return type_;
}
NetEAccess::NetEAccess(NetBranch*br, nature_t*nat)
: branch_(br), nature_(nat)
{
}
NetEAccess::~NetEAccess()
{
}
ivl_variable_type_t NetEAccess::expr_type() const
{
return IVL_VT_REAL;
}
+82
View File
@@ -0,0 +1,82 @@
/*
* Copyright (c) 2000-2004 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
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_force.cc,v 1.13 2004/12/11 02:31:26 steve Exp $"
#endif
# include "config.h"
# include "compiler.h"
/*
* This file contains implementation of the NetForce, NetRelease,
* NetCAssign and NetDeassign classes. These are similar or related in
* that they handle the procedural continuous assign and force
* statements.
*/
# include "netlist.h"
# include <assert.h>
/*
* $Log: net_force.cc,v $
* Revision 1.13 2004/12/11 02:31:26 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.12 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items.
*
* Revision 1.11 2003/03/06 00:28:41 steve
* All NetObj objects have lex_string base names.
*
* Revision 1.10 2003/01/27 05:09:17 steve
* Spelling fixes.
*
* Revision 1.9 2002/08/19 00:06:12 steve
* Allow release to handle removal of target net.
*
* Revision 1.8 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
* Revision 1.7 2002/01/19 19:02:08 steve
* Pass back target errors processing conditionals.
*
* Revision 1.6 2001/11/14 03:28:49 steve
* DLL target support for force and release.
*
* Revision 1.5 2001/10/31 05:24:52 steve
* ivl_target support for assign/deassign.
*
* Revision 1.4 2001/10/28 01:14:53 steve
* NetObj constructor finally requires a scope.
*
* Revision 1.3 2001/07/25 03:10:49 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.2 2000/05/12 01:22:41 steve
* NetCAssign needs to incr_eref its lval to lock it down.
*
* Revision 1.1 2000/05/11 23:37:27 steve
* Add support for procedural continuous assignment.
*
*/
+1 -1
View File
@@ -104,7 +104,7 @@ bool PECallFunction::check_call_matches_definition_(Design*des, NetScope*dscope)
1 nil pointer. This is how the parser tells me of no
parameter. In other words, ``func()'' is 1 nil parameter. */
unsigned parms_count = parms_.size();
unsigned parms_count = parms_.count();
if ((parms_count == 1) && (parms_[0] == 0))
parms_count = 0;
+6 -44
View File
@@ -134,13 +134,13 @@ verinum::V Link::get_init() const
}
void Link::cur_link(NetPins*&net, unsigned &pin)
void Link::cur_link(NetObj*&net, unsigned &pin)
{
net = node_;
pin = pin_;
}
void Link::cur_link(const NetPins*&net, unsigned &pin) const
void Link::cur_link(const NetObj*&net, unsigned &pin) const
{
net = node_;
pin = pin_;
@@ -186,12 +186,12 @@ const Link* Link::next_nlink() const
return next_;
}
const NetPins*Link::get_obj() const
const NetObj*Link::get_obj() const
{
return node_;
}
NetPins*Link::get_obj()
NetObj*Link::get_obj()
{
return node_;
}
@@ -247,51 +247,13 @@ verinum::V Nexus::get_init() const
return verinum::Vz;
}
bool Nexus::drivers_present() const
{
assert(list_);
for (Link*cur = list_ ; cur ; cur = cur->next_) {
if (cur->get_dir() == Link::OUTPUT)
return true;
if (cur->get_dir() == Link::INPUT)
continue;
// Must be PASSIVE, so if it is some kind of net, see if
// it is the sort that might drive the nexus.
const NetPins*obj;
unsigned pin;
cur->cur_link(obj, pin);
if (const NetNet*net = dynamic_cast<const NetNet*>(obj))
switch (net->type()) {
case NetNet::SUPPLY0:
case NetNet::SUPPLY1:
case NetNet::TRI0:
case NetNet::TRI1:
case NetNet::WAND:
case NetNet::WOR:
case NetNet::TRIAND:
case NetNet::TRIOR:
case NetNet::REG:
return true;
default:
break;
}
}
return false;
}
void Nexus::drivers_delays(NetExpr*rise, NetExpr*fall, NetExpr*decay)
{
for (Link*cur = list_ ; cur ; cur = cur->next_) {
if (cur->get_dir() != Link::OUTPUT)
continue;
NetObj*obj = dynamic_cast<NetObj*>(cur->get_obj());
if (obj == 0)
continue;
NetObj*obj = cur->get_obj();
obj->rise_time(rise);
obj->fall_time(fall);
obj->decay_time(decay);
@@ -435,7 +397,7 @@ const char* Nexus::name() const
if (sig == 0) {
const Link*lnk = first_nlink();
const NetObj*obj = dynamic_cast<const NetObj*>(lnk->get_obj());
const NetObj*obj = lnk->get_obj();
pin = lnk->get_pin();
cerr << "internal error: No signal for nexus of " <<
obj->name() << " pin " << pin << "(" <<
+2 -15
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-2007 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
@@ -53,13 +53,8 @@ NexusSet* NetEBinary::nex_input(bool rem_out)
NexusSet* NetEConcat::nex_input(bool rem_out)
{
if (parms_[0] == NULL) return NULL;
NexusSet*result = parms_[0]->nex_input(rem_out);
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
if (parms_[idx] == NULL) {
delete result;
return NULL;
}
NexusSet*tmp = parms_[idx]->nex_input(rem_out);
result->add(*tmp);
delete tmp;
@@ -67,11 +62,6 @@ NexusSet* NetEConcat::nex_input(bool rem_out)
return result;
}
NexusSet* NetEAccess::nex_input(bool rem_out)
{
return new NexusSet;
}
/*
* A constant has not inputs, so always return an empty set.
*/
@@ -108,10 +98,6 @@ NexusSet* NetESelect::nex_input(bool rem_out)
{
NexusSet*result = base_? base_->nex_input(rem_out) : new NexusSet();
NexusSet*tmp = expr_->nex_input(rem_out);
if (tmp == NULL) {
delete result;
return NULL;
}
result->add(*tmp);
delete tmp;
return result;
@@ -395,3 +381,4 @@ NexusSet* NetWhile::nex_input(bool rem_out)
delete tmp;
return result;
}
+2 -4
View File
@@ -41,7 +41,6 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t)
signals_ = 0;
events_ = 0;
lcounter_ = 0;
is_auto_ = false;
if (up) {
default_nettype_ = up->default_nettype();
@@ -167,7 +166,7 @@ bool NetScope::replace_parameter(perm_string key, NetExpr*expr)
/*
* This is not really complete (msb, lsb, sign). It is currently only
* used to add a genvar to the local parameter list.
* used to add a genver to the local parameter list.
*/
NetExpr* NetScope::set_localparam(perm_string key, NetExpr*expr,
const LineInfo&file_line)
@@ -262,7 +261,6 @@ NetFuncDef* NetScope::func_def()
assert( type_ == FUNC );
return func_;
}
bool NetScope::in_func()
{
return (type_ == FUNC) ? true : false;
@@ -277,7 +275,7 @@ const NetFuncDef* NetScope::func_def() const
void NetScope::set_module_name(perm_string n)
{
assert(type_ == MODULE);
module_name_ = n; /* NOTE: n must have been permallocated. */
module_name_ = n; /* NOTE: n mus have been permallocated. */
}
perm_string NetScope::module_name() const
+5 -9
View File
@@ -100,12 +100,8 @@ void join_island(NetObj*obj)
Nexus*nex = obj->pin(idx).nexus();
for (Link*cur = nex->first_nlink() ; cur ; cur = cur->next_nlink()) {
unsigned pin;
NetPins*tmp_pins;
cur->cur_link(tmp_pins, pin);
NetObj*tmp = dynamic_cast<NetObj*> (tmp_pins);
if (tmp == 0)
continue;
NetObj*tmp;
cur->cur_link(tmp, pin);
// Skip self.
if (tmp == obj)
@@ -118,7 +114,7 @@ void join_island(NetObj*obj)
// If that is an uncommitted branch, then save
// it. When I finally choose an island for self,
// these branches will be scanned so that they join
// these branches will be scanned so tha they join
// this island as well.
if (tmp_branch->island == 0) {
uncommitted_neighbors.push_back(tmp);
@@ -132,7 +128,7 @@ void join_island(NetObj*obj)
if (branch->island == 0) {
if (debug_elaborate)
cerr << obj->get_fileline() << ": debug: "
<< "Join branch to existing island." << endl;
<< "Join brach to existing island." << endl;
branch->island = tmp_branch->island;
} else if (branch->island != tmp_branch->island) {
@@ -143,7 +139,7 @@ void join_island(NetObj*obj)
}
}
// If after all that we did not find an island to join, then
// If after all that we did not find an idland to join, then
// start the island not and join it.
if (branch->island == 0) {
branch->island = new ivl_island_s;
+30 -90
View File
@@ -91,7 +91,7 @@ unsigned count_inputs(const Link&pin)
const Nexus*nex = pin.nexus();
for (const Link*clnk = nex->first_nlink()
; clnk ; clnk = clnk->next_nlink()) {
const NetPins*cur;
const NetObj*cur;
unsigned cpin;
clnk->cur_link(cur, cpin);
if (cur->pin(cpin).get_dir() == Link::INPUT)
@@ -108,7 +108,7 @@ unsigned count_outputs(const Link&pin)
const Nexus*nex = pin.nexus();
for (const Link*clnk = nex->first_nlink()
; clnk ; clnk = clnk->next_nlink()) {
const NetPins*cur;
const NetObj*cur;
unsigned cpin;
clnk->cur_link(cur, cpin);
if (cur->pin(cpin).get_dir() == Link::OUTPUT)
@@ -125,7 +125,7 @@ unsigned count_signals(const Link&pin)
const Nexus*nex = pin.nexus();
for (const Link*clnk = nex->first_nlink()
; clnk ; clnk = clnk->next_nlink()) {
const NetPins*cur;
const NetObj*cur;
unsigned cpin;
clnk->cur_link(cur, cpin);
if (dynamic_cast<const NetNet*>(cur))
@@ -142,7 +142,7 @@ const NetNet* find_link_signal(const NetObj*net, unsigned pin, unsigned&bidx)
for (const Link*clnk = nex->first_nlink()
; clnk ; clnk = clnk->next_nlink()) {
const NetPins*cur;
const NetObj*cur;
unsigned cpin;
clnk->cur_link(cur, cpin);
@@ -171,8 +171,8 @@ Link* find_next_output(Link*lnk)
return 0;
}
NetPins::NetPins(unsigned npins)
: npins_(npins)
NetObj::NetObj(NetScope*s, perm_string n, unsigned np)
: scope_(s), name_(n), npins_(np), delay1_(0), delay2_(0), delay3_(0)
{
pins_ = new Link[npins_];
for (unsigned idx = 0 ; idx < npins_ ; idx += 1) {
@@ -181,37 +181,9 @@ NetPins::NetPins(unsigned npins)
}
}
NetPins::~NetPins()
{
delete[]pins_;
}
Link& NetPins::pin(unsigned idx)
{
if (idx >= npins_) {
cerr << get_fileline() << ": internal error: pin("<<idx<<")"
<< " out of bounds("<<npins_<<")" << endl;
cerr << get_fileline() << ": : typeid="
<< typeid(*this).name() << endl;
}
assert(idx < npins_);
return pins_[idx];
}
const Link& NetPins::pin(unsigned idx) const
{
assert(idx < npins_);
return pins_[idx];
}
NetObj::NetObj(NetScope*s, perm_string n, unsigned np)
: NetPins(np), scope_(s), name_(n), delay1_(0), delay2_(0), delay3_(0)
{
}
NetObj::~NetObj()
{
delete[]pins_;
}
NetScope* NetObj::scope()
@@ -224,6 +196,25 @@ const NetScope* NetObj::scope() const
return scope_;
}
Link& NetObj::pin(unsigned idx)
{
if (idx >= npins_) {
cerr << get_fileline() << ": internal error: pin("<<idx<<")"
<< " out of bounds("<<npins_<<")" << endl;
cerr << get_fileline() << ": : typeid="
<< typeid(*this).name() << endl;
}
assert(idx < npins_);
return pins_[idx];
}
const Link& NetObj::pin(unsigned idx) const
{
assert(idx < npins_);
return pins_[idx];
}
NetNode::NetNode(NetScope*s, perm_string n, unsigned npins)
: NetObj(s, n, npins), node_next_(0), node_prev_(0), design_(0)
{
@@ -235,19 +226,6 @@ NetNode::~NetNode()
design_->del_node(this);
}
NetBranch::NetBranch(discipline_t*dis)
: NetPins(2), discipline_(dis)
{
pin(0).set_name(perm_string::literal("A"), 0);
pin(0).set_dir(Link::PASSIVE);
pin(1).set_name(perm_string::literal("B"), 0);
pin(1).set_dir(Link::PASSIVE);
}
NetBranch::~NetBranch()
{
}
NetBus::NetBus(NetScope*s, unsigned pin_count)
: NetObj(s, perm_string::literal(""), pin_count)
{
@@ -426,8 +404,7 @@ const Link& NetDelaySrc::condit_pin() const
NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
: NetObj(s, n, 1), sig_next_(0), sig_prev_(0),
type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE),
signed_(false), isint_(false), discipline_(0), msb_(npins-1), lsb_(0),
dimensions_(0),
signed_(false), isint_(false), msb_(npins-1), lsb_(0), dimensions_(0),
s0_(0), e0_(0), local_flag_(false), eref_count_(0), lref_count_(0)
{
assert(s);
@@ -467,7 +444,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
: NetObj(s, n, 1),
sig_next_(0), sig_prev_(0), type_(t),
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
isint_(false), discipline_(0), msb_(ms), lsb_(ls), dimensions_(0), s0_(0), e0_(0),
isint_(false), msb_(ms), lsb_(ls), dimensions_(0), s0_(0), e0_(0),
local_flag_(false), eref_count_(0), lref_count_(0)
{
assert(s);
@@ -515,7 +492,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
: NetObj(s, n, calculate_count(array_s, array_e)),
sig_next_(0), sig_prev_(0), type_(t), port_type_(NOT_A_PORT),
data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false),
discipline_(0), msb_(ms), lsb_(ls), dimensions_(1), s0_(array_s), e0_(array_e),
msb_(ms), lsb_(ls), dimensions_(1), s0_(array_s), e0_(array_e),
local_flag_(false), eref_count_(0), lref_count_(0)
{
assert(s);
@@ -645,17 +622,6 @@ void NetNet::set_isint(bool flag)
isint_ = flag;
}
discipline_t* NetNet::get_discipline() const
{
return discipline_;
}
void NetNet::set_discipline(discipline_t*dis)
{
ivl_assert(*this, discipline_ == 0);
discipline_ = dis;
}
long NetNet::lsb() const
{
return lsb_;
@@ -883,24 +849,6 @@ const NetScope* NetProcTop::scope() const
return scope_;
}
NetCastInt::NetCastInt(NetScope*scope, perm_string n, unsigned width)
: NetNode(scope, n, 2), width_(width)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("I"), 0);
}
NetCastReal::NetCastReal(NetScope*scope, perm_string n, bool signed_flag)
: NetNode(scope, n, 2), signed_flag_(signed_flag)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("I"), 0);
}
NetConcat::NetConcat(NetScope*scope, perm_string n, unsigned wid, unsigned cnt)
: NetNode(scope, n, cnt+1), width_(wid)
{
@@ -1548,11 +1496,6 @@ NetLiteral::~NetLiteral()
{
}
ivl_variable_type_t NetLiteral::data_type() const
{
return IVL_VT_REAL;
}
const verireal& NetLiteral::value_real() const
{
return real_;
@@ -2609,7 +2552,6 @@ DelayType NetBlock::delay_type() const
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
DelayType dt = cur->delay_type();
if (dt > result) result = dt;
if (dt == DEFINITE_DELAY) break;
}
return result;
@@ -2644,9 +2586,7 @@ DelayType NetCondit::delay_type() const
if (else_) {
result = combine_delays(if_->delay_type(), else_->delay_type());
} else {
/* Because of the indeterminate conditional value the
* best we can have for this case is a possible delay. */
result = combine_delays(if_->delay_type(), NO_DELAY);
result = if_->delay_type();
}
return result;
+18 -159
View File
@@ -29,8 +29,6 @@
# include <map>
# include <list>
# include <vector>
# include <set>
# include <utility>
# include "ivl_target.h"
# include "pform_types.h"
# include "config.h"
@@ -68,8 +66,6 @@ class NetTaskDef;
class NetEvTrig;
class NetEvWait;
class nature_t;
class discipline_t;
struct target;
struct functor_t;
@@ -78,24 +74,6 @@ ostream& operator << (ostream&o, ivl_variable_type_t val);
extern void join_island(NetObj*obj);
class NetPins : public LineInfo {
public:
explicit NetPins(unsigned npins);
virtual ~NetPins();
unsigned pin_count() const { return npins_; }
Link&pin(unsigned idx);
const Link&pin(unsigned idx) const;
void dump_node_pins(ostream&, unsigned) const;
private:
Link*pins_;
const unsigned npins_;
};
/* =========
* A NetObj is anything that has any kind of behavior in the
* netlist. Nodes can be gates, registers, etc. and are linked
@@ -116,7 +94,7 @@ class NetPins : public LineInfo {
* interpretation of the rise/fall/decay times is typically left to
* the target to properly interpret.
*/
class NetObj : public NetPins, public Attrib {
class NetObj : public Attrib, public virtual LineInfo {
public:
public:
@@ -130,6 +108,8 @@ class NetObj : public NetPins, public Attrib {
perm_string name() const { return name_; }
unsigned pin_count() const { return npins_; }
const NetExpr* rise_time() const { return delay1_; }
const NetExpr* fall_time() const { return delay2_; }
const NetExpr* decay_time() const { return delay3_; }
@@ -138,11 +118,17 @@ class NetObj : public NetPins, public Attrib {
void fall_time(const NetExpr* d) { delay2_ = d; }
void decay_time(const NetExpr* d) { delay3_ = d; }
Link&pin(unsigned idx);
const Link&pin(unsigned idx) const;
void dump_node_pins(ostream&, unsigned) const;
void dump_obj_attr(ostream&, unsigned) const;
private:
NetScope*scope_;
perm_string name_;
Link*pins_;
const unsigned npins_;
const NetExpr* delay1_;
const NetExpr* delay2_;
const NetExpr* delay3_;
@@ -162,31 +148,11 @@ class IslandBranch {
struct ivl_island_s* island;
};
/*
* A NetBranch is a construct of Verilog-A that is a branch between
* two nodes. The branch has exactly 2 pins and a discipline.
*
* pin(0) is the source of flow through a branch and the plus side of
* potential. Pin(1) is the sink of flow and the minus (or ground) of
* potential.
*/
class NetBranch : public NetPins {
public:
explicit NetBranch(discipline_t*dis);
explicit NetBranch(discipline_t*dis, perm_string name);
~NetBranch();
private:
discipline_t*discipline_;
perm_string name_;
};
class Link {
friend void connect(Link&, Link&);
friend void connect(Nexus*, Link&);
friend class NetPins;
friend class NetObj;
friend class Nexus;
public:
@@ -220,8 +186,8 @@ class Link {
void set_init(verinum::V val);
verinum::V get_init() const;
void cur_link(NetPins*&net, unsigned &pin);
void cur_link(const NetPins*&net, unsigned &pin) const;
void cur_link(NetObj*&net, unsigned &pin);
void cur_link(const NetObj*&net, unsigned &pin) const;
// Get a pointer to the nexus that represents all the links
// connected to me.
@@ -248,8 +214,8 @@ class Link {
// Return information about the object that this link is
// a part of.
const NetPins*get_obj() const;
NetPins*get_obj();
const NetObj*get_obj() const;
NetObj*get_obj();
unsigned get_pin() const;
// A link of an object (sometimes called a "pin") has a
@@ -262,7 +228,7 @@ class Link {
private:
// The NetNode manages these. They point back to the
// NetNode so that following the links can get me here.
NetPins *node_;
NetObj *node_;
unsigned pin_;
DIR dir_;
@@ -322,10 +288,6 @@ class Nexus {
NetNet* pick_any_net();
/* This method returns true if there are any drivers
(including variables) attached to this nexus. */
bool drivers_present() const;
/* This method returns true if all the possible drivers of
this nexus are constant. It will also return true if there
are no drivers at all. */
@@ -556,10 +518,6 @@ class NetNet : public NetObj {
bool get_isint() const;
void set_isint(bool);
/* Attach a discipline to the net. */
discipline_t* get_discipline() const;
void set_discipline(discipline_t*dis);
/* These methods return the msb and lsb indices for the most
significant and least significant bits. These are signed
longs, and may be different from pin numbers. For example,
@@ -627,7 +585,6 @@ class NetNet : public NetObj {
ivl_variable_type_t data_type_;
bool signed_;
bool isint_; // original type of integer
discipline_t*discipline_;
long msb_, lsb_;
const unsigned dimensions_;
@@ -729,9 +686,6 @@ class NetScope : public Attrib {
unsigned get_def_lineno() const { return def_lineno_; };
bool in_func();
/* Is the task or function automatic. */
void is_auto(bool is_auto) { is_auto_ = is_auto; };
bool is_auto() const { return is_auto_; };
const NetTaskDef* task_def() const;
const NetFuncDef* func_def() const;
@@ -764,13 +718,8 @@ class NetScope : public Attrib {
const hname_t& fullname() const { return name_; }
void run_defparams(class Design*);
void run_defparams_later(class Design*);
void evaluate_parameters(class Design*);
// Look for defparams that never matched, and print warnings.
void residual_defparams(class Design*);
/* This method generates a non-hierarchical name that is
guaranteed to be unique within this scope. */
perm_string local_symbol();
@@ -788,8 +737,7 @@ class NetScope : public Attrib {
assignments from the scope pass to the parameter evaluation
step. After that, it is not used. */
list<pair<pform_name_t,NetExpr*> > defparams;
list<pair<list<hname_t>,NetExpr*> > defparams_later;
map<pform_name_t,NetExpr*>defparams;
public:
struct range_t {
@@ -875,12 +823,11 @@ class NetScope : public Attrib {
NetScope*sub_;
unsigned lcounter_;
bool is_auto_;
};
/*
* This class implements the LPM_ABS component. The node has a single
* input, a signed expression, that it converts to the absolute
* input, a signe expression, that it converts to the absolute
* value. The gate is simple: pin(0) is the output and pin(1) is the input.
*/
class NetAbs : public NetNode {
@@ -969,44 +916,6 @@ class NetArrayDq : public NetNode {
};
/*
* Convert an IVL_VT_REAL input to a logical value with the
* given width. The input is pin(1) and the output is pin(0).
*/
class NetCastInt : public NetNode {
public:
NetCastInt(NetScope*s, perm_string n, unsigned width);
unsigned width() const { return width_; }
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
private:
unsigned width_;
};
/*
* Convert an input to IVL_VT_REAL. The input is pin(1), which can be
* any vector type (VT_BOOL or VT_LOGIC) and the output is pin(0),
* which is IVL_VT_REAL. The conversion interprets the input as an
* unsigned value unless the signed_flag is true.
*/
class NetCastReal : public NetNode {
public:
NetCastReal(NetScope*s, perm_string n, bool signed_flag);
bool signed_flag() const { return signed_flag_; }
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
private:
bool signed_flag_;
};
/*
* This type represents the LPM_CLSHIFT device.
*/
@@ -1470,7 +1379,7 @@ class NetSysFunc : public NetNode {
class NetTran : public NetNode, public IslandBranch {
public:
// Tran devices other than TRAN_VP
// Tran devices other then TRAN_VP
NetTran(NetScope*scope, perm_string n, ivl_switch_type_t type);
// Create a TRAN_VP
NetTran(NetScope*scope, perm_string n, unsigned wid,
@@ -2918,27 +2827,6 @@ class NetEUFunc : public NetExpr {
NetEUFunc& operator= (const NetEUFunc&);
};
/*
* A call to a nature access function for a branch.
*/
class NetEAccess : public NetExpr {
public:
explicit NetEAccess(NetBranch*br, nature_t*nat);
~NetEAccess();
virtual ivl_variable_type_t expr_type() const;
virtual void dump(ostream&) const;
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEAccess*dup_expr() const;
virtual NexusSet* nex_input(bool rem_out = true);
private:
NetBranch*branch_;
nature_t*nature_;
};
/*
* A call to a user defined task is elaborated into this object. This
* contains a pointer to the elaborated task definition, but is a
@@ -3206,7 +3094,6 @@ class NetEBComp : public NetEBinary {
NetEConst* must_be_leeq_(NetExpr*le, const verinum&rv, bool eq_flag);
NetEConst*eval_eqeq_(bool ne_flag);
NetEConst*eval_eqeq_real_(NetExpr*le, NetExpr*ri, bool ne_flag);
NetEConst*eval_less_();
NetEConst*eval_leeq_();
NetEConst*eval_leeq_real_(NetExpr*le, NetExpr*ri, bool eq_flag);
@@ -3505,8 +3392,6 @@ class NetESFunc : public NetExpr {
NetExpr* parm(unsigned idx);
const NetExpr* parm(unsigned idx) const;
virtual NetExpr* eval_tree(int prune_to_width = -1);
virtual ivl_variable_type_t expr_type() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual bool set_width(unsigned, bool last_chance);
@@ -3675,18 +3560,6 @@ class NetESignal : public NetExpr {
NetExpr*word_;
};
/*
* The Design object keeps a list of work items for processing
* elaboration. This is the type of those work items.
*/
struct elaborator_work_item_t {
explicit elaborator_work_item_t(Design*d)
: des(d) { }
virtual ~elaborator_work_item_t() { }
virtual void elaborate_runrun() =0;
protected:
Design*des;
};
/*
* This class contains an entire design. It includes processes and a
@@ -3736,23 +3609,10 @@ class Design {
NetScope* find_scope(NetScope*, const std::list<hname_t>&path,
NetScope::TYPE type = NetScope::MODULE) const;
/* These members help manage elaboration of scopes. When we
get to a point in scope elaboration where we want to put
off a scope elaboration, an object of scope_elaboration_t
is pushed onto the scope_elaborations list. The scope
elaborator will go through this list elaborating scopes
until the list is empty. */
list<elaborator_work_item_t*>elaboration_work_list;
void run_elaboration_work(void);
set<NetScope*> defparams_later;
// PARAMETERS
void run_defparams();
void evaluate_parameters();
// Look for defparams that never matched, and print warnings.
void residual_defparams();
/* This method locates a signal, starting at a given
scope. The name parameter may be partially hierarchical, so
@@ -3774,7 +3634,6 @@ class Design {
// PROCESSES
void add_process(NetProcTop*);
void delete_process(NetProcTop*);
bool check_always_delay() const;
// Iterate over the design...
void dump(ostream&) const;
+24 -92
View File
@@ -76,46 +76,6 @@ NetNet* add_to_net(Design*des, NetNet*sig, long val)
#endif
}
NetNet* cast_to_int(Design*des, NetScope*scope, NetNet*src, unsigned wid)
{
if (src->data_type() != IVL_VT_REAL)
return src;
NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, wid);
tmp->data_type(IVL_VT_LOGIC);
tmp->set_line(*src);
tmp->local_flag(true);
NetCastInt*cast = new NetCastInt(scope, scope->local_symbol(), wid);
cast->set_line(*src);
des->add_node(cast);
connect(cast->pin(0), tmp->pin(0));
connect(cast->pin(1), src->pin(0));
return tmp;
}
NetNet* cast_to_real(Design*des, NetScope*scope, NetNet*src)
{
if (src->data_type() == IVL_VT_REAL)
return src;
NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE);
tmp->data_type(IVL_VT_REAL);
tmp->set_line(*src);
tmp->local_flag(true);
NetCastReal*cast = new NetCastReal(scope, scope->local_symbol(), src->get_signed());
cast->set_line(*src);
des->add_node(cast);
connect(cast->pin(0), tmp->pin(0));
connect(cast->pin(1), src->pin(0));
return tmp;
}
/*
* Add a signed constant to an existing expression. Generate a new
* NetEBAdd node that has the input expression and an expression made
@@ -244,57 +204,6 @@ bool eval_as_double(double&value, NetExpr*expr)
return false;
}
/*
* At the parser level, a name component is a name with a collection
* of expressions. For example foo[N] is the name "foo" and the index
* expression "N". This function takes as input the name component and
* returns the path component name. It will evaluate the index
* expression if it is present.
*/
hname_t eval_path_component(Design*des, NetScope*scope,
const name_component_t&comp)
{
// No index expression, so the path component is an undecorated
// name, for example "foo".
if (comp.index.empty())
return hname_t(comp.name);
// The parser will assure that path components will have only
// one index. For example, foo[N] is one index, foo[n][m] is two.
assert(comp.index.size() == 1);
const index_component_t&index = comp.index.front();
// The parser will assure that path components will have only
// bit select index expressions. For example, "foo[n]" is OK,
// but "foo[n:m]" is not.
assert(index.sel == index_component_t::SEL_BIT);
// Evaluate the bit select to get a number.
NetExpr*tmp = elab_and_eval(des, scope, index.msb, -1);
ivl_assert(*index.msb, tmp);
// Now we should have a constant value for the bit select
// expression, and we can use it to make the final hname_t
// value, for example "foo[5]".
if (NetEConst*ctmp = dynamic_cast<NetEConst*>(tmp)) {
hname_t res(comp.name, ctmp->value().as_long());
delete ctmp;
return res;
}
// Darn, the expression doesn't evaluate to a constant. That's
// an error to be reported. And make up a fake index value to
// return to the caller.
cerr << index.msb->get_fileline() << ": error: "
<< "Scope index expression is not constant: "
<< *index.msb << endl;
des->errors += 1;
delete tmp;
return hname_t (comp.name, 0);
}
std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
const pform_name_t&path)
{
@@ -304,7 +213,30 @@ std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
for (pform_path_it cur = path.begin() ; cur != path.end(); cur++) {
const name_component_t&comp = *cur;
res.push_back( eval_path_component(des,scope,comp) );
if (comp.index.empty()) {
res.push_back(hname_t(comp.name));
continue;
}
assert(comp.index.size() == 1);
const index_component_t&index = comp.index.front();
assert(index.sel == index_component_t::SEL_BIT);
NetExpr*tmp = elab_and_eval(des, scope, index.msb, -1);
ivl_assert(*index.msb, tmp);
if (NetEConst*ctmp = dynamic_cast<NetEConst*>(tmp)) {
res.push_back(hname_t(comp.name, ctmp->value().as_long()));
delete ctmp;
continue;
} else {
cerr << index.msb->get_fileline() << ": error: "
<< "Scope index expression is not constant: "
<< *index.msb << endl;
des->errors += 1;
}
return res;
}
return res;
-17
View File
@@ -64,13 +64,6 @@ extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w);
extern NetNet*pad_to_width_signed(Design*des, NetNet*n, unsigned w);
/*
* Generate the nodes necessary to cast an expression (a net) to a
* real value.
*/
extern NetNet*cast_to_int(Design*des, NetScope*scope, NetNet*src, unsigned wid);
extern NetNet*cast_to_real(Design*des, NetScope*scope, NetNet*src);
/*
* Take the input expression and return a variation that assures that
* the expression is 1-bit wide and logical. This reflects the needs
@@ -152,16 +145,6 @@ void eval_expr(NetExpr*&expr, int prune_width =-1);
bool eval_as_long(long&value, NetExpr*expr);
bool eval_as_double(double&value, NetExpr*expr);
/*
* Evaluate the component of a scope path to get an hname_t value. Do
* the evaluation in the context of the given scope.
*/
extern hname_t eval_path_component(Design*des, NetScope*scope,
const name_component_t&comp);
/*
* Evaluate an entire scope path in the context of the given scope.
*/
extern std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
const pform_name_t&path);
+117 -327
View File
@@ -180,7 +180,6 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
PEventStatement*event_statement;
Statement*statement;
svector<Statement*>*statement_list;
AStatement*astatement;
PTaskFuncArg function_type;
@@ -206,7 +205,7 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
%token K_PSTAR K_STARP
%token K_LOR K_LAND K_NAND K_NOR K_NXOR K_TRIGGER
%token K_abs K_abstol K_access K_acos K_acosh K_asin K_analog K_asinh
%token K_atan K_atanh K_atan2 K_automatic
%token K_atan K_atanh K_atan2
%token K_always K_and K_assign K_begin K_bool K_buf K_bufif0 K_bufif1 K_case
%token K_casex K_casez K_ceil K_cmos K_continuous K_cos K_cosh
%token K_ddt_nature K_deassign K_default K_defparam K_disable K_discrete
@@ -240,7 +239,7 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
%type <flag> from_exclude
%type <number> number
%type <flag> signed_opt udp_reg_opt edge_operator automatic_opt
%type <flag> signed_opt udp_reg_opt edge_operator
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
%type <letter> udp_input_sym udp_output_sym
%type <text> udp_input_list udp_sequ_entry udp_comb_entry
@@ -283,7 +282,6 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
%type <pform_name> hierarchy_identifier
%type <expr> expression expr_primary expr_mintypmax
%type <expr> lpvalue
%type <expr> branch_probe_expression
%type <expr> delay_value delay_value_simple
%type <exprs> delay1 delay3 delay3_opt delay_value_list
%type <exprs> expression_list_with_nuls expression_list_proper
@@ -304,8 +302,6 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
%type <statement> statement statement_or_null
%type <statement_list> statement_list
%type <astatement> analog_statement
%type <letter> spec_polarity
%type <perm_strings> specify_path_identifiers
@@ -355,13 +351,6 @@ number : BASED_NUMBER
based_size = 0; }
;
/* real and realtime are exactly the same so save some code
* with a common matching rule. */
real_or_realtime
: K_real
| K_realtime
;
/* Verilog-2001 supports attribute lists, which can be attached to a
variety of different objects. The syntax inside the (* *) is a
comma separated list of names or names with assigned values. */
@@ -443,7 +432,7 @@ block_item_decl
/* Integer declarations are simpler in that they do not have all the
trappings of a general variable declaration. All of that is
implicit in the "integer" of the declaration. */
implicit in the "integer" of the declaratin. */
| attribute_list_opt K_integer register_variable_list ';'
{ pform_set_reg_integer($3);
@@ -456,7 +445,7 @@ block_item_decl
/* real declarations are fairly simple as there is no range of
signed flag in the declaration. Create the real as a NetNet::REG
with real value. Note that real and realtime are interchangeable
with real value. Note that real and realtime are interchangable
in this context. */
| attribute_list_opt K_real real_variable_list ';'
@@ -862,9 +851,7 @@ event_expression
function name really is a nature attribute identifier. */
branch_probe_expression
: IDENTIFIER '(' IDENTIFIER ',' IDENTIFIER ')'
{ $$ = pform_make_branch_probe_expression(@1, $1, $3, $5); }
| IDENTIFIER '(' IDENTIFIER ')'
{ $$ = pform_make_branch_probe_expression(@1, $1, $3); }
;
expression
@@ -1199,7 +1186,7 @@ expr_primary
}
/* Many of the VAMS built-in functions are available as builtin
functions with $system_function equivalents. */
functions with $system_function equivilents. */
| K_acos '(' expression ')'
{ perm_string tn = perm_string::literal("$acos");
@@ -1508,32 +1495,6 @@ gate_instance
delete rng;
$$ = tmp;
}
| IDENTIFIER '(' error ')'
{ lgate*tmp = new lgate;
tmp->name = $1;
tmp->parms = 0;
tmp->parms_by_name = 0;
tmp->file = @1.text;
tmp->lineno = @1.first_line;
yyerror(@2, "error: Syntax error in instance port "
"expression(s).");
delete[]$1;
$$ = tmp;
}
| IDENTIFIER range '(' error ')'
{ lgate*tmp = new lgate;
tmp->name = $1;
tmp->parms = 0;
tmp->parms_by_name = 0;
tmp->file = @1.text;
tmp->lineno = @1.first_line;
yyerror(@3, "error: Syntax error in instance port "
"expression(s).");
delete[]$1;
$$ = tmp;
}
;
gate_instance_list
@@ -2117,7 +2078,6 @@ module_item
}
| attribute_list_opt K_analog analog_statement
{ pform_make_analog_behavior(@2, AProcess::PR_ALWAYS, $3); }
/* The task declaration rule matches the task declaration
header, then pushes the function scope. This causes the
@@ -2127,41 +2087,41 @@ module_item
statements in the task body. But we continue to accept it as an
extension. */
| K_task automatic_opt IDENTIFIER ';'
| K_task IDENTIFIER ';'
{ assert(current_task == 0);
current_task = pform_push_task_scope($3, $2);
current_task = pform_push_task_scope($2);
FILE_NAME(current_task, @1);
}
task_item_list_opt
statement_or_null
K_endtask
{ current_task->set_ports($6);
current_task->set_statement($7);
{ current_task->set_ports($5);
current_task->set_statement($6);
pform_pop_scope();
current_task = 0;
delete[]$3;
delete[]$2;
}
| K_task automatic_opt IDENTIFIER
| K_task IDENTIFIER
{ assert(current_task == 0);
current_task = pform_push_task_scope($3, $2);
current_task = pform_push_task_scope($2);
FILE_NAME(current_task, @1);
}
'(' task_port_decl_list ')' ';'
block_item_decls_opt
statement_or_null
K_endtask
{ current_task->set_ports($6);
current_task->set_statement($10);
{ current_task->set_ports($5);
current_task->set_statement($9);
pform_pop_scope();
current_task = 0;
delete[]$3;
delete[]$2;
}
| K_task automatic_opt IDENTIFIER error K_endtask
| K_task IDENTIFIER error K_endtask
{
pform_pop_scope();
current_task = 0;
delete[]$3;
delete[]$2;
}
/* The function declaration rule matches the function declaration
@@ -2169,42 +2129,42 @@ module_item
definitions in the func_body to take on the scope of the function
instead of the module. */
| K_function automatic_opt function_range_or_type_opt IDENTIFIER ';'
| K_function function_range_or_type_opt IDENTIFIER ';'
{ assert(current_function == 0);
current_function = pform_push_function_scope($4, $2);
current_function = pform_push_function_scope($3);
FILE_NAME(current_function, @1);
}
function_item_list statement
K_endfunction
{ current_function->set_ports($7);
current_function->set_statement($8);
current_function->set_return($3);
{ current_function->set_ports($6);
current_function->set_statement($7);
current_function->set_return($2);
pform_pop_scope();
current_function = 0;
delete[]$4;
delete[]$3;
}
| K_function automatic_opt function_range_or_type_opt IDENTIFIER
| K_function function_range_or_type_opt IDENTIFIER
{ assert(current_function == 0);
current_function = pform_push_function_scope($4, $2);
current_function = pform_push_function_scope($3);
FILE_NAME(current_function, @1);
}
'(' task_port_decl_list ')' ';'
block_item_decls_opt
statement
K_endfunction
{ current_function->set_ports($7);
current_function->set_statement($11);
current_function->set_return($3);
{ current_function->set_ports($6);
current_function->set_statement($10);
current_function->set_return($2);
pform_pop_scope();
current_function = 0;
delete[]$4;
delete[]$3;
}
| K_function automatic_opt function_range_or_type_opt IDENTIFIER error K_endfunction
| K_function function_range_or_type_opt IDENTIFIER error K_endfunction
{
pform_pop_scope();
current_task = 0;
delete[]$4;
delete[]$3;
}
/* A generate region can contain further module items. Actually, it
@@ -2240,15 +2200,6 @@ module_item
K_endcase
{ pform_endgenerate(); }
/* Handle some anachronistic syntax cases. */
| K_generate K_begin module_item_list_opt K_end K_endgenerate
{ /* Detect and warn about anachronistic begin/end use */
if (generation_flag > GN_VER2001) {
warn_count += 1;
cerr << @2 << ": warning: Anachronistic use of begin/end to surround generate schemes." << endl;
}
}
/* specify blocks are parsed but ignored. */
| K_specify K_endspecify
@@ -2311,11 +2262,6 @@ module_item
{ yyerror(@1, "error: Malformed $attribute parameter list."); }
;
automatic_opt
: K_automatic { $$ = true; }
| { $$ = false;}
;
generate_if : K_if '(' expression ')' { pform_start_generate_if(@1, $3); }
generate_case_items
@@ -2438,14 +2384,7 @@ parameter_assign_decl
param_active_type = IVL_VT_LOGIC;
}
| K_integer
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum(integer_width-1, integer_width));
(*range_stub)[0] = re;
re = new PENumber(new verinum((uint64_t)0, integer_width));
(*range_stub)[1] = re;
/* The default range is [31:0] */
param_active_range = range_stub;
{ param_active_range = 0;
param_active_signed = true;
param_active_type = IVL_VT_LOGIC;
}
@@ -2454,24 +2393,7 @@ parameter_assign_decl
param_active_signed = false;
param_active_type = IVL_VT_LOGIC;
}
| K_time
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum((uint64_t)63, integer_width));
(*range_stub)[0] = re;
re = new PENumber(new verinum((uint64_t)0, integer_width));
(*range_stub)[1] = re;
/* The range is [63:0] */
param_active_range = range_stub;
param_active_signed = false;
param_active_type = IVL_VT_LOGIC;
}
parameter_assign_list
{ param_active_range = 0;
param_active_signed = false;
param_active_type = IVL_VT_LOGIC;
}
| real_or_realtime
| K_real
{ param_active_range = 0;
param_active_signed = true;
param_active_type = IVL_VT_REAL;
@@ -2554,7 +2476,7 @@ localparam_assign_decl
localparam_assign_list
{ param_active_range = 0;
param_active_signed = false;
param_active_type = IVL_VT_LOGIC;
param_active_type = IVL_VT_NO_TYPE;
}
| K_signed range
{ param_active_range = $2;
@@ -2567,14 +2489,7 @@ localparam_assign_decl
param_active_type = IVL_VT_LOGIC;
}
| K_integer
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum(integer_width-1, integer_width));
(*range_stub)[0] = re;
re = new PENumber(new verinum((uint64_t)0, integer_width));
(*range_stub)[1] = re;
/* The default range is [31:0] */
param_active_range = range_stub;
{ param_active_range = 0;
param_active_signed = true;
param_active_type = IVL_VT_LOGIC;
}
@@ -2583,24 +2498,7 @@ localparam_assign_decl
param_active_signed = false;
param_active_type = IVL_VT_LOGIC;
}
| K_time
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum((uint64_t)63, integer_width));
(*range_stub)[0] = re;
re = new PENumber(new verinum((uint64_t)0, integer_width));
(*range_stub)[1] = re;
/* The range is [63:0] */
param_active_range = range_stub;
param_active_signed = false;
param_active_type = IVL_VT_LOGIC;
}
localparam_assign_list
{ param_active_range = 0;
param_active_signed = false;
param_active_type = IVL_VT_LOGIC;
}
| real_or_realtime
| K_real
{ param_active_range = 0;
param_active_signed = true;
param_active_type = IVL_VT_REAL;
@@ -3591,31 +3489,28 @@ statement
FILE_NAME(tmp, @1);
$$ = tmp;
}
| event_control attribute_list_opt statement_or_null
{ PEventStatement*tmp = $1;
if (tmp == 0) {
yyerror(@1, "error: Invalid event control.");
$$ = 0;
} else {
if ($3) pform_bind_attributes($3->attributes,$2);
tmp->set_statement($3);
$$ = tmp;
}
}
| '@' '*' attribute_list_opt statement_or_null
{ PEventStatement*tmp = new PEventStatement;
FILE_NAME(tmp, @1);
if ($4) pform_bind_attributes($4->attributes,$3);
tmp->set_statement($4);
$$ = tmp;
}
| '@' '(' '*' ')' attribute_list_opt statement_or_null
{ PEventStatement*tmp = new PEventStatement;
FILE_NAME(tmp, @1);
if ($6) pform_bind_attributes($6->attributes,$5);
tmp->set_statement($6);
$$ = tmp;
}
| event_control statement_or_null
{ PEventStatement*tmp = $1;
if (tmp == 0) {
yyerror(@1, "error: Invalid event control.");
$$ = 0;
} else {
tmp->set_statement($2);
$$ = tmp;
}
}
| '@' '*' statement_or_null
{ PEventStatement*tmp = new PEventStatement;
FILE_NAME(tmp, @1);
tmp->set_statement($3);
$$ = tmp;
}
| '@' '(' '*' ')' statement_or_null
{ PEventStatement*tmp = new PEventStatement;
FILE_NAME(tmp, @1);
tmp->set_statement($5);
$$ = tmp;
}
| lpvalue '=' expression ';'
{ PAssign*tmp = new PAssign($1,$3);
FILE_NAME(tmp, @1);
@@ -3651,23 +3546,28 @@ statement
$$ = tmp;
}
| lpvalue '=' event_control expression ';'
{ PAssign*tmp = new PAssign($1,0,$3,$4);
{ PAssign*tmp = new PAssign($1,$3,$4);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue '=' K_repeat '(' expression ')' event_control expression ';'
{ PAssign*tmp = new PAssign($1,$5,$7,$8);
{ PAssign*tmp = new PAssign($1,$7,$8);
FILE_NAME(tmp,@1);
tmp->set_lineno(@1.first_line);
yyerror(@3, "sorry: repeat event control not supported.");
delete $5;
$$ = tmp;
}
| lpvalue K_LE event_control expression ';'
{ PAssignNB*tmp = new PAssignNB($1,0,$3,$4);
{ yyerror(@1, "sorry: Event controls not supported here.");
PAssignNB*tmp = new PAssignNB($1,$4);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_LE K_repeat '(' expression ')' event_control expression ';'
{ PAssignNB*tmp = new PAssignNB($1,$5,$7,$8);
{ yyerror(@1, "sorry: Event controls not supported here.");
delete $5;
PAssignNB*tmp = new PAssignNB($1,$8);
FILE_NAME(tmp, @1);
$$ = tmp;
}
@@ -3740,15 +3640,14 @@ statement_list
;
statement_or_null
: statement
{ $$ = $1; }
| ';'
{ $$ = 0; }
;
: statement
| ';' { $$ = 0; }
;
analog_statement
: branch_probe_expression K_CONTRIBUTE expression ';'
{ $$ = pform_contribution_statement(@2, $1, $3); }
{ yyerror(@1, "sorry: Analog contribution statements not supported."); }
;
/* Task items are, other than the statement, task port items and
@@ -3758,43 +3657,39 @@ task_item
| task_port_item { $$ = $1; }
;
reg_opt
: K_reg
|
;
task_port_item
: K_input reg_opt signed_opt range_opt list_of_identifiers ';'
: K_input signed_opt range_opt list_of_identifiers ';'
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT,
IVL_VT_NO_TYPE, $3,
$4, $5,
IVL_VT_NO_TYPE, $2,
$3, $4,
@1.text, @1.first_line);
$$ = tmp;
}
| K_output reg_opt signed_opt range_opt list_of_identifiers ';'
| K_output signed_opt range_opt list_of_identifiers ';'
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::POUTPUT,
IVL_VT_LOGIC, $3,
$4, $5,
IVL_VT_LOGIC, $2,
$3, $4,
@1.text, @1.first_line);
$$ = tmp;
}
| K_inout reg_opt signed_opt range_opt list_of_identifiers ';'
| K_inout signed_opt range_opt list_of_identifiers ';'
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINOUT,
IVL_VT_LOGIC, $3,
$4, $5,
IVL_VT_LOGIC, $2,
$3, $4,
@1.text, @1.first_line);
$$ = tmp;
}
/* When the port is an integer, infer a signed vector of the integer
shape. Generate a range ([31:0]) to make it work. */
shape. Generate a range to make it work. */
| K_input K_integer list_of_identifiers ';'
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
{ svector<PExpr*>*range_stub
= new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum(integer_width-1,
integer_width));
@@ -3809,7 +3704,8 @@ task_port_item
$$ = tmp;
}
| K_output K_integer list_of_identifiers ';'
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
{ svector<PExpr*>*range_stub
= new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum(integer_width-1,
integer_width));
@@ -3824,7 +3720,8 @@ task_port_item
$$ = tmp;
}
| K_inout K_integer list_of_identifiers ';'
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
{ svector<PExpr*>*range_stub
= new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum(integer_width-1,
integer_width));
@@ -3839,54 +3736,9 @@ task_port_item
$$ = tmp;
}
/* Ports can be time with a width of [63:0] (unsigned). */
/* Ports can be real. */
| K_input K_time list_of_identifiers ';'
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum((uint64_t)63, integer_width));
(*range_stub)[0] = re;
re = new PENumber(new verinum((uint64_t)0, integer_width));
(*range_stub)[1] = re;
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT,
IVL_VT_LOGIC, false,
range_stub, $3,
@1.text, @1.first_line);
$$ = tmp;
}
| K_output K_time list_of_identifiers ';'
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum((uint64_t)63, integer_width));
(*range_stub)[0] = re;
re = new PENumber(new verinum((uint64_t)0, integer_width));
(*range_stub)[1] = re;
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::POUTPUT,
IVL_VT_LOGIC, false,
range_stub, $3,
@1.text, @1.first_line);
$$ = tmp;
}
| K_inout K_time list_of_identifiers ';'
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum((uint64_t)63, integer_width));
(*range_stub)[0] = re;
re = new PENumber(new verinum((uint64_t)0, integer_width));
(*range_stub)[1] = re;
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINOUT,
IVL_VT_LOGIC, false,
range_stub, $3,
@1.text, @1.first_line);
$$ = tmp;
}
/* Ports can be real or realtime. */
| K_input real_or_realtime list_of_identifiers ';'
| K_input K_real list_of_identifiers ';'
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT,
IVL_VT_REAL, false,
@@ -3894,7 +3746,7 @@ task_port_item
@1.text, @1.first_line);
$$ = tmp;
}
| K_output real_or_realtime list_of_identifiers ';'
| K_output K_real list_of_identifiers ';'
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::POUTPUT,
IVL_VT_REAL, true,
@@ -3902,7 +3754,7 @@ task_port_item
@1.text, @1.first_line);
$$ = tmp;
}
| K_inout real_or_realtime list_of_identifiers ';'
| K_inout K_real list_of_identifiers ';'
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINOUT,
IVL_VT_REAL, true,
@@ -3932,51 +3784,50 @@ task_item_list_opt
task_port_decl
: K_input reg_opt signed_opt range_opt IDENTIFIER
: K_input signed_opt range_opt IDENTIFIER
{ port_declaration_context.port_type = NetNet::PINPUT;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = $3;
port_declaration_context.sign_flag = $2;
delete port_declaration_context.range;
port_declaration_context.range = copy_range($4);
port_declaration_context.range = copy_range($3);
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT,
IVL_VT_LOGIC, $3,
$4, list_from_identifier($5),
IVL_VT_LOGIC, $2,
$3, list_from_identifier($4),
@1.text, @1.first_line);
$$ = tmp;
}
| K_output reg_opt signed_opt range_opt IDENTIFIER
| K_output signed_opt range_opt IDENTIFIER
{ port_declaration_context.port_type = NetNet::POUTPUT;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = $3;
port_declaration_context.sign_flag = $2;
delete port_declaration_context.range;
port_declaration_context.range = copy_range($4);
port_declaration_context.range = copy_range($3);
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::POUTPUT,
IVL_VT_LOGIC, $3,
$4, list_from_identifier($5),
IVL_VT_LOGIC, $2,
$3, list_from_identifier($4),
@1.text, @1.first_line);
$$ = tmp;
}
| K_inout reg_opt signed_opt range_opt IDENTIFIER
| K_inout signed_opt range_opt IDENTIFIER
{ port_declaration_context.port_type = NetNet::PINOUT;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = $3;
port_declaration_context.sign_flag = $2;
delete port_declaration_context.range;
port_declaration_context.range = copy_range($4);
port_declaration_context.range = copy_range($3);
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINOUT,
IVL_VT_LOGIC, $3,
$4, list_from_identifier($5),
IVL_VT_LOGIC, $2,
$3, list_from_identifier($4),
@1.text, @1.first_line);
$$ = tmp;
}
/* Ports can be integer with a width of [31:0]. */
| K_input K_integer IDENTIFIER
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
{ svector<PExpr*>*range_stub
= new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum(integer_width-1,
integer_width));
@@ -3997,7 +3848,8 @@ task_port_decl
$$ = tmp;
}
| K_output K_integer IDENTIFIER
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
{ svector<PExpr*>*range_stub
= new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum(integer_width-1,
integer_width));
@@ -4018,7 +3870,8 @@ task_port_decl
$$ = tmp;
}
| K_inout K_integer IDENTIFIER
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
{ svector<PExpr*>*range_stub
= new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum(integer_width-1,
integer_width));
@@ -4039,72 +3892,9 @@ task_port_decl
$$ = tmp;
}
/* Ports can be time with a width of [63:0] (unsigned). */
/* Ports can be real. */
| K_input K_time IDENTIFIER
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum((uint64_t)63, integer_width));
(*range_stub)[0] = re;
re = new PENumber(new verinum((uint64_t)0, integer_width));
(*range_stub)[1] = re;
port_declaration_context.port_type = NetNet::PINPUT;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = false;
delete port_declaration_context.range;
port_declaration_context.range = copy_range(range_stub);
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT,
IVL_VT_LOGIC, false,
range_stub,
list_from_identifier($3),
@1.text, @1.first_line);
$$ = tmp;
}
| K_output K_time IDENTIFIER
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum((uint64_t)63, integer_width));
(*range_stub)[0] = re;
re = new PENumber(new verinum((uint64_t)0, integer_width));
(*range_stub)[1] = re;
port_declaration_context.port_type = NetNet::POUTPUT;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = false;
delete port_declaration_context.range;
port_declaration_context.range = copy_range(range_stub);
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::POUTPUT,
IVL_VT_LOGIC, false,
range_stub,
list_from_identifier($3),
@1.text, @1.first_line);
$$ = tmp;
}
| K_inout K_time IDENTIFIER
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum((uint64_t)63, integer_width));
(*range_stub)[0] = re;
re = new PENumber(new verinum((uint64_t)0, integer_width));
(*range_stub)[1] = re;
port_declaration_context.port_type = NetNet::PINOUT;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = false;
delete port_declaration_context.range;
port_declaration_context.range = copy_range(range_stub);
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINOUT,
IVL_VT_LOGIC, false,
range_stub,
list_from_identifier($3),
@1.text, @1.first_line);
$$ = tmp;
}
/* Ports can be real or realtime. */
| K_input real_or_realtime IDENTIFIER
| K_input K_real IDENTIFIER
{ port_declaration_context.port_type = NetNet::PINPUT;
port_declaration_context.var_type = IVL_VT_REAL;
port_declaration_context.sign_flag = false;
@@ -4117,7 +3907,7 @@ task_port_decl
@1.text, @1.first_line);
$$ = tmp;
}
| K_output real_or_realtime IDENTIFIER
| K_output K_real IDENTIFIER
{ port_declaration_context.port_type = NetNet::POUTPUT;
port_declaration_context.var_type = IVL_VT_REAL;
port_declaration_context.sign_flag = false;
@@ -4130,7 +3920,7 @@ task_port_decl
@1.text, @1.first_line);
$$ = tmp;
}
| K_inout real_or_realtime IDENTIFIER
| K_inout K_real IDENTIFIER
{ port_declaration_context.port_type = NetNet::PINOUT;
port_declaration_context.var_type = IVL_VT_REAL;
port_declaration_context.sign_flag = false;
+8 -11
View File
@@ -30,15 +30,6 @@ unsigned error_count = 0;
unsigned warn_count = 0;
unsigned long based_size = 0;
std::ostream& operator << (std::ostream&o, const YYLTYPE&loc)
{
if (loc.text)
o << loc.text << ":";
o << loc.first_line;
return o;
}
void VLerror(const char*msg)
{
error_count += 1;
@@ -48,14 +39,20 @@ void VLerror(const char*msg)
void VLerror(const YYLTYPE&loc, const char*msg)
{
error_count += 1;
cerr << loc << ": " << msg << endl;
if (loc.text)
cerr << loc.text << ":";
cerr << loc.first_line << ": " << msg << endl;
based_size = 0; /* Clear the base information if we have an error. */
}
void yywarn(const YYLTYPE&loc, const char*msg)
{
warn_count += 1;
cerr << loc << ": warning: " << msg << endl;
if (loc.text)
cerr << loc.text << ":";
cerr << loc.first_line << ": warning: " << msg << endl;
}
int VLwrap()
-3
View File
@@ -23,7 +23,6 @@
#endif
# include <list>
# include <ostream>
# include "compiler.h"
# include "pform.h"
@@ -63,8 +62,6 @@ extern void VLerror(const YYLTYPE&loc, const char*msg);
#define yywarn VLwarn
extern void VLwarn(const YYLTYPE&loc, const char*msg);
extern ostream& operator << (ostream&, const YYLTYPE&loc);
extern unsigned error_count, warn_count;
extern unsigned long based_size;
+51 -112
View File
@@ -93,83 +93,44 @@ static PScope* lexical_scope = 0;
void pform_pop_scope()
{
if (pform_cur_generate) {
assert(pform_cur_generate->lexical_scope);
PScope*cur = pform_cur_generate->lexical_scope;
pform_cur_generate->lexical_scope = cur->pscope_parent();
} else {
assert(lexical_scope);
lexical_scope = lexical_scope->pscope_parent();
}
lexical_scope = lexical_scope->pscope_parent();
}
PTask* pform_push_task_scope(char*name, bool is_auto)
PTask* pform_push_task_scope(char*name)
{
perm_string task_name = lex_strings.make(name);
PTask*task = new PTask(task_name, pform_cur_module);
PTask*task;
if (pform_cur_generate) {
task = new PTask(task_name, pform_cur_generate->lexical_scope,
is_auto);
pform_cur_generate->tasks[task->pscope_name()] = task;
pform_cur_generate->lexical_scope = task;
} else {
task = new PTask(task_name, lexical_scope, is_auto);
pform_cur_module->tasks[task->pscope_name()] = task;
lexical_scope = task;
}
// Add the task to the current module
pform_cur_module->add_task(task->pscope_name(), task);
// Make this the current lexical scope
lexical_scope = task;
return task;
}
PFunction* pform_push_function_scope(char*name, bool is_auto)
PFunction* pform_push_function_scope(char*name)
{
perm_string func_name = lex_strings.make(name);
PFunction*func = new PFunction(func_name, lexical_scope);
PFunction*func;
if (pform_cur_generate) {
func = new PFunction(func_name, pform_cur_generate->lexical_scope,
is_auto);
pform_cur_generate->funcs[func->pscope_name()] = func;
pform_cur_generate->lexical_scope = func;
} else {
func = new PFunction(func_name, lexical_scope, is_auto);
pform_cur_module->funcs[func->pscope_name()] = func;
lexical_scope = func;
}
// Add the task to the current module
pform_cur_module->add_function(func->pscope_name(), func);
// Make this the current lexical scope
lexical_scope = func;
return func;
}
PBlock* pform_push_block_scope(char*name, PBlock::BL_TYPE bt)
{
perm_string block_name = lex_strings.make(name);
PBlock*block = new PBlock(block_name, lexical_scope, bt);
PBlock*block;
if (pform_cur_generate) {
block = new PBlock(block_name, pform_cur_generate->lexical_scope, bt);
pform_cur_generate->lexical_scope = block;
} else {
block = new PBlock(block_name, lexical_scope, bt);
lexical_scope = block;
}
// Make this the current lexical scope
lexical_scope = block;
return block;
}
void pform_bind_attributes(map<perm_string,PExpr*>&attributes,
svector<named_pexpr_t*>*attr)
{
if (attr == 0)
return;
for (unsigned idx = 0 ; idx < attr->count() ; idx += 1) {
named_pexpr_t*tmp = (*attr)[idx];
attributes[tmp->name] = tmp->parm;
}
delete attr;
}
PWire*pform_get_wire_in_scope(perm_string name)
{
/* Note that if we are processing a generate, then the
@@ -177,45 +138,9 @@ PWire*pform_get_wire_in_scope(perm_string name)
cannot be within sub-scopes. Only directly in
modules. */
if (pform_cur_generate)
if (pform_cur_generate->lexical_scope)
return pform_cur_generate->lexical_scope->wires_find(name);
else
return pform_cur_generate->wires_find(name);
else
return lexical_scope->wires_find(name);
}
return pform_cur_generate->get_wire(name);
static void pform_put_wire_in_scope(perm_string name, PWire*net)
{
if (pform_cur_generate)
if (pform_cur_generate->lexical_scope)
pform_cur_generate->lexical_scope->wires[name] = net;
else
pform_cur_generate->wires[name] = net;
else
lexical_scope->wires[name] = net;
}
static void pform_put_behavior_in_scope(PProcess*pp)
{
if (pform_cur_generate)
if (pform_cur_generate->lexical_scope)
pform_cur_generate->lexical_scope->behaviors.push_back(pp);
else
pform_cur_generate->behaviors.push_back(pp);
else
lexical_scope->behaviors.push_back(pp);
}
void pform_put_behavior_in_scope(AProcess*pp)
{
if (pform_cur_generate)
if (pform_cur_generate->lexical_scope)
pform_cur_generate->lexical_scope->analog_behaviors.push_back(pp);
else
pform_cur_generate->analog_behaviors.push_back(pp);
else
lexical_scope->analog_behaviors.push_back(pp);
return lexical_scope->wires_find(name);
}
void pform_set_default_nettype(NetNet::Type type,
@@ -583,7 +508,7 @@ void pform_endgenerate()
if (pform_cur_generate != 0) {
assert(cur->scheme_type == PGenerate::GS_CASE_ITEM
|| pform_cur_generate->scheme_type != PGenerate::GS_CASE);
pform_cur_generate->generate_schemes.push_back(cur);
pform_cur_generate->generates.push_back(cur);
} else {
assert(cur->scheme_type != PGenerate::GS_CASE_ITEM);
pform_cur_module->generate_schemes.push_back(cur);
@@ -1311,7 +1236,7 @@ void pform_make_pgassign_list(svector<PExpr*>*alist,
void pform_make_reginit(const struct vlltype&li,
perm_string name, PExpr*expr)
{
PWire*cur = pform_get_wire_in_scope(name);
PWire*cur = lexical_scope->wires_find(name);
if (cur == 0) {
VLerror(li, "internal error: reginit to non-register?");
delete expr;
@@ -1325,7 +1250,7 @@ void pform_make_reginit(const struct vlltype&li,
PProcess*top = new PProcess(PProcess::PR_INITIAL, ass);
FILE_NAME(top, li);
pform_put_behavior_in_scope(top);
lexical_scope->behaviors.push_back(top);
}
/*
@@ -1346,7 +1271,7 @@ void pform_module_define_port(const struct vlltype&li,
svector<PExpr*>*range,
svector<named_pexpr_t*>*attr)
{
PWire*cur = pform_get_wire_in_scope(name);
PWire*cur = lexical_scope->wires_find(name);
if (cur) {
ostringstream msg;
msg << name << " definition conflicts with "
@@ -1380,7 +1305,7 @@ void pform_module_define_port(const struct vlltype&li,
cur->attributes[tmp->name] = tmp->parm;
}
}
pform_put_wire_in_scope(name, cur);
lexical_scope->wires[name] = cur;
}
/*
@@ -1463,8 +1388,12 @@ void pform_makewire(const vlltype&li, perm_string name,
}
}
if (new_wire_flag)
pform_put_wire_in_scope(name, cur);
if (new_wire_flag) {
if (pform_cur_generate)
pform_cur_generate->wires[name] = cur;
else
lexical_scope->wires[name] = cur;
}
}
/*
@@ -1540,11 +1469,11 @@ void pform_makewire(const vlltype&li,
void pform_set_port_type(perm_string name, NetNet::PortType pt,
const char*file, unsigned lineno)
{
PWire*cur = pform_get_wire_in_scope(name);
PWire*cur = lexical_scope->wires_find(name);
if (cur == 0) {
cur = new PWire(name, NetNet::IMPLICIT, NetNet::PIMPLICIT, IVL_VT_NO_TYPE);
FILE_NAME(cur, file, lineno);
pform_put_wire_in_scope(name, cur);
lexical_scope->wires[name] = cur;
}
switch (cur->get_port_type()) {
@@ -1626,13 +1555,13 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
/* Look for a preexisting wire. If it exists, set the
port direction. If not, create it. */
PWire*curw = pform_get_wire_in_scope(name);
PWire*curw = lexical_scope->wires_find(name);
if (curw) {
curw->set_port_type(pt);
} else {
curw = new PWire(name, NetNet::IMPLICIT_REG, pt, vtype);
FILE_NAME(curw, file, lineno);
pform_put_wire_in_scope(name, curw);
lexical_scope->wires[name] = curw;
}
curw->set_signed(signed_flag);
@@ -1693,7 +1622,7 @@ void pform_set_reg_idx(perm_string name, PExpr*l, PExpr*r)
{
PWire*cur = 0;
if (pform_cur_generate) {
cur = pform_cur_generate->wires_find(name);
cur = pform_cur_generate->get_wire(name);
} else {
cur = lexical_scope->wires_find(name);
}
@@ -1786,7 +1715,7 @@ void pform_set_specparam(perm_string name, PExpr*expr)
void pform_set_defparam(const pform_name_t&name, PExpr*expr)
{
assert(expr);
pform_cur_module->defparms.push_back(make_pair(name,expr));
pform_cur_module->defparms[name] = expr;
}
/*
@@ -1876,13 +1805,13 @@ void pform_set_port_type(const struct vlltype&li,
static void pform_set_reg_integer(perm_string name)
{
PWire*cur = pform_get_wire_in_scope(name);
PWire*cur = lexical_scope->wires_find(name);
if (cur == 0) {
cur = new PWire(name, NetNet::INTEGER,
NetNet::NOT_A_PORT,
IVL_VT_LOGIC);
cur->set_signed(true);
pform_put_wire_in_scope(name, cur);
lexical_scope->wires[name] = cur;
} else {
bool rc = cur->set_wire_type(NetNet::INTEGER);
assert(rc);
@@ -1910,10 +1839,10 @@ void pform_set_reg_integer(list<perm_string>*names)
static void pform_set_reg_time(perm_string name)
{
PWire*cur = pform_get_wire_in_scope(name);
PWire*cur = lexical_scope->wires_find(name);
if (cur == 0) {
cur = new PWire(name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_LOGIC);
pform_put_wire_in_scope(name, cur);
lexical_scope->wires[name] = cur;
} else {
bool rc = cur->set_wire_type(NetNet::REG);
assert(rc);
@@ -1964,9 +1893,19 @@ PProcess* pform_make_behavior(PProcess::Type type, Statement*st,
{
PProcess*pp = new PProcess(type, st);
pform_bind_attributes(pp->attributes, attr);
if (attr) {
for (unsigned idx = 0 ; idx < attr->count() ; idx += 1) {
named_pexpr_t*tmp = (*attr)[idx];
pp->attributes[tmp->name] = tmp->parm;
}
delete attr;
}
if (pform_cur_generate)
pform_cur_generate->add_behavior(pp);
else
pform_cur_module->behaviors.push_back(pp);
pform_put_behavior_in_scope(pp);
return pp;
}
+2 -21
View File
@@ -24,7 +24,6 @@
# include "named.h"
# include "Module.h"
# include "Statement.h"
# include "AStatement.h"
# include "PGate.h"
# include "PExpr.h"
# include "PTask.h"
@@ -117,10 +116,6 @@ struct lgate {
unsigned lineno;
};
/* Use this function to transform the parted form of the attribute
list to the attribute map that is used later. */
extern void pform_bind_attributes(map<perm_string,PExpr*>&attributes,
svector<named_pexpr_t*>*attr);
/* The lexor calls this function to change the default nettype. */
extern void pform_set_default_nettype(NetNet::Type net,
@@ -180,11 +175,10 @@ extern void pform_make_udp(perm_string name,
*/
extern void pform_pop_scope();
extern PTask*pform_push_task_scope(char*name, bool is_auto);
extern PFunction*pform_push_function_scope(char*name, bool is_auto);
extern PTask*pform_push_task_scope(char*name);
extern PFunction*pform_push_function_scope(char*name);
extern PBlock*pform_push_block_scope(char*name, PBlock::BL_TYPE tt);
extern void pform_put_behavior_in_scope(AProcess*proc);
extern verinum* pform_verinum_with_size(verinum*s, verinum*val,
const char*file, unsigned lineno);
@@ -395,17 +389,4 @@ extern void pform_attach_discipline(const struct vlltype&loc,
extern void pform_dump(ostream&out, const nature_t*);
extern void pform_dump(ostream&out, const discipline_t*);
/* ** pform_analog.cc
*/
extern void pform_make_analog_behavior(const struct vlltype&loc,
AProcess::Type type, AStatement*st);
extern AStatement*pform_contribution_statement(const struct vlltype&loc,
PExpr*lval, PExpr*rval);
extern PExpr* pform_make_branch_probe_expression(const struct vlltype&loc,
char*name, char*n1, char*n2);
extern PExpr* pform_make_branch_probe_expression(const struct vlltype&loc,
char*name, char*branch);
#endif
-69
View File
@@ -1,69 +0,0 @@
/*
* Copyright (c) 2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "config.h"
# include "compiler.h"
# include "pform.h"
# include "parse_misc.h"
# include "AStatement.h"
AStatement* pform_contribution_statement(const struct vlltype&loc,
PExpr*lval, PExpr*rval)
{
AContrib*tmp = new AContrib(lval, rval);
FILE_NAME(tmp, loc);
return tmp;
}
void pform_make_analog_behavior(const struct vlltype&loc, AProcess::Type pt,
AStatement*statement)
{
AProcess*proc = new AProcess(pt, statement);
FILE_NAME(proc, loc);
pform_put_behavior_in_scope(proc);
}
PExpr* pform_make_branch_probe_expression(const struct vlltype&loc,
char*name, char*n1, char*n2)
{
vector<PExpr*> parms (2);
parms[0] = new PEIdent(lex_strings.make(n1));
FILE_NAME(parms[0], loc);
parms[1] = new PEIdent(lex_strings.make(n2));
FILE_NAME(parms[1], loc);
PECallFunction*res = new PECallFunction(lex_strings.make(name), parms);
FILE_NAME(res, loc);
return res;
}
PExpr* pform_make_branch_probe_expression(const struct vlltype&loc,
char*name, char*branch_name)
{
vector<PExpr*> parms (1);
parms[0] = new PEIdent(lex_strings.make(branch_name));
FILE_NAME(parms[0], loc);
PECallFunction*res = new PECallFunction(lex_strings.make(name), parms);
FILE_NAME(res, loc);
return res;
}
+1 -18
View File
@@ -25,7 +25,6 @@
map<perm_string,nature_t*> natures;
map<perm_string,discipline_t*> disciplines;
map<perm_string,nature_t*> access_function_nature;
static perm_string nature_name = perm_string::perm_string();
static perm_string nature_access = perm_string::perm_string();
@@ -63,24 +62,9 @@ void pform_end_nature(const struct vlltype&loc)
}
nature_t*tmp = new nature_t(nature_name, nature_access);
FILE_NAME(tmp, loc);
natures[nature_name] = tmp;
// Make sure the access function is not used by multiple
// different natures.
if (nature_t*dup_access_nat = access_function_nature[nature_access]) {
cerr << tmp->get_fileline() << ": error: "
<< "Access function name " << nature_access
<< " is already used by nature " << dup_access_nat->name()
<< " declared at " << dup_access_nat->get_fileline()
<< "." << endl;
error_count += 1;
}
// Map the access functio back to the nature so that
// expressions that use the access function can find it.
access_function_nature[nature_access] = tmp;
FILE_NAME(tmp, loc);
nature_name = perm_string::perm_string();
nature_access = perm_string::perm_string();
@@ -205,7 +189,6 @@ void pform_attach_discipline(const struct vlltype&loc,
error_count += 1;
} else {
cur_net->set_data_type(IVL_VT_REAL);
cur_net->set_discipline(discipline);
}
}
+30 -112
View File
@@ -40,12 +40,6 @@ ostream& operator << (ostream&out, const PExpr&obj)
return out;
}
ostream& operator << (ostream&out, const PEventStatement&obj)
{
obj.dump_inline(out);
return out;
}
ostream& operator << (ostream&o, const PDelays&d)
{
d.dump_delays(o);
@@ -155,21 +149,6 @@ std::ostream& operator << (std::ostream&out, ddomain_t dom)
return out;
}
static void dump_attributes_map(ostream&out,
const map<perm_string,PExpr*>&attributes,
int ind)
{
for (map<perm_string,PExpr*>::const_iterator idx = attributes.begin()
; idx != attributes.end() ; idx++ ) {
out << setw(ind) << "" << "(* " << (*idx).first;
if ((*idx).second) {
out << " = " << *(*idx).second;
}
out << " *)" << endl;
}
}
void PExpr::dump(ostream&out) const
{
out << typeid(*this).name();
@@ -201,9 +180,9 @@ void PECallFunction::dump(ostream &out) const
{
out << path_ << "(";
if (parms_.size() > 0) {
if (parms_.count() > 0) {
if (parms_[0]) parms_[0]->dump(out);
for (unsigned idx = 1; idx < parms_.size(); ++idx) {
for (unsigned idx = 1; idx < parms_.count(); ++idx) {
out << ", ";
if (parms_[idx]) parms_[idx]->dump(out);
}
@@ -301,9 +280,6 @@ void PEBinary::dump(ostream&out) const
case 'N':
out << "!==";
break;
case 'p':
out << "**";
break;
case 'R':
out << ">>>";
break;
@@ -375,7 +351,14 @@ void PWire::dump(ostream&out, unsigned ind) const
}
out << ";" << endl;
dump_attributes_map(out, attributes, 8);
for (map<perm_string,PExpr*>::const_iterator idx = attributes.begin()
; idx != attributes.end()
; idx ++) {
out << " " << (*idx).first;
if ((*idx).second)
out << " = " << *(*idx).second;
out << endl;
}
}
void PGate::dump_pins(ostream&out) const
@@ -546,43 +529,20 @@ void Statement::dump(ostream&out, unsigned ind) const
out << setw(ind) << "";
out << "/* " << get_fileline() << ": " << typeid(*this).name()
<< " */ ;" << endl;
dump_attributes_map(out, attributes, ind+2);
}
void AStatement::dump(ostream&out, unsigned ind) const
{
/* I give up. I don't know what type this statement is,
so just print the C++ typeid and let the user figure
it out. */
out << setw(ind) << "";
out << "/* " << get_fileline() << ": " << typeid(*this).name()
<< " */ ;" << endl;
}
void AContrib::dump(ostream&out, unsigned ind) const
{
out << setw(ind) << "";
out << *lval_ << " <+ " << *rval_
<< "; /* " << get_fileline() << " */"
<< endl;
}
void PAssign::dump(ostream&out, unsigned ind) const
{
out << setw(ind) << "" << *lval() << " = ";
if (delay_) out << "#" << *delay_ << " ";
if (count_) out << "repeat(" << *count_ << ") ";
if (event_) out << *event_ << " ";
out << *rval() << ";" << " /* " << get_fileline() << " */" << endl;
out << setw(ind) << "";
out << *lval() << " = " << delay_ << " " << *rval() << ";";
out << " /* " << get_fileline() << " */" << endl;
}
void PAssignNB::dump(ostream&out, unsigned ind) const
{
out << setw(ind) << "" << *lval() << " <= ";
if (delay_) out << "#" << *delay_ << " ";
if (count_) out << "repeat(" << *count_ << ") ";
if (event_) out << *event_ << " ";
out << *rval() << ";" << " /* " << get_fileline() << " */" << endl;
out << setw(ind) << "";
out << *lval() << " <= " << delay_ << " " << *rval() << ";";
out << " /* " << get_fileline() << " */" << endl;
}
void PBlock::dump(ostream&out, unsigned ind) const
@@ -640,7 +600,6 @@ void PCase::dump(ostream&out, unsigned ind) const
break;
}
out << " (" << *expr_ << ") /* " << get_fileline() << " */" << endl;
dump_attributes_map(out, attributes, ind+2);
for (unsigned idx = 0 ; idx < items_->count() ; idx += 1) {
PCase::Item*cur = (*items_)[idx];
@@ -733,23 +692,6 @@ void PEventStatement::dump(ostream&out, unsigned ind) const
}
}
void PEventStatement::dump_inline(ostream&out) const
{
assert(statement_ == 0);
if (expr_.count() == 0) {
out << "@* ";
} else {
out << "@(" << *(expr_[0]);
if (expr_.count() > 1)
for (unsigned idx = 1 ; idx < expr_.count() ; idx += 1)
out << " or " << *(expr_[idx]);
out << ")";
}
}
void PForce::dump(ostream&out, unsigned ind) const
{
out << setw(ind) << "" << "force " << *lval_ << " = " << *expr_
@@ -773,7 +715,6 @@ void PForStatement::dump(ostream&out, unsigned ind) const
void PFunction::dump(ostream&out, unsigned ind) const
{
out << setw(ind) << "" << "function ";
if (is_auto_) cout << "automatic ";
switch (return_type_.type) {
case PTF_NONE:
out << "?none? ";
@@ -834,9 +775,6 @@ void PRepeat::dump(ostream&out, unsigned ind) const
void PTask::dump(ostream&out, unsigned ind) const
{
out << setw(ind) << "" << "task ";
if (is_auto_) cout << "automatic ";
out << pscope_name() << ";" << endl;
if (ports_)
for (unsigned idx = 0 ; idx < ports_->count() ; idx += 1) {
out << setw(ind) << "";
@@ -889,26 +827,16 @@ void PProcess::dump(ostream&out, unsigned ind) const
out << " /* " << get_fileline() << " */" << endl;
dump_attributes_map(out, attributes, ind+2);
for (map<perm_string,PExpr*>::const_iterator idx = attributes.begin()
; idx != attributes.end() ; idx++ ) {
statement_->dump(out, ind+2);
}
void AProcess::dump(ostream&out, unsigned ind) const
{
switch (type_) {
case AProcess::PR_INITIAL:
out << setw(ind) << "" << "analog initial";
break;
case AProcess::PR_ALWAYS:
out << setw(ind) << "" << "analog";
break;
out << setw(ind+2) << "" << "(* " << (*idx).first;
if ((*idx).second) {
out << " = " << *(*idx).second;
}
out << " *)" << endl;
}
out << " /* " << get_fileline() << " */" << endl;
dump_attributes_map(out, attributes, ind+2);
statement_->dump(out, ind+2);
}
@@ -1009,13 +937,8 @@ void PGenerate::dump(ostream&out, unsigned indent) const
(*idx)->dump(out, indent+2);
}
for (list<AProcess*>::const_iterator idx = analog_behaviors.begin()
; idx != analog_behaviors.end() ; idx++) {
(*idx)->dump(out, indent+2);
}
for (list<PGenerate*>::const_iterator idx = generate_schemes.begin()
; idx != generate_schemes.end() ; idx++) {
for (list<PGenerate*>::const_iterator idx = generates.begin()
; idx != generates.end() ; idx++) {
(*idx)->dump(out, indent+2);
}
@@ -1068,6 +991,7 @@ void Module::dump(ostream&out) const
}
typedef map<perm_string,param_expr_t>::const_iterator parm_iter_t;
typedef map<pform_name_t,PExpr*>::const_iterator parm_hiter_t;
for (parm_iter_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
out << " parameter " << (*cur).second.type << " ";
@@ -1144,7 +1068,6 @@ void Module::dump(ostream&out) const
<< *(*cur).second << ";" << endl;
}
typedef list<Module::named_expr_t>::const_iterator parm_hiter_t;
for (parm_hiter_t cur = defparms.begin()
; cur != defparms.end() ; cur ++) {
out << " defparam " << (*cur).first << " = ";
@@ -1166,8 +1089,8 @@ void Module::dump(ostream&out) const
// Dump the task definitions.
typedef map<perm_string,PTask*>::const_iterator task_iter_t;
for (task_iter_t cur = tasks.begin()
; cur != tasks.end() ; cur ++) {
for (task_iter_t cur = tasks_.begin()
; cur != tasks_.end() ; cur ++) {
out << " task " << (*cur).first << ";" << endl;
(*cur).second->dump(out, 6);
out << " endtask;" << endl;
@@ -1175,8 +1098,8 @@ void Module::dump(ostream&out) const
// Dump the function definitions.
typedef map<perm_string,PFunction*>::const_iterator func_iter_t;
for (func_iter_t cur = funcs.begin()
; cur != funcs.end() ; cur ++) {
for (func_iter_t cur = funcs_.begin()
; cur != funcs_.end() ; cur ++) {
out << " function " << (*cur).first << ";" << endl;
(*cur).second->dump(out, 6);
out << " endfunction;" << endl;
@@ -1199,11 +1122,6 @@ void Module::dump(ostream&out) const
(*behav)->dump(out, 4);
}
for (list<AProcess*>::const_iterator idx = analog_behaviors.begin()
; idx != analog_behaviors.end() ; idx++) {
(*idx)->dump(out, 4);
}
for (list<PSpecPath*>::const_iterator spec = specify_paths.begin()
; spec != specify_paths.end()
; spec ++ ) {
+12 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2007 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -16,6 +16,17 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: pform_types.cc,v 1.1 2007/05/24 04:07:12 steve Exp $"
#endif
# include "pform_types.h"
bool operator < (const name_component_t&lef, const name_component_t&rig)
{
if (lef.name < rig.name)
return true;
return false;
}
+6 -26
View File
@@ -1,7 +1,7 @@
#ifndef __pform_types_H
#define __pform_types_H
/*
* Copyright (c) 2007-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2007 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
@@ -18,6 +18,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: pform_types.h,v 1.2 2007/06/04 02:19:07 steve Exp $"
#endif
// This for the perm_string type.
# include "StringHeap.h"
@@ -47,36 +50,13 @@ struct name_component_t {
std::list<index_component_t>index;
};
extern bool operator < (const name_component_t&lef, const name_component_t&rig);
/*
* The pform_name_t is the general form for a hierarchical
* identifier. It is an ordered list of name components. Each name
* component is an identifier and an optional list of bit/part
* selects. The simplest name component is a simple identifier:
*
* foo
*
* The bit/part selects come from the source and are made part of the
* name component. A bit select is a single number that may be a bit
* select of a vector or a word select of an array:
*
* foo[5] -- a bit select/word index
* foo[6:4] -- a part select
*
* The index components of a name component are collected into an
* ordered list, so there may be many, for example:
*
* foo[5][6:4] -- a part select of an array word
*
* The pform_name_t, then, is an ordered list of these name
* components. The list of names comes from a hierarchical name in the
* source, like this:
*
* foo[5].bar[6:4] -- a part select of a vector in sub-scope foo[5].
* The pform_name_t is the general form for a hierarchical identifier.
*/
typedef std::list<name_component_t> pform_name_t;
inline perm_string peek_head_name(const pform_name_t&that)
{
return that.front().name;
-13
View File
@@ -1,13 +0,0 @@
#!/bin/sh
# This script manually creates a version.h file.
#
# It is used when creating a MinGW executable from a Cygwin
# hosted git repository. It assumes that git is available.
#
# sh scripts/CREATE_VERSION.sh
#
echo "Building version.h with git describe"
tmp=`git describe | sed -e 's;\(.*\);#define VERSION_TAG "\1";'`
echo "$tmp" > version.h
+1 -1
View File
@@ -7,7 +7,7 @@
# sh scripts/MAKE_SNAPSHOT.sh 20080428 ~/tmp
#
# The above assumes that there is a tag "s20080428" at the point
# to be snapshot. (The tag has the "s", but the argument to this
# to be snaphot. (The tag has the "s", but the argument to this
# script does not have the "s"). This script extracts based on the
# tag, uses the temporary directory to stage intermediate results,
# and finally creates a file called verilog-20080428.tar.gz that
-23
View File
@@ -1,23 +0,0 @@
#
# This is a debug conf file that the scripts/devel-stub.sh script uses
# to control the ivl core. The contents of this file are normally written
# to a temporary file by the driver program, but for devel purposes, where
# the driver program is not used, this config substitutes.
#
# NOTE: DO NOT INSTALL THIS FILE!
#
generation:2005
generation:specify
generation:xtypes
generation:verilog-ams
iwidth:32
sys_func:vpi/system.sft
sys_func:vpi/va_math.sft
warnings:implicit
debug:eval_tree
debug:elaborate
debug:scopes
debug:synth2
out:a.out
ivlpp:./ivlpp/ivlpp -D__ICARUS__ -L -Pfoo.pp
sys_func:scripts/devel-stub.sft
-5
View File
@@ -1,5 +0,0 @@
# This is an example function table.
$realtime vpiSysFuncReal
$verywide vpiSysFuncSized 128 signed
-14
View File
@@ -1,14 +0,0 @@
# This is a little developer convenience script to run the ivl core program
# in place with the stub target. It runs the ivl core verbose, with diagnostic
# output files enable, and without the driver program or preprocessor.
# It is useful only for development of the ivl core program.
#
# Run this script in the source directory for the ivl core program so that
# the patch to the other components is correct.
#
# NOTE: DO NOT INSTALL THIS FILE.
./ivl -v -Ctgt-stub/stub.conf -C./scripts/devel-stub.conf -Pa.pf -Na.net -fDLL=tgt-stub/stub.tgt foo.vl
echo "*** ivl command completed, rc=$?"
+40 -15
View File
@@ -1,7 +1,7 @@
#ifndef __svector_H
#define __svector_H
/*
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -20,10 +20,12 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: svector.h,v 1.11 2007/03/22 16:08:17 steve Exp $"
#endif
# include "config.h"
# include <string>
# include <vector>
# include <assert.h>
/*
@@ -104,18 +106,41 @@ template <> inline svector<std::string>::svector(unsigned size)
{
}
/*
* This is a convenience function that converts an svector to a
* vector. This is to ease the transition from svector to vector so
* that the svector class can be gradually removed.
*/
template <class T> inline std::vector<T> vector_from_svector(const svector<T>&that)
{
std::vector<T> res (that.count());
for (unsigned idx = 0 ; idx < that.count() ; idx += 1)
res[idx] = that[idx];
return res;
}
* $Log: svector.h,v $
* Revision 1.11 2007/03/22 16:08:17 steve
* Spelling fixes from Larry
*
* Revision 1.10 2005/06/14 19:13:43 steve
* gcc3/4 compile errors.
*
* Revision 1.9 2003/07/23 02:35:44 steve
* Inline the svector<string> constructor.
*
* Revision 1.8 2003/07/16 00:54:07 steve
* Needs the config.h header.
*
* Revision 1.7 2003/07/15 05:07:13 steve
* Move PUdp constructor into compiled file.
*
* Revision 1.6 2002/08/12 01:35:00 steve
* conditional ident string using autoconfig.
*
* Revision 1.5 2000/02/23 02:56:55 steve
* Macintosh compilers do not support ident.
*
* Revision 1.4 1999/06/15 03:44:53 steve
* Get rid of the STL vector template.
*
* Revision 1.3 1999/05/06 04:37:17 steve
* Get rid of list<lgate> types.
*
* Revision 1.2 1999/05/01 02:57:53 steve
* Handle much more complex event expressions.
*
* Revision 1.1 1999/04/29 02:16:26 steve
* Parse OR of event expressions.
*
*/
#endif
+1 -1
View File
@@ -598,7 +598,7 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
delete expr_input;
/* Detect the case that this is a *synchronous* set/reset. It
is not asynchronous because we know the condition is not
is not asyncronous because we know the condition is not
included in the sensitivity list, but if the if_ case is
constant (has no inputs) then we can model this as a
synchronous set/reset.
+9 -31
View File
@@ -354,7 +354,6 @@ extern "C" ivl_expr_t ivl_expr_oper3(ivl_expr_t net)
extern "C" ivl_parameter_t ivl_expr_parameter(ivl_expr_t net)
{
assert(net);
switch (net->type_) {
case IVL_EX_NUMBER:
return net->u_.number_.parameter;
@@ -887,8 +886,6 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
assert(net);
switch (net->type) {
case IVL_LPM_ABS:
case IVL_LPM_CAST_INT:
case IVL_LPM_CAST_REAL:
assert(idx == 0);
return net->u_.arith.a;
@@ -1031,19 +1028,20 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
switch (net->type) {
case IVL_LPM_ABS:
case IVL_LPM_ADD:
case IVL_LPM_CAST_INT:
case IVL_LPM_CAST_REAL:
case IVL_LPM_DIVIDE:
case IVL_LPM_MOD:
case IVL_LPM_MULT:
case IVL_LPM_POW:
case IVL_LPM_SUB:
assert(idx == 0);
return net->u_.arith.q;
case IVL_LPM_CMP_GE:
case IVL_LPM_CMP_GT:
case IVL_LPM_CMP_EQ:
case IVL_LPM_CMP_NE:
case IVL_LPM_CMP_EEQ:
case IVL_LPM_CMP_NEE:
case IVL_LPM_DIVIDE:
case IVL_LPM_MOD:
case IVL_LPM_MULT:
case IVL_LPM_POW:
case IVL_LPM_SUB:
assert(idx == 0);
return net->u_.arith.q;
@@ -1146,7 +1144,6 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
return 0;
case IVL_LPM_ABS:
case IVL_LPM_ADD:
case IVL_LPM_CAST_REAL:
case IVL_LPM_CMP_EEQ:
case IVL_LPM_CMP_EQ:
case IVL_LPM_CMP_GE:
@@ -1169,7 +1166,6 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR:
return net->u_.shift.signed_flag;
case IVL_LPM_CAST_INT:
case IVL_LPM_SIGN_EXT: // Sign extend is always signed.
return 1;
case IVL_LPM_SFUNC:
@@ -1439,18 +1435,6 @@ extern int ivl_path_source_negedge(ivl_delaypath_t net)
return net->negedge ? 1 : 0;
}
extern "C" const char*ivl_process_file(ivl_process_t net)
{
assert(net);
return net->file.str();
}
extern "C" unsigned ivl_process_lineno(ivl_process_t net)
{
assert(net);
return net->lineno;
}
extern "C" ivl_process_type_t ivl_process_type(ivl_process_t net)
{
return net->type_;
@@ -1548,12 +1532,6 @@ extern "C" const char*ivl_scope_file(ivl_scope_t net)
return net->file.str();
}
extern "C" unsigned ivl_scope_is_auto(ivl_scope_t net)
{
assert(net);
return net->is_auto;
}
extern "C" unsigned ivl_scope_lineno(ivl_scope_t net)
{
assert(net);
@@ -1688,7 +1666,7 @@ extern "C" ivl_switch_t ivl_scope_switch(ivl_scope_t net, unsigned idx)
assert(idx < net->switches.size());
return net->switches[idx];
}
extern "C" int ivl_scope_time_precision(ivl_scope_t net)
{
assert(net);
-15
View File
@@ -149,19 +149,6 @@ ivl_expr_t dll_target::expr_from_value_(const verinum&val)
return expr;
}
void dll_target::expr_access_func(const NetEAccess*net)
{
assert(expr_ == 0);
// Make a stub Branch Access Function expression node.
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
expr_->type_ = IVL_EX_BACCESS;
expr_->value_ = IVL_VT_REAL;
expr_->file = net->get_file();
expr_->lineno = net->get_lineno();
expr_->width_ = 1;
expr_->signed_= 1;
}
void dll_target::expr_binary(const NetEBinary*net)
{
assert(expr_ == 0);
@@ -219,7 +206,6 @@ void dll_target::expr_const(const NetEConst*net)
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
assert(expr_);
expr_->value_= net->expr_type();
FILE_NAME(expr_, net);
if (net->value().is_string()) {
expr_->type_ = IVL_EX_STRING;
@@ -277,7 +263,6 @@ void dll_target::expr_creal(const NetECReal*net)
expr_->width_ = net->expr_width();
expr_->signed_ = 1;
expr_->type_ = IVL_EX_REALNUM;
FILE_NAME(expr_, net);
expr_->value_= IVL_VT_REAL;
expr_->u_.real_.value = net->value().as_double();
}
+11 -16
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000 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,6 +17,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: $"
#endif
# include "config.h"
@@ -34,8 +37,6 @@
bool dll_target::process(const NetProcTop*net)
{
bool rc_flag = true;
ivl_process_t obj = (struct ivl_process_s*)
calloc(1, sizeof(struct ivl_process_s));
@@ -49,7 +50,6 @@ bool dll_target::process(const NetProcTop*net)
default:
assert(0);
}
FILE_NAME(obj, net);
/* Save the scope of the process. */
obj->scope_ = lookup_scope_(net->scope());
@@ -70,7 +70,7 @@ bool dll_target::process(const NetProcTop*net)
assert(stmt_cur_ == 0);
stmt_cur_ = (struct ivl_statement_s*)calloc(1, sizeof*stmt_cur_);
assert(stmt_cur_);
rc_flag = net->statement()->emit_proc(this) && rc_flag;
net->statement()->emit_proc(this);
assert(stmt_cur_);
obj->stmt_ = stmt_cur_;
@@ -80,7 +80,7 @@ bool dll_target::process(const NetProcTop*net)
obj->next_ = des_.threads_;
des_.threads_ = obj;
return rc_flag;
return true;
}
void dll_target::task_def(const NetScope*net)
@@ -190,7 +190,7 @@ void dll_target::make_assign_lvals_(const NetAssignBase*net)
/*
*/
bool dll_target::proc_assign(const NetAssign*net)
void dll_target::proc_assign(const NetAssign*net)
{
assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE);
@@ -214,8 +214,6 @@ bool dll_target::proc_assign(const NetAssign*net)
stmt_cur_->u_.assign_.delay = expr_;
expr_ = 0;
}
return true;
}
@@ -401,8 +399,6 @@ bool dll_target::proc_cassign(const NetCAssign*net)
bool dll_target::proc_condit(const NetCondit*net)
{
bool rc_flag = true;
assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE);
FILE_NAME(stmt_cur_, net);
@@ -414,20 +410,18 @@ bool dll_target::proc_condit(const NetCondit*net)
assert(expr_ == 0);
net->expr()->expr_scan(this);
stmt_cur_->u_.condit_.cond_ = expr_;
if (expr_ == 0)
rc_flag = false;
expr_ = 0;
ivl_statement_t save_cur_ = stmt_cur_;
stmt_cur_ = save_cur_->u_.condit_.stmt_+0;
rc_flag = net->emit_recurse_if(this) && rc_flag;
bool flag = net->emit_recurse_if(this);
stmt_cur_ = save_cur_->u_.condit_.stmt_+1;
rc_flag = net->emit_recurse_else(this) && rc_flag;
flag = flag && net->emit_recurse_else(this);
stmt_cur_ = save_cur_;
return rc_flag;
return flag;
}
bool dll_target::proc_deassign(const NetDeassign*net)
@@ -751,3 +745,4 @@ void dll_target::proc_while(const NetWhile*net)
net->emit_proc_recurse(this);
stmt_cur_ = save_cur_;
}
+5 -81
View File
@@ -30,7 +30,6 @@
# include <malloc.h>
#endif
# include <stdlib.h>
# include "ivl_assert.h"
#if defined(__WIN32__)
@@ -539,13 +538,6 @@ void dll_target::make_scope_param_expr(ivl_parameter_t cur_par, NetExpr*etmp)
}
if (expr_ == 0) {
cerr << etmp->get_fileline() << ": internal error: "
<< "Parameter expression not reduced to constant? "
<< *etmp << endl;
}
ivl_assert(*etmp, expr_);
cur_par->value = expr_;
expr_ = 0;
}
@@ -575,7 +567,6 @@ void dll_target::add_root(ivl_design_s &des_, const NetScope *s)
root_->time_units = s->time_unit();
root_->nattr = s->attr_cnt();
root_->attr = fill_in_attributes(s);
root_->is_auto = 0;
des_.nroots_++;
if (des_.roots_)
@@ -857,7 +848,7 @@ bool dll_target::bufz(const NetBUFZ*net)
logic_attributes(obj, net);
make_logic_delays_(obj, net);
scope_add_logic(scope, obj);
return true;
@@ -1559,71 +1550,6 @@ void dll_target::lpm_clshift(const NetCLShift*net)
scope_add_lpm(obj->scope, obj);
}
bool dll_target::lpm_cast_int(const NetCastInt*net)
{
ivl_lpm_t obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_CAST_INT;
obj->name = net->name(); // NetCastInt names are permallocated
assert(net->scope());
obj->scope = find_scope(des_, net->scope());
assert(obj->scope);
obj->width = net->width();
const Nexus*nex;
nex = net->pin(0).nexus();
assert(nex->t_cookie());
obj->u_.arith.q = nex->t_cookie();
nex = net->pin(1).nexus();
assert(nex->t_cookie());
obj->u_.arith.a = nex->t_cookie();
nexus_lpm_add(obj->u_.arith.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
nexus_lpm_add(obj->u_.arith.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
make_lpm_delays_(obj, net);
scope_add_lpm(obj->scope, obj);
return true;
}
bool dll_target::lpm_cast_real(const NetCastReal*net)
{
ivl_lpm_t obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_CAST_REAL;
obj->name = net->name(); // NetCastReal names are permallocated
assert(net->scope());
obj->scope = find_scope(des_, net->scope());
assert(obj->scope);
obj->width = 0;
obj->u_.arith.signed_flag = net->signed_flag()? 1 : 0;
const Nexus*nex;
nex = net->pin(0).nexus();
assert(nex->t_cookie());
obj->u_.arith.q = nex->t_cookie();
nex = net->pin(1).nexus();
assert(nex->t_cookie());
obj->u_.arith.a = nex->t_cookie();
nexus_lpm_add(obj->u_.arith.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
nexus_lpm_add(obj->u_.arith.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
make_lpm_delays_(obj, net);
scope_add_lpm(obj->scope, obj);
return true;
}
/*
* Make out of the NetCompare object an ivl_lpm_s object. The
* comparators in ivl_target do not support < or <=, but they can be
@@ -1921,7 +1847,6 @@ void dll_target::lpm_mult(const NetMult*net)
unsigned wid = net->width_r();
obj->width = wid;
obj->u_.arith.signed_flag = 0;
const Nexus*nex;
@@ -1956,7 +1881,7 @@ void dll_target::lpm_mux(const NetMux*net)
{
ivl_lpm_t obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_MUX;
obj->name = net->name(); // The NetMux permallocates its name.
obj->name = net->name(); // The NetMux perallocates its name.
obj->scope = find_scope(des_, net->scope());
assert(obj->scope);
@@ -2205,7 +2130,6 @@ bool dll_target::net_const(const NetConst*net)
assert(net->pin_count() == 1);
obj->width_ = net->width();
obj->signed_ = 0;
if (obj->width_ <= sizeof(obj->b.bit_)) {
bits = obj->b.bit_;
@@ -2322,8 +2246,7 @@ void dll_target::scope(const NetScope*net)
scope->time_precision = net->time_precision();
scope->time_units = net->time_unit();
scope->nattr = net->attr_cnt();
scope->attr = fill_in_attributes(net);
scope->is_auto = net->is_auto();
scope->attr = fill_in_attributes(net);
switch (net->type()) {
case NetScope::MODULE:
@@ -2378,7 +2301,8 @@ void dll_target::signal(const NetNet*net)
object, or creating the sigs_ array if this is the first
signal. */
obj->scope_ = find_scope(des_, net->scope());
FILE_NAME(obj, net);
obj->file = perm_string::literal("N/A");
obj->lineno = 0;
assert(obj->scope_);
if (obj->scope_->nsigs_ == 0) {
+2 -20
View File
@@ -76,8 +76,6 @@ struct dll_target : public target_t, public expr_scan_t {
void lpm_abs(const NetAbs*);
void lpm_add_sub(const NetAddSub*);
bool lpm_array_dq(const NetArrayDq*);
bool lpm_cast_int(const NetCastInt*);
bool lpm_cast_real(const NetCastReal*);
void lpm_clshift(const NetCLShift*);
void lpm_compare(const NetCompare*);
void lpm_divide(const NetDivide*);
@@ -111,7 +109,7 @@ struct dll_target : public target_t, public expr_scan_t {
/* These methods and members are used for forming the
statements of a thread. */
struct ivl_statement_s*stmt_cur_;
bool proc_assign(const NetAssign*);
void proc_assign(const NetAssign*);
void proc_assign_nb(const NetAssignNB*);
bool proc_block(const NetBlock*);
void proc_case(const NetCase*);
@@ -134,7 +132,6 @@ struct dll_target : public target_t, public expr_scan_t {
void task_def(const NetScope*);
struct ivl_expr_s*expr_;
void expr_access_func(const NetEAccess*);
void expr_binary(const NetEBinary*);
void expr_concat(const NetEConcat*);
void expr_const(const NetEConst*);
@@ -540,7 +537,7 @@ struct ivl_parameter_s {
unsigned lineno;
};
/*
* All we know about a process is its type (initial or always) and the
* All we know about a process it its type (initial or always) and the
* single statement that is it. A process also has a scope, although
* that generally only matters for VPI calls.
*/
@@ -548,8 +545,6 @@ struct ivl_process_s {
ivl_process_type_t type_;
ivl_scope_t scope_;
ivl_statement_t stmt_;
perm_string file;
unsigned lineno;
struct ivl_attribute_s*attr;
unsigned nattr;
@@ -591,7 +586,6 @@ struct ivl_scope_s {
/* Scopes that are tasks/functions have a definition. */
ivl_statement_t def;
unsigned is_auto;
unsigned ports;
ivl_signal_t*port;
@@ -767,16 +761,4 @@ static inline void FILE_NAME(ivl_switch_t net, const LineInfo*info)
net->lineno = info->get_lineno();
}
static inline void FILE_NAME(ivl_process_t net, const LineInfo*info)
{
net->file = info->get_file();
net->lineno = info->get_lineno();
}
static inline void FILE_NAME(ivl_signal_t net, const LineInfo*info)
{
net->file = info->get_file();
net->lineno = info->get_lineno();
}
#endif
+1151
View File
File diff suppressed because it is too large Load Diff
+1 -22
View File
@@ -107,20 +107,6 @@ bool target_t::lpm_array_dq(const NetArrayDq*)
return false;
}
bool target_t::lpm_cast_int(const NetCastInt*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled NetCastInt." << endl;
return false;
}
bool target_t::lpm_cast_real(const NetCastReal*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled NetCastReal." << endl;
return false;
}
void target_t::lpm_clshift(const NetCLShift*)
{
cerr << "target (" << typeid(*this).name() << "): "
@@ -243,11 +229,10 @@ bool target_t::process(const NetProcTop*top)
return top->statement()->emit_proc(this);
}
bool target_t::proc_assign(const NetAssign*)
void target_t::proc_assign(const NetAssign*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled procedural assignment." << endl;
return false;
}
void target_t::proc_assign_nb(const NetAssignNB*)
@@ -378,12 +363,6 @@ expr_scan_t::~expr_scan_t()
{
}
void expr_scan_t::expr_access_func(const NetEAccess*)
{
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
"unhandled expr_access_func." << endl;
}
void expr_scan_t::expr_const(const NetEConst*)
{
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
+1 -4
View File
@@ -72,8 +72,6 @@ struct target_t {
virtual void lpm_add_sub(const NetAddSub*);
virtual bool lpm_array_dq(const NetArrayDq*);
virtual void lpm_clshift(const NetCLShift*);
virtual bool lpm_cast_int(const NetCastInt*);
virtual bool lpm_cast_real(const NetCastReal*);
virtual void lpm_compare(const NetCompare*);
virtual void lpm_divide(const NetDivide*);
virtual void lpm_modulo(const NetModulo*);
@@ -105,7 +103,7 @@ struct target_t {
virtual bool process(const NetProcTop*);
/* Various kinds of process nodes are dispatched through these. */
virtual bool proc_assign(const NetAssign*);
virtual void proc_assign(const NetAssign*);
virtual void proc_assign_nb(const NetAssignNB*);
virtual bool proc_block(const NetBlock*);
virtual void proc_case(const NetCase*);
@@ -133,7 +131,6 @@ struct target_t {
of expressions. */
struct expr_scan_t {
virtual ~expr_scan_t();
virtual void expr_access_func(const NetEAccess*);
virtual void expr_const(const NetEConst*);
virtual void expr_param(const NetEConstParam*);
virtual void expr_rparam(const NetECRealParam*);
+54
View File
@@ -16,14 +16,68 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: targets.cc,v 1.12 2004/12/11 02:31:28 steve Exp $"
#endif
# include "config.h"
# include "target.h"
extern const struct target tgt_dll;
#ifdef WITH_T_XNF
extern const struct target tgt_xnf;
#endif
const struct target *target_table[] = {
&tgt_dll,
#ifdef WITH_T_XNF
&tgt_xnf,
#endif
0
};
/*
* $Log: targets.cc,v $
* Revision 1.12 2004/12/11 02:31:28 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.11 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
* Revision 1.10 2002/08/11 23:39:33 steve
* Remove VVM option.
*
* Revision 1.9 2002/02/16 03:18:54 steve
* Make vvm optional, normally off.
*
* Revision 1.8 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.7 2000/12/02 04:50:32 steve
* Make the null target into a loadable target.
*
* Revision 1.6 2000/08/12 16:34:37 steve
* Start stub for loadable targets.
*
* Revision 1.5 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.4 1999/05/01 02:57:53 steve
* Handle much more complex event expressions.
*
* Revision 1.3 1999/01/24 01:35:36 steve
* Support null target for generating no output.
*
* Revision 1.2 1998/11/16 05:03:53 steve
* Add the sigfold function that unlinks excess
* signal nodes, and add the XNF target.
*
* Revision 1.1 1998/11/03 23:29:07 steve
* Introduce verilog to CVS.
*
*/
+1 -1
View File
@@ -160,7 +160,7 @@ device pins are connected.
.SH EXAMPLES
.TB 8
.I COMPILING WITH XILINX FOUNDATION/ISE
.I COMPILING WITH XILINX FOUNDATION/iSE
Compile a single-file design with command line tools like so:
.nf
+7 -7
View File
@@ -75,22 +75,22 @@ check: all
install: all installdirs $(libdir)/ivl/null.tgt $(INSTALL_DOC) $(libdir)/ivl/null.conf $(libdir)/ivl/null-s.conf
$(libdir)/ivl/null.tgt: ./null.tgt
$(INSTALL_PROGRAM) ./null.tgt $(DESTDIR)$(libdir)/ivl/null.tgt
$(INSTALL_PROGRAM) ./null.tgt $(libdir)/ivl/null.tgt
$(libdir)/ivl/null.conf: $(srcdir)/null.conf
$(INSTALL_DATA) $(srcdir)/null.conf $(DESTDIR)$(libdir)/ivl/null.conf
$(INSTALL_DATA) $(srcdir)/null.conf $(libdir)/ivl/null.conf
$(libdir)/ivl/null-s.conf: $(srcdir)/null-s.conf
$(INSTALL_DATA) $(srcdir)/null-s.conf $(DESTDIR)$(libdir)/ivl/null-s.conf
$(INSTALL_DATA) $(srcdir)/null-s.conf $(libdir)/ivl/null-s.conf
installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(DESTDIR)$(includedir) $(DESTDIR)$(bindir) $(DESTDIR)$(libdir)/ivl
$(srcdir)/../mkinstalldirs $(includedir) $(bindir) $(libdir)/ivl
uninstall:
rm -f $(DESTDIR)$(libdir)/ivl/null.tgt
rm -f $(DESTDIR)$(libdir)/ivl/null.conf
rm -f $(DESTDIR)$(libdir)/ivl/null-s.conf
rm -f $(libdir)/ivl/null.tgt
rm -f $(libdir)/ivl/null.conf
rm -f $(libdir)/ivl/null-s.conf
-include $(patsubst %.o, dep/%.d, $O)
+7 -7
View File
@@ -76,21 +76,21 @@ install: all installdirs $(libdir)/ivl/stub.tgt \
$(libdir)/ivl/stub.conf $(libdir)/ivl/stub-s.conf
$(libdir)/ivl/stub.tgt: ./stub.tgt
$(INSTALL_PROGRAM) ./stub.tgt $(DESTDIR)$(libdir)/ivl/stub.tgt
$(INSTALL_PROGRAM) ./stub.tgt $(libdir)/ivl/stub.tgt
$(libdir)/ivl/stub.conf: stub.conf
$(INSTALL_DATA) $< $(DESTDIR)$(libdir)/ivl/stub.conf
$(INSTALL_DATA) $< $(libdir)/ivl/stub.conf
$(libdir)/ivl/stub-s.conf: stub-s.conf
$(INSTALL_DATA) $< $(DESTDIR)$(libdir)/ivl/stub-s.conf
$(INSTALL_DATA) $< $(libdir)/ivl/stub-s.conf
installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(DESTDIR)$(includedir) $(DESTDIR)$(bindir) $(DESTDIR)$(libdir)/ivl
$(srcdir)/../mkinstalldirs $(includedir) $(bindir) $(libdir)/ivl
uninstall:
rm -f $(DESTDIR)$(libdir)/ivl/stub.tgt
rm -f $(DESTDIR)$(libdir)/ivl/stub.conf
rm -f $(DESTDIR)$(libdir)/ivl/stub-s.conf
rm -f $(libdir)/ivl/stub.tgt
rm -f $(libdir)/ivl/stub.conf
rm -f $(libdir)/ivl/stub-s.conf
-include $(patsubst %.o, dep/%.d, $O)
+2 -35
View File
@@ -43,40 +43,16 @@ static void show_array_expression(ivl_expr_t net, unsigned ind)
ivl_signal_dimensions(sig), width, vt);
}
static void show_branch_access_expression(ivl_expr_t net, unsigned ind)
{
fprintf(out, "%*s<Branch Access>\n", ind, "");
if (ivl_expr_value(net) != IVL_VT_REAL) {
fprintf(out, "%*sERROR: Expecting type IVL_VT_REAL, got %s\n",
ind, "", vt_type_string(net));
stub_errors += 1;
}
}
static void show_binary_expression(ivl_expr_t net, unsigned ind)
{
unsigned width = ivl_expr_width(net);
const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
const char*vt = vt_type_string(net);
ivl_expr_t oper1 = ivl_expr_oper1(net);
ivl_expr_t oper2 = ivl_expr_oper2(net);
fprintf(out, "%*s<\"%c\" width=%u, %s, type=%s>\n", ind, "",
ivl_expr_opcode(net), width, sign, vt);
if (oper1) {
show_expression(oper1, ind+3);
} else {
fprintf(out, "%*sERROR: Missing operand 1\n", ind+3, "");
stub_errors += 1;
}
if (oper2) {
show_expression(oper2, ind+3);
} else {
fprintf(out, "%*sERROR: Missing operand 2\n", ind+3, "");
stub_errors += 1;
}
show_expression(ivl_expr_oper1(net), ind+3);
show_expression(ivl_expr_oper2(net), ind+3);
switch (ivl_expr_opcode(net)) {
@@ -202,11 +178,6 @@ void show_unary_expression(ivl_expr_t net, unsigned ind)
break;
}
if (ivl_expr_opcode(net) == '!' && ivl_expr_type(net)==IVL_VT_REAL) {
fprintf(out, "%*sERROR: Real argument to unary ! !?\n", ind,"");
stub_errors += 1;
}
fprintf(out, "%*s<unary \"%s\" width=%u, %s, type=%s>\n", ind, "",
name, width, sign, vt);
show_expression(ivl_expr_oper1(net), ind+4);
@@ -227,10 +198,6 @@ void show_expression(ivl_expr_t net, unsigned ind)
show_array_expression(net, ind);
break;
case IVL_EX_BACCESS:
show_branch_access_expression(net, ind);
break;
case IVL_EX_BINARY:
show_binary_expression(net, ind);
break;
+1 -6
View File
@@ -264,12 +264,7 @@ void show_statement(ivl_statement_t net, unsigned ind)
ivl_statement_t f = ivl_stmt_cond_false(net);
fprintf(out, "%*sif (...)\n", ind, "");
if (ex) {
show_expression(ex, ind+4);
} else {
fprintf(out, "%*sERROR: Condition expression is NIL;\n", ind+4, "");
stub_errors += 1;
}
show_expression(ex, ind+4);
if (t)
show_statement(t, ind+4);
else
+3 -62
View File
@@ -240,56 +240,6 @@ static void show_lpm_array(ivl_lpm_t net)
}
}
static void show_lpm_cast_int(ivl_lpm_t net)
{
unsigned width = ivl_lpm_width(net);
fprintf(out, " LPM_CAST_INT %s: <width=%u>\n",
ivl_lpm_basename(net), width);
ivl_nexus_t q = ivl_lpm_q(net,0);
ivl_nexus_t a = ivl_lpm_data(net,0);
fprintf(out, " O: %s\n", ivl_nexus_name(ivl_lpm_q(net,0)));
fprintf(out, " A: %s\n", ivl_nexus_name(ivl_lpm_data(net,0)));
if (type_of_nexus(q) == IVL_VT_REAL) {
fprintf(out, " ERROR: Data type of Q is %s, expecting !real\n",
data_type_string(type_of_nexus(q)));
stub_errors += 1;
}
if (type_of_nexus(a) != IVL_VT_REAL) {
fprintf(out, " ERROR: Data type of A is %s, expecting real\n",
data_type_string(type_of_nexus(a)));
stub_errors += 1;
}
}
static void show_lpm_cast_real(ivl_lpm_t net)
{
unsigned width = ivl_lpm_width(net);
fprintf(out, " LPM_CAST_REAL %s: <width=%u>\n",
ivl_lpm_basename(net), width);
ivl_nexus_t q = ivl_lpm_q(net,0);
ivl_nexus_t a = ivl_lpm_data(net,0);
fprintf(out, " O: %s\n", ivl_nexus_name(ivl_lpm_q(net,0)));
fprintf(out, " A: %s\n", ivl_nexus_name(ivl_lpm_data(net,0)));
if (type_of_nexus(q) != IVL_VT_REAL) {
fprintf(out, " ERROR: Data type of Q is %s, expecting real\n",
data_type_string(type_of_nexus(q)));
stub_errors += 1;
}
if (type_of_nexus(a) == IVL_VT_REAL) {
fprintf(out, " ERROR: Data type of A is %s, expecting !real\n",
data_type_string(type_of_nexus(a)));
stub_errors += 1;
}
}
static void show_lpm_divide(ivl_lpm_t net)
{
unsigned width = ivl_lpm_width(net);
@@ -852,14 +802,6 @@ static void show_lpm(ivl_lpm_t net)
show_lpm_array(net);
break;
case IVL_LPM_CAST_INT:
show_lpm_cast_int(net);
break;
case IVL_LPM_CAST_REAL:
show_lpm_cast_real(net);
break;
case IVL_LPM_DIVIDE:
show_lpm_divide(net);
break;
@@ -1042,7 +984,7 @@ static void signal_nexus_const(ivl_signal_t sig,
switch (ivl_const_type(con)) {
case IVL_VT_LOGIC:
bits = ivl_const_bits(con);
for (idx = 0 ; idx < width ; idx += 1) {
for (idx = 0 ; idx < width ; idx += 1) {
fprintf(out, "%c", bits[width-idx-1]);
}
break;
@@ -1448,13 +1390,12 @@ static int show_scope(ivl_scope_t net, void*x)
ivl_scope_name(net), ivl_scope_params(net),
ivl_scope_sigs(net), ivl_scope_logs(net));
char *is_auto = ivl_scope_is_auto(net) ? "automatic " : "";
switch (ivl_scope_type(net)) {
case IVL_SCT_MODULE:
fprintf(out, " module %s", ivl_scope_tname(net));
break;
case IVL_SCT_FUNCTION:
fprintf(out, " function %s%s", is_auto, ivl_scope_tname(net));
fprintf(out, " function %s", ivl_scope_tname(net));
break;
case IVL_SCT_BEGIN:
fprintf(out, " begin : %s", ivl_scope_tname(net));
@@ -1463,7 +1404,7 @@ static int show_scope(ivl_scope_t net, void*x)
fprintf(out, " fork : %s", ivl_scope_tname(net));
break;
case IVL_SCT_TASK:
fprintf(out, " task %s%s", is_auto, ivl_scope_tname(net));
fprintf(out, " task %s", ivl_scope_tname(net));
break;
default:
fprintf(out, " type(%u) %s", ivl_scope_type(net),
-92
View File
@@ -1,92 +0,0 @@
#
# This source code is free software; you can redistribute it
# and/or modify it in source code form under the terms of the GNU
# Library General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc.,
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
SHELL = /bin/sh
VERSION = 0.0
prefix = @prefix@
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
VPATH = $(srcdir)
bindir = @bindir@
libdir = @libdir@
includedir = $(prefix)/include
CXX = @CXX@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = @ident_support@ -I. -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ @PICFLAG@
CXXFLAGS = -Wall @CXXFLAGS@
LDFLAGS = @LDFLAGS@
all: dep vhdl.tgt vhdl.conf
dep:
mkdir dep
%.o: %.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o
mv $*.d dep
O = vhdl.o vhdl_element.o vhdl_type.o vhdl_syntax.o scope.o process.o \
stmt.o expr.o lpm.o display.o support.o cast.o logic.o
ifeq (@WIN32@,yes)
TGTLDFLAGS=-L.. -livl
TGTDEPLIBS=../libivl.a
else
TGTLDFLAGS=
TGTDEPLIBS=
endif
vhdl.tgt: $O $(TGTDEPLIBS)
$(CXX) @shared@ -o $@ $O $(TGTLDFLAGS)
Makefile: Makefile.in config.status
./config.status
clean:
rm -rf $(O) dep vhdl.tgt
distclean: clean
rm -f Makefile config.status config.log config.cache vhdl_config.h
check: all
install: all installdirs $(libdir)/ivl/vhdl.tgt $(libdir)/ivl/vhdl.conf
$(libdir)/ivl/vhdl.tgt: ./vhdl.tgt
$(INSTALL_PROGRAM) ./vhdl.tgt $(DESTDIR)$(libdir)/ivl/vhdl.tgt
$(libdir)/ivl/vhdl.conf: vhdl.conf
$(INSTALL_DATA) $< $(DESTDIR)$(libdir)/ivl/vhdl.conf
installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(DESTDIR)$(libdir)/ivl
uninstall:
rm -f $(DESTDIR)$(libdir)/ivl/vhdl.tgt $(DESTDIR)$(libdir)/ivl/vhdl.conf
-include $(patsubst %.o, dep/%.d, $O)
-279
View File
@@ -1,279 +0,0 @@
/*
* Generate code to convert between VHDL types.
*
* Copyright (C) 2008 Nick Gasson (nick@nickg.me.uk)
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "vhdl_syntax.hh"
#include "vhdl_target.h"
#include "support.hh"
#include <cassert>
#include <iostream>
vhdl_expr *vhdl_expr::cast(const vhdl_type *to)
{
//std::cout << "Cast: from=" << type_->get_string()
// << " (" << type_->get_width() << ") "
// << " to=" << to->get_string() << " ("
// << to->get_width() << ")" << std::endl;
// If this expression hasn't been given a type then
// we can't generate any type conversion code
if (NULL == type_)
return this;
if (to->get_name() == type_->get_name()) {
if (to->get_width() == type_->get_width())
return this; // Identical
else
return resize(to->get_width());
}
else {
switch (to->get_name()) {
case VHDL_TYPE_BOOLEAN:
return to_boolean();
case VHDL_TYPE_INTEGER:
return to_integer();
case VHDL_TYPE_UNSIGNED:
case VHDL_TYPE_SIGNED:
case VHDL_TYPE_STD_LOGIC_VECTOR:
return to_vector(to->get_name(), to->get_width());
case VHDL_TYPE_STD_LOGIC:
return to_std_logic();
default:
assert(false);
}
}
}
/*
* Generate code to cast an expression to a vector type (std_logic_vector,
* signed, unsigned).
*/
vhdl_expr *vhdl_expr::to_vector(vhdl_type_name_t name, int w)
{
if (type_->get_name() == VHDL_TYPE_STD_LOGIC) {
vhdl_expr *others = w == 1 ? NULL : new vhdl_const_bit('0');
vhdl_bit_spec_expr *bs =
new vhdl_bit_spec_expr(new vhdl_type(name, w - 1, 0), others);
bs->add_bit(0, this);
return bs;
}
else {
// We have to cast the expression before resizing or the
// wrong sign bit may be extended (i.e. when casting between
// signed/unsigned *and* resizing)
vhdl_type *t = new vhdl_type(name, w - 1, 0);
vhdl_fcall *conv = new vhdl_fcall(t->get_string().c_str(), t);
conv->add_expr(this);
if (w != type_->get_width())
return conv->resize(w);
else
return conv;
}
}
/*
* Convert a generic expression to an Integer.
*/
vhdl_expr *vhdl_expr::to_integer()
{
vhdl_fcall *conv;
if (type_->get_name() == VHDL_TYPE_STD_LOGIC) {
require_support_function(SF_LOGIC_TO_INTEGER);
conv = new vhdl_fcall(support_function::function_name(SF_LOGIC_TO_INTEGER),
vhdl_type::integer());
}
else
conv = new vhdl_fcall("To_Integer", vhdl_type::integer());
conv->add_expr(this);
return conv;
}
/*
* Convert a generic expression to a Boolean.
*/
vhdl_expr *vhdl_expr::to_boolean()
{
if (type_->get_name() == VHDL_TYPE_STD_LOGIC) {
// '1' is true all else are false
vhdl_const_bit *one = new vhdl_const_bit('1');
return new vhdl_binop_expr
(this, VHDL_BINOP_EQ, one, vhdl_type::boolean());
}
else if (type_->get_name() == VHDL_TYPE_UNSIGNED) {
// Need to use a support function for this conversion
require_support_function(SF_UNSIGNED_TO_BOOLEAN);
vhdl_fcall *conv =
new vhdl_fcall(support_function::function_name(SF_UNSIGNED_TO_BOOLEAN),
vhdl_type::boolean());
conv->add_expr(this);
return conv;
}
else if (type_->get_name() == VHDL_TYPE_SIGNED) {
require_support_function(SF_SIGNED_TO_BOOLEAN);
vhdl_fcall *conv =
new vhdl_fcall(support_function::function_name(SF_SIGNED_TO_BOOLEAN),
vhdl_type::boolean());
conv->add_expr(this);
return conv;
}
else {
assert(false);
}
}
/*
* Generate code to convert and expression to std_logic.
*/
vhdl_expr *vhdl_expr::to_std_logic()
{
if (type_->get_name() == VHDL_TYPE_BOOLEAN) {
require_support_function(SF_BOOLEAN_TO_LOGIC);
vhdl_fcall *ah =
new vhdl_fcall(support_function::function_name(SF_BOOLEAN_TO_LOGIC),
vhdl_type::std_logic());
ah->add_expr(this);
return ah;
}
else if (type_->get_name() == VHDL_TYPE_SIGNED) {
require_support_function(SF_SIGNED_TO_LOGIC);
vhdl_fcall *ah =
new vhdl_fcall(support_function::function_name(SF_SIGNED_TO_LOGIC),
vhdl_type::std_logic());
ah->add_expr(this);
return ah;
}
else if (type_->get_name() == VHDL_TYPE_UNSIGNED) {
require_support_function(SF_UNSIGNED_TO_LOGIC);
vhdl_fcall *ah =
new vhdl_fcall(support_function::function_name(SF_UNSIGNED_TO_LOGIC),
vhdl_type::std_logic());
ah->add_expr(this);
return ah;
}
else
assert(false);
}
/*
* Change the width of a signed/unsigned type.
*/
vhdl_expr *vhdl_expr::resize(int newwidth)
{
vhdl_type *rtype;
assert(type_);
if (type_->get_name() == VHDL_TYPE_SIGNED)
rtype = vhdl_type::nsigned(newwidth);
else if (type_->get_name() == VHDL_TYPE_UNSIGNED)
rtype = vhdl_type::nunsigned(newwidth);
else
return this; // Doesn't make sense to resize non-vector type
vhdl_fcall *resize = new vhdl_fcall("Resize", rtype);
resize->add_expr(this);
resize->add_expr(new vhdl_const_int(newwidth));
return resize;
}
vhdl_expr *vhdl_const_int::to_vector(vhdl_type_name_t name, int w)
{
if (name == VHDL_TYPE_SIGNED || name == VHDL_TYPE_UNSIGNED) {
const char *fname = name == VHDL_TYPE_SIGNED
? "To_Signed" : "To_Unsigned";
vhdl_fcall *conv = new vhdl_fcall(fname, new vhdl_type(name, w - 1, 0));
conv->add_expr(this);
conv->add_expr(new vhdl_const_int(w));
return conv;
}
else
return vhdl_expr::to_vector(name, w);
}
int vhdl_const_bits::bits_to_int() const
{
char msb = value_[value_.size() - 1];
int result = 0, bit;
for (int i = sizeof(int)*8 - 1; i >= 0; i--) {
if (i > (int)value_.size() - 1)
bit = msb == '1' ? 1 : 0;
else
bit = value_[i] == '1' ? 1 : 0;
result = (result << 1) | bit;
}
return result;
}
vhdl_expr *vhdl_const_bits::to_std_logic()
{
// VHDL won't let us cast directly between a vector and
// a scalar type
// But we don't need to here as we have the bits available
// Take the least significant bit
char lsb = value_[0];
return new vhdl_const_bit(lsb);
}
vhdl_expr *vhdl_const_bits::to_vector(vhdl_type_name_t name, int w)
{
if (name == VHDL_TYPE_STD_LOGIC_VECTOR) {
// Don't need to do anything
return this;
}
else if (name == VHDL_TYPE_SIGNED || name == VHDL_TYPE_UNSIGNED) {
// Extend with sign bit
value_.resize(w, value_[0]);
return this;
}
else
assert(false);
}
vhdl_expr *vhdl_const_bits::to_integer()
{
return new vhdl_const_int(bits_to_int());
}
vhdl_expr *vhdl_const_bit::to_integer()
{
return new vhdl_const_int(bit_ == '1' ? 1 : 0);
}
vhdl_expr *vhdl_const_bit::to_boolean()
{
return new vhdl_const_bool(bit_ == '1');
}

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