Merge branch 'master' of ssh://steve-icarus@icarus.com/~steve-icarus/git/verilog
This commit is contained in:
commit
b2c9352bb5
|
|
@ -302,6 +302,14 @@ void NetArrayDq::dump_node(ostream&o, unsigned ind) const
|
|||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetCastReal::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Cast to real (NetCastReal): " <<
|
||||
name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetCLShift::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Combinatorial shift (NetCLShift): " <<
|
||||
|
|
|
|||
10
elab_net.cc
10
elab_net.cc
|
|
@ -716,6 +716,16 @@ NetNet* PEBinary::elaborate_net_div_(Design*des, NetScope*scope,
|
|||
|
||||
unsigned rwidth = lwidth;
|
||||
|
||||
// If either operand is IVL_VT_REAL, then cast the other to
|
||||
// IVL_VT_REAL so that the division can become IVL_VT_REAL.
|
||||
|
||||
if (lsig->data_type()==IVL_VT_REAL || rsig->data_type()==IVL_VT_REAL) {
|
||||
if (lsig->data_type() != IVL_VT_REAL)
|
||||
lsig = cast_to_real(des, scope, lsig);
|
||||
if (rsig->data_type() != IVL_VT_REAL)
|
||||
rsig = cast_to_real(des, scope, rsig);
|
||||
}
|
||||
|
||||
if (rwidth == 0) {
|
||||
rwidth = lsig->vector_width();
|
||||
if (rsig->vector_width() > rwidth)
|
||||
|
|
|
|||
5
emit.cc
5
emit.cc
|
|
@ -72,6 +72,11 @@ bool NetCaseCmp::emit_node(struct target_t*tgt) const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool NetCastReal::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->lpm_cast_real(this);
|
||||
}
|
||||
|
||||
bool NetCLShift::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_clshift(this);
|
||||
|
|
|
|||
|
|
@ -254,6 +254,7 @@ typedef enum ivl_lpm_type_e {
|
|||
IVL_LPM_ABS = 32,
|
||||
IVL_LPM_ADD = 0,
|
||||
IVL_LPM_ARRAY = 30,
|
||||
IVL_LPM_CAST_REAL = 33,
|
||||
IVL_LPM_CONCAT = 16,
|
||||
IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */
|
||||
IVL_LPM_CMP_EQ = 10,
|
||||
|
|
|
|||
|
|
@ -849,6 +849,15 @@ const NetScope* NetProcTop::scope() const
|
|||
return scope_;
|
||||
}
|
||||
|
||||
NetCastReal::NetCastReal(NetScope*scope, perm_string n, bool signed_flag)
|
||||
: NetNode(scope, n, 2), signed_flag_(signed_flag)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("O"), 0);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(1).set_name(perm_string::literal("I"), 0);
|
||||
}
|
||||
|
||||
NetConcat::NetConcat(NetScope*scope, perm_string n, unsigned wid, unsigned cnt)
|
||||
: NetNode(scope, n, cnt+1), width_(wid)
|
||||
{
|
||||
|
|
|
|||
20
netlist.h
20
netlist.h
|
|
@ -916,6 +916,26 @@ class NetArrayDq : public NetNode {
|
|||
|
||||
};
|
||||
|
||||
/*
|
||||
* Convert an input to IVL_VT_REAL. The input is pin(1), which can be
|
||||
* any vector type (VT_BOOL or VT_LOGIC) and the output is pin(0),
|
||||
* which is IVL_VT_REAL. The conversion interprets the input as an
|
||||
* unsigned value unless the signed_flag is true.
|
||||
*/
|
||||
class NetCastReal : public NetNode {
|
||||
|
||||
public:
|
||||
NetCastReal(NetScope*s, perm_string n, bool signed_flag);
|
||||
|
||||
bool signed_flag() const { return signed_flag_; }
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
|
||||
private:
|
||||
bool signed_flag_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This type represents the LPM_CLSHIFT device.
|
||||
*/
|
||||
|
|
|
|||
19
netmisc.cc
19
netmisc.cc
|
|
@ -76,6 +76,25 @@ NetNet* add_to_net(Design*des, NetNet*sig, long val)
|
|||
#endif
|
||||
}
|
||||
|
||||
NetNet* cast_to_real(Design*des, NetScope*scope, NetNet*src)
|
||||
{
|
||||
if (src->data_type() == IVL_VT_REAL)
|
||||
return src;
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE);
|
||||
tmp->data_type(IVL_VT_REAL);
|
||||
tmp->set_line(*src);
|
||||
|
||||
NetCastReal*cast = new NetCastReal(scope, scope->local_symbol(), src->get_signed());
|
||||
cast->set_line(*src);
|
||||
des->add_node(cast);
|
||||
|
||||
connect(cast->pin(0), tmp->pin(0));
|
||||
connect(cast->pin(1), src->pin(0));
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a signed constant to an existing expression. Generate a new
|
||||
* NetEBAdd node that has the input expression and an expression made
|
||||
|
|
|
|||
|
|
@ -64,6 +64,12 @@ extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w);
|
|||
|
||||
extern NetNet*pad_to_width_signed(Design*des, NetNet*n, unsigned w);
|
||||
|
||||
/*
|
||||
* Generate the nodes necessary to cast an expression (a net) to a
|
||||
* real value.
|
||||
*/
|
||||
extern NetNet*cast_to_real(Design*des, NetScope*scope, NetNet*src);
|
||||
|
||||
/*
|
||||
* Take the input expression and return a variation that assures that
|
||||
* the expression is 1-bit wide and logical. This reflects the needs
|
||||
|
|
|
|||
16
t-dll-api.cc
16
t-dll-api.cc
|
|
@ -886,6 +886,7 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
|
|||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_ABS:
|
||||
case IVL_LPM_CAST_REAL:
|
||||
assert(idx == 0);
|
||||
return net->u_.arith.a;
|
||||
|
||||
|
|
@ -1028,20 +1029,18 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
|
|||
switch (net->type) {
|
||||
case IVL_LPM_ABS:
|
||||
case IVL_LPM_ADD:
|
||||
case IVL_LPM_DIVIDE:
|
||||
case IVL_LPM_MOD:
|
||||
case IVL_LPM_MULT:
|
||||
case IVL_LPM_POW:
|
||||
case IVL_LPM_SUB:
|
||||
assert(idx == 0);
|
||||
return net->u_.arith.q;
|
||||
|
||||
case IVL_LPM_CAST_REAL:
|
||||
case IVL_LPM_CMP_GE:
|
||||
case IVL_LPM_CMP_GT:
|
||||
case IVL_LPM_CMP_EQ:
|
||||
case IVL_LPM_CMP_NE:
|
||||
case IVL_LPM_CMP_EEQ:
|
||||
case IVL_LPM_CMP_NEE:
|
||||
case IVL_LPM_DIVIDE:
|
||||
case IVL_LPM_MOD:
|
||||
case IVL_LPM_MULT:
|
||||
case IVL_LPM_POW:
|
||||
case IVL_LPM_SUB:
|
||||
assert(idx == 0);
|
||||
return net->u_.arith.q;
|
||||
|
||||
|
|
@ -1144,6 +1143,7 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
|
|||
return 0;
|
||||
case IVL_LPM_ABS:
|
||||
case IVL_LPM_ADD:
|
||||
case IVL_LPM_CAST_REAL:
|
||||
case IVL_LPM_CMP_EEQ:
|
||||
case IVL_LPM_CMP_EQ:
|
||||
case IVL_LPM_CMP_GE:
|
||||
|
|
|
|||
33
t-dll.cc
33
t-dll.cc
|
|
@ -1550,6 +1550,39 @@ void dll_target::lpm_clshift(const NetCLShift*net)
|
|||
scope_add_lpm(obj->scope, obj);
|
||||
}
|
||||
|
||||
bool dll_target::lpm_cast_real(const NetCastReal*net)
|
||||
{
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_CAST_REAL;
|
||||
obj->name = net->name(); // NetCastReal names are permallocated
|
||||
assert(net->scope());
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->width = 0;
|
||||
obj->u_.arith.signed_flag = net->signed_flag()? 1 : 0;
|
||||
|
||||
const Nexus*nex;
|
||||
|
||||
nex = net->pin(0).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.arith.q = nex->t_cookie();
|
||||
|
||||
nex = net->pin(1).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.arith.a = nex->t_cookie();
|
||||
|
||||
nexus_lpm_add(obj->u_.arith.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
nexus_lpm_add(obj->u_.arith.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
make_lpm_delays_(obj, net);
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make out of the NetCompare object an ivl_lpm_s object. The
|
||||
* comparators in ivl_target do not support < or <=, but they can be
|
||||
|
|
|
|||
1
t-dll.h
1
t-dll.h
|
|
@ -76,6 +76,7 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
void lpm_abs(const NetAbs*);
|
||||
void lpm_add_sub(const NetAddSub*);
|
||||
bool lpm_array_dq(const NetArrayDq*);
|
||||
bool lpm_cast_real(const NetCastReal*);
|
||||
void lpm_clshift(const NetCLShift*);
|
||||
void lpm_compare(const NetCompare*);
|
||||
void lpm_divide(const NetDivide*);
|
||||
|
|
|
|||
|
|
@ -107,6 +107,13 @@ bool target_t::lpm_array_dq(const NetArrayDq*)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool target_t::lpm_cast_real(const NetCastReal*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetCastReal." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
void target_t::lpm_clshift(const NetCLShift*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
|
|
|
|||
1
target.h
1
target.h
|
|
@ -72,6 +72,7 @@ struct target_t {
|
|||
virtual void lpm_add_sub(const NetAddSub*);
|
||||
virtual bool lpm_array_dq(const NetArrayDq*);
|
||||
virtual void lpm_clshift(const NetCLShift*);
|
||||
virtual bool lpm_cast_real(const NetCastReal*);
|
||||
virtual void lpm_compare(const NetCompare*);
|
||||
virtual void lpm_divide(const NetDivide*);
|
||||
virtual void lpm_modulo(const NetModulo*);
|
||||
|
|
|
|||
|
|
@ -240,6 +240,31 @@ static void show_lpm_array(ivl_lpm_t net)
|
|||
}
|
||||
}
|
||||
|
||||
static void show_lpm_cast_real(ivl_lpm_t net)
|
||||
{
|
||||
unsigned width = ivl_lpm_width(net);
|
||||
|
||||
fprintf(out, " LPM_CAST_REAL %s: <width=%u>\n",
|
||||
ivl_lpm_basename(net), width);
|
||||
|
||||
ivl_nexus_t q = ivl_lpm_q(net,0);
|
||||
ivl_nexus_t a = ivl_lpm_data(net,0);
|
||||
fprintf(out, " O: %s\n", ivl_nexus_name(ivl_lpm_q(net,0)));
|
||||
fprintf(out, " A: %s\n", ivl_nexus_name(ivl_lpm_data(net,0)));
|
||||
|
||||
if (type_of_nexus(q) != IVL_VT_REAL) {
|
||||
fprintf(out, " ERROR: Data type of Q is %s, expecting real\n",
|
||||
data_type_string(type_of_nexus(q)));
|
||||
stub_errors += 1;
|
||||
}
|
||||
|
||||
if (type_of_nexus(a) == IVL_VT_REAL) {
|
||||
fprintf(out, " ERROR: Data type of A is %s, expecting !real\n",
|
||||
data_type_string(type_of_nexus(a)));
|
||||
stub_errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void show_lpm_divide(ivl_lpm_t net)
|
||||
{
|
||||
unsigned width = ivl_lpm_width(net);
|
||||
|
|
@ -802,6 +827,10 @@ static void show_lpm(ivl_lpm_t net)
|
|||
show_lpm_array(net);
|
||||
break;
|
||||
|
||||
case IVL_LPM_CAST_REAL:
|
||||
show_lpm_cast_real(net);
|
||||
break;
|
||||
|
||||
case IVL_LPM_DIVIDE:
|
||||
show_lpm_divide(net);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -387,6 +387,7 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
|
|||
case IVL_LPM_ABS:
|
||||
case IVL_LPM_ADD:
|
||||
case IVL_LPM_ARRAY:
|
||||
case IVL_LPM_CAST_REAL:
|
||||
case IVL_LPM_CONCAT:
|
||||
case IVL_LPM_CMP_EEQ:
|
||||
case IVL_LPM_CMP_EQ:
|
||||
|
|
|
|||
|
|
@ -1079,6 +1079,17 @@ static void draw_lpm_abs(ivl_lpm_t net)
|
|||
net, dly, src_table[0]);
|
||||
}
|
||||
|
||||
static void draw_lpm_cast_real(ivl_lpm_t net)
|
||||
{
|
||||
const char*src_table[1];
|
||||
draw_lpm_data_inputs(net, 0, 1, src_table);
|
||||
|
||||
const char*dly = draw_lpm_output_delay(net);
|
||||
|
||||
fprintf(vvp_out, "L_%p%s .cast/real %s;\n",
|
||||
net, dly, src_table[0]);
|
||||
}
|
||||
|
||||
static void draw_lpm_add(ivl_lpm_t net)
|
||||
{
|
||||
const char*src_table[2];
|
||||
|
|
@ -1644,6 +1655,10 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
|
|||
draw_lpm_abs(net);
|
||||
return;
|
||||
|
||||
case IVL_LPM_CAST_REAL:
|
||||
draw_lpm_cast_real(net);
|
||||
return;
|
||||
|
||||
case IVL_LPM_ADD:
|
||||
case IVL_LPM_SUB:
|
||||
case IVL_LPM_MULT:
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
# include "vpi_user.h"
|
||||
# include "sys_priv.h"
|
||||
# include <assert.h>
|
||||
# include <ctype.h>
|
||||
# include <string.h>
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
|
|
@ -91,6 +92,7 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
|
|||
s_vpi_value val;
|
||||
int fail = 0;
|
||||
char *mode_string = 0;
|
||||
unsigned idx;
|
||||
vpiHandle item = vpi_scan(argv);
|
||||
vpiHandle mode = vpi_scan(argv);
|
||||
|
||||
|
|
@ -103,10 +105,54 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
|
|||
vpi_printf("WARNING: %s line %d: ",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's mode argument was not a valid string.\n",
|
||||
vpi_printf("%s's mode argument is not a valid string.\n",
|
||||
name);
|
||||
fail = 1;
|
||||
}
|
||||
|
||||
/* Make sure the mode string is correct. */
|
||||
if (strlen(val.value.str) > 3) {
|
||||
vpi_printf("WARNING: %s line %d: ",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's mode argument (%s) is too long.\n",
|
||||
name, val.value.str);
|
||||
fail = 1;
|
||||
} else {
|
||||
unsigned bin = 0, plus = 0;
|
||||
switch (val.value.str[0]) {
|
||||
case 'r':
|
||||
case 'w':
|
||||
case 'a':
|
||||
for (idx = 1; idx < 3 ; idx++) {
|
||||
if (val.value.str[idx] == '\0') break;
|
||||
switch (val.value.str[idx]) {
|
||||
case 'b':
|
||||
if (bin) fail = 1;
|
||||
bin = 1;
|
||||
break;
|
||||
case '+':
|
||||
if (plus) fail = 1;
|
||||
plus = 1;
|
||||
break;
|
||||
default:
|
||||
fail = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (! fail) break;
|
||||
|
||||
default:
|
||||
vpi_printf("WARNING: %s line %d: ",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's mode argument (%s) is invalid.\n",
|
||||
name, val.value.str);
|
||||
fail = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mode_string = strdup(val.value.str);
|
||||
|
||||
vpi_free_object(argv);
|
||||
|
|
@ -121,12 +167,31 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
|
|||
if (val.format != vpiStringVal || !*(val.value.str)) {
|
||||
vpi_printf("WARNING: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's file name argument was not a valid string.\n",
|
||||
vpi_printf("%s's file name argument is not a valid string.\n",
|
||||
name);
|
||||
fail = 1;
|
||||
if (mode) free(mode_string);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that the file name is composed of only printable
|
||||
* characters.
|
||||
*/
|
||||
unsigned len = strlen(val.value.str);
|
||||
for (idx = 0; idx < len; idx++) {
|
||||
if (! isprint(val.value.str[idx])) {
|
||||
char msg [64];
|
||||
snprintf(msg, 64, "WARNING: %s line %d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s %s's file name argument contains non-"
|
||||
"printable characters.\n", msg, name);
|
||||
vpi_printf("%*s \"%s\"\n", strlen(msg), " ", val.value.str);
|
||||
fail = 1;
|
||||
if (mode) free(mode_string);
|
||||
}
|
||||
}
|
||||
|
||||
/* If either the mode or file name are not valid just return. */
|
||||
if (fail) return 0;
|
||||
|
||||
|
|
@ -168,11 +233,29 @@ static PLI_INT32 sys_fopenrwa_calltf(PLI_BYTE8*name)
|
|||
if (val.format != vpiStringVal || !*(val.value.str)) {
|
||||
vpi_printf("WARNING: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s's file name argument was not a valid string.\n",
|
||||
vpi_printf("%s's file name argument is not a valid string.\n",
|
||||
name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that the file name is composed of only printable
|
||||
* characters.
|
||||
*/
|
||||
unsigned idx, len = strlen(val.value.str);
|
||||
for (idx = 0; idx < len; idx++) {
|
||||
if (! isprint(val.value.str[idx])) {
|
||||
char msg [64];
|
||||
snprintf(msg, 64, "WARNING: %s line %d:",
|
||||
vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s %s's file name argument contains non-"
|
||||
"printable characters.\n", msg, name);
|
||||
vpi_printf("%*s \"%s\"\n", strlen(msg), " ", val.value.str);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Open the file and return the result. */
|
||||
val.format = vpiIntVal;
|
||||
val.value.integer = vpi_fopen(val.value.str, mode);
|
||||
|
|
@ -616,19 +699,19 @@ static PLI_INT32 sys_common_fd_calltf(PLI_BYTE8*name)
|
|||
|
||||
val.format = vpiIntVal;
|
||||
switch (name[4]) {
|
||||
case 'l': /* $ftell() */
|
||||
case 'l': /* $ftell() */
|
||||
val.value.integer = ftell(fp);
|
||||
break;
|
||||
case 'f': /* $feof() is from 1264-2005*/
|
||||
case 'f': /* $feof() is from 1264-2005*/
|
||||
val.value.integer = feof(fp);
|
||||
break;
|
||||
case 'i': /* $rewind() */
|
||||
case 'i': /* $rewind() */
|
||||
val.value.integer = fseek(fp, 0L, SEEK_SET);
|
||||
break;
|
||||
case 't': /* $fgetc() */
|
||||
case 't': /* $fgetc() */
|
||||
val.value.integer = fgetc(fp);
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh),
|
||||
(int)vpi_get(vpiLineNo, callh));
|
||||
vpi_printf("%s cannot be processed with this routine.\n", name);
|
||||
|
|
|
|||
16
vvp/arith.cc
16
vvp/arith.cc
|
|
@ -90,6 +90,22 @@ void vvp_arith_abs::recv_real(vvp_net_ptr_t ptr, double bit)
|
|||
vvp_send_real(ptr.ptr()->out, out);
|
||||
}
|
||||
|
||||
vvp_arith_cast_real::vvp_arith_cast_real(bool signed_flag)
|
||||
: signed_(signed_flag)
|
||||
{
|
||||
}
|
||||
|
||||
vvp_arith_cast_real::~vvp_arith_cast_real()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_arith_cast_real::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
{
|
||||
double val;
|
||||
vector4_to_value(bit, val, signed_);
|
||||
vvp_send_real(ptr.ptr()->out, val);
|
||||
}
|
||||
|
||||
// Division
|
||||
|
||||
vvp_arith_div::vvp_arith_div(unsigned wid, bool signed_flag)
|
||||
|
|
|
|||
11
vvp/arith.h
11
vvp/arith.h
|
|
@ -60,6 +60,17 @@ class vvp_arith_abs : public vvp_net_fun_t {
|
|||
private:
|
||||
};
|
||||
|
||||
class vvp_arith_cast_real : public vvp_net_fun_t {
|
||||
public:
|
||||
explicit vvp_arith_cast_real(bool signed_flag);
|
||||
~vvp_arith_cast_real();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
|
||||
private:
|
||||
bool signed_;
|
||||
};
|
||||
|
||||
class vvp_arith_div : public vvp_arith_ {
|
||||
|
||||
public:
|
||||
|
|
|
|||
43
vvp/array.cc
43
vvp/array.cc
|
|
@ -56,6 +56,8 @@ vvp_array_t array_find(const char*label)
|
|||
* represent the words of the array. The vpi_array_t is a pointer to this.
|
||||
*/
|
||||
struct __vpiArray {
|
||||
__vpiArray() { }
|
||||
|
||||
struct __vpiHandle base;
|
||||
struct __vpiScope*scope;
|
||||
const char*name; /* Permanently allocated string */
|
||||
|
|
@ -64,11 +66,11 @@ struct __vpiArray {
|
|||
struct __vpiDecConst last_addr;
|
||||
struct __vpiDecConst msb;
|
||||
struct __vpiDecConst lsb;
|
||||
unsigned vals_width;
|
||||
// If this is a net array, nets lists the handles.
|
||||
vpiHandle*nets;
|
||||
// If this is a var array, then these are used instead of nets.
|
||||
vvp_vector4_t *vals;
|
||||
unsigned vals_width;
|
||||
vvp_vector4array_t *vals;
|
||||
struct __vpiArrayWord*vals_words;
|
||||
|
||||
class vvp_fun_arrayport*ports_;
|
||||
|
|
@ -411,7 +413,7 @@ static int vpi_array_var_word_get(int code, vpiHandle ref)
|
|||
|
||||
switch (code) {
|
||||
case vpiSize:
|
||||
return (int) parent->vals_width;
|
||||
return (int) parent->vals->width();
|
||||
|
||||
case vpiLeftRange:
|
||||
return parent->msb.value;
|
||||
|
|
@ -448,14 +450,9 @@ static void vpi_array_var_word_get_value(vpiHandle ref, p_vpi_value value)
|
|||
|
||||
assert(obj);
|
||||
unsigned index = decode_array_word_pointer(obj, parent);
|
||||
unsigned width = parent->vals_width;
|
||||
unsigned width = parent->vals->width();
|
||||
|
||||
/* If we don't have a value yet just return X. */
|
||||
if (parent->vals[index].size() == 0) {
|
||||
vpip_vec4_get_value(vvp_vector4_t(width), width, false, value);
|
||||
} else {
|
||||
vpip_vec4_get_value(parent->vals[index], width, false, value);
|
||||
}
|
||||
vpip_vec4_get_value(parent->vals->get_word(index), width, false, value);
|
||||
}
|
||||
|
||||
static vpiHandle vpi_array_var_word_put_value(vpiHandle ref, p_vpi_value vp, int flags)
|
||||
|
|
@ -696,18 +693,18 @@ void array_set_word(vvp_array_t arr,
|
|||
if (arr->vals) {
|
||||
assert(arr->nets == 0);
|
||||
if (part_off != 0 || val.size() != arr->vals_width) {
|
||||
if (arr->vals[address].size() == 0)
|
||||
arr->vals[address] = vvp_vector4_t(arr->vals_width, BIT4_X);
|
||||
if ((part_off + val.size()) > arr->vals[address].size()) {
|
||||
vvp_vector4_t tmp = arr->vals->get_word(address);
|
||||
if ((part_off + val.size()) > tmp.size()) {
|
||||
cerr << "part_off=" << part_off
|
||||
<< " val.size()=" << val.size()
|
||||
<< " arr->vals[address].size()=" << arr->vals[address].size()
|
||||
<< " arr->vals[address].size()=" << tmp.size()
|
||||
<< " arr->vals_width=" << arr->vals_width << endl;
|
||||
assert(0);
|
||||
}
|
||||
arr->vals[address].set_vec(part_off, val);
|
||||
tmp.set_vec(part_off, val);
|
||||
arr->vals->set_word(address, tmp);
|
||||
} else {
|
||||
arr->vals[address] = val;
|
||||
arr->vals->set_word(address, val);
|
||||
}
|
||||
array_word_change(arr, address);
|
||||
return;
|
||||
|
|
@ -730,14 +727,7 @@ vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address)
|
|||
if (arr->vals) {
|
||||
assert(arr->nets == 0);
|
||||
|
||||
vvp_vector4_t tmp;
|
||||
if (address < arr->array_count)
|
||||
tmp = arr->vals[address];
|
||||
|
||||
if (tmp.size() == 0)
|
||||
tmp = vvp_vector4_t(arr->vals_width, BIT4_X);
|
||||
|
||||
return tmp;
|
||||
return arr->vals->get_word(address);
|
||||
}
|
||||
|
||||
assert(arr->vals == 0);
|
||||
|
|
@ -848,8 +838,8 @@ void compile_var_array(char*label, char*name, int last, int first,
|
|||
struct __vpiArray*arr = ARRAY_HANDLE(obj);
|
||||
|
||||
/* Make the words. */
|
||||
arr->vals = new vvp_vector4_t[arr->array_count];
|
||||
arr->vals_width = labs(msb-lsb) + 1;
|
||||
arr->vals = new vvp_vector4array_t(arr->vals_width, arr->array_count);
|
||||
vpip_make_dec_const(&arr->msb, msb);
|
||||
vpip_make_dec_const(&arr->lsb, lsb);
|
||||
|
||||
|
|
@ -989,7 +979,8 @@ void array_word_change(vvp_array_t array, unsigned long addr)
|
|||
|
||||
if (cur->cb_data.cb_rtn != 0) {
|
||||
if (cur->cb_data.value)
|
||||
vpip_vec4_get_value(array->vals[addr], array->vals_width,
|
||||
vpip_vec4_get_value(array->vals->get_word(addr),
|
||||
array->vals_width,
|
||||
false, cur->cb_data.value);
|
||||
|
||||
callback_execute(cur);
|
||||
|
|
|
|||
|
|
@ -889,6 +889,21 @@ template <class T_> void make_arith(T_ *arith, char*label,
|
|||
free(argv);
|
||||
}
|
||||
|
||||
void compile_arith_cast_real(char*label, unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
vvp_arith_cast_real*arith = new vvp_arith_cast_real(false);
|
||||
|
||||
vvp_net_t* ptr = new vvp_net_t;
|
||||
ptr->fun = arith;
|
||||
|
||||
define_functor_symbol(label, ptr);
|
||||
free(label);
|
||||
|
||||
assert(argc == 1);
|
||||
inputs_connect(ptr, argc, argv);
|
||||
free(argv);
|
||||
}
|
||||
|
||||
void compile_arith_abs(char*label, unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
vvp_arith_abs*arith = new vvp_arith_abs;
|
||||
|
|
|
|||
|
|
@ -151,6 +151,8 @@ extern void compile_arith_pow(char*label, long width, bool signed_flag,
|
|||
unsigned argc, struct symb_s*argv);
|
||||
extern void compile_arith_abs(char*label,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
extern void compile_arith_cast_real(char*label,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
extern void compile_arith_div(char*label, long width, bool signed_flag,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
extern void compile_arith_mod(char*label, long width,
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@
|
|||
".array/real" { return K_ARRAY_R; }
|
||||
".array/s" { return K_ARRAY_S; }
|
||||
".array/port" { return K_ARRAY_PORT; }
|
||||
".cast/real" { return K_CAST_REAL; }
|
||||
".cmp/eeq" { return K_CMP_EEQ; }
|
||||
".cmp/eq" { return K_CMP_EQ; }
|
||||
".cmp/eq.r" { return K_CMP_EQ_R; }
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ static struct __vpiModPath*modpath_dst = 0;
|
|||
%token K_ARITH_MULT K_ARITH_MULT_R K_ARITH_SUB K_ARITH_SUB_R
|
||||
%token K_ARITH_SUM K_ARITH_SUM_R K_ARITH_POW K_ARITH_POW_R K_ARITH_POW_S
|
||||
%token K_ARRAY K_ARRAY_I K_ARRAY_R K_ARRAY_S K_ARRAY_PORT
|
||||
%token K_CAST_REAL
|
||||
%token K_CMP_EEQ K_CMP_EQ K_CMP_EQ_R K_CMP_NEE K_CMP_NE K_CMP_NE_R
|
||||
%token K_CMP_GE K_CMP_GE_R K_CMP_GE_S K_CMP_GT K_CMP_GT_R K_CMP_GT_S
|
||||
%token K_CONCAT K_DEBUG K_DELAY K_DFF
|
||||
|
|
@ -252,6 +253,11 @@ statement
|
|||
compile_arith_abs($1, obj.cnt, obj.vect);
|
||||
}
|
||||
|
||||
| T_LABEL K_CAST_REAL symbols ';'
|
||||
{ struct symbv_s obj = $3;
|
||||
compile_arith_cast_real($1, obj.cnt, obj.vect);
|
||||
}
|
||||
|
||||
/* Arithmetic statements generate functor arrays of a given width
|
||||
that take like size input vectors. */
|
||||
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ void del_thr_event_s::run_run(void)
|
|||
|
||||
struct assign_vector4_event_s : public event_s {
|
||||
/* The default constructor. */
|
||||
assign_vector4_event_s() { }
|
||||
assign_vector4_event_s(const vvp_vector4_t&that) : val(that) { }
|
||||
/* A constructor that makes the val directly. */
|
||||
assign_vector4_event_s(const vvp_vector4_t&that, unsigned adr, unsigned wid)
|
||||
: val(that,adr,wid) { }
|
||||
|
|
@ -572,23 +572,10 @@ void schedule_assign_vector(vvp_net_ptr_t ptr,
|
|||
const vvp_vector4_t&bit,
|
||||
vvp_time64_t delay)
|
||||
{
|
||||
struct assign_vector4_event_s*cur = new struct assign_vector4_event_s;
|
||||
struct assign_vector4_event_s*cur = new struct assign_vector4_event_s(bit);
|
||||
cur->ptr = ptr;
|
||||
cur->base = base;
|
||||
cur->vwid = vwid;
|
||||
cur->val = bit;
|
||||
schedule_event_(cur, delay, SEQ_NBASSIGN);
|
||||
}
|
||||
|
||||
void schedule_assign_vector(vvp_net_ptr_t ptr,
|
||||
const vvp_vector4_t&bit,
|
||||
vvp_time64_t delay)
|
||||
{
|
||||
struct assign_vector4_event_s*cur = new struct assign_vector4_event_s;
|
||||
cur->ptr = ptr;
|
||||
cur->val = bit;
|
||||
cur->vwid = 0;
|
||||
cur->base = 0;
|
||||
schedule_event_(cur, delay, SEQ_NBASSIGN);
|
||||
}
|
||||
|
||||
|
|
@ -619,11 +606,10 @@ void schedule_assign_array_word(vvp_array_t mem,
|
|||
schedule_event_(cur, delay, SEQ_NBASSIGN);
|
||||
}
|
||||
|
||||
void schedule_set_vector(vvp_net_ptr_t ptr, vvp_vector4_t bit)
|
||||
void schedule_set_vector(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
{
|
||||
struct assign_vector4_event_s*cur = new struct assign_vector4_event_s;
|
||||
struct assign_vector4_event_s*cur = new struct assign_vector4_event_s(bit);
|
||||
cur->ptr = ptr;
|
||||
cur->val = bit;
|
||||
cur->base = 0;
|
||||
cur->vwid = 0;
|
||||
schedule_event_(cur, 0, SEQ_ACTIVE);
|
||||
|
|
@ -647,9 +633,8 @@ void schedule_set_vector(vvp_net_ptr_t ptr, double bit)
|
|||
|
||||
void schedule_init_vector(vvp_net_ptr_t ptr, vvp_vector4_t bit)
|
||||
{
|
||||
struct assign_vector4_event_s*cur = new struct assign_vector4_event_s;
|
||||
struct assign_vector4_event_s*cur = new struct assign_vector4_event_s(bit);
|
||||
cur->ptr = ptr;
|
||||
cur->val = bit;
|
||||
cur->base = 0;
|
||||
cur->vwid = 0;
|
||||
cur->next = schedule_init_list;
|
||||
|
|
|
|||
|
|
@ -47,9 +47,6 @@ extern void schedule_assign_vector(vvp_net_ptr_t ptr,
|
|||
const vvp_vector4_t&val,
|
||||
vvp_time64_t delay);
|
||||
|
||||
extern void schedule_assign_vector(vvp_net_ptr_t ptr,
|
||||
const vvp_vector4_t&val,
|
||||
vvp_time64_t delay);
|
||||
extern void schedule_assign_plucked_vector(vvp_net_ptr_t ptr,
|
||||
vvp_time64_t delay,
|
||||
const vvp_vector4_t&val,
|
||||
|
|
@ -66,7 +63,7 @@ extern void schedule_assign_array_word(vvp_array_t mem,
|
|||
* constant value (i.e. C4<...>) to the input of a functor. This
|
||||
* creates an event in the active queue.
|
||||
*/
|
||||
extern void schedule_set_vector(vvp_net_ptr_t ptr, vvp_vector4_t val);
|
||||
extern void schedule_set_vector(vvp_net_ptr_t ptr, const vvp_vector4_t&val);
|
||||
extern void schedule_set_vector(vvp_net_ptr_t ptr, vvp_vector8_t val);
|
||||
extern void schedule_set_vector(vvp_net_ptr_t ptr, double val);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-2008 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
|
||||
|
|
@ -16,9 +16,6 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpip_hex.cc,v 1.4 2006/02/21 02:39:27 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "vpi_priv.h"
|
||||
|
|
@ -140,21 +137,24 @@ void vpip_vec4_to_hex_str(const vvp_vector4_t&bits, char*buf,
|
|||
}
|
||||
}
|
||||
|
||||
if (slen > 0) {
|
||||
unsigned padd = 0;
|
||||
/* Fill in X or Z if they are the only thing in the value. */
|
||||
switch (bits.size() % 4) {
|
||||
case 1:
|
||||
if (val == 2) val = 170;
|
||||
else if (val == 3) val = 255;
|
||||
break;
|
||||
case 2:
|
||||
if (val == 10) val = 170;
|
||||
else if (val == 15) val = 255;
|
||||
break;
|
||||
case 3:
|
||||
if (val == 42) val = 170;
|
||||
else if (val == 63) val = 255;
|
||||
break;
|
||||
}
|
||||
|
||||
if (slen > 0) {
|
||||
slen -= 1;
|
||||
buf[slen] = hex_digits[val];
|
||||
switch(buf[slen]) {
|
||||
case 'X': padd = 2; break;
|
||||
case 'Z': padd = 3; break;
|
||||
}
|
||||
if (padd) {
|
||||
for (unsigned idx = bits.size() % 4; idx < 4; idx += 1) {
|
||||
val = val | padd << 2*idx;
|
||||
}
|
||||
buf[slen] = hex_digits[val];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-2008 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
|
||||
|
|
@ -16,9 +16,6 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpip_oct.cc,v 1.4 2006/02/21 02:39:27 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "vpi_priv.h"
|
||||
|
|
@ -120,9 +117,20 @@ void vpip_vec4_to_oct_str(const vvp_vector4_t&bits, char*buf, unsigned nbuf,
|
|||
}
|
||||
}
|
||||
|
||||
/* Fill in X or Z if they are the only thing in the value. */
|
||||
switch (bits.size() % 3) {
|
||||
case 1:
|
||||
if (val == 2) val = 42;
|
||||
else if (val == 3) val = 63;
|
||||
break;
|
||||
case 2:
|
||||
if (val == 10) val = 42;
|
||||
else if (val == 15) val = 63;
|
||||
break;
|
||||
}
|
||||
|
||||
if (slen > 0) {
|
||||
slen -= 1;
|
||||
buf[slen] = oct_digits[val];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -707,7 +707,7 @@ bool of_ASSIGN_V0(vthread_t thr, vvp_code_t cp)
|
|||
schedule_assign_plucked_vector(ptr, delay, thr->bits4, bit, wid);
|
||||
} else {
|
||||
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
|
||||
schedule_assign_vector(ptr, value, delay);
|
||||
schedule_assign_plucked_vector(ptr, delay, value, 0, wid);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -732,7 +732,7 @@ bool of_ASSIGN_V0D(vthread_t thr, vvp_code_t cp)
|
|||
schedule_assign_plucked_vector(ptr, delay, thr->bits4, bit, wid);
|
||||
} else {
|
||||
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
|
||||
schedule_assign_vector(ptr, value, delay);
|
||||
schedule_assign_plucked_vector(ptr, delay, value, 0, wid);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
265
vvp/vvp_net.cc
265
vvp/vvp_net.cc
|
|
@ -1177,6 +1177,94 @@ bool vector4_to_value(const vvp_vector4_t&vec, double&val, bool signed_flag)
|
|||
return flag;
|
||||
}
|
||||
|
||||
vvp_vector4array_t::vvp_vector4array_t(unsigned width, unsigned words)
|
||||
: width_(width), words_(words)
|
||||
{
|
||||
array_ = new v4cell[words_];
|
||||
|
||||
if (width_ <= vvp_vector4_t::BITS_PER_WORD) {
|
||||
for (unsigned idx = 0 ; idx < words_ ; idx += 1) {
|
||||
array_[idx].abits_val_ = vvp_vector4_t::WORD_X_ABITS;
|
||||
array_[idx].bbits_val_ = vvp_vector4_t::WORD_X_BBITS;
|
||||
}
|
||||
} else {
|
||||
for (unsigned idx = 0 ; idx < words_ ; idx += 1) {
|
||||
array_[idx].abits_ptr_ = 0;
|
||||
array_[idx].bbits_ptr_ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vvp_vector4array_t::~vvp_vector4array_t()
|
||||
{
|
||||
if (array_) {
|
||||
if (width_ > vvp_vector4_t::BITS_PER_WORD) {
|
||||
for (unsigned idx = 0 ; idx < words_ ; idx += 1)
|
||||
if (array_[idx].abits_ptr_)
|
||||
delete[]array_[idx].abits_ptr_;
|
||||
}
|
||||
delete[]array_;
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_vector4array_t::set_word(unsigned index, const vvp_vector4_t&that)
|
||||
{
|
||||
assert(index < words_);
|
||||
assert(that.size_ == width_);
|
||||
|
||||
v4cell&cell = array_[index];
|
||||
|
||||
if (width_ <= vvp_vector4_t::BITS_PER_WORD) {
|
||||
cell.abits_val_ = that.abits_val_;
|
||||
cell.bbits_val_ = that.bbits_val_;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned cnt = (width_ + vvp_vector4_t::BITS_PER_WORD-1)/vvp_vector4_t::BITS_PER_WORD;
|
||||
|
||||
if (cell.abits_ptr_ == 0) {
|
||||
cell.abits_ptr_ = new unsigned long[2*cnt];
|
||||
cell.bbits_ptr_ = cell.abits_ptr_ + cnt;
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
cell.abits_ptr_[idx] = that.abits_ptr_[idx];
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
cell.bbits_ptr_[idx] = that.bbits_ptr_[idx];
|
||||
}
|
||||
|
||||
vvp_vector4_t vvp_vector4array_t::get_word(unsigned index) const
|
||||
{
|
||||
if (index >= words_)
|
||||
return vvp_vector4_t(width_, BIT4_X);
|
||||
|
||||
assert(index < words_);
|
||||
|
||||
v4cell&cell = array_[index];
|
||||
|
||||
if (width_ <= vvp_vector4_t::BITS_PER_WORD) {
|
||||
vvp_vector4_t res;
|
||||
res.size_ = width_;
|
||||
res.abits_val_ = cell.abits_val_;
|
||||
res.bbits_val_ = cell.bbits_val_;
|
||||
return res;
|
||||
}
|
||||
|
||||
vvp_vector4_t res (width_, BIT4_X);
|
||||
if (cell.abits_ptr_ == 0)
|
||||
return res;
|
||||
|
||||
unsigned cnt = (width_ + vvp_vector4_t::BITS_PER_WORD-1)/vvp_vector4_t::BITS_PER_WORD;
|
||||
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
res.abits_ptr_[idx] = cell.abits_ptr_[idx];
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
res.bbits_ptr_[idx] = cell.bbits_ptr_[idx];
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
template <class T> T coerce_to_width(const T&that, unsigned width)
|
||||
{
|
||||
if (that.size() == width)
|
||||
|
|
@ -2621,7 +2709,7 @@ void vvp_wide_fun_core::propagate_vec4(const vvp_vector4_t&bit,
|
|||
vvp_time64_t delay)
|
||||
{
|
||||
if (delay)
|
||||
schedule_assign_vector(ptr_->out, bit, delay);
|
||||
schedule_assign_plucked_vector(ptr_->out, delay, bit, 0, bit.size());
|
||||
else
|
||||
vvp_send_vec4(ptr_->out, bit);
|
||||
}
|
||||
|
|
@ -2774,16 +2862,13 @@ ostream& operator <<(ostream&out, vvp_scalar_t a)
|
|||
return out;
|
||||
}
|
||||
|
||||
vvp_scalar_t resolve(vvp_scalar_t a, vvp_scalar_t b)
|
||||
/*
|
||||
* This function is only called if the actual interface function rules
|
||||
* out some of the eazy cases. If we get here, we can assume that
|
||||
* neither of the values is HiZ, and the values are not exactly equal.
|
||||
*/
|
||||
vvp_scalar_t fully_featured_resolv_(vvp_scalar_t a, vvp_scalar_t b)
|
||||
{
|
||||
// If the value is 0, that is the same as HiZ. In that case,
|
||||
// resolution is simply a matter of returning the *other* value.
|
||||
if (a.value_ == 0)
|
||||
return b;
|
||||
if (b.value_ == 0)
|
||||
return a;
|
||||
|
||||
vvp_scalar_t res = a;
|
||||
|
||||
if (UNAMBIG(a.value_) && UNAMBIG(b.value_)) {
|
||||
|
||||
|
|
@ -2792,108 +2877,112 @@ vvp_scalar_t resolve(vvp_scalar_t a, vvp_scalar_t b)
|
|||
but different values, then this becomes
|
||||
ambiguous. */
|
||||
|
||||
if (a.value_ == b.value_) {
|
||||
if ((b.value_&0x07) > (a.value_&0x07)) {
|
||||
|
||||
/* values are equal. do nothing. */
|
||||
/* b value is stronger. Take it. */
|
||||
return b;
|
||||
|
||||
} else if ((b.value_&0x07) > (res.value_&0x07)) {
|
||||
} else if ((b.value_&0x77) == (a.value_&0x77)) {
|
||||
|
||||
/* New value is stronger. Take it. */
|
||||
res.value_ = b.value_;
|
||||
|
||||
} else if ((b.value_&0x77) == (res.value_&0x77)) {
|
||||
|
||||
/* Strengths are the same. Make value ambiguous. */
|
||||
res.value_ = (res.value_&0x70) | (b.value_&0x07) | 0x80;
|
||||
// Strengths are the same. Since we know already
|
||||
// that the values are not the same, Make value
|
||||
// into "x".
|
||||
vvp_scalar_t tmp (a);
|
||||
tmp.value_ = (tmp.value_&0x77) | 0x80;
|
||||
return tmp;
|
||||
|
||||
} else {
|
||||
|
||||
/* Must be res is the stronger one. */
|
||||
/* Must be "a" is the stronger one. */
|
||||
return a;
|
||||
}
|
||||
|
||||
} else if (UNAMBIG(res.value_)) {
|
||||
unsigned tmp = 0;
|
||||
}
|
||||
|
||||
if ((res.value_&0x70) > (b.value_&0x70))
|
||||
tmp |= res.value_&0xf0;
|
||||
/* If one of the signals is unambiguous, then it
|
||||
will sweep up the weaker parts of the ambiguous
|
||||
signal. The result may be ambiguous, or maybe not. */
|
||||
|
||||
if (UNAMBIG(a.value_)) {
|
||||
vvp_scalar_t res;
|
||||
|
||||
if ((a.value_&0x70) > (b.value_&0x70))
|
||||
res.value_ |= a.value_&0xf0;
|
||||
else
|
||||
tmp |= b.value_&0xf0;
|
||||
res.value_ |= b.value_&0xf0;
|
||||
|
||||
if ((res.value_&0x07) > (b.value_&0x07))
|
||||
tmp |= res.value_&0x0f;
|
||||
if ((a.value_&0x07) > (b.value_&0x07))
|
||||
res.value_ |= a.value_&0x0f;
|
||||
else
|
||||
tmp |= b.value_&0x0f;
|
||||
res.value_ |= b.value_&0x0f;
|
||||
|
||||
res.value_ = tmp;
|
||||
return res;
|
||||
|
||||
} else if (UNAMBIG(b.value_)) {
|
||||
|
||||
/* If one of the signals is unambiguous, then it
|
||||
will sweep up the weaker parts of the ambiguous
|
||||
signal. The result may be ambiguous, or maybe not. */
|
||||
vvp_scalar_t res;
|
||||
|
||||
unsigned tmp = 0;
|
||||
|
||||
if ((b.value_&0x70) > (res.value_&0x70))
|
||||
tmp |= b.value_&0xf0;
|
||||
if ((b.value_&0x70) > (a.value_&0x70))
|
||||
res.value_ |= b.value_&0xf0;
|
||||
else
|
||||
tmp |= res.value_&0xf0;
|
||||
res.value_ |= a.value_&0xf0;
|
||||
|
||||
if ((b.value_&0x07) > (res.value_&0x07))
|
||||
tmp |= b.value_&0x0f;
|
||||
if ((b.value_&0x07) > (a.value_&0x07))
|
||||
res.value_ |= b.value_&0x0f;
|
||||
else
|
||||
tmp |= res.value_&0x0f;
|
||||
res.value_ |= a.value_&0x0f;
|
||||
|
||||
res.value_ = tmp;
|
||||
return res;
|
||||
|
||||
} else {
|
||||
|
||||
/* If both signals are ambiguous, then the result
|
||||
has an even wider ambiguity. */
|
||||
|
||||
unsigned tmp = 0;
|
||||
int sv1a = a.value_&0x80 ? STREN1(a.value_) : - STREN1(a.value_);
|
||||
int sv0a = a.value_&0x08 ? STREN0(a.value_) : - STREN0(a.value_);
|
||||
int sv1b = b.value_&0x80 ? STREN1(b.value_) : - STREN1(b.value_);
|
||||
int sv0b = b.value_&0x08 ? STREN0(b.value_) : - STREN0(b.value_);
|
||||
|
||||
int sv1 = sv1a;
|
||||
int sv0 = sv0a;
|
||||
|
||||
if (sv0a > sv1)
|
||||
sv1 = sv0a;
|
||||
if (sv1b > sv1)
|
||||
sv1 = sv1b;
|
||||
if (sv0b > sv1)
|
||||
sv1 = sv0b;
|
||||
|
||||
if (sv1a < sv0)
|
||||
sv0 = sv1a;
|
||||
if (sv1b < sv0)
|
||||
sv0 = sv1b;
|
||||
if (sv0b < sv0)
|
||||
sv0 = sv0b;
|
||||
|
||||
if (sv1 > 0) {
|
||||
tmp |= 0x80;
|
||||
tmp |= sv1 << 4;
|
||||
} else {
|
||||
/* Set the MSB when both arguments MSBs are set. This
|
||||
can only happen if both one strengths are zero. */
|
||||
tmp |= (a.value_&b.value_)&0x80;
|
||||
tmp |= (-sv1) << 4;
|
||||
}
|
||||
|
||||
if (sv0 > 0) {
|
||||
tmp |= 0x08;
|
||||
tmp |= sv0;
|
||||
} else {
|
||||
tmp |= (-sv0);
|
||||
}
|
||||
|
||||
res.value_ = tmp;
|
||||
}
|
||||
|
||||
|
||||
/* If both signals are ambiguous, then the result
|
||||
has an even wider ambiguity. */
|
||||
|
||||
unsigned tmp = 0;
|
||||
int sv1a = a.value_&0x80 ? STREN1(a.value_) : - STREN1(a.value_);
|
||||
int sv0a = a.value_&0x08 ? STREN0(a.value_) : - STREN0(a.value_);
|
||||
int sv1b = b.value_&0x80 ? STREN1(b.value_) : - STREN1(b.value_);
|
||||
int sv0b = b.value_&0x08 ? STREN0(b.value_) : - STREN0(b.value_);
|
||||
|
||||
int sv1 = sv1a;
|
||||
int sv0 = sv0a;
|
||||
|
||||
if (sv0a > sv1)
|
||||
sv1 = sv0a;
|
||||
if (sv1b > sv1)
|
||||
sv1 = sv1b;
|
||||
if (sv0b > sv1)
|
||||
sv1 = sv0b;
|
||||
|
||||
if (sv1a < sv0)
|
||||
sv0 = sv1a;
|
||||
if (sv1b < sv0)
|
||||
sv0 = sv1b;
|
||||
if (sv0b < sv0)
|
||||
sv0 = sv0b;
|
||||
|
||||
if (sv1 > 0) {
|
||||
tmp |= 0x80;
|
||||
tmp |= sv1 << 4;
|
||||
} else {
|
||||
/* Set the MSB when both arguments MSBs are set. This
|
||||
can only happen if both one strengths are zero. */
|
||||
tmp |= (a.value_&b.value_)&0x80;
|
||||
tmp |= (-sv1) << 4;
|
||||
}
|
||||
|
||||
if (sv0 > 0) {
|
||||
tmp |= 0x08;
|
||||
tmp |= sv0;
|
||||
} else {
|
||||
tmp |= (-sv0);
|
||||
}
|
||||
|
||||
vvp_scalar_t res;
|
||||
res.value_ = tmp;
|
||||
|
||||
/* Canonicalize the HiZ value. */
|
||||
if ((res.value_&0x77) == 0)
|
||||
res.value_ = 0;
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ extern int edge(vvp_bit4_t from, vvp_bit4_t to);
|
|||
class vvp_vector4_t {
|
||||
|
||||
friend vvp_vector4_t operator ~(const vvp_vector4_t&that);
|
||||
friend class vvp_vector4array_t;
|
||||
|
||||
public:
|
||||
explicit vvp_vector4_t(unsigned size =0, vvp_bit4_t bits =BIT4_X);
|
||||
|
|
@ -383,6 +384,42 @@ extern bool vector4_to_value(const vvp_vector4_t&a, long&val, bool is_signed);
|
|||
extern bool vector4_to_value(const vvp_vector4_t&a, unsigned long&val);
|
||||
extern bool vector4_to_value(const vvp_vector4_t&a, double&val, bool is_signed);
|
||||
|
||||
/*
|
||||
* vvp_vector4array_t
|
||||
*/
|
||||
class vvp_vector4array_t {
|
||||
|
||||
public:
|
||||
vvp_vector4array_t(unsigned width, unsigned words);
|
||||
~vvp_vector4array_t();
|
||||
|
||||
unsigned width() const { return width_; }
|
||||
unsigned words() const { return words_; }
|
||||
|
||||
vvp_vector4_t get_word(unsigned idx) const;
|
||||
void set_word(unsigned idx, const vvp_vector4_t&that);
|
||||
|
||||
private:
|
||||
struct v4cell {
|
||||
union {
|
||||
unsigned long abits_val_;
|
||||
unsigned long*abits_ptr_;
|
||||
};
|
||||
union {
|
||||
unsigned long bbits_val_;
|
||||
unsigned long*bbits_ptr_;
|
||||
};
|
||||
};
|
||||
|
||||
unsigned width_;
|
||||
unsigned words_;
|
||||
v4cell* array_;
|
||||
|
||||
private: // Not implemented
|
||||
vvp_vector4array_t(const vvp_vector4array_t&);
|
||||
vvp_vector4array_t& operator = (const vvp_vector4array_t&);
|
||||
};
|
||||
|
||||
/* vvp_vector2_t
|
||||
*/
|
||||
class vvp_vector2_t {
|
||||
|
|
@ -479,7 +516,7 @@ inline unsigned vvp_vector2_t::size() const
|
|||
*/
|
||||
class vvp_scalar_t {
|
||||
|
||||
friend vvp_scalar_t resolve(vvp_scalar_t a, vvp_scalar_t b);
|
||||
friend vvp_scalar_t fully_featured_resolv_(vvp_scalar_t a, vvp_scalar_t b);
|
||||
|
||||
public:
|
||||
// Make a HiZ value.
|
||||
|
|
@ -543,7 +580,24 @@ inline vvp_bit4_t vvp_scalar_t::value() const
|
|||
}
|
||||
|
||||
|
||||
extern vvp_scalar_t resolve(vvp_scalar_t a, vvp_scalar_t b);
|
||||
inline vvp_scalar_t resolve(vvp_scalar_t a, vvp_scalar_t b)
|
||||
{
|
||||
extern vvp_scalar_t fully_featured_resolv_(vvp_scalar_t a, vvp_scalar_t b);
|
||||
|
||||
// If the value is HiZ, resolution is simply a matter of
|
||||
// returning the *other* value.
|
||||
if (a.is_hiz())
|
||||
return b;
|
||||
if (b.is_hiz())
|
||||
return a;
|
||||
// If the values are the identical, then resolution is simply
|
||||
// returning *either* value.
|
||||
if (a .eeq( b ))
|
||||
return a;
|
||||
|
||||
return fully_featured_resolv_(a,b);
|
||||
}
|
||||
|
||||
extern ostream& operator<< (ostream&, vvp_scalar_t);
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue