2003-01-26 00:48:05 +01:00
|
|
|
/*
|
2009-01-16 20:09:48 +01:00
|
|
|
* Copyright (c) 2003-2009 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
|
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
|
|
|
|
*/
|
|
|
|
|
|
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
|
2003-01-26 00:48:05 +01:00
|
|
|
# include <stdio.h>
|
|
|
|
|
# include <stdlib.h>
|
2003-03-13 05:59:21 +01:00
|
|
|
# include <string.h>
|
2003-01-26 00:48:05 +01:00
|
|
|
#ifdef HAVE_MALLOC_H
|
|
|
|
|
# include <malloc.h>
|
|
|
|
|
#endif
|
|
|
|
|
# include <assert.h>
|
|
|
|
|
|
2008-11-02 04:44:03 +01:00
|
|
|
struct __vpiRealVar* vpip_realvar_from_handle(vpiHandle obj)
|
|
|
|
|
{
|
|
|
|
|
assert(obj);
|
|
|
|
|
if (obj->vpi_type->type_code == vpiRealVar)
|
|
|
|
|
return (struct __vpiRealVar*)obj;
|
|
|
|
|
else
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2007-12-03 18:44:31 +01:00
|
|
|
static int real_var_get(int code, vpiHandle ref)
|
|
|
|
|
{
|
|
|
|
|
assert(ref->vpi_type->type_code == vpiRealVar);
|
|
|
|
|
|
2008-11-02 04:44:03 +01:00
|
|
|
struct __vpiRealVar*rfp = vpip_realvar_from_handle(ref);
|
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:
|
2008-10-30 17:23:23 +01:00
|
|
|
return (int) vpip_scope(rfp)->is_automatic;
|
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)
|
|
|
|
|
{
|
|
|
|
|
assert(ref->vpi_type->type_code == vpiRealVar);
|
|
|
|
|
|
|
|
|
|
struct __vpiRealVar*rfp = (struct __vpiRealVar*)ref;
|
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]);
|
|
|
|
|
}
|
|
|
|
|
|
2007-12-19 00:11:50 +01:00
|
|
|
char *nm, *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
|
|
|
}
|
|
|
|
|
|
2008-10-29 02:52:32 +01:00
|
|
|
char *rbuf = generic_get_str(code, &(vpip_scope(rfp)->base), 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)
|
|
|
|
|
{
|
|
|
|
|
assert(ref->vpi_type->type_code == vpiRealVar);
|
|
|
|
|
|
|
|
|
|
struct __vpiRealVar*rfp = (struct __vpiRealVar*)ref;
|
|
|
|
|
|
|
|
|
|
switch (code) {
|
|
|
|
|
|
|
|
|
|
case vpiParent:
|
2008-10-29 02:52:32 +01:00
|
|
|
return rfp->is_netarray ? rfp->within.parent : 0;
|
2007-12-03 18:44:31 +01:00
|
|
|
|
|
|
|
|
case vpiIndex:
|
2008-10-29 02:52:32 +01:00
|
|
|
return rfp->is_netarray ? rfp->id.index : 0;
|
|
|
|
|
|
|
|
|
|
case vpiScope:
|
|
|
|
|
return &(vpip_scope(rfp)->base);
|
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)
|
|
|
|
|
{
|
|
|
|
|
assert(ref->vpi_type->type_code == vpiRealVar);
|
|
|
|
|
|
|
|
|
|
struct __vpiRealVar*rfp = (struct __vpiRealVar*)ref;
|
|
|
|
|
|
|
|
|
|
if (code == vpiIndex) {
|
2008-10-29 02:52:32 +01:00
|
|
|
return rfp->is_netarray ? (rfp->id.index->vpi_type->iterate_)
|
|
|
|
|
(code, rfp->id.index) : 0;
|
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)
|
|
|
|
|
{
|
|
|
|
|
assert(ref->vpi_type->type_code == vpiRealVar);
|
|
|
|
|
|
2005-07-06 06:29:25 +02:00
|
|
|
struct __vpiRealVar*rfp
|
|
|
|
|
= (struct __vpiRealVar*)ref;
|
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
|
|
|
}
|
|
|
|
|
|
2008-03-11 05:54:58 +01:00
|
|
|
static vpiHandle real_var_put_value(vpiHandle ref, p_vpi_value vp, int)
|
2003-01-26 00:48:05 +01:00
|
|
|
{
|
|
|
|
|
assert(ref->vpi_type->type_code == vpiRealVar);
|
|
|
|
|
|
2009-03-28 03:12:11 +01:00
|
|
|
double result = real_from_vpi_value(vp);
|
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
|
|
|
|
|
|
|
|
struct __vpiRealVar*rfp = (struct __vpiRealVar*)ref;
|
|
|
|
|
assert(rfp);
|
|
|
|
|
vvp_net_ptr_t destination (rfp->net, 0);
|
|
|
|
|
vvp_send_real(destination, result, vthread_get_wt_context());
|
2003-01-26 00:48:05 +01:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const struct __vpirt vpip_real_var_rt = {
|
|
|
|
|
vpiRealVar,
|
|
|
|
|
|
2007-12-03 18:44:31 +01:00
|
|
|
real_var_get,
|
|
|
|
|
real_var_get_str,
|
|
|
|
|
real_var_get_value,
|
|
|
|
|
real_var_put_value,
|
2003-01-26 00:48:05 +01:00
|
|
|
|
2007-12-03 18:44:31 +01:00
|
|
|
real_var_get_handle,
|
|
|
|
|
real_var_iterate,
|
2003-01-26 00:48:05 +01:00
|
|
|
0,
|
|
|
|
|
|
2003-02-02 02:40:24 +01:00
|
|
|
0
|
2003-01-26 00:48:05 +01:00
|
|
|
};
|
|
|
|
|
|
2003-02-10 06:20:10 +01:00
|
|
|
void vpip_real_value_change(struct __vpiCallback*cbh,
|
|
|
|
|
vpiHandle ref)
|
|
|
|
|
{
|
2005-07-06 06:29:25 +02:00
|
|
|
struct __vpiRealVar*rfp
|
|
|
|
|
= (struct __vpiRealVar*)ref;
|
2009-08-21 05:31:11 +02:00
|
|
|
vvp_vpi_callback*obj = dynamic_cast<vvp_vpi_callback*>(rfp->net->fil);
|
|
|
|
|
assert(obj);
|
2005-07-06 06:29:25 +02:00
|
|
|
|
2009-08-21 05:31:11 +02:00
|
|
|
obj->add_vpi_callback(cbh);
|
2003-02-10 06:20:10 +01:00
|
|
|
}
|
|
|
|
|
|
2005-07-06 06:29:25 +02:00
|
|
|
vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net)
|
2003-01-26 00:48:05 +01:00
|
|
|
{
|
|
|
|
|
struct __vpiRealVar*obj = (struct __vpiRealVar*)
|
|
|
|
|
malloc(sizeof(struct __vpiRealVar));
|
|
|
|
|
|
|
|
|
|
obj->base.vpi_type = &vpip_real_var_rt;
|
2008-10-28 01:54:50 +01:00
|
|
|
obj->id.name = name ? vpip_name_string(name) : 0;
|
2008-10-29 02:52:32 +01:00
|
|
|
obj->is_netarray = 0;
|
2005-07-06 06:29:25 +02:00
|
|
|
obj->net = net;
|
2003-01-26 00:48:05 +01:00
|
|
|
|
2008-10-29 02:52:32 +01:00
|
|
|
obj->within.scope = vpip_peek_current_scope();
|
2007-08-17 00:13:25 +02:00
|
|
|
|
2003-01-26 00:48:05 +01:00
|
|
|
return &obj->base;
|
|
|
|
|
}
|
2009-01-31 03:36:07 +01:00
|
|
|
|
|
|
|
|
#ifdef CHECK_WITH_VALGRIND
|
|
|
|
|
void real_delete(vpiHandle item)
|
|
|
|
|
{
|
|
|
|
|
struct __vpiRealVar*obj = (struct __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
|
|
|
|
|
|
|
|
free(obj);
|
|
|
|
|
}
|
|
|
|
|
#endif
|