Jump to content

Pipeline with Stalling Example


Dilan Manatunga

Recommended Posts

I've been trying to find a good example of a simple pipeline that includes pipeline stalls. The reason I am looking for this is that every simple pipeline example I have found typically represents each stage as SC_METHOD sensitive to clk.pos(). That system works well when we have a free-flowing pipeline, but I am wondering how a pipeline with stalls is modeled. In that case, whether Stage 1 should output is dependent on whether Stage 2 finished whatever operation it was performing (for example: multi-cycle arithmetic operation causing a stall).

The only idea I currently have on how to implement this is that instead of representing the stages as SC_METHODs that are sensitive to posedge, we have pipeline latches that are sensitive to posedge and take in signals of new_value and stall, while each pipeline stage is sensitive to the output of the previous pipeline latch. I haven't tried this out though, and I'm not sure if it is the right approach or if there is a better approach out there.

Link to comment
Share on other sites

I'm not aware of any example so I will no be able to answer your question.

But I do not see your problem. You would do it as it is done in hardware. Each stage is providing a ready signal indicating to the stage before that it can take inputs. And now the preceeding stage updates its outputs only if the ready signal of the next stage is active.

Link to comment
Share on other sites

I will include a code example when it is less late for me, but I guess my confusion with what you suggested is when the previous stage sees the ready signal value. Say we go on a slight modification of the pipe example, where there is a ready signal connected from each stage to the previous stage.  Now, if some stage decides it should stall, and indicates so by writing an sc_signal that the ready signal to the not ready state,  I though that the previous stage won't see that updated signal value till the next posedge event, when it really should be seeing it in the current posedge event. 

 

 

Link to comment
Share on other sites

Ok, my goal here was to create a 3 stage pipeline that essentially should stall infinitely when the number 2 reaches the third stage. It is again, a modification of the pipe example.

class Stage0 : sc_module {
 public:
  sc_in<bool> clk;
  sc_out<int> out;

  SC_CTOR(Stage0) {
    SC_METHOD(Tick);
    dont_initialize();
    sensitive << clk.pos();
  }

  void Tick() {
    static int i = 0;
    out.write(++i);
  } 
};
  
class Stage1 : sc_module {
 public:
  sc_in<bool> clk;
  sc_in<int> in; 
  sc_in<bool> stall;
  sc_out<int> out;
  
  SC_CTOR(Stage1) { 
    SC_METHOD(Tick);
    dont_initialize(); 
    sensitive << clk.pos();
  }
  
  void Tick() { 
    if (!stall.read()) {
      out.write(in.read());
    }
  }
};
  
class Stage2 : sc_module {
 public:
  sc_in<bool> clk;
  sc_in<int> in;
  sc_out<bool> stall;
  sc_out<int> out;
  
  SC_CTOR(Stage2) {
    SC_METHOD(Tick);
    dont_initialize();
    sensitive << clk.pos();
  }
  
  void Tick() {
    stall.write(false);
    out.write(in.read());
    if (in.read() == 2) {
      stall.write(true);
    }
  }
};

And this was my test suite:

int sc_main(int, char *[])
{
  
  //Signals
  sc_signal<int> in1;
  sc_signal<int> in2;
  sc_signal<int> out2;
  sc_signal<bool> stall;
  
  //Clock
  sc_signal<bool>   clk;
    
  sc_trace_file *vcd = sc_create_vcd_trace_file("pipe");
  sc_trace(vcd, clk, "clk");
  sc_trace(vcd, in1, "in1");
  sc_trace(vcd, in2, "in2");
  sc_trace(vcd, out2, "out2");
  sc_trace(vcd, stall, "stall");
      
  Stage0 S0("stage0");
  S0.clk(clk);
  S0.out(in1);
  
  Stage1 S1("stage1");
  S1.clk(clk);
  S1.in(in1); 
  S1.stall(stall);
  S1.out(in2); 
  
  Stage2 S2("stage2");
  S2.clk(clk);
  S2.in(in2);
  S2.stall(stall);
  S2.out(out2);
  
  sc_start(0, SC_NS);               //Initialize simulation
  for(int i = 0; i < 50; i++){
      clk.write(1);
      sc_start( 0.5, SC_NS );
      clk.write(0);
      sc_start( 0.5, SC_NS );
  } 
  
  return 0;
}

So I attached the waveform below.

vcd_picture.thumb.png.b96a3d02125c4fb3ac86a3754d7cd72a.png

What I would want, is that from t=2ns, the in2 latch should essentially be stuck at 2.

From my current implementation, the in2 latch stalls at 3 for a couple cycles, before continuing on. This matches my understanding, because the stage S1 will not see the updated stall signal from stage S2 until the next positive edge at t=4ns, at which point it would have written the value 3. 

Again, this is why I am unsure of what is the best way to implement a pipeline that supports stalling using SystemC.

 

Link to comment
Share on other sites

Well, if Stage1 should hold the value of 2 until Stage2 is able to process it then Stage2 need to tell Stage1 that is busy with the value before. In your example Stage2 read (consumed) already the value 2 so that Stage1 can provide the next value (3).

This is what you see in the simulation: Stage2 tells Stage1 that it is busy processing the value of 2 so Stage 1 holds the next value (3) until Stage2 is ready. Actually the implementation and behavior is correct.

Link to comment
Share on other sites

Sorry if there is a loss of clarity in what I said, so let me try explaining some stuff again.

From searching around the web, almost every example of a pipeline I have seen, as well as the one included in the SystemC examples, uses this on positive edge sensitivity for the SC_METHOD that represents a given stage.

Now, this might be a misconception on my part, but in these pipelines, I view the connecting sc_signals between stages as representing pipeline latches. So, when I think of stalling, I would expect the sc_signal to retain its old value if the stage that reads that value decides to stall. Something similar to picture below.

2010495640_Screenshot2020-08-31at12_31.17PM-Display2.png.b71711078cbcec445d5c46f19905763e.png

I understand the issues of why a back-propagation signal (in the way I implemented it) does not work when SC_METHOD is sensitive to the positive edge. To put into my own words, the sc_signals now are more akin to a 1-entry queue, where once a stage has read that value, it is the stage's responsibility to keep that internal value if it plans to stall. 

And I have ideas how I could implement something similar to the picture. The thing is my current ideas involve many more modules (a module for each stage, and a module for each latch), with different sensitives (latches sensitive to positive clock, stage sensitive to latch output). I was more just wondering if there were better, more recommended ways for this approach that might hew closer to the non-stalling pipeline examples.

 

 

Link to comment
Share on other sites

  • 2 weeks later...

A SC_METHOD being sensitive to a positive edge of a clock is not a latch rather a register. It is the same than in (System)Verilog or VHDL.

Moreover a sc_signal is not a queue at all. Writes in the same delta cylce superseed earlier writes in the same delta cycle. A signal in SystemC is similar to a wire or reg in Verilog or a signal in VHDL. Maybe you should revisit your understanding of RTL description and its logics.

There are many ways how to implement things. You may write a lot of different modules what brings a lot of overhead. Usually you implement a pipeline as a set of processes (SC_METHODS or even SC_THREADS) communicating via sc_signals or sc_fifos.

Link to comment
Share on other sites

I'm sorry in my last post as I made some terminology assumptions that were unclear.

I said pipeline latch from the computer architecture perspective, which is essentially synonymous with a register, as opposed to maybe an SR-latch.

My calling an sc_signal as a 1-entry queue was also bad and unnecessarily confusing. I was just trying to illustrate that a consumer stage cannot count on the signal value remaining the same at the next cycle in the case where the consuming stage stalls. That is why I said sc_signal acts like a 1-entry queue, because at every positive edge when a consuming stage reads the sc_signal, that value is lost as the proceeding edge will always end up writing a new value. Again, calling this a queue was needlessly complicating on my part and I could have picked a better description.

I feel I am re-iterating myself, but again my whole issue has been, and as you mentioned, the traditional method of doing pipelines is a set of processes (SC_METHOD/SC_THREAD) communicating via sc_signals. Yet going off that basis, I have not found an example, nor have I been able to construct a mechanism (with just standard SystemC components), that implement pipeline stalling, where the intermediate pipeline latches/registers are done similar to the circuit diagram in my previous comment.

 

 

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...