iverilog/vvp/vpi_const.cc

859 lines
19 KiB
C++
Raw Permalink Normal View History

/*
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* 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
*/
# include "vpi_priv.h"
# include "compile.h"
# include "config.h"
#ifdef CHECK_WITH_VALGRIND
# include "vvp_cleanup.h"
#endif
# include <stdio.h>
2001-09-15 20:27:04 +02:00
#ifdef HAVE_MALLOC_H
# include <malloc.h>
2001-09-15 20:27:04 +02:00
#endif
# include <stdlib.h>
# include <string.h>
# include <assert.h>
static int string_get(int code, vpiHandle ref)
{
struct __vpiStringConst*rfp;
switch (code) {
case vpiSize:
rfp = (struct __vpiStringConst*)ref;
2004-05-18 20:43:38 +02:00
assert((ref->vpi_type->type_code == vpiConstant)
|| ((ref->vpi_type->type_code == vpiParameter)));
//fprintf(stderr, "String:|%s|, Length: %d\n", rfp->value, strlen(rfp->value));
return strlen(rfp->value)*8;
case vpiSigned:
return 0;
case vpiConstType:
return vpiStringConst;
case vpiAutomatic:
return 0;
#ifdef CHECK_WITH_VALGRIND
case _vpiFromThr:
return _vpiNoThr;
#endif
default:
fprintf(stderr, "vvp error: get %d not supported "
"by vpiStringConst\n", code);
assert(0);
return 0;
}
}
static void string_value(vpiHandle ref, p_vpi_value vp)
{
unsigned uint_value;
Implement the swrite* and sformat system tasks plus a few other fixes. This patch implements the swrite* and sformat system tasks. It also makes $simtime distinguishable from the other integer time tasks. This was needed to get the correct time units when $simtime was given as an argument to $swrite*. The string constant code was also modified to allow a string to be returned as a vector (0/1 bit pattern). Here are some more specifics about the swrite* changes. 1. They do not share formatting code with the other display functions, so they may/will produce different results. 2. All %{alpha} codes allow a width and justification. Others have been enhanced (%t allows the default width and precision to be overridden, time functions print with time formatting, better error checking and messages, etc.). 3. %u and %z formatting codes have been added. It is important to note that these two formats can produce embedded NULLs, since these functions are returning a string anything after the first NULL will not be reachable! memcpy is used instead of regular string processing where needed so that the original string will contain the total result. The size returned when the string is created is the true length. A warning will be printed if a string with embedded NULLs is produced (strlen() does not match the true length). 4. Real numbers are printed with %g instead of %f. Once this new formatting code has been evaluated we should incorporate the changes/fixes into the formatting code for the other functions or the other functions could be modified to use this new code. The true string length is available so we should be able to work around the embedded NULL problem.
2007-08-14 00:56:02 +02:00
p_vpi_vecval vecp;
struct __vpiStringConst*rfp = (struct __vpiStringConst*)ref;
2003-03-13 05:59:21 +01:00
int size = strlen(rfp->value);
char*rbuf = 0;
char*cp;
2003-03-11 00:37:07 +01:00
assert((ref->vpi_type->type_code == vpiConstant)
|| ((ref->vpi_type->type_code == vpiParameter)));
switch (vp->format) {
case vpiObjTypeVal:
/* String parameters by default have vpiStringVal values. */
vp->format = vpiStringVal;
case vpiStringVal:
rbuf = need_result_buf(size + 1, RBUF_VAL);
strcpy(rbuf, (char*)rfp->value);
vp->value.str = rbuf;
break;
case vpiDecStrVal:
if (size > 4){
// We only support standard integers. Ignore other bytes...
size = 4;
fprintf(stderr, "Warning (vpi_const.cc): %%d on constant strings only looks "
"at first 4 bytes!\n");
}
2003-03-13 05:59:21 +01:00
rbuf = need_result_buf(size + 1, RBUF_VAL);
uint_value = 0;
for(int i=0; i<size;i ++){
uint_value <<=8;
uint_value += (unsigned char)(rfp->value[i]);
}
2003-03-13 05:59:21 +01:00
sprintf(rbuf, "%u", uint_value);
vp->value.str = rbuf;
break;
case vpiBinStrVal:
2003-03-13 05:59:21 +01:00
rbuf = need_result_buf(8 * size + 1, RBUF_VAL);
cp = rbuf;
for(int i=0; i<size;i ++){
for(int bit=7;bit>=0; bit--){
*cp++ = "01"[ (rfp->value[i]>>bit)&1 ];
}
}
*cp = 0;
2003-03-13 05:59:21 +01:00
vp->value.str = rbuf;
break;
case vpiHexStrVal:
2003-03-13 05:59:21 +01:00
rbuf = need_result_buf(2 * size + 1, RBUF_VAL);
cp = rbuf;
for(int i=0; i<size;i++){
for(int nibble=1;nibble>=0; nibble--){
*cp++ = "0123456789abcdef"[ (rfp->value[i]>>(nibble*4))&15 ];
}
}
*cp = 0;
2003-03-13 05:59:21 +01:00
vp->value.str = rbuf;
break;
case vpiOctStrVal:
fprintf(stderr, "ERROR (vpi_const.cc): %%o display of constant strings not yet implemented\n");
assert(0);
break;
case vpiIntVal:
vp->value.integer = 0;
for(int i=0; i<size;i ++){
for(int bit=7;bit>=0; bit--){
vp->value.integer <<= 1;
vp->value.integer += (rfp->value[i]>>bit)&1;
}
}
break;
Implement the swrite* and sformat system tasks plus a few other fixes. This patch implements the swrite* and sformat system tasks. It also makes $simtime distinguishable from the other integer time tasks. This was needed to get the correct time units when $simtime was given as an argument to $swrite*. The string constant code was also modified to allow a string to be returned as a vector (0/1 bit pattern). Here are some more specifics about the swrite* changes. 1. They do not share formatting code with the other display functions, so they may/will produce different results. 2. All %{alpha} codes allow a width and justification. Others have been enhanced (%t allows the default width and precision to be overridden, time functions print with time formatting, better error checking and messages, etc.). 3. %u and %z formatting codes have been added. It is important to note that these two formats can produce embedded NULLs, since these functions are returning a string anything after the first NULL will not be reachable! memcpy is used instead of regular string processing where needed so that the original string will contain the total result. The size returned when the string is created is the true length. A warning will be printed if a string with embedded NULLs is produced (strlen() does not match the true length). 4. Real numbers are printed with %g instead of %f. Once this new formatting code has been evaluated we should incorporate the changes/fixes into the formatting code for the other functions or the other functions could be modified to use this new code. The true string length is available so we should be able to work around the embedded NULL problem.
2007-08-14 00:56:02 +02:00
case vpiVectorVal:
vp->value.vector = (p_vpi_vecval)
need_result_buf((size+3)/4*
sizeof(s_vpi_vecval),
RBUF_VAL);
Implement the swrite* and sformat system tasks plus a few other fixes. This patch implements the swrite* and sformat system tasks. It also makes $simtime distinguishable from the other integer time tasks. This was needed to get the correct time units when $simtime was given as an argument to $swrite*. The string constant code was also modified to allow a string to be returned as a vector (0/1 bit pattern). Here are some more specifics about the swrite* changes. 1. They do not share formatting code with the other display functions, so they may/will produce different results. 2. All %{alpha} codes allow a width and justification. Others have been enhanced (%t allows the default width and precision to be overridden, time functions print with time formatting, better error checking and messages, etc.). 3. %u and %z formatting codes have been added. It is important to note that these two formats can produce embedded NULLs, since these functions are returning a string anything after the first NULL will not be reachable! memcpy is used instead of regular string processing where needed so that the original string will contain the total result. The size returned when the string is created is the true length. A warning will be printed if a string with embedded NULLs is produced (strlen() does not match the true length). 4. Real numbers are printed with %g instead of %f. Once this new formatting code has been evaluated we should incorporate the changes/fixes into the formatting code for the other functions or the other functions could be modified to use this new code. The true string length is available so we should be able to work around the embedded NULL problem.
2007-08-14 00:56:02 +02:00
uint_value = 0;
vecp = vp->value.vector;
vecp->aval = vecp->bval = 0;
Implement the swrite* and sformat system tasks plus a few other fixes. This patch implements the swrite* and sformat system tasks. It also makes $simtime distinguishable from the other integer time tasks. This was needed to get the correct time units when $simtime was given as an argument to $swrite*. The string constant code was also modified to allow a string to be returned as a vector (0/1 bit pattern). Here are some more specifics about the swrite* changes. 1. They do not share formatting code with the other display functions, so they may/will produce different results. 2. All %{alpha} codes allow a width and justification. Others have been enhanced (%t allows the default width and precision to be overridden, time functions print with time formatting, better error checking and messages, etc.). 3. %u and %z formatting codes have been added. It is important to note that these two formats can produce embedded NULLs, since these functions are returning a string anything after the first NULL will not be reachable! memcpy is used instead of regular string processing where needed so that the original string will contain the total result. The size returned when the string is created is the true length. A warning will be printed if a string with embedded NULLs is produced (strlen() does not match the true length). 4. Real numbers are printed with %g instead of %f. Once this new formatting code has been evaluated we should incorporate the changes/fixes into the formatting code for the other functions or the other functions could be modified to use this new code. The true string length is available so we should be able to work around the embedded NULL problem.
2007-08-14 00:56:02 +02:00
for(int i=0; i<size;i ++){
vecp->aval |= rfp->value[i] << uint_value*8;
uint_value += 1;
if (uint_value > 3) {
uint_value = 0;
vecp += 1;
vecp->aval = vecp->bval = 0;
Implement the swrite* and sformat system tasks plus a few other fixes. This patch implements the swrite* and sformat system tasks. It also makes $simtime distinguishable from the other integer time tasks. This was needed to get the correct time units when $simtime was given as an argument to $swrite*. The string constant code was also modified to allow a string to be returned as a vector (0/1 bit pattern). Here are some more specifics about the swrite* changes. 1. They do not share formatting code with the other display functions, so they may/will produce different results. 2. All %{alpha} codes allow a width and justification. Others have been enhanced (%t allows the default width and precision to be overridden, time functions print with time formatting, better error checking and messages, etc.). 3. %u and %z formatting codes have been added. It is important to note that these two formats can produce embedded NULLs, since these functions are returning a string anything after the first NULL will not be reachable! memcpy is used instead of regular string processing where needed so that the original string will contain the total result. The size returned when the string is created is the true length. A warning will be printed if a string with embedded NULLs is produced (strlen() does not match the true length). 4. Real numbers are printed with %g instead of %f. Once this new formatting code has been evaluated we should incorporate the changes/fixes into the formatting code for the other functions or the other functions could be modified to use this new code. The true string length is available so we should be able to work around the embedded NULL problem.
2007-08-14 00:56:02 +02:00
}
}
break;
default:
fprintf(stderr, "ERROR (vpi_const.cc): vp->format: %d\n", vp->format);
assert(0);
vp->format = vpiSuppressVal;
break;
}
}
static const struct __vpirt vpip_string_rt = {
vpiConstant,
string_get,
0,
string_value,
0,
0,
0
};
static int free_temp_string(vpiHandle obj)
{
struct __vpiStringConst*rfp = (struct __vpiStringConst*)obj;
assert(obj->vpi_type->type_code == vpiConstant);
delete [] rfp->value;
free(rfp);
return 1;
}
static const struct __vpirt vpip_string_temp_rt = {
vpiConstant,
string_get,
0,
string_value,
0,
0,
0,
0,
free_temp_string
};
/*
* Strings are described at the level of the vvp source as a string
* with literal characters or octal escapes. No other escapes are
* included, they are processed already by the compiler that generated
* the vvp source.
*/
static void vpip_process_string(struct __vpiStringConst*obj)
{
char*chr = obj->value;
char*dp = obj->value;
while (*chr) {
char next_char = *chr;
/* Process octal escapes that I might find. */
if (*chr == '\\') {
for (int idx = 1 ; idx <= 3 ; idx += 1) {
assert(chr[idx] != 0);
assert(chr[idx] < '8');
assert(chr[idx] >= '0');
next_char = next_char*8 + chr[idx] - '0';
}
chr += 3;
}
*dp++ = next_char;
chr += 1;
}
*dp = 0;
obj->value_len = dp - obj->value;
}
vpiHandle vpip_make_string_const(char*text, bool persistent_flag)
{
struct __vpiStringConst*obj;
obj = (struct __vpiStringConst*)
malloc(sizeof (struct __vpiStringConst));
obj->base.vpi_type = persistent_flag
? &vpip_string_rt
: &vpip_string_temp_rt;
obj->value = text;
obj->value_len = 0;
vpip_process_string(obj);
return &obj->base;
}
2003-03-11 00:37:07 +01:00
struct __vpiStringParam : public __vpiStringConst {
const char*basename;
struct __vpiScope* scope;
unsigned file_idx;
unsigned lineno;
2003-03-11 00:37:07 +01:00
};
static int string_param_get(int code, vpiHandle ref)
{
struct __vpiStringParam*rfp = (struct __vpiStringParam*)ref;
assert(ref->vpi_type->type_code == vpiParameter);
if (code == vpiLineNo) {
return rfp->lineno;
}
return string_get(code, ref);
}
2003-03-11 00:37:07 +01:00
static char* string_param_get_str(int code, vpiHandle obj)
{
struct __vpiStringParam*rfp = (struct __vpiStringParam*)obj;
2003-03-13 05:59:21 +01:00
2003-03-11 00:37:07 +01:00
assert(obj->vpi_type->type_code == vpiParameter);
if (code == vpiFile) {
return simple_set_rbuf_str(file_names[rfp->file_idx]);
}
return generic_get_str(code, &rfp->scope->base, rfp->basename, NULL);
}
static vpiHandle string_param_handle(int code, vpiHandle obj)
{
struct __vpiStringParam*rfp = (struct __vpiStringParam*)obj;
assert(obj->vpi_type->type_code == vpiParameter);
switch (code) {
case vpiScope:
return &rfp->scope->base;
case vpiModule:
return vpip_module(rfp->scope);
2003-03-11 00:37:07 +01:00
default:
return 0;
}
}
static const struct __vpirt vpip_string_param_rt = {
vpiParameter,
string_param_get,
2003-03-11 00:37:07 +01:00
string_param_get_str,
string_value,
0,
string_param_handle,
2003-03-11 00:37:07 +01:00
0,
0,
0
};
vpiHandle vpip_make_string_param(char*name, char*text,
long file_idx, long lineno)
2003-03-11 00:37:07 +01:00
{
struct __vpiStringParam*obj;
obj = (struct __vpiStringParam*)
malloc(sizeof (struct __vpiStringParam));
obj->base.vpi_type = &vpip_string_param_rt;
obj->value = text;
obj->value_len = 0;
2003-03-11 00:37:07 +01:00
obj->basename = name;
obj->scope = vpip_peek_current_scope();
obj->file_idx = (unsigned) file_idx;
obj->lineno = (unsigned) lineno;
2003-03-11 00:37:07 +01:00
vpip_process_string(obj);
2003-03-11 00:37:07 +01:00
return &obj->base;
}
static int binary_get(int code, vpiHandle ref)
{
struct __vpiBinaryConst*rfp = (struct __vpiBinaryConst*)ref;
2006-03-08 06:29:42 +01:00
assert(ref->vpi_type->type_code == vpiConstant
|| ref->vpi_type->type_code == vpiParameter);
switch (code) {
case vpiConstType:
return vpiBinaryConst;
case vpiLineNo:
return 0; // Not implemented for now!
case vpiSigned:
return rfp->signed_flag? 1 : 0;
case vpiSize:
2006-03-06 06:43:15 +01:00
return rfp->bits.size();
case vpiAutomatic:
return 0;
#ifdef CHECK_WITH_VALGRIND
case _vpiFromThr:
return _vpiNoThr;
#endif
default:
fprintf(stderr, "vvp error: get %d not supported "
"by vpiBinaryConst\n", code);
assert(0);
return 0;
}
}
static void binary_value(vpiHandle ref, p_vpi_value vp)
{
2006-03-08 06:29:42 +01:00
assert(ref->vpi_type->type_code == vpiConstant
|| ref->vpi_type->type_code == vpiParameter);
2003-03-13 05:59:21 +01:00
struct __vpiBinaryConst*rfp = (struct __vpiBinaryConst*)ref;
switch (vp->format) {
case vpiObjTypeVal:
2006-03-06 06:43:15 +01:00
case vpiBinStrVal:
case vpiDecStrVal:
case vpiOctStrVal:
case vpiHexStrVal:
case vpiScalarVal:
2006-03-06 06:43:15 +01:00
case vpiIntVal:
case vpiVectorVal:
2002-04-28 01:26:24 +02:00
case vpiStringVal:
2006-03-06 06:43:15 +01:00
case vpiRealVal:
vpip_vec4_get_value(rfp->bits, rfp->bits.size(),
rfp->signed_flag, vp);
2002-04-28 01:26:24 +02:00
break;
default:
fprintf(stderr, "vvp error: format %d not supported "
"by vpiBinaryConst\n", vp->format);
vp->format = vpiSuppressVal;
break;
}
}
static const struct __vpirt vpip_binary_rt = {
vpiConstant,
binary_get,
0,
binary_value,
0,
0,
0
};
/*
* Make a VPI constant from a vector string. The string is normally a
* ASCII string, with each letter a 4-value bit. The first character
* may be an 's' if the vector is signed.
*/
vpiHandle vpip_make_binary_const(unsigned wid, const char*bits)
{
struct __vpiBinaryConst*obj;
2006-03-08 06:29:42 +01:00
obj = new __vpiBinaryConst;
obj->base.vpi_type = &vpip_binary_rt;
obj->signed_flag = 0;
obj->sized_flag = 0;
2006-03-06 06:43:15 +01:00
obj->bits = vvp_vector4_t(wid);
const char*bp = bits;
if (*bp == 's') {
bp += 1;
obj->signed_flag = 1;
}
2006-03-06 06:43:15 +01:00
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_bit4_t val = BIT4_0;
switch (bp[wid-idx-1]) {
case '0':
2006-03-06 06:43:15 +01:00
val = BIT4_0;
break;
case '1':
2006-03-06 06:43:15 +01:00
val = BIT4_1;
break;
case 'x':
2006-03-06 06:43:15 +01:00
val = BIT4_X;
break;
case 'z':
2006-03-06 06:43:15 +01:00
val = BIT4_Z;
break;
}
2006-03-06 06:43:15 +01:00
obj->bits.set_bit(idx, val);
}
return &(obj->base);
}
2006-03-08 06:29:42 +01:00
struct __vpiBinaryParam : public __vpiBinaryConst {
const char*basename;
struct __vpiScope*scope;
unsigned file_idx;
unsigned lineno;
2006-03-08 06:29:42 +01:00
};
static int binary_param_get(int code, vpiHandle ref)
{
struct __vpiBinaryParam*rfp = (struct __vpiBinaryParam*)ref;
assert(ref->vpi_type->type_code == vpiParameter);
if (code == vpiLineNo) {
return rfp->lineno;
}
return binary_get(code, ref);
}
2006-03-08 06:29:42 +01:00
static char* binary_param_get_str(int code, vpiHandle obj)
{
struct __vpiBinaryParam*rfp = (struct __vpiBinaryParam*)obj;
assert(obj->vpi_type->type_code == vpiParameter);
if (code == vpiFile) {
return simple_set_rbuf_str(file_names[rfp->file_idx]);
}
return generic_get_str(code, &rfp->scope->base, rfp->basename, NULL);
2006-03-08 06:29:42 +01:00
}
static vpiHandle binary_param_handle(int code, vpiHandle obj)
{
struct __vpiBinaryParam*rfp = (struct __vpiBinaryParam*)obj;
assert(obj->vpi_type->type_code == vpiParameter);
switch (code) {
case vpiScope:
return &rfp->scope->base;
case vpiModule:
return vpip_module(rfp->scope);
2006-03-08 06:29:42 +01:00
default:
return 0;
}
}
static const struct __vpirt vpip_binary_param_rt = {
vpiParameter,
binary_param_get,
2006-03-08 06:29:42 +01:00
binary_param_get_str,
binary_value,
0,
binary_param_handle,
0,
0,
0
};
vpiHandle vpip_make_binary_param(char*name, const vvp_vector4_t&bits,
bool signed_flag,
long file_idx, long lineno)
2006-03-08 06:29:42 +01:00
{
struct __vpiBinaryParam*obj = new __vpiBinaryParam;
obj->base.vpi_type = &vpip_binary_param_rt;
obj->bits = bits;
obj->signed_flag = signed_flag? 1 : 0;
obj->sized_flag = 0;
2006-03-08 06:29:42 +01:00
obj->basename = name;
obj->scope = vpip_peek_current_scope();
obj->file_idx = (unsigned) file_idx;
obj->lineno = (unsigned) lineno;
2006-03-08 06:29:42 +01:00
return &obj->base;
}
static int dec_get(int code, vpiHandle ref)
{
switch (code) {
case vpiConstType:
return vpiDecConst;
case vpiSigned:
return 1;
case vpiSize:
return 32;
case vpiAutomatic:
return 0;
#ifdef CHECK_WITH_VALGRIND
case _vpiFromThr:
return _vpiNoThr;
#endif
default:
fprintf(stderr, "vvp error: get %d not supported "
"by vpiDecConst\n", code);
assert(0);
return 0;
}
}
static void dec_value(vpiHandle ref, p_vpi_value vp)
{
struct __vpiDecConst*rfp = (struct __vpiDecConst*)ref;
assert(ref->vpi_type->type_code == vpiConstant);
2003-03-13 05:59:21 +01:00
char*rbuf = need_result_buf(64 + 1, RBUF_VAL);
char*cp = rbuf;
switch (vp->format) {
case vpiObjTypeVal:
case vpiIntVal: {
vp->value.integer = rfp->value;
break;
}
case vpiDecStrVal:
2003-03-13 05:59:21 +01:00
sprintf(rbuf, "%d", rfp->value);
2003-03-13 05:59:21 +01:00
vp->value.str = rbuf;
break;
case vpiBinStrVal:
for(int bit=31; bit<=0;bit--){
*cp++ = "01"[ (rfp->value>>bit)&1 ];
}
*cp = 0;
2003-03-13 05:59:21 +01:00
vp->value.str = rbuf;
break;
case vpiHexStrVal:
2003-03-13 05:59:21 +01:00
sprintf(rbuf, "%08x", rfp->value);
2003-03-13 05:59:21 +01:00
vp->value.str = rbuf;
break;
case vpiOctStrVal:
2003-03-13 05:59:21 +01:00
sprintf(rbuf, "%011x", rfp->value);
2003-03-13 05:59:21 +01:00
vp->value.str = rbuf;
break;
default:
fprintf(stderr, "vvp error (vpi_const.cc): format %d not supported "
"by vpiDecConst\n", vp->format);
vp->format = vpiSuppressVal;
break;
}
}
static const struct __vpirt vpip_dec_rt = {
vpiConstant,
dec_get,
0,
dec_value,
0,
0,
0
};
vpiHandle vpip_make_dec_const(struct __vpiDecConst*obj, int value)
{
obj->base.vpi_type = &vpip_dec_rt;
obj->value = value;
return &(obj->base);
}
vpiHandle vpip_make_dec_const(int value)
{
struct __vpiDecConst*obj;
obj = (struct __vpiDecConst*)
malloc(sizeof (struct __vpiDecConst));
return vpip_make_dec_const(obj, value);
}
static int real_get(int code, vpiHandle ref)
{
switch (code) {
case vpiLineNo:
return 0; // Not implemented for now!
case vpiSize:
return 1;
case vpiConstType:
return vpiRealConst;
case vpiSigned:
return 1;
case vpiAutomatic:
return 0;
#ifdef CHECK_WITH_VALGRIND
case _vpiFromThr:
return _vpiNoThr;
#endif
default:
fprintf(stderr, "vvp error: get %d not supported "
"by vpiDecConst\n", code);
assert(0);
return 0;
}
}
static void real_value(vpiHandle ref, p_vpi_value vp)
{
struct __vpiRealConst*rfp = (struct __vpiRealConst*)ref;
assert((ref->vpi_type->type_code == vpiConstant) ||
(ref->vpi_type->type_code == vpiParameter));
vpip_real_get_value(rfp->value, vp);
}
static const struct __vpirt vpip_real_rt = {
vpiConstant,
real_get,
0,
real_value,
0,
0,
0
};
vpiHandle vpip_make_real_const(struct __vpiRealConst*obj, double value)
{
obj->base.vpi_type = &vpip_real_rt;
obj->value = value;
return &(obj->base);
}
vpiHandle vpip_make_real_const(double value)
{
struct __vpiRealConst*obj;
obj =(struct __vpiRealConst*) malloc(sizeof (struct __vpiRealConst));
return vpip_make_real_const(obj, value);
}
struct __vpiRealParam : public __vpiRealConst {
const char*basename;
struct __vpiScope* scope;
unsigned file_idx;
unsigned lineno;
};
static int real_param_get(int code, vpiHandle ref)
{
struct __vpiRealParam*rfp = (struct __vpiRealParam*)ref;
assert(ref->vpi_type->type_code == vpiParameter);
if (code == vpiLineNo) {
return rfp->lineno;
}
return real_get(code, ref);
}
static char* real_param_get_str(int code, vpiHandle obj)
{
struct __vpiRealParam*rfp = (struct __vpiRealParam*)obj;
assert(obj->vpi_type->type_code == vpiParameter);
if (code == vpiFile) {
return simple_set_rbuf_str(file_names[rfp->file_idx]);
}
return generic_get_str(code, &rfp->scope->base, rfp->basename, NULL);
}
static vpiHandle real_param_handle(int code, vpiHandle obj)
{
struct __vpiRealParam*rfp = (struct __vpiRealParam*)obj;
assert(obj->vpi_type->type_code == vpiParameter);
switch (code) {
case vpiScope:
return &rfp->scope->base;
case vpiModule:
return vpip_module(rfp->scope);
default:
return 0;
}
}
static const struct __vpirt vpip_real_param_rt = {
vpiParameter,
real_param_get,
real_param_get_str,
real_value,
0,
real_param_handle,
0,
0,
0
};
vpiHandle vpip_make_real_param(char*name, double value,
long file_idx, long lineno)
{
struct __vpiRealParam*obj;
obj = (struct __vpiRealParam*)
malloc(sizeof (struct __vpiRealParam));
obj->base.vpi_type = &vpip_real_param_rt;
obj->value = value;
obj->basename = name;
obj->scope = vpip_peek_current_scope();
obj->file_idx = (unsigned) file_idx;
obj->lineno = (unsigned) lineno;
return &obj->base;
}
#ifdef CHECK_WITH_VALGRIND
void constant_delete(vpiHandle item)
{
assert(item->vpi_type->type_code == vpiConstant);
switch(vpi_get(vpiConstType, item)) {
case vpiStringConst: {
struct __vpiStringConst*rfp = (struct __vpiStringConst*)item;
delete [] rfp->value;
free(rfp);
break; }
case vpiDecConst: {
struct __vpiDecConst*rfp = (struct __vpiDecConst*)item;
free(rfp);
break; }
case vpiBinaryConst: {
struct __vpiBinaryConst*rfp = (struct __vpiBinaryConst*)item;
delete rfp;
break; }
case vpiRealConst: {
struct __vpiRealConst*rfp = (struct __vpiRealConst*)item;
free(rfp);
break; }
default:
assert(0);
}
}
void parameter_delete(vpiHandle item)
{
switch(vpi_get(vpiConstType, item)) {
case vpiStringConst: {
struct __vpiStringParam*rfp = (struct __vpiStringParam*)item;
delete [] rfp->basename;
delete [] rfp->value;
free(rfp);
break; }
case vpiBinaryConst: {
struct __vpiBinaryParam*rfp = (struct __vpiBinaryParam*)item;
delete [] rfp->basename;
delete rfp;
break; }
case vpiRealConst: {
struct __vpiRealParam*rfp = (struct __vpiRealParam*)item;
delete [] rfp->basename;
free(rfp);
break; }
default:
assert(0);
}
}
#endif