I'm currently creating a pipeline for my asm simulator. I'm to do this with multithreading. Currently I have four threads which correspond to each Fetch, Decode, Execute, and Write Back. I'm confused about how to code a correct pipeline. Here is some of my code:
private void Fetch()
{
while(_continue)
{
fetchEvent.WaitOne();
if (!_continue) break;
lock (irLock)
{
try
{
// Do stuff to fetch instruction...
catch (IndexOutOfRangeException e) { Err = "Segmentation Fault at Line " + _pc.ToString(); }
catch (Exception e) { Err = e.Message + "Line " + _pc.ToString(); }
_pc++;
GiveTurnTo(2); // used these 2 lines to handle mutual exclusion
WaitTurn(1);
}
}
}
private void Decode()
{
while (_continue)
{
decodeEvent.WaitOne();
if (!_continue) break;
lock (irLock)
{
WaitTurn(2);
Console.WriteLine("decode works");
GiveTurnTo(1);
}
}
}
private void Execute()
{
while (_continue)
{
exeEvent.WaitOne();
if (!_continue) break;
lock (irLock)
{
//WaitTurn(3);
Console.WriteLine("Am I, execute, getting a turn?");
// GiveTurnTo(4);
}
}
}
private void WriteBack()
{
while (_continue)
{
wbEvent.WaitOne();
if (!_continue) break;
lock (irLock)
{
Console.WriteLine("Am I, Write Back, getting a turn?");
//GiveTurnTo(1);
// WaitTurn(4);
}
}
}
}
I use this method to run a cycle with a button click:
public void nextInstruction()
{
fetchEvent.Set();
decodeEvent.Set();
exeEvent.Set();
wbEvent.Set();
}
I was thinking of changing nextInstruction() to this:
public void nextInstruction()
{
fetchEvent.Set();
}
Where each button click will always start with Fetch. After that I thought maybe I could place a set event within the Fetch method to call the next part in the cycle (Decode) and do the same for the following methods. I would end up with something like this:
private void Fetch()
{
while(_continue)
{
// Do stuff....
decodeEvent.Set();
}
}
private void Decode()
{
while (_continue)
{
// Do stuff...
exeEvent.Set();
}
}
private void Execute()
{
while (_continue)
{
// Do stuff...
wbEvent.Set();
}
}
private void WriteBack()
{
while (_continue)
{
// Do stuff...
}
}
Instead of leaving those set events out in the open, I think they should be activated by some sort of logic, but I don't know what kind of logic. Maybe they could be activated by a button click. That would allow me to control when an instruction is passed down the cycle. In theory, I think this could give me the structure of a pipeline. Can anyone provide any input on this? Can this be accomplished with just Auto Reset Events?
If you look at the first block of code I gave, you can see I tried using a lock, but that made it so only one thread could run at a time. I want to make it so that it follows the format of Fetch0, {Decode0, Fetch1}, {Execute0, Decode1, Fetch3},...
and so on. Are locks a necessity in this case?