Consider a "hybrid" method.  Spawn threads for each type of event, and have 
each thread handle all consumers of the event.  The thread blocks on the event 
semaphore.  When the event occurs, it wakes up and walks the list of all 
registered event consumers.  The first thing a consumer must do is ensure that 
all necessary conditions for execution are met and exit if not.  This allows 
for a consumer to be registered with multiple event handlers but only execute 
if conditions are correct.  Note that an event handler to be registered with 
multiple event threads would require an internal mutex to prevent multiple 
calls to a particular handler from executing in parallel.  If you know you are 
going to have a huge number of consumers for a particular event, the most 
generic "clock-tick" event for example, then you can spawn multiple handler 
threads and balance the consumers across them appropriate.

In object oriented terms, you have an event handler class that runs in its own 
thread and blocks on semaphore passed in at object creation.  You have an event 
consumer base class that registers itself with one or more event handlers that 
are passed in at creation.  The various parts of the simulation derived from 
and extend this event consumer class, though any extension needs to be private 
or you make a mess of the object model.  You could potentially add type 
specific public members to the event consumer so long as they were only used 
for reading state or initial simulation setup and hence called outside the 
event framework.  When the event occurs and the event handler object wakes, it 
steps through its list of registered consumer objects and executes the 
"consume" method of each.

This would allow you to make event trees as well.  Take that ubiquitous 
"clock-tick" event.  It is effectively the top (or root depending on which way 
you want your tree to point) of the tree. Major function blocks of the 
simulation may be the consumers of the event.  Each consumer's event handler is 
responsible for updating another semaphore to which the next level of event 
handlers are synchronized.  A given event generator will block until all its 
registered event handlers have processed the event and everything gets kept in 
sync.  The event generator sets a count based on the number of registered 
handlers and blocks while this count is none zero.  Each handler executes all 
its consumers and decrements the count (locking as appropriate).   Slowly, each 
generator will unblock when all it's handlers are done and will then decrement 
the count of it's parent event generator as so the "done" state will percolate 
up the tree.  When it reaches the
 top, the entire sequences starts again.

This all requires you to well define the interfaces between your simulation 
blocks and you will almost certainly have to instantiate all the blocks and 
then register the interconnections between them with object/method pointers -- 
hence the need for well defined interfaces.  Effectively you are taking your 
Verilog modules and turning them into C++ objects that model the behavior at 
the interface level.

I'm sure there are all sorts of mistakes in the above as I kind of just typed 
it out while I was thinking.  It would be much easier to explain on a white 
board, but the basic foundation would not be terribly complex.  Making sure 
things behaved as expected, avoiding deadlocks, and making it fast on the other 
hand....

Patrick M


________________________________
 From: Timothy Normand Miller <[email protected]>
To: ogml <[email protected]> 
Sent: Monday, September 24, 2012 10:43 AM
Subject: [Open-graphics] Going nuts with threads for event management -- thread 
limits in Linux?
 
One of the reasons I had thought about using behavioral Verilog (i.e.
using Verilog as a scripting language) to implement the simulator is
that there's a built-in event management system.  We can easily do
things like send signals that cause parallel processes to happen,
perform actions based on global and local timers, and even pause what
appears to be sequential code, because it's waiting on some other
event.  The problems with doing it this way include (a) some
algorithms are unnecessarily more challenging to express in Verilog
than C++, and (b) being interpreted, the performance will be far too
low for a useful simulator.

One way to handle event processing would be to have a global event
queue, into which you can put objects and method pointers to be called
at an appropriate time. This is clean for some things (handing off an
operation to the next stage in a pipeline, which is implemented in a
totally different method), while it's nasty for others where the most
straightforward implementation is sequential code with pauses in it.

Another way to handle it would be to spawn threads that represent the
parallel systems and use IPC (e.g. cond_waits) to block on information
(i.e. waiting for a memory read to come back) or send signals (i.e.
making the request in the first place).  The problem here is that we
could end up with thousands of thread contexts, and I don't know what
the feasibility of this is.  It would be scalable to arbitrary numbers
of CPUs, but the IPC overhead itself could be significant.  Allowing
green threads in the mix would constitute a compromise.

The simulator should match up with the hardware, but only at a high
level.  The objectives are performance and accuracy, and we can get
both if we can choose different ways to implement an algorithm that
don't look like hardware, as long as the outputs (timing, energy,
etc.) are correct.

One example where I think we'd benefit from deviating from exactly
modeling the hardware is in pipeline segments that don't have external
communication.  If you have a 6-stage pipeline segment that does
nothing but compute, then it would be best to implement it as one
chunk of code that posts its results to appear 6 cycles in the future,
rather than having each stage get entered into the event system.

Suggestions welcome, please.

-- 
Timothy Normand Miller, PhD
http://www.cse.ohio-state.edu/~millerti
Open Graphics Project
_______________________________________________
Open-graphics mailing list
[email protected]
http://lists.duskglow.com/mailman/listinfo/open-graphics
List service provided by Duskglow Consulting, LLC (www.duskglow.com)
_______________________________________________
Open-graphics mailing list
[email protected]
http://lists.duskglow.com/mailman/listinfo/open-graphics
List service provided by Duskglow Consulting, LLC (www.duskglow.com)

Reply via email to