Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Optimize counter bitwidth in Foreach control #293

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

kumasento
Copy link
Contributor

@kumasento kumasento commented Feb 2, 2020

Introduction

This PR aims to improve the bitwidth synthesized for counters in Foreach. Counters are all initialized to I32 at the moment, which is not optimal since for many cases there can be a much tighter bitwidth bound, and therefore, much resource can be saved and timing can be improved. This idea has been mentioned by @mattfel1 in #288 .

An motivating example that this type of optimization can be adopted:

Foreach(N by 1) { i => F(i) }

Here, suppose N is a constant or its boundary is statically known, we can then calculate the minimum bitwidth required for the counter that counts from 0 to N-1, simply by floor(log2(N)) + 1.

Implementation

To implement this optimization, I'm thinking of adding a new Transformer pass during compilation, CounterBitwidthTransformer, which iterates the program, finds all the OpForeach, and replaces their CounterNew with a new instance that has reduced bitwidth.

There are some questions though, mostly due to my insufficient knowledge on Spatial internals:

  1. Is there any other transform that may replace CounterNew without inheriting its data type, i.e., replace our updated CounterNew[T] by CounterNew[I32], where T is the optimized data type?
  2. Is CounterNew the only counter we should take care of?
  3. Is there any function can be reused that maps bitwidth to CounterNew[T] with specified T?

Test plan

There is a new app (will be deleted later) TestCounterBitwidth that simply iterates a SRAM and updates its content using Foreach. If we can notice the CounterNew can be updated to one that has shorter bitwidth, and its generated hardware uses less resource, we may assume that this optimization pass is helpful.

I can also implement unit tests later once I figure out how to do that.

Schedule

The initial version of this work will come out in the next two weeks, and we can finalize other details and make improvements in the following weeks.

val bitwidth = math.max(getBitwidth(begin), getBitwidth(end))

// TODO: Find a better way that can map bitwidth to the exact Fix type
if (bitwidth <= 7) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mattfel1 Hi there, I feel that it would be tedious to implement all the bitwidth-to-type cast and there should be a better way that I'm not aware of. Maybe you've met this scenario before and have a good way to deal with it? Thanks!

Copy link
Member

Choose a reason for hiding this comment

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

Unfortunately, I don't think there is a non-tedious way to do this.
Since each bitwidth is its own trait (argon/lang/types/CustomBitWidths.scala), its painful to work with. Some people have used quasiquotes for this problem before but there isn't a nice way that I know of.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks @mattfel1 ! In my latest update I manually added all the mappings for different bit-width values. Hope it looks fine.

@kumasento kumasento changed the title Optimize counter bitwidth in Foreach control WIP: Optimize counter bitwidth in Foreach control Feb 4, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants