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

A few more FuTIL questions. #214

Closed
cgyurgyik opened this issue Sep 24, 2020 · 4 comments
Closed

A few more FuTIL questions. #214

cgyurgyik opened this issue Sep 24, 2020 · 4 comments
Labels
Priority: Low Don't do these during a deadline

Comments

@cgyurgyik
Copy link
Collaborator

cgyurgyik commented Sep 24, 2020

I'm still in the process of figuring out the process of Dahlia -> FuTIL -> verilog, so any help that in regard is great.
Edit: ^ fud is the answer to this from Slack chat.

I had a few more questions on top of that.

  1. Let's say I have a group inner_multiplies.
    I want to do the following:
 group inner_multiplies {
      mult.left = reg1.out;
      mult.right = reg5.out;
      reg_inner1.in = mult.out;
      mult.left = reg2.out;
      mult.right = reg6.out;
      reg_inner2.in = mult.out;
      mult.left = reg3.out;
      mult.right = reg7.out;
      reg_inner3.in = mult.out;
      mult.left = reg4.out;
      mult.right = reg8.out;
      reg_inner4.in = mult.out;
      inner_multiplies[done] = reg_inner4.done;        // & reg_inner3.done & reg_inner2.done & reg_inner1.done
    }

How come I can't take the & of these done cases? Unnecessary perhaps, i.e. is it guaranteed that within a group, reg_inner1 will be completed before reg_inner2, and so on?

  1. Given a function component X(a: 32, b:32) -> (res: 32) How can I put in some dummy values to actually test the result? I believe I just make a new component main() -> () { ... } and add some values for a, b, but how do I see the value of res?

  2. In fib.expect, I see:

group cond0<"static"=0> {
      cond0[done] = 1'd1;
      lt0.left = i_0.out;
      lt0.right = const3.out;
    }

3a. What is <"static"=0> ?
3b. You set cond0[done] to 1 immediately. Why is this? Won't this mean that the rest may not necessarily compute, or is this not the case? If it is not the case, why would one put it in the beginning rather than the end of the group?

@cgyurgyik cgyurgyik added the Priority: Low Don't do these during a deadline label Sep 24, 2020
@rachitnigam
Copy link
Contributor

  1. The error message when you try to do this might be misleading. You can write:
inner_multiplies[done] = reg_inner4.done & reg_inner3.done & reg_inner2.done & reg_inner1.done ? 1'd1;

The inner_multiplies[done] hole requires a one-bit signal. It can come from anywhere!

  1. This is the classic problem of testing "hierarchical hardware designs" where you want to observe the state of the inner modules somehow. I would try doing something like:
cells { 
   x = X; // instantiate the X component
}
wires {
  group test_X {
    x.a = 32'd1;
    x.b = 32'd2;
  }
}
control {
  test_X;
}

When you run this program through a simulator, you will notice that the simulation trace contains a signal .TOP.main.x.res which will have the values on that wire. Try getting the json trace first and seeing if you can find the signal. If not, we'll debug on slack.

3a. "static"=0 is an optimization attribute. There is compiler pass called static-timing that compiles groups in a special way when we know the exact number of cycles they run for.

3b. This is a so-called combinational group---a group that immediately compute the results. Their semantics is not yet precise. See the discussion in #207.

@cgyurgyik
Copy link
Collaborator Author

Thanks Rachit. A few follow-ups & new questions below.

Follow-up for 3a, Is there a 1:1, i.e. "static"=0 is 0 cycles? Also, out of curiosity, how do we know how many cycles an instruction takes? Isn't this dependent on specific hardware?

New Q1: about dot.data:
I haven't been able to compile and simulate this yet given issues on my end, but figured it has an easy answer anyways. I'm curious why dot has the value 97 here. Everything else makes sense. But why does the function name have value 97?

New Q2: Can you tell me where write_en is defined, its semantics, and how it differs from write_data (as well as its semantics)? Is this part of the primitive stdlib, or some verilog thing? I see it being used there, but not an actual definition.

@rachitnigam
Copy link
Contributor

Follow-up for 3a, Is there a 1:1, i.e. "static"=0 is 0 cycles?

Indeed! While FuTIL programs can specify those and we compile them but the semantics are not quite clear. This is also what the discussion about #207 is trying to get at.

Also, out of curiosity, how do we know how many cycles an instruction takes? Isn't this dependent on specific hardware?

Ah, this is true when you're working with CPUs. But with FuTIL, you're the one who's building that specific hardware so you get to decide who many cycles things take! For example, registers (memories) in hardware take one cycle to propagate their state from input to output which is the key way to add more cycles to an operation. For example, you add four registers in a multiplier's logic and now it takes 4 cycles!

I haven't been able to compile and simulate this yet given issues on my end, but figured it has an easy answer anyways. I'm curious why dot has the value 97 here. Everything else makes sense. But why does the function name have value 97?

The dot variable actually refers to this local variable: https://github.com/cucapra/futil/blob/fud/benchmarks/dot-product.fuse#L5

Dahlia compiles to FuTIL by "hoisting" all local variables to the top and turning them into a register. The data is providing a value of that. When we clean up our interfaces a bit more, you shouldn't see that variable.

Can you tell me where write_en is defined, its semantics, and how it differs from write_data (as well as its semantics)? Is this part of the primitive stdlib, or some verilog thing? I see it being used there, but not an actual definition.

write_en and write_data have the same semantics (but different names). With memories, your input signal can always have a value on it. You need some way to tell the register that the input signal is something that it needs to store. The write_en (or "write enable") signal is what tells registers that they need to write the value on their input. If the signal is not set, the register just ignores its input.

@rachitnigam
Copy link
Contributor

@cgyurgyik if the answers make sense, please close the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Priority: Low Don't do these during a deadline
Projects
None yet
Development

No branches or pull requests

2 participants