Add basic support for vpiBit

This commit is contained in:
Cary R 2020-05-31 00:24:32 -07:00
parent a1518b5761
commit 7eb0efd424
6 changed files with 395 additions and 15 deletions

View File

@ -1,7 +1,7 @@
#ifndef VPI_USER_H
#define VPI_USER_H
/*
* Copyright (c) 1999-2019 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2020 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
@ -286,12 +286,14 @@ typedef struct t_vpi_delay {
#define vpiNamedEvent 34
#define vpiNamedFork 35
#define vpiNet 36
#define vpiNetBit 37
#define vpiParameter 41
#define vpiPartSelect 42
#define vpiPathTerm 43
#define vpiPort 44
#define vpiRealVar 47
#define vpiReg 48
#define vpiRegBit 49
#define vpiSysFuncCall 56
#define vpiSysTaskCall 57
#define vpiTask 59

View File

@ -63,7 +63,7 @@ dllib=@DLLIB@
MDIR1 = -DMODULE_DIR1='"$(libdir)/ivl$(suffix)"'
VPI = vpi_modules.o vpi_callback.o vpi_cobject.o vpi_const.o vpi_darray.o \
VPI = vpi_modules.o vpi_bit.o vpi_callback.o vpi_cobject.o vpi_const.o vpi_darray.o \
vpi_event.o vpi_iter.o vpi_mcd.o \
vpi_priv.o vpi_scope.o vpi_real.o vpi_signal.o vpi_string.o vpi_tasks.o vpi_time.o \
vpi_vthr_vector.o vpip_bin.o vpip_hex.o vpip_oct.o \

238
vvp/vpi_bit.cc Normal file
View File

@ -0,0 +1,238 @@
/*
* Copyright (c) 2020 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*
* vpiNetBit and vpiRegBit are handled here along with some help from their
* parent singal or net.
*/
# include "compile.h"
# include "vpi_priv.h"
# include <cassert>
static const __vpiBit*bit_from_handle(const __vpiHandle*ref)
{
if (ref == NULL) return NULL;
const __vpiBit::as_bit_t*ptr = dynamic_cast<const __vpiBit::as_bit_t*> (ref);
if (ptr == NULL) return NULL;
return (const struct __vpiBit*) ref;
}
static __vpiBit*bit_from_handle(__vpiHandle*ref)
{
if (ref == NULL) return NULL;
__vpiBit::as_bit_t*ptr = dynamic_cast<__vpiBit::as_bit_t*> (ref);
if (ptr == NULL) return NULL;
return (struct __vpiBit*) ref;
}
static int bit_get_type(const __vpiBit*rfp)
{
assert(rfp);
const struct __vpiSignal*parent = rfp->get_parent();
assert(parent);
switch (parent->get_type_code()) {
case vpiNet:
return vpiNetBit;
case vpiReg:
return vpiRegBit;
}
assert(0);
}
static int bit_get(int code, vpiHandle ref)
{
struct __vpiBit*rfp = bit_from_handle(ref);
assert(rfp);
struct __vpiSignal*parent = rfp->get_parent();
assert(parent);
switch (code) {
case vpiArray: // A bit is not an array
return 0;
case vpiAutomatic:
return vpi_get(vpiAutomatic, parent);
case vpiIndex:
{
s_vpi_value vp;
vp.format = vpiIntVal;
vpi_get_value(rfp->index, &vp);
return vp.value.integer;
}
case vpiLineNo:
return vpi_get(vpiLineNo, parent);
case vpiScalar: // A bit is a scalar
return 1;
case vpiSigned: // A bit is unsigned
return 0;
case vpiSize: // A bit has a width of 1
return 1;
case vpiVector: // A bit is not a vector
return 0;
// FIXME: Do we need a _vpiFromThr or _vpiNexusID case?
default:
fprintf(stderr, "VPI error: unknown bit_get property %d.\n",
code);
return vpiUndefined;
}
}
static char* bit_get_str(int code, vpiHandle ref)
{
struct __vpiBit*rfp = bit_from_handle(ref);
assert(rfp);
if (code == vpiFile) { // Not implemented for now!
return simple_set_rbuf_str(file_names[0]);
}
if ((code != vpiName) && (code != vpiFullName)) return NULL;
struct __vpiSignal*parent = rfp->get_parent();
assert(parent);
char *nm, *ixs;
nm = strdup(vpi_get_str(vpiName, parent));
s_vpi_value vp;
vp.format = vpiDecStrVal;
vpi_get_value(rfp->index, &vp);
ixs = vp.value.str;
char *rbuf = generic_get_str(code, vpip_scope(parent), nm, ixs);
free(nm);
return rbuf;
}
static vpiHandle bit_get_handle(int code, vpiHandle ref)
{
struct __vpiBit*rfp = bit_from_handle(ref);
assert(rfp);
struct __vpiSignal*parent = rfp->get_parent();
assert(parent);
switch (code) {
case vpiIndex:
return rfp->index;
case vpiParent:
return parent;
case vpiScope:
return vpi_handle(vpiScope, parent);
case vpiModule:
return vpi_handle(vpiModule, parent);
}
return 0;
}
/*
static vpiHandle bit_iterate(int code, vpiHandle ref)
{
struct __vpiBit*rfp = bit_from_handle(ref);
assert(rfp);
(void) code;
return 0;
}
static vpiHandle bit_index(int idx, vpiHandle ref)
{
struct __vpiBit*rfp = bit_from_handle(ref);
assert(rfp);
(void) idx;
return 0;
}
*/
static void bit_get_value(vpiHandle ref, s_vpi_value*vp)
{
struct __vpiBit*rfp = bit_from_handle(ref);
assert(rfp);
struct __vpiSignal*parent = rfp->get_parent();
assert(parent);
parent->get_bit_value(rfp, vp);
}
static vpiHandle bit_put_value(vpiHandle ref, s_vpi_value*vp, int flags)
{
struct __vpiBit*rfp = bit_from_handle(ref);
assert(rfp);
(void) vp;
(void) flags;
fprintf(stderr, "Sorry: vpi_put_value() for %s type %s is not "
"implemented\n", vpi_get_str(vpiFullName, ref),
vpi_get_str(vpiType, ref));
// FIXME: Put the value to the net or reg bit.
return ref;
}
int __vpiBit::get_index(void) const
{
s_vpi_value vp;
vp.format = vpiIntVal;
vpi_get_value(index, &vp);
return vp.value.integer;
}
int __vpiBit::as_bit_t::get_type_code(void) const
{ return bit_get_type(bit_from_handle(this)); }
int __vpiBit::as_bit_t::vpi_get(int code)
{ return bit_get(code, this); }
char* __vpiBit::as_bit_t::vpi_get_str(int code)
{ return bit_get_str(code, this); }
void __vpiBit::as_bit_t::vpi_get_value(p_vpi_value val)
{ bit_get_value(this, val); }
vpiHandle __vpiBit::as_bit_t::vpi_put_value(p_vpi_value val, int flags)
{ return bit_put_value(this, val, flags); }
vpiHandle __vpiBit::as_bit_t::vpi_handle(int code)
{ return bit_get_handle(code, this); }
//vpiHandle __vpiBit::as_bit_t::vpi_iterate(int code) // FIXME: Is this needed?
//{ return bit_iterate(code, this); }
//vpiHandle __vpiBit::as_bit_t::vpi_index(int idx) // FIXME: Is this needed?
//{ return bit_index(idx, this); }

View File

@ -355,6 +355,8 @@ static const char* vpi_type_values(PLI_INT32 code)
return "vpiNet";
case vpiNetArray:
return "vpiNetArray";
case vpiNetBit:
return "vpiNetBit";
case vpiParameter:
return "vpiParameter";
case vpiPartSelect:
@ -363,6 +365,8 @@ static const char* vpi_type_values(PLI_INT32 code)
return "vpiRealVar";
case vpiReg:
return "vpiReg";
case vpiRegBit:
return "vpiRegBit";
case vpiShortIntVar:
return "vpiShortIntVar";
case vpiStringVar:

View File

@ -344,6 +344,11 @@ struct __vpiSignal : public __vpiHandle {
public:
unsigned width() const;
vpiHandle get_index(int index);
void get_bit_value(struct __vpiBit*bit, p_vpi_value vp);
void make_bits();
struct __vpiBit*bits;
public:
union { // The scope or parent array that contains me.
@ -366,7 +371,7 @@ struct __vpiSignal : public __vpiHandle {
static void*operator new(std::size_t size);
static void operator delete(void*); // not implemented
protected:
inline __vpiSignal() { }
inline __vpiSignal() : bits(NULL) { }
private: // Not implemented
static void*operator new[] (std::size_t size);
static void operator delete[](void*);
@ -384,6 +389,31 @@ extern vpiHandle vpip_make_net4(__vpiScope*scope,
const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*node);
/*
* This is used to represent a bit in a net/reg.
*/
struct __vpiBit {
struct as_bit_t : public __vpiHandle {
int get_type_code(void) const;
int vpi_get(int code);
char* vpi_get_str(int code);
void vpi_get_value(p_vpi_value val);
vpiHandle vpi_put_value(p_vpi_value val, int flags);
vpiHandle vpi_handle(int code);
} as_bit;
vpiHandle index;
union {
struct __vpiSignal*parent;
struct __vpiBit*bit0;
};
inline unsigned get_norm_index() const { return this - bit0; }
inline struct __vpiSignal*get_parent() const {return (bit0 - 1)->parent; }
int get_index(void) const;
};
/*
* This is used by system calls to represent a bit/part select of
* a simple variable or constant array word.

View File

@ -671,26 +671,125 @@ static vpiHandle signal_iterate(int code, vpiHandle ref)
return 0;
}
void __vpiSignal::make_bits()
{
assert(bits == NULL);
bits = new struct __vpiBit[width() + 1];
// Make word[-1] point to the parent.
bits->parent = this;
// Now point to word[0].
bits += 1;
// Update each bit to point to the base
struct __vpiBit*base = bits;
for (unsigned idx = 0; idx < width(); idx += 1) {
base[idx].bit0 = base;
int real_idx;
if (msb.get_value() >= lsb.get_value()) {
real_idx = idx + lsb.get_value();
} else {
real_idx = lsb.get_value() - idx;
}
base[idx].index = new __vpiDecConst(real_idx);
}
}
vpiHandle __vpiSignal::get_index(int idx)
{
/* Check to see if the index is in range. */
if (msb.get_value() >= lsb.get_value()) {
if ((idx > msb.get_value()) || (idx < lsb.get_value())) return 0;
} else {
if ((idx < msb.get_value()) || (idx > lsb.get_value())) return 0;
}
/* Normalize the index */
unsigned norm_idx;
if (msb.get_value() >= lsb.get_value()) {
norm_idx = idx - lsb.get_value();
} else {
norm_idx = lsb.get_value() - idx;
}
if (bits == NULL) make_bits();
return &(bits[norm_idx].as_bit);
}
void __vpiSignal::get_bit_value(struct __vpiBit*bit, p_vpi_value vp)
{
unsigned index = bit->get_norm_index();
vvp_signal_value*vsig = dynamic_cast<vvp_signal_value*>(node->fil);
assert(vsig);
if (vp->format == vpiObjTypeVal) {
vp->format = vpiIntVal;
}
switch (vp->format) {
case vpiBinStrVal:
format_vpiBinStrVal(vsig, index, 1, vp);
break;
case vpiOctStrVal:
format_vpiOctStrVal(vsig, index, 1, vp);
break;
case vpiDecStrVal:
format_vpiDecStrVal(vsig, index, 1, false, vp);
break;
case vpiHexStrVal:
format_vpiHexStrVal(vsig, index, 1, vp);
break;
case vpiStringVal:
format_vpiStringVal(vsig, index, 1, vp);
break;
case vpiIntVal:
format_vpiIntVal(vsig, index, 1, false, vp);
break;
case vpiRealVal:
format_vpiRealVal(vsig, index, 1, false, vp);
break;
case vpiScalarVal:
format_vpiScalarVal(vsig, index, vp);
break;
case vpiStrengthVal:
format_vpiStrengthVal(vsig, index, 1, vp);
break;
case vpiVectorVal:
format_vpiVectorVal(vsig, index, 1, vp);
break;
default:
fprintf(stderr, "internal error: get_value() "
"type %d is not implemented for bit "
"select %s[%d] in scope %s.\n",
(int)vp->format, vpi_get_str(vpiName),
bit->get_index(),
vpip_scope(this)->scope_name());
assert(0);
};
}
static vpiHandle signal_index(int idx, vpiHandle ref)
{
struct __vpiSignal*rfp = dynamic_cast<__vpiSignal*>(ref);
assert(rfp);
/* Check to see if the index is in range. */
if (rfp->msb.get_value() >= rfp->lsb.get_value()) {
if ((idx > rfp->msb.get_value()) || (idx < rfp->lsb.get_value())) return 0;
} else {
if ((idx < rfp->msb.get_value()) || (idx > rfp->lsb.get_value())) return 0;
}
/* We can only get the bit for a net or reg. */
PLI_INT32 type = vpi_get(vpiType, ref);
if ((type != vpiNet) && (type != vpiReg)) return 0;
/* Return a vpiNetBit or vpiRegBit handle for the individual bit. */
cerr << "Sorry: Icarus does not currently support "
<< "vpi_get_handle_by_index() for "
<< vpi_get_str(vpiType, ref);
cerr << " objects (" << vpi_get_str(vpiName, ref) << ")." << endl;
return 0;
return rfp->get_index(idx);
}
unsigned __vpiSignal::width(void) const
@ -1100,6 +1199,13 @@ void signal_delete(vpiHandle item)
assert(obj->node->fil);
obj->node->fil->clear_all_callbacks();
vvp_net_delete(obj->node);
if (obj->bits) {
for (unsigned idx=0; idx<obj->width(); idx+=1) {
delete obj->bits[idx].index;
}
obj->bits -= 1;
delete [] obj->bits;
}
signal_dels += 1;
VALGRIND_MEMPOOL_FREE(reinterpret_cast<vpiSignal_plug *>(obj)->pool, obj);
}