2003-01-26 00:48:05 +01:00
|
|
|
/*
|
2025-10-13 22:14:57 +02:00
|
|
|
* Copyright (c) 2003-2025 Stephen Williams (steve@icarus.com)
|
2003-01-26 00:48:05 +01:00
|
|
|
*
|
|
|
|
|
* This source code is free software; you can redistribute it
|
|
|
|
|
* and/or modify it in source code form under the terms of the GNU
|
|
|
|
|
* General Public License as published by the Free Software
|
|
|
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
|
|
|
* any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
2012-08-29 03:41:23 +02:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2003-01-26 00:48:05 +01:00
|
|
|
*/
|
|
|
|
|
|
2008-01-01 18:45:02 +01:00
|
|
|
# include "compile.h"
|
2003-01-26 00:48:05 +01:00
|
|
|
# include "vpi_priv.h"
|
2009-04-16 04:08:37 +02:00
|
|
|
# include "vvp_net_sig.h"
|
2003-02-10 06:20:10 +01:00
|
|
|
# include "schedule.h"
|
2009-10-16 23:18:00 +02:00
|
|
|
#ifdef CHECK_WITH_VALGRIND
|
|
|
|
|
# include "vvp_cleanup.h"
|
|
|
|
|
#endif
|
2010-05-31 22:12:06 +02:00
|
|
|
# include <cstdio>
|
|
|
|
|
# include <cstdlib>
|
|
|
|
|
# include <cstring>
|
|
|
|
|
# include <cassert>
|
2010-10-24 00:52:56 +02:00
|
|
|
# include "ivl_alloc.h"
|
2003-01-26 00:48:05 +01:00
|
|
|
|
2007-12-03 18:44:31 +01:00
|
|
|
static int real_var_get(int code, vpiHandle ref)
|
|
|
|
|
{
|
2012-01-19 19:16:39 +01:00
|
|
|
struct __vpiRealVar*rfp = dynamic_cast<__vpiRealVar*>(ref);
|
|
|
|
|
assert(rfp);
|
2007-12-03 18:44:31 +01:00
|
|
|
|
2008-05-01 00:39:50 +02:00
|
|
|
switch (code) {
|
|
|
|
|
case vpiArray:
|
2008-10-29 02:52:32 +01:00
|
|
|
return rfp->is_netarray != 0;
|
2008-05-01 00:39:50 +02:00
|
|
|
|
|
|
|
|
case vpiSize:
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
case vpiLineNo:
|
|
|
|
|
return 0; // Not implemented for now!
|
2008-10-28 18:52:39 +01:00
|
|
|
|
|
|
|
|
case vpiAutomatic:
|
2015-12-21 05:26:57 +01:00
|
|
|
return vpip_scope(rfp)->is_automatic()? 1 : 0;
|
2007-12-03 18:44:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2003-01-26 00:48:05 +01:00
|
|
|
|
2003-02-10 06:20:10 +01:00
|
|
|
static char* real_var_get_str(int code, vpiHandle ref)
|
|
|
|
|
{
|
2012-01-19 19:16:39 +01:00
|
|
|
struct __vpiRealVar*rfp = dynamic_cast<__vpiRealVar*>(ref);
|
|
|
|
|
assert(rfp);
|
2007-12-19 00:11:50 +01:00
|
|
|
|
2008-01-01 18:45:02 +01:00
|
|
|
if (code == vpiFile) { // Not implemented for now!
|
|
|
|
|
return simple_set_rbuf_str(file_names[0]);
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-13 22:14:57 +02:00
|
|
|
char *nm;
|
|
|
|
|
const char *ixs;
|
2008-10-29 02:52:32 +01:00
|
|
|
if (rfp->is_netarray) {
|
|
|
|
|
nm = strdup(vpi_get_str(vpiName, rfp->within.parent));
|
2007-12-19 00:11:50 +01:00
|
|
|
s_vpi_value vp;
|
2007-12-03 20:41:52 +01:00
|
|
|
vp.format = vpiDecStrVal;
|
|
|
|
|
vpi_get_value(rfp->id.index, &vp);
|
2007-12-19 00:11:50 +01:00
|
|
|
ixs = vp.value.str; /* do I need to strdup() this? */
|
2007-12-03 20:41:52 +01:00
|
|
|
} else {
|
|
|
|
|
nm = strdup(rfp->id.name);
|
2007-12-19 00:11:50 +01:00
|
|
|
ixs = NULL;
|
2003-02-10 06:20:10 +01:00
|
|
|
}
|
|
|
|
|
|
2012-01-19 19:16:39 +01:00
|
|
|
char *rbuf = generic_get_str(code, vpip_scope(rfp), nm, ixs);
|
2007-12-03 20:41:52 +01:00
|
|
|
free(nm);
|
2007-12-19 00:11:50 +01:00
|
|
|
return rbuf;
|
2003-02-10 06:20:10 +01:00
|
|
|
}
|
|
|
|
|
|
2007-12-03 18:44:31 +01:00
|
|
|
static vpiHandle real_var_get_handle(int code, vpiHandle ref)
|
|
|
|
|
{
|
2012-01-19 19:16:39 +01:00
|
|
|
struct __vpiRealVar*rfp = dynamic_cast<__vpiRealVar*>(ref);
|
|
|
|
|
assert(rfp);
|
2007-12-03 18:44:31 +01:00
|
|
|
|
|
|
|
|
switch (code) {
|
|
|
|
|
|
|
|
|
|
case vpiParent:
|
2022-12-28 08:59:39 +01:00
|
|
|
return rfp->is_netarray ? rfp->within.parent : NULL;
|
2007-12-03 18:44:31 +01:00
|
|
|
|
|
|
|
|
case vpiIndex:
|
2022-12-28 08:59:39 +01:00
|
|
|
return rfp->is_netarray ? rfp->id.index : NULL;
|
2008-10-29 02:52:32 +01:00
|
|
|
|
|
|
|
|
case vpiScope:
|
2012-01-19 19:16:39 +01:00
|
|
|
return vpip_scope(rfp);
|
2009-01-16 20:09:48 +01:00
|
|
|
|
|
|
|
|
case vpiModule:
|
|
|
|
|
return vpip_module(vpip_scope(rfp));
|
2007-12-03 18:44:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static vpiHandle real_var_iterate(int code, vpiHandle ref)
|
|
|
|
|
{
|
2012-01-19 19:16:39 +01:00
|
|
|
struct __vpiRealVar*rfp = dynamic_cast<__vpiRealVar*>(ref);
|
|
|
|
|
assert(rfp);
|
2007-12-03 18:44:31 +01:00
|
|
|
|
|
|
|
|
if (code == vpiIndex) {
|
2022-12-28 08:59:39 +01:00
|
|
|
return rfp->is_netarray ? rfp->id.index->vpi_iterate(code) : NULL;
|
2007-12-03 18:44:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-26 00:48:05 +01:00
|
|
|
static void real_var_get_value(vpiHandle ref, s_vpi_value*vp)
|
|
|
|
|
{
|
2012-01-19 19:16:39 +01:00
|
|
|
struct __vpiRealVar*rfp = dynamic_cast<__vpiRealVar*>(ref);
|
|
|
|
|
assert(rfp);
|
2003-01-26 00:48:05 +01:00
|
|
|
|
2009-09-16 06:28:21 +02:00
|
|
|
vvp_signal_value*fil
|
|
|
|
|
= dynamic_cast<vvp_signal_value*>(rfp->net->fil);
|
2003-02-04 05:03:40 +01:00
|
|
|
|
2009-09-16 06:28:21 +02:00
|
|
|
fil->get_signal_value(vp);
|
2003-01-26 00:48:05 +01:00
|
|
|
}
|
|
|
|
|
|
2015-06-26 01:53:36 +02:00
|
|
|
static vpiHandle real_var_put_value(vpiHandle ref, p_vpi_value vp, int flags)
|
2003-01-26 00:48:05 +01:00
|
|
|
{
|
2012-01-19 19:16:39 +01:00
|
|
|
struct __vpiRealVar*rfp = dynamic_cast<__vpiRealVar*>(ref);
|
Rework $plusarg routines.
This patch addresses a number of issues:
Rewrote the $test$plusargs and $value$plusargs routines to have
better error/warning messages, to support runtime strings, to
correctly load bit based values (truncating, padding, negative
value), added support for the real formats using strtod() and
added "x/X" as an alias for "h/H" to match the other part of
Icarus.
Rewrite the vpip_{bin,oct,hex}_str_to_vec4 routines to ignore
embedded "_" characters. Add support for a negative value and
set the entire value to 'bx if an invalid digit is found. A
warning is printed for this case.
Rewrite vpip_dec_str_to_vec4 to ignore embedded "_" characters,
to support a single "x" or "z" constant and to return 'bx if an
invalid digit is found. A warning is printed for this case.
It simplifies the system task/functions error/warning messages.
It removes the signed flag for the bin and dec string conversions.
This was not being used (was always false) and the new negative
value support makes this obsolete.
Add support for a real variable to handle Bin, Oct, Dec and Hex
strings. They are converted into a vvp_vector4_t which is then
converted to a real value.
Add support for setting a bit based value using a real value.
Removed an unneeded rfp signal in vpip_make_reg()
2008-11-13 22:28:19 +01:00
|
|
|
assert(rfp);
|
|
|
|
|
vvp_net_ptr_t destination (rfp->net, 0);
|
2015-06-26 01:53:36 +02:00
|
|
|
|
|
|
|
|
/* If this is a release, then we are not really putting a
|
|
|
|
|
value. Instead, issue a release "command" to the signal
|
|
|
|
|
node to cause it to release a forced value. */
|
|
|
|
|
if (flags == vpiReleaseFlag) {
|
|
|
|
|
assert(rfp->net->fil);
|
|
|
|
|
rfp->net->fil->force_unlink();
|
|
|
|
|
rfp->net->fil->release(destination, rfp->is_wire);
|
|
|
|
|
real_var_get_value(ref, vp);
|
|
|
|
|
return ref;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double result = real_from_vpi_value(vp);
|
|
|
|
|
|
|
|
|
|
if (flags == vpiForceFlag) {
|
|
|
|
|
vvp_vector2_t mask (vvp_vector2_t::FILL1, 1);
|
|
|
|
|
rfp->net->force_real(result, mask);
|
|
|
|
|
} else if (rfp->is_wire) {
|
|
|
|
|
rfp->net->send_real(result, vthread_get_wt_context());
|
|
|
|
|
} else {
|
|
|
|
|
vvp_send_real(destination, result, vthread_get_wt_context());
|
|
|
|
|
}
|
2003-01-26 00:48:05 +01:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-19 19:16:39 +01:00
|
|
|
inline __vpiRealVar::__vpiRealVar()
|
2012-01-20 23:15:26 +01:00
|
|
|
{ }
|
2012-01-19 19:16:39 +01:00
|
|
|
|
2012-01-20 00:04:51 +01:00
|
|
|
int __vpiRealVar::get_type_code(void) const
|
|
|
|
|
{ return vpiRealVar; }
|
|
|
|
|
|
2012-01-20 20:39:48 +01:00
|
|
|
int __vpiRealVar::vpi_get(int code)
|
|
|
|
|
{ return real_var_get(code, this); }
|
|
|
|
|
|
|
|
|
|
char* __vpiRealVar::vpi_get_str(int code)
|
|
|
|
|
{ return real_var_get_str(code, this); }
|
|
|
|
|
|
|
|
|
|
void __vpiRealVar::vpi_get_value(p_vpi_value val)
|
|
|
|
|
{ real_var_get_value(this, val); }
|
|
|
|
|
|
|
|
|
|
vpiHandle __vpiRealVar::vpi_put_value(p_vpi_value val, int flags)
|
|
|
|
|
{ return real_var_put_value(this, val, flags); }
|
|
|
|
|
|
|
|
|
|
vpiHandle __vpiRealVar::vpi_handle(int code)
|
|
|
|
|
{ return real_var_get_handle(code, this); }
|
|
|
|
|
|
|
|
|
|
vpiHandle __vpiRealVar::vpi_iterate(int code)
|
|
|
|
|
{ return real_var_iterate(code, this); }
|
2003-01-26 00:48:05 +01:00
|
|
|
|
2017-11-07 19:48:48 +01:00
|
|
|
static vpiHandle vpip_make_real_(__vpiScope*scope, const char*name,
|
|
|
|
|
vvp_net_t*net, bool is_wire)
|
2003-01-26 00:48:05 +01:00
|
|
|
{
|
2012-01-19 19:16:39 +01:00
|
|
|
struct __vpiRealVar*obj = new __vpiRealVar;
|
2003-01-26 00:48:05 +01:00
|
|
|
|
2022-12-28 08:59:39 +01:00
|
|
|
obj->id.name = name ? vpip_name_string(name) : NULL;
|
2008-10-29 02:52:32 +01:00
|
|
|
obj->is_netarray = 0;
|
2015-06-26 01:53:36 +02:00
|
|
|
obj->is_wire = is_wire;
|
2005-07-06 06:29:25 +02:00
|
|
|
obj->net = net;
|
2003-01-26 00:48:05 +01:00
|
|
|
|
2017-11-07 19:48:48 +01:00
|
|
|
obj->within.scope = scope;
|
2007-08-17 00:13:25 +02:00
|
|
|
|
2012-01-19 19:16:39 +01:00
|
|
|
return obj;
|
2003-01-26 00:48:05 +01:00
|
|
|
}
|
2009-01-31 03:36:07 +01:00
|
|
|
|
2017-11-07 19:48:48 +01:00
|
|
|
vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net)
|
|
|
|
|
{
|
|
|
|
|
return vpip_make_real_(vpip_peek_current_scope(), name, net, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vpiHandle vpip_make_real_net(__vpiScope*scope,
|
|
|
|
|
const char*name, vvp_net_t*net)
|
|
|
|
|
{
|
|
|
|
|
return vpip_make_real_(scope, name, net, true);
|
|
|
|
|
}
|
|
|
|
|
|
2009-01-31 03:36:07 +01:00
|
|
|
#ifdef CHECK_WITH_VALGRIND
|
|
|
|
|
void real_delete(vpiHandle item)
|
|
|
|
|
{
|
2012-01-19 19:16:39 +01:00
|
|
|
struct __vpiRealVar*obj = dynamic_cast<__vpiRealVar*>(item);
|
2009-09-25 00:11:56 +02:00
|
|
|
assert(obj->net->fil);
|
|
|
|
|
obj->net->fil->clear_all_callbacks();
|
2009-10-16 23:18:00 +02:00
|
|
|
vvp_net_delete(obj->net);
|
2009-01-31 03:36:07 +01:00
|
|
|
|
2012-01-19 19:16:39 +01:00
|
|
|
delete obj;
|
2009-01-31 03:36:07 +01:00
|
|
|
}
|
|
|
|
|
#endif
|