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

Reimplement static-timing pass. #909

Merged
merged 52 commits into from
Feb 22, 2022
Merged

Reimplement static-timing pass. #909

merged 52 commits into from
Feb 22, 2022

Conversation

mikeurbach
Copy link
Collaborator

Supersedes #908. Closes #654.

@mikeurbach
Copy link
Collaborator Author

Alright, here we go. Please see original discussion from #905.

Copy link
Contributor

@rachitnigam rachitnigam left a comment

Choose a reason for hiding this comment

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

Okay, housekeeping comments are done. I'm going to read through the final logic once and see if there is anything to change. Just to make sure I remember, I need to:

  • check while + @bound works as expected
  • seq transition logic can be simplified (question from the original PR)

@rachitnigam
Copy link
Contributor

seq transition logic can be simplified (question from the original PR)

I'm okay with the seq logic as it is. I think there needs to be some redundancy with that logic somewhere; tdcc does something similar with enables I think.

@mikeurbach
Copy link
Collaborator Author

@rachitnigam I think this should be good for review, the housekeeping items should be addressed. What's the best way to reduce duplication in the start_* methods? I tried to write a generic version that just called "calculate_states", but I'm not sure how to get the attributes out of a generic ir::Control.

@rachitnigam
Copy link
Contributor

You can use the GetAttributes trait which is implemented by Control nodes.

@mikeurbach
Copy link
Collaborator Author

Sorry for the noob question, but I am trying to write a generic function that takes a &mut ir::Control, and pass it a &mut ir::Seq, for example. How do you call such a function? It looks like:

fn start_generic(
    con: &mut ir::Control,
    comp: &mut ir::Component,
    sigs: &LibrarySignatures,
    dump_fsm: bool,
) -> VisResult {
...

And I want to say something like:

    fn start_seq(
	&mut self,
        con: &mut ir::Seq,
        comp: &mut ir::Component,
	sigs: &LibrarySignatures,
        _comps: &[ir::Component],
    ) -> VisResult {
        start_generic(con, comp, sigs, self.dump_fsm)
    }

This doesn't work, so I'm trying to "upcast" the &mut ir::Seq to a &mut ir::Control. I tried something like this, but that tries to move out of a mutable reference:

start_generic(&mut ir::Control::Seq(*con), comp, sigs, self.dump_fsm)

@rachitnigam
Copy link
Contributor

Hm, generally you’d have to do this by defining start generic on some shared trait implemented by all the control nodes but there isn’t such a thing. Additionally, since you’re going to dispatch on the input anyways, it might not be useful after all.

maybe it’ll help if you explain which boilerplate you’re trying to remove and I can try to explain a Rust-y way to do it.

@mikeurbach
Copy link
Collaborator Author

Well, all of the start_seq, start_par, etc. all have the same structure, but dispatch to the specific _calculate_states methods. I was thinking it would be good to write a single method with the same structure, which calls the generic calculate_states. start_seq and friends could just call the generic method with their specific control construct.

@rachitnigam
Copy link
Contributor

I see, I'd probably separate the checking logic into a function that takes something that implements GetAttributes:

fn check_static<C: GetAttributes>(con: C) -> bool {
  ...
}

I don't currently have an obvious way to take something like this and also dispatch it. One probable way is using dynamic trait objects (dyn impl) but that forces Rust to build a virtual table for the function which might be unnecessary in this case.

(3)->(4)
1'b1
(4)->(5)
1'b1
Copy link
Contributor

Choose a reason for hiding this comment

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

It occurs to me that there might be a simple optimization possible in the realize_schedule method to calculate consecutive "runs" of FSM states where we basically just want fsm.in = fsm.out + 1 and simplify the generated transitions a bit. Not super crucial but will probably start mattering when you look at resources.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Opened an issue for this enhancement so we don't lose it: #929.

Copy link
Contributor

@rachitnigam rachitnigam left a comment

Choose a reason for hiding this comment

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

LGTM! Thanks for bearing with the back and forth @mikeurbach and super awesome work on this. I've felt a comment on a simple FSM optimization that could be useful but I'll leave it to your judgement. Merge when you think this is ready and feel free to ask any more questions.

@mikeurbach
Copy link
Collaborator Author

I don't currently have an obvious way to take something like this and also dispatch it.

If you're fine with this level of duplication, so am I. The checking could be factored out, but it's not going to save much.

I've felt a comment on a simple FSM optimization that could be useful but I'll leave it to your judgement

I was thinking about this a bit as well. In a lot of cases I think we would be able to have the FSM state simply increment.

I'm inclined to leave this be for now, and consider this a starting point for more optimizations. This currently provides the behavior I'm looking for, so I'm happy if further resource reductions are added later, along with #911 and other such optimizations.

@mikeurbach
Copy link
Collaborator Author

Thanks for all the iterations on this @rachitnigam! Landing this now as a starting point, and we can tackle the further enhancements in smaller PRs now that the functionality is locked in.

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.

Reimplement static-timing pass
2 participants