Extend VPI and build to for SIMetrix cosimulation

Added: basic vpiPort VPI Objects for vpiModulkes
    vpiDirection, vpiPortIndex,   vpiName, vpiSize attributes

   Since ports do not exist as net-like entities (nets either side
   module instance boundaries are in effect connect directly in
   the language front-ends internal representation) the port information
   is effectively just meta-data passed through t-dll  interface and
   output as a additional annotation of module scopes in vvp.

Added: vpiLocalParam attribute for vpiParameter VPI objects

Added: support build for 32-bit target on 64-bit host (--with-m32
   option to configure.in and minor tweaks to Makefiles and systemc-vpi).
This commit is contained in:
Andrew Stevens 2012-06-04 21:43:33 +02:00 committed by Stephen Williams
parent 3354d83391
commit 9b3d20239a
33 changed files with 623 additions and 93 deletions

View File

@ -95,6 +95,7 @@ CFLAGS = @WARNING_FLAGS@ @CFLAGS@
CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@
PICFLAGS = @PICFLAG@
LDFLAGS = @rdynamic@ @LDFLAGS@
CTARGETFLAGS = @CTARGETFLAGS@
# Source files in the libmisc directory
M = LineInfo.o StringHeap.o
@ -228,6 +229,7 @@ iverilog-vpi: $(srcdir)/iverilog-vpi.sh Makefile
-e 's;@IVCXX@;$(CXX);' \
-e 's;@IVCFLAGS@;$(CFLAGS);' \
-e 's;@IVCXXFLAGS@;$(CXXFLAGS);' \
-e 's;@IVCTARGETFLAGS@;$(CTARGETFLAGS);' \
-e 's;@INCLUDEDIR@;$(includedir);' \
-e 's;@LIBDIR@;@libdir@;' $< > $@
chmod +x $@

View File

@ -90,6 +90,22 @@ unsigned Module::find_port(const char*name) const
return ports.size();
}
perm_string Module::get_port_name(unsigned idx) const
{
assert(idx < ports.size());
if (ports[idx] == 0) {
/* It is possible to have undeclared ports. These
are ports that are skipped in the declaration,
for example like so: module foo(x ,, y); The
port between x and y is unnamed and thus
inaccessible to binding by name. */
return perm_string::literal("");
}
return ports[idx]->name;
}
PGate* Module::get_gate(perm_string name)
{

View File

@ -136,6 +136,9 @@ class Module : public PScopeExtra, public LineInfo {
const vector<PEIdent*>& get_port(unsigned idx) const;
unsigned find_port(const char*name) const;
// Return port name ("" for undeclared port)
perm_string get_port_name(unsigned idx) const;
PGate* get_gate(perm_string name);
const list<PGate*>& get_gates() const;

View File

@ -311,7 +311,7 @@ class PEIdent : public PExpr {
// Elaborate the PEIdent as a port to a module. This method
// only applies to Ident expressions.
NetNet* elaborate_port(Design*des, NetScope*sc) const;
NetNet* elaborate_subport(Design*des, NetScope*sc) const;
verinum* eval_const(Design*des, NetScope*sc) const;

View File

@ -91,6 +91,20 @@ fi
AC_LANG(C++)
AC_ARG_WITH([m32], [AC_HELP_STRING([--with-m32], [Compile 32-bit on x86_64])],
[ with_m32=yes ],[ with_m32=no ])
AS_IF( [test "x$with_m32" = xyes],
[ AC_MSG_NOTICE([Compiling for 32-bit environment - needs gcc on x86_64])
LDTARGETFLAGS="-m elf_i386"
CTARGETFLAGS="-m32"
],
[])
CFLAGS="$CTARGETFLAGS $CFLAGS"
CXXFLAGS="$CTARGETFLAGS $CXXFLAGS"
LDFLAGS="$CTARGETFLAGS $LDFLAGS"
# Check that we are using either the GNU compilers or the Sun compilers
# but not a mixture of the two (not currently supported).
AC_CHECK_DECL(__SUNPRO_CC, using_sunpro_cc=1, using_sunpro_cc=0)
@ -111,7 +125,11 @@ else
fi
fi
iverilog_temp_cxxflags="$CXXFLAGS"
CXXFLAGS="-DHAVE_DECL_BASENAME $CXXFLAGS"
AC_CHECK_HEADERS(getopt.h inttypes.h libiberty.h iosfwd sys/wait.h)
CXXFLAGS="$iverilog_temp_cxxflags"
AC_CHECK_SIZEOF(unsigned long long)
AC_CHECK_SIZEOF(unsigned long)
@ -178,6 +196,11 @@ if test -z "$DLLIB" ; then
AC_CHECK_LIB(dld,shl_load,[DLLIB=-ldld])
fi
AC_SUBST(DLLIB)
AC_SUBST(LDRELOCFLAGS)
AC_SUBST(CTARGETFLAGS)
AC_SUBST(LDTARGETFLAGS)
AC_PROG_INSTALL
@ -304,4 +327,9 @@ AC_MSG_RESULT(ok)
# XXX disable tgt-fpga for the moment
#
# Ensure compiler target options go in...
AC_OUTPUT(Makefile ivlpp/Makefile vhdlpp/Makefile vvp/Makefile vpi/Makefile driver/Makefile driver-vpi/Makefile cadpli/Makefile libveriuser/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-vvp/Makefile tgt-vhdl/Makefile tgt-fpga/Makefile tgt-verilog/Makefile tgt-pal/Makefile tgt-vlog95/Makefile tgt-pcb/Makefile)

View File

@ -691,7 +691,7 @@ NetNet* PEIdent::elaborate_bi_net(Design*des, NetScope*scope) const
* instantiation (PGModule::elaborate_mod_) to get NetNet objects for
* the port.
*/
NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
NetNet* PEIdent::elaborate_subport(Design*des, NetScope*scope) const
{
ivl_assert(*this, scope->type() == NetScope::MODULE);
NetNet*sig = des->find_signal(scope, path_);
@ -748,7 +748,7 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
/* If this is a part select of the entire signal (or no part
select at all) then we're done. */
if ((lidx == 0) && (midx == (long)sig->vector_width()-1)) {
scope->add_module_port(sig);
scope->add_module_port_net(sig);
return sig;
}
@ -795,7 +795,7 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
ps->set_line(*this);
des->add_node(ps);
scope->add_module_port(sig);
scope->add_module_port_net(sig);
return sig;
}

View File

@ -52,7 +52,8 @@ typedef map<perm_string,LexicalScope::param_expr_t>::const_iterator mparm_it_t;
static void collect_parm_item_(Design*des, NetScope*scope, perm_string name,
const LexicalScope::param_expr_t&cur,
bool is_annotatable)
bool is_annotatable,
bool local_flag)
{
NetScope::range_t*range_list = 0;
for (LexicalScope::range_t*range = cur.range ; range ; range = range->next) {
@ -88,8 +89,9 @@ static void collect_parm_item_(Design*des, NetScope*scope, perm_string name,
range_list = tmp;
}
scope->set_parameter(name, is_annotatable, cur.expr, cur.type, cur.msb,
cur.lsb, cur.signed_flag, range_list, cur);
cur.lsb, cur.signed_flag, local_flag, range_list, cur);
}
static void collect_scope_parameters_(Design*des, NetScope*scope,
@ -107,7 +109,7 @@ static void collect_scope_parameters_(Design*des, NetScope*scope,
des->errors += 1;
}
collect_parm_item_(des, scope, (*cur).first, (*cur).second, false);
collect_parm_item_(des, scope, (*cur).first, (*cur).second, false, false);
}
}
@ -126,7 +128,7 @@ static void collect_scope_localparams_(Design*des, NetScope*scope,
des->errors += 1;
}
collect_parm_item_(des, scope, (*cur).first, (*cur).second, false);
collect_parm_item_(des, scope, (*cur).first, (*cur).second, false, true);
}
}
@ -145,7 +147,7 @@ static void collect_scope_specparams_(Design*des, NetScope*scope,
des->errors += 1;
}
collect_parm_item_(des, scope, (*cur).first, (*cur).second, true);
collect_parm_item_(des, scope, (*cur).first, (*cur).second, true, false);
}
}

View File

@ -1250,6 +1250,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
get_name() << "..." << endl;
for (unsigned inst = 0 ; inst < instance.size() ; inst += 1) {
rmod->elaborate(des, instance[inst]);
instance[inst]->set_num_ports( rmod->port_count() );
}
if (debug_elaborate) cerr << get_fileline() << ": debug: ...done." << endl;
@ -1329,7 +1330,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
unconnected_port = true;
}
// Inside the module, the port is zero or more signals
// Inside the module, the port connects zero or more signals
// that were already elaborated. List all those signals
// and the NetNet equivalents, for all the instances.
vector<PEIdent*> mport = rmod->get_port(idx);
@ -1349,19 +1350,24 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
// will be assembled in that order as well.
NetScope*inst_scope = instance[instance.size()-inst-1];
unsigned int prt_vector_width = 0;
PortType::Enum ptype = PortType::PIMPLICIT;
// Scan the module sub-ports for this instance...
for (unsigned ldx = 0 ; ldx < mport.size() ; ldx += 1) {
unsigned lbase = inst * mport.size();
PEIdent*pport = mport[ldx];
assert(pport);
prts[lbase + ldx]
= pport->elaborate_port(des, inst_scope);
if (prts[lbase + ldx] == 0)
NetNet *netnet = pport->elaborate_subport(des, inst_scope);
prts[lbase + ldx] = netnet;
if (netnet == 0)
continue;
assert(prts[lbase + ldx]);
prts_vector_width += prts[lbase + ldx]->vector_width();
assert(netnet);
prts_vector_width += netnet->vector_width();
prt_vector_width += netnet->vector_width();
ptype = PortType::merged(netnet->port_type(), ptype);
}
inst_scope->add_module_port_info(idx, rmod->get_port_name(idx), ptype, prt_vector_width );
}
// If I find that the port is unconnected inside the
@ -4512,6 +4518,7 @@ static void elaborate_tasks(Design*des, NetScope*scope,
* When a module is instantiated, it creates the scope then uses this
* method to elaborate the contents of the module.
*/
bool Module::elaborate(Design*des, NetScope*scope) const
{
bool result_flag = true;
@ -4976,10 +4983,22 @@ Design* elaborate(list<perm_string>roots)
// creates all the NetNet and NetMemory objects for declared
// objects.
for (i = 0; i < root_elems.count(); i++) {
Module *rmod = root_elems[i]->mod;
NetScope *scope = root_elems[i]->scope;
scope->set_num_ports( rmod->port_count() );
if (debug_elaborate) {
cerr << "<toplevel>" << ": debug: " << rmod->mod_name()
<< ": port elaboration root "
<< rmod->port_count() << " ports" << endl;
}
if (! rmod->elaborate_sig(des, scope)) {
if (debug_elaborate) {
cerr << "<toplevel>" << ": debug: " << rmod->mod_name()
<< ": elaborate_sig failed!!!" << endl;
}
delete des;
return 0;
}
@ -4988,11 +5007,26 @@ Design* elaborate(list<perm_string>roots)
// defined for the root modules. This code does that.
for (unsigned idx = 0; idx < rmod->port_count(); idx += 1) {
vector<PEIdent*> mport = rmod->get_port(idx);
unsigned int prt_vector_width = 0;
PortType::Enum ptype = PortType::PIMPLICIT;
for (unsigned pin = 0; pin < mport.size(); pin += 1) {
// This really does more than we need and adds extra
// stuff to the design that should be cleaned later.
(void) mport[pin]->elaborate_port(des, scope);
(void) mport[pin]->elaborate_subport(des, scope);
NetNet *netnet = mport[pin]->elaborate_subport(des, scope);
if( netnet != 0 )
{
// Elaboration may actually fail with erroneous input source
prt_vector_width += netnet->vector_width();
ptype = PortType::merged(netnet->port_type(), ptype);
}
}
if (debug_elaborate) {
cerr << "<toplevel>" << ": debug: " << rmod->mod_name()
<< ": adding module port "
<< rmod->get_port_name(idx) << endl;
}
scope->add_module_port_info(idx, rmod->get_port_name(idx), ptype, prt_vector_width );
}
}
@ -5019,5 +5053,11 @@ Design* elaborate(list<perm_string>roots)
des = 0;
}
if (debug_elaborate) {
cerr << "<toplevel>" << ": debug: "
<< " finishing with "
<< des->find_root_scopes().size() << " root scopes " << endl;
}
return des;
}

View File

@ -28,7 +28,7 @@ SUFFIX=@SUFFIX@
# These are used for linking...
LD=$CC
LDFLAGS="@SHARED@ -L@LIBDIR@"
LDFLAGS="@IVCTARGETFLAGS@ @SHARED@ -L@LIBDIR@"
LDLIBS="-lveriuser$SUFFIX -lvpi$SUFFIX"
CCSRC=

View File

@ -193,6 +193,7 @@ typedef struct ivl_parameter_s*ivl_parameter_t;
typedef struct ivl_process_s *ivl_process_t;
typedef struct ivl_scope_s *ivl_scope_t;
typedef struct ivl_signal_s *ivl_signal_t;
typedef struct ivl_port_info_s *ivl_port_info_t;
typedef struct ivl_switch_s *ivl_switch_t;
typedef struct ivl_memory_s *ivl_memory_t; //XXXX __attribute__((deprecated));
typedef struct ivl_statement_s*ivl_statement_t;
@ -363,7 +364,7 @@ typedef enum ivl_scope_type_e {
/* Signals (ivl_signal_t) that are ports into the scope that contains
them have a port type. Otherwise, they are port IVL_SIP_NONE. */
typedef enum ivl_signal_port_e {
typedef enum OUT {
IVL_SIP_NONE = 0,
IVL_SIP_INPUT = 1,
IVL_SIP_OUTPUT= 2,
@ -1568,6 +1569,10 @@ extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net);
* Return the value of the parameter. This should be a simple
* constant expression, an IVL_EX_STRING or IVL_EX_NUMBER.
*
* ivl_parameter_local
* Return whether parameter was local (localparam, implicit genvar etc)
* or not.
*
* ivl_parameter_file
* ivl_parameter_lineno
* Returns the file and line where this parameter is defined
@ -1575,7 +1580,7 @@ extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net);
extern const char* ivl_parameter_basename(ivl_parameter_t net);
extern ivl_scope_t ivl_parameter_scope(ivl_parameter_t net);
extern ivl_expr_t ivl_parameter_expr(ivl_parameter_t net);
extern int ivl_parameter_local(ivl_parameter_t net);
extern const char* ivl_parameter_file(ivl_parameter_t net);
extern unsigned ivl_parameter_lineno(ivl_parameter_t net);
@ -1738,6 +1743,12 @@ extern const char* ivl_scope_basename(ivl_scope_t net);
extern unsigned ivl_scope_params(ivl_scope_t net);
extern ivl_parameter_t ivl_scope_param(ivl_scope_t net, unsigned idx);
extern ivl_scope_t ivl_scope_parent(ivl_scope_t net);
extern unsigned ivl_scope_mod_module_ports(ivl_scope_t net);
extern const char *ivl_scope_mod_module_port_name(ivl_scope_t net, unsigned idx );
extern ivl_signal_port_t ivl_scope_mod_module_port_type(ivl_scope_t net, unsigned idx );
extern unsigned ivl_scope_mod_module_port_width(ivl_scope_t net, unsigned idx );
extern unsigned ivl_scope_ports(ivl_scope_t net);
extern ivl_signal_t ivl_scope_port(ivl_scope_t net, unsigned idx);
extern ivl_nexus_t ivl_scope_mod_port(ivl_scope_t net, unsigned idx);
@ -1878,6 +1889,7 @@ extern int ivl_signal_msb(ivl_signal_t net) __attribute__((deprecated));
extern int ivl_signal_lsb(ivl_signal_t net) __attribute__((deprecated));
extern unsigned ivl_signal_width(ivl_signal_t net);
extern ivl_signal_port_t ivl_signal_port(ivl_signal_t net);
extern int ivl_signal_module_port_index(ivl_signal_t net);
extern int ivl_signal_signed(ivl_signal_t net);
extern int ivl_signal_integer(ivl_signal_t net);
extern int ivl_signal_local(ivl_signal_t net);

View File

@ -44,6 +44,10 @@ else
INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
endif
LDRELOCFLAGS = @LDRELOCFLAGS@
LDTARGETFLAGS = @LDTARGETFLAGS@
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@
CFLAGS = @WARNING_FLAGS@ @CFLAGS@
@ -87,7 +91,7 @@ stamp-config-h: $(srcdir)/config.h.in ../config.status
config.h: stamp-config-h
libveriuser.o: $O
$(LD) -r -o $@ $O
$(LD) $(LDTARGETFLAGS) -r -o $@ $O
libveriuser.a: libveriuser.o
rm -f $@

10
main.cc
View File

@ -784,7 +784,13 @@ int main(int argc, char*argv[])
#if defined(TRAP_SIGINT_FOR_DEBUG)
signal(SIGINT, &signals_handler);
#endif
if( ::getenv("IVL_WAIT_FOR_DEBUGGER") != 0 ) {
fprintf( stderr, "Waiting for debugger...\n");
bool debugger_release = false;
while( !debugger_release ) {
sleep(1);
}
}
library_suff.push_back(strdup(".v"));
// Start the module list with the base system module.
@ -839,6 +845,8 @@ int main(int argc, char*argv[])
cout << COPYRIGHT << endl << endl;
cout << NOTICE << endl;
cout << " FLAGS DLL " << flags["DLL"] << endl;
dll_target_obj.test_version(flags["DLL"]);
return 0;

View File

@ -114,14 +114,10 @@ void NetScope::set_line(perm_string file, perm_string def_file,
def_lineno_ = def_lineno;
}
/*
* This is the full-featured version of set_parameter. It is used for
* adding parameter, localparam, and specparam declarations to the
* parameter list.
*/
void NetScope::set_parameter(perm_string key, bool is_annotatable,
PExpr*val, ivl_variable_type_t type__,
PExpr*msb, PExpr*lsb, bool signed_flag,
bool local_flag,
NetScope::range_t*range_list,
const LineInfo&file_line)
{
@ -135,6 +131,7 @@ void NetScope::set_parameter(perm_string key, bool is_annotatable,
ref.msb = 0;
ref.lsb = 0;
ref.signed_flag = signed_flag;
ref.local_flag = local_flag;
ivl_assert(file_line, ref.range == 0);
ref.range = range_list;
ref.val = 0;
@ -370,23 +367,51 @@ perm_string NetScope::module_name() const
return module_name_;
}
void NetScope::add_module_port(NetNet*port)
void NetScope::set_num_ports(unsigned int num_ports)
{
assert(type_ == MODULE);
ports_.push_back(port);
assert(type_ == MODULE);
assert( ports_.size() == 0 );
ports_.resize( num_ports );
}
unsigned NetScope::module_ports() const
void NetScope::add_module_port_net(NetNet*subport)
{
assert(type_ == MODULE);
return ports_.size();
port_nets.push_back(subport);
}
NetNet* NetScope::module_port(unsigned idx) const
void NetScope::add_module_port_info( unsigned idx, perm_string name, PortType::Enum ptype,
unsigned long width )
{
assert(type_ == MODULE);
assert(idx < ports_.size());
return ports_[idx];
PortInfo &info = ports_[idx];
info.name = name;
info.type = ptype;
info.width = width;
}
unsigned NetScope::module_port_nets() const
{
assert(type_ == MODULE);
return port_nets.size();
}
const std::vector<PortInfo> & NetScope::module_port_info() const
{
assert(type_ == MODULE);
return ports_;
}
NetNet* NetScope::module_port_net(unsigned idx) const
{
assert(type_ == MODULE);
assert(idx < port_nets.size());
return port_nets[idx];
}
void NetScope::time_unit(int val)

View File

@ -447,12 +447,27 @@ const Link& NetDelaySrc::condit_pin() const
return pin(pin_count()-1);
}
PortType::Enum PortType::merged( Enum lhs, Enum rhs )
{
if( lhs == NOT_A_PORT || rhs == NOT_A_PORT )
return NOT_A_PORT;
if( lhs == PIMPLICIT )
return rhs;
if( rhs == PIMPLICIT )
return lhs;
if( lhs == rhs ) {
return lhs;
}
return PINOUT;
}
NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
: NetObj(s, n, 1),
type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE),
signed_(false), isint_(false), is_scalar_(false), local_flag_(false),
enumeration_(0), struct_type_(0), discipline_(0),
eref_count_(0), lref_count_(0)
eref_count_(0), lref_count_(0),
port_index_(-1)
{
assert(s);
assert(npins>0);
@ -698,6 +713,17 @@ void NetNet::port_type(NetNet::PortType t)
port_type_ = t;
}
int NetNet::get_module_port_index() const
{
return port_index_;
}
void NetNet::set_module_port_index(unsigned idx)
{
port_index_ = idx;
assert( port_index_ >= 0 );
}
ivl_variable_type_t NetNet::data_type() const
{
return data_type_;

View File

@ -556,14 +556,42 @@ class NetDelaySrc : public NetObj {
* anything and they are not a data sink, per se. The pins follow the
* values on the nexus.
*/
class NetNet : public NetObj {
class PortType
{
public:
enum Enum { NOT_A_PORT, PIMPLICIT, PINPUT, POUTPUT, PINOUT, PREF };
/*
* Merge Port types (used to construct a sane combined port-type
* for module ports with complex defining expressions).
*
*/
static Enum merged( Enum lhs, Enum rhs );
};
/*
* Information on actual ports (rather than port-connected signals) of
* module.
* N.b. must be POD as passed through a "C" interface in the t-dll-api.
*/
struct PortInfo
{
PortType::Enum type;
unsigned long width;
perm_string name;
};
class NetNet : public NetObj, public PortType {
public:
enum Type { NONE, IMPLICIT, IMPLICIT_REG, INTEGER, WIRE, TRI, TRI1,
SUPPLY0, SUPPLY1, WAND, TRIAND, TRI0, WOR, TRIOR, REG,
UNRESOLVED_WIRE };
enum PortType { NOT_A_PORT, PIMPLICIT, PINPUT, POUTPUT, PINOUT, PREF };
typedef PortType::Enum PortType;
public:
// The width in this case is a shorthand for ms=width-1 and
@ -592,6 +620,11 @@ class NetNet : public NetObj {
PortType port_type() const;
void port_type(PortType t);
// If this net net is a port (i.e. a *sub*port net of a module port)
// its port index is number of the module it connects through
int get_module_port_index() const; // -1 Not connected to port...
void set_module_port_index(unsigned idx);
ivl_variable_type_t data_type() const;
void data_type(ivl_variable_type_t t);
@ -713,6 +746,7 @@ class NetNet : public NetObj {
std::vector<bool> lref_mask_;
vector<class NetDelaySrc*> delay_paths_;
int port_index_;
};
extern std::ostream&operator << (std::ostream&out, const std::list<netrange_t>&rlist);
@ -747,6 +781,7 @@ class NetScope : public Attrib {
void set_parameter(perm_string name, bool is_annotatable,
PExpr*val, ivl_variable_type_t type,
PExpr*msb, PExpr*lsb, bool signed_flag,
bool local_flag,
NetScope::range_t*range_list,
const LineInfo&file_line);
void set_parameter(perm_string name, NetExpr*val,
@ -878,9 +913,18 @@ class NetScope : public Attrib {
perm_string module_name() const;
/* If the scope is a module then it may have ports that we need
* to keep track of. */
void add_module_port(NetNet*port);
unsigned module_ports() const;
NetNet*module_port(unsigned idx) const;
void set_num_ports(unsigned int num_ports);
void add_module_port_net(NetNet*port);
unsigned module_port_nets() const;
NetNet*module_port_net(unsigned idx) const;
void add_module_port_info( unsigned idx,
perm_string name, // May be "" for undeclared port
PortType::Enum type,
unsigned long width );
const std::vector<PortInfo> &module_port_info() const;
/* Scopes have their own time units and time precision. The
unit and precision are given as power of 10, i.e., -3 is
@ -951,6 +995,7 @@ class NetScope : public Attrib {
param_expr_t() : msb_expr(0), lsb_expr(0), val_expr(0), val_scope(0),
solving(false), is_annotatable(false),
type(IVL_VT_NO_TYPE), signed_flag(false),
local_flag(false),
msb(0), lsb(0), range(0), val(0) { }
// Source expressions
PExpr*msb_expr;
@ -965,6 +1010,7 @@ class NetScope : public Attrib {
// Type information
ivl_variable_type_t type;
bool signed_flag;
bool local_flag;
NetExpr*msb;
NetExpr*lsb;
// range constraints
@ -1018,7 +1064,10 @@ class NetScope : public Attrib {
typedef std::map<perm_string,NetNet*>::const_iterator signals_map_iter_t;
std::map <perm_string,NetNet*> signals_map_;
perm_string module_name_;
vector<NetNet*>ports_;
vector<NetNet*> port_nets;
vector<PortInfo> ports_;
union {
NetTaskDef*task_;
NetFuncDef*func_;

View File

@ -1681,6 +1681,13 @@ extern "C" const char* ivl_parameter_basename(ivl_parameter_t net)
return net->basename;
}
extern "C" int ivl_parameter_local(ivl_parameter_t net)
{
assert(net);
return net->local;
}
extern "C" ivl_expr_t ivl_parameter_expr(ivl_parameter_t net)
{
assert(net);
@ -1979,6 +1986,40 @@ extern "C" ivl_scope_t ivl_scope_parent(ivl_scope_t net)
return net->parent;
}
extern "C" unsigned ivl_scope_mod_module_ports(ivl_scope_t net)
{
assert(net);
assert (net->type_ == IVL_SCT_MODULE );
return static_cast<unsigned>(net->module_ports_info.size());
}
extern "C" const char *ivl_scope_mod_module_port_name(ivl_scope_t net, unsigned idx )
{
assert(net);
assert (net->type_ == IVL_SCT_MODULE );
assert( idx < net->module_ports_info.size());
return net->module_ports_info[idx].name;
}
extern "C" ivl_signal_port_t ivl_scope_mod_module_port_type(ivl_scope_t net, unsigned idx )
{
switch( net->module_ports_info[idx].type )
{
case PortType::PINPUT : return IVL_SIP_INPUT;
case PortType::POUTPUT : return IVL_SIP_OUTPUT;
case PortType::PINOUT : return IVL_SIP_INOUT;
default : return IVL_SIP_NONE;
}
}
extern "C" unsigned ivl_scope_mod_module_port_width(ivl_scope_t net, unsigned idx )
{
return net->module_ports_info[idx].width;
}
extern "C" unsigned ivl_scope_ports(ivl_scope_t net)
{
assert(net);
@ -2198,6 +2239,11 @@ extern "C" ivl_signal_port_t ivl_signal_port(ivl_signal_t net)
return net->port_;
}
extern "C" int ivl_signal_module_port_index(ivl_signal_t net)
{
return net->module_port_index_;
}
extern "C" int ivl_signal_local(ivl_signal_t net)
{
return net->local_;

View File

@ -478,6 +478,7 @@ void dll_target::make_scope_parameters(ivl_scope_t scop, const NetScope*net)
assert(idx < scop->nparam_);
ivl_parameter_t cur_par = scop->param_ + idx;
cur_par->basename = (*cur_pit).first;
cur_par->local = cur_pit->second.local_flag;
cur_par->scope = scop;
FILE_NAME(cur_par, &((*cur_pit).second));
@ -550,13 +551,14 @@ void dll_target::add_root(ivl_design_s &des__, const NetScope *s)
root_->attr = fill_in_attributes(s);
root_->is_auto = 0;
root_->is_cell = s->is_cell();
root_->ports = s->module_ports();
root_->ports = s->module_port_nets();
if (root_->ports > 0) {
root_->u_.net = new NetNet*[root_->ports];
for (unsigned idx = 0; idx < root_->ports; idx += 1) {
root_->u_.net[idx] = s->module_port(idx);
root_->u_.net[idx] = s->module_port_net(idx);
}
}
root_->module_ports_info = s->module_port_info();
des__.nroots_++;
if (des__.roots_)
@ -2299,14 +2301,16 @@ void dll_target::scope(const NetScope*net)
case NetScope::MODULE:
scop->type_ = IVL_SCT_MODULE;
scop->tname_ = net->module_name();
scop->ports = net->module_ports();
scop->ports = net->module_port_nets();
if (scop->ports > 0) {
scop->u_.net = new NetNet*[scop->ports];
for (unsigned idx = 0; idx < scop->ports; idx += 1) {
scop->u_.net[idx] = net->module_port(idx);
scop->u_.net[idx] = net->module_port_net(idx);
}
}
scop->module_ports_info = net->module_port_info();
break;
case NetScope::TASK: {
const NetTaskDef*def = net->task_def();
if (def == 0) {
@ -2425,6 +2429,8 @@ void dll_target::signal(const NetNet*net)
break;
}
obj->module_port_index_ = net->get_module_port_index();
switch (net->type()) {
case NetNet::REG:

View File

@ -584,6 +584,7 @@ struct ivl_parameter_s {
perm_string basename;
ivl_scope_t scope;
ivl_expr_t value;
bool local;
perm_string file;
unsigned lineno;
};
@ -647,6 +648,10 @@ struct ivl_scope_s {
unsigned is_cell;
// Ports of Module scope (just introspection data for VPI) - actual connections
// are nets defined in u_.net (may be > 1 per module port)
std::vector<PortInfo> module_ports_info;
unsigned ports;
union {
ivl_signal_t*port;
@ -672,6 +677,7 @@ struct ivl_scope_s {
struct ivl_signal_s {
ivl_signal_type_t type_;
ivl_signal_port_t port_;
int module_port_index_;
ivl_variable_type_t data_type;
ivl_discipline_t discipline;
perm_string file;
@ -709,6 +715,7 @@ struct ivl_signal_s {
unsigned nattr;
};
/*
* The ivl_statement_t represents any statement. The type of statement
* is defined by the ivl_statement_type_t enumeration. Given the type,

View File

@ -417,6 +417,36 @@ const char*draw_input_from_net(ivl_nexus_t nex)
}
/* Create flag string for port nature */
static const char *port_type_str( ivl_signal_port_t ptype )
{
switch( ptype )
{
case IVL_SIP_INPUT :
return "INPUT";
case IVL_SIP_OUTPUT :
return "OUTPUT";
case IVL_SIP_INOUT :
return "INOUT";
case IVL_SIP_NONE :
default :
return "NOT_PORT";
}
}
/* Create flag string for et nature" port nature / localness */
static const char *port_nature_flag_str( ivl_signal_t sig )
{
return port_type_str( ivl_signal_port(sig) );
}
static const char *local_flag_str( ivl_signal_t sig )
{
return ivl_signal_local(sig)? "*" : "";
}
/*
* This function draws a reg/int/variable in the scope. This is a very
* simple device to draw as there are no inputs to connect so no need
@ -442,9 +472,9 @@ static void draw_reg_in_scope(ivl_signal_t sig)
break;
}
const char*datatype_flag = ivl_signal_integer(sig) ? "/i" :
const char *datatype_flag = ivl_signal_integer(sig) ? "/i" :
ivl_signal_signed(sig)? "/s" : "";
const char*local_flag = ivl_signal_local(sig)? "*" : "";
const char *local_flag = local_flag_str(sig);
switch (ivl_signal_data_type(sig)) {
case IVL_VT_BOOL:
@ -477,7 +507,7 @@ static void draw_reg_in_scope(ivl_signal_t sig)
fprintf(vvp_out, "v%p_0 .var%s %s\"%s\", %d %d;%s\n",
sig, datatype_flag, local_flag,
vvp_mangle_name(ivl_signal_basename(sig)), msb, lsb,
ivl_signal_local(sig)? " Local signal" : "");
ivl_signal_local(sig)? " Local signal" : "" );
}
}
@ -506,7 +536,8 @@ static void draw_net_in_scope(ivl_signal_t sig)
}
const char*datatype_flag = ivl_signal_signed(sig)? "/s" : "";
const char*local_flag = ivl_signal_local(sig)? "*" : "";
const char *local_flag = local_flag_str(sig);
unsigned iword;
switch (ivl_signal_data_type(sig)) {
@ -562,7 +593,7 @@ static void draw_net_in_scope(ivl_signal_t sig)
sig, iword, vec8, datatype_flag, sig,
iword, msb, lsb, driver,
nex_data->drivers_count,
strength_aware_flag?", strength-aware":"");
strength_aware_flag?", strength-aware":"" );
} else if (ivl_signal_local(sig) && ivl_scope_is_auto(ivl_signal_scope(sig))) {
assert(word_count == 1);
@ -578,13 +609,13 @@ static void draw_net_in_scope(ivl_signal_t sig)
/* If this is an isolated word, it uses its
own name. */
assert(word_count == 1);
fprintf(vvp_out, "v%p_%u .net%s%s %s\"%s\", %d %d, %s;"
" %u drivers%s\n",
fprintf(vvp_out, "v%p_%u .net%s%s %s\"%s\", %d %d, %s; "
" %u drivers %s\n",
sig, iword, vec8, datatype_flag, local_flag,
vvp_mangle_name(ivl_signal_basename(sig)),
msb, lsb, driver,
nex_data->drivers_count,
strength_aware_flag?", strength-aware":"");
strength_aware_flag?", strength-aware":"" );
}
nex_data->net = sig;
nex_data->net_word = iword;
@ -600,7 +631,7 @@ static void draw_net_in_scope(ivl_signal_t sig)
if (word_count == ivl_signal_array_count(nex_data->net)) {
if (iword == 0) {
fprintf(vvp_out, "v%p .array \"%s\", v%p; Alias to %s\n",
fprintf(vvp_out, "v%p .array \"%s\", v%p; Alias to %s \n",
sig, vvp_mangle_name(ivl_signal_basename(sig)),
nex_data->net,
ivl_signal_basename(nex_data->net));
@ -615,7 +646,7 @@ static void draw_net_in_scope(ivl_signal_t sig)
sig,
vvp_mangle_name(ivl_signal_basename(sig)),
swapped ? first : last,
swapped ? last : first);
swapped ? last : first );
}
fprintf(vvp_out, "v%p_%u .alias%s v%p %u, %d %d, "
@ -637,7 +668,7 @@ static void draw_net_in_scope(ivl_signal_t sig)
if (strength_aware_flag)
vec8 = "8";
fprintf(vvp_out, "v%p_%u .net%s%s %s\"%s\", %d %d, %s;"
fprintf(vvp_out, "v%p_%u .net%s%s %s\"%s\", %d %d, %s; "
" alias, %u drivers%s\n",
sig, iword, vec8, datatype_flag, local_flag,
vvp_mangle_name(ivl_signal_basename(sig)),
@ -2075,6 +2106,20 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
}
}
static const char *vvp_port_info_type_str(ivl_signal_port_t ptype)
{
switch( ptype )
{
case IVL_SIP_INPUT : return "/INPUT";
case IVL_SIP_OUTPUT : return "/OUTPUT";
case IVL_SIP_INOUT : return "/INOUT";
case IVL_SIP_NONE : return "/NODIR";
default :
abort(); // NO SUPPORT FOR ANYTHING ELSE YET...
}
}
int draw_scope(ivl_scope_t net, ivl_scope_t parent)
{
unsigned idx;
@ -2109,20 +2154,36 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
fprintf(vvp_out, " .timescale %d %d;\n", ivl_scope_time_units(net),
ivl_scope_time_precision(net));
if( ivl_scope_type(net) == IVL_SCT_MODULE ) {
// Port data for VPI: needed for vpiPorts property of vpiModule
for( idx = 0; idx < ivl_scope_mod_module_ports(net); ++idx ) {
const char *name = ivl_scope_mod_module_port_name(net,idx);
ivl_signal_port_t ptype = ivl_scope_mod_module_port_type(net,idx);
unsigned width = ivl_scope_mod_module_port_width(net,idx);
if( name == 0 )
name = "";
fprintf( vvp_out, " .port_info %d %s %u \"%s\"\n",
idx, vvp_port_info_type_str(ptype), width, name );
}
}
for (idx = 0 ; idx < ivl_scope_params(net) ; idx += 1) {
ivl_parameter_t par = ivl_scope_param(net, idx);
ivl_expr_t pex = ivl_parameter_expr(par);
switch (ivl_expr_type(pex)) {
case IVL_EX_STRING:
fprintf(vvp_out, "P_%p .param/str \"%s\" %d %d, \"%s\";\n",
fprintf(vvp_out, "P_%p .param/str \"%s\" %d %d %d, \"%s\";\n",
par, ivl_parameter_basename(par),
ivl_parameter_local(par),
ivl_file_table_index(ivl_parameter_file(par)),
ivl_parameter_lineno(par),
ivl_expr_string(pex));
break;
case IVL_EX_NUMBER:
fprintf(vvp_out, "P_%p .param/l \"%s\" %d %d, %sC4<",
fprintf(vvp_out, "P_%p .param/l \"%s\" %d %d %d, %sC4<",
par, ivl_parameter_basename(par),
ivl_parameter_local(par),
ivl_file_table_index(ivl_parameter_file(par)),
ivl_parameter_lineno(par),
ivl_expr_signed(pex)? "+":"");
@ -2136,8 +2197,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
break;
case IVL_EX_REALNUM:
{ char *res = draw_Cr_to_string(ivl_expr_dvalue(pex));
fprintf(vvp_out, "P_%p .param/real \"%s\" %d %d, %s; "
fprintf(vvp_out, "P_%p .param/real \"%s\" %d %d %d, %s; "
"value=%#g\n", par, ivl_parameter_basename(par),
ivl_parameter_local(par),
ivl_file_table_index(ivl_parameter_file(par)),
ivl_parameter_lineno(par), res,
ivl_expr_dvalue(pex));

View File

@ -43,6 +43,7 @@ EXTERN_C_START
# include <stdarg.h>
# include <stdio.h>
# include <stdarg.h>
# include "_pli_types.h"
#define ICARUS_VPI_CONST
@ -286,6 +287,7 @@ typedef struct t_vpi_delay {
#define vpiParameter 41
#define vpiPartSelect 42
#define vpiPathTerm 43
#define vpiPort 44
#define vpiRealVar 47
#define vpiReg 48
#define vpiSysFuncCall 56
@ -325,6 +327,14 @@ typedef struct t_vpi_delay {
#define vpiTimePrecision 12
#define vpiDefFile 15
#define vpiDefLineNo 16
#define vpiDirection 20 /* direction of port: */
# define vpiInput 1
# define vpiOutput 2
# define vpiInout 3
# define vpiMixedIO 4 /* Not currently output */
# define vpiNoDirection 5
#define vpiNetType 22
# define vpiWire 1
# define vpiWand 2
@ -338,6 +348,7 @@ typedef struct t_vpi_delay {
# define vpiSupply1 10
# define vpiSupply0 11
#define vpiArray 28
#define vpiPortIndex 29
#define vpiEdge 36
# define vpiNoEdge 0x00 /* No edge */
# define vpiEdge01 0x01 /* 0 --> 1 */
@ -371,6 +382,7 @@ typedef struct t_vpi_delay {
#define vpiAutomatic 50
#define vpiConstantSelect 53
#define vpiSigned 65
#define vpiLocalParam 70
/* IVL private properties, also see vvp/vpi_priv.h for other properties */
#define _vpiNexusId 0x1000000
/* used in vvp/vpi_priv.h 0x1000001 */

View File

@ -17,6 +17,9 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "config.h"
# include "delay.h"
# include "arith.h"
# include "compile.h"
# include "logic.h"
@ -28,6 +31,7 @@
# include "vpi_priv.h"
# include "parse_misc.h"
# include "statistics.h"
# include "schedule.h"
# include <iostream>
# include <list>
# include <cstdlib>
@ -610,7 +614,7 @@ static void compile_array_lookup(struct vvp_code_s*code, char*label)
resolv_submit(res);
}
static list<struct __vpiSysTaskCall*> scheduled_compiletf;
static std::list<struct __vpiSysTaskCall*> scheduled_compiletf;
void compile_compiletf(struct __vpiSysTaskCall*obj)
{
@ -859,7 +863,7 @@ void input_connect(vvp_net_t*fdx, unsigned port, char*label)
void inputs_connect(vvp_net_t*fdx, unsigned argc, struct symb_s*argv)
{
if (argc > 4) {
cerr << "XXXX argv[0] = " << argv[0].text << endl;
std::cerr << "XXXX argv[0] = " << argv[0].text << std::endl;
}
assert(argc <= 4);
@ -1808,11 +1812,12 @@ void compile_thread(char*start_sym, char*flag)
}
void compile_param_logic(char*label, char*name, char*value, bool signed_flag,
bool local_flag,
long file_idx, long lineno)
{
vvp_vector4_t value4 = c4string_to_vector4(value);
vpiHandle obj = vpip_make_binary_param(name, value4, signed_flag,
file_idx, lineno);
local_flag, file_idx, lineno);
compile_vpi_symbol(label, obj);
vpip_attach_to_current_scope(obj);
@ -1821,10 +1826,11 @@ void compile_param_logic(char*label, char*name, char*value, bool signed_flag,
}
void compile_param_string(char*label, char*name, char*value,
bool local_flag,
long file_idx, long lineno)
{
// name and value become owned bi vpip_make_string_param
vpiHandle obj = vpip_make_string_param(name, value, file_idx, lineno);
vpiHandle obj = vpip_make_string_param(name, value, local_flag, file_idx, lineno);
compile_vpi_symbol(label, obj);
vpip_attach_to_current_scope(obj);
@ -1832,10 +1838,11 @@ void compile_param_string(char*label, char*name, char*value,
}
void compile_param_real(char*label, char*name, char*value,
bool local_flag,
long file_idx, long lineno)
{
double dvalue = crstring_to_double(value);
vpiHandle obj = vpip_make_real_param(name, dvalue, file_idx, lineno);
vpiHandle obj = vpip_make_real_param(name, dvalue, local_flag, file_idx, lineno);
compile_vpi_symbol(label, obj);
vpip_attach_to_current_scope(obj);

View File

@ -254,11 +254,13 @@ extern void compile_vpi_symbol(const char*label, vpiHandle obj);
extern void compile_vpi_lookup(vpiHandle *objref, char*label);
extern void compile_param_string(char*label, char*name, char*value,
bool local_flag,
long file_idx, long lineno);
extern void compile_param_logic(char*label, char*name, char*value,
bool signed_flag,
bool signed_flag, bool local_flag,
long file_idx, long lineno);
extern void compile_param_real(char*label, char*name, char*value,
bool local_flag,
long file_idx, long lineno);
/*
@ -456,6 +458,17 @@ extern void compile_variable(char*label, char*name,
extern void compile_var_real(char*label, char*name,
int msb, int lsb);
/*
* This function is used to create a scope port
* Current ONLY module ports are supported and ports exist purely
* as meta-data for VPI queries (i.e. there is NO corresponding net etc)
* as elaboration internally eliminates port-nets by directly connecting
* nets connected through module ports.
*/
extern void compile_port_info( unsigned index, int vpi_port_type, unsigned width, const char *name );
/*
* The compile_net function is called to create a .net vector with a
* given name.

View File

@ -19,6 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include <stddef.h>
# include "vvp_net.h"
# include "schedule.h"

View File

@ -171,6 +171,7 @@ static char* strdupnew(char const *str)
".part/v" { return K_PART_V; }
".part/v.s" { return K_PART_V_S; }
".port" { return K_PORT; }
".port_info" { return K_PORT_INFO; }
".reduce/and" { return K_REDUCE_AND; }
".reduce/or" { return K_REDUCE_OR; }
".reduce/xor" { return K_REDUCE_XOR; }
@ -263,6 +264,12 @@ static char* strdupnew(char const *str)
assert(yylval.text);
return T_SYMBOL; }
"/INPUT" { return K_PORT_INPUT; }
"/OUTPUT" { return K_PORT_OUTPUT; }
"/INOUT" { return K_PORT_INOUT; }
"/MIXED" { return K_PORT_MIXED; }
"/NODIR" { return K_PORT_NODIR; }
/* Symbols are pretty much what is left. They are used to refer to
labels so the rule must match a string that a label would match. */
[.$_a-zA-Z\\]([.$_a-zA-Z\\0-9/]|(\\.))* {

View File

@ -284,6 +284,16 @@ int main(int argc, char*argv[])
vpip_module_path[0] = strdup(basepath);
#endif
if( ::getenv("VVP_WAIT_FOR_DEBUGGER") != 0 ) {
fprintf( stderr, "Waiting for debugger...\n");
bool debugger_release = false;
while( !debugger_release ) {
sleep(1);
}
}
/* For non-interactive runs we do not want to run the interactive
* debugger, so make $stop just execute a $finish. */
stop_is_finish = false;

View File

@ -68,6 +68,8 @@ static struct __vpiModPath*modpath_dst = 0;
vpiHandle vpi;
vvp_delay_t*cdelay;
int vpi_enum;
};
%token K_A K_ALIAS K_ALIAS_R K_APV
@ -84,7 +86,7 @@ static struct __vpiModPath*modpath_dst = 0;
%token K_EXPORT K_EXTEND_S K_FUNCTOR K_IMPORT K_ISLAND K_MODPATH
%token K_NET K_NET_S K_NET_R K_NET_2S K_NET_2U K_NET8 K_NET8_S
%token K_PARAM_STR K_PARAM_L K_PARAM_REAL K_PART K_PART_PV
%token K_PART_V K_PART_V_S K_PORT K_PV K_REDUCE_AND K_REDUCE_OR K_REDUCE_XOR
%token K_PART_V K_PART_V_S K_PORT K_PORT_INFO K_PV K_REDUCE_AND K_REDUCE_OR K_REDUCE_XOR
%token K_REDUCE_NAND K_REDUCE_NOR K_REDUCE_XNOR K_REPEAT
%token K_RESOLV K_SCOPE K_SFUNC K_SFUNC_E K_SHIFTL K_SHIFTR K_SHIFTRS
%token K_THREAD K_TIMESCALE K_TRAN K_TRANIF0 K_TRANIF1 K_TRANVP
@ -95,6 +97,7 @@ static struct __vpiModPath*modpath_dst = 0;
%token K_disable K_fork
%token K_ivl_version K_ivl_delay_selection
%token K_vpi_module K_vpi_time_precision K_file_names K_file_line
%token K_PORT_INPUT K_PORT_OUTPUT K_PORT_INOUT K_PORT_MIXED K_PORT_NODIR
%token <text> T_INSTR
%token <text> T_LABEL
@ -104,6 +107,7 @@ static struct __vpiModPath*modpath_dst = 0;
%token <vect> T_VECTOR
%type <flag> local_flag
%type <vpi_enum> port_type
%type <numb> signed_t_number
%type <symb> symbol symbol_opt
%type <symbv> symbols symbols_net
@ -628,6 +632,7 @@ statement
T_NUMBER T_NUMBER T_NUMBER ',' T_SYMBOL ';'
{ compile_scope_decl($1, $3, $5, $6, $14, $7, $8, $10, $11, $12); }
/* Legacy declaration that does not have `celldefine information. */
| T_LABEL K_SCOPE T_SYMBOL ',' T_STRING T_STRING T_NUMBER T_NUMBER ','
@ -649,6 +654,10 @@ statement
{ compile_scope_recall($2); }
/* Port information for scopes... currently this is just meta-data for VPI queries */
| K_PORT_INFO T_NUMBER port_type T_NUMBER T_STRING
{ compile_port_info( $2 /* port_index */, $3, $4 /* width */, $5 /*&name */ ); }
| K_TIMESCALE T_NUMBER T_NUMBER';'
{ compile_timescale($2, $3); }
| K_TIMESCALE '-' T_NUMBER T_NUMBER';'
@ -758,17 +767,17 @@ statement
/* Parameter statements come in a few simple forms. The most basic
is the string parameter. */
| T_LABEL K_PARAM_STR T_STRING T_NUMBER T_NUMBER',' T_STRING ';'
{ compile_param_string($1, $3, $7, $4, $5); }
| T_LABEL K_PARAM_STR T_STRING T_NUMBER T_NUMBER T_NUMBER',' T_STRING ';'
{ compile_param_string($1, $3, $8, $4, $5, $6); }
| T_LABEL K_PARAM_L T_STRING T_NUMBER T_NUMBER',' T_SYMBOL ';'
{ compile_param_logic($1, $3, $7, false, $4, $5); }
| T_LABEL K_PARAM_L T_STRING T_NUMBER T_NUMBER T_NUMBER',' T_SYMBOL ';'
{ compile_param_logic($1, $3, $8, false, $4, $5, $6); }
| T_LABEL K_PARAM_L T_STRING T_NUMBER T_NUMBER',' '+' T_SYMBOL ';'
{ compile_param_logic($1, $3, $8, true, $4, $5); }
| T_LABEL K_PARAM_L T_STRING T_NUMBER T_NUMBER T_NUMBER',' '+' T_SYMBOL ';'
{ compile_param_logic($1, $3, $9, true, $4, $5, $6 ); }
| T_LABEL K_PARAM_REAL T_STRING T_NUMBER T_NUMBER',' T_SYMBOL ';'
{ compile_param_real($1, $3, $7, $4, $5); }
| T_LABEL K_PARAM_REAL T_STRING T_NUMBER T_NUMBER T_NUMBER',' T_SYMBOL ';'
{ compile_param_real($1, $3, $8, $4, $5, $6); }
/* Islands */
@ -1049,6 +1058,14 @@ modpath_src_list
| modpath_src_list ',' modpath_src
;
port_type
: K_PORT_INPUT { $$ = vpiInput; }
| K_PORT_OUTPUT { $$ = vpiOutput; }
| K_PORT_INOUT { $$ = vpiInout; }
| K_PORT_MIXED { $$ = vpiMixedIO; }
| K_PORT_NODIR { $$ = vpiNoDirection; }
;
modpath_src
: symbol '(' numbers ')' symbol
{ compile_modpath_src(modpath_dst, 0, $1, $3, 0, $5, false); }

View File

@ -86,6 +86,7 @@ struct argv_s {
char **syms;
};
extern void argv_init(struct argv_s*obj);
extern void argv_add(struct argv_s*obj, vpiHandle);
extern void argv_sym_add(struct argv_s*obj, char *);

View File

@ -63,7 +63,7 @@ struct event_s {
void event_s::single_step_display(void)
{
cerr << "event_s: Step into event " << typeid(*this).name() << endl;
std::cerr << "event_s: Step into event " << typeid(*this).name() << std::endl;
}
struct event_time_s {

View File

@ -258,6 +258,7 @@ class __vpiStringParam : public __vpiStringConst {
vpiHandle vpi_handle(int code);
struct __vpiScope* scope;
bool local_flag;
unsigned file_idx;
unsigned lineno;
private:
@ -280,10 +281,16 @@ int __vpiStringParam::get_type_code(void) const
int __vpiStringParam::vpi_get(int code)
{
if (code == vpiLineNo)
return lineno;
switch (code) {
case vpiLineNo :
return lineno;
return __vpiStringConst::vpi_get(code);
case vpiLocalParam :
return local_flag;
default :
return __vpiStringConst::vpi_get(code);
}
}
@ -312,10 +319,11 @@ vpiHandle __vpiStringParam::vpi_handle(int code)
}
vpiHandle vpip_make_string_param(char*name, char*text,
long file_idx, long lineno)
bool local_flag, long file_idx, long lineno)
{
__vpiStringParam*obj = new __vpiStringParam(text, name);
obj->scope = vpip_peek_current_scope();
obj->local_flag = local_flag;
obj->file_idx = (unsigned) file_idx;
obj->lineno = (unsigned) lineno;
@ -449,6 +457,7 @@ struct __vpiBinaryParam : public __vpiBinaryConst {
struct __vpiScope*scope;
unsigned file_idx;
unsigned lineno;
bool local_flag;
private:
char*basename_;
};
@ -469,10 +478,16 @@ int __vpiBinaryParam::get_type_code(void) const
int __vpiBinaryParam::vpi_get(int code)
{
if (code == vpiLineNo)
return lineno;
switch (code) {
case vpiLineNo :
return lineno;
return __vpiBinaryConst::vpi_get(code);
case vpiLocalParam :
return local_flag;
default :
return __vpiBinaryConst::vpi_get(code);
}
}
char*__vpiBinaryParam::vpi_get_str(int code)
@ -500,13 +515,14 @@ vpiHandle __vpiBinaryParam::vpi_handle(int code)
vpiHandle vpip_make_binary_param(char*name, const vvp_vector4_t&bits,
bool signed_flag,
bool signed_flag, bool local_flag,
long file_idx, long lineno)
{
struct __vpiBinaryParam*obj = new __vpiBinaryParam(bits, name);
obj->signed_flag = signed_flag? 1 : 0;
obj->sized_flag = 0;
obj->local_flag = local_flag;
obj->scope = vpip_peek_current_scope();
obj->file_idx = (unsigned) file_idx;
obj->lineno = (unsigned) lineno;
@ -662,6 +678,7 @@ struct __vpiRealParam : public __vpiRealConst {
vpiHandle vpi_handle(int code);
struct __vpiScope* scope;
bool local_flag;
unsigned file_idx;
unsigned lineno;
private:
@ -686,10 +703,16 @@ int __vpiRealParam::get_type_code(void) const
int __vpiRealParam::vpi_get(int code)
{
if (code == vpiLineNo)
return lineno;
switch (code) {
case vpiLineNo :
return lineno;
return __vpiRealConst::vpi_get(code);
case vpiLocalParam :
return local_flag;
default :
return __vpiRealConst::vpi_get(code);
}
}
char* __vpiRealParam::vpi_get_str(int code)
@ -716,11 +739,12 @@ vpiHandle __vpiRealParam::vpi_handle(int code)
vpiHandle vpip_make_real_param(char*name, double value,
long file_idx, long lineno)
bool local_flag, long file_idx, long lineno)
{
struct __vpiRealParam*obj = new __vpiRealParam(value, name);
obj->scope = vpip_peek_current_scope();
obj->local_flag = local_flag;
obj->file_idx = (unsigned) file_idx;
obj->lineno = (unsigned) lineno;

View File

@ -322,6 +322,10 @@ static const char* vpi_type_values(PLI_INT32 code)
return "vpiNamedEvent";
case vpiNamedFork:
return "vpiNamedFork";
case vpiPathTerm:
return "vpiPathTerm";
case vpiPort:
return "vpiPort";
case vpiNet:
return "vpiNet";
case vpiNetArray:
@ -541,8 +545,7 @@ void vpi_set_vlog_info(int argc, char** argv)
vpi_vlog_info.argv = argv;
static char trace_buf[1024];
if (const char*path = getenv("VPI_TRACE")) {
if (const char*path = getenv("VPI_TRACE")) {
if (!strcmp(path,"-"))
vpi_trace = stdout;
else {

View File

@ -200,6 +200,10 @@ struct __vpiScopedRealtime : public __vpiSystemTime {
void vpi_get_value(p_vpi_value val);
};
struct __vpiPortInfo : public __vpiHandle {
};
/*
* Scopes are created by .scope statements in the source. These
@ -536,7 +540,7 @@ extern struct __vpiSysTaskCall*vpip_cur_task;
*/
vpiHandle vpip_make_string_const(char*text, bool persistent =true);
vpiHandle vpip_make_string_param(char*name, char*value,
vpiHandle vpip_make_string_param(char*name, char*value, bool local_flag,
long file_idx, long lineno);
struct __vpiBinaryConst : public __vpiHandle {
@ -554,7 +558,7 @@ struct __vpiBinaryConst : public __vpiHandle {
vpiHandle vpip_make_binary_const(unsigned wid, const char*bits);
vpiHandle vpip_make_binary_param(char*name, const vvp_vector4_t&bits,
bool signed_flag,
bool signed_flag, bool local_flag,
long file_idx, long lineno);
struct __vpiDecConst : public __vpiHandle {
@ -577,7 +581,7 @@ class __vpiRealConst : public __vpiHandle {
};
vpiHandle vpip_make_real_const(double value);
vpiHandle vpip_make_real_param(char*name, double value,
vpiHandle vpip_make_real_param(char*name, double value, bool local_flag,
long file_idx, long lineno);
/*

View File

@ -30,6 +30,7 @@
# include <cassert>
# include "ivl_alloc.h"
static vpiHandle *vpip_root_table_ptr = 0;
static unsigned vpip_root_table_cnt = 0;
@ -525,3 +526,96 @@ unsigned vpip_add_item_to_context(automatic_hooks_s*item,
/* Offset the context index by 2 to leave space for the list links. */
return 2 + idx;
}
struct vpiPortInfo : public __vpiHandle {
vpiPortInfo( __vpiScope *parent,
unsigned index,
int vpi_direction,
unsigned width,
const char *name );
int get_type_code(void) const { return vpiPort; }
int vpi_get(int code);
char* vpi_get_str(int code);
vpiHandle vpi_handle(int code);
protected:
__vpiScope *parent_;
unsigned index_;
int direction_;
unsigned width_;
const char *name_;
};
vpiPortInfo::vpiPortInfo( __vpiScope *parent,
unsigned index,
int vpi_direction,
unsigned width,
const char *name ) :
parent_(parent),
index_(index),
direction_(vpi_direction),
width_(width),
name_(name)
{
}
int vpiPortInfo::vpi_get(int code)
{
switch( code ) {
case vpiDirection :
return direction_;
case vpiPortIndex :
return index_;
case vpiSize :
return width_;
default :
return vpiUndefined;
}
}
char *vpiPortInfo::vpi_get_str(int code)
{
switch( code ) {
case vpiName :
return simple_set_rbuf_str(name_);
default :
return NULL;
}
}
vpiHandle vpiPortInfo::vpi_handle(int code)
{
switch (code) {
case vpiParent:
case vpiScope:
case vpiModule:
return parent_;
default :
break;
}
return 0;
}
/* Port info is meta-data to allow vpi queries of the port signature of modules for
* code-generators etc. There are no actual nets corresponding to instances of module ports
* as elaboration directly connects nets connected through module ports.
*/
void compile_port_info( unsigned index, int vpi_direction, unsigned width, const char *name )
{
vpiHandle obj = new vpiPortInfo( vpip_peek_current_scope(),
index, vpi_direction, width, name );
vpip_attach_to_current_scope(obj);
}

View File

@ -141,6 +141,7 @@ void compile_variable(char*label, char*name,
delete[] name;
}
vvp_net_t* create_constant_node(const char*val_str)
{
if (c4string_test(val_str)) {