Re: [vhdl-200x] Parallel execution of procedures within sequentiel statements

From: Jerry Kaczynski <jarekk@aldec.com>
Date: Wed Feb 15 2012 - 16:25:01 PST

Hi Martin,

As Jim mentioned earlier, you must use separate processes to have something
similar to 'fork..join' in VHDL and it is your responsibility to provide
synchronization mechanism.
I have dug out pure abstract example of fork..join_all/join_any emulation
in VHDL using custom resolved types that I have created for a newsletter a
few years ago.
Read code comments, compile and run in a simulator that lets you monitor
signal values in delta cycles - it should be clear then.
The code is by no means the only one and the best solution to the problem
you presented - it is just an educational device.

Good luck,

Jerry Kaczynski
ALDEC Research Engineer

----- code starts here -----
package Forking is
-- data type describing states of forking processes
type prc_state is (stop, run, start);
-- vectorized 'prc_state'; required by resolution functions
type prc_state_array is array(natural range<>) of prc_state;
-- resolution function for modeling 'fork-join_all'
function resolve_all(a : prc_state_array) return prc_state;
-- resolved subtype of 'prc_state' for modeling 'fork-join_all'
subtype prc_join_all is resolve_all prc_state;
-- resolution function for modeling 'fork-join_any'
function resolve_any(a : prc_state_array) return prc_state;
-- resolved subtype of 'prc_state' for modeling 'fork-join_any'
subtype prc_join_any is resolve_any prc_state;
-- procedure for initializing fork; must be used by all
-- threads, even the parent; data type of the argument
-- decides if 'join_all' or 'join_any' will be used
procedure fork(signal s: inout prc_state);
-- procedure joining all threads; must be called
-- at the end of each thread
procedure join_all(signal s: inout prc_join_all);
-- procedure joining child threads of 'fork-join_any';
-- should not be called in parent thread!
procedure join_any(signal s: inout prc_join_any);
-- procedure waiting for any forked thread to complete;
-- should be called ONLY in parent thread
procedure wait_for_any(signal s: inout prc_join_any);
end package Forking;

package body Forking is
function resolve_all(a : prc_state_array) return prc_state is
  variable isStart, isStop : Boolean := True;
begin
for i in a'range loop
if a(i)/=start then
isStart := False;
end if;
if a(i)/=stop then
isStop := False;
end if;
end loop;
if isStart then
return start;
elsif isStop then
return stop;
else
return run;
end if;
end function resolve_all;
 function resolve_any(a : prc_state_array) return prc_state is
  variable isStart, isRun : Boolean := True;
begin
for i in a'range loop
if a(i)/=start then
isStart := False;
end if;
if a(i)/=run then
isRun := False;
end if;
end loop;
if isStart then
return start;
elsif isRun then
return run;
else
return stop;
end if;
end function resolve_any;
 procedure fork(signal s: inout prc_state) is
begin
s <= start;
wait until s=start;
s <= run;
end;
 procedure join_all(signal s: inout prc_join_all) is
begin
s <= stop;
wait until s=stop;
end;
 procedure join_any(signal s: inout prc_join_any) is
begin
s <= stop;
wait until s=stop;
end;
 procedure wait_for_any(signal s: inout prc_join_any) is
begin
wait until s=stop;
end;
end package body Forking;

use work.forking.all;

entity Paternal is
end Paternal;

architecture Behavior of Paternal is
  signal ctrl1 : prc_join_all;
  signal ctrl2 : prc_join_any;
begin
father: process
begin
wait for 10 ns;
report "Father says: We should be forking right after this..." severity
warning;
-- 'father' spawns three child processes here and continues
-- to run itself till all 'join_all' procedures complete
fork(ctrl1);
report "They are working...";
-- time to wait for all child processes to complete
join_all(ctrl1);
report "Now joined after all that forking!";
wait for 10 ns;
report "Father says: Let's begin the race..." severity warning;
-- now 'father' spawns two child processes using signal
-- 'ctrl2' of 'prc_join_any' type; the first child process
-- to execute 'join_any' procedure will pass control back
-- to the statement right after 'wait_for_any'
fork(ctrl2);
wait_for_any(ctrl2);
report "Now I know which horse is the fastest!";
wait;
end process father;
 -- 'son1','son2' and 'son3' processes are forked using 'ctrl1' signal
-- of 'prc_join_all' type, which means that the last to complete
-- execution will return control to the parent process
son1: process
begin
fork(ctrl1);
report "Son1 at work!";
wait for 10 ns;
report "Son1 done!!!";
join_all(ctrl1);
wait;
end process son1;
 son2: process
begin
fork(ctrl1);
report "Son2 at work!";
wait for 20 ns;
report "Son2 done!!!";
join_all(ctrl1);
wait;
end process son2;
 son3: process
begin
fork(ctrl1);
report "Son3 at work!";
wait for 30 ns;
report "Son3 done!!!";
join_all(ctrl1);
wait;
end process son3;

-- 'horse1' and 'horse2' processes are forked using 'ctrl2' signal
-- of 'prc_join_any' type, which means that the first to complete
-- execution will return control to the parent process
horse1: process
begin
fork(ctrl2);
report "Horse1 running!";
wait for 15 ns;
report "Horse1 arrived!!!";
join_any(ctrl2);
wait;
end process horse1;
 horse2: process
begin
fork(ctrl2);
report "Horse2 running!";
wait for 12 ns;
report "Horse2 arrived!!!";
join_any(ctrl2);
wait;
end process horse2;
end Behavior;
----- code ends here -----

On Wed, Feb 15, 2012 at 3:19 AM, Stolpe Martin <Martin.Stolpe@newtec.de>wrote:

> Hello,
>
> I hope this is the right place to ask this question:
> Is it possible to execute procedures in process in parallel? What I have
> in mind would be something like this:
>
> ....
> procedure my_proc
> (signal din : in std_logic_vector;
> signal dout : out std_logic) is
> begin
> -- procedure statements
> ...
> wait for 8 ns;
> ...
> end my_proc;
>
> signal sig1, sig2: std_logic_vector (31 downto 0);
> signal data1, data2: std_logic;
>
> begin
> ...
> simulation_proc: process
> begin
> ...
> -- the following two processes should be started in parallel
> -- begin parallel (
> my_proc(sig1, data1);
> my_proc(sig2, data2);
> -- )
> -- end parallel;
> -- end parallel block
> wait;
> end process simulation;
> ...
>
> The idea behind this is that I want to start the processes like threads in
> other programming languages. If I write the code like this in a process at
> first "my_proc(sig1, data1);" would be started, then the simulator would
> wait 8 ns in that procedure and after that time the procedure
> "my_proc(sig2, data2);" would be started, where the simulator would wait
> for another 8 ns;
>
>
> Best regards
> Martin Stolpe
>
> i.A. Martin Stolpe
> Systemingenieur
> R&D Smart Embedded Systems (SW)
>
> NewTec GmbH
> System-Entwicklung und Beratung
> Heinrich-von-Stephan-Str. 8B
> D-79100 Freiburg
>
> Telefon : +49 (0) 761 21117-40
> Telefax : +49 (0) 761 21117-41
> email : martin.stolpe@newtec.de
> web : http://www.newtec.de
>
>
> ----------------------------------------------------------------------------------------------------------
> Geschäftsführer: Johannes Werbach, Harald Molle, Ulrich Schwer, Michael
> Tröscher
> Registergericht: Memmingen - HRB 7236 USt.-IdNr. DE130850199
>
> ----------------------------------------------------------------------------------------------------------
>
>
>
> --
> This message has been scanned for viruses and
> dangerous content by MailScanner, and is
> believed to be clean.
>
>
>

-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
Received on Wed Feb 15 16:25:40 2012

This archive was generated by hypermail 2.1.8 : Wed Feb 15 2012 - 16:26:16 PST