Merge branch 'master' into vec4-stack

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

View File

@ -1,7 +1,7 @@
#ifndef __AStatement_H #ifndef IVL_AStatement_H
#define __AStatement_H #define IVL_AStatement_H
/* /*
* Copyright (c) 2008 Stephen Williams (steve@icarus.com) * Copyright (c) 2008-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -82,4 +82,4 @@ class AProcess : public LineInfo {
AProcess& operator= (const AProcess&); AProcess& operator= (const AProcess&);
}; };
#endif #endif /* IVL_AStatement_H */

View File

@ -1,7 +1,7 @@
#ifndef __Attrib_H #ifndef IVL_Attrib_H
#define __Attrib_H #define IVL_Attrib_H
/* /*
* Copyright (c) 2000-2009 Stephen Williams (steve@icarus.com) * Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -57,4 +57,4 @@ class Attrib {
Attrib& operator= (const Attrib&); Attrib& operator= (const Attrib&);
}; };
#endif #endif /* IVL_Attrib_H */

View File

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

40
HName.h
View File

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

View File

@ -68,7 +68,7 @@ dllib=@DLLIB@
# For a cross compile these defines will need to be set accordingly. # For a cross compile these defines will need to be set accordingly.
HOSTCC = @CC@ HOSTCC = @CC@
HOSTCFLAGS = @WARNING_FLAGS@ @CFLAGS@ HOSTCFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
CC = @CC@ CC = @CC@
CXX = @CXX@ CXX = @CXX@
@ -90,7 +90,7 @@ INCLUDE_PATH = -I. -I$(srcdir) -I$(srcdir)/libmisc
endif endif
CPPFLAGS = @DEFS@ $(INCLUDE_PATH) @CPPFLAGS@ CPPFLAGS = @DEFS@ $(INCLUDE_PATH) @CPPFLAGS@
CFLAGS = @WARNING_FLAGS@ @CFLAGS@ CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@ CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@
PICFLAGS = @PICFLAG@ PICFLAGS = @PICFLAG@
LDFLAGS = @rdynamic@ @LDFLAGS@ LDFLAGS = @rdynamic@ @LDFLAGS@
@ -109,7 +109,7 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \ eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
load_module.o netlist.o netmisc.o nettypes.o net_analog.o net_assign.o \ load_module.o netlist.o netmisc.o nettypes.o net_analog.o net_assign.o \
net_design.o netclass.o netdarray.o \ net_design.o netclass.o netdarray.o \
netenum.o netparray.o netscalar.o netstruct.o netvector.o \ netenum.o netparray.o netqueue.o netscalar.o netstruct.o netvector.o \
net_event.o net_expr.o net_func.o \ net_event.o net_expr.o net_func.o \
net_func_eval.o net_link.o net_modulo.o \ net_func_eval.o net_link.o net_modulo.o \
net_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.o \ net_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.o \
@ -175,6 +175,8 @@ endif
cppcheck: $(O:.o=.cc) $(srcdir)/dosify.c $(srcdir)/version.c cppcheck: $(O:.o=.cc) $(srcdir)/dosify.c $(srcdir)/version.c
cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \ cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \
-UYYPARSE_PARAM -UYYPRINT -Ushort -Usize_t -Uyyoverflow \
-UYYTYPE_INT8 -UYYTYPE_INT16 -UYYTYPE_UINT8 -UYYTYPE_UINT16 \
--relative-paths=$(srcdir) $(INCLUDE_PATH) $^ --relative-paths=$(srcdir) $(INCLUDE_PATH) $^
cppcheck-all: cppcheck-all:

View File

@ -1,7 +1,7 @@
#ifndef __Module_H #ifndef IVL_Module_H
#define __Module_H #define IVL_Module_H
/* /*
* Copyright (c) 1998-2010,2012 Stephen Williams (steve@icarus.com) * Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -160,4 +160,4 @@ class Module : public PScopeExtra, public LineInfo {
Module& operator= (const Module&); Module& operator= (const Module&);
}; };
#endif #endif /* IVL_Module_H */

View File

@ -1,7 +1,7 @@
#ifndef __PClass_H #ifndef IVL_PClass_H
#define __PClass_H #define IVL_PClass_H
/* /*
* Copyright (c) 2012 Stephen Williams (steve@icarus.com) * Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -44,4 +44,4 @@ class PClass : public PScopeExtra, public LineInfo {
class_type_t*type; class_type_t*type;
}; };
#endif #endif /* IVL_PClass_H */

View File

@ -1,7 +1,7 @@
#ifndef __PDelays_H #ifndef IVL_PDelays_H
#define __PDelays_H #define IVL_PDelays_H
/* /*
* Copyright (c) 1999-2010 Stephen Williams (steve@icarus.com) * Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -72,4 +72,4 @@ class PDelays {
ostream& operator << (ostream&o, const PDelays&); ostream& operator << (ostream&o, const PDelays&);
#endif #endif /* IVL_PDelays_H */

View File

@ -1,7 +1,7 @@
#ifndef __PEvent_H #ifndef IVL_PEvent_H
#define __PEvent_H #define IVL_PEvent_H
/* /*
* Copyright (c) 2000-2004 Stephen Williams (steve@icarus.com) * Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -51,4 +51,4 @@ class PEvent : public LineInfo {
PEvent& operator= (const PEvent&); PEvent& operator= (const PEvent&);
}; };
#endif #endif /* IVL_PEvent_H */

31
PExpr.h
View File

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

View File

@ -1,7 +1,7 @@
#ifndef __PGate_H #ifndef IVL_PGate_H
#define __PGate_H #define IVL_PGate_H
/* /*
* Copyright (c) 1998-2011 Stephen Williams (steve@icarus.com) * Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -124,6 +124,7 @@ class PGAssign : public PGate {
virtual bool elaborate_sig(Design*des, NetScope*scope) const; virtual bool elaborate_sig(Design*des, NetScope*scope) const;
private: private:
void elaborate_unpacked_array_(Design*des, NetScope*scope, NetNet*lval) const;
}; };
@ -259,4 +260,4 @@ class PGModule : public PGate {
NetNet::PortType dir, bool as_signed) const; NetNet::PortType dir, bool as_signed) const;
}; };
#endif #endif /* IVL_PGate_H */

View File

@ -1,7 +1,7 @@
#ifndef __PGenerate_H #ifndef IVL_PGenerate_H
#define __PGenerate_H #define IVL_PGenerate_H
/* /*
* Copyright (c) 2006-2010,2012 Stephen Williams (steve@icarus.com) * Copyright (c) 2006-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -139,4 +139,4 @@ class PGenerate : public LineInfo, public LexicalScope {
extern std::ostream& operator << (std::ostream&, PGenerate::scheme_t); extern std::ostream& operator << (std::ostream&, PGenerate::scheme_t);
#endif #endif /* IVL_PGenerate_H */

View File

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

View File

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

View File

@ -1,7 +1,7 @@
#ifndef __PScope_H #ifndef IVL_PScope_H
#define __PScope_H #define IVL_PScope_H
/* /*
* Copyright (c) 2008,2010 Stephen Williams (steve@icarus.com) * Copyright (c) 2008-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -187,4 +187,4 @@ class PScopeExtra : public PScope {
void dump_funcs_(ostream&out, unsigned indent) const; void dump_funcs_(ostream&out, unsigned indent) const;
}; };
#endif #endif /* IVL_PScope_H */

View File

@ -1,7 +1,7 @@
#ifndef __PSpec_H #ifndef IVL_PSpec_H
#define __PSpec_H #define IVL_PSpec_H
/* /*
* Copyright (c) 2006-2011 Stephen Williams <steve@icarus.com> * Copyright (c) 2006-2014 Stephen Williams <steve@icarus.com>
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -84,4 +84,4 @@ class PSpecPath : public LineInfo {
std::vector<class PExpr*>delays; std::vector<class PExpr*>delays;
}; };
#endif #endif /* IVL_PSpec_H */

14
PTask.h
View File

@ -1,7 +1,7 @@
#ifndef __PTask_H #ifndef IVL_PTask_H
#define __PTask_H #define IVL_PTask_H
/* /*
* Copyright (c) 1999-2008,2010,2012 Stephen Williams (steve@icarus.com) * Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -49,6 +49,12 @@ class PTaskFunc : public PScope, public LineInfo {
// to the class type. // to the class type.
inline class_type_t* method_of() const { return this_type_; } inline class_type_t* method_of() const { return this_type_; }
virtual void elaborate_sig(Design*des, NetScope*scope) const =0;
virtual void elaborate(Design*des, NetScope*scope) const =0;
virtual void dump(std::ostream&, unsigned) const =0;
protected: protected:
// Elaborate the ports list. Write into the ports vector the // Elaborate the ports list. Write into the ports vector the
// NetNet pointers for the ports, and write into the pdefs the // NetNet pointers for the ports, and write into the pdefs the
@ -146,4 +152,4 @@ class PFunction : public PTaskFunc {
bool is_auto_; bool is_auto_;
}; };
#endif #endif /* IVL_PTask_H */

8
PUdp.h
View File

@ -1,7 +1,7 @@
#ifndef __PUdp_H #ifndef IVL_PUdp_H
#define __PUdp_H #define IVL_PUdp_H
/* /*
* Copyright (c) 1998-2011 Stephen Williams (steve@picturel.com) * Copyright (c) 1998-2014 Stephen Williams (steve@picturel.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -76,4 +76,4 @@ class PUdp : public LineInfo {
PUdp& operator= (const PUdp&); PUdp& operator= (const PUdp&);
}; };
#endif #endif /* IVL_PUdp_H */

View File

@ -1,7 +1,7 @@
#ifndef __PWire_H #ifndef IVL_PWire_H
#define __PWire_H #define IVL_PWire_H
/* /*
* Copyright (c) 1998-2009,2012 Stephen Williams (steve@icarus.com) * Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -129,4 +129,4 @@ class PWire : public LineInfo {
PWire& operator= (const PWire&); PWire& operator= (const PWire&);
}; };
#endif #endif /* IVL_PWire_H */

View File

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

View File

@ -1,7 +1,7 @@
#ifndef __Statement_H #ifndef IVL_Statement_H
#define __Statement_H #define IVL_Statement_H
/* /*
* Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com) * Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -224,12 +224,16 @@ class PCallTask : public Statement {
NetProc* elaborate_sys(Design*des, NetScope*scope) const; NetProc* elaborate_sys(Design*des, NetScope*scope) const;
NetProc* elaborate_usr(Design*des, NetScope*scope) const; NetProc* elaborate_usr(Design*des, NetScope*scope) const;
NetProc*elaborate_method_(Design*des, NetScope*scope) const; NetProc*elaborate_method_(Design*des, NetScope*scope,
bool add_this_flag = false) const;
NetProc*elaborate_function_(Design*des, NetScope*scope) const; NetProc*elaborate_function_(Design*des, NetScope*scope) const;
NetProc*elaborate_build_call_(Design*des, NetScope*scope, NetProc*elaborate_build_call_(Design*des, NetScope*scope,
NetScope*task, NetExpr*use_this) const; NetScope*task, NetExpr*use_this) const;
NetProc*elaborate_sys_task_method_(Design*des, NetScope*scope,
NetNet*net,
perm_string method_name,
const char*sys_task_name) const;
bool test_task_calls_ok_(Design*des, NetScope*scope) const; bool test_task_calls_ok_(Design*des, NetScope*scope) const;
PPackage*package_; PPackage*package_;
@ -440,6 +444,26 @@ class PForce : public Statement {
PExpr*expr_; PExpr*expr_;
}; };
class PForeach : public Statement {
public:
explicit PForeach(perm_string var, const std::list<perm_string>&ix, Statement*stmt);
~PForeach();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
NetProc* elaborate_static_array_(Design*des, NetScope*scope,
const std::vector<netrange_t>&dims) const;
private:
perm_string array_var_;
std::vector<perm_string> index_vars_;
Statement*statement_;
};
class PForever : public Statement { class PForever : public Statement {
public: public:
explicit PForever(Statement*s); explicit PForever(Statement*s);
@ -558,4 +582,4 @@ class PWhile : public Statement {
Statement*statement_; Statement*statement_;
}; };
#endif #endif /* IVL_Statement_H */

View File

@ -1,7 +1,7 @@
#ifndef PLI_TYPES #ifndef PLI_TYPES_H
#define PLI_TYPES #define PLI_TYPES_H
/* /*
* Copyright (c) 2003 Stephen Williams (steve@icarus.com) * Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -85,4 +85,4 @@ typedef char PLI_BYTE8;
typedef unsigned char PLI_UBYTE8; typedef unsigned char PLI_UBYTE8;
#endif #endif
#endif #endif /* PLI_TYPES_H */

View File

@ -1,7 +1,7 @@
#ifndef __acc_user_H #ifndef ACC_USER_H
#define __acc_user_H #define ACC_USER_H
/* /*
* Copyright (c) 2002 Stephen Williams (steve@icarus.com) * Copyright (c) 2002-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -228,6 +228,7 @@ extern PLI_INT32 acc_fetch_size(handle obj);
extern PLI_INT32 acc_fetch_type(handle obj); extern PLI_INT32 acc_fetch_type(handle obj);
extern PLI_INT32 acc_fetch_fulltype(handle obj); extern PLI_INT32 acc_fetch_fulltype(handle obj);
extern PLI_INT32 acc_fetch_paramtype(handle obj);
extern PLI_INT32 acc_fetch_range(handle object, int *msb, int *lsb); extern PLI_INT32 acc_fetch_range(handle object, int *msb, int *lsb);
extern const char* acc_fetch_type_str(PLI_INT32 type); extern const char* acc_fetch_type_str(PLI_INT32 type);
@ -270,4 +271,4 @@ extern char* acc_version(void);
EXTERN_C_END EXTERN_C_END
#endif #endif /* ACC_USER_H */

11
aclocal.m4 vendored
View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
#ifndef __ivl_dlfcn_H #ifndef IVL_ivl_dlfcn_H
#define __ivl_dlfcn_H #define IVL_ivl_dlfcn_H
/* /*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com) * Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -91,4 +91,4 @@ static __inline__ const char*dlerror(void)
{ return strerror( errno ); } { return strerror( errno ); }
#endif #endif
#endif #endif /* IVL_ivl_dlfcn_H */

View File

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

View File

@ -1,7 +1,7 @@
#ifndef __config_H /* -*- c++ -*- */ #ifndef IVL_config_H /* -*- c++ -*- */
#define __config_H #define IVL_config_H
/* /*
* Copyright (c) 2001-2012 Stephen Williams (steve@icarus.com) * Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -62,4 +62,4 @@
*/ */
# undef CHECK_WITH_VALGRIND # undef CHECK_WITH_VALGRIND
#endif /* __config_H */ #endif /* IVL_config_H */

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
#ifndef __discipline_H #ifndef IVL_discipline_H
#define __discipline_H #define IVL_discipline_H
/* /*
* Copyright (c) 2008-2010 Stephen Williams (steve@icarus.com) * Copyright (c) 2008-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -74,4 +74,4 @@ extern map<perm_string,ivl_discipline_t> disciplines;
// Map access function name to the nature that it accesses. // Map access function name to the nature that it accesses.
extern map<perm_string,ivl_nature_t> access_function_nature; extern map<perm_string,ivl_nature_t> access_function_nature;
#endif #endif /* IVL_discipline_H */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

45
emit.cc
View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
#ifndef __functor_H #ifndef IVL_functor_H
#define __functor_H #define IVL_functor_H
/* /*
* Copyright (c) 1999-2008,2012 Stephen Williams (steve@icarus.com) * Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -105,4 +105,4 @@ struct proc_match_t {
virtual int block(class NetBlock*); virtual int block(class NetBlock*);
}; };
#endif #endif /* IVL_functor_H */

View File

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

View File

@ -1,5 +1,7 @@
#ifndef IVL_ivl_assert_H
#define IVL_ivl_assert_H
/* /*
* Copyright (c) 2007-2010 Stephen Williams (steve@icarus.com) * Copyright (c) 2007-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -17,9 +19,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
#ifndef __ivl_assert_h
#define __ivl_assert_h
# include <cstdlib> # include <cstdlib>
#define ivl_assert(tok, expression) \ #define ivl_assert(tok, expression) \
@ -32,4 +31,4 @@
} \ } \
} while (0) } while (0)
#endif #endif /* IVL_ivl_assert_H */

View File

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

View File

@ -1,7 +1,7 @@
#ifndef __ivl_target_priv_H #ifndef IVL_ivl_target_priv_H
#define __ivl_target_priv_H #define IVL_ivl_target_priv_H
/* /*
* Copyright (c) 2008 Stephen Williams (steve@icarus.com) * Copyright (c) 2008-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -52,6 +52,7 @@ struct ivl_design_s {
// Keep arrays of root scopes. // Keep arrays of root scopes.
std::map<const NetScope*,ivl_scope_t> classes; std::map<const NetScope*,ivl_scope_t> classes;
std::map<const NetScope*,ivl_scope_t> root_tasks;
std::vector<ivl_scope_t> packages; std::vector<ivl_scope_t> packages;
std::vector<ivl_scope_t> roots; std::vector<ivl_scope_t> roots;
@ -90,4 +91,4 @@ struct ivl_island_s {
extern std::ostream& operator << (std::ostream&o, ivl_drive_t str); extern std::ostream& operator << (std::ostream&o, ivl_drive_t str);
#endif #endif /* IVL_ivl_target_priv_H */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
#ifndef __LineInfo_H #ifndef IVL_LineInfo_H
#define __LineInfo_H #define IVL_LineInfo_H
/* /*
* Copyright (c) 1999-2011 Stephen Williams (steve@icarus.com) * Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -54,4 +54,4 @@ class LineInfo {
unsigned lineno_; unsigned lineno_;
}; };
#endif #endif /* IVL_LineInfo_H */

View File

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

View File

@ -1,7 +1,7 @@
#ifndef __StringHeap_H #ifndef IVL_StringHeap_H
#define __StringHeap_H #define IVL_StringHeap_H
/* /*
* Copyright (c) 2002-2009 Stephen Williams (steve@icarus.com) * Copyright (c) 2002-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -52,6 +52,7 @@ class perm_string {
const char*text_; const char*text_;
}; };
extern const perm_string empty_perm_string;
extern bool operator == (perm_string a, perm_string b); extern bool operator == (perm_string a, perm_string b);
extern bool operator == (perm_string a, const char* b); extern bool operator == (perm_string a, const char* b);
extern bool operator != (perm_string a, perm_string b); extern bool operator != (perm_string a, perm_string b);
@ -120,4 +121,4 @@ class StringHeapLex : private StringHeap {
StringHeapLex& operator= (const StringHeapLex&); StringHeapLex& operator= (const StringHeapLex&);
}; };
#endif #endif /* IVL_StringHeap_H */

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003 Stephen Williams (steve@picturel.com) * Copyright (c) 2003-2014 Stephen Williams (steve@picturel.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -25,6 +25,7 @@
PLI_INT32 acc_fetch_direction(handle obj) PLI_INT32 acc_fetch_direction(handle obj)
{ {
(void)obj; /* Parameter is not used. */
if (pli_trace) { if (pli_trace) {
fprintf(pli_trace, "acc_fetch_direction: enter.\n"); fprintf(pli_trace, "acc_fetch_direction: enter.\n");
fflush(pli_trace); fflush(pli_trace);

View File

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

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003-2010 Stephen Williams (steve@icarus.com) * Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -40,3 +40,12 @@ const char* acc_fetch_type_str(PLI_INT32 type)
vpi_printf("acc_fetch_type_str: type %d is what accType?\n", (int)type); vpi_printf("acc_fetch_type_str: type %d is what accType?\n", (int)type);
return "acc_fetch_type_str(unknown)"; return "acc_fetch_type_str(unknown)";
} }
/*
* FIXME: What does this do? How should it be declared in acc_user.h?
*/
PLI_INT32 acc_fetch_paramtype(handle obj)
{
(void)obj; /* Parameter is not used. */
return 0;
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003 Stephen Williams (steve@picturel.com) * Copyright (c) 2003-2014 Stephen Williams (steve@picturel.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -25,6 +25,7 @@
handle acc_handle_hiconn(handle obj) handle acc_handle_hiconn(handle obj)
{ {
(void)obj; /* Parameter is not used. */
if (pli_trace) { if (pli_trace) {
fprintf(pli_trace, "acc_handle_hiconn: enter.\n"); fprintf(pli_trace, "acc_handle_hiconn: enter.\n");
fflush(pli_trace); fflush(pli_trace);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003 Stephen Williams (steve@picturel.com) * Copyright (c) 2003-2014 Stephen Williams (steve@picturel.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -25,6 +25,8 @@
handle acc_next_bit(handle ref, handle bit) handle acc_next_bit(handle ref, handle bit)
{ {
(void)ref; /* Parameter is not used. */
(void)bit; /* Parameter is not used. */
if (pli_trace) { if (pli_trace) {
fprintf(pli_trace, "acc_next_bit: enter.\n"); fprintf(pli_trace, "acc_next_bit: enter.\n");
fflush(pli_trace); fflush(pli_trace);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003 Stephen Williams (steve@icarus.com) * Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -25,6 +25,8 @@
handle acc_next_port(handle ref, handle bit) handle acc_next_port(handle ref, handle bit)
{ {
(void)ref; /* Parameter is not used. */
(void)bit; /* Parameter is not used. */
if (pli_trace) { if (pli_trace) {
fprintf(pli_trace, "acc_next_port: enter.\n"); fprintf(pli_trace, "acc_next_port: enter.\n");
fflush(pli_trace); fflush(pli_trace);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003-2010 Stephen Williams (steve@icarus.com) * Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -162,6 +162,7 @@ void acc_vcl_add(handle obj, PLI_INT32(*consumer)(p_vc_record),
switch (vpi_get(vpiType, obj)) { switch (vpi_get(vpiType, obj)) {
case vpiNet: case vpiNet:
case vpiReg:
cur = malloc(sizeof (struct vcl_record)); cur = malloc(sizeof (struct vcl_record));
cur->obj = obj; cur->obj = obj;
cur->consumer = consumer; cur->consumer = consumer;
@ -195,5 +196,9 @@ void acc_vcl_add(handle obj, PLI_INT32(*consumer)(p_vc_record),
void acc_vcl_delete(handle obj, PLI_INT32(*consumer)(p_vc_record), void acc_vcl_delete(handle obj, PLI_INT32(*consumer)(p_vc_record),
void*data, PLI_INT32 vcl_flag) void*data, PLI_INT32 vcl_flag)
{ {
(void)obj; /* Parameter is not used. */
(void)consumer; /* Parameter is not used. */
(void)data; /* Parameter is not used. */
(void)vcl_flag; /* Parameter is not used. */
vpi_printf("XXXX acc_vcl_delete(...)\n"); vpi_printf("XXXX acc_vcl_delete(...)\n");
} }

View File

@ -1,7 +1,7 @@
#ifndef __config_H #ifndef IVL_config_H
#define __config_H #define IVL_config_H
/* /*
* Copyright (c) 2003 Stephen Williams (steve@icarus.com) * Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -37,4 +37,4 @@ typedef unsigned long ivl_u64_t;
# endif # endif
#endif #endif
#endif #endif /* IVL_config_H */

View File

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

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003 Stephen Williams (steve@icarus.com) * Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -25,6 +25,8 @@
struct t_tfexprinfo* tf_exprinfo(PLI_INT32 a, struct t_tfexprinfo*ip) struct t_tfexprinfo* tf_exprinfo(PLI_INT32 a, struct t_tfexprinfo*ip)
{ {
(void)a; /* Parameter is not used. */
(void)ip; /* Parameter is not used. */
if (pli_trace) { if (pli_trace) {
fprintf(pli_trace, "tf_exprinfo: enter.\n"); fprintf(pli_trace, "tf_exprinfo: enter.\n");
fflush(pli_trace); fflush(pli_trace);

View File

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

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2002 Michael Ruff (mruff at chiaro.com) * Copyright (c) 2002-2014 Michael Ruff (mruff at chiaro.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -58,6 +58,8 @@ PLI_INT32 tf_message(PLI_INT32 level, char*facility,
{ {
va_list ap; va_list ap;
(void)level; /* Parameter is not used. */
vpi_printf("%s[%s] ", facility, messno); vpi_printf("%s[%s] ", facility, messno);
va_start(ap, fmt); va_start(ap, fmt);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003 Stephen Williams (steve@icarus.com) * Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -23,8 +23,11 @@
# include <vpi_user.h> # include <vpi_user.h>
# include "priv.h" # include "priv.h"
struct t_tfnoeinfo* tf_nodeinfo(PLI_INT32 a, struct t_tfnodeinfo*ip) /* XXX Not declared or used anywhere? */
struct t_tfnodeinfo* tf_nodeinfo(PLI_INT32 a, struct t_tfnodeinfo*ip)
{ {
(void)a; /* Parameter is not used. */
(void)ip; /* Parameter is not used. */
if (pli_trace) { if (pli_trace) {
fprintf(pli_trace, "tf_nodeinfo: enter.\n"); fprintf(pli_trace, "tf_nodeinfo: enter.\n");
fflush(pli_trace); fflush(pli_trace);

View File

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

View File

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

View File

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

View File

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

16
main.cc
View File

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

View File

@ -1,7 +1,7 @@
#ifndef __named_H #ifndef IVL_named_H
#define __named_H #define IVL_named_H
/* /*
* Copyright (c) 2000-2004 Stephen Williams (steve@icarus.com) * Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -31,4 +31,4 @@ template <class T> struct named {
T parm; T parm;
}; };
#endif #endif /* IVL_named_H */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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