Merge branch 'master' of git://icarus.com/~steve-icarus/verilog into vhdl
This commit is contained in:
commit
ed929a37bb
66
elaborate.cc
66
elaborate.cc
|
|
@ -3381,29 +3381,6 @@ bool PProcess::elaborate(Design*des, NetScope*scope) const
|
||||||
verinum(1));
|
verinum(1));
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
/* If this is an always block and we have no or zero delay then
|
|
||||||
* a runtime infinite loop will happen. If we possible have some
|
|
||||||
* delay then print a warning that an infinite loop is possible.
|
|
||||||
*/
|
|
||||||
if (type() == PProcess::PR_ALWAYS) {
|
|
||||||
DelayType dly_type = top->statement()->delay_type();
|
|
||||||
|
|
||||||
if (dly_type == NO_DELAY || dly_type == ZERO_DELAY) {
|
|
||||||
cerr << get_fileline() << ": error: always statement"
|
|
||||||
<< " does not have any delay." << endl;
|
|
||||||
cerr << get_fileline() << ": : A runtime infinite"
|
|
||||||
<< " loop will occur." << endl;
|
|
||||||
des->errors += 1;
|
|
||||||
return false;
|
|
||||||
|
|
||||||
} else if (dly_type == POSSIBLE_DELAY && warn_inf_loop) {
|
|
||||||
cerr << get_fileline() << ": warning: always statement"
|
|
||||||
<< " may not have any delay." << endl;
|
|
||||||
cerr << get_fileline() << ": : A runtime infinite"
|
|
||||||
<< " loop may be possible." << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3871,6 +3848,37 @@ class later_defparams : public elaborator_work_item_t {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool Design::check_always_delay() const
|
||||||
|
{
|
||||||
|
bool result_flag = true;
|
||||||
|
|
||||||
|
for (const NetProcTop*pr = procs_ ; pr ; pr = pr->next_) {
|
||||||
|
/* If this is an always block and we have no or zero delay then
|
||||||
|
* a runtime infinite loop will happen. If we possible have some
|
||||||
|
* delay then print a warning that an infinite loop is possible.
|
||||||
|
*/
|
||||||
|
if (pr->type() == NetProcTop::KALWAYS) {
|
||||||
|
DelayType dly_type = pr->statement()->delay_type();
|
||||||
|
|
||||||
|
if (dly_type == NO_DELAY || dly_type == ZERO_DELAY) {
|
||||||
|
cerr << pr->get_fileline() << ": error: always"
|
||||||
|
<< " statement does not have any delay." << endl;
|
||||||
|
cerr << pr->get_fileline() << ": : A runtime"
|
||||||
|
<< " infinite loop will occur." << endl;
|
||||||
|
result_flag = false;
|
||||||
|
|
||||||
|
} else if (dly_type == POSSIBLE_DELAY && warn_inf_loop) {
|
||||||
|
cerr << pr->get_fileline() << ": warning: always"
|
||||||
|
<< " statement may not have any delay." << endl;
|
||||||
|
cerr << pr->get_fileline() << ": : A runtime"
|
||||||
|
<< " infinite loop may be possible." << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result_flag;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function is the root of all elaboration. The input is the list
|
* This function is the root of all elaboration. The input is the list
|
||||||
* of root module names. The function locates the Module definitions
|
* of root module names. The function locates the Module definitions
|
||||||
|
|
@ -3906,7 +3914,7 @@ Design* elaborate(list<perm_string>roots)
|
||||||
// Get the module definition for this root instance.
|
// Get the module definition for this root instance.
|
||||||
Module *rmod = (*mod).second;
|
Module *rmod = (*mod).second;
|
||||||
|
|
||||||
// Make the root scope. This makes a NetScoep object and
|
// Make the root scope. This makes a NetScope object and
|
||||||
// pushes it into the list of root scopes in the Design.
|
// pushes it into the list of root scopes in the Design.
|
||||||
NetScope*scope = des->make_root_scope(*root);
|
NetScope*scope = des->make_root_scope(*root);
|
||||||
|
|
||||||
|
|
@ -3919,7 +3927,7 @@ Design* elaborate(list<perm_string>roots)
|
||||||
des->set_precision(rmod->time_precision);
|
des->set_precision(rmod->time_precision);
|
||||||
|
|
||||||
|
|
||||||
// Save this scope, along with its defintion, in the
|
// Save this scope, along with its definition, in the
|
||||||
// "root_elems" list for later passes.
|
// "root_elems" list for later passes.
|
||||||
struct root_elem *r = new struct root_elem;
|
struct root_elem *r = new struct root_elem;
|
||||||
r->mod = rmod;
|
r->mod = rmod;
|
||||||
|
|
@ -3997,8 +4005,14 @@ Design* elaborate(list<perm_string>roots)
|
||||||
rc &= rmod->elaborate(des, scope);
|
rc &= rmod->elaborate(des, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (rc == false) {
|
if (rc == false) {
|
||||||
|
delete des;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now that everything is fully elaborated verify that we do
|
||||||
|
// not have an always block with no delay (an infinite loop).
|
||||||
|
if (des->check_always_delay() == false) {
|
||||||
delete des;
|
delete des;
|
||||||
des = 0;
|
des = 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1588,6 +1588,12 @@ static int load_next_input()
|
||||||
if(depend_file)
|
if(depend_file)
|
||||||
fprintf(depend_file, "%s\n", istack->path);
|
fprintf(depend_file, "%s\n", istack->path);
|
||||||
|
|
||||||
|
/* This works around an issue in flex yyrestart() where it
|
||||||
|
* uses yyin to create a new buffer when one does not exist.
|
||||||
|
* I would have assumed that it would use the file argument.
|
||||||
|
* The problem is that we have deleted the buffer and freed
|
||||||
|
* yyin (isp->file) above. */
|
||||||
|
yyin = 0;
|
||||||
yyrestart(istack->file);
|
yyrestart(istack->file);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2575,6 +2575,7 @@ DelayType NetBlock::delay_type() const
|
||||||
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
|
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
|
||||||
DelayType dt = cur->delay_type();
|
DelayType dt = cur->delay_type();
|
||||||
if (dt > result) result = dt;
|
if (dt > result) result = dt;
|
||||||
|
if (dt == DEFINITE_DELAY) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -2609,7 +2610,9 @@ DelayType NetCondit::delay_type() const
|
||||||
if (else_) {
|
if (else_) {
|
||||||
result = combine_delays(if_->delay_type(), else_->delay_type());
|
result = combine_delays(if_->delay_type(), else_->delay_type());
|
||||||
} else {
|
} else {
|
||||||
result = if_->delay_type();
|
/* Because of the indeterminate conditional value the
|
||||||
|
* best we can have for this case is a possible delay. */
|
||||||
|
result = combine_delays(if_->delay_type(), NO_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -3715,6 +3715,7 @@ class Design {
|
||||||
// PROCESSES
|
// PROCESSES
|
||||||
void add_process(NetProcTop*);
|
void add_process(NetProcTop*);
|
||||||
void delete_process(NetProcTop*);
|
void delete_process(NetProcTop*);
|
||||||
|
bool check_always_delay() const;
|
||||||
|
|
||||||
// Iterate over the design...
|
// Iterate over the design...
|
||||||
void dump(ostream&) const;
|
void dump(ostream&) const;
|
||||||
|
|
|
||||||
|
|
@ -245,16 +245,16 @@ bool eval_as_double(double&value, NetExpr*expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* At the parser level, a name component it a name with a collection
|
* At the parser level, a name component is a name with a collection
|
||||||
* of expressions. For example foo[N] is the name "foo" and the index
|
* of expressions. For example foo[N] is the name "foo" and the index
|
||||||
* expression "N". This function takes as input the name component and
|
* expression "N". This function takes as input the name component and
|
||||||
* returns the path component name. It will evaulate the index
|
* returns the path component name. It will evaluate the index
|
||||||
* expression if it is present.
|
* expression if it is present.
|
||||||
*/
|
*/
|
||||||
hname_t eval_path_component(Design*des, NetScope*scope,
|
hname_t eval_path_component(Design*des, NetScope*scope,
|
||||||
const name_component_t&comp)
|
const name_component_t&comp)
|
||||||
{
|
{
|
||||||
// No index exression, so the path component is an undecorated
|
// No index expression, so the path component is an undecorated
|
||||||
// name, for example "foo".
|
// name, for example "foo".
|
||||||
if (comp.index.empty())
|
if (comp.index.empty())
|
||||||
return hname_t(comp.name);
|
return hname_t(comp.name);
|
||||||
|
|
@ -284,7 +284,7 @@ hname_t eval_path_component(Design*des, NetScope*scope,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Darn, the expression doesn't evaluate to a constant. That's
|
// Darn, the expression doesn't evaluate to a constant. That's
|
||||||
// and error to be reported. And make up a fake index value to
|
// an error to be reported. And make up a fake index value to
|
||||||
// return to the caller.
|
// return to the caller.
|
||||||
cerr << index.msb->get_fileline() << ": error: "
|
cerr << index.msb->get_fileline() << ": error: "
|
||||||
<< "Scope index expression is not constant: "
|
<< "Scope index expression is not constant: "
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,13 @@
|
||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct args_info {
|
||||||
|
char*text;
|
||||||
|
int vec_flag; /* True if the vec must be released. */
|
||||||
|
struct vector_info vec;
|
||||||
|
struct args_info *child; /* Arguments can be nested. */
|
||||||
|
};
|
||||||
|
|
||||||
static const char* magic_sfuncs[] = {
|
static const char* magic_sfuncs[] = {
|
||||||
"$time",
|
"$time",
|
||||||
"$stime",
|
"$stime",
|
||||||
|
|
@ -68,6 +75,153 @@ static int is_fixed_memory_word(ivl_expr_t net)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int get_vpi_taskfunc_signal_arg(struct args_info *result,
|
||||||
|
ivl_expr_t expr)
|
||||||
|
{
|
||||||
|
char buffer[4096];
|
||||||
|
|
||||||
|
switch (ivl_expr_type(expr)) {
|
||||||
|
case IVL_EX_SIGNAL:
|
||||||
|
/* If the signal node is narrower then the signal itself,
|
||||||
|
then this is a part select so I'm going to need to
|
||||||
|
evaluate the expression.
|
||||||
|
|
||||||
|
Also, if the signedness of the expression is different
|
||||||
|
from the signedness of the signal. This could be
|
||||||
|
caused by a $signed or $unsigned system function.
|
||||||
|
|
||||||
|
If I don't need to do any evaluating, then skip it as
|
||||||
|
I'll be passing the handle to the signal itself. */
|
||||||
|
if (ivl_expr_width(expr) !=
|
||||||
|
ivl_signal_width(ivl_expr_signal(expr))) {
|
||||||
|
/* This should never happen since we have IVL_EX_SELECT. */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
} else if (ivl_expr_signed(expr) !=
|
||||||
|
ivl_signal_signed(ivl_expr_signal(expr))) {
|
||||||
|
return 0;
|
||||||
|
} else if (is_fixed_memory_word(expr)) {
|
||||||
|
/* This is a word of a non-array, or a word of a net
|
||||||
|
array, so we can address the word directly. */
|
||||||
|
ivl_signal_t sig = ivl_expr_signal(expr);
|
||||||
|
unsigned use_word = 0;
|
||||||
|
ivl_expr_t word_ex = ivl_expr_oper1(expr);
|
||||||
|
if (word_ex) {
|
||||||
|
/* Some array select have been evaluated. */
|
||||||
|
if (number_is_immediate(word_ex,
|
||||||
|
8*sizeof(unsigned), 0)) {
|
||||||
|
use_word = get_number_immediate(word_ex);
|
||||||
|
word_ex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (word_ex) return 0;
|
||||||
|
|
||||||
|
assert(word_ex == 0);
|
||||||
|
snprintf(buffer, sizeof buffer, "v%p_%u", sig, use_word);
|
||||||
|
result->text = strdup(buffer);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* What's left, this is the work of a var array.
|
||||||
|
Create the right code to handle it. */
|
||||||
|
ivl_signal_t sig = ivl_expr_signal(expr);
|
||||||
|
unsigned use_word = 0;
|
||||||
|
ivl_expr_t word_ex = ivl_expr_oper1(expr);
|
||||||
|
if (word_ex) {
|
||||||
|
/* Some array select have been evaluated. */
|
||||||
|
if (number_is_immediate(word_ex,
|
||||||
|
8*sizeof(unsigned), 0)) {
|
||||||
|
use_word = get_number_immediate(word_ex);
|
||||||
|
word_ex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (word_ex && (ivl_expr_type(word_ex)==IVL_EX_SIGNAL ||
|
||||||
|
ivl_expr_type(word_ex)==IVL_EX_SELECT)) {
|
||||||
|
/* Special case: the index is a signal/select. */
|
||||||
|
result->child = calloc(1, sizeof(struct args_info));
|
||||||
|
if (get_vpi_taskfunc_signal_arg(result->child,
|
||||||
|
word_ex)) {
|
||||||
|
snprintf(buffer, sizeof buffer, "&A<v%p, %s >",
|
||||||
|
sig, result->child->text);
|
||||||
|
free(result->child->text);
|
||||||
|
} else {
|
||||||
|
free(result->child);
|
||||||
|
result->child = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if (word_ex) {
|
||||||
|
/* Fallback case: evaluate expression. */
|
||||||
|
struct vector_info av;
|
||||||
|
av = draw_eval_expr(word_ex, STUFF_OK_XZ);
|
||||||
|
snprintf(buffer, sizeof buffer, "&A<v%p, %u %u>",
|
||||||
|
sig, av.base, av.wid);
|
||||||
|
result->vec = av;
|
||||||
|
result->vec_flag = 1;
|
||||||
|
} else {
|
||||||
|
snprintf(buffer, sizeof buffer, "&A<v%p, %u>",
|
||||||
|
sig, use_word);
|
||||||
|
}
|
||||||
|
result->text = strdup(buffer);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IVL_EX_SELECT: {
|
||||||
|
ivl_expr_t vexpr = ivl_expr_oper1(expr);
|
||||||
|
assert(vexpr);
|
||||||
|
|
||||||
|
/* This code is only for signals or selects. */
|
||||||
|
if (ivl_expr_type(vexpr) != IVL_EX_SIGNAL &&
|
||||||
|
ivl_expr_type(vexpr) != IVL_EX_SELECT) return 0;
|
||||||
|
|
||||||
|
/* The signal is part of an array. */
|
||||||
|
/* Add &APV<> code here when it is finished. */
|
||||||
|
if (ivl_expr_oper1(vexpr)) return 0;
|
||||||
|
|
||||||
|
ivl_expr_t bexpr = ivl_expr_oper2(expr);
|
||||||
|
assert(bexpr);
|
||||||
|
|
||||||
|
/* This is a constant bit/part select. */
|
||||||
|
if (number_is_immediate(bexpr, 64, 1)) {
|
||||||
|
snprintf(buffer, sizeof buffer, "&PV<v%p_0, %ld, %u>",
|
||||||
|
ivl_expr_signal(vexpr),
|
||||||
|
get_number_immediate(bexpr),
|
||||||
|
ivl_expr_width(expr));
|
||||||
|
/* This is an indexed bit/part select. */
|
||||||
|
} else if (ivl_expr_type(bexpr) == IVL_EX_SIGNAL ||
|
||||||
|
ivl_expr_type(bexpr) == IVL_EX_SELECT) {
|
||||||
|
/* Special case: the base is a signal/select. */
|
||||||
|
result->child = calloc(1, sizeof(struct args_info));
|
||||||
|
if (get_vpi_taskfunc_signal_arg(result->child, bexpr)) {
|
||||||
|
snprintf(buffer, sizeof buffer, "&PV<v%p_0, %s, %u>",
|
||||||
|
ivl_expr_signal(vexpr),
|
||||||
|
result->child->text,
|
||||||
|
ivl_expr_width(expr));
|
||||||
|
free(result->child->text);
|
||||||
|
} else {
|
||||||
|
free(result->child);
|
||||||
|
result->child = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Fallback case: evaluate the expression. */
|
||||||
|
struct vector_info rv;
|
||||||
|
rv = draw_eval_expr(bexpr, STUFF_OK_XZ);
|
||||||
|
snprintf(buffer, sizeof buffer, "&PV<v%p_0, %u %u, %u>",
|
||||||
|
ivl_expr_signal(vexpr),
|
||||||
|
rv.base, rv.wid,
|
||||||
|
ivl_expr_width(expr));
|
||||||
|
result->vec = rv;
|
||||||
|
result->vec_flag = 1;
|
||||||
|
}
|
||||||
|
result->text = strdup(buffer);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void draw_vpi_taskfunc_args(const char*call_string,
|
static void draw_vpi_taskfunc_args(const char*call_string,
|
||||||
ivl_statement_t tnet,
|
ivl_statement_t tnet,
|
||||||
ivl_expr_t fnet)
|
ivl_expr_t fnet)
|
||||||
|
|
@ -77,11 +231,7 @@ static void draw_vpi_taskfunc_args(const char*call_string,
|
||||||
? ivl_stmt_parm_count(tnet)
|
? ivl_stmt_parm_count(tnet)
|
||||||
: ivl_expr_parms(fnet);
|
: ivl_expr_parms(fnet);
|
||||||
|
|
||||||
struct args_info {
|
struct args_info *args = calloc(parm_count, sizeof(struct args_info));
|
||||||
char*text;
|
|
||||||
int vec_flag; /* True if the vec must be released. */
|
|
||||||
struct vector_info vec;
|
|
||||||
} *args = calloc(parm_count, sizeof(struct args_info));
|
|
||||||
|
|
||||||
char buffer[4096];
|
char buffer[4096];
|
||||||
|
|
||||||
|
|
@ -154,121 +304,9 @@ static void draw_vpi_taskfunc_args(const char*call_string,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IVL_EX_SIGNAL:
|
case IVL_EX_SIGNAL:
|
||||||
/* If the signal node is narrower then the signal
|
case IVL_EX_SELECT:
|
||||||
itself, then this is a part select so I'm going
|
if (get_vpi_taskfunc_signal_arg(&args[idx], expr)) continue;
|
||||||
to need to evaluate the expression.
|
else break;
|
||||||
|
|
||||||
Also, if the signedness of the expression is
|
|
||||||
different from the signedness of the
|
|
||||||
signal. This could be caused by a $signed or
|
|
||||||
$unsigned system function.
|
|
||||||
|
|
||||||
If I don't need to do any evaluating, then skip
|
|
||||||
it as I'll be passing the handle to the signal
|
|
||||||
itself. */
|
|
||||||
if (ivl_expr_width(expr) !=
|
|
||||||
ivl_signal_width(ivl_expr_signal(expr))) {
|
|
||||||
break;
|
|
||||||
|
|
||||||
} else if (ivl_expr_signed(expr) !=
|
|
||||||
ivl_signal_signed(ivl_expr_signal(expr))) {
|
|
||||||
break;
|
|
||||||
} else if (is_fixed_memory_word(expr)) {
|
|
||||||
/* This is a word of a non-array, or a word
|
|
||||||
of a net array, so we can address the
|
|
||||||
word directly. */
|
|
||||||
ivl_signal_t sig = ivl_expr_signal(expr);
|
|
||||||
unsigned use_word = 0;
|
|
||||||
ivl_expr_t word_ex = ivl_expr_oper1(expr);
|
|
||||||
if (word_ex) {
|
|
||||||
/* Some array select have been evaluated. */
|
|
||||||
if (number_is_immediate(word_ex, 8*sizeof(unsigned), 0)) {
|
|
||||||
use_word = get_number_immediate(word_ex);
|
|
||||||
word_ex = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (word_ex)
|
|
||||||
break;
|
|
||||||
|
|
||||||
assert(word_ex == 0);
|
|
||||||
snprintf(buffer, sizeof buffer, "v%p_%u", sig, use_word);
|
|
||||||
args[idx].text = strdup(buffer);
|
|
||||||
continue;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* What's left, this is the work of a var
|
|
||||||
array. Create the right code to handle
|
|
||||||
it. */
|
|
||||||
ivl_signal_t sig = ivl_expr_signal(expr);
|
|
||||||
unsigned use_word = 0;
|
|
||||||
ivl_expr_t word_ex = ivl_expr_oper1(expr);
|
|
||||||
if (word_ex) {
|
|
||||||
/* Some array select have been evaluated. */
|
|
||||||
if (number_is_immediate(word_ex, 8*sizeof(unsigned), 0)) {
|
|
||||||
use_word = get_number_immediate(word_ex);
|
|
||||||
word_ex = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (word_ex && ivl_expr_type(word_ex)==IVL_EX_SIGNAL) {
|
|
||||||
/* Special case: the index is a signal. */
|
|
||||||
snprintf(buffer, sizeof buffer,
|
|
||||||
"&A<v%p, v%p_0 >", sig,
|
|
||||||
ivl_expr_signal(word_ex));
|
|
||||||
} else if (word_ex) {
|
|
||||||
/* Fallback case: evaluate expression. */
|
|
||||||
struct vector_info av;
|
|
||||||
av = draw_eval_expr(word_ex, STUFF_OK_XZ);
|
|
||||||
snprintf(buffer, sizeof buffer,
|
|
||||||
"&A<v%p, %u %u>", sig, av.base, av.wid);
|
|
||||||
args[idx].vec = av;
|
|
||||||
args[idx].vec_flag = 1;
|
|
||||||
} else {
|
|
||||||
snprintf(buffer, sizeof buffer,
|
|
||||||
"&A<v%p, %u>", sig, use_word);
|
|
||||||
}
|
|
||||||
args[idx].text = strdup(buffer);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
case IVL_EX_SELECT: {
|
|
||||||
ivl_expr_t vexpr = ivl_expr_oper1(expr);
|
|
||||||
assert(vexpr);
|
|
||||||
|
|
||||||
/* This code is only for signals. */
|
|
||||||
if (ivl_expr_type(vexpr) != IVL_EX_SIGNAL) break;
|
|
||||||
|
|
||||||
/* The signal is part of an array. */
|
|
||||||
/* Add &APV<> code here when it is finished. */
|
|
||||||
if (ivl_expr_oper1(vexpr)) break;
|
|
||||||
|
|
||||||
ivl_expr_t bexpr = ivl_expr_oper2(expr);
|
|
||||||
assert(bexpr);
|
|
||||||
|
|
||||||
/* This is a constant bit/part select. */
|
|
||||||
if (number_is_immediate(bexpr, 64, 1)) {
|
|
||||||
snprintf(buffer, sizeof buffer, "&PV<v%p_0, %ld, %u>",
|
|
||||||
ivl_expr_signal(vexpr),
|
|
||||||
get_number_immediate(bexpr),
|
|
||||||
ivl_expr_width(expr));
|
|
||||||
/* This is an indexed bit/part select. */
|
|
||||||
} else if (ivl_expr_type(bexpr) == IVL_EX_SIGNAL) {
|
|
||||||
/* Sepcial case: the base is a signal. */
|
|
||||||
snprintf(buffer, sizeof buffer, "&PV<v%p_0, v%p_0, %u>",
|
|
||||||
ivl_expr_signal(vexpr),
|
|
||||||
ivl_expr_signal(bexpr),
|
|
||||||
ivl_expr_width(expr));
|
|
||||||
} else {
|
|
||||||
/* Fallback case: evaluate the expression. */
|
|
||||||
struct vector_info rv;
|
|
||||||
rv = draw_eval_expr(bexpr, STUFF_OK_XZ);
|
|
||||||
snprintf(buffer, sizeof buffer, "&PV<v%p_0, %u %u, %u>",
|
|
||||||
ivl_expr_signal(vexpr),
|
|
||||||
rv.base, rv.wid,
|
|
||||||
ivl_expr_width(expr));
|
|
||||||
}
|
|
||||||
args[idx].text = strdup(buffer);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Everything else will need to be evaluated and
|
/* Everything else will need to be evaluated and
|
||||||
passed as a constant to the vpi task. */
|
passed as a constant to the vpi task. */
|
||||||
|
|
@ -301,14 +339,22 @@ static void draw_vpi_taskfunc_args(const char*call_string,
|
||||||
fprintf(vvp_out, "%s", call_string);
|
fprintf(vvp_out, "%s", call_string);
|
||||||
|
|
||||||
for (idx = 0 ; idx < parm_count ; idx += 1) {
|
for (idx = 0 ; idx < parm_count ; idx += 1) {
|
||||||
|
|
||||||
fprintf(vvp_out, ", %s", args[idx].text);
|
fprintf(vvp_out, ", %s", args[idx].text);
|
||||||
free(args[idx].text);
|
free(args[idx].text);
|
||||||
if (args[idx].vec_flag) {
|
struct args_info*ptr;
|
||||||
if (args[idx].vec.wid > 0)
|
/* Clear the nested children vectors. */
|
||||||
clr_vector(args[idx].vec);
|
for (ptr = &args[idx]; ptr != NULL; ptr = ptr->child) {
|
||||||
else
|
if (ptr->vec_flag) {
|
||||||
clr_word(args[idx].vec.base);
|
if (ptr->vec.wid > 0) clr_vector(ptr->vec);
|
||||||
|
else clr_word(ptr->vec.base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Free the nested children. */
|
||||||
|
ptr = args[idx].child;
|
||||||
|
while (ptr != NULL) {
|
||||||
|
struct args_info*tptr = ptr;
|
||||||
|
ptr = ptr->child;
|
||||||
|
free(tptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1670,22 +1670,31 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
|
||||||
vvp_errors += 1;
|
vvp_errors += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Detect the special case that the entire number fits in an
|
||||||
|
immediate. In this case we generate a single %movi
|
||||||
|
instruction. */
|
||||||
if ((!number_is_unknown(exp)) && number_is_immediate(exp, IMM_WID,0)) {
|
if ((!number_is_unknown(exp)) && number_is_immediate(exp, IMM_WID,0)) {
|
||||||
unsigned long val = get_number_immediate(exp);
|
unsigned long val = get_number_immediate(exp);
|
||||||
fprintf(vvp_out, " %%movi %u, %lu, %u;\n", res.base, val, wid);
|
fprintf(vvp_out, " %%movi %u, %lu, %u;\n", res.base, val, wid);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Use %movi as much as possible to build the value into the
|
||||||
|
destination. Use the %mov to handle the remaining general
|
||||||
|
bits. */
|
||||||
idx = 0;
|
idx = 0;
|
||||||
|
unsigned long val = 0;
|
||||||
|
unsigned val_bits = 0;
|
||||||
|
unsigned val_addr = res.base;
|
||||||
while (idx < nwid) {
|
while (idx < nwid) {
|
||||||
unsigned cnt;
|
char src = 0;
|
||||||
char src = '?';
|
|
||||||
switch (bits[idx]) {
|
switch (bits[idx]) {
|
||||||
case '0':
|
case '0':
|
||||||
src = '0';
|
val_bits += 1;
|
||||||
break;
|
break;
|
||||||
case '1':
|
case '1':
|
||||||
src = '1';
|
val |= 1UL << val_bits;
|
||||||
|
val_bits += 1;
|
||||||
break;
|
break;
|
||||||
case 'x':
|
case 'x':
|
||||||
src = '2';
|
src = '2';
|
||||||
|
|
@ -1695,14 +1704,29 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (cnt = 1 ; idx+cnt < nwid ; cnt += 1)
|
if (val_bits >= IMM_WID
|
||||||
if (bits[idx+cnt] != bits[idx])
|
|| (val_bits>0 && src != 0)
|
||||||
break;
|
|| (val_bits>0 && idx+1==nwid)) {
|
||||||
|
fprintf(vvp_out, " %%movi %u, %lu, %u;\n",
|
||||||
|
val_addr, val, val_bits);
|
||||||
|
val_addr += val_bits;
|
||||||
|
val_bits = 0;
|
||||||
|
val = 0;
|
||||||
|
}
|
||||||
|
|
||||||
fprintf(vvp_out, " %%mov %u, %c, %u;\n",
|
if (src != 0) {
|
||||||
res.base+idx, src, cnt);
|
assert(val_bits == 0);
|
||||||
|
unsigned cnt;
|
||||||
|
for (cnt = 1 ; idx+cnt < nwid ; cnt += 1)
|
||||||
|
if (bits[idx+cnt] != bits[idx])
|
||||||
|
break;
|
||||||
|
|
||||||
idx += cnt;
|
fprintf(vvp_out, " %%mov %u, %c, %u;\n", val_addr, src, cnt);
|
||||||
|
val_addr += cnt;
|
||||||
|
idx += cnt-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
idx += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pad the number up to the expression width. */
|
/* Pad the number up to the expression width. */
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ static PLI_INT32 sys_clog2_compiletf(PLI_BYTE8 *name)
|
||||||
|
|
||||||
vpi_printf("%s $clog2 takes at most one argument.\n", msg);
|
vpi_printf("%s $clog2 takes at most one argument.\n", msg);
|
||||||
vpi_printf("%*s Found %u extra argument%s.\n",
|
vpi_printf("%*s Found %u extra argument%s.\n",
|
||||||
strlen(msg), " ", argc, argc == 1 ? "" : "s");
|
(int) strlen(msg), " ", argc, argc == 1 ? "" : "s");
|
||||||
vpi_control(vpiFinish, 1);
|
vpi_control(vpiFinish, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
38
vvp/array.cc
38
vvp/array.cc
|
|
@ -75,6 +75,7 @@ struct __vpiArray {
|
||||||
|
|
||||||
class vvp_fun_arrayport*ports_;
|
class vvp_fun_arrayport*ports_;
|
||||||
struct __vpiCallback *vpi_callbacks;
|
struct __vpiCallback *vpi_callbacks;
|
||||||
|
bool signed_flag;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct __vpiArrayIterator {
|
struct __vpiArrayIterator {
|
||||||
|
|
@ -452,7 +453,8 @@ static void vpi_array_var_word_get_value(vpiHandle ref, p_vpi_value value)
|
||||||
unsigned index = decode_array_word_pointer(obj, parent);
|
unsigned index = decode_array_word_pointer(obj, parent);
|
||||||
unsigned width = parent->vals->width();
|
unsigned width = parent->vals->width();
|
||||||
|
|
||||||
vpip_vec4_get_value(parent->vals->get_word(index), width, false, value);
|
vpip_vec4_get_value(parent->vals->get_word(index), width,
|
||||||
|
parent->signed_flag, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static vpiHandle vpi_array_var_word_put_value(vpiHandle ref, p_vpi_value vp, int flags)
|
static vpiHandle vpi_array_var_word_put_value(vpiHandle ref, p_vpi_value vp, int flags)
|
||||||
|
|
@ -635,7 +637,7 @@ static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value value)
|
||||||
|
|
||||||
unsigned index = obj->get_address();
|
unsigned index = obj->get_address();
|
||||||
vvp_vector4_t tmp = array_get_word(parent, index);
|
vvp_vector4_t tmp = array_get_word(parent, index);
|
||||||
vpip_vec4_get_value(tmp, parent->vals_width, false, value);
|
vpip_vec4_get_value(tmp, parent->vals_width, parent->signed_flag, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static vpiHandle vpi_array_vthr_A_put_value(vpiHandle ref, p_vpi_value vp, int)
|
static vpiHandle vpi_array_vthr_A_put_value(vpiHandle ref, p_vpi_value vp, int)
|
||||||
|
|
@ -756,11 +758,14 @@ vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address)
|
||||||
}
|
}
|
||||||
|
|
||||||
static vpiHandle vpip_make_array(char*label, const char*name,
|
static vpiHandle vpip_make_array(char*label, const char*name,
|
||||||
int first_addr, int last_addr)
|
int first_addr, int last_addr,
|
||||||
|
bool signed_flag)
|
||||||
{
|
{
|
||||||
struct __vpiArray*obj = (struct __vpiArray*)
|
struct __vpiArray*obj = (struct __vpiArray*)
|
||||||
malloc(sizeof(struct __vpiArray));
|
malloc(sizeof(struct __vpiArray));
|
||||||
|
|
||||||
|
obj->signed_flag = signed_flag;
|
||||||
|
|
||||||
// Assume increasing addresses.
|
// Assume increasing addresses.
|
||||||
assert(last_addr >= first_addr);
|
assert(last_addr >= first_addr);
|
||||||
unsigned array_count = last_addr+1-first_addr;
|
unsigned array_count = last_addr+1-first_addr;
|
||||||
|
|
@ -833,7 +838,8 @@ void array_attach_word(vvp_array_t array, unsigned long addr, vpiHandle word)
|
||||||
void compile_var_array(char*label, char*name, int last, int first,
|
void compile_var_array(char*label, char*name, int last, int first,
|
||||||
int msb, int lsb, char signed_flag)
|
int msb, int lsb, char signed_flag)
|
||||||
{
|
{
|
||||||
vpiHandle obj = vpip_make_array(label, name, first, last);
|
vpiHandle obj = vpip_make_array(label, name, first, last,
|
||||||
|
signed_flag != 0);
|
||||||
|
|
||||||
struct __vpiArray*arr = ARRAY_HANDLE(obj);
|
struct __vpiArray*arr = ARRAY_HANDLE(obj);
|
||||||
|
|
||||||
|
|
@ -853,7 +859,7 @@ void compile_var_array(char*label, char*name, int last, int first,
|
||||||
void compile_real_array(char*label, char*name, int last, int first,
|
void compile_real_array(char*label, char*name, int last, int first,
|
||||||
int msb, int lsb)
|
int msb, int lsb)
|
||||||
{
|
{
|
||||||
vpiHandle obj = vpip_make_array(label, name, first, last);
|
vpiHandle obj = vpip_make_array(label, name, first, last, true);
|
||||||
|
|
||||||
struct __vpiArray*arr = ARRAY_HANDLE(obj);
|
struct __vpiArray*arr = ARRAY_HANDLE(obj);
|
||||||
vvp_array_t array = array_find(label);
|
vvp_array_t array = array_find(label);
|
||||||
|
|
@ -874,7 +880,7 @@ void compile_real_array(char*label, char*name, int last, int first,
|
||||||
|
|
||||||
void compile_net_array(char*label, char*name, int last, int first)
|
void compile_net_array(char*label, char*name, int last, int first)
|
||||||
{
|
{
|
||||||
vpiHandle obj = vpip_make_array(label, name, first, last);
|
vpiHandle obj = vpip_make_array(label, name, first, last, false);
|
||||||
|
|
||||||
struct __vpiArray*arr = ARRAY_HANDLE(obj);
|
struct __vpiArray*arr = ARRAY_HANDLE(obj);
|
||||||
arr->nets = (vpiHandle*)calloc(arr->array_count, sizeof(vpiHandle));
|
arr->nets = (vpiHandle*)calloc(arr->array_count, sizeof(vpiHandle));
|
||||||
|
|
@ -981,7 +987,8 @@ void array_word_change(vvp_array_t array, unsigned long addr)
|
||||||
if (cur->cb_data.value)
|
if (cur->cb_data.value)
|
||||||
vpip_vec4_get_value(array->vals->get_word(addr),
|
vpip_vec4_get_value(array->vals->get_word(addr),
|
||||||
array->vals_width,
|
array->vals_width,
|
||||||
false, cur->cb_data.value);
|
array->signed_flag,
|
||||||
|
cur->cb_data.value);
|
||||||
|
|
||||||
callback_execute(cur);
|
callback_execute(cur);
|
||||||
prev = cur;
|
prev = cur;
|
||||||
|
|
@ -1170,6 +1177,23 @@ vpiHandle vpip_make_vthr_A(char*label, char*symbol)
|
||||||
|
|
||||||
return &(obj->base);
|
return &(obj->base);
|
||||||
}
|
}
|
||||||
|
vpiHandle vpip_make_vthr_A(char*label, vpiHandle handle)
|
||||||
|
{
|
||||||
|
struct __vpiArrayVthrA*obj = (struct __vpiArrayVthrA*)
|
||||||
|
malloc(sizeof (struct __vpiArrayVthrA));
|
||||||
|
|
||||||
|
obj->base.vpi_type = &vpip_array_vthr_A_rt;
|
||||||
|
|
||||||
|
obj->array = array_find(label);
|
||||||
|
assert(obj->array);
|
||||||
|
free(label);
|
||||||
|
|
||||||
|
obj->address_handle = handle;
|
||||||
|
obj->address = 0;
|
||||||
|
obj->wid = 0;
|
||||||
|
|
||||||
|
return &(obj->base);
|
||||||
|
}
|
||||||
|
|
||||||
void compile_array_cleanup(void)
|
void compile_array_cleanup(void)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
14
vvp/parse.y
14
vvp/parse.y
|
|
@ -105,7 +105,7 @@ static struct __vpiModPath*modpath_dst = 0;
|
||||||
%type <table> udp_table
|
%type <table> udp_table
|
||||||
|
|
||||||
%type <argv> argument_opt argument_list
|
%type <argv> argument_opt argument_list
|
||||||
%type <vpi> argument
|
%type <vpi> argument symbol_access
|
||||||
%type <cdelay> delay delay_opt
|
%type <cdelay> delay delay_opt
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
@ -831,21 +831,29 @@ argument
|
||||||
{ $$ = vpip_make_binary_const($1.idx, $1.text);
|
{ $$ = vpip_make_binary_const($1.idx, $1.text);
|
||||||
free($1.text);
|
free($1.text);
|
||||||
}
|
}
|
||||||
| K_A '<' T_SYMBOL ',' T_NUMBER '>'
|
| symbol_access
|
||||||
|
{ $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
symbol_access
|
||||||
|
: K_A '<' T_SYMBOL ',' T_NUMBER '>'
|
||||||
{ $$ = vpip_make_vthr_A($3, $5); }
|
{ $$ = vpip_make_vthr_A($3, $5); }
|
||||||
| K_A '<' T_SYMBOL ',' T_NUMBER T_NUMBER '>'
|
| K_A '<' T_SYMBOL ',' T_NUMBER T_NUMBER '>'
|
||||||
{ $$ = vpip_make_vthr_A($3, $5, $6); }
|
{ $$ = vpip_make_vthr_A($3, $5, $6); }
|
||||||
| K_A '<' T_SYMBOL ',' T_SYMBOL '>'
|
| K_A '<' T_SYMBOL ',' T_SYMBOL '>'
|
||||||
{ $$ = vpip_make_vthr_A($3, $5); }
|
{ $$ = vpip_make_vthr_A($3, $5); }
|
||||||
|
| K_A '<' T_SYMBOL ',' symbol_access '>'
|
||||||
|
{ $$ = vpip_make_vthr_A($3, $5); }
|
||||||
| K_PV '<' T_SYMBOL ',' T_NUMBER ',' T_NUMBER '>'
|
| K_PV '<' T_SYMBOL ',' T_NUMBER ',' T_NUMBER '>'
|
||||||
{ $$ = vpip_make_PV($3, $5, $7); }
|
{ $$ = vpip_make_PV($3, $5, $7); }
|
||||||
| K_PV '<' T_SYMBOL ',' '-' T_NUMBER ',' T_NUMBER '>'
|
| K_PV '<' T_SYMBOL ',' '-' T_NUMBER ',' T_NUMBER '>'
|
||||||
{ $$ = vpip_make_PV($3, -$6, $8); }
|
{ $$ = vpip_make_PV($3, -$6, $8); }
|
||||||
| K_PV '<' T_SYMBOL ',' T_SYMBOL ',' T_NUMBER '>'
|
| K_PV '<' T_SYMBOL ',' T_SYMBOL ',' T_NUMBER '>'
|
||||||
{ $$ = vpip_make_PV($3, $5, $7); }
|
{ $$ = vpip_make_PV($3, $5, $7); }
|
||||||
|
| K_PV '<' T_SYMBOL ',' symbol_access ',' T_NUMBER '>'
|
||||||
|
{ $$ = vpip_make_PV($3, $5, $7); }
|
||||||
| K_PV '<' T_SYMBOL ',' T_NUMBER T_NUMBER ',' T_NUMBER '>'
|
| K_PV '<' T_SYMBOL ',' T_NUMBER T_NUMBER ',' T_NUMBER '>'
|
||||||
{ $$ = vpip_make_PV($3, $5, $6, $8); }
|
{ $$ = vpip_make_PV($3, $5, $6, $8); }
|
||||||
;
|
|
||||||
|
|
||||||
/* functor operands can only be a list of symbols. */
|
/* functor operands can only be a list of symbols. */
|
||||||
symbols
|
symbols
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,7 @@ struct __vpiPV {
|
||||||
};
|
};
|
||||||
extern vpiHandle vpip_make_PV(char*name, int base, int width);
|
extern vpiHandle vpip_make_PV(char*name, int base, int width);
|
||||||
extern vpiHandle vpip_make_PV(char*name, char*symbol, int width);
|
extern vpiHandle vpip_make_PV(char*name, char*symbol, int width);
|
||||||
|
extern vpiHandle vpip_make_PV(char*name, vpiHandle handle, int width);
|
||||||
extern vpiHandle vpip_make_PV(char*name, int tbase, int twid, int width);
|
extern vpiHandle vpip_make_PV(char*name, int tbase, int twid, int width);
|
||||||
|
|
||||||
extern struct __vpiPV* vpip_PV_from_handle(vpiHandle obj);
|
extern struct __vpiPV* vpip_PV_from_handle(vpiHandle obj);
|
||||||
|
|
@ -456,9 +457,10 @@ vpiHandle vpip_make_vthr_vector(unsigned base, unsigned wid, bool signed_flag);
|
||||||
|
|
||||||
vpiHandle vpip_make_vthr_word(unsigned base, const char*type);
|
vpiHandle vpip_make_vthr_word(unsigned base, const char*type);
|
||||||
|
|
||||||
vpiHandle vpip_make_vthr_A(char*symbol, unsigned index);
|
vpiHandle vpip_make_vthr_A(char*label, unsigned index);
|
||||||
vpiHandle vpip_make_vthr_A(char*label, char*symbol);
|
vpiHandle vpip_make_vthr_A(char*label, char*symbol);
|
||||||
vpiHandle vpip_make_vthr_A(char*symbol, unsigned tbase, unsigned twid);
|
vpiHandle vpip_make_vthr_A(char*label, unsigned tbase, unsigned twid);
|
||||||
|
vpiHandle vpip_make_vthr_A(char*label, vpiHandle handle);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function is called before any compilation to load VPI
|
* This function is called before any compilation to load VPI
|
||||||
|
|
|
||||||
|
|
@ -1171,6 +1171,21 @@ vpiHandle vpip_make_PV(char*var, char*symbol, int width)
|
||||||
return &obj->base;
|
return &obj->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vpiHandle vpip_make_PV(char*var, vpiHandle handle, int width)
|
||||||
|
{
|
||||||
|
struct __vpiPV*obj = (struct __vpiPV*) malloc(sizeof(struct __vpiPV));
|
||||||
|
obj->base.vpi_type = &vpip_PV_rt;
|
||||||
|
obj->parent = vvp_lookup_handle(var);
|
||||||
|
obj->sbase = handle;
|
||||||
|
obj->tbase = 0;
|
||||||
|
obj->twid = 0;
|
||||||
|
obj->width = (unsigned) width;
|
||||||
|
obj->net = 0;
|
||||||
|
functor_ref_lookup(&obj->net, var);
|
||||||
|
|
||||||
|
return &obj->base;
|
||||||
|
}
|
||||||
|
|
||||||
vpiHandle vpip_make_PV(char*var, int tbase, int twid, int width)
|
vpiHandle vpip_make_PV(char*var, int tbase, int twid, int width)
|
||||||
{
|
{
|
||||||
struct __vpiPV*obj = (struct __vpiPV*) malloc(sizeof(struct __vpiPV));
|
struct __vpiPV*obj = (struct __vpiPV*) malloc(sizeof(struct __vpiPV));
|
||||||
|
|
|
||||||
|
|
@ -1626,7 +1626,10 @@ static unsigned long* divide_bits(unsigned long*ap, unsigned long*bp, unsigned w
|
||||||
unsigned cur_ptr = cur-1;
|
unsigned cur_ptr = cur-1;
|
||||||
unsigned long cur_res;
|
unsigned long cur_res;
|
||||||
if (ap[cur_ptr+btop] >= bp[btop]) {
|
if (ap[cur_ptr+btop] >= bp[btop]) {
|
||||||
cur_res = ap[cur_ptr+btop] / bp[btop];
|
unsigned long high = 0;
|
||||||
|
if (cur_ptr+btop+1 < words)
|
||||||
|
high = ap[cur_ptr+btop+1];
|
||||||
|
cur_res = divide2words(ap[cur_ptr+btop], bp[btop], high);
|
||||||
|
|
||||||
} else if (cur_ptr+btop+1 >= words) {
|
} else if (cur_ptr+btop+1 >= words) {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -1749,6 +1752,9 @@ bool of_DIV_S(vthread_t thr, vvp_code_t cp)
|
||||||
|
|
||||||
assert(adra >= 4);
|
assert(adra >= 4);
|
||||||
|
|
||||||
|
// Get the values, left in right, in binary form. If there is
|
||||||
|
// a problem with either (caused by an X or Z bit) then we
|
||||||
|
// know right away that the entire result is X.
|
||||||
unsigned long*ap = vector_to_array(thr, adra, wid);
|
unsigned long*ap = vector_to_array(thr, adra, wid);
|
||||||
if (ap == 0) {
|
if (ap == 0) {
|
||||||
vvp_vector4_t tmp(wid, BIT4_X);
|
vvp_vector4_t tmp(wid, BIT4_X);
|
||||||
|
|
@ -1764,6 +1770,7 @@ bool of_DIV_S(vthread_t thr, vvp_code_t cp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sign extend the bits in the array to fill out the array.
|
||||||
unsigned long sign_mask = 0;
|
unsigned long sign_mask = 0;
|
||||||
if (unsigned long sign_bits = (words*CPU_WORD_BITS) - wid) {
|
if (unsigned long sign_bits = (words*CPU_WORD_BITS) - wid) {
|
||||||
sign_mask = -1UL << (CPU_WORD_BITS-sign_bits);
|
sign_mask = -1UL << (CPU_WORD_BITS-sign_bits);
|
||||||
|
|
@ -1773,6 +1780,7 @@ bool of_DIV_S(vthread_t thr, vvp_code_t cp)
|
||||||
bp[words-1] |= sign_mask;
|
bp[words-1] |= sign_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the value fits in a single word, then use the native divide.
|
||||||
if (wid <= CPU_WORD_BITS) {
|
if (wid <= CPU_WORD_BITS) {
|
||||||
if (bp[0] == 0) {
|
if (bp[0] == 0) {
|
||||||
vvp_vector4_t tmp(wid, BIT4_X);
|
vvp_vector4_t tmp(wid, BIT4_X);
|
||||||
|
|
|
||||||
|
|
@ -2144,22 +2144,19 @@ void vvp_net_fun_t::recv_vec4(vvp_net_ptr_t, const vvp_vector4_t&)
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vvp_net_fun_t::recv_vec4_pv(vvp_net_ptr_t, const vvp_vector4_t&bits,
|
void vvp_net_fun_t::recv_vec4_pv(vvp_net_ptr_t, const vvp_vector4_t&bit,
|
||||||
unsigned base, unsigned wid, unsigned vwid)
|
unsigned base, unsigned wid, unsigned vwid)
|
||||||
{
|
{
|
||||||
cerr << "internal error: " << typeid(*this).name() << ": "
|
cerr << "internal error: " << typeid(*this).name() << ": "
|
||||||
<< "recv_vec4_pv(" << bits << ", " << base
|
<< "recv_vec4_pv(" << bit << ", " << base
|
||||||
<< ", " << wid << ", " << vwid << ") not implemented" << endl;
|
<< ", " << wid << ", " << vwid << ") not implemented" << endl;
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vvp_net_fun_t::recv_vec8_pv(vvp_net_ptr_t, const vvp_vector8_t&bits,
|
void vvp_net_fun_t::recv_vec8_pv(vvp_net_ptr_t port, const vvp_vector8_t&bit,
|
||||||
unsigned base, unsigned wid, unsigned vwid)
|
unsigned base, unsigned wid, unsigned vwid)
|
||||||
{
|
{
|
||||||
cerr << "internal error: " << typeid(*this).name() << ": "
|
recv_vec4_pv(port, reduce4(bit), base, wid, vwid);
|
||||||
<< "recv_vec8_pv(" << bits << ", " << base
|
|
||||||
<< ", " << wid << ", " << vwid << ") not implemented" << endl;
|
|
||||||
assert(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vvp_net_fun_t::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
void vvp_net_fun_t::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
||||||
|
|
|
||||||
|
|
@ -859,8 +859,9 @@ struct vvp_net_t {
|
||||||
* port. The value is a vvp_vector4_t.
|
* port. The value is a vvp_vector4_t.
|
||||||
*
|
*
|
||||||
* Most nodes do not care about the specific strengths of bits, so the
|
* Most nodes do not care about the specific strengths of bits, so the
|
||||||
* default behavior for recv_vec8 is to reduce the operand to a
|
* default behavior for recv_vec8 and recv_vec8_pv is to reduce the
|
||||||
* vvp_vector4_t and pass it on to the recv_vec4 method.
|
* operand to a vvp_vector4_t and pass it on to the recv_vec4 or
|
||||||
|
* recv_vec4_pv method.
|
||||||
*/
|
*/
|
||||||
class vvp_net_fun_t {
|
class vvp_net_fun_t {
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue