Issues in Ada Concurrency - concurrency

I need some help and also some insight. This is a program in Ada-2005 which has 3 tasks. The output is 'z'. If the 3 tasks do not happen in the order of their placement in the program then output can vary from z = 2, z = 1 to z = 0 ( That is easy to see in the program, mutual exclusion is attempted to make sure output is z = 2).
WITH Ada.Text_IO; USE Ada.Text_IO;
WITH Ada.Integer_Text_IO; USE Ada.Integer_Text_IO;
WITH System; USE System;
procedure xyz is
x : Integer := 0;
y : Integer := 0;
z : Integer := 0;
task task1 is
pragma Priority(System.Default_Priority + 3);
end task1;
task task2 is
pragma Priority(System.Default_Priority + 2);
end task2;
task task3 is
pragma Priority(System.Default_Priority + 1);
end task3;
task body task1 is
begin
x := x + 1;
end task1;
task body task2 is
begin
y := x + y;
end task2;
task body task3 is
begin
z := x + y + z;
end task3;
begin
Put(" z = ");
Put(z);
end xyz;
I first tried this program
(a) without pragmas, the result : In 100 tries, occurence of 2: 86, occurence of 1: 10, occurence of 0: 4.
Then
(b) with pragmas, the result : In 100 tries, occurence of 2: 84, occurence of 1 : 14, occurence of 0: 2.
Which is unexpected as the 2 results are nearly identical. Which means pragmas or no pragmas the output has same behavior.
Those who are Ada concurrency Gurus please shed some light on this topic. Alternative solutions with semaphores (if possible) is also invited.
Further in my opinion for a critical process (that is what we do with Ada), with pragmas the result should be z = 2, 100% at all times, hence or otherwise this program should be termed as 85% critical !!!! (That should not be so with Ada)

A protected object to do the three operations might look something like this. But note, all this does is make sure that the three variables x, y and z are consistent with the order that the updates occurred in; it says nothing about the order.
protected P is
procedure Update_X;
procedure Update_Y;
procedure Update_Z;
function Get_Z return Integer;
private
X : Integer := 0;
Y : Integer := 0;
Z : Integer := 0;
end P;
protected body P is
procedure Update_X is
begin
X := X + 1;
end Update_X;
procedure Update_Y is
begin
Y := Y + X;
end Update_Y;
procedure Update_Z is
begin
Z := X + Y + Z;
end Update_Z;
function Get_Z return Integer is
begin
return Z;
end Get_Z;
end P;
On the other hand, to make sure that the three tasks "submit their results" in the proper order, you could rewrite P so that a call to say Update_Y will block until Update_X has been called: Get_Z now has to be an entry with an out parameter rather than a function.
protected P is
entry Update_X;
entry Update_Y;
entry Update_Z;
entry Get_Z (Result : out Integer);
private
X_Updated : Boolean := False;
Y_Updated : Boolean := False;
Z_Updated : Boolean := False;
X : Integer := 0;
Y : Integer := 0;
Z : Integer := 0;
end P;
protected body P is
entry Update_X when True is
begin
X := X + 1;
X_Updated := True;
end Update_X;
entry Update_Y when X_Updated is
begin
Y := Y + X;
Y_Updated := True;
end Update_Y;
entry Update_Z when Y_Updated is
begin
Z := X + Y + Z;
Z_Updated := True;
end Update_Z;
entry Get_Z (Result : out Integer) when Z_Updated is
begin
Result := Z;
end Get_Z;
end P;
The three tasks can now have any priority you like. But the task that calls Update_Z will block until the other two have reported.

Well, those pragmas just prioritize the tasks on your system, they don't guarantee any kind of mutual-exclusion on those variables.
There may be some systems where that is enough. However, most Ada implementations these days map Ada tasks to OS threads, and most consumer PC's these days have multiple processors and can spilt their threads among them. There's nothing stopping the OS from scheduling the next lower-priority thread on your second processor while the highest priority thread is running.
This kind of behavior in a program is called a "race condition".
If you want mutual-exlusion on those variables, you need to implement that. Either give control of the variables to one task and use rendezvous to modify them from other tasks, or look into putting them into protected objects. I'd suggest the latter, as rendezvous can be much more difficult to get right. However, if you want to order the calls in a specific way, a master controller task calling rendezvous on the other tasks might be the way to go.

here is a program that is a sequential variant of the above ! .... with just one task (even that can be avoided if I use a single procedure, as suggested by Marc C and T.E.D )
WITH Ada.Text_IO; USE Ada.Text_IO;
WITH Ada.Integer_Text_IO; USE
Ada.Integer_Text_IO;
WITH System; USE System;
procedure xyzsimple is
x : Integer := 0;
y : Integer := 0;
z : Integer := 0;
task type xyz;
T: xyz;
task body xyz is
begin
x:= x + 1;
y:= x + y;
z:= x + y + z;
end xyz;
begin Put(" z = ");
Put(z);
end xyzsimple;
This program always gvies output z = 2, but then it doesn't serve to illustrate what I was trying to do. This program is deterministic, not into the paradigm of concurrency ! Further, this program will never exhibit 'RACE CONDITION' that T.E.D had mentioned.

Related

SystemVerilog, if-statements order inside an always_comb block

I am new to SystemVerilog and I would like to know how multiple assignments to the same signal are handled inside an always_comb block.
I am analyzing an FSM written by someonelse and I don't understand which would be the next state (signal named "ctrl_fsm_ns") if all the if-statements are true. Searching on google, I found out that here blocking assignments are used, so I expect that the last if-statement will decide the next state (so it is like a certain priority is assigned to each if-statement). But what if inside each if-block different signals are asserted? They will be all asserted even if the next state will be the last one, for example?
Here is the piece of code I don't understand.
always_comb
begin
...
unique case (ctrl_fsm_cs)
...
FIRST_FETCH:
begin
is_decoding_o = 1'b0;
// Stall because of IF miss
if ((id_ready_i == 1'b1) )
begin
ctrl_fsm_ns = DECODE;
end
// handle interrupts
if (irq_req_ctrl_i & irq_enable_int) begin
// This assumes that the pipeline is always flushed before
// going to sleep.
ctrl_fsm_ns = IRQ_TAKEN_IF;
halt_if_o = 1'b1;
halt_id_o = 1'b1;
end
if ((debug_req_pending || trigger_match_i) & (~debug_mode_q))
begin
ctrl_fsm_ns = DBG_TAKEN_IF;
halt_if_o = 1'b1;
halt_id_o = 1'b1;
end
end
Your question to the code above is a general programming question and not Verilog-specific. Because there are only blocking assignments in use, the code is entirely procedural.
Since the code isn't using an "if-else-if" sequence, but just "if-if-if", all the "if" conditions will be evaluated IN ORDER, and all assignments will happen IN ORDER, thus the final assignment will win out (as Dave said).
In your comments above you asked about what if (A_expr,B_expr,C_expr) where all true? Then (A,B,C) will all be set to 1.
A_expr=1; B_expr=1; C_expr=1;
if (A_expr) A = 1;
if (B_expr) B = 1;
if (C_expr) C = 1;
For each variable in the always_comb block, the last assignment is the final value. The tool analyzes the procedural flow to make sure every variable that is being assigned has at least one assignment in every possible flow through the code. If there is any possibility that a variable could be read without being written to, that is considered latch behavior and would be illegal for an always_comb block.
You need to look at the code before or after the case statement to see if there are any other assignments to the halt_ variables.
An example based on your comments:
always_comb begin
A = 0; B = 1; C = 2;
if (I) A = X;
if (J) B = Y;
if (K) begin B = Z; C = Z; end
end
That is equivalent to these three continuous assignments:
assign A = I ? X : 0;
assign B = K ? Z : (J ? Y : 1 );
assign C = K ? Z : 2;
Each if statement becomes a multiplexor, and the latter statements have the higher priority.

Is there any short-way to find first '1' bit?

I want to show ,the mentioned problem on the title, to you in a function.
finding_first_one(signal a : std_logic_vector(...)) { return bit_number }
Meaning this, lets say, we have a signal '10010100', then return value, bit_number, should be 2. Is there any short way to find it in one cycle. I do not want to scan all the bits per clock.
You can do a for loop in your function.
Be aware that for loop cannot always be implemented on hardware and that it can use A LOT of logic elements.
Try something like this (not tested). index should be equal to 2 in one clock cycle.
architecture behav of test is
signal sig : std_logic_vector(15 downto 0) := x"2224";
signal index : integer;
function finding_first_one (signal a : std_logic_vector()) return integer is
begin
for i in a'low to a'high loop
if a(i) = '1' then
return i;
end if;
end loop;
-- all zero
return -1;
end function;
begin
process (CLK)
begin
if rising_edge(clk) then
index <= finding_first_one(sig);
end if;
end process;
end architecture;

Reading from multiple channels simultaneously in Golang

I am new to Golang. Right now I am trying to figure out how to make an any-to-one channel in Golang, where the setup is as follows:
say I have two goroutines numgen1 and numgen2 executing concurrently and writing numbers to channels num1 resp. num2. I would like to add the numbers sent from numgen1 and numgen2 in a new process, addnum. I have tried something like this:
func addnum(num1, num2, sum chan int) {
done := make(chan bool)
go func() {
n1 := <- num1
done <- true
}()
n2 := <- num2
<- done
sum <- n1 + n2
}
but this seems sadly incorrect. Could someone please give me some ideas?
Thank you very much for your help.
Depending on your requirements, you may need to read both of the channels for every iteration (i.e. a sort-of 'zip' function). You can do this with a select, similarly to user860302's answer:
func main() {
c1 := make(chan int)
c2 := make(chan int)
out := make(chan int)
go func(in1, in2 <-chan int, out chan<- int) {
for {
sum := 0
select {
case sum = <-in1:
sum += <-in2
case sum = <-in2:
sum += <-in1
}
out <- sum
}
}(c1, c2, out)
}
This runs forever. My preferred way to terminate goroutines like this one is to close the input channels. In this case you would need to wait for both to close, then close(out) before terminating.
Tip: note the use of directional channels as goroutine formal parameters. The compiler catches more mistakes when you write it this way. Happiness!
The simplest answer would be
func addnum(num1, num2, sum chan int) {
n1 := <- num1
n2 := <- num2
sum <- n1 + n2
}
Since you need both num1 and num2 to do the calculation, it makes no sense to do it otherwise. After all, there are two possible execution orders:
num1 generates a number, followed by num2
num2 generates a number, followed by num1
In the first case, our channel reads correspond exactly to the execution order. In the second case, our first read will block until num1 has finally produced a number; the second read will complete near-instantaneous because the num2 channel already has a number.
If you want to know more about channels in Go, I'd suggest to have a look at http://godoc.org/github.com/thomas11/csp -- this is a collection of Hoare's CSP examples written in Go.
To answer the question "Reading from multiple channels simultaneously"
There is a way to listen to multiple channels simultaneously :
func main() {
c1 := make(chan string)
c2 := make(chan string)
...
go func() {
for {
select {
case msg1 := <- c1:
fmt.Println(msg1)
case msg2 := <- c2:
fmt.Println(msg2)
}
}
}()
In this example, I create a channel msg1 and msg2.
Then I create a go routine with an infinite loop. In this loop, I listen to msg1 AND msg2.
This system allow you to read to multiple channels simultaneously and to process the messages when the arrive.
In order to avoid leaks, I should probably add another channel to stop the goroutine.

VHDL Casting Error

I'm quite stumped for the past several days I've been trying to solve a casting error inside my VHDL. My code is attached below.
It will evaluate the if statement properly but will not assign the new value to the min or max variables. I know this as I commented out and tested different aspects of the function.
FYI. The type t_battery_data, contains an array of std_logic_vectors(15 downto 0) that are the voltages I'm comparing in the function below.
I'm not sure why it's performing this way. About all I could find in my searching online was to include the, ieee.numeric_std library which I have done.
Still stumped. Any suggestions would be greatly appreciated. Thanks!
function cell_delta_voltage_counts(
bat_data: t_battery_data
) return integer is
constant POS_INFINITY: integer:= 2 ** 16 - 1;
constant NEG_INFINITY: integer:= 0;
variable min: integer range 0 to 2 ** 16 - 1:= POS_INFINITY-5;
variable max: integer range 0 to 2 ** 16 - 1:= NEG_INFINITY;
begin
for i in 0 to NUM_CELLS-1 loop
if (to_integer(unsigned(bat_data.cell_readings(i).voltage)) < min) then
min := to_integer(unsigned(bat_data.cell_readings(i).voltage));
end if;
if (to_integer(unsigned(bat_data.cell_readings(i).voltage)) > max) then
max := to_integer(unsigned(bat_data.cell_readings(i).voltage));
end if;
end loop;
return max - min;
end function cell_delta_voltage_counts;
I don't use a lot of functions, but IIRC if you expect min and max to 'remember' their state between calls, you need to declare them outside the function and declare the function as impure:
variable min: integer range 0 to 2 ** 16 - 1:= POS_INFINITY-5;
variable max: integer range 0 to 2 ** 16 - 1:= NEG_INFINITY;
impure function cell_delta_voltage_counts(
...
I can't see anything wrong here. I tried your code and it works for me in Modelsim DE 10.1c. What simulator are you using?
Here's the code I used when trying your function:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity test is
end entity;
architecture sim of test is
constant NUM_CELLS : integer := 2;
type t_reading is record
voltage : std_logic_vector(15 downto 0);
end record t_reading;
type t_readings is array(natural range <>) of t_reading;
type t_battery_data is record
cell_readings : t_readings(0 to NUM_CELLS-1);
end record t_battery_data;
function cell_delta_voltage_counts(
(...)
end function cell_delta_voltage_counts;
begin
process
variable v_battery_data : t_battery_data;
variable v_result : integer := 0;
begin
v_battery_data.cell_readings(0).voltage := x"000a";
v_battery_data.cell_readings(1).voltage := x"001a";
v_result := cell_delta_voltage_counts(v_battery_data);
report "result: " & integer'image(v_result);
wait;
end process;
end architecture;
I used your function exactly as you posted it. The output of simulation is "result: 16" as expected.

sml syntax having a hard time looking up documentation

I am trying to "simulate" a pass by value result function with the following code but there seems to be a syntax error. I've been looking through sml tutorials but I'm having a hard time figuring out why this doesn't work
1 val x = ref 0;
2 fun p(y': int ref)=
3 let
4 val y = !y'
5 in
6 let
7 y = 1
8 in
9 let x := 0
10 in
11 y' := y
12 end
13 end
14 end
15 p(x)
In the let <decs> in <exp>, <decs> needs to be one or more declarations.
In your case, on line 7 you do y = 1 - note, this is not an assigment, but a comparison. That is, in C++ it would be equivalent to doing y == 1. You cannot assign to non-ref variables. (And in general, you want to avoid ref variables as much as possible.)
You could do val y = 1 in its place, in which case you create a new value by the name of y, which shadows over the old y (but does not change it; you create a new value).
Likewise, on line 9, you do x := 0, which is not a declaration, but an expression, which assigns the value 0 to the reference value x, and then returns unit.
In addition, you can do multiple declarations in your let statements, so you don't need the nesting you do.
Finally, you write p(x) on the toplevel. You can only write expressions on the toplevel, if the declaration preceding ends with a semicolon; otherwise it believes it to be a part of the declaration. That is
val a = 5
6
is interpreted to be
val a = 5 6
In short, you could rewrite it to this:
val x = ref 0;
fun p(y': int ref)=
let
val y = !y' (* this line might as well be deleted. *)
val y = 1
in
x := 0;
y' := y
end;
p(x)
Or, the shorter version, since the SML has good type inference:
val x = ref 0;
fun p y' = (x := 0; y' := 1);
p x
I will say this, though; if you come from a language like C++ or similar, it may be tempting to use 'a refs a lot, but you will often find, that minimizing the use of them often leads to cleaner code in SML. (And other functional languages.)
let y = 1 ... is wrong. So is let x := 0. Inside let ... in, you need either val or fun declarations.
It seems you have some misunderstandings of SML. let is used to declare new local variables in a scope. It is strange for you to try to declare a variable named y in an inner scope that shadows the y that you declared in the let in the immediately outer scope. You either meant one of two things:
Change the value of the "y" variable defined in the outer scope. This is impossible. You cannot change the value of a variable in ML
You want to declared a new, unrelated variable that is also named "y", and hide the previous "y" within this scope; in this case, you would use let var y = 1 in ...
Also, it is strange that you have let x := 0. x := 0 is a valid expression in itself. It changes the value contained in the reference pointed to by x. You don't need a let. Since x := 0 is only evaluated for side effects, and returns type unit (i.e. nothing useful), you might familiarize yourself with the ; operator, with which you can use to string together a bunch of side-effect "statements" which evaluate to the result of the last one: x := 0; y' := y