2001-03-20 07:16:23 +01:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2001 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
|
|
|
|
|
*/
|
|
|
|
|
#if !defined(WINNT)
|
2001-12-18 06:31:54 +01:00
|
|
|
#ident "$Id: vpi_signal.cc,v 1.31 2001/12/18 05:31:54 steve Exp $"
|
2001-03-20 07:16:23 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* vpiReg handles are handled here. These objects represent vectors of
|
|
|
|
|
* .var objects that can be manipulated by the VPI module.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
# include "vpi_priv.h"
|
2001-03-21 06:13:03 +01:00
|
|
|
# include "functor.h"
|
2001-05-09 06:23:18 +02:00
|
|
|
# include <stdio.h>
|
2001-09-15 20:27:04 +02:00
|
|
|
#ifdef HAVE_MALLOC_H
|
2001-03-20 07:16:23 +01:00
|
|
|
# include <malloc.h>
|
2001-09-15 20:27:04 +02:00
|
|
|
#endif
|
|
|
|
|
# include <stdlib.h>
|
2001-06-29 02:44:56 +02:00
|
|
|
# include <string.h>
|
2001-03-20 07:16:23 +01:00
|
|
|
# include <assert.h>
|
|
|
|
|
|
2001-03-25 22:45:09 +02:00
|
|
|
/*
|
|
|
|
|
* Hex digits that represent 4-value bits of Verilog are not as
|
|
|
|
|
* trivially obvious to display as if the bits were the usual 2-value
|
|
|
|
|
* bits. So, although it is possible to write a function that
|
|
|
|
|
* generates a correct character for 4*4-value bits, it is easier to
|
|
|
|
|
* just perform the lookup in a table. This only takes 256 bytes,
|
|
|
|
|
* which is not many executable instructions:-)
|
|
|
|
|
*
|
|
|
|
|
* The table is calculated as compile time, therefore, by the
|
|
|
|
|
* draw_tt.c program.
|
|
|
|
|
*/
|
2001-03-25 21:38:05 +02:00
|
|
|
extern const char hex_digits[256];
|
|
|
|
|
|
2001-03-25 22:45:09 +02:00
|
|
|
extern const char oct_digits[256];
|
|
|
|
|
|
2001-12-18 06:31:54 +01:00
|
|
|
/*
|
|
|
|
|
* The string values need a result buf to hold the results. This
|
|
|
|
|
* buffer can be reused for that purpose. Whenever I have a need, the
|
|
|
|
|
* need_result_buf function makes sure that need can be met.
|
|
|
|
|
*/
|
|
|
|
|
static char*result_buf = 0;
|
|
|
|
|
static size_t result_buf_size = 0;
|
|
|
|
|
static void need_result_buf(size_t cnt)
|
|
|
|
|
{
|
|
|
|
|
if (result_buf_size == 0) {
|
|
|
|
|
result_buf = (char*)malloc(cnt);
|
|
|
|
|
} else if (result_buf_size < cnt) {
|
|
|
|
|
result_buf = (char*)realloc(result_buf, cnt);
|
|
|
|
|
}
|
|
|
|
|
result_buf_size = cnt;
|
|
|
|
|
}
|
|
|
|
|
|
2001-03-20 07:16:23 +01:00
|
|
|
/*
|
|
|
|
|
* implement vpi_get for vpiReg objects.
|
|
|
|
|
*/
|
|
|
|
|
static int signal_get(int code, vpiHandle ref)
|
|
|
|
|
{
|
|
|
|
|
assert((ref->vpi_type->type_code==vpiNet)
|
|
|
|
|
|| (ref->vpi_type->type_code==vpiReg));
|
|
|
|
|
|
|
|
|
|
struct __vpiSignal*rfp = (struct __vpiSignal*)ref;
|
|
|
|
|
|
|
|
|
|
switch (code) {
|
|
|
|
|
|
|
|
|
|
case vpiSigned:
|
2001-04-04 19:43:19 +02:00
|
|
|
return rfp->signed_flag != 0;
|
2001-03-20 07:16:23 +01:00
|
|
|
|
|
|
|
|
case vpiSize:
|
|
|
|
|
if (rfp->msb >= rfp->lsb)
|
|
|
|
|
return rfp->msb - rfp->lsb + 1;
|
|
|
|
|
else
|
|
|
|
|
return rfp->lsb - rfp->msb + 1;
|
|
|
|
|
|
2001-09-30 07:18:46 +02:00
|
|
|
case _vpiNexusId:
|
|
|
|
|
if (rfp->msb == rfp->lsb)
|
|
|
|
|
return vvp_fvector_get(rfp->bits, 0);
|
|
|
|
|
else
|
|
|
|
|
return 0;
|
|
|
|
|
|
2001-03-20 07:16:23 +01:00
|
|
|
default:
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char* signal_get_str(int code, vpiHandle ref)
|
|
|
|
|
{
|
|
|
|
|
assert((ref->vpi_type->type_code==vpiNet)
|
|
|
|
|
|| (ref->vpi_type->type_code==vpiReg));
|
|
|
|
|
|
|
|
|
|
struct __vpiSignal*rfp = (struct __vpiSignal*)ref;
|
|
|
|
|
|
2001-06-29 02:44:56 +02:00
|
|
|
static char full_name[4096];
|
|
|
|
|
|
2001-03-20 07:16:23 +01:00
|
|
|
switch (code) {
|
|
|
|
|
|
|
|
|
|
case vpiFullName:
|
2001-06-29 02:44:56 +02:00
|
|
|
strcpy(full_name, vpi_get_str(vpiFullName, &rfp->scope->base));
|
|
|
|
|
strcat(full_name, ".");
|
|
|
|
|
strcat(full_name, rfp->name);
|
|
|
|
|
return full_name;
|
|
|
|
|
|
|
|
|
|
case vpiName:
|
2001-03-20 07:16:23 +01:00
|
|
|
return (char*)rfp->name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2001-10-15 03:49:50 +02:00
|
|
|
static vpiHandle signal_get_handle(int code, vpiHandle ref)
|
|
|
|
|
{
|
|
|
|
|
assert((ref->vpi_type->type_code==vpiNet)
|
|
|
|
|
|| (ref->vpi_type->type_code==vpiReg));
|
|
|
|
|
|
|
|
|
|
struct __vpiSignal*rfp = (struct __vpiSignal*)ref;
|
|
|
|
|
|
|
|
|
|
switch (code) {
|
|
|
|
|
|
|
|
|
|
case vpiScope:
|
|
|
|
|
return &rfp->scope->base;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2001-03-21 06:13:03 +01:00
|
|
|
|
2001-04-04 19:43:19 +02:00
|
|
|
static void signal_vpiDecStrVal(struct __vpiSignal*rfp, s_vpi_value*vp)
|
|
|
|
|
{
|
|
|
|
|
unsigned wid = (rfp->msb >= rfp->lsb)
|
|
|
|
|
? (rfp->msb - rfp->lsb + 1)
|
|
|
|
|
: (rfp->lsb - rfp->msb + 1);
|
|
|
|
|
|
|
|
|
|
unsigned long val = 0;
|
|
|
|
|
unsigned count_x = 0, count_z = 0;
|
|
|
|
|
|
|
|
|
|
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
2001-08-08 03:05:06 +02:00
|
|
|
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, wid-idx-1);
|
2001-04-04 19:43:19 +02:00
|
|
|
val *= 2;
|
2001-10-31 05:27:46 +01:00
|
|
|
switch (functor_get(fptr)) {
|
2001-04-04 19:43:19 +02:00
|
|
|
case 0:
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
val += 1;
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
count_x += 1;
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
count_z += 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (count_x == wid) {
|
2001-12-18 06:31:54 +01:00
|
|
|
need_result_buf(2);
|
|
|
|
|
result_buf[0] = 'x';
|
|
|
|
|
result_buf[1] = 0;
|
2001-04-04 19:43:19 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (count_x > 0) {
|
2001-12-18 06:31:54 +01:00
|
|
|
need_result_buf(2);
|
|
|
|
|
result_buf[0] = 'X';
|
|
|
|
|
result_buf[1] = 0;
|
2001-04-04 19:43:19 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (count_z == wid) {
|
2001-12-18 06:31:54 +01:00
|
|
|
need_result_buf(2);
|
|
|
|
|
result_buf[0] = 'z';
|
|
|
|
|
result_buf[1] = 0;
|
2001-04-04 19:43:19 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (count_z > 0) {
|
2001-12-18 06:31:54 +01:00
|
|
|
need_result_buf(2);
|
|
|
|
|
result_buf[0] = 'Z';
|
|
|
|
|
result_buf[1] = 0;
|
2001-04-04 19:43:19 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2001-12-18 06:31:54 +01:00
|
|
|
need_result_buf((wid+2) / 3 + 1);
|
|
|
|
|
|
2001-04-04 19:43:19 +02:00
|
|
|
if (rfp->signed_flag) {
|
2001-05-22 06:08:49 +02:00
|
|
|
long tmp;
|
|
|
|
|
assert(sizeof(tmp) == sizeof(val));
|
|
|
|
|
if (val & (1<<(wid-1)) && wid < 8*sizeof(tmp)) {
|
|
|
|
|
tmp = -1;
|
|
|
|
|
tmp <<= wid;
|
|
|
|
|
tmp |= val;
|
|
|
|
|
} else {
|
|
|
|
|
tmp = val;
|
|
|
|
|
}
|
2001-12-18 06:31:54 +01:00
|
|
|
sprintf(result_buf, "%ld", tmp);
|
|
|
|
|
assert(strlen(result_buf) < result_buf_size);
|
2001-05-22 06:08:49 +02:00
|
|
|
|
2001-04-04 19:43:19 +02:00
|
|
|
} else {
|
2001-12-18 06:31:54 +01:00
|
|
|
sprintf(result_buf, "%lu", val);
|
|
|
|
|
assert(strlen(result_buf) < result_buf_size);
|
2001-04-04 19:43:19 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-07-24 03:34:56 +02:00
|
|
|
static void signal_vpiStringVal(struct __vpiSignal*rfp, s_vpi_value*vp)
|
|
|
|
|
{
|
|
|
|
|
char*cp;
|
|
|
|
|
unsigned idx;
|
|
|
|
|
unsigned wid = (rfp->msb >= rfp->lsb)
|
|
|
|
|
? (rfp->msb - rfp->lsb + 1)
|
|
|
|
|
: (rfp->lsb - rfp->msb + 1);
|
|
|
|
|
|
|
|
|
|
assert(wid % 8 == 0);
|
|
|
|
|
|
2001-12-18 06:31:54 +01:00
|
|
|
/* The result will use a character for each 8 bits of the
|
|
|
|
|
vector. */
|
|
|
|
|
need_result_buf(wid/8 + 1);
|
|
|
|
|
|
|
|
|
|
cp = result_buf;
|
2001-07-24 03:34:56 +02:00
|
|
|
for (idx = wid ; idx >= 8 ; idx -= 8) {
|
|
|
|
|
char tmp = 0;
|
|
|
|
|
unsigned bdx;
|
|
|
|
|
|
|
|
|
|
for (bdx = 8 ; bdx > 0 ; bdx -= 1) {
|
2001-08-08 03:05:06 +02:00
|
|
|
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx-8+bdx-1);
|
2001-07-24 03:34:56 +02:00
|
|
|
tmp <<= 1;
|
2001-10-31 05:27:46 +01:00
|
|
|
switch (functor_get(fptr)) {
|
2001-07-24 03:34:56 +02:00
|
|
|
case 0:
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
tmp |= 1;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*cp++ = tmp? tmp : ' ';
|
|
|
|
|
}
|
|
|
|
|
*cp++ = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2001-03-20 07:16:23 +01:00
|
|
|
/*
|
|
|
|
|
* The get_value method reads the values of the functors and returns
|
|
|
|
|
* the vector to the caller. This causes no side-effect, and reads the
|
|
|
|
|
* variables like a %load would.
|
|
|
|
|
*/
|
|
|
|
|
static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
|
|
|
|
|
{
|
|
|
|
|
assert((ref->vpi_type->type_code==vpiNet)
|
|
|
|
|
|| (ref->vpi_type->type_code==vpiReg));
|
|
|
|
|
|
|
|
|
|
struct __vpiSignal*rfp = (struct __vpiSignal*)ref;
|
|
|
|
|
|
2001-03-21 06:13:03 +01:00
|
|
|
unsigned wid = (rfp->msb >= rfp->lsb)
|
|
|
|
|
? (rfp->msb - rfp->lsb + 1)
|
|
|
|
|
: (rfp->lsb - rfp->msb + 1);
|
|
|
|
|
|
|
|
|
|
switch (vp->format) {
|
|
|
|
|
|
2001-05-15 17:09:08 +02:00
|
|
|
case vpiIntVal:
|
|
|
|
|
assert(wid <= 8 * sizeof vp->value.integer);
|
|
|
|
|
vp->value.integer = 0;
|
|
|
|
|
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
2001-08-08 03:05:06 +02:00
|
|
|
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
|
2001-10-31 05:27:46 +01:00
|
|
|
switch (functor_get(fptr)) {
|
2001-05-15 17:09:08 +02:00
|
|
|
case 0:
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
vp->value.integer |= 1<<idx;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
idx = wid;
|
|
|
|
|
vp->value.integer = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2001-03-21 06:13:03 +01:00
|
|
|
case vpiBinStrVal:
|
2001-12-18 06:31:54 +01:00
|
|
|
need_result_buf(wid+1);
|
|
|
|
|
|
2001-03-21 06:13:03 +01:00
|
|
|
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
2001-08-08 03:05:06 +02:00
|
|
|
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
|
2001-12-18 06:31:54 +01:00
|
|
|
result_buf[wid-idx-1] = "01xz"[functor_get(fptr)];
|
2001-03-21 06:13:03 +01:00
|
|
|
}
|
2001-12-18 06:31:54 +01:00
|
|
|
result_buf[wid] = 0;
|
|
|
|
|
vp->value.str = result_buf;
|
2001-03-21 06:13:03 +01:00
|
|
|
break;
|
|
|
|
|
|
2001-03-25 21:38:05 +02:00
|
|
|
case vpiHexStrVal: {
|
|
|
|
|
unsigned hval, hwid;
|
|
|
|
|
hwid = (wid + 3) / 4;
|
2001-12-18 06:31:54 +01:00
|
|
|
|
|
|
|
|
need_result_buf(hwid+1);
|
|
|
|
|
result_buf[hwid] = 0;
|
2001-03-25 21:38:05 +02:00
|
|
|
hval = 0;
|
|
|
|
|
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
2001-08-08 03:05:06 +02:00
|
|
|
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
|
2001-10-31 05:27:46 +01:00
|
|
|
hval = hval | (functor_get(fptr) << 2*(idx % 4));
|
2001-03-25 21:38:05 +02:00
|
|
|
|
|
|
|
|
if (idx%4 == 3) {
|
|
|
|
|
hwid -= 1;
|
2001-12-18 06:31:54 +01:00
|
|
|
result_buf[hwid] = hex_digits[hval];
|
2001-03-25 21:38:05 +02:00
|
|
|
hval = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hwid > 0) {
|
|
|
|
|
hwid -= 1;
|
2001-12-18 06:31:54 +01:00
|
|
|
result_buf[hwid] = hex_digits[hval];
|
2001-07-16 20:48:07 +02:00
|
|
|
unsigned padd = 0;
|
2001-12-18 06:31:54 +01:00
|
|
|
switch(result_buf[hwid]) {
|
2001-07-16 20:48:07 +02:00
|
|
|
case 'X': padd = 2; break;
|
|
|
|
|
case 'Z': padd = 3; break;
|
|
|
|
|
}
|
|
|
|
|
if (padd) {
|
|
|
|
|
for (unsigned idx = wid % 4; idx < 4; idx += 1) {
|
|
|
|
|
hval = hval | padd << 2*idx;
|
|
|
|
|
}
|
2001-12-18 06:31:54 +01:00
|
|
|
result_buf[hwid] = hex_digits[hval];
|
2001-07-16 20:48:07 +02:00
|
|
|
}
|
2001-03-25 21:38:05 +02:00
|
|
|
}
|
2001-12-18 06:31:54 +01:00
|
|
|
vp->value.str = result_buf;
|
2001-03-25 21:38:05 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2001-03-25 22:45:09 +02:00
|
|
|
case vpiOctStrVal: {
|
|
|
|
|
unsigned hval, hwid;
|
|
|
|
|
hwid = (wid + 2) / 3;
|
2001-12-18 06:31:54 +01:00
|
|
|
|
|
|
|
|
need_result_buf(hwid+1);
|
|
|
|
|
result_buf[hwid] = 0;
|
2001-03-25 22:45:09 +02:00
|
|
|
hval = 0;
|
|
|
|
|
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
2001-08-08 03:05:06 +02:00
|
|
|
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
|
2001-10-31 05:27:46 +01:00
|
|
|
hval = hval | (functor_get(fptr) << 2*(idx % 3));
|
2001-03-25 22:45:09 +02:00
|
|
|
|
|
|
|
|
if (idx%3 == 2) {
|
|
|
|
|
hwid -= 1;
|
2001-12-18 06:31:54 +01:00
|
|
|
result_buf[hwid] = oct_digits[hval];
|
2001-03-25 22:45:09 +02:00
|
|
|
hval = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hwid > 0) {
|
|
|
|
|
hwid -= 1;
|
2001-12-18 06:31:54 +01:00
|
|
|
result_buf[hwid] = oct_digits[hval];
|
2001-07-16 20:48:07 +02:00
|
|
|
unsigned padd = 0;
|
2001-12-18 06:31:54 +01:00
|
|
|
switch(result_buf[hwid]) {
|
2001-07-16 20:48:07 +02:00
|
|
|
case 'X': padd = 2; break;
|
|
|
|
|
case 'Z': padd = 3; break;
|
|
|
|
|
}
|
|
|
|
|
if (padd) {
|
|
|
|
|
for (unsigned idx = wid % 3; idx < 3; idx += 1) {
|
|
|
|
|
hval = hval | padd << 2*idx;
|
|
|
|
|
}
|
2001-12-18 06:31:54 +01:00
|
|
|
result_buf[hwid] = oct_digits[hval];
|
2001-07-16 20:48:07 +02:00
|
|
|
}
|
2001-03-25 22:45:09 +02:00
|
|
|
}
|
2001-12-18 06:31:54 +01:00
|
|
|
vp->value.str = result_buf;
|
2001-03-25 22:45:09 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2001-04-04 19:43:19 +02:00
|
|
|
case vpiDecStrVal:
|
|
|
|
|
signal_vpiDecStrVal(rfp, vp);
|
2001-12-18 06:31:54 +01:00
|
|
|
vp->value.str = result_buf;
|
2001-04-04 19:43:19 +02:00
|
|
|
break;
|
|
|
|
|
|
2001-07-24 03:34:56 +02:00
|
|
|
case vpiStringVal:
|
|
|
|
|
signal_vpiStringVal(rfp, vp);
|
2001-12-18 06:31:54 +01:00
|
|
|
vp->value.str = result_buf;
|
2001-07-24 03:34:56 +02:00
|
|
|
break;
|
|
|
|
|
|
2001-10-18 06:52:31 +02:00
|
|
|
case vpiVectorVal:
|
|
|
|
|
{
|
|
|
|
|
s_vpi_vecval *op = vp->value.vector;
|
|
|
|
|
unsigned int obit = 0;
|
|
|
|
|
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
|
|
|
|
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
|
2001-10-31 05:27:46 +01:00
|
|
|
switch (functor_get(fptr)) {
|
2001-10-18 06:52:31 +02:00
|
|
|
case 0:
|
|
|
|
|
op->aval &= ~(1 << obit);
|
|
|
|
|
op->bval &= ~(1 << obit);
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
op->aval |= (1 << obit);
|
|
|
|
|
op->bval &= ~(1 << obit);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
op->aval &= ~(1 << obit);
|
|
|
|
|
op->bval |= (1 << obit);
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
op->aval |= (1 << obit);
|
|
|
|
|
op->bval |= (1 << obit);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
obit++;
|
|
|
|
|
if (obit == 8*sizeof(op->aval)) {
|
|
|
|
|
op++;
|
|
|
|
|
obit = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2001-03-21 06:13:03 +01:00
|
|
|
default:
|
2001-07-24 03:34:56 +02:00
|
|
|
fprintf(stderr, "vvp internal error: signal_get_value: "
|
|
|
|
|
"value type %u not implemented.\n", vp->format);
|
|
|
|
|
|
2001-03-21 06:13:03 +01:00
|
|
|
assert(0);
|
|
|
|
|
}
|
2001-03-20 07:16:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The put_value method writes the value into the vector, and returns
|
|
|
|
|
* the affected ref. This operation works much like the %set or
|
|
|
|
|
* %assign instructions and causes all the side-effects that the
|
|
|
|
|
* equivilent instruction would cause.
|
|
|
|
|
*/
|
2001-08-09 21:38:23 +02:00
|
|
|
|
|
|
|
|
static void functor_poke(struct __vpiSignal*rfp, unsigned idx,
|
|
|
|
|
unsigned val, unsigned str)
|
|
|
|
|
{
|
|
|
|
|
vvp_ipoint_t ptr = vvp_fvector_get(rfp->bits,idx);
|
|
|
|
|
functor_t fu = functor_index(ptr);
|
2001-12-06 04:31:24 +01:00
|
|
|
fu->put_ostr(val, str, true);
|
2001-08-09 21:38:23 +02:00
|
|
|
}
|
|
|
|
|
|
2001-03-20 07:16:23 +01:00
|
|
|
static vpiHandle signal_put_value(vpiHandle ref, s_vpi_value*vp,
|
2001-04-25 06:45:52 +02:00
|
|
|
p_vpi_time when, int flags)
|
2001-03-20 07:16:23 +01:00
|
|
|
{
|
2001-05-14 02:42:32 +02:00
|
|
|
unsigned wid;
|
|
|
|
|
struct __vpiSignal*rfp;
|
|
|
|
|
|
2001-03-20 07:16:23 +01:00
|
|
|
assert((ref->vpi_type->type_code==vpiNet)
|
|
|
|
|
|| (ref->vpi_type->type_code==vpiReg));
|
|
|
|
|
|
2001-05-14 02:42:32 +02:00
|
|
|
rfp = (struct __vpiSignal*)ref;
|
2001-03-20 07:16:23 +01:00
|
|
|
|
2001-04-25 06:45:52 +02:00
|
|
|
/* XXXX delays are not yet supported. */
|
|
|
|
|
assert(flags == vpiNoDelay);
|
|
|
|
|
|
2001-05-14 02:42:32 +02:00
|
|
|
wid = (rfp->msb >= rfp->lsb)
|
2001-04-25 06:45:52 +02:00
|
|
|
? (rfp->msb - rfp->lsb + 1)
|
|
|
|
|
: (rfp->lsb - rfp->msb + 1);
|
|
|
|
|
|
|
|
|
|
switch (vp->format) {
|
|
|
|
|
|
2001-04-26 02:01:33 +02:00
|
|
|
case vpiIntVal: {
|
2001-05-14 02:42:32 +02:00
|
|
|
if (wid > 8*sizeof(long)) {
|
|
|
|
|
fprintf(stderr, "internal error: wid(%u) "
|
|
|
|
|
"too large.\n", wid);
|
|
|
|
|
assert(0);
|
|
|
|
|
}
|
2001-08-09 21:38:23 +02:00
|
|
|
|
2001-04-26 02:01:33 +02:00
|
|
|
long val = vp->value.integer;
|
|
|
|
|
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
2001-08-09 21:38:23 +02:00
|
|
|
functor_poke(rfp, idx, val&1, (val&1)? St1 : St0);
|
2001-04-26 02:01:33 +02:00
|
|
|
val >>= 1;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2001-04-25 06:45:52 +02:00
|
|
|
case vpiScalarVal:
|
|
|
|
|
switch (vp->value.scalar) {
|
|
|
|
|
case vpi0:
|
2001-08-09 21:38:23 +02:00
|
|
|
functor_poke(rfp, 0, 0, St0);
|
2001-04-25 06:45:52 +02:00
|
|
|
break;
|
|
|
|
|
case vpi1:
|
2001-08-09 21:38:23 +02:00
|
|
|
functor_poke(rfp, 0, 1, St1);
|
2001-04-25 06:45:52 +02:00
|
|
|
break;
|
|
|
|
|
case vpiX:
|
2001-08-09 21:38:23 +02:00
|
|
|
functor_poke(rfp, 0, 2, StX);
|
2001-04-25 06:45:52 +02:00
|
|
|
break;
|
|
|
|
|
case vpiZ:
|
2001-08-09 21:38:23 +02:00
|
|
|
functor_poke(rfp, 0, 3, HiZ);
|
2001-04-25 06:45:52 +02:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
assert(0);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case vpiVectorVal: {
|
|
|
|
|
assert(wid <= sizeof (unsigned long));
|
|
|
|
|
|
|
|
|
|
unsigned long aval = vp->value.vector->aval;
|
|
|
|
|
unsigned long bval = vp->value.vector->bval;
|
|
|
|
|
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
|
|
|
|
int bit = (aval&1) | ((bval<<1)&2);
|
|
|
|
|
switch (bit) {
|
|
|
|
|
case 0: /* zero */
|
2001-08-09 21:38:23 +02:00
|
|
|
functor_poke(rfp,idx, 0, St0);
|
2001-04-25 06:45:52 +02:00
|
|
|
break;
|
|
|
|
|
case 1: /* one */
|
2001-08-09 21:38:23 +02:00
|
|
|
functor_poke(rfp,idx, 1, St1);
|
2001-04-25 06:45:52 +02:00
|
|
|
break;
|
|
|
|
|
case 2: /* z */
|
2001-08-09 21:38:23 +02:00
|
|
|
functor_poke(rfp,idx, 3, HiZ);
|
2001-04-25 06:45:52 +02:00
|
|
|
break;
|
|
|
|
|
case 3: /* x */
|
2001-08-09 21:38:23 +02:00
|
|
|
functor_poke(rfp,idx, 2, StX);
|
2001-04-25 06:45:52 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
aval >>= 1;
|
|
|
|
|
bval >>= 1;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
assert(0);
|
|
|
|
|
|
|
|
|
|
}
|
2001-03-20 07:16:23 +01:00
|
|
|
|
|
|
|
|
return ref;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const struct __vpirt vpip_reg_rt = {
|
|
|
|
|
vpiReg,
|
|
|
|
|
signal_get,
|
|
|
|
|
signal_get_str,
|
|
|
|
|
signal_get_value,
|
|
|
|
|
signal_put_value,
|
2001-10-15 03:49:50 +02:00
|
|
|
signal_get_handle,
|
2001-03-20 07:16:23 +01:00
|
|
|
0
|
|
|
|
|
};
|
|
|
|
|
|
2001-03-25 01:35:35 +01:00
|
|
|
static const struct __vpirt vpip_net_rt = {
|
|
|
|
|
vpiNet,
|
|
|
|
|
signal_get,
|
|
|
|
|
signal_get_str,
|
|
|
|
|
signal_get_value,
|
|
|
|
|
signal_put_value,
|
2001-10-15 03:49:50 +02:00
|
|
|
signal_get_handle,
|
2001-03-25 01:35:35 +01:00
|
|
|
0
|
|
|
|
|
};
|
|
|
|
|
|
2001-03-20 07:16:23 +01:00
|
|
|
/*
|
2001-07-13 05:02:34 +02:00
|
|
|
* Construct a vpiReg object. It's like a net, except for the type.
|
2001-03-20 07:16:23 +01:00
|
|
|
*/
|
2001-04-05 03:34:26 +02:00
|
|
|
vpiHandle vpip_make_reg(char*name, int msb, int lsb, bool signed_flag,
|
2001-08-08 03:05:06 +02:00
|
|
|
vvp_fvector_t vec)
|
2001-03-20 07:16:23 +01:00
|
|
|
{
|
2001-08-08 03:05:06 +02:00
|
|
|
vpiHandle obj = vpip_make_net(name, msb,lsb, signed_flag, vec);
|
2001-07-13 05:02:34 +02:00
|
|
|
obj->vpi_type = &vpip_reg_rt;
|
|
|
|
|
return obj;
|
2001-03-20 07:16:23 +01:00
|
|
|
}
|
|
|
|
|
|
2001-03-25 01:35:35 +01:00
|
|
|
/*
|
2001-07-13 05:02:34 +02:00
|
|
|
* Construct a vpiNet object. Give the object specified dimensions,
|
2001-03-25 01:35:35 +01:00
|
|
|
* and point to the specified functor for the lsb.
|
|
|
|
|
*/
|
2001-04-05 03:34:26 +02:00
|
|
|
vpiHandle vpip_make_net(char*name, int msb, int lsb, bool signed_flag,
|
2001-08-08 03:05:06 +02:00
|
|
|
vvp_fvector_t vec)
|
2001-03-25 01:35:35 +01:00
|
|
|
{
|
|
|
|
|
struct __vpiSignal*obj = (struct __vpiSignal*)
|
|
|
|
|
malloc(sizeof(struct __vpiSignal));
|
|
|
|
|
obj->base.vpi_type = &vpip_net_rt;
|
|
|
|
|
obj->name = name;
|
|
|
|
|
obj->msb = msb;
|
|
|
|
|
obj->lsb = lsb;
|
2001-04-05 03:34:26 +02:00
|
|
|
obj->signed_flag = signed_flag? 1 : 0;
|
2001-08-08 03:05:06 +02:00
|
|
|
obj->bits = vec;
|
|
|
|
|
obj->callback = 0;
|
2001-03-25 01:35:35 +01:00
|
|
|
|
|
|
|
|
obj->scope = vpip_peek_current_scope();
|
|
|
|
|
|
|
|
|
|
return &obj->base;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2001-03-20 07:16:23 +01:00
|
|
|
/*
|
|
|
|
|
* $Log: vpi_signal.cc,v $
|
2001-12-18 06:31:54 +01:00
|
|
|
* Revision 1.31 2001/12/18 05:31:54 steve
|
|
|
|
|
* Remove result length restrictions for vpi_get_value.
|
|
|
|
|
*
|
2001-12-06 04:31:24 +01:00
|
|
|
* Revision 1.30 2001/12/06 03:31:25 steve
|
|
|
|
|
* Support functor delays for gates and UDP devices.
|
|
|
|
|
* (Stephan Boettcher)
|
|
|
|
|
*
|
2001-11-07 04:34:41 +01:00
|
|
|
* Revision 1.29 2001/11/07 03:34:42 steve
|
|
|
|
|
* Use functor pointers where vvp_ipoint_t is unneeded.
|
|
|
|
|
*
|
2001-10-31 05:27:46 +01:00
|
|
|
* Revision 1.28 2001/10/31 04:27:47 steve
|
|
|
|
|
* Rewrite the functor type to have fewer functor modes,
|
|
|
|
|
* and use objects to manage the different types.
|
|
|
|
|
* (Stephan Boettcher)
|
|
|
|
|
*
|
2001-10-18 06:52:31 +02:00
|
|
|
* Revision 1.27 2001/10/18 04:52:31 steve
|
|
|
|
|
* Support vpiVectorVal for signals. (Philip Blundell)
|
|
|
|
|
*
|
2001-10-15 03:49:50 +02:00
|
|
|
* Revision 1.26 2001/10/15 01:49:50 steve
|
|
|
|
|
* Support getting scope of scope, and scope of signals.
|
|
|
|
|
*
|
2001-09-30 07:18:46 +02:00
|
|
|
* Revision 1.25 2001/09/30 05:18:46 steve
|
|
|
|
|
* Reduce VCD output by removing duplicates. (Stephan Boettcher)
|
|
|
|
|
*
|
2001-09-15 20:27:04 +02:00
|
|
|
* Revision 1.24 2001/09/15 18:27:05 steve
|
|
|
|
|
* Make configure detect malloc.h
|
|
|
|
|
*
|
2001-08-09 21:38:23 +02:00
|
|
|
* Revision 1.23 2001/08/09 19:38:23 steve
|
|
|
|
|
* Nets (wires) do not use their own functors.
|
|
|
|
|
* Modifications to propagation of values.
|
|
|
|
|
* (Stephan Boettcher)
|
2001-03-20 07:16:23 +01:00
|
|
|
*/
|
|
|
|
|
|