diff --git a/Makefile.in b/Makefile.in index bcebfa4070..26f2f13efb 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 $@ @@ -239,7 +241,7 @@ version.exe: $(srcdir)/version.c $(srcdir)/version_base.h version_tag.h %.o: %.cc config.h $(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o mv $*.d dep/$*.d - + # Here are some explicit dependencies needed to get things going. main.o: main.cc version_tag.h diff --git a/Module.cc b/Module.cc index d448f6dfc6..ce70a91643 100644 --- a/Module.cc +++ b/Module.cc @@ -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) { diff --git a/Module.h b/Module.h index ad6604b377..a414b9e68f 100644 --- a/Module.h +++ b/Module.h @@ -136,6 +136,9 @@ class Module : public PScopeExtra, public LineInfo { const vector& 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& get_gates() const; diff --git a/PExpr.h b/PExpr.h index a4036680bc..98a16e14ac 100644 --- a/PExpr.h +++ b/PExpr.h @@ -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; diff --git a/configure.in b/configure.in index 28349c4755..6910d511c0 100644 --- a/configure.in +++ b/configure.in @@ -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) diff --git a/elab_net.cc b/elab_net.cc index fa4a3fd2ac..11019a989e 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -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; } diff --git a/elab_scope.cc b/elab_scope.cc index 796f606338..617e8bac8d 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -52,7 +52,8 @@ typedef map::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); } } diff --git a/elaborate.cc b/elaborate.cc index 319051b185..c777fb65a5 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -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 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(listroots) // 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 << "" << ": debug: " << rmod->mod_name() + << ": port elaboration root " + << rmod->port_count() << " ports" << endl; + } if (! rmod->elaborate_sig(des, scope)) { + if (debug_elaborate) { + cerr << "" << ": debug: " << rmod->mod_name() + << ": elaborate_sig failed!!!" << endl; + } delete des; return 0; } @@ -4988,11 +5007,26 @@ Design* elaborate(listroots) // defined for the root modules. This code does that. for (unsigned idx = 0; idx < rmod->port_count(); idx += 1) { vector 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 << "" << ": 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(listroots) des = 0; } + if (debug_elaborate) { + cerr << "" << ": debug: " + << " finishing with " + << des->find_root_scopes().size() << " root scopes " << endl; + } + return des; } diff --git a/iverilog-vpi.sh b/iverilog-vpi.sh index c280733bd1..38f81613bb 100644 --- a/iverilog-vpi.sh +++ b/iverilog-vpi.sh @@ -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= diff --git a/ivl_target.h b/ivl_target.h index 2933ac0e69..0639ca7e5a 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -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); diff --git a/libveriuser/Makefile.in b/libveriuser/Makefile.in index 557c12fa0c..ceaf8e7a3b 100644 --- a/libveriuser/Makefile.in +++ b/libveriuser/Makefile.in @@ -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 $@ diff --git a/main.cc b/main.cc index 2b8066576f..2218ff8722 100644 --- a/main.cc +++ b/main.cc @@ -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; diff --git a/net_scope.cc b/net_scope.cc index 47d4751ce9..f6a4131c34 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -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); + assert( ports_.size() == 0 ); + ports_.resize( num_ports ); +} + +void NetScope::add_module_port_net(NetNet*subport) +{ + assert(type_ == MODULE); + port_nets.push_back(subport); +} + + +void NetScope::add_module_port_info( unsigned idx, perm_string name, PortType::Enum ptype, + unsigned long width ) { assert(type_ == MODULE); - ports_.push_back(port); + PortInfo &info = ports_[idx]; + info.name = name; + info.type = ptype; + info.width = width; } -unsigned NetScope::module_ports() const + +unsigned NetScope::module_port_nets() const { assert(type_ == MODULE); - return ports_.size(); + return port_nets.size(); } -NetNet* NetScope::module_port(unsigned idx) const + +const std::vector & NetScope::module_port_info() const +{ + assert(type_ == MODULE); + return ports_; +} + + + +NetNet* NetScope::module_port_net(unsigned idx) const { assert(type_ == MODULE); - assert(idx < ports_.size()); - return ports_[idx]; + assert(idx < port_nets.size()); + return port_nets[idx]; } void NetScope::time_unit(int val) diff --git a/netlist.cc b/netlist.cc index b3bb702e27..03a393a007 100644 --- a/netlist.cc +++ b/netlist.cc @@ -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_; diff --git a/netlist.h b/netlist.h index 12a0384d0d..7ba64280db 100644 --- a/netlist.h +++ b/netlist.h @@ -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 lref_mask_; vector delay_paths_; + int port_index_; }; extern std::ostream&operator << (std::ostream&out, const std::list&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 &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::const_iterator signals_map_iter_t; std::map signals_map_; perm_string module_name_; - vectorports_; + vector port_nets; + + vector ports_; + union { NetTaskDef*task_; NetFuncDef*func_; diff --git a/t-dll-api.cc b/t-dll-api.cc index 150258cacb..d38025c2b4 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -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(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_; diff --git a/t-dll.cc b/t-dll.cc index 0bee8e88d4..3960681fe0 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -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: diff --git a/t-dll.h b/t-dll.h index 265c595901..ca5f4db3c8 100644 --- a/t-dll.h +++ b/t-dll.h @@ -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 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, diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 37555c5ca3..c927ed9323 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -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)); diff --git a/vpi_user.h b/vpi_user.h index 3d58118350..d0fe2b4150 100644 --- a/vpi_user.h +++ b/vpi_user.h @@ -43,6 +43,7 @@ EXTERN_C_START # include # include +# include # 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 */ diff --git a/vvp/compile.cc b/vvp/compile.cc index 9edb2e97f7..2d863726f1 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -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 # include # include @@ -610,7 +614,7 @@ static void compile_array_lookup(struct vvp_code_s*code, char*label) resolv_submit(res); } -static list scheduled_compiletf; +static std::list 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); diff --git a/vvp/compile.h b/vvp/compile.h index 29fb2cb1e6..35d69d8459 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -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. diff --git a/vvp/delay.h b/vvp/delay.h index 567abe4ddd..62864656fe 100644 --- a/vvp/delay.h +++ b/vvp/delay.h @@ -19,6 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ +# include # include "vvp_net.h" # include "schedule.h" diff --git a/vvp/lexor.lex b/vvp/lexor.lex index 1109205cd9..db33b636b9 100644 --- a/vvp/lexor.lex +++ b/vvp/lexor.lex @@ -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; } @@ -262,6 +263,12 @@ static char* strdupnew(char const *str) yylval.text = strdup(yytext); 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. */ diff --git a/vvp/main.cc b/vvp/main.cc index cb2f63d5b5..9a3595d9af 100644 --- a/vvp/main.cc +++ b/vvp/main.cc @@ -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; diff --git a/vvp/parse.y b/vvp/parse.y index aff881aa2b..846ec9e1a4 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -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 T_INSTR %token T_LABEL @@ -104,6 +107,7 @@ static struct __vpiModPath*modpath_dst = 0; %token T_VECTOR %type local_flag +%type port_type %type signed_t_number %type symbol symbol_opt %type 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); } diff --git a/vvp/parse_misc.h b/vvp/parse_misc.h index 3ac77505dc..33caa87302 100644 --- a/vvp/parse_misc.h +++ b/vvp/parse_misc.h @@ -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 *); diff --git a/vvp/schedule.cc b/vvp/schedule.cc index 83d627ae28..220cc01494 100644 --- a/vvp/schedule.cc +++ b/vvp/schedule.cc @@ -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 { diff --git a/vvp/vpi_const.cc b/vvp/vpi_const.cc index f7ca58757e..03fbb728d2 100644 --- a/vvp/vpi_const.cc +++ b/vvp/vpi_const.cc @@ -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; + + case vpiLocalParam : + return local_flag; - return __vpiBinaryConst::vpi_get(code); + 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; + + case vpiLocalParam : + return local_flag; - return __vpiRealConst::vpi_get(code); + 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; diff --git a/vvp/vpi_priv.cc b/vvp/vpi_priv.cc index 309993783b..5d6c8b96bb 100644 --- a/vvp/vpi_priv.cc +++ b/vvp/vpi_priv.cc @@ -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 { diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 2f42379576..332a90d04d 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -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); /* diff --git a/vvp/vpi_scope.cc b/vvp/vpi_scope.cc index a93e2aa0aa..3e06ae5d25 100644 --- a/vvp/vpi_scope.cc +++ b/vvp/vpi_scope.cc @@ -30,6 +30,7 @@ # include # 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); +} diff --git a/vvp/words.cc b/vvp/words.cc index 2cfdcd3dcb..895f331f60 100644 --- a/vvp/words.cc +++ b/vvp/words.cc @@ -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)) {