Advertisement
AquaBlitz11

Recitation 9

Oct 11th, 2024
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // the solution
  2. module PipelinedAdd4;
  3.   input Vector#(4, Word) in;
  4.   RegU#(Vector#(2, Word)) pipeReg1;
  5.   RegU#(Word) pipeReg2;
  6.   method Word out = pipeReg2;
  7.  
  8.   rule tick;
  9.     Vector#(2, Word) newPipeReg1;
  10.     newPipeReg1[0] = in[0]+in[1];
  11.     newPipeReg2[1] = in[2]+in[3];
  12.     pipeReg1 <= newPipeReg1;
  13.  
  14.     Word newPipeReg2 = pipeReg1[0] + pipeReg1[1];
  15.     pipeReg2 <= newPipeReg2;
  16.   endrule
  17. endmodule
  18.  
  19. // note, this is different from vector of registers!
  20. module PipelinedAdd4;
  21.   input Vector#(4, Word) in;
  22.   Vector#(2, RegU#(Word)) pipeReg1;
  23.   RegU#(Word) pipeReg2;
  24.   method Word out = pipeReg2;
  25.  
  26.   rule tick;
  27.     pipeReg1[0] <= in[0]+in[1];
  28.     pipeReg1[1] <= in[2]+in[3];
  29.     pipeReg2 <= pipeReg1[0] + pipeReg1[1];
  30.   endrule
  31. endmodule
  32.  
  33. // or, we could just not separate the stages
  34. module PipelinedAdd4;
  35.   input Vector#(4, Word) in;
  36.   Vector#(3, RegU#(Word)) s;
  37.   method Word out = s[2];
  38.  
  39.   rule tick;
  40.     s[0] <= in[0]+in[1];
  41.     s[1] <= in[2]+in[3];
  42.     s[2] <= s[0]+s[1];
  43.   endrule
  44. endmodule
  45.  
  46. // or make register of vector
  47. module PipelinedAdd4;
  48.   input Vector#(4, Word) in;
  49.   RegU#(Vector#(3, Word)) s;
  50.   method Word out = s[2];
  51.  
  52.   rule tick;
  53.     Vector#(3, Word) sp;
  54.     sp[0] = in[0]+in[1];
  55.     sp[1] = in[2]+in[3];
  56.     sp[2] = s[0]+s[1]; // careful, must refer to s in this cycle not sp
  57.     s <= sp;
  58.   endrule
  59. endmodule
  60.  
  61. // ok, let's do by-stage solution with valid bit
  62. module PipelinedAdd4;
  63.   input Maybe#(Vector#(4, Word)) in default = Invalid;
  64.   RegU#(Maybe#(Vector#(2, Word))) pipeReg1; // Maybe#(RegU#(...)) doesn't make sense.
  65.   RegU#(Maybe#(Word)) pipeReg2;             // also, it's better to have Maybe#(Vector#(...)) than Vector#(Maybe#(...))
  66.   method Maybe#(Word) out = pipeReg2;
  67.  
  68.   rule tick;
  69.     if (isValid(in)) begin
  70.       Vector#(2, Word) newPipeReg1Data;
  71.       Vector#(4, Word) in_v = fromMaybe(?, in);
  72.       newPipeReg1Data[0] = in_v[0] + in_v[1];
  73.       newPipeReg1Data[1] = in_v[1] + in_v[2];
  74.       pipeReg1 <= Valid(newPipeReg1Data);
  75.     end else begin
  76.       pipeReg1 <= Invalid;
  77.     end
  78.  
  79.     if (isValid(pipeReg1)) begin
  80.       Vector#(2, Word) pipeReg1_v = fromMaybe(?, pipeReg1);
  81.       pipeReg2 <= Valid(pipeReg1_v[0]+pipeReg1_v[1]);
  82.     end else begin
  83.       pipeReg2 <= Invalid;
  84.     end
  85.   endrule
  86. endmodule
  87.  
  88. // alternatively, we can just focus on the data and valid bits separately
  89. // (not fully, since Minispec requires us to provide data with Valid at the same time.)
  90. module PipelinedAdd4;
  91.   input Maybe#(Vector#(4, Word)) in default = Invalid;
  92.   RegU#(Maybe#(Vector#(2, Word))) pipeReg1;
  93.   RegU#(Maybe#(Word)) pipeReg2;
  94.   method Maybe#(Word) out = pipeReg2;
  95.  
  96.   rule tick;
  97.     Vector#(2, Word) newPipeReg1Data;
  98.     Vector#(4, Word) in_v = fromMaybe(?, in);
  99.     newPipeReg1Data[0] = in_v[0] + in_v[1];
  100.     newPipeReg1Data[1] = in_v[1] + in_v[2];
  101.     pipeReg1 <= isValid(in) ? Valid(newPipeReg1Data) : Invalid;
  102.  
  103.     Vector#(2, Word) pipeReg1_v = fromMaybe(?, pipeReg1);
  104.     pipeReg2 <= isValid(pipeReg1) ? Valid(pipeReg1_v[0]+pipeReg1_v[1]) : Invalid;
  105.   endrule
  106. endmodule
  107.  
  108. // now with stall signal. we should think backward.
  109. module PipelinedAdd4;
  110.  
  111.   input Maybe#(Vector#(4, Word)) in default = Invalid;
  112.   input Bool outStall default = False; // NEW INPUT!!
  113.  
  114.   RegU#(Maybe#(Vector#(2, Word))) pipeReg1;
  115.   RegU#(Maybe#(Word)) pipeReg2;
  116.   method Maybe#(Word) out = pipeReg2;
  117.  
  118.   rule tick;
  119.     Bool stallpipeReg2 = outStall && isValid(stage[1]);
  120.     // 1. pipeReg2 full, outStall is true -> pipeReg2 data mustn't change.
  121.     // 2. pipeReg2 full, outStall is false -> pipeReg2 presents data, which is consumed,
  122.     //                                   so must take data from stage 0.
  123.     // 3. pipeReg2 empty, outStall is true -> pipeReg2 should take data from pipeReg1.
  124.     // 4. pipeReg2 empty, outStall is false -> pipeReg2 should take data from pipeReg1.
  125.  
  126.     // what if stallpipeReg2 = outStall; only?
  127.     // 1. pipeReg2 full, outStall is true -> pipeReg2 data mustn't change.
  128.     // 2. pipeReg2 full, outStall is false -> data is taken from stage 0. fine.
  129.     // 3. pipeReg2 empty, outStall is true -> we don't take data. loss of throughput, similar to global stall.
  130.     // 4. pipeReg2 empty, outStall is false -> data is taken from stage 0. fine.
  131.  
  132.     // what if stallpipeReg2 = isValid(stage[1]); only?
  133.     // 1. pipeReg2 full, outStall is true -> pipeReg2 data mustn't change. fine.
  134.     // 2. pipeReg2 full, outStall is false -> consumer already takes data, but we didn't invalidate this. bad.
  135.     //                                      fix: if full, must invalidate if outStall is false.
  136.     //                                           (careful, don't invalidate if outStall is true!)
  137.     // 3. pipeReg2 empty, outStall is true -> pipeReg2 takes data from stage 0. fine.
  138.     // 4. pipeReg2 empty, outStall is false -> pipeReg2 takes data from stage 0. fine.
  139.     if (!stallpipeReg2) begin
  140.       Vector#(2, Word) pipeReg1_v = fromMaybe(?, pipeReg1);
  141.       pipeReg2 <= isValid(pipeReg1) ? Valid(pipeReg1_v[0]+pipeReg1_v[1]) : Invalid;
  142.     end
  143.  
  144.     Bool stallpipeReg1 = stallpipeReg2 && isValid(stage[0]);
  145.     if (!stallpipeReg1) begin
  146.       Vector#(2, Word) newPipeReg1Data;
  147.       Vector#(4, Word) in_v = fromMaybe(?, in);
  148.       newPipeReg1Data[0] = in_v[0] + in_v[1];
  149.       newPipeReg1Data[1] = in_v[1] + in_v[2];
  150.       pipeReg1 <= isValid(in) ? Valid(newPipeReg1Data) : Invalid;
  151.     end
  152.  
  153.     // Bool stallInput = stallpipeReg1 && isValid(in);
  154.     // why && with isValid(in)? so, if producer doesn't have input yet, we encourage
  155.     // the producer to try to provide output as fast as possible.
  156.     // this really shouldn't matter, though, because one implicit rule is that
  157.     // producer should try to produce output on best-effort basis, regardless of the received stall signal.
  158.     // in fact, if valid depends on stall, we have a combinational loop!
  159.   endrule
  160.  
  161.   // problem: method should not access input, by convention:
  162.   // method Bool isFull = outStall && isValid(pipeReg1) && isValid(pipeReg2);
  163.  
  164.   // solution: we could do this, but ugly:
  165.   // method Bool isFull(Bool outStall) = outStall && isValid(pipeReg1) && isValid(pipeReg2);
  166.  
  167.   // or just rely on the producer to have access to consumer's stall signal
  168.   method Bool isFull = isValid(pipeReg1) && isValid(pipeReg2);
  169.   // what happens if the producer doesn't check the consumer's stall signal?
  170.  
  171. endmodule
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement