Fix the compiler and modpath scaling of real delays.
A real delay must be scaled and rounded using the local precision before it is finally scaled to the simulation time units. This patch fixes the compiler to do this correctly or generate the correct code for run time calculated delays. Delays in a CA already worked correctly. The run time was also fixed to scale modpath (SDF back annotation) delays correctly.
This commit is contained in:
parent
3868334f5c
commit
21d15ceece
17
PDelays.cc
17
PDelays.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2009 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1999-2010 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -92,15 +92,10 @@ static NetExpr*calculate_val(Design*des, NetScope*scope, PExpr*expr)
|
||||||
units, and return an adjusted value. */
|
units, and return an adjusted value. */
|
||||||
|
|
||||||
if (NetECReal*tmp = dynamic_cast<NetECReal*>(dex)) {
|
if (NetECReal*tmp = dynamic_cast<NetECReal*>(dex)) {
|
||||||
verireal fn = tmp->value();
|
uint64_t delay = get_scaled_time_from_real(des, scope, tmp);
|
||||||
|
|
||||||
int shift = scope->time_unit() - des->get_precision();
|
|
||||||
int64_t delay = fn.as_long64(shift);
|
|
||||||
if (delay < 0)
|
|
||||||
delay = 0;
|
|
||||||
|
|
||||||
delete tmp;
|
delete tmp;
|
||||||
NetEConst*tmp2 = new NetEConst(verinum(delay));
|
NetEConst*tmp2 = new NetEConst(verinum(delay, 64));
|
||||||
tmp2->set_line(*expr);
|
tmp2->set_line(*expr);
|
||||||
return tmp2;
|
return tmp2;
|
||||||
}
|
}
|
||||||
|
|
@ -108,11 +103,10 @@ static NetExpr*calculate_val(Design*des, NetScope*scope, PExpr*expr)
|
||||||
|
|
||||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(dex)) {
|
if (NetEConst*tmp = dynamic_cast<NetEConst*>(dex)) {
|
||||||
verinum fn = tmp->value();
|
verinum fn = tmp->value();
|
||||||
|
|
||||||
uint64_t delay = des->scale_to_precision(fn.as_ulong64(), scope);
|
uint64_t delay = des->scale_to_precision(fn.as_ulong64(), scope);
|
||||||
|
|
||||||
delete tmp;
|
delete tmp;
|
||||||
NetEConst*tmp2 = new NetEConst(verinum(delay));
|
NetEConst*tmp2 = new NetEConst(verinum(delay, 64));
|
||||||
tmp2->set_line(*expr);
|
tmp2->set_line(*expr);
|
||||||
return tmp2;
|
return tmp2;
|
||||||
}
|
}
|
||||||
|
|
@ -132,7 +126,8 @@ static NetExpr* make_delay_nets(Design*des, NetScope*scope, NetExpr*expr)
|
||||||
NetNet*sig = expr->synthesize(des, scope, expr);
|
NetNet*sig = expr->synthesize(des, scope, expr);
|
||||||
if (sig == 0) {
|
if (sig == 0) {
|
||||||
cerr << expr->get_fileline() << ": error: Expression " << *expr
|
cerr << expr->get_fileline() << ": error: Expression " << *expr
|
||||||
<< " is not suitable for delay expression." << endl;
|
<< " is not suitable as a delay expression." << endl;
|
||||||
|
des->errors += 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -161,3 +161,11 @@ NetEUReduce* NetEUReduce::dup_expr() const
|
||||||
tmp->set_line(*this);
|
tmp->set_line(*this);
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetECast* NetECast::dup_expr() const
|
||||||
|
{
|
||||||
|
NetECast*tmp = new NetECast(op_, expr_->dup_expr());
|
||||||
|
assert(tmp);
|
||||||
|
tmp->set_line(*this);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
|
||||||
89
elaborate.cc
89
elaborate.cc
|
|
@ -1960,55 +1960,68 @@ static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope)
|
||||||
units, and return an adjusted NetEConst. */
|
units, and return an adjusted NetEConst. */
|
||||||
|
|
||||||
if (NetECReal*tmp = dynamic_cast<NetECReal*>(dex)) {
|
if (NetECReal*tmp = dynamic_cast<NetECReal*>(dex)) {
|
||||||
verireal fn = tmp->value();
|
uint64_t delay = get_scaled_time_from_real(des, scope, tmp);
|
||||||
|
|
||||||
int shift = scope->time_unit() - des->get_precision();
|
|
||||||
int64_t delay = fn.as_long64(shift);
|
|
||||||
if (delay < 0)
|
|
||||||
delay = 0;
|
|
||||||
|
|
||||||
delete tmp;
|
delete tmp;
|
||||||
return new NetEConst(verinum(delay));
|
NetEConst*tmp2 = new NetEConst(verinum(delay, 64));
|
||||||
|
tmp2->set_line(*expr);
|
||||||
|
return tmp2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(dex)) {
|
if (NetEConst*tmp = dynamic_cast<NetEConst*>(dex)) {
|
||||||
verinum fn = tmp->value();
|
verinum fn = tmp->value();
|
||||||
|
uint64_t delay = des->scale_to_precision(fn.as_ulong64(), scope);
|
||||||
uint64_t delay =
|
|
||||||
des->scale_to_precision(fn.as_ulong64(), scope);
|
|
||||||
|
|
||||||
delete tmp;
|
delete tmp;
|
||||||
return new NetEConst(verinum(delay));
|
NetEConst*tmp2 = new NetEConst(verinum(delay, 64));
|
||||||
|
tmp2->set_line(*expr);
|
||||||
|
return tmp2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* The expression is not constant, so generate an expanded
|
/* The expression is not constant, so generate an expanded
|
||||||
expression that includes the necessary scale shifts, and
|
expression that includes the necessary scale shifts, and
|
||||||
return that expression. */
|
return that expression. */
|
||||||
int shift = scope->time_unit() - des->get_precision();
|
ivl_assert(*expr, dex);
|
||||||
if (shift > 0) {
|
if (dex->expr_type() == IVL_VT_REAL) {
|
||||||
uint64_t scale = 1;
|
// Scale the real value.
|
||||||
while (shift > 0) {
|
int shift = scope->time_unit() - scope->time_precision();
|
||||||
scale *= 10;
|
assert(shift >= 0);
|
||||||
shift -= 1;
|
double round = 1;
|
||||||
}
|
for (int lp = 0; lp < shift; lp += 1) round *= 10.0;
|
||||||
|
|
||||||
ivl_assert(*expr, dex);
|
NetExpr*scal_val = new NetECReal(verireal(round));
|
||||||
NetExpr*scal_val = new NetEConst(verinum(scale));
|
scal_val->set_line(*expr);
|
||||||
dex = new NetEBMult('*', dex, scal_val);
|
dex = new NetEBMult('*', dex, scal_val);
|
||||||
}
|
dex->set_line(*expr);
|
||||||
|
|
||||||
if (shift < 0) {
|
// Cast this part of the expression to an integer.
|
||||||
unsigned long scale = 1;
|
dex = new NetECast('i', dex);
|
||||||
while (shift < 0) {
|
dex->set_width(64);
|
||||||
scale *= 10;
|
dex->set_line(*expr);
|
||||||
shift += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ivl_assert(*expr, dex);
|
// Now scale the integer value.
|
||||||
NetExpr*scal_val = new NetEConst(verinum(scale));
|
shift = scope->time_precision() - des->get_precision();
|
||||||
dex = new NetEBDiv('/', dex, scal_val);
|
assert(shift >= 0);
|
||||||
|
uint64_t scale = 1;
|
||||||
|
for (int lp = 0; lp < shift; lp += 1) scale *= 10;
|
||||||
|
|
||||||
|
scal_val = new NetEConst(verinum(scale, 64));
|
||||||
|
scal_val->set_line(*expr);
|
||||||
|
dex = new NetEBMult('*', dex, scal_val);
|
||||||
|
dex->set_width(64);
|
||||||
|
dex->set_line(*expr);
|
||||||
|
} else {
|
||||||
|
int shift = scope->time_unit() - des->get_precision();
|
||||||
|
assert(shift >= 0);
|
||||||
|
uint64_t scale = 1;
|
||||||
|
for (int lp = 0; lp < shift; lp += 1) scale *= 10;
|
||||||
|
|
||||||
|
NetExpr*scal_val = new NetEConst(verinum(scale, 64));
|
||||||
|
scal_val->set_line(*expr);
|
||||||
|
dex = new NetEBMult('*', dex, scal_val);
|
||||||
|
dex->set_line(*expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dex;
|
return dex;
|
||||||
|
|
@ -3901,7 +3914,6 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
|
||||||
"module(s) with no `timescale." << endl;
|
"module(s) with no `timescale." << endl;
|
||||||
display_ts_dly_warning = false;
|
display_ts_dly_warning = false;
|
||||||
}
|
}
|
||||||
int shift = scope->time_unit() - des->get_precision();
|
|
||||||
|
|
||||||
/* Elaborate the delay values themselves. Remember to scale
|
/* Elaborate the delay values themselves. Remember to scale
|
||||||
them for the timescale/precision of the scope. */
|
them for the timescale/precision of the scope. */
|
||||||
|
|
@ -3910,17 +3922,18 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
|
||||||
probe_expr_width(des, scope, exp);
|
probe_expr_width(des, scope, exp);
|
||||||
NetExpr*cur = elab_and_eval(des, scope, exp, 0);
|
NetExpr*cur = elab_and_eval(des, scope, exp, 0);
|
||||||
|
|
||||||
if (NetEConst*cur_con = dynamic_cast<NetEConst*> (cur)) {
|
if (NetEConst*con = dynamic_cast<NetEConst*> (cur)) {
|
||||||
delay_value[idx] = cur_con->value().as_ulong();
|
verinum fn = con->value();
|
||||||
for (int tmp = 0 ; tmp < shift ; tmp += 1)
|
delay_value[idx] = des->scale_to_precision(fn.as_ulong64(),
|
||||||
delay_value[idx] *= 10;
|
scope);
|
||||||
|
|
||||||
} else if (NetECReal*cur_rcon = dynamic_cast<NetECReal*>(cur)) {
|
} else if (NetECReal*rcon = dynamic_cast<NetECReal*>(cur)) {
|
||||||
delay_value[idx] = cur_rcon->value().as_long(shift);
|
delay_value[idx] = get_scaled_time_from_real(des, scope,
|
||||||
|
rcon);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
cerr << get_fileline() << ": error: Path delay value "
|
cerr << get_fileline() << ": error: Path delay value "
|
||||||
<< "must be constant." << endl;
|
<< "must be constant (" << *cur << ")." << endl;
|
||||||
delay_value[idx] = 0;
|
delay_value[idx] = 0;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2009 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1999-2010 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -977,6 +977,28 @@ NetNet* NetEUReduce::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||||
return osig;
|
return osig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetNet* NetECast::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||||
|
{
|
||||||
|
NetNet*isig = expr_->synthesize(des, scope, root);
|
||||||
|
|
||||||
|
if (isig == 0) return 0;
|
||||||
|
|
||||||
|
switch (op()) {
|
||||||
|
case 'i':
|
||||||
|
isig = cast_to_int(des, scope, isig, isig->vector_width());
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
isig = cast_to_real(des, scope, isig);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
cerr << get_fileline() << ": internal error: "
|
||||||
|
<< "Unable to synthesize " << *this << "." << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isig;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Turn a part/bit select expression into gates.
|
* Turn a part/bit select expression into gates.
|
||||||
* We know some things about the expression that elaboration enforces
|
* We know some things about the expression that elaboration enforces
|
||||||
|
|
|
||||||
26
netlist.cc
26
netlist.cc
|
|
@ -2430,6 +2430,32 @@ ivl_variable_type_t NetEUReduce::expr_type() const
|
||||||
return expr_->expr_type();
|
return expr_->expr_type();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetECast::NetECast(char op__, NetExpr*ex)
|
||||||
|
: NetEUnary(op__, ex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NetECast::~NetECast()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ivl_variable_type_t NetECast::expr_type() const
|
||||||
|
{
|
||||||
|
ivl_variable_type_t ret;
|
||||||
|
switch (op_) {
|
||||||
|
case 'i':
|
||||||
|
ret = IVL_VT_LOGIC;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
ret = IVL_VT_REAL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
NetLogic::NetLogic(NetScope*s, perm_string n, unsigned pins,
|
NetLogic::NetLogic(NetScope*s, perm_string n, unsigned pins,
|
||||||
TYPE t, unsigned wid)
|
TYPE t, unsigned wid)
|
||||||
: NetNode(s, n, pins), type_(t), width_(wid)
|
: NetNode(s, n, pins), type_(t), width_(wid)
|
||||||
|
|
|
||||||
13
netlist.h
13
netlist.h
|
|
@ -3750,6 +3750,8 @@ class NetETernary : public NetExpr {
|
||||||
* N -- Reduction NOR (~|)
|
* N -- Reduction NOR (~|)
|
||||||
* X -- Reduction NXOR (~^ or ^~)
|
* X -- Reduction NXOR (~^ or ^~)
|
||||||
* m -- abs(x) (i.e. "magnitude")
|
* m -- abs(x) (i.e. "magnitude")
|
||||||
|
* i -- Cast from real to integer (vector)
|
||||||
|
* r -- Cast from integer (vector) to real
|
||||||
*/
|
*/
|
||||||
class NetEUnary : public NetExpr {
|
class NetEUnary : public NetExpr {
|
||||||
|
|
||||||
|
|
@ -3805,6 +3807,17 @@ class NetEUReduce : public NetEUnary {
|
||||||
virtual ivl_variable_type_t expr_type() const;
|
virtual ivl_variable_type_t expr_type() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class NetECast : public NetEUnary {
|
||||||
|
|
||||||
|
public:
|
||||||
|
NetECast(char op, NetExpr*ex);
|
||||||
|
~NetECast();
|
||||||
|
|
||||||
|
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
||||||
|
virtual NetECast* dup_expr() const;
|
||||||
|
virtual ivl_variable_type_t expr_type() const;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When a signal shows up in an expression, this type represents
|
* When a signal shows up in an expression, this type represents
|
||||||
* it. From this the expression can get any kind of access to the
|
* it. From this the expression can get any kind of access to the
|
||||||
|
|
|
||||||
16
netmisc.cc
16
netmisc.cc
|
|
@ -494,3 +494,19 @@ const_bool const_logical(const NetExpr*expr)
|
||||||
|
|
||||||
return C_NON;
|
return C_NON;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t get_scaled_time_from_real(Design*des, NetScope*scope, NetECReal*val)
|
||||||
|
{
|
||||||
|
verireal fn = val->value();
|
||||||
|
|
||||||
|
int shift = scope->time_unit() - scope->time_precision();
|
||||||
|
assert(shift >= 0);
|
||||||
|
int64_t delay = fn.as_long64(shift);
|
||||||
|
|
||||||
|
|
||||||
|
shift = scope->time_precision() - des->get_precision();
|
||||||
|
assert(shift >= 0);
|
||||||
|
for (int lp = 0; lp < shift; lp += 1) delay *= 10;
|
||||||
|
|
||||||
|
return delay;
|
||||||
|
}
|
||||||
|
|
|
||||||
10
netmisc.h
10
netmisc.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __netmisc_H
|
#ifndef __netmisc_H
|
||||||
#define __netmisc_H
|
#define __netmisc_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2009 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1999-2010 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -235,4 +235,12 @@ extern bool dly_used_no_timescale;
|
||||||
extern bool dly_used_timescale;
|
extern bool dly_used_timescale;
|
||||||
extern bool display_ts_dly_warning;
|
extern bool display_ts_dly_warning;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When scaling a real value to a time we need to do some standard
|
||||||
|
* processing.
|
||||||
|
*/
|
||||||
|
extern uint64_t get_scaled_time_from_real(Design*des,
|
||||||
|
NetScope*scope,
|
||||||
|
NetECReal*val);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1999-2010 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -474,6 +474,8 @@ bool NetEUnary::set_width(unsigned w, bool)
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case '~':
|
case '~':
|
||||||
case '-':
|
case '-':
|
||||||
|
case 'r':
|
||||||
|
case 'i':
|
||||||
flag = expr_->set_width(w);
|
flag = expr_->set_width(w);
|
||||||
expr_width(w);
|
expr_width(w);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -286,8 +286,8 @@ void draw_eval_expr_into_integer(ivl_expr_t expr, unsigned ix)
|
||||||
|
|
||||||
case IVL_VT_REAL:
|
case IVL_VT_REAL:
|
||||||
word = draw_eval_real(expr);
|
word = draw_eval_real(expr);
|
||||||
clr_word(word);
|
|
||||||
fprintf(vvp_out, " %%cvt/sr %u, %u;\n", ix, word);
|
fprintf(vvp_out, " %%cvt/sr %u, %u;\n", ix, word);
|
||||||
|
clr_word(word);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -2933,7 +2933,7 @@ static struct vector_info draw_unary_expr(ivl_expr_t expr, unsigned wid)
|
||||||
struct vector_info res;
|
struct vector_info res;
|
||||||
ivl_expr_t sub = ivl_expr_oper1(expr);
|
ivl_expr_t sub = ivl_expr_oper1(expr);
|
||||||
const char *rop = 0;
|
const char *rop = 0;
|
||||||
int inv = 0;
|
int word, inv = 0;
|
||||||
|
|
||||||
switch (ivl_expr_opcode(expr)) {
|
switch (ivl_expr_opcode(expr)) {
|
||||||
case '&': rop = "and"; break;
|
case '&': rop = "and"; break;
|
||||||
|
|
@ -3117,15 +3117,32 @@ static struct vector_info draw_unary_expr(ivl_expr_t expr, unsigned wid)
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(vvp_out, " %%cmpi/s %d, 0, %u;\n", res.base, res.wid);
|
fprintf(vvp_out, " %%cmpi/s %d, 0, %u;\n", res.base, res.wid);
|
||||||
fprintf(vvp_out, " %%jmp/0xz T_%u.%u, 5;\n", thread_count, local_count);
|
fprintf(vvp_out, " %%jmp/0xz T_%u.%u, 5;\n", thread_count,
|
||||||
|
local_count);
|
||||||
fprintf(vvp_out, " %%inv %d, %u;\n", res.base, res.wid);
|
fprintf(vvp_out, " %%inv %d, %u;\n", res.base, res.wid);
|
||||||
fprintf(vvp_out, " %%addi %d, 1, %u;\n", res.base, res.wid);
|
fprintf(vvp_out, " %%addi %d, 1, %u;\n", res.base, res.wid);
|
||||||
fprintf(vvp_out, "T_%u.%u ;\n", thread_count, local_count);
|
fprintf(vvp_out, "T_%u.%u ;\n", thread_count, local_count);
|
||||||
local_count += 1;
|
local_count += 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'i': /* Cast a real value to an integer. */
|
||||||
|
assert(ivl_expr_value(sub) == IVL_VT_REAL);
|
||||||
|
word = draw_eval_real(sub);
|
||||||
|
res.base = allocate_vector(wid);
|
||||||
|
res.wid = wid;
|
||||||
|
fprintf(vvp_out, " %%cvt/vr %u, %u, %u;\n", res.base, word,
|
||||||
|
res.wid);
|
||||||
|
clr_word(word);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'r': /* Handled in eval_real.c. */
|
||||||
|
fprintf(stderr, "vvp error: integer -> real cast in integer "
|
||||||
|
"context.\n");
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "vvp error: unhandled unary: %c\n",
|
fprintf(stderr, "vvp error: unhandled unary operator: %c\n",
|
||||||
ivl_expr_opcode(expr));
|
ivl_expr_opcode(expr));
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003-2009 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2003-2010 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -139,6 +139,7 @@ static int draw_binary_real(ivl_expr_t expr)
|
||||||
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_out);
|
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_out);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "XXXX draw_binary_real(%c)\n",
|
fprintf(stderr, "XXXX draw_binary_real(%c)\n",
|
||||||
ivl_expr_opcode(expr));
|
ivl_expr_opcode(expr));
|
||||||
|
|
@ -444,6 +445,20 @@ static int draw_unary_real(ivl_expr_t expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
sube = ivl_expr_oper1(expr);
|
sube = ivl_expr_oper1(expr);
|
||||||
|
|
||||||
|
if (ivl_expr_opcode(expr) == 'r') { /* Cast an integer value to a real. */
|
||||||
|
struct vector_info res;
|
||||||
|
char *suffix = "";
|
||||||
|
assert(ivl_expr_value(sube) != IVL_VT_REAL);
|
||||||
|
res = draw_eval_expr(sube, 1);
|
||||||
|
if (ivl_expr_signed(sube)) suffix = "/s";
|
||||||
|
sub = allocate_word();
|
||||||
|
fprintf(vvp_out, " %%cvt/rv%s %d, %u, %u;\n", suffix, sub,
|
||||||
|
res.base, res.wid);
|
||||||
|
clr_vector(res);
|
||||||
|
return sub;
|
||||||
|
}
|
||||||
|
|
||||||
sub = draw_eval_real(sube);
|
sub = draw_eval_real(sube);
|
||||||
|
|
||||||
if (ivl_expr_opcode(expr) == '+')
|
if (ivl_expr_opcode(expr) == '+')
|
||||||
|
|
@ -458,16 +473,20 @@ static int draw_unary_real(ivl_expr_t expr)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ivl_expr_opcode(expr) == 'm') { /* abs(sube) */
|
if (ivl_expr_opcode(expr) == 'm') { /* abs() */
|
||||||
fprintf(vvp_out, " %%abs/wr %d, %d;\n", sub, sub);
|
fprintf(vvp_out, " %%abs/wr %d, %d;\n", sub, sub);
|
||||||
return sub;
|
return sub;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(vvp_out, "; XXXX unary (%c) on sube in %d\n",
|
if (ivl_expr_opcode(expr) == 'i') { /* Handled in eval_expr.c. */
|
||||||
ivl_expr_opcode(expr), sub);
|
fprintf(stderr, "vvp error: real -> integer cast in real "
|
||||||
fprintf(stderr, "XXXX evaluate unary (%c) on sube in %d\n",
|
"context.\n");
|
||||||
ivl_expr_opcode(expr), sub);
|
assert(0);
|
||||||
return 0;
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "vvp error: unhandled real unary operator: %c.\n",
|
||||||
|
ivl_expr_opcode(expr));
|
||||||
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int draw_eval_real(ivl_expr_t expr)
|
int draw_eval_real(ivl_expr_t expr)
|
||||||
|
|
|
||||||
|
|
@ -192,10 +192,6 @@ void sdf_iopath_delays(int vpi_edge, const char*src, const char*dst,
|
||||||
delay_vals[idx].type = vpiScaledRealTime;
|
delay_vals[idx].type = vpiScaledRealTime;
|
||||||
if (delval_list->val[idx].defined) {
|
if (delval_list->val[idx].defined) {
|
||||||
delay_vals[idx].real = delval_list->val[idx].value;
|
delay_vals[idx].real = delval_list->val[idx].value;
|
||||||
/* Simulation cannot support negative delays. */
|
|
||||||
if (delay_vals[idx].real < 0.0) {
|
|
||||||
delay_vals[idx].real = 0.0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -781,7 +781,7 @@ static int modpath_src_free_object( vpiHandle ref )
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This routine will put specific dimension of delay[] values
|
* This routine will put specific dimension of delay[] values
|
||||||
* into a vpiHandle. In this case, he will put
|
* into a vpiHandle. In this case, we will put
|
||||||
* specific delays values in a vpiModPathIn object
|
* specific delays values in a vpiModPathIn object
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
@ -817,6 +817,11 @@ static void modpath_src_put_delays (vpiHandle ref, p_vpi_delay delays)
|
||||||
tmp[idx] = vpip_timestruct_to_time(delays->da+use_map[0][idx]);
|
tmp[idx] = vpip_timestruct_to_time(delays->da+use_map[0][idx]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// You cannot create a modpath with a negative delay so set it
|
||||||
|
// to zero per 1364-2005 section 14.3.1.
|
||||||
|
for (idx = 0 ; idx < delays->no_of_delays ; idx += 1) {
|
||||||
|
if (delays->da[idx].real < 0.0) delays->da[idx].real = 0.0;
|
||||||
|
}
|
||||||
for (idx = 0 ; idx < 12 ; idx += 1) {
|
for (idx = 0 ; idx < 12 ; idx += 1) {
|
||||||
tmp[idx] = vpip_scaled_real_to_time64(delays->da[use_map[0][idx]].real,
|
tmp[idx] = vpip_scaled_real_to_time64(delays->da[use_map[0][idx]].real,
|
||||||
src->dest->scope);
|
src->dest->scope);
|
||||||
|
|
|
||||||
|
|
@ -67,18 +67,33 @@ double vpip_time_to_scaled_real(vvp_time64_t ti, struct __vpiScope*scope)
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This routine does not currently support negative real delays and it
|
||||||
|
* does not check for overflow. It is only used for modpath delays and
|
||||||
|
* they are required to be non-negative.
|
||||||
|
*/
|
||||||
vvp_time64_t vpip_scaled_real_to_time64(double val, struct __vpiScope*scope)
|
vvp_time64_t vpip_scaled_real_to_time64(double val, struct __vpiScope*scope)
|
||||||
{
|
{
|
||||||
int units;
|
int shift = 0;
|
||||||
if (scope)
|
if (scope) shift = scope->time_units - scope->time_precision;
|
||||||
units = scope->time_units;
|
assert(shift >= 0);
|
||||||
else
|
|
||||||
units = vpi_time_precision;
|
|
||||||
|
|
||||||
double scale = pow(10.0L, units - vpi_time_precision);
|
assert(val >= 0);
|
||||||
|
|
||||||
|
// Scale to the local precision and then round away from zero.
|
||||||
|
double scale = pow(10.0L, shift);
|
||||||
val *= scale;
|
val *= scale;
|
||||||
|
|
||||||
return (vvp_time64_t) val;
|
vvp_time64_t delay = (vvp_time64_t) (val + 0.5);
|
||||||
|
|
||||||
|
// If needed now scale the value to the simulator precision.
|
||||||
|
if (scope) {
|
||||||
|
shift = scope->time_precision - vpi_time_precision;
|
||||||
|
assert(shift >= 0);
|
||||||
|
for (int lp = 0; lp < shift; lp += 1) delay *= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
return delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int timevar_time_get(int code, vpiHandle ref)
|
static int timevar_time_get(int code, vpiHandle ref)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue