Permalink
Browse files

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.
  • Loading branch information...
1 parent 3868334 commit 21d15ceece7ee6f6d54d1030f5b117a46f8e8165 @caryr caryr committed with Jun 18, 2010
Showing with 230 additions and 75 deletions.
  1. +6 −11 PDelays.cc
  2. +8 −0 dup_expr.cc
  3. +51 −38 elaborate.cc
  4. +23 −1 expr_synth.cc
  5. +26 −0 netlist.cc
  6. +13 −0 netlist.h
  7. +16 −0 netmisc.cc
  8. +9 −1 netmisc.h
  9. +3 −1 set_width.cc
  10. +21 −4 tgt-vvp/eval_expr.c
  11. +26 −7 tgt-vvp/eval_real.c
  12. +0 −4 vpi/sys_sdf.c
  13. +6 −1 vvp/delay.cc
  14. +22 −7 vvp/vpi_time.cc
View
@@ -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
* and/or modify it in source code form under the terms of the GNU
@@ -92,27 +92,21 @@ static NetExpr*calculate_val(Design*des, NetScope*scope, PExpr*expr)
units, and return an adjusted value. */
if (NetECReal*tmp = dynamic_cast<NetECReal*>(dex)) {
- verireal fn = tmp->value();
-
- int shift = scope->time_unit() - des->get_precision();
- int64_t delay = fn.as_long64(shift);
- if (delay < 0)
- delay = 0;
+ uint64_t delay = get_scaled_time_from_real(des, scope, tmp);
delete tmp;
- NetEConst*tmp2 = new NetEConst(verinum(delay));
+ NetEConst*tmp2 = new NetEConst(verinum(delay, 64));
tmp2->set_line(*expr);
return tmp2;
}
if (NetEConst*tmp = dynamic_cast<NetEConst*>(dex)) {
verinum fn = tmp->value();
-
uint64_t delay = des->scale_to_precision(fn.as_ulong64(), scope);
delete tmp;
- NetEConst*tmp2 = new NetEConst(verinum(delay));
+ NetEConst*tmp2 = new NetEConst(verinum(delay, 64));
tmp2->set_line(*expr);
return tmp2;
}
@@ -132,7 +126,8 @@ static NetExpr* make_delay_nets(Design*des, NetScope*scope, NetExpr*expr)
NetNet*sig = expr->synthesize(des, scope, expr);
if (sig == 0) {
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;
}
View
@@ -161,3 +161,11 @@ NetEUReduce* NetEUReduce::dup_expr() const
tmp->set_line(*this);
return tmp;
}
+
+NetECast* NetECast::dup_expr() const
+{
+ NetECast*tmp = new NetECast(op_, expr_->dup_expr());
+ assert(tmp);
+ tmp->set_line(*this);
+ return tmp;
+}
View
@@ -1960,55 +1960,68 @@ static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope)
units, and return an adjusted NetEConst. */
if (NetECReal*tmp = dynamic_cast<NetECReal*>(dex)) {
- verireal fn = tmp->value();
-
- int shift = scope->time_unit() - des->get_precision();
- int64_t delay = fn.as_long64(shift);
- if (delay < 0)
- delay = 0;
+ uint64_t delay = get_scaled_time_from_real(des, scope, 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)) {
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;
- 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
expression that includes the necessary scale shifts, and
return that expression. */
- int shift = scope->time_unit() - des->get_precision();
- if (shift > 0) {
+ ivl_assert(*expr, dex);
+ if (dex->expr_type() == IVL_VT_REAL) {
+ // Scale the real value.
+ int shift = scope->time_unit() - scope->time_precision();
+ assert(shift >= 0);
+ double round = 1;
+ for (int lp = 0; lp < shift; lp += 1) round *= 10.0;
+
+ NetExpr*scal_val = new NetECReal(verireal(round));
+ scal_val->set_line(*expr);
+ dex = new NetEBMult('*', dex, scal_val);
+ dex->set_line(*expr);
+
+ // Cast this part of the expression to an integer.
+ dex = new NetECast('i', dex);
+ dex->set_width(64);
+ dex->set_line(*expr);
+
+ // Now scale the integer value.
+ shift = scope->time_precision() - des->get_precision();
+ assert(shift >= 0);
uint64_t scale = 1;
- while (shift > 0) {
- scale *= 10;
- shift -= 1;
- }
+ for (int lp = 0; lp < shift; lp += 1) scale *= 10;
- ivl_assert(*expr, dex);
- NetExpr*scal_val = new NetEConst(verinum(scale));
+ scal_val = new NetEConst(verinum(scale, 64));
+ scal_val->set_line(*expr);
dex = new NetEBMult('*', dex, scal_val);
- }
-
- if (shift < 0) {
- unsigned long scale = 1;
- while (shift < 0) {
- scale *= 10;
- shift += 1;
- }
+ 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;
- ivl_assert(*expr, dex);
- NetExpr*scal_val = new NetEConst(verinum(scale));
- dex = new NetEBDiv('/', dex, scal_val);
+ 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;
@@ -3901,7 +3914,6 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
"module(s) with no `timescale." << endl;
display_ts_dly_warning = false;
}
- int shift = scope->time_unit() - des->get_precision();
/* Elaborate the delay values themselves. Remember to scale
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);
NetExpr*cur = elab_and_eval(des, scope, exp, 0);
- if (NetEConst*cur_con = dynamic_cast<NetEConst*> (cur)) {
- delay_value[idx] = cur_con->value().as_ulong();
- for (int tmp = 0 ; tmp < shift ; tmp += 1)
- delay_value[idx] *= 10;
+ if (NetEConst*con = dynamic_cast<NetEConst*> (cur)) {
+ verinum fn = con->value();
+ delay_value[idx] = des->scale_to_precision(fn.as_ulong64(),
+ scope);
- } else if (NetECReal*cur_rcon = dynamic_cast<NetECReal*>(cur)) {
- delay_value[idx] = cur_rcon->value().as_long(shift);
+ } else if (NetECReal*rcon = dynamic_cast<NetECReal*>(cur)) {
+ delay_value[idx] = get_scaled_time_from_real(des, scope,
+ rcon);
} else {
cerr << get_fileline() << ": error: Path delay value "
- << "must be constant." << endl;
+ << "must be constant (" << *cur << ")." << endl;
delay_value[idx] = 0;
des->errors += 1;
}
View
@@ -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
* 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;
}
+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.
* We know some things about the expression that elaboration enforces
View
@@ -2430,6 +2430,32 @@ ivl_variable_type_t NetEUReduce::expr_type() const
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,
TYPE t, unsigned wid)
: NetNode(s, n, pins), type_(t), width_(wid)
View
@@ -3750,6 +3750,8 @@ class NetETernary : public NetExpr {
* N -- Reduction NOR (~|)
* X -- Reduction NXOR (~^ or ^~)
* m -- abs(x) (i.e. "magnitude")
+ * i -- Cast from real to integer (vector)
+ * r -- Cast from integer (vector) to real
*/
class NetEUnary : public NetExpr {
@@ -3805,6 +3807,17 @@ class NetEUReduce : public NetEUnary {
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
* it. From this the expression can get any kind of access to the
View
@@ -494,3 +494,19 @@ const_bool const_logical(const NetExpr*expr)
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;
+}
View
@@ -1,7 +1,7 @@
#ifndef __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
* 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 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
View
@@ -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
* 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_) {
case '~':
case '-':
+ case 'r':
+ case 'i':
flag = expr_->set_width(w);
expr_width(w);
break;
Oops, something went wrong.

0 comments on commit 21d15ce

Please sign in to comment.