Clarification on what exactly constitutes as a continue target in Vulkan SPIR-V - vulkan

I'm trying to understand the SPIR-V spec, understanding for loops for example. In the beginning of the 1.6 revision 2 spec, the following example (taking only part of it for consisveness)
for (int i = 0; i < 4; ++i)
color *= multiplier;
turns into:
%49 = OpLabel
OpLoopMerge %51 %52 None ; structured loop
OpBranch %53
%53 = OpLabel
%54 = OpLoad %16 %48
%56 = OpSLessThan %25 %54 %55 ; i < 4 ?
OpBranchConditional %56 %50 %51 ; body or break
%50 = OpLabel ; body
%58 = OpLoad %7 %57
%59 = OpLoad %7 %31
%60 = OpFMul %7 %59 %58
OpStore %31 %60
OpBranch %52
%52 = OpLabel ; continue target
%61 = OpLoad %16 %48
%62 = OpIAdd %16 %61 %21 ; ++i
OpStore %48 %62
OpBranch %49 ; loop back
%51 = OpLabel ; loop merge point
OpReturn
OpFunctionEnd
In the spec, it specifies a block starts with a label, and ends with a any branch termination instruction. This turns the above into the following:
;Block 1
%49 = OpLabel
OpLoopMerge %51 %52 None ; structured loop
OpBranch %53
;Block 2
%53 = OpLabel
%54 = OpLoad %16 %48
%56 = OpSLessThan %25 %54 %55 ; i < 4 ?
OpBranchConditional %56 %50 %51 ; body or break
;Block 3
%50 = OpLabel ; body
%58 = OpLoad %7 %57
%59 = OpLoad %7 %31
%60 = OpFMul %7 %59 %58
OpStore %31 %60
OpBranch %52
;Block 4
%52 = OpLabel ; continue target
%61 = OpLoad %16 %48
%62 = OpIAdd %16 %61 %21 ; ++i
OpStore %48 %62
OpBranch %49 ; loop back
;Block 5
%51 = OpLabel ; loop merge point
OpReturn
OpFunctionEnd
Then the spec states:
Header Block: A block containing a merge instruction.
Loop Header: A header block whose merge instruction is an OpLoopMerge
So the loop header here is block 1, where OpLoopMerge is located.
OpLoopMerge claims three parameters, two which matter here:
Merge Block is the label of the merge block for this structured loop.
Continue Target is the label of a block targeted for processing a loop "continue".
Merge block is
Merge Block: A block declared by the Merge Block operand of a merge instruction.
Which my understanding is when the "structured loop/selection" ends, in this case it's right at the end of the function, block 5. This then makes sense to me.
The Continue target is what isn't clear to me. The continue target here is block 4, according to the op loop merge instruction. Why is the continue target not block 3? or block 2? What makes block 4 the continue target here? Is it because it's the block where the final decision is made to exit or continue the loop? is that what is meant by "processing a loop "continue"?

The "continue target" exists to serve the needs of the continue control flow instruction in most languages. In higher-level languages, in a loop, you can issue a continue statement. This jumps to the next iteration in the loop.
The "continue target" is the part of the loop code that starts the next iteration. You either branch here directly from a continue statement, or you branch here from the end of the body of the loop.
If the source contained a continue statement, that would be part of the loop's body, which in your example is Block 3. So there'd be no reason for that to be the continue target; that would cause an infinite loop, since the actual terminal condition is never checked, nor is the iteration expression evaluated.
And Block 2 also makes no sense. When you continue a loop, you must execute the iteration expression. Repeating the terminal condition wouldn't help, because it obviously already passed. That's how it got into the loop body to begin with. Until the iteration expression is evaluated, the terminal condition will continue to pass. And again, an infinite loop would result.

Related

Looking for help in correcting the syntax error in my Verilog code

module HazardDetectionUnit(stall, Rs1, Rt1, Rt2, MemRead2, clk);
input clk, MemRead2;
input [4:0] Rs1, Rt1, Rt2;
output reg [2:0] stall;
always #(negedge clk)
begin
if(MemRead2 & ((Rt2 = Rs1) | (Rt2 = Rt1))) //Error has been detected in this line
stall <= 3'b000;
else
stall <= 3'b111;
end
endmodule
ERROR: /nfs/home/s/s_ankith/HazardDetectionUnit_MIPS.v(7): near ")":
Syntax error. Assignment sub-exprs. are only allowed in SystemVerilog
or PSL.
You need == for testing equality:
if(MemRead2 & ((Rt2 == Rs1) | (Rt2 == Rt1)))

PISO register output is not as expected

I have a problem in PISO verilog register.
Below is my code
`timescale 1ns / 1ps
module PISO(
input clk,
input load,
input [3:0] d,
output reg Qout);
reg [3 : 0]Q;
always # (posedge clk)
begin
if ( load )
Q <= d;
else
begin
Qout <= d[3];
Q<= { Q[2:0] , 1'b0 };
end
end
endmodule
and my testbench
`timescale 1ns / 1ps
module PISO_tb();
PISO uut(clk,load,d,Qout);
reg clk;
reg load;
reg [3:0]d;
wire Qout;
initial begin
clk=0;
forever #5 clk = ~clk;
end
initial begin
load = 1;
d[0] = 1'b0;
d[1] = 1'b1;
d[2] = 1'b0;
d[3] = 1'b1;
#6 load = 0;
end
endmodule
And it isn't working as it should, please help me with testbench maybe? Because I think the verilog code is okay and it should work properly.
You want the Qout signal to be the output of the shift register (Q) instead of the input, so that the output toggles instead of remaining at 1. Change:
Qout <= d[3];
to:
Qout <= Q[3];

Changing a mutable field in OCaml

When I run the following code I get a syntax error, although as far as I can tell the syntax is correct. This attempts to implement a queue structure, where the function from_list converts a list to a queue with the corresponding values. I wrote str_of_int_q to print the contents of a queue. x and y are supposed to be two nodes, with x at the head and y at the tail.
;; open Assert
type 'a qnode = {v: 'a;
mutable next: 'a qnode option}
type 'a queue = {mutable head: 'a qnode option;
mutable tail: 'a qnode option}
let from_list (l: 'a list) : 'a queue =
let rec loop (l2: 'a list) (qu: 'a queue) =
begin match l2 with
| [] -> qu
| [x] -> let y = {v = x; next = None} in
qu.head <- Some y; qu.tail <- Some y;
qu
| h1::h2::t -> let y = qu.head in
let z = {v = h1; next = y} in
qu.head <- Some z;
qu
end
in loop l {head = None; tail = None}
let str_of_int_q (q: int queue) : string =
let rec loop (r: int qnode option) (s: string) : string =
begin match r with
| None -> s
| Some n -> loop n.next (s ^ (string_of_int n.v))
end
in loop q.head ""
let x = {v = 1; next = None}
let y = {v = 2; next = None}
x.next <- Some y;
let z = {head = Some x; tail = Some y}
;; print_endline (str_of_int_q z)
My error:
line 32, characters 7-9:
Error: Syntax error
Line 32 is the line x.next <- Some y; and characters 7-9 indicate the <-. But I'm storing into a mutable field an object of the appropriate type, so I don't see what's going wrong.
Top-level statements are separated by ;; in OCaml. However, ;; is optional before several keywords, such as let, open, type, etc. This is why you don't need ;; most of the time.
In your case, ;; is needed to disambiguate between let y = {v = 2; next = None} and x.next <- Some y. The latter is an expression and doesn't start with a special keyword, so OCaml doesn't know to insert an implicit ;; here.
See also http://ocaml.org/learn/tutorials/structure_of_ocaml_programs.html#The-disappearance-of.
As explained there, you can either do
let y = {v = 2; next = None}
;; x.next <- Some y
or
let y = {v = 2; next = None}
let () = x.next <- Some y
This latter solution works because by introducing a dummy binding we're starting our statement with let, which disambiguates again.
Note: I've also removed the trailing ; from your code. ; is actually an infix operator that combines two expressions (by throwing the result of the first one away and returning the result of the second one). This is not what you want here.

SystemVerilog Instantiated Modules Share Inputs When They Shouldn't (Easy Solution)?

I am having a small issue here in when I instantiated my modules. I am using a generate loop to create 100 instances of 2 counters (16 & 32 bit counters). Each counter should have their own independent controls (UPDN & EN), but they share a clock and a reset.
Module Descriptions:
SAT_COUNTER.sv // SIMPLE COUNTER MODULE
TWO_SC.sv // INSTANTIATES TWO SAT_COUNTER MODULES (16 BIT & 32 BIT
COUNTERS)
GEN_SC.sv // INSTANTIATES 100 MODULES OF TWO_SC MODULES
tb_GEN_SC.sv // TESTBENCH
I am sure that my problem is in the GEN_SC module where I instantiate all 100..
I appreciate any help! Thank you in advance!
module SAT_COUNTER(
COUNT, // SCALABLE COUNT OUTPUT
CLK, // CLOCK
al_RST, // ACTIVE LOW RESET
UPDN, // COUNTER WILL COUNT: UP = 1; DN = 0;
EN); // ENABLE
parameter WIDTH = 8;
input CLK, al_RST, UPDN, EN;
output reg [WIDTH-1:0] COUNT;
...
endmodule
//**********************
module TWO_SC(
COUNT1, // N-BIT COUNTER OUTPUT
COUNT2, // M-BIT COUNTER OUTPUT
CLK, // CLOCK
al_RST, // ACTIVE-LOW RESET
UPDN, // DIR. CONTROL
EN); // ENABLE
parameter WIDTH1 = 16;
parameter WIDTH2 = 32;
input CLK, al_RST;
input [1:0] UPDN, EN;
output [WIDTH1-1:0] COUNT1;
output [WIDTH2-1:0] COUNT2;
SAT_COUNTER #(WIDTH1) GSC1(.COUNT(COUNT1), .CLK(CLK), .al_RST(al_RST), .UPDN(UPDN[0]), .EN(EN[0]));
SAT_COUNTER #(WIDTH2) GSC2(.COUNT(COUNT2), .CLK(CLK), .al_RST(al_RST), .UPDN(UPDN[1]), .EN(EN[1]));
endmodule
//**********************
module GEN_SC(
COUNT1, // COUNT1
COUNT2, // COUNT2
CLK, // CLOCK
al_RST, // ACTIVE-LOW RESET
UPDN, // DIR. CONTROL
EN); // ENABLE
parameter MOD_COUNT = 100;
parameter WIDTH1 = 16;
parameter WIDTH2 = 32;
input CLK, al_RST;
input [1:0] UPDN [MOD_COUNT-1:0];
input [1:0] EN [MOD_COUNT-1:0];
output [WIDTH1-1:0] COUNT1;
output [WIDTH2-1:0] COUNT2;
genvar j;
generate
for(j = 0; j < MOD_COUNT; j++) begin: SC
TWO_SC #(.WIDTH1(WIDTH1), .WIDTH2(WIDTH2)) TWOCOUNTERS(.COUNT1(COUNT1), .COUNT2(COUNT2), .CLK(CLK), .al_RST(al_RST), .UPDN(UPDN[j]), .EN(EN[j]));
end
endgenerate
endmodule
//**********************
module tb_GEN_SC();
parameter MOD_COUNT = 100;
parameter WIDTH1 = 16;
parameter WIDTH2 = 32;
reg CLK, al_RST;
reg [1:0] UPDN [MOD_COUNT-1:0];
reg [1:0] EN [MOD_COUNT-1:0];
wire [WIDTH1-1:0] COUNT1;
wire [WIDTH2-1:0] COUNT2;
GEN_SC #(.WIDTH1(WIDTH1), .WIDTH2(WIDTH2)) UUT(COUNT1, COUNT2, CLK, al_RST, UPDN, EN);
initial begin
CLK = 1'b1;
forever
#5 CLK = ~CLK;
end
initial
$monitorb("%d COUNT = %b (%d) | UPDN = %b | EN = %b | COUNT = %b (%d) | UPDN = %b | EN = %b | al_RST = %b | CLK = %b", $time, UUT.SC[87].TWOCOUNTERS.COUNT1, UUT.SC[87].TWOCOUNTERS.COUNT1, UUT.SC[87].TWOCOUNTERS.UPDN[0], UUT.SC[87].TWOCOUNTERS.EN[0], UUT.SC[99].TWOCOUNTERS.COUNT1, UUT.SC[99].TWOCOUNTERS.COUNT1, UUT.SC[99].TWOCOUNTERS.UPDN[0], UUT.SC[99].TWOCOUNTERS.EN[0], al_RST, CLK);
initial begin
$vcdpluson;
UUT.SC[87].TWOCOUNTERS.GSC1.UPDN = 1; UUT.SC[99].TWOCOUNTERS.GSC1.UPDN = 1; EN = 0; al_RST = 1;
#10 UUT.SC[99].TWOCOUNTERS.GSC1.UPDN = 0; al_RST = 0; // RESET COUNTER
#10 EN = 1; al_RST = 1; // ENABLE COUNTER AND COUNT UP (HITS MAX)
#200 UUT.SC[87].TWOCOUNTERS.GSC1.UPDN = 0; UUT.SC[99].TWOCOUNTERS.GSC1.UPDN = 1; EN = 1; // BEGIN TO COUNT DOWN
#10 EN = 0;
#60 EN = 3;
// #230 UPDN = 1; UPDN = 0;
#3017 al_RST = 0;
#100 al_RST = 1;
#20 $finish;
end
/////////// ERRORS I GET /////////////////
Error-[IBLHS-NT] Illegal behavioral left hand side
tb_GEN_SC.sv, 34
Net type cannot be used on the left side of this assignment.
The offending expression is : tb_GEN_SC.UUT.SC[87].TWOCOUNTERS.GSC1.UPDN
Source info: tb_GEN_SC.UUT.SC[87].TWOCOUNTERS.GSC1.UPDN = 1;
Error-[IBLHS-NT] Illegal behavioral left hand side
tb_GEN_SC.sv, 34
Net type cannot be used on the left side of this assignment.
The offending expression is : tb_GEN_SC.UUT.SC[99].TWOCOUNTERS.GSC1.UPDN
Source info: tb_GEN_SC.UUT.SC[99].TWOCOUNTERS.GSC1.UPDN = 1;
Error-[IUDA] Incompatible dimensions
tb_GEN_SC.sv, 34
Incompatible unpacked dimensions in assignment
Arrays with incompatible unpacked dimensions cannot be used in assignments,
initializations and instantiations.
Error-[ICTA] Incompatible complex type
tb_GEN_SC.sv, 34
Incompatible complex type assignment
Type of source expression is incompatible with type of target expression.
Mismatching types cannot be used in assignments, initializations and
instantiations. The type of the target is 'reg[1:0]$[99:0]', while the type
of the source is 'int'.
Source Expression: 0
You have just one UPDB and one EN port in port list. So how you wana apply different UPDN and EN to instances?
An idea is to define an array with size of MOD_COUNT so that each element has its own control input. then in genvar loop you can use the index. like this:
input [1:0] UPDN [MOD_COUNT-1:0];
input [1:0] EN [MOD_COUNT-1:0];
...
generate
for(j = 0; j < MOD_COUNT; j++) begin: SC
TWO_SC #(.WIDTH1(WIDTH1), .WIDTH2(WIDTH2)) TWOCOUNTERS(.COUNT1(COUNT1),
.COUNT2(COUNT2), .CLK(CLK), .al_RST(al_RST), .UPDN(UPDN[j]), .EN(EN[j]));
end
endgenerate

What is time complexity for the following code?

It seems the complexity of the following code should be O(n^2) but it's O(n), how?
void fun(int n, int arr[])
{
int i = 0, j = 0;
for(; i < n; ++i)
while(j < n && arr[i] < arr[j])
j++;
}
In the first look, the time complexity seems to be O(n^2) due to two loops. But, please note that the variable j is not initialized for each value of variable i.
Hence, the inner j++ will be executed at most n times.
The i loop also runs n times.
So, the whole thing runs for O(n) times.
Please observe the difference between the function given in question and the below function:
void fun(int n, int arr[])
{
int i = 0, j = 0;
for(; i < n; ++i)
{
j = 0;
while(j < n && arr[i] < arr[j])
j++;
}
}`
Still not convinced ?
Let's assume the array passed has its element in decreasing order. We will just dry run through the code :
Iteration 1 : i = 0, j = 0. arr[0] < arr[0] is false. So, the
inner while loop breaks.
Iteration 2: i =1, j = 0. arr[1] < arr[0] is true. j becomes
Iteration 3 : i = 1, j = 1. Condition false. We break. Note
that j will remain 1 and is not reset back to 0.
Iteration 4 : i = 2, j = 1. arr[2] < arr[1]. True. j = 2.
Iteration 5 : i = 2, j = 2. Condition false. Break.
Iteration 6 : i = 3, j = 2. arr[3] < arr[2]. True. j = 3.
Iteration 7 : i = 3, j = 3. Condition false. Break.
As you can see, the inner while loop only runs once in this case.
So, total iterations is 2 * N.
j is not reset to 0 with every iteration of the outer loop. As such, it runs to n-1 just once, same as i does. So you have two parallel/intermingled iterations from 0 to (at most) n-1.
In every step, the program increases i by one. The program terminates when i reaches n. The "outer loop" is run n times.
There is also an "inner loop" about j. But all it does is increase j until it reaches i (at most, sometimes it does less). j is never decreased. So that part is also run at most n times in total (not n times for each iteration of the "outer loop").
The answer is O(n)
The outer loop runs 'n' times and the inner loop only runs to 'n' a single time in all the iterations combined as the value of j is never reset to 0.
Therefore the answer is O(n+n)=O(n).
Lets consider the worst case when the while loop is executed maximum no. of times.
Initially: i=0 , j=0 => while loop does not gets executed since arr[0] = arr[0] i.e. j=0.
Second iteration : i=1 , j=0 => while loop gets executed for the worst case i.e. j=1.
Third iteration : i=2 , j=1 => while loop again gets executed for the worst case i.e. j=2.
...
nth iteration : i=n-1 , j=n-2 => while loop again gets executed for the worst case i.e. j=n-1.
So, by doing this exercise we can observe that every time j = i-1
except i=0 and j=0 OR we can say that the while loop is just running in parallel to the for loop and thus the no. of executions of the while loop is equal to the no. of executions of the for loop.
Hence Order = O(n);
The answer is O(n) because the test condition inside the 'while' loop fails!
while(j < n && arr[i] < arr[j])
In the beginning, i=0 and j=0, which means arr[i] = arr[j], but the while loop test condition says arr[i]<arr[j], and its completely wrong to assume arr[0]<arr[0]
The code only runs the for loop n times.
The final answer is O(n) not O(n^2)
For some clarity, you can go through these two examples
Example 1 :
#include <stdio.h>
int main()
{
int i = 0, j = 0;
int n = 5;
int arr[] = {6,7,8,9,10,11};
for(; i < n; ++i)
{
printf("\nThis is for loop, its running 5 times\n");
while(j < n && arr[i] < arr[j]){
j++;
printf("\nThis is while loop!\n");
}
};
return 0;
}
The Output is :
This is for loop, its running 5 times
This is for loop, its running 5 times
This is for loop, its running 5 times
This is for loop, its running 5 times
This is for loop, its running 5 times
In the above output, we can't find the print statement present in 'while' loop
Example 2 :
#include <stdio.h>
int main()
{
int i = 0, j = 0;
int n = 5;
int arr[] = {6,7,8,9,10,11};
for(; i < n; ++i)
{
printf("\nThis is for loop, its running 5 times\n");
while(j < n && arr[i] <= arr[j]){
j++;
printf("\nThis is while loop!\n");
}
};
return 0;
}
Here, a small change is made
arr[i] <= arr[j]
'=' is used
Output:
This is for loop, its running 5 times
This is while loop!
This is while loop!
This is while loop!
This is while loop!
This is while loop!
This is for loop, its running 5 times
This is for loop, its running 5 times
This is for loop, its running 5 times
This is for loop, its running 5 times
Here, the print statement in while loop is executed, because arr[i]=arr[j],
arr[0] = arr[0]
For the 'Example 2' shown above the time complexity is O(n^2)
Note that the variable j is not initialized for each value of variable i.
Hence, the inner j++ will be executed at most n times.
The i loop also runs n times.
So, the whole thing runs for O(n) times.