Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions src/rsz/src/Rebuffer2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -828,6 +828,11 @@ Delay Rebuffer::marginedSlackThreshold(Delay slack)
return slack - (ref_slack_ - slack) * 2e-6;
}

float lerp(float a, float b, float t)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use std::lerp

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I purposely open-coded it so we can see the formula and reason about the rounding errors (though I'm not fully sure compiler cannot rewrite it in optimization)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note the std version handles more corner cases but perhaps they don't arise here.

  template<typename _Fp>
    constexpr _Fp
    __lerp(_Fp __a, _Fp __b, _Fp __t) noexcept
    {
      if ((__a <= 0 && __b >= 0) || (__a >= 0 && __b <= 0))
	return __t * __b + (1 - __t) * __a;

      if (__t == 1)
	return __b;                        // exact

      // Exact at __t=0, monotonic except near __t=1,
      // bounded, determinate, and consistent:
      const _Fp __x = __a + __t * (__b - __a);
      return (__t > 1) == (__b > __a)
	? (__b < __x ? __x : __b)
	: (__b > __x ? __x : __b);  // monotonic near __t=1
    }

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting they have different cases. I assume that's just one way it may be implemented.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They handle overflow for one. The core formula is similar.

{
return a + (b - a) * t;
}

// Recover area on a rebuffering choice without regressing timing
BufferedNetPtr Rebuffer::recoverArea(const BufferedNetPtr& root,
Delay slack_target,
Expand Down Expand Up @@ -877,9 +882,8 @@ BufferedNetPtr Rebuffer::recoverArea(const BufferedNetPtr& root,
opts = recurse(inner, 0);
}

Delay threshold = marginedSlackThreshold(
(slack_target + node->arrivalDelay()) * alpha
+ node->slack() * (1.0 - alpha));
Delay threshold = marginedSlackThreshold(lerp(
node->slack(), slack_target + node->arrivalDelay(), alpha));
insertBufferOptions(opts,
level,
/*next_segment_wl=*/upstream_wl,
Expand All @@ -892,9 +896,8 @@ BufferedNetPtr Rebuffer::recoverArea(const BufferedNetPtr& root,
const BnetSeq& left_opts = recurse(node->ref(), upstream_wl);
const BnetSeq& right_opts = recurse(node->ref2(), upstream_wl);

Delay threshold = marginedSlackThreshold(
(slack_target + node->arrivalDelay()) * alpha
+ node->slack() * (1.0 - alpha));
Delay threshold = marginedSlackThreshold(lerp(
node->slack(), slack_target + node->arrivalDelay(), alpha));
BnetMetrics assured_envelope = node->metrics().withSlack(threshold);
BnetPtr assured_fallback;

Expand Down Expand Up @@ -1030,10 +1033,9 @@ void Rebuffer::annotateTiming(const BnetPtr& tree)
int ret = recurse(bnet->ref()) + recurse(bnet->ref2());
const BnetPtr& p = bnet->ref();
const BnetPtr& q = bnet->ref2();
const BnetPtr& min_req = fuzzyLess(p->slack(), q->slack()) ? p : q;
bnet->setSlackTransition(
combinedTransition(p->slackTransition(), q->slackTransition()));
bnet->setSlack(min_req->slack());
bnet->setSlack(std::min(p->slack(), q->slack()));
bnet->setCapacitance(p->cap() + q->cap());
return ret;
}
Expand Down