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:
commit
a98f21aa65
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __AStatement_H
|
||||
#define __AStatement_H
|
||||
#ifndef IVL_AStatement_H
|
||||
#define IVL_AStatement_H
|
||||
/*
|
||||
* Copyright (c) 2008 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2008-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -82,4 +82,4 @@ class AProcess : public LineInfo {
|
|||
AProcess& operator= (const AProcess&);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_AStatement_H */
|
||||
|
|
|
|||
8
Attrib.h
8
Attrib.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __Attrib_H
|
||||
#define __Attrib_H
|
||||
#ifndef IVL_Attrib_H
|
||||
#define IVL_Attrib_H
|
||||
/*
|
||||
* Copyright (c) 2000-2009 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -57,4 +57,4 @@ class Attrib {
|
|||
Attrib& operator= (const Attrib&);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_Attrib_H */
|
||||
|
|
|
|||
68
HName.cc
68
HName.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -22,22 +22,26 @@
|
|||
# include <iostream>
|
||||
# include <cstring>
|
||||
# include <cstdlib>
|
||||
# include <climits>
|
||||
|
||||
using namespace std;
|
||||
|
||||
hname_t::hname_t()
|
||||
{
|
||||
number_ = INT_MIN;
|
||||
}
|
||||
|
||||
hname_t::hname_t(perm_string text)
|
||||
: name_(text)
|
||||
{
|
||||
number_ = INT_MIN;
|
||||
}
|
||||
|
||||
hname_t::hname_t(perm_string text, int num)
|
||||
: name_(text), number_(num)
|
||||
: name_(text), number_(1)
|
||||
{
|
||||
number_[0] = num;
|
||||
}
|
||||
|
||||
hname_t::hname_t(perm_string text, vector<int>&nums)
|
||||
: name_(text), number_(nums)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -53,24 +57,50 @@ hname_t& hname_t::operator = (const hname_t&that)
|
|||
return *this;
|
||||
}
|
||||
|
||||
bool operator < (const hname_t&l, const hname_t&r)
|
||||
bool hname_t::operator < (const hname_t&r) const
|
||||
{
|
||||
int cmp = strcmp(l.peek_name(), r.peek_name());
|
||||
int cmp = strcmp(name_, r.name_);
|
||||
if (cmp < 0) return true;
|
||||
if (cmp > 0) return false;
|
||||
if (l.has_number() && r.has_number())
|
||||
return l.peek_number() < r.peek_number();
|
||||
else
|
||||
return false;
|
||||
|
||||
// The text parts are equal, so compare then number
|
||||
// parts. Finish as soon as we find one to be less or more
|
||||
// than the other.
|
||||
size_t idx = 0;
|
||||
while (number_.size() > idx || r.number_.size() > idx) {
|
||||
|
||||
// Ran out of l numbers, so less.
|
||||
if (number_.size() <= idx)
|
||||
return true;
|
||||
|
||||
// Ran out of r numbers, so greater.
|
||||
if (r.number_.size() <= idx)
|
||||
return false;
|
||||
|
||||
if (number_[idx] < r.number_[idx])
|
||||
return true;
|
||||
|
||||
if (number_[idx] > r.number_[idx])
|
||||
return false;
|
||||
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
// Fall-through means that we are equal, including all the
|
||||
// number parts, so not less.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator == (const hname_t&l, const hname_t&r)
|
||||
bool hname_t::operator == (const hname_t&r) const
|
||||
{
|
||||
if (l.peek_name() == r.peek_name()) {
|
||||
if (l.has_number() && r.has_number())
|
||||
return l.peek_number() == r.peek_number();
|
||||
else
|
||||
return true;
|
||||
if (name_ == r.name_) {
|
||||
if (number_.size() != r.number_.size())
|
||||
return false;
|
||||
|
||||
for (size_t idx = 0 ; idx < number_.size() ; idx += 1)
|
||||
if (number_[idx] != r.number_[idx]) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -84,8 +114,8 @@ ostream& operator<< (ostream&out, const hname_t&that)
|
|||
}
|
||||
|
||||
out << that.peek_name();
|
||||
if (that.has_number())
|
||||
out << "[" << that.peek_number() << "]";
|
||||
for (size_t idx = 0 ; idx < that.number_.size() ; idx += 1)
|
||||
out << "[" << that.number_[idx] << "]";
|
||||
|
||||
return out;
|
||||
}
|
||||
|
|
|
|||
40
HName.h
40
HName.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __HName_H
|
||||
#define __HName_H
|
||||
#ifndef IVL_HName_H
|
||||
#define IVL_HName_H
|
||||
/*
|
||||
* Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -21,13 +21,10 @@
|
|||
|
||||
# include <iostream>
|
||||
# include <list>
|
||||
# include <vector>
|
||||
# include "StringHeap.h"
|
||||
# include <climits>
|
||||
#ifdef __GNUC__
|
||||
#if __GNUC__ > 2
|
||||
using namespace std;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
# include <cassert>
|
||||
|
||||
/*
|
||||
* This class represents a component of a Verilog hierarchical name. A
|
||||
|
|
@ -39,27 +36,33 @@ using namespace std;
|
|||
|
||||
class hname_t {
|
||||
|
||||
friend ostream& operator<< (ostream&out, const hname_t&that);
|
||||
|
||||
public:
|
||||
hname_t ();
|
||||
explicit hname_t (perm_string text);
|
||||
explicit hname_t (perm_string text, int num);
|
||||
explicit hname_t (perm_string text, std::vector<int>&nums);
|
||||
hname_t (const hname_t&that);
|
||||
~hname_t();
|
||||
|
||||
hname_t& operator= (const hname_t&);
|
||||
|
||||
bool operator == (const hname_t&that) const;
|
||||
bool operator < (const hname_t&that) const;
|
||||
|
||||
// Return the string part of the hname_t.
|
||||
perm_string peek_name(void) const;
|
||||
|
||||
bool has_number() const;
|
||||
int peek_number() const;
|
||||
size_t has_numbers() const;
|
||||
int peek_number(size_t idx) const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
// If the number is anything other than INT_MIN, then this is
|
||||
// the numeric part of the name. Otherwise, it is not part of
|
||||
// the name at all.
|
||||
int number_;
|
||||
std::vector<int> number_;
|
||||
|
||||
private: // not implemented
|
||||
};
|
||||
|
|
@ -73,18 +76,17 @@ inline perm_string hname_t::peek_name(void) const
|
|||
return name_;
|
||||
}
|
||||
|
||||
inline int hname_t::peek_number() const
|
||||
inline int hname_t::peek_number(size_t idx) const
|
||||
{
|
||||
return number_;
|
||||
assert(number_.size() > idx);
|
||||
return number_[idx];
|
||||
}
|
||||
|
||||
inline bool hname_t::has_number() const
|
||||
inline size_t hname_t::has_numbers() const
|
||||
{
|
||||
return number_ != INT_MIN;
|
||||
return number_.size();
|
||||
}
|
||||
|
||||
extern bool operator < (const hname_t&, const hname_t&);
|
||||
extern bool operator == (const hname_t&, const hname_t&);
|
||||
extern ostream& operator<< (ostream&, const hname_t&);
|
||||
|
||||
inline bool operator != (const hname_t&l, const hname_t&r)
|
||||
|
|
@ -102,4 +104,4 @@ inline ostream& operator<< (ostream&out, const list<hname_t>&ll)
|
|||
return out;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* IVL_HName_H */
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ dllib=@DLLIB@
|
|||
|
||||
# For a cross compile these defines will need to be set accordingly.
|
||||
HOSTCC = @CC@
|
||||
HOSTCFLAGS = @WARNING_FLAGS@ @CFLAGS@
|
||||
HOSTCFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
||||
|
||||
CC = @CC@
|
||||
CXX = @CXX@
|
||||
|
|
@ -90,7 +90,7 @@ INCLUDE_PATH = -I. -I$(srcdir) -I$(srcdir)/libmisc
|
|||
endif
|
||||
|
||||
CPPFLAGS = @DEFS@ $(INCLUDE_PATH) @CPPFLAGS@
|
||||
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
|
||||
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
||||
CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@
|
||||
PICFLAGS = @PICFLAG@
|
||||
LDFLAGS = @rdynamic@ @LDFLAGS@
|
||||
|
|
@ -109,7 +109,7 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
|
|||
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
|
||||
load_module.o netlist.o netmisc.o nettypes.o net_analog.o net_assign.o \
|
||||
net_design.o netclass.o netdarray.o \
|
||||
netenum.o netparray.o netscalar.o netstruct.o netvector.o \
|
||||
netenum.o netparray.o netqueue.o netscalar.o netstruct.o netvector.o \
|
||||
net_event.o net_expr.o net_func.o \
|
||||
net_func_eval.o net_link.o net_modulo.o \
|
||||
net_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.o \
|
||||
|
|
@ -175,6 +175,8 @@ endif
|
|||
|
||||
cppcheck: $(O:.o=.cc) $(srcdir)/dosify.c $(srcdir)/version.c
|
||||
cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \
|
||||
-UYYPARSE_PARAM -UYYPRINT -Ushort -Usize_t -Uyyoverflow \
|
||||
-UYYTYPE_INT8 -UYYTYPE_INT16 -UYYTYPE_UINT8 -UYYTYPE_UINT16 \
|
||||
--relative-paths=$(srcdir) $(INCLUDE_PATH) $^
|
||||
|
||||
cppcheck-all:
|
||||
|
|
|
|||
8
Module.h
8
Module.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __Module_H
|
||||
#define __Module_H
|
||||
#ifndef IVL_Module_H
|
||||
#define IVL_Module_H
|
||||
/*
|
||||
* Copyright (c) 1998-2010,2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -160,4 +160,4 @@ class Module : public PScopeExtra, public LineInfo {
|
|||
Module& operator= (const Module&);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_Module_H */
|
||||
|
|
|
|||
8
PClass.h
8
PClass.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __PClass_H
|
||||
#define __PClass_H
|
||||
#ifndef IVL_PClass_H
|
||||
#define IVL_PClass_H
|
||||
/*
|
||||
* Copyright (c) 2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -44,4 +44,4 @@ class PClass : public PScopeExtra, public LineInfo {
|
|||
class_type_t*type;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PClass_H */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __PDelays_H
|
||||
#define __PDelays_H
|
||||
#ifndef IVL_PDelays_H
|
||||
#define IVL_PDelays_H
|
||||
/*
|
||||
* Copyright (c) 1999-2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -72,4 +72,4 @@ class PDelays {
|
|||
|
||||
ostream& operator << (ostream&o, const PDelays&);
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PDelays_H */
|
||||
|
|
|
|||
8
PEvent.h
8
PEvent.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __PEvent_H
|
||||
#define __PEvent_H
|
||||
#ifndef IVL_PEvent_H
|
||||
#define IVL_PEvent_H
|
||||
/*
|
||||
* Copyright (c) 2000-2004 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -51,4 +51,4 @@ class PEvent : public LineInfo {
|
|||
PEvent& operator= (const PEvent&);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PEvent_H */
|
||||
|
|
|
|||
31
PExpr.h
31
PExpr.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __PExpr_H
|
||||
#define __PExpr_H
|
||||
#ifndef IVL_PExpr_H
|
||||
#define IVL_PExpr_H
|
||||
/*
|
||||
* Copyright (c) 1998-2013 Stephen Williams <steve@icarus.com>
|
||||
* Copyright (c) 1998-2014 Stephen Williams <steve@icarus.com>
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
|
|
@ -245,6 +245,10 @@ class PEConcat : public PExpr {
|
|||
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
|
||||
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t type, unsigned flags) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
|
|
@ -366,6 +370,11 @@ class PEIdent : public PExpr {
|
|||
// only applies to Ident expressions.
|
||||
NetNet* elaborate_subport(Design*des, NetScope*sc) const;
|
||||
|
||||
// Elaborate the identifier allowing for unpacked arrays. This
|
||||
// method only applies to Ident expressions because only Ident
|
||||
// expressions can can be unpacked arrays.
|
||||
NetNet* elaborate_unpacked_net(Design*des, NetScope*sc) const;
|
||||
|
||||
verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual bool is_collapsible_net(Design*des, NetScope*scope) const;
|
||||
|
|
@ -500,12 +509,23 @@ class PEIdent : public PExpr {
|
|||
NetESignal*net,
|
||||
NetScope*found,
|
||||
bool need_const) const;
|
||||
NetExpr*elaborate_expr_net_bit_last_(Design*des,
|
||||
NetScope*scope,
|
||||
NetESignal*net,
|
||||
NetScope*found,
|
||||
bool need_const) const;
|
||||
|
||||
NetExpr*elaborate_expr_class_member_(Design*des,
|
||||
NetScope*scope,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
|
||||
unsigned test_width_method_(Design*des, NetScope*scope, width_mode_t&mode);
|
||||
NetExpr*elaborate_expr_method_(Design*des,
|
||||
NetScope*scope,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
|
||||
private:
|
||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
bool bidirectional_flag) const;
|
||||
|
|
@ -916,7 +936,8 @@ class PECallFunction : public PExpr {
|
|||
NetExpr*elaborate_expr_pkg_(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, unsigned flags)const;
|
||||
NetExpr*elaborate_expr_method_(Design*des, NetScope*scope,
|
||||
unsigned expr_wid) const;
|
||||
unsigned expr_wid,
|
||||
bool add_this_flag = false) const;
|
||||
#if 0
|
||||
NetExpr*elaborate_expr_string_method_(Design*des, NetScope*scope) const;
|
||||
NetExpr*elaborate_expr_enum_method_(Design*des, NetScope*scope,
|
||||
|
|
@ -980,4 +1001,4 @@ class PEVoid : public PExpr {
|
|||
unsigned flags) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PExpr_H */
|
||||
|
|
|
|||
9
PGate.h
9
PGate.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __PGate_H
|
||||
#define __PGate_H
|
||||
#ifndef IVL_PGate_H
|
||||
#define IVL_PGate_H
|
||||
/*
|
||||
* Copyright (c) 1998-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -124,6 +124,7 @@ class PGAssign : public PGate {
|
|||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
void elaborate_unpacked_array_(Design*des, NetScope*scope, NetNet*lval) const;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -259,4 +260,4 @@ class PGModule : public PGate {
|
|||
NetNet::PortType dir, bool as_signed) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PGate_H */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __PGenerate_H
|
||||
#define __PGenerate_H
|
||||
#ifndef IVL_PGenerate_H
|
||||
#define IVL_PGenerate_H
|
||||
/*
|
||||
* Copyright (c) 2006-2010,2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2006-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -139,4 +139,4 @@ class PGenerate : public LineInfo, public LexicalScope {
|
|||
|
||||
extern std::ostream& operator << (std::ostream&, PGenerate::scheme_t);
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PGenerate_H */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __PPackage_H
|
||||
#define __PPackage_H
|
||||
#ifndef IVL_PPackage_H
|
||||
#define IVL_PPackage_H
|
||||
/*
|
||||
* Copyright (c) 2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
|
|
@ -44,4 +44,4 @@ class PPackage : public PScopeExtra, public LineInfo {
|
|||
void pform_dump(std::ostream&out) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PPackage_H */
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ PScope::PScope(perm_string n)
|
|||
|
||||
PScope::~PScope()
|
||||
{
|
||||
for(map<perm_string, data_type_t*>::iterator it = typedefs.begin();
|
||||
it != typedefs.end(); ++it)
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
PWire* LexicalScope::wires_find(perm_string name)
|
||||
|
|
|
|||
8
PScope.h
8
PScope.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __PScope_H
|
||||
#define __PScope_H
|
||||
#ifndef IVL_PScope_H
|
||||
#define IVL_PScope_H
|
||||
/*
|
||||
* Copyright (c) 2008,2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2008-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -187,4 +187,4 @@ class PScopeExtra : public PScope {
|
|||
void dump_funcs_(ostream&out, unsigned indent) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PScope_H */
|
||||
|
|
|
|||
8
PSpec.h
8
PSpec.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __PSpec_H
|
||||
#define __PSpec_H
|
||||
#ifndef IVL_PSpec_H
|
||||
#define IVL_PSpec_H
|
||||
/*
|
||||
* Copyright (c) 2006-2011 Stephen Williams <steve@icarus.com>
|
||||
* Copyright (c) 2006-2014 Stephen Williams <steve@icarus.com>
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -84,4 +84,4 @@ class PSpecPath : public LineInfo {
|
|||
std::vector<class PExpr*>delays;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PSpec_H */
|
||||
|
|
|
|||
14
PTask.h
14
PTask.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __PTask_H
|
||||
#define __PTask_H
|
||||
#ifndef IVL_PTask_H
|
||||
#define IVL_PTask_H
|
||||
/*
|
||||
* Copyright (c) 1999-2008,2010,2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -49,6 +49,12 @@ class PTaskFunc : public PScope, public LineInfo {
|
|||
// to the class type.
|
||||
inline class_type_t* method_of() const { return this_type_; }
|
||||
|
||||
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const =0;
|
||||
virtual void elaborate(Design*des, NetScope*scope) const =0;
|
||||
|
||||
virtual void dump(std::ostream&, unsigned) const =0;
|
||||
|
||||
protected:
|
||||
// Elaborate the ports list. Write into the ports vector the
|
||||
// NetNet pointers for the ports, and write into the pdefs the
|
||||
|
|
@ -146,4 +152,4 @@ class PFunction : public PTaskFunc {
|
|||
bool is_auto_;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PTask_H */
|
||||
|
|
|
|||
8
PUdp.h
8
PUdp.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __PUdp_H
|
||||
#define __PUdp_H
|
||||
#ifndef IVL_PUdp_H
|
||||
#define IVL_PUdp_H
|
||||
/*
|
||||
* Copyright (c) 1998-2011 Stephen Williams (steve@picturel.com)
|
||||
* Copyright (c) 1998-2014 Stephen Williams (steve@picturel.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -76,4 +76,4 @@ class PUdp : public LineInfo {
|
|||
PUdp& operator= (const PUdp&);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PUdp_H */
|
||||
|
|
|
|||
8
PWire.h
8
PWire.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __PWire_H
|
||||
#define __PWire_H
|
||||
#ifndef IVL_PWire_H
|
||||
#define IVL_PWire_H
|
||||
/*
|
||||
* Copyright (c) 1998-2009,2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -129,4 +129,4 @@ class PWire : public LineInfo {
|
|||
PWire& operator= (const PWire&);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_PWire_H */
|
||||
|
|
|
|||
14
Statement.cc
14
Statement.cc
|
|
@ -336,6 +336,20 @@ PForce::~PForce()
|
|||
delete expr_;
|
||||
}
|
||||
|
||||
PForeach::PForeach(perm_string av, const list<perm_string>&ix, Statement*s)
|
||||
: array_var_(av), index_vars_(ix.size()), statement_(s)
|
||||
{
|
||||
size_t idx = 0;
|
||||
for (list<perm_string>::const_iterator cur = ix.begin()
|
||||
; cur != ix.end() ; ++cur)
|
||||
index_vars_[idx++] = *cur;
|
||||
}
|
||||
|
||||
PForeach::~PForeach()
|
||||
{
|
||||
delete statement_;
|
||||
}
|
||||
|
||||
PForever::PForever(Statement*s)
|
||||
: statement_(s)
|
||||
{
|
||||
|
|
|
|||
36
Statement.h
36
Statement.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __Statement_H
|
||||
#define __Statement_H
|
||||
#ifndef IVL_Statement_H
|
||||
#define IVL_Statement_H
|
||||
/*
|
||||
* Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -224,12 +224,16 @@ class PCallTask : public Statement {
|
|||
NetProc* elaborate_sys(Design*des, NetScope*scope) const;
|
||||
NetProc* elaborate_usr(Design*des, NetScope*scope) const;
|
||||
|
||||
NetProc*elaborate_method_(Design*des, NetScope*scope) const;
|
||||
NetProc*elaborate_method_(Design*des, NetScope*scope,
|
||||
bool add_this_flag = false) const;
|
||||
NetProc*elaborate_function_(Design*des, NetScope*scope) const;
|
||||
|
||||
NetProc*elaborate_build_call_(Design*des, NetScope*scope,
|
||||
NetScope*task, NetExpr*use_this) const;
|
||||
|
||||
NetProc*elaborate_sys_task_method_(Design*des, NetScope*scope,
|
||||
NetNet*net,
|
||||
perm_string method_name,
|
||||
const char*sys_task_name) const;
|
||||
bool test_task_calls_ok_(Design*des, NetScope*scope) const;
|
||||
|
||||
PPackage*package_;
|
||||
|
|
@ -440,6 +444,26 @@ class PForce : public Statement {
|
|||
PExpr*expr_;
|
||||
};
|
||||
|
||||
class PForeach : public Statement {
|
||||
public:
|
||||
explicit PForeach(perm_string var, const std::list<perm_string>&ix, Statement*stmt);
|
||||
~PForeach();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
NetProc* elaborate_static_array_(Design*des, NetScope*scope,
|
||||
const std::vector<netrange_t>&dims) const;
|
||||
|
||||
private:
|
||||
perm_string array_var_;
|
||||
std::vector<perm_string> index_vars_;
|
||||
Statement*statement_;
|
||||
};
|
||||
|
||||
class PForever : public Statement {
|
||||
public:
|
||||
explicit PForever(Statement*s);
|
||||
|
|
@ -558,4 +582,4 @@ class PWhile : public Statement {
|
|||
Statement*statement_;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_Statement_H */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef PLI_TYPES
|
||||
#define PLI_TYPES
|
||||
#ifndef PLI_TYPES_H
|
||||
#define PLI_TYPES_H
|
||||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -85,4 +85,4 @@ typedef char PLI_BYTE8;
|
|||
typedef unsigned char PLI_UBYTE8;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif /* PLI_TYPES_H */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __acc_user_H
|
||||
#define __acc_user_H
|
||||
#ifndef ACC_USER_H
|
||||
#define ACC_USER_H
|
||||
/*
|
||||
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -228,6 +228,7 @@ extern PLI_INT32 acc_fetch_size(handle obj);
|
|||
|
||||
extern PLI_INT32 acc_fetch_type(handle obj);
|
||||
extern PLI_INT32 acc_fetch_fulltype(handle obj);
|
||||
extern PLI_INT32 acc_fetch_paramtype(handle obj);
|
||||
extern PLI_INT32 acc_fetch_range(handle object, int *msb, int *lsb);
|
||||
extern const char* acc_fetch_type_str(PLI_INT32 type);
|
||||
|
||||
|
|
@ -270,4 +271,4 @@ extern char* acc_version(void);
|
|||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
#endif /* ACC_USER_H */
|
||||
|
|
|
|||
|
|
@ -218,17 +218,6 @@ AC_SUBST(strip_dynamic)
|
|||
# AC_MSG_RESULT($strip_dynamic)
|
||||
])# AX_LD_RDYNAMIC
|
||||
|
||||
# AX_CPP_PRECOMP
|
||||
# --------------
|
||||
AC_DEFUN([AX_CPP_PRECOMP],
|
||||
[# Darwin requires -no-cpp-precomp
|
||||
case "${host}" in
|
||||
*-*-darwin*)
|
||||
CPPFLAGS="-no-cpp-precomp $CPPFLAGS"
|
||||
CFLAGS="-no-cpp-precomp $CFLAGS"
|
||||
;;
|
||||
esac
|
||||
])# AX_CPP_PRECOMP
|
||||
|
||||
# AX_C99_STRTOD
|
||||
# -------------
|
||||
|
|
|
|||
4
async.cc
4
async.cc
|
|
@ -50,8 +50,8 @@ bool NetEvWait::is_asynchronous()
|
|||
level sensitive, but the nex_async_ method takes care of
|
||||
that test. */
|
||||
NexusSet*sense = new NexusSet;
|
||||
for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) {
|
||||
NexusSet*tmp = event(idx)->nex_async_();
|
||||
for (unsigned idx = 0 ; idx < events_.size() ; idx += 1) {
|
||||
NexusSet*tmp = events_[idx]->nex_async_();
|
||||
if (tmp == 0) {
|
||||
delete sense;
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
|
|||
endif
|
||||
|
||||
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@
|
||||
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
|
||||
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
O = cadpli.o
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ static void thunker_register(void)
|
|||
}
|
||||
}
|
||||
|
||||
void (*vlog_startup_routines[])() = {
|
||||
void (*vlog_startup_routines[])(void) = {
|
||||
thunker_register,
|
||||
0
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __ivl_dlfcn_H
|
||||
#define __ivl_dlfcn_H
|
||||
#ifndef IVL_ivl_dlfcn_H
|
||||
#define IVL_ivl_dlfcn_H
|
||||
/*
|
||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -91,4 +91,4 @@ static __inline__ const char*dlerror(void)
|
|||
{ return strerror( errno ); }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif /* IVL_ivl_dlfcn_H */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef __compiler_H
|
||||
#define __compiler_H
|
||||
#ifndef IVL_compiler_H
|
||||
#define IVL_compiler_H
|
||||
/*
|
||||
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
|
|
@ -283,4 +283,4 @@ extern void cleanup_sys_func_table();
|
|||
*/
|
||||
extern ivl_sfunc_as_task_t def_sfunc_as_task;
|
||||
|
||||
#endif
|
||||
#endif /* IVL_compiler_H */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __config_H /* -*- c++ -*- */
|
||||
#define __config_H
|
||||
#ifndef IVL_config_H /* -*- c++ -*- */
|
||||
#define IVL_config_H
|
||||
/*
|
||||
* Copyright (c) 2001-2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -62,4 +62,4 @@
|
|||
*/
|
||||
# undef CHECK_WITH_VALGRIND
|
||||
|
||||
#endif /* __config_H */
|
||||
#endif /* IVL_config_H */
|
||||
|
|
|
|||
12
configure.in
12
configure.in
|
|
@ -14,10 +14,6 @@ AC_CANONICAL_HOST
|
|||
dnl Checks for programs.
|
||||
AC_PROG_CC
|
||||
# AC_PROG_CC_C99 is only available in autoconf version 2.60 and later.
|
||||
# If you must use an older version then comment out the following two
|
||||
# lines, but be warned that there could be issues with finding the
|
||||
# nan(), etc. functions. It is really best to upgrade to a supported
|
||||
# version of autoconf.
|
||||
AC_PREREQ([2.60])
|
||||
AC_PROG_CC_C99
|
||||
AC_PROG_CXX
|
||||
|
|
@ -85,8 +81,9 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
|
|||
CFLAGS="$iverilog_temp_cflags"
|
||||
|
||||
AC_SUBST(DEPENDENCY_FLAG, [-MD])
|
||||
AC_SUBST(WARNING_FLAGS, ["-Wall -Wshadow"])
|
||||
AC_SUBST(WARNING_FLAGS_CXX, ["$iverilog_wextra_flag"])
|
||||
AC_SUBST(WARNING_FLAGS, ["-Wall $iverilog_wextra_flag -Wshadow"])
|
||||
AC_SUBST(WARNING_FLAGS_CC, [""])
|
||||
AC_SUBST(WARNING_FLAGS_CXX, [""])
|
||||
fi
|
||||
|
||||
AC_LANG(C++)
|
||||
|
|
@ -217,9 +214,6 @@ AX_LD_EXTRALIBS
|
|||
# CFLAGS inherited by cadpli/Makefile?
|
||||
AX_C_PICFLAG
|
||||
|
||||
# may modify CPPFLAGS and CFLAGS
|
||||
AX_CPP_PRECOMP
|
||||
|
||||
# may modify LDFLAGS
|
||||
AX_C99_STRTOD
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
// These are correct and are used to find the base (zero) pin.
|
||||
thisSubtraction:netlist.h:4589
|
||||
thisSubtraction:netlist.h:4598
|
||||
thisSubtraction:netlist.h:4938
|
||||
thisSubtraction:netlist.h:4947
|
||||
|
|
|
|||
190
design_dump.cc
190
design_dump.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -30,6 +30,7 @@
|
|||
# include "discipline.h"
|
||||
# include "netclass.h"
|
||||
# include "netdarray.h"
|
||||
# include "netqueue.h"
|
||||
# include "netvector.h"
|
||||
# include "ivl_assert.h"
|
||||
# include "PExpr.h"
|
||||
|
|
@ -113,6 +114,9 @@ ostream& operator << (ostream&o, ivl_variable_type_t val)
|
|||
case IVL_VT_CLASS:
|
||||
o << "class";
|
||||
break;
|
||||
case IVL_VT_QUEUE:
|
||||
o << "queue";
|
||||
break;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
|
@ -145,18 +149,87 @@ ostream& operator << (ostream&o, ivl_switch_type_t val)
|
|||
return o;
|
||||
}
|
||||
|
||||
ostream& operator << (ostream&fd, PortType::Enum val)
|
||||
{
|
||||
switch (val) {
|
||||
case PortType::NOT_A_PORT:
|
||||
fd << "NOT_A_PORT";
|
||||
break;
|
||||
case PortType::PIMPLICIT:
|
||||
fd << "PIMPLICIT";
|
||||
break;
|
||||
case PortType::PINPUT:
|
||||
fd << "PINPUT";
|
||||
break;
|
||||
case PortType::POUTPUT:
|
||||
fd << "POUTPUT";
|
||||
break;
|
||||
case PortType::PINOUT:
|
||||
fd << "PINOUT";
|
||||
break;
|
||||
case PortType::PREF:
|
||||
fd << "PREF";
|
||||
break;
|
||||
default:
|
||||
fd << "PortType::Enum::?";
|
||||
break;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
ostream& operator << (ostream&fd, NetCaseCmp::kind_t that)
|
||||
{
|
||||
switch (that) {
|
||||
case NetCaseCmp::EEQ:
|
||||
fd << "===";
|
||||
break;
|
||||
case NetCaseCmp::NEQ:
|
||||
fd << "!==";
|
||||
break;
|
||||
case NetCaseCmp::XEQ:
|
||||
fd << "==?";
|
||||
break;
|
||||
case NetCaseCmp::ZEQ:
|
||||
fd << "==z?";
|
||||
break;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
ostream& ivl_type_s::debug_dump(ostream&o) const
|
||||
{
|
||||
o << typeid(*this).name();
|
||||
return o;
|
||||
}
|
||||
|
||||
ostream& netclass_t::debug_dump(ostream&fd) const
|
||||
{
|
||||
fd << "class " << name_ << "{";
|
||||
for (size_t idx = 0 ; idx < property_table_.size() ; idx += 1) {
|
||||
if (idx != 0) fd << "; ";
|
||||
if (property_table_[idx].type)
|
||||
property_table_[idx].type->debug_dump(fd);
|
||||
else
|
||||
fd << "NO_TYPE";
|
||||
fd << " " << property_table_[idx].name;
|
||||
}
|
||||
fd << "}";
|
||||
return fd;
|
||||
}
|
||||
|
||||
ostream& netdarray_t::debug_dump(ostream&o) const
|
||||
{
|
||||
o << "dynamic array of " << *element_type();
|
||||
return o;
|
||||
}
|
||||
|
||||
ostream& netqueue_t::debug_dump(ostream&fd) const
|
||||
{
|
||||
fd << "queue of " << *element_type();
|
||||
return fd;
|
||||
}
|
||||
|
||||
ostream& netvector_t::debug_dump(ostream&o) const
|
||||
{
|
||||
o << type_ << (signed_? " signed" : " unsigned") << packed_dims_;
|
||||
|
|
@ -170,10 +243,7 @@ static inline void dump_scope_path(ostream&o, const NetScope*scope)
|
|||
dump_scope_path(o, parent);
|
||||
o << ".";
|
||||
}
|
||||
const hname_t name = scope->fullname();
|
||||
o << name.peek_name();
|
||||
if (name.has_number())
|
||||
o << "[" << name.peek_number() << "]";
|
||||
o << scope->fullname();
|
||||
}
|
||||
|
||||
ostream& operator <<(ostream&o, struct __ScopePathManip marg)
|
||||
|
|
@ -192,6 +262,68 @@ ostream& operator <<(ostream&o, struct __ObjectPathManip marg)
|
|||
return o;
|
||||
}
|
||||
|
||||
ostream& operator <<(ostream&fd, Link::DIR dir)
|
||||
{
|
||||
switch (dir) {
|
||||
case Link::PASSIVE:
|
||||
fd << "PASSIVE";
|
||||
break;
|
||||
case Link::INPUT:
|
||||
fd << "INPUT";
|
||||
break;
|
||||
case Link::OUTPUT:
|
||||
fd << "OUTPUT";
|
||||
break;
|
||||
default:
|
||||
fd << "<" << (int)dir << ">";
|
||||
break;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
void NetPins::show_type(ostream&fd) const
|
||||
{
|
||||
fd << typeid(*this).name();
|
||||
}
|
||||
|
||||
void NetObj::show_type(ostream&fd) const
|
||||
{
|
||||
fd << typeid(*this).name() << "[" << scope_path(scope_) << "." << name_ << "]";
|
||||
}
|
||||
|
||||
struct __ShowTypeManip { const NetPins*pins; };
|
||||
inline __ShowTypeManip show_type(const NetPins*pins)
|
||||
{ __ShowTypeManip tmp; tmp.pins = pins; return tmp; }
|
||||
|
||||
inline ostream& operator << (ostream&fd, __ShowTypeManip man)
|
||||
{
|
||||
if (man.pins == 0)
|
||||
fd << "NexusSet";
|
||||
else
|
||||
man.pins->show_type(fd);
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
void Link::dump_link(ostream&fd, unsigned ind) const
|
||||
{
|
||||
const Link*cur;
|
||||
const Nexus*nex = nexus();
|
||||
|
||||
if (nex == 0) {
|
||||
fd << setw(ind) << "" << "<unlinked>" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
for (cur = nex->first_nlink() ; cur; cur = cur->next_nlink()) {
|
||||
const NetPins*obj = cur->get_obj();
|
||||
unsigned pin = cur->get_pin();
|
||||
fd << setw(ind) << "" << "Pin " << pin
|
||||
<< " of " << show_type(obj)
|
||||
<< ", dir=" << cur->dir_ << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void NetBranch::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
static const char*pin_names[2] = {
|
||||
|
|
@ -523,10 +655,7 @@ void NetBUFZ::dump_node(ostream&o, unsigned ind) const
|
|||
|
||||
void NetCaseCmp::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
if (eeq_)
|
||||
o << setw(ind) << "" << "case compare === : " << name() << endl;
|
||||
else
|
||||
o << setw(ind) << "" << "case compare !== : " << name() << endl;
|
||||
o << setw(ind) << "" << "case compare " << kind_ << ": " << name() << endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
|
@ -674,6 +803,21 @@ void NetPartSelect::dump_node(ostream&o, unsigned ind) const
|
|||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetSubstitute::dump_node(ostream&fd, unsigned ind) const
|
||||
{
|
||||
fd << setw(ind) << "" << "NetSubstitute: "
|
||||
<< name();
|
||||
if (rise_time())
|
||||
fd << " #(" << *rise_time()
|
||||
<< "," << *fall_time()
|
||||
<< "," << *decay_time() << ")";
|
||||
else
|
||||
fd << " #(.,.,.)";
|
||||
fd << " width=" << wid_ << " base=" << off_ <<endl;
|
||||
dump_node_pins(fd, ind+4);
|
||||
dump_obj_attr(fd, ind+4);
|
||||
}
|
||||
|
||||
void NetReplicate::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NetReplicate: "
|
||||
|
|
@ -977,7 +1121,7 @@ void NetCase::dump(ostream&o, unsigned ind) const
|
|||
break;
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
|
||||
for (unsigned idx = 0 ; idx < items_.size() ; idx += 1) {
|
||||
o << setw(ind+2) << "";
|
||||
if (items_[idx].guard)
|
||||
o << *items_[idx].guard << ":";
|
||||
|
|
@ -1138,6 +1282,13 @@ void NetForever::dump(ostream&o, unsigned ind) const
|
|||
statement_->dump(o, ind+2);
|
||||
}
|
||||
|
||||
void NetForLoop::dump(ostream&fd, unsigned ind) const
|
||||
{
|
||||
fd << setw(ind) << "" << "FOR LOOP index=" << index_->name() << endl;
|
||||
statement_->dump(fd, ind+4);
|
||||
step_statement_->dump(fd, ind+4);
|
||||
}
|
||||
|
||||
void NetFree::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "// free storage : " << scope_path(scope_) << endl;
|
||||
|
|
@ -1568,6 +1719,11 @@ void NetEEvent::dump(ostream&o) const
|
|||
o << "<event=" << event_->name() << ">";
|
||||
}
|
||||
|
||||
void NetELast::dump(ostream&fd) const
|
||||
{
|
||||
fd << "<last of " << sig_->name() << ">";
|
||||
}
|
||||
|
||||
void NetENetenum::dump(ostream&o) const
|
||||
{
|
||||
o << "<netenum=" << netenum_ << ">";
|
||||
|
|
@ -1593,6 +1749,8 @@ void NetENull::dump(ostream&o) const
|
|||
void NetEProperty::dump(ostream&o) const
|
||||
{
|
||||
o << net_->name() << ".<" << pidx_ << ">";
|
||||
if (index_)
|
||||
o << "[" << *index_ << "]";
|
||||
}
|
||||
|
||||
void NetEScope::dump(ostream&o) const
|
||||
|
|
@ -1721,6 +1879,18 @@ void Design::dump(ostream&o) const
|
|||
cur->second->dump(o);
|
||||
}
|
||||
|
||||
o << "$ROOT CLASSESS:" << endl;
|
||||
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
|
||||
; cur != classes_.end() ; ++cur) {
|
||||
cur->second->dump_scope(o);
|
||||
}
|
||||
|
||||
o << "$ROOT TASKS/FUNCTIONS:" << endl;
|
||||
for (map<NetScope*,PTaskFunc*>::const_iterator cur = root_tasks_.begin()
|
||||
; cur != root_tasks_.end() ; ++ cur) {
|
||||
cur->first->dump(o);
|
||||
}
|
||||
|
||||
o << "SCOPES:" << endl;
|
||||
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
|
||||
scope != root_scopes_.end(); ++ scope ) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __discipline_H
|
||||
#define __discipline_H
|
||||
#ifndef IVL_discipline_H
|
||||
#define IVL_discipline_H
|
||||
/*
|
||||
* Copyright (c) 2008-2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2008-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -74,4 +74,4 @@ extern map<perm_string,ivl_discipline_t> disciplines;
|
|||
// Map access function name to the nature that it accesses.
|
||||
extern map<perm_string,ivl_nature_t> access_function_nature;
|
||||
|
||||
#endif
|
||||
#endif /* IVL_discipline_H */
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
|
|||
endif
|
||||
|
||||
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
|
||||
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
O = main.o res.o
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
|
|||
endif
|
||||
|
||||
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
|
||||
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
O = main.o substit.o cflexor.o cfparse.o
|
||||
|
|
@ -67,7 +67,11 @@ distclean: clean
|
|||
rm -f Makefile config.log
|
||||
|
||||
cppcheck: $(O:.o=.c)
|
||||
cppcheck --enable=all -f $(INCLUDE_PATH) $^
|
||||
cppcheck --enable=all -f \
|
||||
-UYY_USER_INIT \
|
||||
-UYYPARSE_PARAM -UYYPRINT -Ushort -Uyyoverflow \
|
||||
-UYYTYPE_INT8 -UYYTYPE_INT16 -UYYTYPE_UINT8 -UYYTYPE_UINT16 \
|
||||
$(INCLUDE_PATH) $^
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in ../config.status
|
||||
cd ..; ./config.status --file=driver/$@
|
||||
|
|
|
|||
|
|
@ -247,7 +247,7 @@ void cfreset(FILE*fd, const char*path)
|
|||
/*
|
||||
* Modern version of flex (>=2.5.9) can clean up the scanner data.
|
||||
*/
|
||||
void destroy_lexor()
|
||||
void destroy_lexor(void)
|
||||
{
|
||||
# ifdef FLEX_SCANNER
|
||||
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ item
|
|||
}
|
||||
|
||||
| error
|
||||
{ fprintf(stderr, "Error: unable to parse line %d in "
|
||||
{ fprintf(stderr, "Error: unable to parse line %u in "
|
||||
"%s.\n", cflloc.first_line, current_file);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -270,5 +270,6 @@ skip_arg : TOK_PLUSARG
|
|||
|
||||
int yyerror(const char*msg)
|
||||
{
|
||||
(void)msg; /* Parameter is not used. */
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __cfparse_misc_H
|
||||
#define __cfparse_misc_H
|
||||
#ifndef IVL_cfparse_misc_H
|
||||
#define IVL_cfparse_misc_H
|
||||
/*
|
||||
* Copyright (c) 2001-2009 Picture Elements, Inc.
|
||||
* Copyright (c) 2001-2014 Picture Elements, Inc.
|
||||
* Stephen Williams (steve@picturel.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
|
|
@ -38,7 +38,7 @@ int cflex(void);
|
|||
int cferror(const char *);
|
||||
int cfparse(void);
|
||||
void switch_to_command_file(const char *);
|
||||
void destroy_lexor();
|
||||
void destroy_lexor(void);
|
||||
char *current_file;
|
||||
|
||||
#endif
|
||||
#endif /* IVL_cfparse_misc_H */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef __globals_H
|
||||
#define __globals_H
|
||||
#ifndef IVL_globals_H
|
||||
#define IVL_globals_H
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
|
|
@ -54,4 +54,4 @@ extern void process_parameter(const char*name);
|
|||
/* Set the default timescale for the simulator. */
|
||||
extern void process_timescale(const char*ts_string);
|
||||
|
||||
#endif
|
||||
#endif /* IVL_globals_H */
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ const char HELP[] =
|
|||
#endif
|
||||
#include <fcntl.h>
|
||||
|
||||
#if HAVE_GETOPT_H
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
|
||||
|
|
@ -188,7 +188,7 @@ static const char** defparm_base = 0;
|
|||
static int defparm_size = 0;
|
||||
|
||||
/* Function to add a command file name to the FIFO. */
|
||||
void add_cmd_file(const char* filename)
|
||||
static void add_cmd_file(const char* filename)
|
||||
{
|
||||
p_command_file new;
|
||||
|
||||
|
|
@ -205,7 +205,7 @@ void add_cmd_file(const char* filename)
|
|||
}
|
||||
|
||||
/* Function to return the top command file name from the FIFO. */
|
||||
char *get_cmd_file()
|
||||
static char *get_cmd_file(void)
|
||||
{
|
||||
char *filename;
|
||||
|
||||
|
|
@ -402,7 +402,7 @@ static int t_preprocess_only(void)
|
|||
* needed to run the command from the configuration file (which is
|
||||
* already parsed for us) so we can handle must of the generic cases.
|
||||
*/
|
||||
static int t_compile()
|
||||
static int t_compile(void)
|
||||
{
|
||||
unsigned rc;
|
||||
|
||||
|
|
@ -625,7 +625,7 @@ void process_file_name(const char*name, int lib_flag)
|
|||
}
|
||||
}
|
||||
|
||||
int process_generation(const char*name)
|
||||
static int process_generation(const char*name)
|
||||
{
|
||||
if (strcmp(name,"1995") == 0)
|
||||
generation = "1995";
|
||||
|
|
@ -750,7 +750,7 @@ int process_generation(const char*name)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int process_depfile(const char*name)
|
||||
static int process_depfile(const char*name)
|
||||
{
|
||||
const char*cp = strchr(name, '=');
|
||||
if (cp) {
|
||||
|
|
@ -784,7 +784,7 @@ int process_depfile(const char*name)
|
|||
/*
|
||||
* If it exists add the SFT file for the given module.
|
||||
*/
|
||||
void add_sft_file(const char *module)
|
||||
static void add_sft_file(const char *module)
|
||||
{
|
||||
char *file;
|
||||
|
||||
|
|
@ -799,7 +799,7 @@ int main(int argc, char **argv)
|
|||
{
|
||||
int e_flag = 0;
|
||||
int version_flag = 0;
|
||||
int opt, idx;
|
||||
int opt;
|
||||
|
||||
#ifdef __MINGW32__
|
||||
/* Calculate the ivl_root from the path to the command. This
|
||||
|
|
@ -907,7 +907,7 @@ int main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hI:M:m:N::o:P:p:Ss:T:t:vVW:y:Y:")) != EOF) {
|
||||
while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hI:M:m:N:o:P:p:Ss:T:t:vVW:y:Y:")) != EOF) {
|
||||
|
||||
switch (opt) {
|
||||
case 'B':
|
||||
|
|
@ -1142,7 +1142,7 @@ int main(int argc, char **argv)
|
|||
vhdlpp_work = "ivl_vhdl_work";
|
||||
fprintf(defines_file, "vhdlpp:%s%cvhdlpp\n", vhdlpp_dir, sep);
|
||||
fprintf(defines_file, "vhdlpp-work:%s\n", vhdlpp_work);
|
||||
for (idx = 0 ; idx < vhdlpp_libdir_cnt ; idx += 1)
|
||||
for (unsigned idx = 0 ; idx < vhdlpp_libdir_cnt ; idx += 1)
|
||||
fprintf(defines_file, "vhdlpp-libdir:%s\n", vhdlpp_libdir[idx]);
|
||||
|
||||
/* Process parameter definition from command line. The last
|
||||
|
|
@ -1156,7 +1156,7 @@ int main(int argc, char **argv)
|
|||
|
||||
/* Finally, process all the remaining words on the command
|
||||
line as file names. */
|
||||
for (idx = optind ; idx < argc ; idx += 1)
|
||||
for (int idx = optind ; idx < argc ; idx += 1)
|
||||
process_file_name(argv[idx], 0);
|
||||
|
||||
/* If the use of a default include directory is not
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
# include <stdlib.h>
|
||||
# include <stdio.h>
|
||||
# include "ivl_alloc.h"
|
||||
# include "globals.h"
|
||||
|
||||
|
||||
char* substitutions(const char*str)
|
||||
|
|
|
|||
|
|
@ -182,6 +182,14 @@ NetEEvent* NetEEvent::dup_expr() const
|
|||
return 0;
|
||||
}
|
||||
|
||||
NetELast* NetELast::dup_expr() const
|
||||
{
|
||||
NetELast*tmp = new NetELast(sig_);
|
||||
ivl_assert(*this, tmp);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetENetenum* NetENetenum::dup_expr() const
|
||||
{
|
||||
ivl_assert(*this, 0);
|
||||
|
|
@ -249,6 +257,7 @@ NetESignal* NetESignal::dup_expr() const
|
|||
NetESignal*tmp = new NetESignal(net_, word_);
|
||||
ivl_assert(*this, tmp);
|
||||
tmp->expr_width(expr_width());
|
||||
tmp->cast_signed(has_sign());
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
|
|
|||
452
elab_expr.cc
452
elab_expr.cc
|
|
@ -30,6 +30,7 @@
|
|||
# include "netlist.h"
|
||||
# include "netclass.h"
|
||||
# include "netenum.h"
|
||||
# include "netparray.h"
|
||||
# include "netvector.h"
|
||||
# include "discipline.h"
|
||||
# include "netmisc.h"
|
||||
|
|
@ -106,6 +107,7 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type,
|
|||
int context_wid = -1;
|
||||
switch (lv_type) {
|
||||
case IVL_VT_DARRAY:
|
||||
case IVL_VT_QUEUE:
|
||||
// For these types, use a different elab_and_eval that
|
||||
// uses the lv_net_type. We should eventually transition
|
||||
// all the types to this new form.
|
||||
|
|
@ -309,7 +311,7 @@ unsigned PEBinary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
|||
|
||||
case '%':
|
||||
case '/':
|
||||
min_width_ = max(min_width_, expr_width_);
|
||||
min_width_ = UINT_MAX; // disable width pruning
|
||||
break;
|
||||
|
||||
case 'l': // << Should be handled by PEBShift
|
||||
|
|
@ -530,7 +532,7 @@ NetExpr* PEBinary::elaborate_expr_base_mult_(Design*,
|
|||
if (NetEConst*rp_const = dynamic_cast<NetEConst*> (rp)) {
|
||||
verinum rp_val = rp_const->value();
|
||||
|
||||
if (! rp_val.is_defined()) {
|
||||
if (!rp_val.is_defined() && (lp->expr_type() == IVL_VT_LOGIC)) {
|
||||
NetEConst*tmp = make_const_x(expr_wid);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
tmp->set_line(*this);
|
||||
|
|
@ -538,7 +540,7 @@ NetExpr* PEBinary::elaborate_expr_base_mult_(Design*,
|
|||
return tmp;
|
||||
}
|
||||
|
||||
if (rp_val.is_zero() && (lp->expr_type() != IVL_VT_LOGIC)) {
|
||||
if (rp_val.is_zero() && (lp->expr_type() == IVL_VT_BOOL)) {
|
||||
NetEConst*tmp = make_const_0(expr_wid);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
tmp->set_line(*this);
|
||||
|
|
@ -815,7 +817,7 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
|||
if (op_ == 'l')
|
||||
min_width_ = left_->min_width();
|
||||
else
|
||||
min_width_ = expr_width_;
|
||||
min_width_ = UINT_MAX; // disable width pruning
|
||||
|
||||
return fix_width_(mode);
|
||||
}
|
||||
|
|
@ -1296,10 +1298,27 @@ unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope,
|
|||
return expr_width_;
|
||||
}
|
||||
|
||||
if (use_darray && (method_name == "pop_back" || method_name=="pop_front")) {
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PECallFunction::test_width_method_: "
|
||||
<< "Detected " << method_name << " method"
|
||||
<< " of dynamic arrays." << endl;
|
||||
}
|
||||
|
||||
expr_type_ = use_darray->element_base_type();
|
||||
expr_width_ = use_darray->element_width();
|
||||
min_width_ = expr_width_;
|
||||
signed_flag_= false;
|
||||
|
||||
return expr_width_;
|
||||
}
|
||||
|
||||
if (const netclass_t*class_type = net->class_type()) {
|
||||
cerr << get_fileline() << ": PECallFunction::test_width_method_: "
|
||||
<< "Try to find method " << method_name
|
||||
<< " of class " << class_type->get_name() << endl;
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PECallFunction::test_width_method_: "
|
||||
<< "Try to find method " << method_name
|
||||
<< " of class " << class_type->get_name() << endl;
|
||||
}
|
||||
|
||||
NetScope*func = class_type->method_from_name(method_name);
|
||||
if (func == 0) {
|
||||
|
|
@ -1768,6 +1787,14 @@ static const netstruct_t::member_t*get_struct_member(const LineInfo*li,
|
|||
bool calculate_part(const LineInfo*li, Design*des, NetScope*scope,
|
||||
const index_component_t&index, long&off, unsigned long&wid)
|
||||
{
|
||||
if (index.sel == index_component_t::SEL_BIT_LAST) {
|
||||
cerr << li->get_fileline() << ": sorry: "
|
||||
<< "Last element select expression "
|
||||
<< "not supported." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Evaluate the last index expression into a constant long.
|
||||
NetExpr*texpr = elab_and_eval(des, scope, index.msb, -1, true);
|
||||
long msb;
|
||||
|
|
@ -1809,6 +1836,11 @@ bool calculate_part(const LineInfo*li, Design*des, NetScope*scope,
|
|||
}
|
||||
return true;
|
||||
|
||||
case index_component_t::SEL_IDX_UP:
|
||||
wid = lsb;
|
||||
off = msb;
|
||||
break;
|
||||
|
||||
default:
|
||||
ivl_assert(*li, 0);
|
||||
break;
|
||||
|
|
@ -2051,11 +2083,24 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
|||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
ivl_assert(*this, def);
|
||||
|
||||
ivl_assert(*this, def);
|
||||
NetScope*dscope = def->scope();
|
||||
ivl_assert(*this, dscope);
|
||||
|
||||
/* In SystemVerilog a method calling another method in the
|
||||
* current class needs to be elaborated as a method with an
|
||||
* implicit this added. */
|
||||
if (gn_system_verilog() && (path_.size() == 1)) {
|
||||
const NetScope *c_scope = scope->get_class_scope();
|
||||
if (c_scope && (c_scope == dscope->get_class_scope())) {
|
||||
NetExpr*tmp = elaborate_expr_method_(des, scope, expr_wid,
|
||||
true);
|
||||
assert(tmp);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
bool need_const = NEED_CONST & flags;
|
||||
|
||||
// It is possible to get here before the called function has been
|
||||
|
|
@ -2249,17 +2294,22 @@ unsigned PECallFunction::elaborate_arguments_(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
||||
unsigned expr_wid) const
|
||||
unsigned expr_wid,
|
||||
bool add_this_flag) const
|
||||
{
|
||||
pform_name_t use_path = path_;
|
||||
perm_string method_name = peek_tail_name(use_path);
|
||||
use_path.pop_back();
|
||||
|
||||
/* Add the implicit this reference when requested. */
|
||||
if (add_this_flag) {
|
||||
assert(use_path.empty());
|
||||
use_path.push_front(name_component_t(perm_string::literal("@")));
|
||||
}
|
||||
|
||||
// If there is no object to the left of the method name, then
|
||||
// give up on the idea of looking for an object method.
|
||||
if (use_path.empty()) {
|
||||
return 0;
|
||||
}
|
||||
if (use_path.empty()) return 0;
|
||||
|
||||
NetNet *net = 0;
|
||||
const NetExpr *par;
|
||||
|
|
@ -2323,12 +2373,31 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
|||
if (net->darray_type()) {
|
||||
|
||||
if (method_name == "size") {
|
||||
NetESFunc*sys_expr = new NetESFunc("$ivl_darray_method$size",
|
||||
NetESFunc*sys_expr = new NetESFunc("$size",
|
||||
IVL_VT_BOOL, 32, 1);
|
||||
sys_expr->parm(0, new NetESignal(net));
|
||||
sys_expr->set_line(*this);
|
||||
return sys_expr;
|
||||
}
|
||||
|
||||
if (method_name == "pop_back") {
|
||||
NetESFunc*sys_expr = new NetESFunc("$ivl_darray_method$pop_back",
|
||||
expr_type_,
|
||||
expr_width_, 1);
|
||||
sys_expr->parm(0, new NetESignal(net));
|
||||
sys_expr->set_line(*this);
|
||||
return sys_expr;
|
||||
}
|
||||
|
||||
if (method_name == "pop_front") {
|
||||
NetESFunc*sys_expr = new NetESFunc("$ivl_darray_method$pop_front",
|
||||
expr_type_,
|
||||
expr_width_, 1);
|
||||
sys_expr->parm(0, new NetESignal(net));
|
||||
sys_expr->set_line(*this);
|
||||
return sys_expr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (const netclass_t*class_type = net->class_type()) {
|
||||
|
|
@ -2466,6 +2535,24 @@ unsigned PEConcat::test_width(Design*des, NetScope*scope, width_mode_t&)
|
|||
// Keep track of the concatenation/repeat depth.
|
||||
static int concat_depth = 0;
|
||||
|
||||
NetExpr* PEConcat::elaborate_expr(Design*, NetScope*,
|
||||
ivl_type_t type, unsigned /*flags*/) const
|
||||
{
|
||||
switch (type->base_type()) {
|
||||
case IVL_VT_QUEUE:
|
||||
if (parms_.size() == 0) {
|
||||
NetENull*tmp = new NetENull;
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
default:
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "I don't know how to elaborate(ivl_type_t)"
|
||||
<< " this expression: " << *this << endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
|
|
@ -2604,6 +2691,7 @@ bool PEIdent::calculate_packed_indices_(Design*des, NetScope*scope, NetNet*net,
|
|||
{
|
||||
list<index_component_t> index;
|
||||
index = path_.back().index;
|
||||
ivl_assert(*this, index.size() >= net->unpacked_dimensions());
|
||||
for (size_t idx = 0 ; idx < net->unpacked_dimensions() ; idx += 1)
|
||||
index.pop_front();
|
||||
|
||||
|
|
@ -2787,6 +2875,48 @@ bool PEIdent::calculate_param_range_(Design*, NetScope*,
|
|||
return true;
|
||||
}
|
||||
|
||||
unsigned PEIdent::test_width_method_(Design*des, NetScope*scope, width_mode_t&)
|
||||
{
|
||||
if (!gn_system_verilog())
|
||||
return 0;
|
||||
if (path_.size() < 2)
|
||||
return 0;
|
||||
|
||||
pform_name_t use_path = path_;
|
||||
perm_string member_name = peek_tail_name(path_);
|
||||
use_path.pop_back();
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::test_width_method_: "
|
||||
<< "Try to find method=" << member_name
|
||||
<< " of signal " << use_path << endl;
|
||||
}
|
||||
|
||||
NetNet*net = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent*eve = 0;
|
||||
const NetExpr*ex1 = 0, *ex2 = 0;
|
||||
symbol_search(this, des, scope, use_path, net, par, eve, ex1, ex2);
|
||||
if (net == 0) {
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": PEIdent::test_width_method_: "
|
||||
<< "Only nets can have methods, so give up here." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (/*const netdarray_t*dtype =*/ net->darray_type()) {
|
||||
if (member_name == "size") {
|
||||
expr_type_ = IVL_VT_BOOL;
|
||||
expr_width_ = 32;
|
||||
min_width_ = 32;
|
||||
signed_flag_= true;
|
||||
return 32;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
||||
{
|
||||
NetNet* net = 0;
|
||||
|
|
@ -2801,6 +2931,10 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
|||
ivl_assert(*this, use_scope);
|
||||
}
|
||||
|
||||
if (unsigned tmp = test_width_method_(des, scope, mode)) {
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetScope*found_in = symbol_search(this, des, use_scope, path_,
|
||||
net, par, eve,
|
||||
ex1, ex2);
|
||||
|
|
@ -2845,23 +2979,38 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
|||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.msb);
|
||||
}
|
||||
use_width = 1;
|
||||
// If we have a net in hand, then we can predict what the
|
||||
// slice width will be. If not, then assume it will be a
|
||||
// simple bit select. If the net only has a single dimension
|
||||
// then this is still a simple bit select.
|
||||
if ((net == 0) || (net->packed_dimensions() <= 1))
|
||||
use_width = 1;
|
||||
break;
|
||||
case index_component_t::SEL_BIT_LAST:
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::test_width: "
|
||||
<< "Queue/Darray last index ($)" << endl;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ivl_assert(*this, 0);
|
||||
}
|
||||
|
||||
if (const netdarray_t*darray = net? net->darray_type() : 0) {
|
||||
if (use_sel == index_component_t::SEL_BIT) {
|
||||
switch (use_sel) {
|
||||
case index_component_t::SEL_BIT:
|
||||
case index_component_t::SEL_BIT_LAST:
|
||||
expr_type_ = darray->element_base_type();
|
||||
expr_width_ = darray->element_width();
|
||||
min_width_ = expr_width_;
|
||||
signed_flag_ = net->get_signed();
|
||||
} else {
|
||||
break;
|
||||
default:
|
||||
expr_type_ = net->data_type();
|
||||
expr_width_ = net->vector_width();
|
||||
min_width_ = expr_width_;
|
||||
signed_flag_ = net->get_signed();
|
||||
break;
|
||||
}
|
||||
return expr_width_;
|
||||
}
|
||||
|
|
@ -2877,15 +3026,35 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
|||
|
||||
// The width of a signal expression is the width of the signal.
|
||||
if (net != 0) {
|
||||
size_t use_depth = name_tail.index.size();
|
||||
// Account for unpacked dimensions by assuming that the
|
||||
// unpacked dimensions are consumed first, so subtract
|
||||
// the unpacked dimensions from the dimension depth
|
||||
// useable for making the slice.
|
||||
if (use_depth >= net->unpacked_dimensions()) {
|
||||
use_depth -= net->unpacked_dimensions();
|
||||
|
||||
} else {
|
||||
// In this case, we have a slice of an unpacked
|
||||
// array. This likely handled as an array instead
|
||||
// of a slice. Hmm...
|
||||
use_depth = 0;
|
||||
}
|
||||
|
||||
expr_type_ = net->data_type();
|
||||
expr_width_ = net->vector_width();
|
||||
expr_width_ = net->slice_width(use_depth);
|
||||
min_width_ = expr_width_;
|
||||
signed_flag_ = net->get_signed();
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::test_width: "
|
||||
<< net->name() << " is a net, "
|
||||
<< "type=" << expr_type_
|
||||
<< ", width=" << expr_width_ << endl;
|
||||
<< ", width=" << expr_width_
|
||||
<< ", signed_=" << (signed_flag_?"true":"false")
|
||||
<< ", use_depth=" << use_depth
|
||||
<< ", packed_dimensions=" << net->packed_dimensions()
|
||||
<< ", unpacked_dimensions=" << net->unpacked_dimensions()
|
||||
<< endl;
|
||||
}
|
||||
return expr_width_;
|
||||
}
|
||||
|
|
@ -3000,8 +3169,10 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
|||
|
||||
|
||||
NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t ntype, unsigned) const
|
||||
ivl_type_t ntype, unsigned flags) const
|
||||
{
|
||||
bool need_const = NEED_CONST & flags;
|
||||
|
||||
NetNet* net = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
|
@ -3013,6 +3184,10 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
ivl_assert(*this, use_scope);
|
||||
}
|
||||
|
||||
if (NetExpr* tmp = elaborate_expr_class_member_(des, scope, 0, flags)) {
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* NetScope*found_in = */ symbol_search(this, des, use_scope, path_,
|
||||
net, par, eve,
|
||||
ex1, ex2);
|
||||
|
|
@ -3072,7 +3247,69 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
}
|
||||
ivl_assert(*this, ntype->type_compatible(net->net_type()));
|
||||
|
||||
NetESignal*tmp = new NetESignal(net);
|
||||
const name_component_t&use_comp = path_.back();
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
|
||||
<< "Typed ident " << net->name()
|
||||
<< " with " << use_comp.index.size() << " indices"
|
||||
<< " and " << net->unpacked_dimensions() << " expected."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
if (net->unpacked_dimensions() != use_comp.index.size()) {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "Net " << net->name()
|
||||
<< " expects " << net->unpacked_dimensions()
|
||||
<< ", but got " << use_comp.index.size() << "."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
|
||||
NetESignal*tmp = new NetESignal(net);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
if (net->unpacked_dimensions() == 0) {
|
||||
NetESignal*tmp = new NetESignal(net);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// Convert a set of index expressions to a single expression
|
||||
// that addresses the canonical element.
|
||||
list<NetExpr*>unpacked_indices;
|
||||
list<long> unpacked_indices_const;
|
||||
indices_flags idx_flags;
|
||||
indices_to_expressions(des, scope, this,
|
||||
use_comp.index, net->unpacked_dimensions(),
|
||||
need_const, net->unpacked_count(),
|
||||
idx_flags,
|
||||
unpacked_indices,
|
||||
unpacked_indices_const);
|
||||
|
||||
NetExpr*canon_index = 0;
|
||||
|
||||
if (idx_flags.invalid) {
|
||||
// Nothing to do
|
||||
|
||||
} else if (idx_flags.undefined) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
<< "returning 'bx for undefined array access "
|
||||
<< net->name() << as_indices(unpacked_indices)
|
||||
<< "." << endl;
|
||||
|
||||
} else if (idx_flags.variable) {
|
||||
ivl_assert(*this, unpacked_indices.size() == net->unpacked_dimensions());
|
||||
canon_index = normalize_variable_unpacked(net, unpacked_indices);
|
||||
|
||||
} else {
|
||||
ivl_assert(*this, unpacked_indices_const.size() == net->unpacked_dimensions());
|
||||
canon_index = normalize_variable_unpacked(net, unpacked_indices_const);
|
||||
}
|
||||
|
||||
ivl_assert(*this, canon_index);
|
||||
NetESignal*tmp = new NetESignal(net, canon_index);
|
||||
tmp->set_line(*this);
|
||||
|
||||
return tmp;
|
||||
|
|
@ -3094,19 +3331,24 @@ NetExpr* PEIdent::elaborate_expr_class_member_(Design*des, NetScope*scope,
|
|||
if (path_.size() != 1)
|
||||
return 0;
|
||||
|
||||
const netclass_t*class_type = scope->parent()->class_def();
|
||||
const netclass_t*class_type = find_class_containing_scope(*this, scope);
|
||||
if (class_type == 0)
|
||||
return 0;
|
||||
|
||||
perm_string member_name = peek_tail_name(path_);
|
||||
const name_component_t&name_comp = path_.back();
|
||||
|
||||
perm_string member_name = name_comp.name;
|
||||
int pidx = class_type->property_idx_from_name(member_name);
|
||||
if (pidx < 0)
|
||||
return 0;
|
||||
|
||||
NetNet*this_net = scope->find_signal(perm_string::literal("@"));
|
||||
NetScope*scope_method = find_method_containing_scope(*this, scope);
|
||||
ivl_assert(*this, scope_method);
|
||||
|
||||
NetNet*this_net = scope_method->find_signal(perm_string::literal("@"));
|
||||
if (this_net == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Unable to find 'this' port of " << scope_path(scope)
|
||||
<< "Unable to find 'this' port of " << scope_path(scope_method)
|
||||
<< "." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -3116,7 +3358,8 @@ NetExpr* PEIdent::elaborate_expr_class_member_(Design*des, NetScope*scope,
|
|||
<< "Found member " << member_name
|
||||
<< " is a member of class " << class_type->get_name()
|
||||
<< ", context scope=" << scope_path(scope)
|
||||
<< ", so synthesizing a NetEProperty." << endl;
|
||||
<< ", type=" << *class_type->get_prop_type(pidx)
|
||||
<< ", so making a NetEProperty." << endl;
|
||||
}
|
||||
|
||||
property_qualifier_t qual = class_type->get_prop_qual(pidx);
|
||||
|
|
@ -3132,11 +3375,98 @@ NetExpr* PEIdent::elaborate_expr_class_member_(Design*des, NetScope*scope,
|
|||
return class_static_property_expression(this, class_type, member_name);
|
||||
}
|
||||
|
||||
NetEProperty*tmp = new NetEProperty(this_net, member_name);
|
||||
NetExpr*canon_index = 0;
|
||||
ivl_type_t tmp_type = class_type->get_prop_type(pidx);
|
||||
if (const netuarray_t*tmp_ua = dynamic_cast<const netuarray_t*>(tmp_type)) {
|
||||
|
||||
const std::vector<netrange_t>&dims = tmp_ua->static_dimensions();
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_expr_class_member_: "
|
||||
<< "Property " << class_type->get_prop_name(pidx)
|
||||
<< " has " << dims.size() << " dimensions, "
|
||||
<< " got " << name_comp.index.size() << " indices." << endl;
|
||||
}
|
||||
|
||||
if (dims.size() != name_comp.index.size()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Got " << name_comp.index.size() << " indices, "
|
||||
<< "expecting " << dims.size()
|
||||
<< " to index the property " << class_type->get_prop_name(pidx) << "." << endl;
|
||||
des->errors += 1;
|
||||
|
||||
} else {
|
||||
|
||||
canon_index = make_canonical_index(des, scope, this,
|
||||
name_comp.index, tmp_ua, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (debug_elaborate && canon_index) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_expr_class_member_: "
|
||||
<< "Property " << class_type->get_prop_name(pidx)
|
||||
<< " canonical index: " << *canon_index << endl;
|
||||
}
|
||||
|
||||
NetEProperty*tmp = new NetEProperty(this_net, member_name, canon_index);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr* PEIdent::elaborate_expr_method_(Design*des, NetScope*scope,
|
||||
unsigned, unsigned) const
|
||||
{
|
||||
if (!gn_system_verilog())
|
||||
return 0;
|
||||
if (path_.size() < 2)
|
||||
return 0;
|
||||
|
||||
pform_name_t use_path = path_;
|
||||
perm_string member_name = peek_tail_name(path_);
|
||||
use_path.pop_back();
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_expr_method_: "
|
||||
<< "Try to find method=" << member_name
|
||||
<< " of signal " << use_path << endl;
|
||||
}
|
||||
|
||||
NetNet*net = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent*eve = 0;
|
||||
const NetExpr*ex1 = 0, *ex2 = 0;
|
||||
symbol_search(this, des, scope, use_path, net, par, eve, ex1, ex2);
|
||||
if (net == 0) {
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_expr_method_: "
|
||||
<< "Only nets can have methods, so give up here." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (net->darray_type()) {
|
||||
if (member_name == "size") {
|
||||
NetESFunc*fun = new NetESFunc("$size", IVL_VT_BOOL, 32, 1);
|
||||
fun->set_line(*this);
|
||||
|
||||
NetESignal*arg = new NetESignal(net);
|
||||
arg->set_line(*net);
|
||||
|
||||
fun->parm(0, arg);
|
||||
return fun;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_expr_method_: "
|
||||
<< "Give up trying to find method " << member_name
|
||||
<< " of " << path_ << "." << endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborate an identifier in an expression. The identifier can be a
|
||||
* parameter name, a signal name or a memory name. It can also be a
|
||||
|
|
@ -3197,6 +3527,14 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
ivl_assert(*this, use_scope);
|
||||
}
|
||||
|
||||
// Special case: Detect the special situation that the name is
|
||||
// a method of an object (including built-in methods) that has
|
||||
// no arguments. For example, "foo.size" is the call to the
|
||||
// size() method if foo is an array type.
|
||||
if (NetExpr*tmp = elaborate_expr_method_(des, scope, expr_wid, flags)) {
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetScope*found_in = symbol_search(this, des, use_scope, path_,
|
||||
net, par, eve,
|
||||
ex1, ex2);
|
||||
|
|
@ -3241,6 +3579,13 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
|
||||
if (!tmp) return 0;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
|
||||
<< "Expression as net. expr_wid=" << expr_wid
|
||||
<< ", tmp->expr_width()=" << tmp->expr_width()
|
||||
<< ", tmp=" << *tmp << endl;
|
||||
}
|
||||
|
||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
|
||||
|
|
@ -3898,6 +4243,8 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
|
|||
return 0;
|
||||
}
|
||||
|
||||
ivl_assert(*this, use_sel != index_component_t::SEL_BIT_LAST);
|
||||
|
||||
if (use_sel == index_component_t::SEL_BIT)
|
||||
return elaborate_expr_param_bit_(des, scope, par, found_in,
|
||||
par_msb, par_lsb, need_const);
|
||||
|
|
@ -3988,7 +4335,7 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
|
|||
|
||||
if (name_tail.index.empty()) {
|
||||
cerr << get_fileline() << ": error: Array " << path()
|
||||
<< " Needs an array index here." << endl;
|
||||
<< " needs an array index here." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -4458,6 +4805,15 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
|||
// making a mux part in the netlist.
|
||||
if (NetEConst*msc = dynamic_cast<NetEConst*> (mux)) {
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_expr_net_bit_: "
|
||||
<< "mux is constant=" << *msc
|
||||
<< ", packed_dims()=" << net->sig()->packed_dims()
|
||||
<< ", packed_dims().size()=" << net->sig()->packed_dims().size()
|
||||
<< ", prefix_indices.size()=" << prefix_indices.size()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// Special case: The bit select expression is constant
|
||||
// x/z. The result of the expression is 1'bx.
|
||||
if (! msc->value().is_defined()) {
|
||||
|
|
@ -4475,6 +4831,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
|||
<< endl;
|
||||
}
|
||||
|
||||
// FIXME: Should I be using slice_width() here?
|
||||
NetEConst*tmp = make_const_x(1);
|
||||
tmp->set_line(*this);
|
||||
delete mux;
|
||||
|
|
@ -4566,6 +4923,12 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
|||
if (net->vector_width() == 1)
|
||||
return net;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_expr_net_bit_: "
|
||||
<< "Make bit select idx=" << idx
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// Make an expression out of the index
|
||||
NetEConst*idx_c = new NetEConst(verinum(idx));
|
||||
idx_c->set_line(*net);
|
||||
|
|
@ -4610,6 +4973,29 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
|||
return ss;
|
||||
}
|
||||
|
||||
NetExpr* PEIdent::elaborate_expr_net_bit_last_(Design*, NetScope*,
|
||||
NetESignal*net,
|
||||
NetScope* /* found_in */,
|
||||
bool need_const) const
|
||||
{
|
||||
if (need_const) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Expression with \"[$]\" is not constant." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned use_width = 1;
|
||||
if (const netdarray_t*darray = net->sig()->darray_type()) {
|
||||
use_width = darray->element_width();
|
||||
}
|
||||
|
||||
NetELast*mux = new NetELast(net->sig());
|
||||
mux->set_line(*this);
|
||||
NetESelect*ss = new NetESelect(net, mux, use_width);
|
||||
ss->set_line(*this);
|
||||
return ss;
|
||||
}
|
||||
|
||||
NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
|
||||
NetNet*net, NetScope*found_in,
|
||||
unsigned expr_wid,
|
||||
|
|
@ -4662,6 +5048,10 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
|
|||
return elaborate_expr_net_bit_(des, scope, node, found_in,
|
||||
need_const);
|
||||
|
||||
if (use_sel == index_component_t::SEL_BIT_LAST)
|
||||
return elaborate_expr_net_bit_last_(des, scope, node, found_in,
|
||||
need_const);
|
||||
|
||||
// It's not anything else, so this must be a simple identifier
|
||||
// expression with no part or bit select. Return the signal
|
||||
// itself as the expression.
|
||||
|
|
@ -4740,6 +5130,8 @@ NetExpr* PENewClass::elaborate_expr_constructor_(Design*des, NetScope*scope,
|
|||
const netclass_t*ctype,
|
||||
NetExpr*obj, unsigned /*flags*/) const
|
||||
{
|
||||
ivl_assert(*this, ctype);
|
||||
|
||||
// If there is an initializer function, then pass the object
|
||||
// through that function first. Note that the initializer
|
||||
// function has no arguments other than the object itself.
|
||||
|
|
@ -4777,6 +5169,12 @@ NetExpr* PENewClass::elaborate_expr_constructor_(Design*des, NetScope*scope,
|
|||
|
||||
|
||||
NetFuncDef*def = new_scope->func_def();
|
||||
if (def == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Scope " << scope_path(new_scope)
|
||||
<< " is missing constructor definition." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
ivl_assert(*this, def);
|
||||
|
||||
// Are there too many arguments passed to the function. If so,
|
||||
|
|
|
|||
63
elab_lval.cc
63
elab_lval.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
|
|
@ -27,6 +27,7 @@
|
|||
# include "netstruct.h"
|
||||
# include "netclass.h"
|
||||
# include "netdarray.h"
|
||||
# include "netparray.h"
|
||||
# include "netvector.h"
|
||||
# include "compiler.h"
|
||||
# include <cstdlib>
|
||||
|
|
@ -397,23 +398,49 @@ NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des,
|
|||
if (path_.size() != 1)
|
||||
return 0;
|
||||
|
||||
const netclass_t*class_type = scope->parent()->class_def();
|
||||
const netclass_t*class_type = find_class_containing_scope(*this, scope);
|
||||
if (class_type == 0)
|
||||
return 0;
|
||||
|
||||
perm_string member_name = peek_tail_name(path_);
|
||||
const name_component_t&name_comp = path_.back();
|
||||
|
||||
perm_string member_name = name_comp.name;
|
||||
int pidx = class_type->property_idx_from_name(member_name);
|
||||
if (pidx < 0)
|
||||
return 0;
|
||||
|
||||
NetNet*this_net = scope->find_signal(perm_string::literal("@"));
|
||||
NetScope*scope_method = find_method_containing_scope(*this, scope);
|
||||
ivl_assert(*this, scope_method);
|
||||
|
||||
NetNet*this_net = scope_method->find_signal(perm_string::literal("@"));
|
||||
if (this_net == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Unable to find 'this' port of " << scope_path(scope)
|
||||
<< "Unable to find 'this' port of " << scope_path(scope_method)
|
||||
<< "." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lval_method_class_member_: "
|
||||
<< "Ident " << member_name
|
||||
<< " is a property of class " << class_type->get_name() << endl;
|
||||
}
|
||||
|
||||
NetExpr*canon_index = 0;
|
||||
if (! name_comp.index.empty()) {
|
||||
ivl_type_t property_type = class_type->get_prop_type(pidx);
|
||||
|
||||
if (const netsarray_t* stype = dynamic_cast<const netsarray_t*> (property_type)) {
|
||||
canon_index = make_canonical_index(des, scope, this,
|
||||
name_comp.index, stype, false);
|
||||
|
||||
} else {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Index expressions don't apply to this type of property." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Detect assignment to constant properties. Note that the
|
||||
// initializer constructor MAY assign to constant properties,
|
||||
// as this is how the property gets its value.
|
||||
|
|
@ -448,8 +475,34 @@ NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des,
|
|||
}
|
||||
}
|
||||
|
||||
ivl_type_t tmp_type = class_type->get_prop_type(pidx);
|
||||
if (const netuarray_t*tmp_ua = dynamic_cast<const netuarray_t*>(tmp_type)) {
|
||||
|
||||
const std::vector<netrange_t>&dims = tmp_ua->static_dimensions();
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lval_method_class_member_: "
|
||||
<< "Property " << class_type->get_prop_name(pidx)
|
||||
<< " has " << dims.size() << " dimensions, "
|
||||
<< " got " << name_comp.index.size() << " indices." << endl;
|
||||
if (canon_index) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lval_method_class_member_: "
|
||||
<< "Canonical index is:" << *canon_index << endl;
|
||||
};
|
||||
}
|
||||
|
||||
if (dims.size() != name_comp.index.size()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Got " << name_comp.index.size() << " indices, "
|
||||
<< "expecting " << dims.size()
|
||||
<< " to index the property " << class_type->get_prop_name(pidx) << "." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
NetAssign_*this_lval = new NetAssign_(this_net);
|
||||
this_lval->set_property(member_name);
|
||||
if (canon_index) this_lval->set_word(canon_index);
|
||||
|
||||
return this_lval;
|
||||
}
|
||||
|
|
|
|||
103
elab_net.cc
103
elab_net.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999-2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
|
|
@ -501,6 +501,10 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
unsigned midx = sig->vector_width()-1, lidx = 0;
|
||||
// The default word select is the first.
|
||||
long widx = 0;
|
||||
// Set this to true if we calculate the word index. This is
|
||||
// used to distinguish between unpacked array assignment and
|
||||
// array word assignment.
|
||||
bool widx_flag = false;
|
||||
|
||||
list<long> unpacked_indices_const;
|
||||
|
||||
|
|
@ -555,8 +559,9 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
packed_base = collapse_array_indices(des, scope, sig, tmp_index);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "packed_base expression = " << *packed_base << endl;
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
|
||||
<< "packed_base=" << *packed_base
|
||||
<< ", member_off=" << member_off << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -590,13 +595,31 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
midx = lidx + tmp_wid - 1;
|
||||
}
|
||||
|
||||
} else if (gn_system_verilog() && sig->unpacked_dimensions() > 0 && path_tail.index.empty()) {
|
||||
|
||||
// In this case, we are doing a continuous assignment to
|
||||
// an unpacked array. The NetNet representation is a
|
||||
// NetNet with a pin for each array element, so there is
|
||||
// nothing more needed here.
|
||||
//
|
||||
// This can come up from code like this:
|
||||
// logic [...] data [0:3];
|
||||
// assign data = ...;
|
||||
// In this case, "sig" is "data", and sig->pin_count()
|
||||
// is 4 to account for the unpacked size.
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
|
||||
<< "Net assign to unpacked array \"" << sig->name()
|
||||
<< "\" with " << sig->pin_count() << " elements." << endl;
|
||||
}
|
||||
|
||||
} else if (sig->unpacked_dimensions() > 0) {
|
||||
|
||||
// Make sure there are enough indices to address an array element.
|
||||
if (path_tail.index.size() < sig->unpacked_dimensions()) {
|
||||
cerr << get_fileline() << ": error: Array " << path()
|
||||
<< " needs " << sig->unpacked_dimensions() << " indices,"
|
||||
<< " but got only " << path_tail.index.size() << "." << endl;
|
||||
<< " but got only " << path_tail.index.size() << ". (net)" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -627,6 +650,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
<< sig->name() << as_indices(unpacked_indices)
|
||||
<< "." << endl;
|
||||
widx = -1;
|
||||
widx_flag = true;
|
||||
|
||||
} else {
|
||||
NetExpr*canon_index = 0;
|
||||
|
|
@ -639,12 +663,14 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
<< sig->name() << as_indices(unpacked_indices_const)
|
||||
<< "." << endl;
|
||||
widx = -1;
|
||||
widx_flag = true;
|
||||
|
||||
} else {
|
||||
NetEConst*canon_const = dynamic_cast<NetEConst*>(canon_index);
|
||||
ivl_assert(*this, canon_const);
|
||||
|
||||
widx = canon_const->value().as_long();
|
||||
widx_flag = true;
|
||||
delete canon_index;
|
||||
}
|
||||
}
|
||||
|
|
@ -682,6 +708,16 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
} else if (!path_tail.index.empty()) {
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
|
||||
<< "path_tail.index.size()=" << path_tail.index.size()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// There are index expressions on the name, so this is a
|
||||
// bit/slice select of the name. Calculate a canonical
|
||||
// part select.
|
||||
|
||||
if (sig->get_scalar()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "can not select part of ";
|
||||
|
|
@ -710,14 +746,21 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
unsigned subnet_wid = midx-lidx+1;
|
||||
|
||||
/* Check if the l-value bits are double-driven. */
|
||||
if (sig->type() == NetNet::UNRESOLVED_WIRE && sig->test_and_set_part_driver(midx,lidx)) {
|
||||
if (sig->type() == NetNet::UNRESOLVED_WIRE && sig->test_and_set_part_driver(midx,lidx, widx_flag? widx : 0)) {
|
||||
cerr << get_fileline() << ": error: Unresolved net/uwire "
|
||||
<< sig->name() << " cannot have multiple drivers." << endl;
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": : Overlap in "
|
||||
<< "[" << midx << ":" << lidx << "] (canonical)"
|
||||
<< ", widx=" << (widx_flag? widx : 0)
|
||||
<< ", vector width=" << sig->vector_width()
|
||||
<< endl;
|
||||
}
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sig->pin_count() > 1) {
|
||||
if (sig->pin_count() > 1 && widx_flag) {
|
||||
if (widx < 0 || widx >= (long) sig->pin_count())
|
||||
return 0;
|
||||
|
||||
|
|
@ -729,6 +772,13 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
tmp->local_flag(true);
|
||||
connect(sig->pin(widx), tmp->pin(0));
|
||||
sig = tmp;
|
||||
|
||||
} else if (sig->pin_count() > 1) {
|
||||
|
||||
// If this turns out to be an l-value unpacked array,
|
||||
// then let the caller handle it. It will probably be
|
||||
// converted into an array of assignments.
|
||||
return sig;
|
||||
}
|
||||
|
||||
/* If the desired l-value vector is narrower than the
|
||||
|
|
@ -851,6 +901,33 @@ NetNet* PEIdent::elaborate_subport(Design*des, NetScope*scope) const
|
|||
long midx;
|
||||
long lidx;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_subport: "
|
||||
<< "path_ = \"" << path_
|
||||
<< "\", unpacked_dimensions=" << sig->unpacked_dimensions()
|
||||
<< ", port_type()=" << sig->port_type() << endl;
|
||||
}
|
||||
|
||||
if (sig->unpacked_dimensions() && !gn_system_verilog()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Ports cannot be unpacked arrays. Try enabling SystemVerilog support." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// There cannot be parts to an unpacked array, so process this
|
||||
// simply as an unpacked array.
|
||||
if (sig->unpacked_dimensions()) {
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_subport: "
|
||||
<< "path_=\"" << path_
|
||||
<< "\" is an unpacked array with " << sig->pin_count()
|
||||
<< " elements." << endl;
|
||||
}
|
||||
scope->add_module_port_net(sig);
|
||||
return sig;
|
||||
}
|
||||
|
||||
/* Evaluate the part/bit select expressions, to get the part
|
||||
select of the signal that attaches to the port. Also handle
|
||||
range and direction checking here. */
|
||||
|
|
@ -912,6 +989,20 @@ NetNet* PEIdent::elaborate_subport(Design*des, NetScope*scope) const
|
|||
return sig;
|
||||
}
|
||||
|
||||
NetNet*PEIdent::elaborate_unpacked_net(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetNet* sig = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
perm_string method_name;
|
||||
|
||||
symbol_search(this, des, scope, path_, sig, par, eve);
|
||||
|
||||
ivl_assert(*this, sig);
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
bool PEIdent::is_collapsible_net(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope);
|
||||
|
|
|
|||
143
elab_scope.cc
143
elab_scope.cc
|
|
@ -425,6 +425,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
|
|||
|
||||
netclass_t*use_base_class = 0;
|
||||
if (base_class) {
|
||||
ivl_assert(*pclass, scope);
|
||||
use_base_class = scope->find_class(base_class->name);
|
||||
if (use_base_class == 0) {
|
||||
cerr << pclass->get_fileline() << ": error: "
|
||||
|
|
@ -436,6 +437,9 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
|
|||
|
||||
netclass_t*use_class = new netclass_t(use_type->name, use_base_class);
|
||||
|
||||
ivl_assert(*pclass, use_type->save_elaborated_type == 0);
|
||||
use_type->save_elaborated_type = use_class;
|
||||
|
||||
// Class scopes have no parent scope, because references are
|
||||
// not allowed to escape a class method.
|
||||
NetScope*class_scope = new NetScope(0, hname_t(pclass->pscope_name()),
|
||||
|
|
@ -443,18 +447,22 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
|
|||
class_scope->set_line(pclass);
|
||||
class_scope->set_class_def(use_class);
|
||||
use_class->set_class_scope(class_scope);
|
||||
use_class->set_definition_scope(scope);
|
||||
|
||||
// Collect the properties, elaborate them, and add them to the
|
||||
// elaborated class definition.
|
||||
for (map<perm_string, class_type_t::prop_info_t>::iterator cur = use_type->properties.begin()
|
||||
; cur != use_type->properties.end() ; ++ cur) {
|
||||
if (debug_scopes) {
|
||||
cerr << pclass->get_fileline() << ": elaborate_scope_class: "
|
||||
<< " Property " << cur->first << endl;
|
||||
}
|
||||
|
||||
ivl_type_s*tmp = cur->second.type->elaborate_type(des, scope);
|
||||
ivl_assert(*pclass, tmp);
|
||||
if (debug_scopes) {
|
||||
cerr << pclass->get_fileline() << ": elaborate_scope_class: "
|
||||
<< " Property " << cur->first
|
||||
<< " type=" << *tmp << endl;
|
||||
}
|
||||
use_class->set_property(cur->first, cur->second.qual, tmp);
|
||||
|
||||
}
|
||||
|
||||
for (map<perm_string,PTask*>::iterator cur = pclass->tasks.begin()
|
||||
|
|
@ -493,7 +501,12 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
|
|||
cur->second->elaborate_scope(des, method_scope);
|
||||
}
|
||||
|
||||
scope->add_class(use_class);
|
||||
if (scope) {
|
||||
scope->add_class(use_class);
|
||||
|
||||
} else {
|
||||
des->add_class(use_class, pclass);
|
||||
}
|
||||
}
|
||||
|
||||
static void elaborate_scope_classes(Design*des, NetScope*scope,
|
||||
|
|
@ -505,6 +518,18 @@ static void elaborate_scope_classes(Design*des, NetScope*scope,
|
|||
}
|
||||
}
|
||||
|
||||
void elaborate_rootscope_classes(Design*des)
|
||||
{
|
||||
if (pform_classes.empty())
|
||||
return;
|
||||
|
||||
for (map<perm_string,PClass*>::iterator cur = pform_classes.begin()
|
||||
; cur != pform_classes.end() ; ++ cur) {
|
||||
blend_class_constructors(cur->second);
|
||||
elaborate_scope_class(des, 0, cur->second);
|
||||
}
|
||||
}
|
||||
|
||||
static void replace_scope_parameters_(NetScope*scope, const LineInfo&loc,
|
||||
const Module::replace_t&replacements)
|
||||
{
|
||||
|
|
@ -546,6 +571,25 @@ static void elaborate_scope_events_(Design*des, NetScope*scope,
|
|||
}
|
||||
}
|
||||
|
||||
static void elaborate_scope_task(Design*des, NetScope*scope, PTask*task)
|
||||
{
|
||||
hname_t use_name( task->pscope_name() );
|
||||
|
||||
NetScope*task_scope = new NetScope(scope, use_name, NetScope::TASK);
|
||||
task_scope->is_auto(task->is_auto());
|
||||
task_scope->set_line(task);
|
||||
|
||||
if (scope==0)
|
||||
des->add_root_task(task_scope, task);
|
||||
|
||||
if (debug_scopes) {
|
||||
cerr << task->get_fileline() << ": elaborate_scope_task: "
|
||||
<< "Elaborate task scope " << scope_path(task_scope) << endl;
|
||||
}
|
||||
|
||||
task->elaborate_scope(des, task_scope);
|
||||
}
|
||||
|
||||
static void elaborate_scope_tasks(Design*des, NetScope*scope,
|
||||
const map<perm_string,PTask*>&tasks)
|
||||
{
|
||||
|
|
@ -587,19 +631,30 @@ static void elaborate_scope_tasks(Design*des, NetScope*scope,
|
|||
des->errors += 1;
|
||||
}
|
||||
|
||||
NetScope*task_scope = new NetScope(scope, use_name,
|
||||
NetScope::TASK);
|
||||
task_scope->is_auto((*cur).second->is_auto());
|
||||
task_scope->set_line((*cur).second);
|
||||
|
||||
if (debug_scopes)
|
||||
cerr << cur->second->get_fileline() << ": debug: "
|
||||
<< "Elaborate task scope " << scope_path(task_scope) << endl;
|
||||
(*cur).second->elaborate_scope(des, task_scope);
|
||||
elaborate_scope_task(des, scope, cur->second);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void elaborate_scope_func(Design*des, NetScope*scope, PFunction*task)
|
||||
{
|
||||
hname_t use_name( task->pscope_name() );
|
||||
|
||||
NetScope*task_scope = new NetScope(scope, use_name, NetScope::FUNC);
|
||||
task_scope->is_auto(task->is_auto());
|
||||
task_scope->set_line(task);
|
||||
|
||||
if (scope==0)
|
||||
des->add_root_task(task_scope, task);
|
||||
|
||||
if (debug_scopes) {
|
||||
cerr << task->get_fileline() << ": elaborate_scope_func: "
|
||||
<< "Elaborate task scope " << scope_path(task_scope) << endl;
|
||||
}
|
||||
|
||||
task->elaborate_scope(des, task_scope);
|
||||
}
|
||||
|
||||
static void elaborate_scope_funcs(Design*des, NetScope*scope,
|
||||
const map<perm_string,PFunction*>&funcs)
|
||||
{
|
||||
|
|
@ -642,19 +697,33 @@ static void elaborate_scope_funcs(Design*des, NetScope*scope,
|
|||
des->errors += 1;
|
||||
}
|
||||
|
||||
NetScope*func_scope = new NetScope(scope, use_name,
|
||||
NetScope::FUNC);
|
||||
func_scope->is_auto((*cur).second->is_auto());
|
||||
func_scope->set_line((*cur).second);
|
||||
|
||||
if (debug_scopes)
|
||||
cerr << cur->second->get_fileline() << ": debug: "
|
||||
<< "Elaborate function scope " << scope_path(func_scope) << endl;
|
||||
(*cur).second->elaborate_scope(des, func_scope);
|
||||
elaborate_scope_func(des, scope, cur->second);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void elaborate_rootscope_tasks(Design*des)
|
||||
{
|
||||
for (map<perm_string,PTaskFunc*>::iterator cur = pform_tasks.begin()
|
||||
; cur != pform_tasks.end() ; ++ cur) {
|
||||
|
||||
if (PTask*task = dynamic_cast<PTask*> (cur->second)) {
|
||||
elaborate_scope_task(des, 0, task);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (PFunction*func = dynamic_cast<PFunction*>(cur->second)) {
|
||||
elaborate_scope_func(des, 0, func);
|
||||
continue;
|
||||
}
|
||||
|
||||
cerr << cur->second->get_fileline() << ": internal error: "
|
||||
<< "elabortae_rootscope_tasks does not understand "
|
||||
<< "this object," << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
class generate_schemes_work_item_t : public elaborator_work_item_t {
|
||||
public:
|
||||
generate_schemes_work_item_t(Design*des__, NetScope*scope, Module*mod)
|
||||
|
|
@ -690,12 +759,14 @@ class generate_schemes_work_item_t : public elaborator_work_item_t {
|
|||
bool PPackage::elaborate_scope(Design*des, NetScope*scope)
|
||||
{
|
||||
if (debug_scopes) {
|
||||
cerr << get_fileline() << ": debug: Elaborate package scope "
|
||||
<< scope_path(scope) << "." << endl;
|
||||
cerr << get_fileline() << ": PPackage::elaborate_scope: "
|
||||
<< "Elaborate package " << scope_path(scope) << "." << endl;
|
||||
}
|
||||
|
||||
collect_scope_parameters_(des, scope, parameters);
|
||||
collect_scope_localparams_(des, scope, localparams);
|
||||
elaborate_scope_enumerations(des, scope, enum_sets);
|
||||
elaborate_scope_classes(des, scope, classes_lexical);
|
||||
elaborate_scope_funcs(des, scope, funcs);
|
||||
elaborate_scope_tasks(des, scope, tasks);
|
||||
return true;
|
||||
|
|
@ -705,8 +776,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
|||
const replace_t&replacements)
|
||||
{
|
||||
if (debug_scopes) {
|
||||
cerr << get_fileline() << ": debug: Elaborate scope "
|
||||
<< scope_path(scope) << "." << endl;
|
||||
cerr << get_fileline() << ": Module::elaborate_scope: "
|
||||
<< "Elaborate " << scope_path(scope) << "." << endl;
|
||||
}
|
||||
|
||||
// Add the genvars to the scope.
|
||||
|
|
@ -892,8 +963,10 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
|||
|
||||
// Check the generate block name.
|
||||
|
||||
// A generate "loop" can not have the same name as another scope object.
|
||||
const NetScope *child = container->child(hname_t(scope_name));
|
||||
// A generate "loop" can not have the same name as another
|
||||
// scope object. Find any scope with this name, not just an
|
||||
// exact match scope.
|
||||
const NetScope *child = container->child_byname(scope_name);
|
||||
if (child) {
|
||||
cerr << get_fileline() << ": error: generate \"loop\" and ";
|
||||
child->print_type(cerr);
|
||||
|
|
@ -1897,6 +1970,18 @@ void PEventStatement::elaborate_scope(Design*des, NetScope*scope) const
|
|||
statement_ -> elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
/*
|
||||
* The standard says that we create an implicit scope for foreach
|
||||
* loops, but that is just to hold the index variables, and we'll
|
||||
* handle them by creating unique names. So just jump into the
|
||||
* contained statement for scope elaboration.
|
||||
*/
|
||||
void PForeach::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_ -> elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
/*
|
||||
* Statements that contain a further statement but do not
|
||||
* intrinsically add a scope need to elaborate_scope the contained
|
||||
|
|
|
|||
157
elab_sig.cc
157
elab_sig.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
|
|
@ -41,6 +41,7 @@
|
|||
# include "netvector.h"
|
||||
# include "netdarray.h"
|
||||
# include "netparray.h"
|
||||
# include "netqueue.h"
|
||||
# include "util.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
|
|
@ -206,6 +207,11 @@ bool PPackage::elaborate_sig(Design*des, NetScope*scope) const
|
|||
{
|
||||
bool flag = true;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PPackage::elaborate_sig: "
|
||||
<< "Start package scope=" << scope_path(scope) << endl;
|
||||
}
|
||||
|
||||
flag = elaborate_sig_wires_(des, scope) && flag;
|
||||
|
||||
// After all the wires are elaborated, we are free to
|
||||
|
|
@ -214,6 +220,13 @@ bool PPackage::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
elaborate_sig_funcs(des, scope, funcs);
|
||||
elaborate_sig_tasks(des, scope, tasks);
|
||||
elaborate_sig_classes(des, scope, classes);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PPackage::elaborate_sig: "
|
||||
<< "Done package scope=" << scope_path(scope)
|
||||
<< ", flag=" << flag << endl;
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
|
@ -563,7 +576,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
// Special case: this is a constructor, so the return
|
||||
// signal is also the first argument. For example, the
|
||||
// source code for the definition may be:
|
||||
// function new(...);
|
||||
// function new(...);
|
||||
// endfunction
|
||||
// In this case, the "@" port is the synthetic "this"
|
||||
// argument and we also use it as a return value at the
|
||||
|
|
@ -594,6 +607,11 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
}
|
||||
|
||||
if (ret_type) {
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PFunction::elaborate_sig: "
|
||||
<< "return type: " << *ret_type << endl;
|
||||
return_type_->pform_dump(cerr, 8);
|
||||
}
|
||||
list<netrange_t> ret_unpacked;
|
||||
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_unpacked, ret_type);
|
||||
|
||||
|
|
@ -615,9 +633,10 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
NetFuncDef*def = new NetFuncDef(scope, ret_sig, ports, pdef);
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Attach function definition to scope "
|
||||
<< scope_path(scope) << "." << endl;
|
||||
cerr << get_fileline() << ": PFunction::elaborate_sig: "
|
||||
<< "Attach function definition " << scope_path(scope)
|
||||
<< " with ret_sig width=" << (ret_sig? ret_sig->vector_width() : 0)
|
||||
<< "." << endl;
|
||||
|
||||
scope->set_func_def(def);
|
||||
|
||||
|
|
@ -799,6 +818,12 @@ void PEventStatement::elaborate_sig(Design*des, NetScope*scope) const
|
|||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
void PForeach::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
void PForever::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
|
|
@ -823,55 +848,6 @@ void PWhile::elaborate_sig(Design*des, NetScope*scope) const
|
|||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
static bool evaluate_ranges(Design*des, NetScope*scope,
|
||||
vector<netrange_t>&llist,
|
||||
const list<pform_range_t>&rlist)
|
||||
{
|
||||
bool bad_msb = false, bad_lsb = false;
|
||||
|
||||
for (list<pform_range_t>::const_iterator cur = rlist.begin()
|
||||
; cur != rlist.end() ; ++cur) {
|
||||
long use_msb, use_lsb;
|
||||
|
||||
NetExpr*texpr = elab_and_eval(des, scope, cur->first, -1, true);
|
||||
if (! eval_as_long(use_msb, texpr)) {
|
||||
cerr << cur->first->get_fileline() << ": error: "
|
||||
"Range expressions must be constant." << endl;
|
||||
cerr << cur->first->get_fileline() << " : "
|
||||
"This MSB expression violates the rule: "
|
||||
<< *cur->first << endl;
|
||||
des->errors += 1;
|
||||
bad_msb = true;
|
||||
}
|
||||
|
||||
delete texpr;
|
||||
|
||||
texpr = elab_and_eval(des, scope, cur->second, -1, true);
|
||||
if (! eval_as_long(use_lsb, texpr)) {
|
||||
cerr << cur->second->get_fileline() << ": error: "
|
||||
"Range expressions must be constant." << endl;
|
||||
cerr << cur->second->get_fileline() << " : "
|
||||
"This LSB expression violates the rule: "
|
||||
<< *cur->second << endl;
|
||||
des->errors += 1;
|
||||
bad_lsb = true;
|
||||
}
|
||||
|
||||
delete texpr;
|
||||
|
||||
llist.push_back(netrange_t(use_msb, use_lsb));
|
||||
}
|
||||
|
||||
return bad_msb | bad_lsb;
|
||||
}
|
||||
|
||||
static netclass_t* locate_class_type(Design*, NetScope*scope,
|
||||
class_type_t*class_type)
|
||||
{
|
||||
netclass_t*use_class = scope->find_class(class_type->name);
|
||||
return use_class;
|
||||
}
|
||||
|
||||
static ivl_type_s*elaborate_type(Design*des, NetScope*scope,
|
||||
data_type_t*pform_type)
|
||||
{
|
||||
|
|
@ -949,7 +925,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
des->errors += error_cnt_;
|
||||
|
||||
// A signal can not have the same name as a scope object.
|
||||
const NetScope *child = scope->child(hname_t(name_));
|
||||
const NetScope *child = scope->child_byname(name_);
|
||||
if (child) {
|
||||
cerr << get_fileline() << ": error: signal and ";
|
||||
child->print_type(cerr);
|
||||
|
|
@ -1078,7 +1054,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
|
||||
list<netrange_t>unpacked_dimensions;
|
||||
netdarray_t*netarray = 0;
|
||||
netdarray_t*netdarray = 0;
|
||||
|
||||
for (list<pform_range_t>::const_iterator cur = unpacked_.begin()
|
||||
; cur != unpacked_.end() ; ++cur) {
|
||||
|
|
@ -1091,13 +1067,23 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
if (use_lidx==0 && use_ridx==0) {
|
||||
netvector_t*vec = new netvector_t(packed_dimensions, data_type_);
|
||||
packed_dimensions.clear();
|
||||
ivl_assert(*this, netarray==0);
|
||||
netarray = new netdarray_t(vec);
|
||||
ivl_assert(*this, netdarray==0);
|
||||
netdarray = new netdarray_t(vec);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Special case: Detect the mark for a QUEUE
|
||||
// declaration, which is the dimensions [null:<nil>].
|
||||
if (use_ridx==0 && dynamic_cast<PENull*>(use_lidx)) {
|
||||
netvector_t*vec = new netvector_t(packed_dimensions, data_type_);
|
||||
packed_dimensions.clear();
|
||||
ivl_assert(*this, netdarray==0);
|
||||
netdarray = new netqueue_t(vec);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Cannot handle dynamic arrays of arrays yet.
|
||||
ivl_assert(*this, netarray==0);
|
||||
ivl_assert(*this, netdarray==0);
|
||||
ivl_assert(*this, use_lidx && use_ridx);
|
||||
|
||||
NetExpr*lexp = elab_and_eval(des, scope, use_lidx, -1, true);
|
||||
|
|
@ -1190,22 +1176,11 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
// should already have been elaborated. All we need to
|
||||
// do right now is locate the netclass_t object for the
|
||||
// class, and use that to build the net.
|
||||
netclass_t*use_type = locate_class_type(des, scope, class_type);
|
||||
if (use_type == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Class " << class_type->name
|
||||
<< " isn't elaborated in scope=" << scope_path(scope) << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
ivl_assert(*this, use_type);
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Create class instance signal " << wtype
|
||||
<< " " << name_ << endl;
|
||||
}
|
||||
// (No arrays of classes)
|
||||
list<netrange_t> use_unpacked;
|
||||
sig = new NetNet(scope, name_, wtype, use_unpacked, use_type);
|
||||
|
||||
ivl_assert(*this, class_type->save_elaborated_type);
|
||||
netclass_t*use_type = class_type->save_elaborated_type;
|
||||
|
||||
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_type);
|
||||
|
||||
} else if (struct_type_t*struct_type = dynamic_cast<struct_type_t*>(set_data_type_)) {
|
||||
// If this is a struct type, then build the net with the
|
||||
|
|
@ -1226,7 +1201,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
} else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(set_data_type_)) {
|
||||
list<named_pexpr_t>::const_iterator sample_name = enum_type->names->begin();
|
||||
const netenum_t*use_enum = scope->enumeration_for_name(sample_name->name);
|
||||
const netenum_t*use_enum = scope->find_enumeration_for_name(sample_name->name);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal " << wtype
|
||||
|
|
@ -1240,7 +1215,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_enum);
|
||||
|
||||
|
||||
} else if (netarray) {
|
||||
} else if (netdarray) {
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal " << wtype
|
||||
|
|
@ -1250,7 +1225,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
ivl_assert(*this, packed_dimensions.empty());
|
||||
ivl_assert(*this, unpacked_dimensions.empty());
|
||||
sig = new NetNet(scope, name_, wtype, netarray);
|
||||
sig = new NetNet(scope, name_, wtype, netdarray);
|
||||
|
||||
} else if (parray_type_t*parray_type = dynamic_cast<parray_type_t*>(set_data_type_)) {
|
||||
// The pform gives us a parray_type_t for packed arrays
|
||||
|
|
@ -1266,7 +1241,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal " << wtype
|
||||
<< " parray=" << use_type->packed_dimensions()
|
||||
<< " parray=" << use_type->static_dimensions()
|
||||
<< " " << name_ << unpacked_dimensions
|
||||
<< " in scope " << scope_path(scope) << endl;
|
||||
}
|
||||
|
|
@ -1321,3 +1296,27 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
return sig;
|
||||
}
|
||||
|
||||
|
||||
void Design::root_elaborate_sig(void)
|
||||
{
|
||||
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
|
||||
; cur != classes_.end() ; ++ cur) {
|
||||
|
||||
netclass_t*cur_class = cur->second;
|
||||
PClass*cur_pclass = class_to_pclass_[cur_class];
|
||||
|
||||
cur_class->elaborate_sig(this, cur_pclass);
|
||||
}
|
||||
|
||||
for (map<NetScope*,PTaskFunc*>::iterator cur = root_tasks_.begin()
|
||||
; cur != root_tasks_.end() ; ++ cur) {
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << cur->second->get_fileline() << ": root_elaborate_sig: "
|
||||
<< "Elaborate_sig for root task/func " << scope_path(cur->first) << endl;
|
||||
}
|
||||
|
||||
cur->second->elaborate_sig(this, cur->first);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
49
elab_type.cc
49
elab_type.cc
|
|
@ -22,6 +22,7 @@
|
|||
# include "netclass.h"
|
||||
# include "netdarray.h"
|
||||
# include "netenum.h"
|
||||
# include "netparray.h"
|
||||
# include "netscalar.h"
|
||||
# include "netstruct.h"
|
||||
# include "netvector.h"
|
||||
|
|
@ -31,6 +32,25 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* Elaborations of types may vary depending on the scope that it is
|
||||
* done in, so keep a per-scope cache of the results.
|
||||
*/
|
||||
ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*scope)
|
||||
{
|
||||
Definitions*use_definitions = scope;
|
||||
if (use_definitions == 0)
|
||||
use_definitions = des;
|
||||
|
||||
map<Definitions*,ivl_type_s*>::iterator pos = cache_type_elaborate_.lower_bound(use_definitions);
|
||||
if (pos->first == use_definitions)
|
||||
return pos->second;
|
||||
|
||||
ivl_type_s*tmp = elaborate_type_raw(des, scope);
|
||||
cache_type_elaborate_.insert(pos, pair<NetScope*,ivl_type_s*>(scope, tmp));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
ivl_type_s* data_type_t::elaborate_type_raw(Design*des, NetScope*) const
|
||||
{
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
|
|
@ -75,9 +95,10 @@ ivl_type_s* atom2_type_t::elaborate_type_raw(Design*des, NetScope*) const
|
|||
}
|
||||
}
|
||||
|
||||
ivl_type_s* class_type_t::elaborate_type_raw(Design*, NetScope*scope) const
|
||||
ivl_type_s* class_type_t::elaborate_type_raw(Design*, NetScope*) const
|
||||
{
|
||||
return scope->find_class(name);
|
||||
ivl_assert(*this, save_elaborated_type);
|
||||
return save_elaborated_type;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -188,9 +209,27 @@ ivl_type_s* uarray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
|||
|
||||
ivl_type_t btype = base_type->elaborate_type(des, scope);
|
||||
|
||||
assert(dims->size() == 1);
|
||||
assert(dims->size() >= 1);
|
||||
list<pform_range_t>::const_iterator cur = dims->begin();
|
||||
assert(cur->first == 0 && cur->second==0);
|
||||
ivl_type_s*res = new netdarray_t(btype);
|
||||
|
||||
// Special case: if the dimension is nil:nil, this is a
|
||||
// dynamic array. Note that we only know how to handle dynamic
|
||||
// arrays with 1 dimension at a time.
|
||||
if (cur->first==0 && cur->second==0) {
|
||||
assert(dims->size()==1);
|
||||
ivl_type_s*res = new netdarray_t(btype);
|
||||
return res;
|
||||
}
|
||||
|
||||
vector<netrange_t> dimensions;
|
||||
bool bad_range = evaluate_ranges(des, scope, dimensions, *dims);
|
||||
|
||||
if (bad_range) {
|
||||
cerr << get_fileline() << " : warning: "
|
||||
<< "Bad dimensions for type here." << endl;
|
||||
}
|
||||
|
||||
ivl_assert(*this, btype);
|
||||
ivl_type_s*res = new netuarray_t(dimensions, btype);
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
505
elaborate.cc
505
elaborate.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
|
|
@ -40,6 +40,7 @@
|
|||
# include "netlist.h"
|
||||
# include "netvector.h"
|
||||
# include "netdarray.h"
|
||||
# include "netparray.h"
|
||||
# include "netclass.h"
|
||||
# include "netmisc.h"
|
||||
# include "util.h"
|
||||
|
|
@ -77,11 +78,19 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
return;
|
||||
}
|
||||
|
||||
// If this turns out to be an assignment to an unpacked array,
|
||||
// then handle that special case elsewhere.
|
||||
if (lval->pin_count() > 1) {
|
||||
elaborate_unpacked_array_(des, scope, lval);
|
||||
return;
|
||||
}
|
||||
|
||||
ivl_assert(*this, lval->pin_count() == 1);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: PGAssign: elaborated l-value"
|
||||
<< " width=" << lval->vector_width() << endl;
|
||||
cerr << get_fileline() << ": PGAssign::elaborate: elaborated l-value"
|
||||
<< " width=" << lval->vector_width()
|
||||
<< ", pin_count=" << lval->pin_count() << endl;
|
||||
}
|
||||
|
||||
NetExpr*rval_expr = elaborate_rval_expr(des, scope, lval->net_type(),
|
||||
|
|
@ -211,6 +220,18 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
}
|
||||
|
||||
void PGAssign::elaborate_unpacked_array_(Design*des, NetScope*scope, NetNet*lval) const
|
||||
{
|
||||
PEIdent*rval_pident = dynamic_cast<PEIdent*> (pin(1));
|
||||
ivl_assert(*this, rval_pident);
|
||||
|
||||
NetNet*rval_net = rval_pident->elaborate_unpacked_net(des, scope);
|
||||
|
||||
ivl_assert(*this, rval_net->pin_count() == lval->pin_count());
|
||||
|
||||
assign_unpacked_with_bufz(des, scope, this, lval, rval_net);
|
||||
}
|
||||
|
||||
unsigned PGBuiltin::calculate_array_count_(Design*des, NetScope*scope,
|
||||
long&high, long&low) const
|
||||
{
|
||||
|
|
@ -1287,6 +1308,10 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
|||
perm_string pname = peek_tail_name(mport[0]->path());
|
||||
|
||||
NetNet*tmp = instance[0]->find_signal(pname);
|
||||
|
||||
// Handle the error case where there is no internal
|
||||
// signal connected to the port.
|
||||
if (!tmp) continue;
|
||||
assert(tmp);
|
||||
|
||||
if (tmp->port_type() == NetNet::PINPUT) {
|
||||
|
|
@ -1350,18 +1375,22 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
|||
unsigned int prt_vector_width = 0;
|
||||
PortType::Enum ptype = PortType::PIMPLICIT;
|
||||
// Scan the module sub-ports for this instance...
|
||||
// (Sub-ports are concatenated ports that form the
|
||||
// single port for the instance. This is not a
|
||||
// commonly used feature.)
|
||||
for (unsigned ldx = 0 ; ldx < mport.size() ; ldx += 1) {
|
||||
unsigned lbase = inst * mport.size();
|
||||
PEIdent*pport = mport[ldx];
|
||||
assert(pport);
|
||||
ivl_assert(*this, pport);
|
||||
NetNet *netnet = pport->elaborate_subport(des, inst_scope);
|
||||
prts[lbase + ldx] = netnet;
|
||||
if (netnet == 0)
|
||||
continue;
|
||||
|
||||
assert(netnet);
|
||||
prts_vector_width += netnet->vector_width();
|
||||
prt_vector_width += netnet->vector_width();
|
||||
ivl_assert(*this, netnet);
|
||||
unsigned port_width = netnet->vector_width() * netnet->pin_count();
|
||||
prts_vector_width += port_width;
|
||||
prt_vector_width += port_width;
|
||||
ptype = PortType::merged(netnet->port_type(), ptype);
|
||||
}
|
||||
inst_scope->add_module_port_info(idx, rmod->get_port_name(idx), ptype, prt_vector_width );
|
||||
|
|
@ -1392,9 +1421,25 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
|||
// module[s] port. sig is the thing outside the module
|
||||
// that connects to the port.
|
||||
|
||||
NetNet*sig;
|
||||
NetNet*sig = 0;
|
||||
if (prts.empty() || (prts[0]->port_type() == NetNet::PINPUT)) {
|
||||
|
||||
// Special case: If the input port is an unpacked
|
||||
// array, then there should be no sub-ports and
|
||||
// the r-value expression is processed
|
||||
// differently.
|
||||
if (prts.size() >= 1 && prts[0]->pin_count()>1) {
|
||||
ivl_assert(*this, prts.size()==1);
|
||||
|
||||
PEIdent*rval_pident = dynamic_cast<PEIdent*> (pins[idx]);
|
||||
ivl_assert(*this, rval_pident);
|
||||
|
||||
NetNet*rval_net = rval_pident->elaborate_unpacked_net(des, scope);
|
||||
ivl_assert(*this, rval_net->pin_count() == prts[0]->pin_count());
|
||||
assign_unpacked_with_bufz(des, scope, this, prts[0], rval_net);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Input to module. elaborate the expression to
|
||||
the desired width. If this in an instance
|
||||
array, then let the net determine its own
|
||||
|
|
@ -1471,6 +1516,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
|||
|
||||
} else if (prts[0]->port_type() == NetNet::PINOUT) {
|
||||
|
||||
// For now, do not support unpacked array outputs.
|
||||
ivl_assert(*this, prts[0]->unpacked_dimensions()==0);
|
||||
|
||||
/* Inout to/from module. This is a more
|
||||
complicated case, where the expression must be
|
||||
an lnet, but also an r-value net.
|
||||
|
|
@ -1530,6 +1578,28 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
|||
/* Port type must be OUTPUT here. */
|
||||
ivl_assert(*this, prts[0]->port_type() == NetNet::POUTPUT);
|
||||
|
||||
// Special case: If the output port is an unpacked
|
||||
// array, then there should be no sub-ports and
|
||||
// the passed pexxpression is processed
|
||||
// differently. Note that we are calling it the
|
||||
// "r-value" expression, but since this is an
|
||||
// output port, we assign to it from the internal object.
|
||||
if (prts[0]->pin_count() > 1) {
|
||||
ivl_assert(*this, prts.size()==1);
|
||||
|
||||
PEIdent*rval_pident = dynamic_cast<PEIdent*>(pins[idx]);
|
||||
ivl_assert(*this, rval_pident);
|
||||
|
||||
NetNet*rval_net = rval_pident->elaborate_unpacked_net(des, scope);
|
||||
ivl_assert(*this, rval_net->pin_count() == prts[0]->pin_count());
|
||||
|
||||
assign_unpacked_with_bufz(des, scope, this, rval_net, prts[0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// At this point, arrays are handled.
|
||||
ivl_assert(*this, prts[0]->unpacked_dimensions()==0);
|
||||
|
||||
/* Output from module. Elaborate the port
|
||||
expression as the l-value of a continuous
|
||||
assignment, as the port will continuous assign
|
||||
|
|
@ -2221,6 +2291,14 @@ NetAssign_* PAssign_::elaborate_lval(Design*des, NetScope*scope) const
|
|||
NetAssign_*lv = new NetAssign_(tmp);
|
||||
return lv;
|
||||
}
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PAssign_::elaborate_lval: "
|
||||
<< "lval_ = " << *lval_ << endl;
|
||||
cerr << get_fileline() << ": PAssign_::elaborate_lval: "
|
||||
<< "lval_ expr type = " << typeid(*lval_).name() << endl;
|
||||
}
|
||||
|
||||
return lval_->elaborate_lval(des, scope, false, false);
|
||||
}
|
||||
|
||||
|
|
@ -2451,6 +2529,23 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
rv = elaborate_rval_(des, scope, use_lv_type);
|
||||
|
||||
} else if (const netuarray_t*utype = dynamic_cast<const netuarray_t*>(lv_net_type)) {
|
||||
ivl_assert(*this, lv->more==0);
|
||||
if (debug_elaborate) {
|
||||
if (lv->word())
|
||||
cerr << get_fileline() << ": PAssign::elaborate: "
|
||||
<< "lv->word() = " << *lv->word() << endl;
|
||||
else
|
||||
cerr << get_fileline() << ": PAssign::elaborate: "
|
||||
<< "lv->word() = <nil>" << endl;
|
||||
}
|
||||
ivl_type_t use_lv_type = lv_net_type;
|
||||
ivl_assert(*this, lv->word());
|
||||
use_lv_type = utype->element_type();
|
||||
|
||||
ivl_assert(*this, use_lv_type);
|
||||
rv = elaborate_rval_(des, scope, use_lv_type);
|
||||
|
||||
} else {
|
||||
/* Elaborate the r-value expression, then try to evaluate it. */
|
||||
rv = elaborate_rval_(des, scope, lv_net_type, lv->expr_type(), count_lval_width(lv));
|
||||
|
|
@ -3118,7 +3213,6 @@ NetProc* PChainConstructor::elaborate(Design*des, NetScope*scope) const
|
|||
NetBlock*tmp = new NetBlock(NetBlock::SEQU, 0);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetProc* PCondit::elaborate(Design*des, NetScope*scope) const
|
||||
|
|
@ -3345,6 +3439,17 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
|||
}
|
||||
assert(def);
|
||||
|
||||
/* In SystemVerilog a method calling another method in the
|
||||
* current class needs to be elaborated as a method with an
|
||||
* implicit this added. */
|
||||
if (gn_system_verilog() && (path_.size() == 1)) {
|
||||
const NetScope *c_scope = scope->get_class_scope();
|
||||
if (c_scope && (c_scope == task->get_class_scope())) {
|
||||
NetProc *tmp = elaborate_method_(des, scope, true);
|
||||
assert(tmp);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned parm_count = def->port_count();
|
||||
|
||||
|
|
@ -3359,7 +3464,45 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
|||
return elaborate_build_call_(des, scope, task, 0);
|
||||
}
|
||||
|
||||
NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope) const
|
||||
/*
|
||||
* This private method is called to elaborate built-in methods. The
|
||||
* method_name is the detected name of the built-in method, and the
|
||||
* sys_task_name is the internal system-task name to use.
|
||||
*/
|
||||
NetProc* PCallTask::elaborate_sys_task_method_(Design*des, NetScope*scope,
|
||||
NetNet*net,
|
||||
perm_string method_name,
|
||||
const char*sys_task_name) const
|
||||
{
|
||||
NetESignal*sig = new NetESignal(net);
|
||||
sig->set_line(*this);
|
||||
|
||||
/* If there is a single NULL argument then ignore it since it is
|
||||
* left over from the parser and is not needed by the method. */
|
||||
unsigned nparms = parms_.size();
|
||||
if ((nparms == 1) && (parms_[0] == 0)) nparms = 0;
|
||||
|
||||
vector<NetExpr*>argv (1 + nparms);
|
||||
argv[0] = sig;
|
||||
|
||||
for (unsigned idx = 0 ; idx < nparms ; idx += 1) {
|
||||
PExpr*ex = parms_[idx];
|
||||
if (ex != 0) {
|
||||
argv[idx+1] = elab_sys_task_arg(des, scope,
|
||||
method_name,
|
||||
idx, ex);
|
||||
} else {
|
||||
argv[idx+1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
NetSTask*sys = new NetSTask(sys_task_name, IVL_SFUNC_AS_TASK_IGNORE, argv);
|
||||
sys->set_line(*this);
|
||||
return sys;
|
||||
}
|
||||
|
||||
NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
|
||||
bool add_this_flag) const
|
||||
{
|
||||
pform_name_t use_path = path_;
|
||||
perm_string method_name = peek_tail_name(use_path);
|
||||
|
|
@ -3370,6 +3513,12 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope) const
|
|||
NetEvent *eve;
|
||||
const NetExpr *ex1, *ex2;
|
||||
|
||||
/* Add the implicit this reference when requested. */
|
||||
if (add_this_flag) {
|
||||
assert(use_path.empty());
|
||||
use_path.push_front(name_component_t(perm_string::literal("@")));
|
||||
}
|
||||
|
||||
// There is no signal to search for so this cannot be a method.
|
||||
if (use_path.empty()) return 0;
|
||||
|
||||
|
|
@ -3385,15 +3534,20 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope) const
|
|||
|
||||
// Is this a delete method for dynamic arrays?
|
||||
if (net->darray_type() && method_name=="delete") {
|
||||
NetESignal*sig = new NetESignal(net);
|
||||
return elaborate_sys_task_method_(des, scope, net,
|
||||
method_name,
|
||||
"$ivl_darray_method$delete");
|
||||
}
|
||||
|
||||
vector<NetExpr*> argv (1);
|
||||
argv[0] = sig;
|
||||
|
||||
NetSTask*sys = new NetSTask("$ivl_darray_method$delete",
|
||||
IVL_SFUNC_AS_TASK_IGNORE, argv);
|
||||
sys->set_line(*this);
|
||||
return sys;
|
||||
if (net->queue_type()) {
|
||||
if (method_name=="push_back")
|
||||
return elaborate_sys_task_method_(des, scope, net,
|
||||
method_name,
|
||||
"$ivl_queue_method$push_back");
|
||||
if (method_name=="push_front")
|
||||
return elaborate_sys_task_method_(des, scope, net,
|
||||
method_name,
|
||||
"$ivl_queue_method$push_front");
|
||||
}
|
||||
|
||||
if (const netclass_t*class_type = net->class_type()) {
|
||||
|
|
@ -4470,6 +4624,222 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const
|
|||
return dev;
|
||||
}
|
||||
|
||||
static void find_property_in_class(const LineInfo&loc, const NetScope*scope, perm_string name, const netclass_t*&found_in, int&property)
|
||||
{
|
||||
found_in = find_class_containing_scope(loc, scope);
|
||||
property = -1;
|
||||
|
||||
if (found_in==0) return;
|
||||
|
||||
property = found_in->property_idx_from_name(name);
|
||||
if (property < 0) {
|
||||
found_in = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The foreach statement can be written as a for statement like so:
|
||||
*
|
||||
* for (<idx> = $low(<array>) ; <idx> <= $high(<array>) ; <idx> += 1)
|
||||
* <statement_>
|
||||
*
|
||||
* The <idx> variable is already known to be in the containing named
|
||||
* block scope, which was created by the parser.
|
||||
*/
|
||||
NetProc* PForeach::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
// Locate the signal for the array variable
|
||||
pform_name_t array_name;
|
||||
array_name.push_back(name_component_t(array_var_));
|
||||
NetNet*array_sig = des->find_signal(scope, array_name);
|
||||
|
||||
// And if necessary, look for the class property that is
|
||||
// referenced.
|
||||
const netclass_t*class_scope = 0;
|
||||
int class_property = -1;
|
||||
if (array_sig == 0)
|
||||
find_property_in_class(*this, scope, array_var_, class_scope, class_property);
|
||||
|
||||
if (debug_elaborate && array_sig) {
|
||||
cerr << get_fileline() << ": PForeach::elaborate: "
|
||||
<< "Found array_sig in " << scope_path(array_sig->scope()) << "." << endl;
|
||||
}
|
||||
|
||||
if (debug_elaborate && class_scope) {
|
||||
cerr << get_fileline() << ": PForeach::elaborate: "
|
||||
<< "Found array_sig property (" << class_property
|
||||
<< ") in class " << class_scope->get_name()
|
||||
<< " as " << *class_scope->get_prop_type(class_property) << "." << endl;
|
||||
}
|
||||
|
||||
if (class_scope!=0 && class_property >= 0) {
|
||||
ivl_type_t ptype = class_scope->get_prop_type(class_property);
|
||||
const netsarray_t*atype = dynamic_cast<const netsarray_t*> (ptype);
|
||||
if (atype == 0) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "I can't handle the type of " << array_var_
|
||||
<< " as a foreach loop." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const std::vector<netrange_t>&dims = atype->static_dimensions();
|
||||
if (dims.size() < index_vars_.size()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "class " << class_scope->get_name()
|
||||
<< " property " << array_var_
|
||||
<< " has too few dimensions for foreach dimension list." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return elaborate_static_array_(des, scope, dims);
|
||||
}
|
||||
|
||||
if (array_sig == 0) {
|
||||
cerr << get_fileline() << ": error:"
|
||||
<< " Unable to find foreach array " << array_name
|
||||
<< " in scope " << scope_path(scope)
|
||||
<< "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ivl_assert(*this, array_sig);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PForeach::elaborate: "
|
||||
<< "Scan array " << array_sig->name()
|
||||
<< " of " << array_sig->data_type()
|
||||
<< " with " << array_sig->unpacked_dimensions() << " unpacked"
|
||||
<< " and " << array_sig->packed_dimensions()
|
||||
<< " packed dimensions." << endl;
|
||||
}
|
||||
|
||||
// Classic arrays are processed this way.
|
||||
if (array_sig->data_type()==IVL_VT_BOOL)
|
||||
return elaborate_static_array_(des, scope, array_sig->unpacked_dims());
|
||||
if (array_sig->data_type()==IVL_VT_LOGIC)
|
||||
return elaborate_static_array_(des, scope, array_sig->unpacked_dims());
|
||||
if (array_sig->unpacked_dimensions() >= index_vars_.size())
|
||||
return elaborate_static_array_(des, scope, array_sig->unpacked_dims());
|
||||
|
||||
|
||||
// At this point, we know that the array is dynamic so we
|
||||
// handle that slightly differently, using run-time tests.
|
||||
|
||||
if (index_vars_.size() != 1) {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "Multi-index foreach loops not supported." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
// Get the signal for the index variable.
|
||||
pform_name_t index_name;
|
||||
index_name.push_back(name_component_t(index_vars_[0]));
|
||||
NetNet*idx_sig = des->find_signal(scope, index_name);
|
||||
ivl_assert(*this, idx_sig);
|
||||
|
||||
NetESignal*array_exp = new NetESignal(array_sig);
|
||||
array_exp->set_line(*this);
|
||||
|
||||
NetESignal*idx_exp = new NetESignal(idx_sig);
|
||||
idx_exp->set_line(*this);
|
||||
|
||||
// Make an initialization expression for the index.
|
||||
NetESFunc*init_expr = new NetESFunc("$low", IVL_VT_BOOL, 32, 1);
|
||||
init_expr->set_line(*this);
|
||||
init_expr->parm(0, array_exp);
|
||||
|
||||
// Make a condition expression: idx <= $high(array)
|
||||
NetESFunc*high_exp = new NetESFunc("$high", IVL_VT_BOOL, 32, 1);
|
||||
high_exp->set_line(*this);
|
||||
high_exp->parm(0, array_exp);
|
||||
|
||||
NetEBComp*cond_expr = new NetEBComp('L', idx_exp, high_exp);
|
||||
cond_expr->set_line(*this);
|
||||
|
||||
/* Elaborate the statement that is contained in the foreach
|
||||
loop. */
|
||||
NetProc*sub = statement_->elaborate(des, scope);
|
||||
|
||||
/* Make a step statement: idx += 1 */
|
||||
NetAssign_*idx_lv = new NetAssign_(idx_sig);
|
||||
NetEConst*step_val = make_const_val(1);
|
||||
NetAssign*step = new NetAssign(idx_lv, '+', step_val);
|
||||
step->set_line(*this);
|
||||
|
||||
NetForLoop*stmt = new NetForLoop(idx_sig, init_expr, cond_expr, sub, step);
|
||||
stmt->set_line(*this);
|
||||
stmt->wrap_up();
|
||||
|
||||
return stmt;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a variant of the PForeach::elaborate() method that handles
|
||||
* the case that the array has static dimensions. We can use constants
|
||||
* and possibly do some optimizations.
|
||||
*/
|
||||
NetProc* PForeach::elaborate_static_array_(Design*des, NetScope*scope,
|
||||
const vector<netrange_t>&dims) const
|
||||
{
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PForeach::elaborate_static_array_: "
|
||||
<< "Handle as array with static dimensions." << endl;
|
||||
}
|
||||
|
||||
ivl_assert(*this, index_vars_.size() > 0);
|
||||
ivl_assert(*this, dims.size() == index_vars_.size());
|
||||
|
||||
NetProc*sub = statement_->elaborate(des, scope);
|
||||
NetForLoop*stmt = 0;
|
||||
|
||||
for (int idx_idx = index_vars_.size()-1 ; idx_idx >= 0 ; idx_idx -= 1) {
|
||||
const netrange_t&idx_range = dims[idx_idx];
|
||||
|
||||
// Get the $high and $low constant values for this slice
|
||||
// of the array.
|
||||
NetEConst*hig_expr = make_const_val_s(idx_range.get_msb());
|
||||
NetEConst*low_expr = make_const_val_s(idx_range.get_lsb());
|
||||
if (idx_range.get_msb() < idx_range.get_lsb()) {
|
||||
NetEConst*tmp = hig_expr;
|
||||
hig_expr = low_expr;
|
||||
low_expr = tmp;
|
||||
}
|
||||
|
||||
hig_expr->set_line(*this);
|
||||
low_expr->set_line(*this);
|
||||
|
||||
pform_name_t idx_name;
|
||||
idx_name.push_back(name_component_t(index_vars_[idx_idx]));
|
||||
NetNet*idx_sig = des->find_signal(scope, idx_name);
|
||||
ivl_assert(*this, idx_sig);
|
||||
|
||||
// Make the condition expression <idx> <= $high(slice)
|
||||
NetESignal*idx_expr = new NetESignal(idx_sig);
|
||||
idx_expr->set_line(*this);
|
||||
|
||||
NetEBComp*cond_expr = new NetEBComp('L', idx_expr, hig_expr);
|
||||
cond_expr->set_line(*this);
|
||||
|
||||
// Make the step statement: <idx> += 1
|
||||
NetAssign_*idx_lv = new NetAssign_(idx_sig);
|
||||
NetEConst*step_val = make_const_val_s(1);
|
||||
NetAssign*step = new NetAssign(idx_lv, '+', step_val);
|
||||
step->set_line(*this);
|
||||
|
||||
stmt = new NetForLoop(idx_sig, low_expr, cond_expr, sub, step);
|
||||
stmt->set_line(*this);
|
||||
stmt->wrap_up();
|
||||
|
||||
sub = stmt;
|
||||
}
|
||||
|
||||
return stmt? stmt : sub;
|
||||
}
|
||||
|
||||
/*
|
||||
* elaborate the for loop as the equivalent while loop. This eases the
|
||||
* task for the target code generator. The structure is:
|
||||
|
|
@ -4484,15 +4854,12 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const
|
|||
*/
|
||||
NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*etmp;
|
||||
NetExpr*initial_expr;
|
||||
assert(scope);
|
||||
|
||||
const PEIdent*id1 = dynamic_cast<const PEIdent*>(name1_);
|
||||
assert(id1);
|
||||
|
||||
NetBlock*top = new NetBlock(NetBlock::SEQU, 0);
|
||||
top->set_line(*this);
|
||||
|
||||
/* make the expression, and later the initial assignment to
|
||||
the condition variable. The statement in the for loop is
|
||||
very specifically an assignment. */
|
||||
|
|
@ -4504,34 +4871,23 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
|||
return 0;
|
||||
}
|
||||
assert(sig);
|
||||
NetAssign_*lv = new NetAssign_(sig);
|
||||
|
||||
/* Make the r-value of the initial assignment, and size it
|
||||
properly. Then use it to build the assignment statement. */
|
||||
etmp = elaborate_rval_expr(des, scope, sig->net_type(),
|
||||
lv->expr_type(), lv->lwidth(),
|
||||
expr1_);
|
||||
initial_expr = elaborate_rval_expr(des, scope, sig->net_type(),
|
||||
sig->data_type(), sig->vector_width(),
|
||||
expr1_);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: FOR initial assign: "
|
||||
<< sig->name() << " = " << *etmp << endl;
|
||||
<< sig->name() << " = " << *initial_expr << endl;
|
||||
}
|
||||
|
||||
NetAssign*init = new NetAssign(lv, etmp);
|
||||
init->set_line(*this);
|
||||
|
||||
top->append(init);
|
||||
|
||||
NetBlock*body = new NetBlock(NetBlock::SEQU, 0);
|
||||
body->set_line(*this);
|
||||
|
||||
/* Elaborate the statement that is contained in the for
|
||||
loop. If there is an error, this will return 0 and I should
|
||||
skip the append. No need to worry, the error has been
|
||||
reported so it's OK that the netlist is bogus. */
|
||||
NetProc*tmp = statement_->elaborate(des, scope);
|
||||
if (tmp)
|
||||
body->append(tmp);
|
||||
NetProc*sub = statement_->elaborate(des, scope);
|
||||
|
||||
|
||||
/* Now elaborate the for_step statement. I really should do
|
||||
|
|
@ -4539,20 +4895,19 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
|||
really does step the variable. */
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Elaborate for_step statement "
|
||||
<< sig->name() << " = " << *etmp << endl;
|
||||
<< sig->name() << " = " << *initial_expr << endl;
|
||||
}
|
||||
|
||||
NetProc*step = step_->elaborate(des, scope);
|
||||
|
||||
body->append(step);
|
||||
|
||||
|
||||
/* Elaborate the condition expression. Try to evaluate it too,
|
||||
in case it is a constant. This is an interesting case
|
||||
worthy of a warning. */
|
||||
NetExpr*ce = elab_and_eval(des, scope, cond_, -1);
|
||||
if (ce == 0) {
|
||||
delete top;
|
||||
delete sub;
|
||||
delete step;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -4564,10 +4919,10 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
/* All done, build up the loop. */
|
||||
|
||||
NetWhile*loop = new NetWhile(ce, body);
|
||||
NetForLoop*loop = new NetForLoop(sig, initial_expr, ce, sub, step);
|
||||
loop->set_line(*this);
|
||||
top->append(loop);
|
||||
return top;
|
||||
loop->wrap_up();
|
||||
return loop;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -5199,6 +5554,9 @@ bool PPackage::elaborate(Design*des, NetScope*scope) const
|
|||
// Elaborate task methods.
|
||||
elaborate_tasks(des, scope, tasks);
|
||||
|
||||
// Elaborate class definitions.
|
||||
elaborate_classes(des, scope, classes);
|
||||
|
||||
return result_flag;
|
||||
}
|
||||
|
||||
|
|
@ -5626,6 +5984,28 @@ bool Design::check_proc_delay() const
|
|||
return result_flag;
|
||||
}
|
||||
|
||||
void Design::root_elaborate(void)
|
||||
{
|
||||
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
|
||||
; cur != classes_.end() ; ++ cur) {
|
||||
netclass_t*cur_class = cur->second;
|
||||
PClass*cur_pclass = class_to_pclass_[cur_class];
|
||||
cur_class->elaborate(this, cur_pclass);
|
||||
}
|
||||
|
||||
for (map<NetScope*,PTaskFunc*>::iterator cur = root_tasks_.begin()
|
||||
; cur != root_tasks_.end() ; ++ cur) {
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << cur->second->get_fileline() << ": Design::root_elaborate: "
|
||||
<< "Elaborate for root task/func " << scope_path(cur->first) << endl;
|
||||
}
|
||||
|
||||
cur->second->elaborate(this, cur->first);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is the root of all elaboration. The input is the list
|
||||
* of root module names. The function locates the Module definitions
|
||||
|
|
@ -5657,12 +6037,19 @@ Design* elaborate(list<perm_string>roots)
|
|||
// Elaborate enum sets in $root scope.
|
||||
elaborate_rootscope_enumerations(des);
|
||||
|
||||
// Elaborate tasks and functions in $root scope.
|
||||
elaborate_rootscope_tasks(des);
|
||||
|
||||
// Elaborate classes in $root scope.
|
||||
elaborate_rootscope_classes(des);
|
||||
|
||||
// Elaborate the packages. Package elaboration is simpler
|
||||
// because there are fewer sub-scopes involved.
|
||||
i = 0;
|
||||
for (map<perm_string,PPackage*>::iterator pac = pform_packages.begin()
|
||||
; pac != pform_packages.end() ; ++ pac) {
|
||||
|
||||
ivl_assert(*pac->second, pac->first == pac->second->pscope_name());
|
||||
NetScope*scope = des->make_package_scope(pac->first);
|
||||
scope->set_line(pac->second);
|
||||
|
||||
|
|
@ -5754,6 +6141,11 @@ Design* elaborate(list<perm_string>roots)
|
|||
}
|
||||
}
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << "<toplevel>: elaborate: "
|
||||
<< "elaboration work list done. Start processing residual defparams." << endl;
|
||||
}
|
||||
|
||||
// Look for residual defparams (that point to a non-existent
|
||||
// scope) and clean them out.
|
||||
des->residual_defparams();
|
||||
|
|
@ -5763,6 +6155,11 @@ Design* elaborate(list<perm_string>roots)
|
|||
if (des->errors > 0)
|
||||
return des;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << "<toplevel>: elaborate: "
|
||||
<< "Start calling Package elaborate_sig methods." << endl;
|
||||
}
|
||||
|
||||
// With the parameters evaluated down to constants, we have
|
||||
// what we need to elaborate signals and memories. This pass
|
||||
// creates all the NetNet and NetMemory objects for declared
|
||||
|
|
@ -5781,6 +6178,18 @@ Design* elaborate(list<perm_string>roots)
|
|||
}
|
||||
}
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << "<toplevel>: elaborate: "
|
||||
<< "Start calling $root elaborate_sig methods." << endl;
|
||||
}
|
||||
|
||||
des->root_elaborate_sig();
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << "<toplevel>: elaborate: "
|
||||
<< "Start calling root module elaborate_sig methods." << endl;
|
||||
}
|
||||
|
||||
for (i = 0; i < root_elems.size(); i++) {
|
||||
Module *rmod = root_elems[i].mod;
|
||||
NetScope *scope = root_elems[i].scope;
|
||||
|
|
@ -5812,7 +6221,9 @@ Design* elaborate(list<perm_string>roots)
|
|||
// stuff to the design that should be cleaned later.
|
||||
NetNet *netnet = mport[pin]->elaborate_subport(des, scope);
|
||||
if (netnet != 0) {
|
||||
// Elaboration may actually fail with erroneous input source
|
||||
// Elaboration may actually fail with
|
||||
// erroneous input source
|
||||
ivl_assert(*mport[pin], netnet->pin_count()==1);
|
||||
prt_vector_width += netnet->vector_width();
|
||||
ptype = PortType::merged(netnet->port_type(), ptype);
|
||||
}
|
||||
|
|
@ -5835,6 +6246,8 @@ Design* elaborate(list<perm_string>roots)
|
|||
rc &= pkg->elaborate(des, scope);
|
||||
}
|
||||
|
||||
des->root_elaborate();
|
||||
|
||||
for (i = 0; i < root_elems.size(); i++) {
|
||||
Module *rmod = root_elems[i].mod;
|
||||
NetScope *scope = root_elems[i].scope;
|
||||
|
|
|
|||
45
emit.cc
45
emit.cc
|
|
@ -167,6 +167,11 @@ bool NetSignExtend::emit_node(struct target_t*tgt) const
|
|||
return tgt->sign_extend(this);
|
||||
}
|
||||
|
||||
bool NetSubstitute::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->substitute(this);
|
||||
}
|
||||
|
||||
bool NetUReduce::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->ureduce(this);
|
||||
|
|
@ -283,6 +288,11 @@ bool NetForever::emit_proc(struct target_t*tgt) const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool NetForLoop::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->proc_block(as_block_);
|
||||
}
|
||||
|
||||
bool NetFree::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_free(this);
|
||||
|
|
@ -399,14 +409,13 @@ void NetRepeat::emit_recurse(struct target_t*tgt) const
|
|||
void netclass_t::emit_scope(struct target_t*tgt) const
|
||||
{
|
||||
class_scope_->emit_scope(tgt);
|
||||
class_scope_->emit_defs(tgt);
|
||||
}
|
||||
|
||||
void NetScope::emit_scope(struct target_t*tgt) const
|
||||
{
|
||||
if (debug_emit) {
|
||||
cerr << "NetScope::emit_scope: "
|
||||
<< "Emit scope basename=" << basename() << endl;
|
||||
<< "Emit scope " << scope_path(this) << endl;
|
||||
}
|
||||
|
||||
tgt->scope(this);
|
||||
|
|
@ -451,12 +460,20 @@ bool NetScope::emit_defs(struct target_t*tgt) const
|
|||
{
|
||||
bool flag = true;
|
||||
|
||||
if (debug_emit) {
|
||||
cerr << "NetScope::emit_defs: "
|
||||
<< "Emit definitions for " << scope_path(this) << endl;
|
||||
}
|
||||
|
||||
switch (type_) {
|
||||
case PACKAGE:
|
||||
case MODULE:
|
||||
for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
|
||||
; cur != children_.end() ; ++ cur )
|
||||
flag &= cur->second->emit_defs(tgt);
|
||||
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
|
||||
; cur != classes_.end() ; ++ cur)
|
||||
flag &= cur->second->emit_defs(tgt);
|
||||
break;
|
||||
|
||||
case FUNC:
|
||||
|
|
@ -475,6 +492,11 @@ bool NetScope::emit_defs(struct target_t*tgt) const
|
|||
return flag;
|
||||
}
|
||||
|
||||
bool netclass_t::emit_defs(struct target_t*tgt) const
|
||||
{
|
||||
return class_scope_->emit_defs(tgt);
|
||||
}
|
||||
|
||||
int Design::emit(struct target_t*tgt) const
|
||||
{
|
||||
int rc = 0;
|
||||
|
|
@ -482,12 +504,26 @@ int Design::emit(struct target_t*tgt) const
|
|||
if (tgt->start_design(this) == false)
|
||||
return -2;
|
||||
|
||||
for (map<NetScope*,PTaskFunc*>::const_iterator scope = root_tasks_.begin()
|
||||
; scope != root_tasks_.end() ; ++ scope) {
|
||||
scope->first->emit_scope(tgt);
|
||||
scope->first->emit_defs(tgt);
|
||||
}
|
||||
|
||||
// enumerate package scopes
|
||||
for (map<perm_string,NetScope*>::const_iterator scope = packages_.begin()
|
||||
; scope != packages_.end() ; ++ scope) {
|
||||
scope->second->emit_scope(tgt);
|
||||
}
|
||||
|
||||
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
|
||||
; cur != classes_.end() ; ++cur) {
|
||||
const NetScope*use_scope = cur->second->class_scope();
|
||||
cur->second->emit_scope(tgt);
|
||||
tgt->class_type(use_scope, cur->second);
|
||||
cur->second->emit_defs(tgt);
|
||||
}
|
||||
|
||||
// enumerate root scopes
|
||||
for (list<NetScope*>::const_iterator scope = root_scopes_.begin()
|
||||
; scope != root_scopes_.end(); ++ scope ) {
|
||||
|
|
@ -600,6 +636,11 @@ void NetEEvent::expr_scan(struct expr_scan_t*tgt) const
|
|||
tgt->expr_event(this);
|
||||
}
|
||||
|
||||
void NetELast::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_last(this);
|
||||
}
|
||||
|
||||
void NetENetenum::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_netenum(this);
|
||||
|
|
|
|||
8
eval.cc
8
eval.cc
|
|
@ -44,6 +44,14 @@ verinum* PEBinary::eval_const(Design*des, NetScope*scope) const
|
|||
verinum*res;
|
||||
|
||||
switch (op_) {
|
||||
case 'p': {
|
||||
if (l->is_defined() && r->is_defined()) {
|
||||
res = new verinum(pow(*l, *r));
|
||||
} else {
|
||||
res = new verinum(verinum::Vx, l->len());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '+': {
|
||||
if (l->is_defined() && r->is_defined()) {
|
||||
res = new verinum(*l + *r);
|
||||
|
|
|
|||
|
|
@ -1384,6 +1384,7 @@ NetExpr*NetETernary::blended_arguments_(const NetExpr*te, const NetExpr*fe) cons
|
|||
if (tv == fv) val.set(idx, tv);
|
||||
else val.set(idx, verinum::Vx);
|
||||
}
|
||||
val.has_sign(has_sign());
|
||||
|
||||
if (debug_eval_tree) {
|
||||
cerr << get_fileline() << ": debug: Evaluate ternary with "
|
||||
|
|
@ -2015,6 +2016,7 @@ static bool get_array_info(const NetExpr*arg, long dim,
|
|||
/* A string or dynamic array must be handled by the run time. */
|
||||
switch (sig->data_type()) {
|
||||
case IVL_VT_DARRAY:
|
||||
case IVL_VT_QUEUE:
|
||||
case IVL_VT_STRING:
|
||||
defer = true;
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
|||
|
||||
if (op_ == 'E' || op_ == 'N') {
|
||||
NetCaseCmp*gate = new NetCaseCmp(scope, scope->local_symbol(),
|
||||
width, op_=='E'?true:false);
|
||||
width, op_=='E'?NetCaseCmp::EEQ:NetCaseCmp::NEQ);
|
||||
gate->set_line(*this);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
connect(gate->pin(1), lsig->pin(0));
|
||||
|
|
@ -1271,6 +1271,22 @@ NetNet* NetETernary::synthesize(Design *des, NetScope*scope, NetExpr*root)
|
|||
*/
|
||||
NetNet* NetESignal::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||
{
|
||||
// If this is a synthesis with a specific value for the
|
||||
// signal, then replace it (here) with a constant value.
|
||||
if (net_->scope()==scope && net_->name()==scope->genvar_tmp) {
|
||||
netvector_t*tmp_vec = new netvector_t(net_->data_type(),
|
||||
net_->vector_width()-1, 0);
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, tmp_vec);
|
||||
verinum tmp_val ((uint64_t)scope->genvar_tmp_val, net_->vector_width());
|
||||
NetConst*tmp_const = new NetConst(scope, scope->local_symbol(), tmp_val);
|
||||
tmp_const->set_line(*this);
|
||||
des->add_node(tmp_const);
|
||||
|
||||
connect(tmp->pin(0), tmp_const->pin(0));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
if (word_ == 0)
|
||||
return net_;
|
||||
|
||||
|
|
@ -1440,6 +1456,12 @@ NetNet* NetEUFunc::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
|||
osig->local_flag(true);
|
||||
connect(net->pin(0), osig->pin(0));
|
||||
|
||||
if (debug_synth2) {
|
||||
cerr << get_fileline() << ": NetEUFunc::synthesize: "
|
||||
<< "result_sig_->vector_width()=" << result_sig_->vector_width()
|
||||
<< ", osig->vector_width()=" << osig->vector_width() << endl;
|
||||
}
|
||||
|
||||
/* Connect the pins to the arguments. */
|
||||
NetFuncDef*def = func_->func_def();
|
||||
for (unsigned idx = 0; idx < eparms.size(); idx += 1) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __functor_H
|
||||
#define __functor_H
|
||||
#ifndef IVL_functor_H
|
||||
#define IVL_functor_H
|
||||
/*
|
||||
* Copyright (c) 1999-2008,2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -105,4 +105,4 @@ struct proc_match_t {
|
|||
virtual int block(class NetBlock*);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_functor_H */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __ivl_alloc_H
|
||||
#define __ivl_alloc_H
|
||||
#ifndef IVL_ivl_alloc_H
|
||||
#define IVL_ivl_alloc_H
|
||||
/*
|
||||
* Copyright (C) 2010 Cary R. (cygcary@yahoo.com)
|
||||
* Copyright (C) 2010-2014 Cary R. (cygcary@yahoo.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -83,4 +83,4 @@
|
|||
__ivl_rtn; \
|
||||
})
|
||||
|
||||
#endif
|
||||
#endif /* IVL_ivl_alloc_H */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#ifndef IVL_ivl_assert_H
|
||||
#define IVL_ivl_assert_H
|
||||
/*
|
||||
* Copyright (c) 2007-2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2007-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -17,9 +19,6 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ivl_assert_h
|
||||
#define __ivl_assert_h
|
||||
|
||||
# include <cstdlib>
|
||||
|
||||
#define ivl_assert(tok, expression) \
|
||||
|
|
@ -32,4 +31,4 @@
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
#endif /* IVL_ivl_assert_H */
|
||||
|
|
|
|||
38
ivl_target.h
38
ivl_target.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __ivl_target_H
|
||||
#define __ivl_target_H
|
||||
#ifndef IVL_ivl_target_H
|
||||
#define IVL_ivl_target_H
|
||||
/*
|
||||
* Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -300,6 +300,8 @@ typedef enum ivl_lpm_type_e {
|
|||
IVL_LPM_CONCAT = 16,
|
||||
IVL_LPM_CONCATZ = 36, /* Transparent concat */
|
||||
IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */
|
||||
IVL_LPM_CMP_EQX= 37, /* Windcard EQ (==?) */
|
||||
IVL_LPM_CMP_EQZ= 38, /* casez EQ */
|
||||
IVL_LPM_CMP_EQ = 10,
|
||||
IVL_LPM_CMP_GE = 1,
|
||||
IVL_LPM_CMP_GT = 2,
|
||||
|
|
@ -326,6 +328,7 @@ typedef enum ivl_lpm_type_e {
|
|||
IVL_LPM_SHIFTR = 7,
|
||||
IVL_LPM_SIGN_EXT=27,
|
||||
IVL_LPM_SUB = 8,
|
||||
IVL_LPM_SUBSTITUTE=39,
|
||||
/* IVL_LPM_RAM = 9, / obsolete */
|
||||
IVL_LPM_UFUNC = 14
|
||||
} ivl_lpm_type_t;
|
||||
|
|
@ -437,6 +440,7 @@ typedef enum ivl_variable_type_e {
|
|||
IVL_VT_STRING = 5,
|
||||
IVL_VT_DARRAY = 6, /* Array (esp. dynamic array) */
|
||||
IVL_VT_CLASS = 7, /* SystemVerilog class instances */
|
||||
IVL_VT_QUEUE = 8, /* SystemVerilog queue instances */
|
||||
IVL_VT_VECTOR = IVL_VT_LOGIC /* For compatibility */
|
||||
} ivl_variable_type_t;
|
||||
|
||||
|
|
@ -828,6 +832,10 @@ extern unsigned ivl_event_lineno(ivl_event_t net);
|
|||
* table. That number can be passed to ivl_type_prop_*() functions to
|
||||
* get details about the property.
|
||||
*
|
||||
* If the property is an array, then the ivl_expr_oper1() function
|
||||
* returns the canonical expression for accessing the element of the
|
||||
* property.
|
||||
*
|
||||
* - IVL_EX_NEW
|
||||
* This expression takes one or two operands. The first operand,
|
||||
* returned by ivl_expr_oper1() is the number of elements to create
|
||||
|
|
@ -1265,7 +1273,7 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
|
|||
* width of the part. The ivl_lpm_q is the part end, and the
|
||||
* ivl_lpm_data(0) is the non-part end.
|
||||
*
|
||||
* - Comparisons (IVL_LPM_CMP_GT/GE/EQ/NE/EEQ/NEE)
|
||||
* - Comparisons (IVL_LPM_CMP_GT/GE/EQ/NE/EEQ/NEE/EQX/EQZ)
|
||||
* These devices have two inputs, available by the ivl_lpm_data()
|
||||
* function, and one output available by the ivl_lpm_q function. The
|
||||
* output width is always 1, but the ivl_lpm_width() returns the width
|
||||
|
|
@ -1277,6 +1285,11 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
|
|||
* magnitude compare, the signedness does matter. In any case, the
|
||||
* result of the compare is always unsigned.
|
||||
*
|
||||
* The EQX and EQZ nodes are windcard compares, where xz bits (EQX) or
|
||||
* z bits (EQZ) in the data(1) operand are treated as windcards. no
|
||||
* bits in the data(0) operand are wild. This matches the
|
||||
* SystemVerilog convention for the ==? operator.
|
||||
*
|
||||
* - Mux Device (IVL_LPM_MUX)
|
||||
* The MUX device has a q output, a select input, and a number of data
|
||||
* inputs. The ivl_lpm_q output and the ivl_lpm_data inputs all have
|
||||
|
|
@ -1402,7 +1415,7 @@ extern ivl_nexus_t ivl_lpm_sync_set(ivl_lpm_t net);
|
|||
extern ivl_expr_t ivl_lpm_sset_value(ivl_lpm_t net);
|
||||
/* IVL_LPM_ARRAY */
|
||||
extern ivl_signal_t ivl_lpm_array(ivl_lpm_t net);
|
||||
/* IVL_LPM_PART */
|
||||
/* IVL_LPM_PART IVL_LPM_SUBSTITUTE */
|
||||
extern unsigned ivl_lpm_base(ivl_lpm_t net);
|
||||
/* IVL_LPM_FF */
|
||||
extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
|
||||
|
|
@ -1412,12 +1425,14 @@ extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
|
|||
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
|
||||
/* IVL_LPM_ADD IVL_LPM_CONCAT IVL_LPM_FF IVL_LPM_PART IVL_LPM_MULT
|
||||
IVL_LPM_MUX IVL_LPM_POW IVL_LPM_SHIFTL IVL_LPM_SHIFTR IVL_LPM_SUB
|
||||
IVL_LPM_UFUNC */
|
||||
IVL_LPM_UFUNC IVL_LPM_SUBSTITUTE */
|
||||
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_POW IVL_LPM_SUB */
|
||||
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_POW IVL_LPM_SUB IVL_LPM_CMP_EQ
|
||||
IVL_LPM_CMP_EEQ IVL_LPM_CMP_EQX IVL_LPM_CMP_EQZ IVL_LPM_CMP_NEE */
|
||||
extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART IVL_LPM_POW
|
||||
IVL_LPM_SUB IVL_LPM_UFUNC */
|
||||
IVL_LPM_SUB IVL_LPM_UFUNC IVL_LPM_CMP_EEQ IVL_LPM_CMP_EQX
|
||||
IVL_LPM_CMP_EQZ IVL_LPM_CMP_NEE IVL_LPM_SUBSTITUTE */
|
||||
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net);
|
||||
extern ivl_drive_t ivl_lpm_drive0(ivl_lpm_t net);
|
||||
extern ivl_drive_t ivl_lpm_drive1(ivl_lpm_t net);
|
||||
|
|
@ -1488,6 +1503,11 @@ extern const char*ivl_lpm_string(ivl_lpm_t net);
|
|||
* then the ivl_lval_idx expression must *not* be present.
|
||||
*
|
||||
* For array words, the ivl_lval_width is the width of the word.
|
||||
*
|
||||
* - Arrayed properties
|
||||
* If the l-value is a class property, then the ivl_lval_idx function
|
||||
* will return an expression if the property is in fact arrayed. The
|
||||
* expression is the canonical index for elements in the property.
|
||||
*/
|
||||
|
||||
extern unsigned ivl_lval_width(ivl_lval_t net);
|
||||
|
|
@ -2322,4 +2342,4 @@ typedef const char* (*target_query_f) (const char*key);
|
|||
|
||||
_END_DECL
|
||||
|
||||
#endif
|
||||
#endif /* IVL_ivl_target_H */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __ivl_target_priv_H
|
||||
#define __ivl_target_priv_H
|
||||
#ifndef IVL_ivl_target_priv_H
|
||||
#define IVL_ivl_target_priv_H
|
||||
/*
|
||||
* Copyright (c) 2008 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2008-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -52,6 +52,7 @@ struct ivl_design_s {
|
|||
|
||||
// Keep arrays of root scopes.
|
||||
std::map<const NetScope*,ivl_scope_t> classes;
|
||||
std::map<const NetScope*,ivl_scope_t> root_tasks;
|
||||
std::vector<ivl_scope_t> packages;
|
||||
std::vector<ivl_scope_t> roots;
|
||||
|
||||
|
|
@ -90,4 +91,4 @@ struct ivl_island_s {
|
|||
|
||||
extern std::ostream& operator << (std::ostream&o, ivl_drive_t str);
|
||||
|
||||
#endif
|
||||
#endif /* IVL_ivl_target_priv_H */
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
|
|||
endif
|
||||
|
||||
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
|
||||
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
O = main.o lexor.o
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __globals_H
|
||||
#define __globals_H
|
||||
#ifndef IVL_globals_H
|
||||
#define IVL_globals_H
|
||||
/*
|
||||
* Copyright (c) 1999-2009 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -22,11 +22,11 @@
|
|||
# include <stdio.h>
|
||||
|
||||
extern void reset_lexor(FILE*out, char*paths[]);
|
||||
extern void destroy_lexor();
|
||||
extern void destroy_lexor(void);
|
||||
extern void load_precompiled_defines(FILE*src);
|
||||
extern void define_macro(const char*name, const char*value, int keyword,
|
||||
int argc);
|
||||
extern void free_macros();
|
||||
extern void free_macros(void);
|
||||
extern void dump_precompiled_defines(FILE*out);
|
||||
|
||||
/* These variables contain the include directories to be searched when
|
||||
|
|
@ -54,6 +54,6 @@ extern char dep_mode;
|
|||
extern int verbose_flag;
|
||||
|
||||
/* This is the entry to the lexer. */
|
||||
extern int yylex();
|
||||
extern int yylex(void);
|
||||
|
||||
#endif
|
||||
#endif /* IVL_globals_H */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
%option prefix="yy"
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1999-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -30,29 +30,29 @@
|
|||
# include "globals.h"
|
||||
# include "ivl_alloc.h"
|
||||
|
||||
static void output_init();
|
||||
static void output_init(void);
|
||||
#define YY_USER_INIT output_init()
|
||||
|
||||
static void def_start();
|
||||
static void def_add_arg();
|
||||
static void def_finish();
|
||||
static void def_undefine();
|
||||
static void do_define();
|
||||
static int def_is_done();
|
||||
static void def_start(void);
|
||||
static void def_add_arg(void);
|
||||
static void def_finish(void);
|
||||
static void def_undefine(void);
|
||||
static void do_define(void);
|
||||
static int def_is_done(void);
|
||||
static int is_defined(const char*name);
|
||||
|
||||
static int macro_needs_args(const char*name);
|
||||
static void macro_start_args();
|
||||
static void macro_start_args(void);
|
||||
static void macro_add_to_arg(int is_whitespace);
|
||||
static void macro_finish_arg();
|
||||
static void macro_finish_arg(void);
|
||||
static void do_expand(int use_args);
|
||||
static const char* do_magic(const char*name);
|
||||
static const char* macro_name();
|
||||
static const char* macro_name(void);
|
||||
|
||||
static void include_filename();
|
||||
static void do_include();
|
||||
static void include_filename(void);
|
||||
static void do_include(void);
|
||||
|
||||
static int load_next_input();
|
||||
static int load_next_input(void);
|
||||
|
||||
struct include_stack_t
|
||||
{
|
||||
|
|
@ -804,7 +804,7 @@ static /* inline */ char* def_argv(int arg)
|
|||
return def_buf + def_argo[arg];
|
||||
}
|
||||
|
||||
static void check_for_max_args()
|
||||
static void check_for_max_args(void)
|
||||
{
|
||||
if (def_argc == MAX_DEF_ARG)
|
||||
{
|
||||
|
|
@ -825,14 +825,14 @@ static void def_buf_grow_to_fit(int length)
|
|||
}
|
||||
}
|
||||
|
||||
static void def_start()
|
||||
static void def_start(void)
|
||||
{
|
||||
def_buf_free = def_buf_size;
|
||||
def_argc = 0;
|
||||
def_add_arg();
|
||||
}
|
||||
|
||||
static void def_add_arg()
|
||||
static void def_add_arg(void)
|
||||
{
|
||||
int length = yyleng;
|
||||
|
||||
|
|
@ -852,7 +852,7 @@ static void def_add_arg()
|
|||
|
||||
char*arg = yytext;
|
||||
char*val;
|
||||
int val_length;
|
||||
int val_length = 0;
|
||||
|
||||
/* Break into ARG = value. This happens if the source specifies
|
||||
a default value for the formal argument. In that case, the
|
||||
|
|
@ -979,7 +979,7 @@ static void free_macro(struct define_t* def)
|
|||
free(def);
|
||||
}
|
||||
|
||||
void free_macros()
|
||||
void free_macros(void)
|
||||
{
|
||||
free_macro(def_table);
|
||||
}
|
||||
|
|
@ -1052,7 +1052,7 @@ static char *find_arg(char*ptr, char*head, char*arg)
|
|||
* continuation, then return 1 and this function may be called again
|
||||
* to collect another line of the definition.
|
||||
*/
|
||||
static void do_define()
|
||||
static void do_define(void)
|
||||
{
|
||||
char* cp;
|
||||
char* head;
|
||||
|
|
@ -1202,7 +1202,7 @@ static void do_define()
|
|||
* Return true if the definition text is done. This is the opposite of
|
||||
* the define_continue_flag.
|
||||
*/
|
||||
static int def_is_done()
|
||||
static int def_is_done(void)
|
||||
{
|
||||
return !define_continue_flag;
|
||||
}
|
||||
|
|
@ -1212,7 +1212,7 @@ static int def_is_done()
|
|||
* assigned value to the parsed name. If there is no value, then
|
||||
* assign the string "" (empty string.)
|
||||
*/
|
||||
static void def_finish()
|
||||
static void def_finish(void)
|
||||
{
|
||||
define_continue_flag = 0;
|
||||
|
||||
|
|
@ -1234,7 +1234,7 @@ static void def_finish()
|
|||
def_argc = 0;
|
||||
}
|
||||
|
||||
static void def_undefine()
|
||||
static void def_undefine(void)
|
||||
{
|
||||
struct define_t* cur;
|
||||
struct define_t* tail;
|
||||
|
|
@ -1360,7 +1360,7 @@ static int macro_needs_args(const char*text)
|
|||
}
|
||||
}
|
||||
|
||||
static const char* macro_name()
|
||||
static const char* macro_name(void)
|
||||
{
|
||||
return cur_macro ? cur_macro->name : "";
|
||||
}
|
||||
|
|
@ -1402,7 +1402,7 @@ static void macro_add_to_arg(int is_white_space)
|
|||
def_buf_free -= length;
|
||||
}
|
||||
|
||||
static void macro_finish_arg()
|
||||
static void macro_finish_arg(void)
|
||||
{
|
||||
char* tail = &def_buf[def_buf_size - def_buf_free];
|
||||
|
||||
|
|
@ -1443,7 +1443,7 @@ static void exp_buf_grow_to_fit(int length)
|
|||
}
|
||||
}
|
||||
|
||||
static void expand_using_args()
|
||||
static void expand_using_args(void)
|
||||
{
|
||||
char* head;
|
||||
char* tail;
|
||||
|
|
@ -1634,7 +1634,8 @@ static const char* do_magic(const char*name)
|
|||
|
||||
int actual_len = snprintf(magic_text, desired_cnt,
|
||||
"%u", get_line(istack));
|
||||
assert(actual_len < desired_cnt);
|
||||
assert(actual_len >= 0);
|
||||
assert((unsigned) actual_len < desired_cnt);
|
||||
return magic_text;
|
||||
}
|
||||
else if(!strcmp(name, "__FILE__"))
|
||||
|
|
@ -1654,7 +1655,9 @@ static const char* do_magic(const char*name)
|
|||
|
||||
int actual_len = snprintf(magic_text, desired_cnt,
|
||||
"\"%s\"", path);
|
||||
assert(actual_len < desired_cnt);
|
||||
|
||||
assert(actual_len >= 0);
|
||||
assert((unsigned) actual_len < (unsigned)desired_cnt);
|
||||
return magic_text;
|
||||
}
|
||||
}
|
||||
|
|
@ -1684,13 +1687,13 @@ static const char* do_magic(const char*name)
|
|||
* parsing resumes.
|
||||
*/
|
||||
|
||||
static void output_init()
|
||||
static void output_init(void)
|
||||
{
|
||||
if (line_direct_flag)
|
||||
fprintf(yyout, "`line 1 \"%s\" 0\n", istack->path);
|
||||
}
|
||||
|
||||
static void include_filename()
|
||||
static void include_filename(void)
|
||||
{
|
||||
if(standby) {
|
||||
emit_pathline(istack);
|
||||
|
|
@ -1709,7 +1712,7 @@ static void include_filename()
|
|||
standby->comment = NULL;
|
||||
}
|
||||
|
||||
static void do_include()
|
||||
static void do_include(void)
|
||||
{
|
||||
/* standby is defined by include_filename() */
|
||||
if (standby->path[0] == '/') {
|
||||
|
|
@ -1832,7 +1835,7 @@ static void emit_pathline(struct include_stack_t* isp)
|
|||
fprintf(stderr, "%s:%u: ", isp->path, isp->lineno+1);
|
||||
}
|
||||
|
||||
static void lexor_done()
|
||||
static void lexor_done(void)
|
||||
{
|
||||
while (ifdef_stack)
|
||||
{
|
||||
|
|
@ -1920,7 +1923,7 @@ static void open_input_file(struct include_stack_t*isp)
|
|||
* end of a base file, in which case the next base source file is
|
||||
* opened.
|
||||
*/
|
||||
static int load_next_input()
|
||||
static int load_next_input(void)
|
||||
{
|
||||
int line_mask_flag = 0;
|
||||
struct include_stack_t* isp = istack;
|
||||
|
|
@ -2190,7 +2193,7 @@ void reset_lexor(FILE* out, char* paths[])
|
|||
/*
|
||||
* Modern version of flex (>=2.5.9) can clean up the scanner data.
|
||||
*/
|
||||
void destroy_lexor()
|
||||
void destroy_lexor(void)
|
||||
{
|
||||
# ifdef FLEX_SCANNER
|
||||
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
|
||||
|
|
|
|||
32
lexor.lex
32
lexor.lex
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -134,9 +134,17 @@ TU [munpf]
|
|||
\n { yylloc.first_line += 1; }
|
||||
|
||||
/* C++ style comments start with / / and run to the end of the
|
||||
current line. These are very easy to handle. */
|
||||
current line. These are very easy to handle. The meta-comments
|
||||
format is a little more tricky to handle, but do what we can. */
|
||||
|
||||
"//".* { comment_enter = YY_START; BEGIN(LCOMMENT); }
|
||||
/* The lexor detects "// synthesis translate_on/off" meta-comments,
|
||||
we handle them here by turning on/off a flag. The pform uses
|
||||
that flag to attach implicit attributes to "initial" and
|
||||
"always" statements. */
|
||||
|
||||
"//"{W}*"synthesis"{W}+"translate_on"{W}*\n { pform_mc_translate_on(true); }
|
||||
"//"{W}*"synthesis"{W}+"translate_off"{W}*\n { pform_mc_translate_on(false); }
|
||||
"//" { comment_enter = YY_START; BEGIN(LCOMMENT); }
|
||||
<LCOMMENT>. { yymore(); }
|
||||
<LCOMMENT>\n { yylloc.first_line += 1; BEGIN(comment_enter); }
|
||||
|
||||
|
|
@ -325,8 +333,8 @@ TU [munpf]
|
|||
if (in_package_scope) {
|
||||
if (rc == IDENTIFIER) {
|
||||
if (data_type_t*type = pform_test_type_identifier(in_package_scope, yylval.text)) {
|
||||
delete[]yylval.text;
|
||||
yylval.data_type = type;
|
||||
yylval.type_identifier.text = yylval.text;
|
||||
yylval.type_identifier.type = type;
|
||||
rc = TYPE_IDENTIFIER;
|
||||
}
|
||||
}
|
||||
|
|
@ -361,8 +369,8 @@ TU [munpf]
|
|||
return this as a TYPE_IDENTIFIER instead. */
|
||||
if (rc == IDENTIFIER && gn_system_verilog()) {
|
||||
if (data_type_t*type = pform_test_type_identifier(yylval.text)) {
|
||||
delete[]yylval.text;
|
||||
yylval.data_type = type;
|
||||
yylval.type_identifier.text = yylval.text;
|
||||
yylval.type_identifier.type = type;
|
||||
rc = TYPE_IDENTIFIER;
|
||||
}
|
||||
}
|
||||
|
|
@ -382,8 +390,8 @@ TU [munpf]
|
|||
}
|
||||
if (gn_system_verilog()) {
|
||||
if (data_type_t*type = pform_test_type_identifier(yylval.text)) {
|
||||
delete[]yylval.text;
|
||||
yylval.data_type = type;
|
||||
yylval.type_identifier.text = yylval.text;
|
||||
yylval.type_identifier.type = type;
|
||||
return TYPE_IDENTIFIER;
|
||||
}
|
||||
}
|
||||
|
|
@ -649,14 +657,14 @@ TU [munpf]
|
|||
|GN_KEYWORDS_1364_2005
|
||||
|GN_KEYWORDS_VAMS_2_3;
|
||||
} else {
|
||||
fprintf(stderr, "%s:%u: Ignoring unknown keywords string: %s\n",
|
||||
fprintf(stderr, "%s:%d: Ignoring unknown keywords string: %s\n",
|
||||
yylloc.text, yylloc.first_line, word);
|
||||
}
|
||||
BEGIN(0);
|
||||
}
|
||||
|
||||
<PPBEGIN_KEYWORDS>.* {
|
||||
fprintf(stderr, "%s:%u: Malformed keywords specification: %s\n",
|
||||
fprintf(stderr, "%s:%d: Malformed keywords specification: %s\n",
|
||||
yylloc.text, yylloc.first_line, yytext);
|
||||
BEGIN(0);
|
||||
}
|
||||
|
|
@ -666,7 +674,7 @@ TU [munpf]
|
|||
lexor_keyword_mask = keyword_mask_stack.front();
|
||||
keyword_mask_stack.pop_front();
|
||||
} else {
|
||||
fprintf(stderr, "%s:%u: Mismatched end_keywords directive\n",
|
||||
fprintf(stderr, "%s:%d: Mismatched end_keywords directive\n",
|
||||
yylloc.text, yylloc.first_line);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __lexor_keyword_H
|
||||
#define __lexor_keyword_H
|
||||
#ifndef IVL_lexor_keyword_H
|
||||
#define IVL_lexor_keyword_H
|
||||
/*
|
||||
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -21,4 +21,4 @@
|
|||
|
||||
extern int lexor_keyword_code (const char*str, unsigned len);
|
||||
|
||||
#endif
|
||||
#endif /* IVL_lexor_keyword_H */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __LineInfo_H
|
||||
#define __LineInfo_H
|
||||
#ifndef IVL_LineInfo_H
|
||||
#define IVL_LineInfo_H
|
||||
/*
|
||||
* Copyright (c) 1999-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -54,4 +54,4 @@ class LineInfo {
|
|||
unsigned lineno_;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_LineInfo_H */
|
||||
|
|
|
|||
|
|
@ -210,3 +210,5 @@ ostream& operator << (ostream&out, perm_string that)
|
|||
out << that.str();
|
||||
return out;
|
||||
}
|
||||
|
||||
const perm_string empty_perm_string = perm_string::literal("");
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __StringHeap_H
|
||||
#define __StringHeap_H
|
||||
#ifndef IVL_StringHeap_H
|
||||
#define IVL_StringHeap_H
|
||||
/*
|
||||
* Copyright (c) 2002-2009 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -52,6 +52,7 @@ class perm_string {
|
|||
const char*text_;
|
||||
};
|
||||
|
||||
extern const perm_string empty_perm_string;
|
||||
extern bool operator == (perm_string a, perm_string b);
|
||||
extern bool operator == (perm_string a, const char* b);
|
||||
extern bool operator != (perm_string a, perm_string b);
|
||||
|
|
@ -120,4 +121,4 @@ class StringHeapLex : private StringHeap {
|
|||
StringHeapLex& operator= (const StringHeapLex&);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_StringHeap_H */
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ LDRELOCFLAGS = @LDRELOCFLAGS@
|
|||
LDTARGETFLAGS = @LDTARGETFLAGS@
|
||||
|
||||
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@
|
||||
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
|
||||
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
||||
|
||||
A = a_close.o a_compare_handles.o a_configure.o a_fetch_argc.o \
|
||||
a_fetch_argv.o a_fetch_dir.o a_fetch_fullname.o a_fetch_location.o \
|
||||
|
|
|
|||
|
|
@ -69,9 +69,13 @@ int acc_configure(PLI_INT32 config_param, const char*value)
|
|||
fprintf(pli_trace, "acc_configure(config=%d, %s)\n",
|
||||
(int)config_param, value);
|
||||
}
|
||||
|
||||
#if 0
|
||||
vpi_printf("XXXX acc_configure(%d, %s)\n", (int)config_param,
|
||||
value);
|
||||
#else
|
||||
/* Parameter is not necessarily a string. */
|
||||
vpi_printf("XXXX acc_configure(%d, ...)\n", (int)config_param);
|
||||
#endif
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
# include <vpi_user.h>
|
||||
# include <veriuser.h>
|
||||
# include <acc_user.h>
|
||||
|
||||
/*
|
||||
* acc_fetch_argc implemented using VPI interface
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
# include <vpi_user.h>
|
||||
# include <veriuser.h>
|
||||
# include <acc_user.h>
|
||||
|
||||
/*
|
||||
* acc_fetch_argv implemented using VPI interface
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@picturel.com)
|
||||
* Copyright (c) 2003-2014 Stephen Williams (steve@picturel.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
PLI_INT32 acc_fetch_direction(handle obj)
|
||||
{
|
||||
(void)obj; /* Parameter is not used. */
|
||||
if (pli_trace) {
|
||||
fprintf(pli_trace, "acc_fetch_direction: enter.\n");
|
||||
fflush(pli_trace);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
int acc_fetch_location(p_location loc, handle obj)
|
||||
{
|
||||
(void)obj; /* Parameter is not used. */
|
||||
loc->line_no = 0;
|
||||
loc->filename = "<filename>";
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -40,3 +40,12 @@ const char* acc_fetch_type_str(PLI_INT32 type)
|
|||
vpi_printf("acc_fetch_type_str: type %d is what accType?\n", (int)type);
|
||||
return "acc_fetch_type_str(unknown)";
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: What does this do? How should it be declared in acc_user.h?
|
||||
*/
|
||||
PLI_INT32 acc_fetch_paramtype(handle obj)
|
||||
{
|
||||
(void)obj; /* Parameter is not used. */
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@picturel.com)
|
||||
* Copyright (c) 2003-2014 Stephen Williams (steve@picturel.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
handle acc_handle_hiconn(handle obj)
|
||||
{
|
||||
(void)obj; /* Parameter is not used. */
|
||||
if (pli_trace) {
|
||||
fprintf(pli_trace, "acc_handle_hiconn: enter.\n");
|
||||
fflush(pli_trace);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@picturel.com)
|
||||
* Copyright (c) 2003-2014 Stephen Williams (steve@picturel.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
handle acc_next_bit(handle ref, handle bit)
|
||||
{
|
||||
(void)ref; /* Parameter is not used. */
|
||||
(void)bit; /* Parameter is not used. */
|
||||
if (pli_trace) {
|
||||
fprintf(pli_trace, "acc_next_bit: enter.\n");
|
||||
fflush(pli_trace);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
handle acc_next_port(handle ref, handle bit)
|
||||
{
|
||||
(void)ref; /* Parameter is not used. */
|
||||
(void)bit; /* Parameter is not used. */
|
||||
if (pli_trace) {
|
||||
fprintf(pli_trace, "acc_next_port: enter.\n");
|
||||
fflush(pli_trace);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2010 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -162,6 +162,7 @@ void acc_vcl_add(handle obj, PLI_INT32(*consumer)(p_vc_record),
|
|||
|
||||
switch (vpi_get(vpiType, obj)) {
|
||||
case vpiNet:
|
||||
case vpiReg:
|
||||
cur = malloc(sizeof (struct vcl_record));
|
||||
cur->obj = obj;
|
||||
cur->consumer = consumer;
|
||||
|
|
@ -195,5 +196,9 @@ void acc_vcl_add(handle obj, PLI_INT32(*consumer)(p_vc_record),
|
|||
void acc_vcl_delete(handle obj, PLI_INT32(*consumer)(p_vc_record),
|
||||
void*data, PLI_INT32 vcl_flag)
|
||||
{
|
||||
(void)obj; /* Parameter is not used. */
|
||||
(void)consumer; /* Parameter is not used. */
|
||||
(void)data; /* Parameter is not used. */
|
||||
(void)vcl_flag; /* Parameter is not used. */
|
||||
vpi_printf("XXXX acc_vcl_delete(...)\n");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __config_H
|
||||
#define __config_H
|
||||
#ifndef IVL_config_H
|
||||
#define IVL_config_H
|
||||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -37,4 +37,4 @@ typedef unsigned long ivl_u64_t;
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif /* IVL_config_H */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
static PLI_INT32 delay_callback(struct t_cb_data*cb)
|
||||
{
|
||||
(void)cb; /* Parameter is not used. */
|
||||
vpi_printf("XXXX delay_callback called.\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
struct t_tfexprinfo* tf_exprinfo(PLI_INT32 a, struct t_tfexprinfo*ip)
|
||||
{
|
||||
(void)a; /* Parameter is not used. */
|
||||
(void)ip; /* Parameter is not used. */
|
||||
if (pli_trace) {
|
||||
fprintf(pli_trace, "tf_exprinfo: enter.\n");
|
||||
fflush(pli_trace);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2011 Michael Ruff (mruff at chiaro.com)
|
||||
* Copyright (c) 2002-2014 Michael Ruff (mruff at chiaro.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -39,14 +39,36 @@ static ivl_u64_t pow10u(PLI_INT32 val)
|
|||
}
|
||||
|
||||
static ivl_u64_t
|
||||
scale(int high, int low, void*obj) {
|
||||
vpiHandle hand = vpi_handle(vpiScope, vpi_handle(vpiSysTfCall,0));
|
||||
scale(int high, int low, void*obj)
|
||||
{
|
||||
ivl_u64_t scaled;
|
||||
|
||||
vpiHandle use_obj = obj;
|
||||
if (use_obj == 0) {
|
||||
/* If object is not passed in, then use current scope. */
|
||||
vpiHandle hand = vpi_handle(vpiScope, vpi_handle(vpiSysTfCall,0));
|
||||
use_obj = hand;
|
||||
} else {
|
||||
/* If object IS passed in, make sure it is a scope. If
|
||||
it is not, then get the scope of the object. We need
|
||||
a scope handle to go on. */
|
||||
switch (vpi_get(vpiType,use_obj)) {
|
||||
case vpiModule:
|
||||
case vpiGenScope:
|
||||
case vpiFunction:
|
||||
case vpiTask:
|
||||
case vpiNamedBegin:
|
||||
case vpiNamedFork:
|
||||
break;
|
||||
default:
|
||||
use_obj = vpi_handle(vpiScope, use_obj);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
scaled = high;
|
||||
scaled = (scaled << 32) | low;
|
||||
scaled /= pow10u(vpi_get(vpiTimeUnit,obj ? (vpiHandle)obj : hand) -
|
||||
vpi_get(vpiTimePrecision,0));
|
||||
scaled /= pow10u(vpi_get(vpiTimeUnit, use_obj) - vpi_get(vpiTimePrecision,0));
|
||||
|
||||
return scaled;
|
||||
}
|
||||
|
|
@ -125,6 +147,8 @@ void tf_unscale_longdelay(void*obj, PLI_INT32 low, PLI_INT32 high,
|
|||
ivl_u64_t unscaled;
|
||||
vpiHandle hand = vpi_handle(vpiScope, vpi_handle(vpiSysTfCall,0));
|
||||
|
||||
(void)obj; /* Parameter is not used. */
|
||||
|
||||
unscaled = high;
|
||||
unscaled = (unscaled << 32) | low;
|
||||
unscaled *= pow(10, vpi_get(vpiTimeUnit, hand) -
|
||||
|
|
@ -138,6 +162,8 @@ void tf_scale_realdelay(void*obj, double real, double *areal)
|
|||
{
|
||||
vpiHandle hand = vpi_handle(vpiScope, vpi_handle(vpiSysTfCall,0));
|
||||
|
||||
(void)obj; /* Parameter is not used. */
|
||||
|
||||
*areal = real / pow(10, vpi_get(vpiTimeUnit, hand) -
|
||||
vpi_get(vpiTimePrecision, 0));
|
||||
}
|
||||
|
|
@ -146,6 +172,8 @@ void tf_unscale_realdelay(void*obj, double real, double *areal)
|
|||
{
|
||||
vpiHandle hand = vpi_handle(vpiScope, vpi_handle(vpiSysTfCall,0));
|
||||
|
||||
(void)obj; /* Parameter is not used. */
|
||||
|
||||
*areal = real * pow(10, vpi_get(vpiTimeUnit, hand) -
|
||||
vpi_get(vpiTimePrecision, 0));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002 Michael Ruff (mruff at chiaro.com)
|
||||
* Copyright (c) 2002-2014 Michael Ruff (mruff at chiaro.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -58,6 +58,8 @@ PLI_INT32 tf_message(PLI_INT32 level, char*facility,
|
|||
{
|
||||
va_list ap;
|
||||
|
||||
(void)level; /* Parameter is not used. */
|
||||
|
||||
vpi_printf("%s[%s] ", facility, messno);
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -23,8 +23,11 @@
|
|||
# include <vpi_user.h>
|
||||
# include "priv.h"
|
||||
|
||||
struct t_tfnoeinfo* tf_nodeinfo(PLI_INT32 a, struct t_tfnodeinfo*ip)
|
||||
/* XXX Not declared or used anywhere? */
|
||||
struct t_tfnodeinfo* tf_nodeinfo(PLI_INT32 a, struct t_tfnodeinfo*ip)
|
||||
{
|
||||
(void)a; /* Parameter is not used. */
|
||||
(void)ip; /* Parameter is not used. */
|
||||
if (pli_trace) {
|
||||
fprintf(pli_trace, "tf_nodeinfo: enter.\n");
|
||||
fflush(pli_trace);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <vpi_user.h>
|
||||
#include <stdio.h>
|
||||
#include "veriuser.h"
|
||||
|
||||
/*
|
||||
* tf_nump implemented using VPI interface
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __priv_H
|
||||
#define __priv_H
|
||||
#ifndef IVL_priv_H
|
||||
#define IVL_priv_H
|
||||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -33,4 +33,4 @@ extern char* __acc_newstring(const char*txt);
|
|||
*/
|
||||
FILE* pli_trace;
|
||||
|
||||
#endif
|
||||
#endif /* IVL_priv_H */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2013 Michael Ruff (mruff at chiaro.com)
|
||||
* Copyright (c) 2002-2014 Michael Ruff (mruff at chiaro.com)
|
||||
* Michael Runyan (mrunyan at chiaro.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
|
|
@ -57,6 +57,8 @@ static PLI_INT32 sys_end_of_simulation(p_cb_data cb_data)
|
|||
{
|
||||
unsigned idx;
|
||||
|
||||
(void)cb_data; /* Parameter is not used. */
|
||||
|
||||
for (idx = 0; idx < udata_count; idx += 1) {
|
||||
free(udata_store[idx]);
|
||||
}
|
||||
|
|
@ -370,7 +372,7 @@ PLI_INT32 tf_irosynchronize(void*obj)
|
|||
vpiHandle sys = (vpiHandle)obj;
|
||||
p_pli_data pli = vpi_get_userdata(sys);
|
||||
s_cb_data cb;
|
||||
s_vpi_time ti = {vpiSuppressTime, 0, 0};
|
||||
s_vpi_time ti = {vpiSuppressTime, 0, 0, 0.0};
|
||||
|
||||
cb.reason = cbReadOnlySynch;
|
||||
cb.cb_rtn = callback;
|
||||
|
|
@ -397,7 +399,7 @@ PLI_INT32 tf_isetrealdelay(double dly, void*obj)
|
|||
vpiHandle sys = (vpiHandle)obj;
|
||||
p_pli_data pli = vpi_get_userdata(sys);
|
||||
s_cb_data cb;
|
||||
s_vpi_time ti = {vpiSimTime};
|
||||
s_vpi_time ti = {vpiSimTime, 0, 0, 0.0};
|
||||
|
||||
/* Scale delay to SimTime */
|
||||
ivl_u64_t delay = ((dly
|
||||
|
|
|
|||
|
|
@ -232,3 +232,58 @@ verinum Nexus::driven_vector() const
|
|||
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate a vector that represent all the bits of the vector, with
|
||||
* each driven bit set to true, otherwise false.
|
||||
*/
|
||||
vector<bool> Nexus::driven_mask(void) const
|
||||
{
|
||||
vector<bool> mask (vector_width());
|
||||
|
||||
for (const Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
|
||||
|
||||
Link::DIR link_dir = cur->get_dir();
|
||||
if (link_dir==Link::PASSIVE)
|
||||
continue;
|
||||
if (link_dir==Link::INPUT)
|
||||
continue;
|
||||
|
||||
const NetPins*obj = cur->get_obj();
|
||||
|
||||
// If the link is to a variable (REG or INTEGER) then
|
||||
// the variable is driving all the bits. We have our
|
||||
// complete answer, mark all the bits as driven and
|
||||
// finish. Otherwise, we are not going to get new
|
||||
// information from this node, move on.
|
||||
if (const NetNet*sig = dynamic_cast<const NetNet*> (obj)) {
|
||||
NetNet::Type sig_type = sig->type();
|
||||
if (sig_type==NetNet::INTEGER || sig_type==NetNet::REG) {
|
||||
for (size_t idx = 0 ; idx < mask.size() ; idx += 1)
|
||||
mask[idx] = true;
|
||||
return mask;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
const NetPartSelect*obj_ps = dynamic_cast<const NetPartSelect*>(obj);
|
||||
if (obj_ps && obj_ps->dir()==NetPartSelect::VP)
|
||||
continue;
|
||||
if (obj_ps && cur->get_pin()!=1)
|
||||
continue;
|
||||
if (obj_ps) {
|
||||
for (unsigned idx = 0 ; idx < obj_ps->width() ; idx += 1) {
|
||||
size_t bit = idx + obj_ps->base();
|
||||
ivl_assert(*obj, bit < mask.size());
|
||||
mask[bit] = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
for (size_t idx = 0 ; idx < mask.size() ; idx += 1)
|
||||
mask[idx] = true;
|
||||
return mask;
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
|
|
|||
16
main.cc
16
main.cc
|
|
@ -1019,6 +1019,16 @@ int main(int argc, char*argv[])
|
|||
; cur != disciplines.end() ; ++ cur ) {
|
||||
pform_dump(out, (*cur).second);
|
||||
}
|
||||
out << "PFORM DUMP $ROOT TASKS/FUNCTIONS:" << endl;
|
||||
for (map<perm_string,PTaskFunc*>::iterator cur = pform_tasks.begin()
|
||||
; cur != pform_tasks.end() ; ++ cur) {
|
||||
pform_dump(out, cur->second);
|
||||
}
|
||||
out << "PFORM DUMP $ROOT CLASSES:" << endl;
|
||||
for (map<perm_string,PClass*>::iterator cur = pform_classes.begin()
|
||||
; cur != pform_classes.end() ; ++ cur) {
|
||||
pform_dump(out, cur->second);
|
||||
}
|
||||
out << "PFORM DUMP PACKAGES:" << endl;
|
||||
for (map<perm_string,PPackage*>::iterator pac = pform_packages.begin()
|
||||
; pac != pform_packages.end() ; ++ pac) {
|
||||
|
|
@ -1142,6 +1152,12 @@ int main(int argc, char*argv[])
|
|||
(*idx).second = 0;
|
||||
}
|
||||
|
||||
for(map<perm_string,data_type_t*>::iterator it = pform_typedefs.begin()
|
||||
; it != pform_typedefs.end() ; ++it) {
|
||||
delete (*it).second;
|
||||
(*it).second = 0;
|
||||
}
|
||||
|
||||
if (verbose_flag) {
|
||||
if (times_flag) {
|
||||
times(cycles+2);
|
||||
|
|
|
|||
8
named.h
8
named.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __named_H
|
||||
#define __named_H
|
||||
#ifndef IVL_named_H
|
||||
#define IVL_named_H
|
||||
/*
|
||||
* Copyright (c) 2000-2004 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -31,4 +31,4 @@ template <class T> struct named {
|
|||
T parm;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* IVL_named_H */
|
||||
|
|
|
|||
|
|
@ -134,6 +134,21 @@ NetScope* Design::make_package_scope(perm_string name)
|
|||
return scope;
|
||||
}
|
||||
|
||||
void Design::add_class(netclass_t*cl, PClass*pclass)
|
||||
{
|
||||
Definitions::add_class(cl);
|
||||
class_to_pclass_[cl] = pclass;
|
||||
}
|
||||
|
||||
netclass_t* Design::find_class(perm_string name) const
|
||||
{
|
||||
map<perm_string,netclass_t*>::const_iterator cur = classes_.find(name);
|
||||
if (cur != classes_.end())
|
||||
return cur->second;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetScope* Design::find_package(perm_string name) const
|
||||
{
|
||||
map<perm_string,NetScope*>::const_iterator cur = packages_.find(name);
|
||||
|
|
@ -154,6 +169,17 @@ list<NetScope*> Design::find_package_scopes() const
|
|||
return res;
|
||||
}
|
||||
|
||||
list<NetScope*> Design::find_roottask_scopes() const
|
||||
{
|
||||
list<NetScope*>res;
|
||||
for (map<NetScope*,PTaskFunc*>::const_iterator cur = root_tasks_.begin()
|
||||
; cur != root_tasks_.end() ; ++ cur) {
|
||||
res.push_back (cur->first);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method locates a scope in the design, given its rooted
|
||||
* hierarchical name. Each component of the key is used to scan one
|
||||
|
|
@ -182,7 +208,25 @@ NetScope* Design::find_scope(const std::list<hname_t>&path) const
|
|||
|
||||
tmp.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
for (map<NetScope*,PTaskFunc*>::const_iterator root = root_tasks_.begin()
|
||||
; root != root_tasks_.end() ; ++ root) {
|
||||
|
||||
NetScope*cur = root->first;
|
||||
if (path.front() != cur->fullname())
|
||||
continue;
|
||||
|
||||
std::list<hname_t> tmp = path;
|
||||
tmp.pop_front();
|
||||
|
||||
while (cur) {
|
||||
if (tmp.empty()) return cur;
|
||||
|
||||
cur = cur->child( tmp.front() );
|
||||
|
||||
tmp.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -821,6 +865,11 @@ NetScope* Design::find_task(NetScope*scope, const pform_name_t&name)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void Design::add_root_task(NetScope*tscope, PTaskFunc*tf)
|
||||
{
|
||||
root_tasks_[tscope] = tf;
|
||||
}
|
||||
|
||||
void Design::add_node(NetNode*net)
|
||||
{
|
||||
assert(net->design_ == 0);
|
||||
|
|
|
|||
60
net_event.cc
60
net_event.cc
|
|
@ -20,6 +20,7 @@
|
|||
# include "config.h"
|
||||
# include "compiler.h"
|
||||
# include "netlist.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
/*
|
||||
* NOTE: The name_ is perm-allocated by the caller.
|
||||
|
|
@ -316,6 +317,10 @@ void NetEvProbe::find_similar_probes(list<NetEvProbe*>&plist)
|
|||
|
||||
for (Link*lcur = nex->first_nlink(); lcur; lcur = lcur->next_nlink()) {
|
||||
NetPins*obj = lcur->get_obj();
|
||||
// Skip NexusSet objects
|
||||
if (obj == 0)
|
||||
continue;
|
||||
|
||||
if (obj->pin_count() != pin_count())
|
||||
continue;
|
||||
|
||||
|
|
@ -340,14 +345,14 @@ void NetEvProbe::find_similar_probes(list<NetEvProbe*>&plist)
|
|||
}
|
||||
|
||||
NetEvWait::NetEvWait(NetProc*pr)
|
||||
: statement_(pr), nevents_(0), events_(0)
|
||||
: statement_(pr)
|
||||
{
|
||||
}
|
||||
|
||||
NetEvWait::~NetEvWait()
|
||||
{
|
||||
if (events_) {
|
||||
for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) {
|
||||
if (! events_.empty()) {
|
||||
for (unsigned idx = 0 ; idx < events_.size() ; idx += 1) {
|
||||
NetEvent*tgt = events_[idx];
|
||||
tgt->waitref_ -= 1;
|
||||
|
||||
|
|
@ -365,7 +370,7 @@ NetEvWait::~NetEvWait()
|
|||
delete tmp;
|
||||
}
|
||||
}
|
||||
delete[]events_;
|
||||
events_.clear();
|
||||
}
|
||||
delete statement_;
|
||||
}
|
||||
|
|
@ -374,29 +379,12 @@ void NetEvWait::add_event(NetEvent*tgt)
|
|||
{
|
||||
/* A wait fork is an empty event. */
|
||||
if (! tgt) {
|
||||
assert(nevents_ == 0);
|
||||
nevents_ = 1;
|
||||
events_ = new NetEvent*[1];
|
||||
events_[0] = 0;
|
||||
assert(events_.empty());
|
||||
events_.push_back(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nevents_ == 0) {
|
||||
events_ = new NetEvent*[1];
|
||||
|
||||
} else {
|
||||
assert(events_[0]);
|
||||
NetEvent**tmp = new NetEvent*[nevents_+1];
|
||||
for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) {
|
||||
tmp[idx] = events_[idx];
|
||||
assert(tmp[idx] != tgt);
|
||||
}
|
||||
delete[]events_;
|
||||
events_ = tmp;
|
||||
}
|
||||
|
||||
events_[nevents_] = tgt;
|
||||
nevents_ += 1;
|
||||
events_.push_back(tgt);
|
||||
|
||||
// Remember to tell the NetEvent that there is someone
|
||||
// pointing to it.
|
||||
|
|
@ -411,14 +399,14 @@ void NetEvWait::add_event(NetEvent*tgt)
|
|||
void NetEvWait::replace_event(NetEvent*src, NetEvent*repl)
|
||||
{
|
||||
unsigned idx;
|
||||
for (idx = 0 ; idx < nevents_ ; idx += 1) {
|
||||
for (idx = 0 ; idx < events_.size() ; idx += 1) {
|
||||
if (events_[idx] == src)
|
||||
break;
|
||||
}
|
||||
|
||||
assert(idx < nevents_);
|
||||
assert(idx < events_.size());
|
||||
|
||||
/* First, remove me from the list held by the src NetEvent. */
|
||||
// First, remove me from the list held by the src NetEvent.
|
||||
assert(src->waitref_ > 0);
|
||||
src->waitref_ -= 1;
|
||||
struct NetEvent::wcell_*tmp = src->wlist_;
|
||||
|
|
@ -435,6 +423,7 @@ void NetEvWait::replace_event(NetEvent*src, NetEvent*repl)
|
|||
delete tmp;
|
||||
}
|
||||
|
||||
// Replace the src pointer with the repl pointer.
|
||||
events_[idx] = repl;
|
||||
|
||||
// Remember to tell the replacement NetEvent that there is
|
||||
|
|
@ -448,23 +437,6 @@ void NetEvWait::replace_event(NetEvent*src, NetEvent*repl)
|
|||
|
||||
}
|
||||
|
||||
unsigned NetEvWait::nevents() const
|
||||
{
|
||||
return nevents_;
|
||||
}
|
||||
|
||||
const NetEvent* NetEvWait::event(unsigned idx) const
|
||||
{
|
||||
assert(idx < nevents_);
|
||||
return events_[idx];
|
||||
}
|
||||
|
||||
NetEvent* NetEvWait::event(unsigned idx)
|
||||
{
|
||||
assert(idx < nevents_);
|
||||
return events_[idx];
|
||||
}
|
||||
|
||||
NetProc* NetEvWait::statement()
|
||||
{
|
||||
return statement_;
|
||||
|
|
|
|||
18
net_expr.cc
18
net_expr.cc
|
|
@ -321,6 +321,20 @@ const NetScope* NetECRealParam::scope() const
|
|||
}
|
||||
|
||||
|
||||
NetELast::NetELast(NetNet*s)
|
||||
: sig_(s)
|
||||
{
|
||||
}
|
||||
|
||||
NetELast::~NetELast()
|
||||
{
|
||||
}
|
||||
|
||||
ivl_variable_type_t NetELast::expr_type() const
|
||||
{
|
||||
return IVL_VT_BOOL;
|
||||
}
|
||||
|
||||
NetENetenum::NetENetenum(const netenum_t*s)
|
||||
: netenum_(s)
|
||||
{
|
||||
|
|
@ -362,8 +376,8 @@ NetENull::~NetENull()
|
|||
{
|
||||
}
|
||||
|
||||
NetEProperty::NetEProperty(NetNet*net, perm_string pnam)
|
||||
: net_(net)
|
||||
NetEProperty::NetEProperty(NetNet*net, perm_string pnam, NetExpr*idx)
|
||||
: net_(net), index_(idx)
|
||||
{
|
||||
const netclass_t*use_type = dynamic_cast<const netclass_t*>(net->net_type());
|
||||
assert(use_type);
|
||||
|
|
|
|||
|
|
@ -416,8 +416,8 @@ bool NetCase::evaluate_function_vect_(const LineInfo&loc,
|
|||
|
||||
NetProc*default_statement = 0;
|
||||
|
||||
for (unsigned cnt = 0 ; cnt < nitems_ ; cnt += 1) {
|
||||
Item*item = &items_[cnt];
|
||||
for (unsigned cnt = 0 ; cnt < items_.size() ; cnt += 1) {
|
||||
const Item*item = &items_[cnt];
|
||||
|
||||
if (item->guard == 0) {
|
||||
default_statement = item->statement;
|
||||
|
|
@ -478,8 +478,8 @@ bool NetCase::evaluate_function_real_(const LineInfo&loc,
|
|||
|
||||
NetProc*default_statement = 0;
|
||||
|
||||
for (unsigned cnt = 0 ; cnt < nitems_ ; cnt += 1) {
|
||||
Item*item = &items_[cnt];
|
||||
for (unsigned cnt = 0 ; cnt < items_.size() ; cnt += 1) {
|
||||
const Item*item = &items_[cnt];
|
||||
|
||||
if (item->guard == 0) {
|
||||
default_statement = item->statement;
|
||||
|
|
@ -628,6 +628,16 @@ bool NetForever::evaluate_function(const LineInfo&loc,
|
|||
return flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* For now, resort to the block form of the statement until we learn
|
||||
* to do this directly.
|
||||
*/
|
||||
bool NetForLoop::evaluate_function(const LineInfo&loc,
|
||||
map<perm_string,LocalVar>&context_map) const
|
||||
{
|
||||
return as_block_->evaluate_function(loc, context_map);
|
||||
}
|
||||
|
||||
bool NetRepeat::evaluate_function(const LineInfo&loc,
|
||||
map<perm_string,LocalVar>&context_map) const
|
||||
{
|
||||
|
|
|
|||
50
net_link.cc
50
net_link.cc
|
|
@ -90,13 +90,19 @@ void Nexus::connect(Link&r)
|
|||
|
||||
void connect(Link&l, Link&r)
|
||||
{
|
||||
Nexus*tmp;
|
||||
assert(&l != &r);
|
||||
if (l.nexus_ != 0) {
|
||||
connect(l.nexus_, r);
|
||||
} else if (r.nexus_ != 0) {
|
||||
connect(r.nexus_, l);
|
||||
// If either the l or r link already are part of a Nexus, then
|
||||
// re-use that nexus. Go through some effort so that we are
|
||||
// not gratuitously creating Nexus object.
|
||||
if (l.next_ && (tmp=l.find_nexus_())) {
|
||||
connect(tmp, r);
|
||||
} else if (r.next_ && (tmp=r.find_nexus_())) {
|
||||
connect(tmp, l);
|
||||
} else {
|
||||
Nexus*tmp = new Nexus(l);
|
||||
// No existing Nexus (both links are so far unconnected)
|
||||
// so start one.
|
||||
tmp = new Nexus(l);
|
||||
tmp->connect(r);
|
||||
}
|
||||
}
|
||||
|
|
@ -105,6 +111,8 @@ Link::Link()
|
|||
: dir_(PASSIVE), drive0_(IVL_DR_STRONG), drive1_(IVL_DR_STRONG),
|
||||
next_(0), nexus_(0)
|
||||
{
|
||||
node_ = 0;
|
||||
pin_zero_ = true;
|
||||
}
|
||||
|
||||
Link::~Link()
|
||||
|
|
@ -222,9 +230,11 @@ bool Link::is_linked() const
|
|||
|
||||
bool Link::is_linked(const Link&that) const
|
||||
{
|
||||
if (next_ == 0)
|
||||
// If this or that link is linked to nothing, then they cannot
|
||||
// be linked to each other.
|
||||
if (! this->is_linked())
|
||||
return false;
|
||||
if (that.next_ == 0)
|
||||
if (! that.is_linked())
|
||||
return false;
|
||||
|
||||
const Link*cur = next_;
|
||||
|
|
@ -504,16 +514,24 @@ const char* Nexus::name() const
|
|||
<< obj->name() << " pin " << pin
|
||||
<< " type=" << typeid(*obj).name() << "?" << endl;
|
||||
|
||||
}
|
||||
assert(sig);
|
||||
ostringstream tmp;
|
||||
tmp << scope_path(sig->scope()) << "." << sig->name();
|
||||
if (sig->pin_count() > 1)
|
||||
tmp << "<" << pin << ">";
|
||||
ostringstream tmp;
|
||||
tmp << "nex=" << this << ends;
|
||||
const string tmps = tmp.str();
|
||||
name_ = new char[strlen(tmps.c_str()) + 1];
|
||||
strcpy(name_, tmps.c_str());
|
||||
} else {
|
||||
assert(sig);
|
||||
ostringstream tmp;
|
||||
tmp << scope_path(sig->scope()) << "." << sig->name();
|
||||
if (sig->pin_count() > 1)
|
||||
tmp << "<" << pin << ">";
|
||||
tmp << ends;
|
||||
|
||||
const string tmps = tmp.str();
|
||||
name_ = new char[strlen(tmps.c_str()) + 1];
|
||||
strcpy(name_, tmps.c_str());
|
||||
}
|
||||
|
||||
const string tmps = tmp.str();
|
||||
name_ = new char[strlen(tmps.c_str()) + 1];
|
||||
strcpy(name_, tmps.c_str());
|
||||
return name_;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,6 +106,11 @@ NexusSet* NetEEvent::nex_input(bool)
|
|||
return new NexusSet;
|
||||
}
|
||||
|
||||
NexusSet* NetELast::nex_input(bool)
|
||||
{
|
||||
return new NexusSet;
|
||||
}
|
||||
|
||||
NexusSet* NetENetenum::nex_input(bool)
|
||||
{
|
||||
return new NexusSet;
|
||||
|
|
@ -340,7 +345,7 @@ NexusSet* NetCase::nex_input(bool rem_out)
|
|||
if (result == 0)
|
||||
return 0;
|
||||
|
||||
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
|
||||
for (size_t idx = 0 ; idx < items_.size() ; idx += 1) {
|
||||
|
||||
/* Skip cases that have empty statements. */
|
||||
if (items_[idx].statement == 0)
|
||||
|
|
@ -406,6 +411,25 @@ NexusSet* NetForce::nex_input(bool)
|
|||
return new NexusSet;
|
||||
}
|
||||
|
||||
NexusSet* NetForLoop::nex_input(bool rem_out)
|
||||
{
|
||||
NexusSet*result = init_expr_->nex_input(rem_out);
|
||||
|
||||
NexusSet*tmp = condition_->nex_input(rem_out);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
|
||||
tmp = statement_->nex_input(rem_out);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
|
||||
tmp = step_statement_->nex_input(rem_out);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetForever::nex_input(bool rem_out)
|
||||
{
|
||||
NexusSet*result = statement_->nex_input(rem_out);
|
||||
|
|
|
|||
|
|
@ -60,19 +60,18 @@ void NetAssign_::nex_output(NexusSet&out)
|
|||
}
|
||||
Nexus*nex = sig_->pin(use_word).nexus();
|
||||
if (base_) {
|
||||
long tmp = 0;
|
||||
bool flag = eval_as_long(tmp, base_);
|
||||
if (!flag) {
|
||||
// Unable to evaluate the bit/part select of
|
||||
// the l-value, so this is a mux. Pretty
|
||||
// sure I don't know how to handle this yet
|
||||
// in synthesis, so punt for now.
|
||||
use_base = 0;
|
||||
use_wid = nex->vector_width();
|
||||
|
||||
} else {
|
||||
use_base = tmp;
|
||||
}
|
||||
// Unable to evaluate the bit/part select of
|
||||
// the l-value, so this is a mux. Pretty
|
||||
// sure I don't know how to handle this yet
|
||||
// in synthesis, so punt for now.
|
||||
|
||||
// Even with constant bit/part select, we want to
|
||||
// return the entire signal as an output. The
|
||||
// context will need to sort out which bits are
|
||||
// actually assigned.
|
||||
use_base = 0;
|
||||
use_wid = nex->vector_width();
|
||||
}
|
||||
out.add(nex, use_base, use_wid);
|
||||
}
|
||||
|
|
@ -102,7 +101,7 @@ void NetBlock::nex_output(NexusSet&out)
|
|||
|
||||
void NetCase::nex_output(NexusSet&out)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
|
||||
for (size_t idx = 0 ; idx < items_.size() ; idx += 1) {
|
||||
|
||||
// Empty statements clearly have no output.
|
||||
if (items_[idx].statement == 0)
|
||||
|
|
@ -134,6 +133,11 @@ void NetEvWait::nex_output(NexusSet&out)
|
|||
statement_->nex_output(out);
|
||||
}
|
||||
|
||||
void NetForLoop::nex_output(NexusSet&out)
|
||||
{
|
||||
if (statement_) statement_->nex_output(out);
|
||||
}
|
||||
|
||||
void NetPDelay::nex_output(NexusSet&out)
|
||||
{
|
||||
if (statement_) statement_->nex_output(out);
|
||||
|
|
|
|||
48
net_proc.cc
48
net_proc.cc
|
|
@ -71,23 +71,18 @@ const NetProc* NetBlock::proc_next(const NetProc*cur) const
|
|||
}
|
||||
|
||||
NetCase::NetCase(NetCase::TYPE c, NetExpr*ex, unsigned cnt)
|
||||
: type_(c), expr_(ex), nitems_(cnt)
|
||||
: type_(c), expr_(ex), items_(cnt)
|
||||
{
|
||||
assert(expr_);
|
||||
items_ = new Item[nitems_];
|
||||
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
|
||||
items_[idx].statement = 0;
|
||||
}
|
||||
}
|
||||
|
||||
NetCase::~NetCase()
|
||||
{
|
||||
delete expr_;
|
||||
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
|
||||
for (size_t idx = 0 ; idx < items_.size() ; idx += 1) {
|
||||
delete items_[idx].guard;
|
||||
if (items_[idx].statement) delete items_[idx].statement;
|
||||
}
|
||||
delete[]items_;
|
||||
}
|
||||
|
||||
NetCase::TYPE NetCase::type() const
|
||||
|
|
@ -97,7 +92,7 @@ NetCase::TYPE NetCase::type() const
|
|||
|
||||
void NetCase::set_case(unsigned idx, NetExpr*e, NetProc*p)
|
||||
{
|
||||
assert(idx < nitems_);
|
||||
assert(idx < items_.size());
|
||||
items_[idx].guard = e;
|
||||
items_[idx].statement = p;
|
||||
}
|
||||
|
|
@ -126,6 +121,43 @@ NetForever::~NetForever()
|
|||
delete statement_;
|
||||
}
|
||||
|
||||
NetForLoop::NetForLoop(NetNet*ind, NetExpr*iexpr, NetExpr*cond, NetProc*sub, NetProc*step)
|
||||
: index_(ind), init_expr_(iexpr), condition_(cond), statement_(sub), step_statement_(step)
|
||||
{
|
||||
}
|
||||
|
||||
void NetForLoop::wrap_up()
|
||||
{
|
||||
NetBlock*top = new NetBlock(NetBlock::SEQU, 0);
|
||||
top->set_line(*this);
|
||||
|
||||
NetAssign_*lv = new NetAssign_(index_);
|
||||
NetAssign*set_stmt = new NetAssign(lv, init_expr_);
|
||||
set_stmt->set_line(*init_expr_);
|
||||
top->append(set_stmt);
|
||||
|
||||
NetBlock*internal_block = new NetBlock(NetBlock::SEQU, 0);
|
||||
internal_block->set_line(*this);
|
||||
|
||||
if (statement_) internal_block->append(statement_);
|
||||
internal_block->append(step_statement_);
|
||||
|
||||
NetWhile*wloop = new NetWhile(condition_, internal_block);
|
||||
wloop->set_line(*this);
|
||||
|
||||
top->append(wloop);
|
||||
|
||||
as_block_ = top;
|
||||
}
|
||||
|
||||
NetForLoop::~NetForLoop()
|
||||
{
|
||||
delete init_expr_;
|
||||
delete condition_;
|
||||
delete statement_;
|
||||
delete step_statement_;
|
||||
}
|
||||
|
||||
NetPDelay::NetPDelay(uint64_t d, NetProc*st)
|
||||
: delay_(d), expr_(0), statement_(st)
|
||||
{
|
||||
|
|
|
|||
79
net_scope.cc
79
net_scope.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -96,6 +96,11 @@ const NetExpr* Definitions::enumeration_expr(perm_string key)
|
|||
}
|
||||
}
|
||||
|
||||
void Definitions::add_class(netclass_t*net_class)
|
||||
{
|
||||
classes_[net_class->get_name()] = net_class;
|
||||
}
|
||||
|
||||
/*
|
||||
* The NetScope class keeps a scope tree organized. Each node of the
|
||||
* scope tree points to its parent, its right sibling and its leftmost
|
||||
|
|
@ -130,7 +135,6 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest, bo
|
|||
time_unit_ = 0;
|
||||
time_prec_ = 0;
|
||||
time_from_timescale_ = false;
|
||||
assert(t==MODULE || t==PACKAGE || t==CLASS);
|
||||
}
|
||||
|
||||
switch (t) {
|
||||
|
|
@ -189,6 +193,22 @@ void NetScope::set_line(perm_string file, perm_string def_file,
|
|||
def_lineno_ = def_lineno;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for the enumeration in the current scope and any parent scopes.
|
||||
*/
|
||||
const netenum_t*NetScope::find_enumeration_for_name(perm_string name)
|
||||
{
|
||||
NetScope *cur_scope = this;
|
||||
while (cur_scope) {
|
||||
NetEConstEnum*tmp = cur_scope->enum_names_[name];
|
||||
if (tmp) break;
|
||||
cur_scope = cur_scope->parent();
|
||||
}
|
||||
|
||||
assert(cur_scope);
|
||||
return cur_scope->enum_names_[name]->enumeration();
|
||||
}
|
||||
|
||||
void NetScope::set_parameter(perm_string key, bool is_annotatable,
|
||||
PExpr*val, ivl_variable_type_t type__,
|
||||
PExpr*msb, PExpr*lsb, bool signed_flag,
|
||||
|
|
@ -616,14 +636,9 @@ NetNet* NetScope::find_signal(perm_string key)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void NetScope::add_class(netclass_t*net_class)
|
||||
{
|
||||
classes_[net_class->get_name()] = net_class;
|
||||
}
|
||||
|
||||
netclass_t*NetScope::find_class(perm_string name)
|
||||
{
|
||||
// Special class: The scope itself is the class that we are
|
||||
// Special case: The scope itself is the class that we are
|
||||
// looking for. This may happen for example when elaborating
|
||||
// methods within the class.
|
||||
if (type_==CLASS && name_==hname_t(name))
|
||||
|
|
@ -638,6 +653,13 @@ netclass_t*NetScope::find_class(perm_string name)
|
|||
if (type_==MODULE)
|
||||
return 0;
|
||||
|
||||
if (up_==0 && type_==CLASS) {
|
||||
assert(class_def_);
|
||||
|
||||
NetScope*def_parent = class_def_->definition_scope();
|
||||
return def_parent->find_class(name);
|
||||
}
|
||||
|
||||
// If there is no further to look, ...
|
||||
if (up_ == 0)
|
||||
return 0;
|
||||
|
|
@ -668,6 +690,47 @@ const NetScope* NetScope::child(const hname_t&name) const
|
|||
return cur->second;
|
||||
}
|
||||
|
||||
/* Helper function to see if the given scope is defined in a class and if
|
||||
* so return the class scope. */
|
||||
const NetScope* NetScope::get_class_scope() const
|
||||
{
|
||||
const NetScope*scope = this;
|
||||
while (scope) {
|
||||
switch(scope->type()) {
|
||||
case NetScope::CLASS:
|
||||
return scope;
|
||||
case NetScope::TASK:
|
||||
case NetScope::FUNC:
|
||||
case NetScope::BEGIN_END:
|
||||
case NetScope::FORK_JOIN:
|
||||
break;
|
||||
case NetScope::MODULE:
|
||||
case NetScope::GENBLOCK:
|
||||
case NetScope::PACKAGE:
|
||||
return 0;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
scope = scope->parent();
|
||||
}
|
||||
return scope;
|
||||
}
|
||||
|
||||
const NetScope* NetScope::child_byname(perm_string name) const
|
||||
{
|
||||
hname_t hname (name);
|
||||
map<hname_t,NetScope*>::const_iterator cur = children_.lower_bound(hname);
|
||||
|
||||
if (cur == children_.end())
|
||||
return 0;
|
||||
|
||||
if (cur->first.peek_name() == name)
|
||||
return cur->second;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
perm_string NetScope::local_symbol()
|
||||
{
|
||||
ostringstream res;
|
||||
|
|
|
|||
14
netclass.cc
14
netclass.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
using namespace std;
|
||||
|
||||
netclass_t::netclass_t(perm_string name, netclass_t*sup)
|
||||
: name_(name), super_(sup), class_scope_(0)
|
||||
: name_(name), super_(sup), class_scope_(0), definition_scope_(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -50,10 +50,16 @@ bool netclass_t::set_property(perm_string pname, property_qualifier_t qual, ivl_
|
|||
return true;
|
||||
}
|
||||
|
||||
void netclass_t::set_class_scope(NetScope*class_scope)
|
||||
void netclass_t::set_class_scope(NetScope*class_scope__)
|
||||
{
|
||||
assert(class_scope_ == 0);
|
||||
class_scope_ = class_scope;
|
||||
class_scope_ = class_scope__;
|
||||
}
|
||||
|
||||
void netclass_t::set_definition_scope(NetScope*use_definition_scope)
|
||||
{
|
||||
assert(definition_scope_ == 0);
|
||||
definition_scope_ = use_definition_scope;
|
||||
}
|
||||
|
||||
ivl_variable_type_t netclass_t::base_type() const
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue