Merge branch 'master' of ssh://steve-icarus@icarus.com/~steve-icarus/git/verilog

This commit is contained in:
Stephen Williams 2008-06-17 21:45:58 -07:00
commit b2c9352bb5
31 changed files with 603 additions and 180 deletions

View File

@ -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): " <<

View File

@ -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)

View File

@ -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);

View File

@ -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,

View File

@ -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)
{

View File

@ -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.
*/

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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*);

View File

@ -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() << "): "

View File

@ -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*);

View File

@ -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;

View File

@ -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:

View File

@ -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:

View File

@ -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);

View File

@ -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)

View File

@ -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:

View File

@ -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);

View File

@ -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;

View File

@ -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,

View File

@ -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; }

View File

@ -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. */

View File

@ -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;

View File

@ -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);

View File

@ -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];
}
}
}

View File

@ -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];
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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);
/*