1 | /* the interleaving is emulated in the system process by permit variables */ |
---|
2 | |
---|
3 | `define N 2 |
---|
4 | |
---|
5 | /* to emulate program counter */ |
---|
6 | typedef enum { L1, L2, L3, L4, L5, L6, L7, L8, |
---|
7 | L9, L10, L11, L12, L13, L14, L15, L16 } loc; |
---|
8 | |
---|
9 | /* state of how hard a process want to enter critical section */ |
---|
10 | typedef enum { idle, want_in, in_cs } flag_type; |
---|
11 | |
---|
12 | module system (clk); |
---|
13 | input clk; |
---|
14 | |
---|
15 | /* flag? and turn are shared memory */ |
---|
16 | flag_type reg flag0, flag1; |
---|
17 | reg turn; |
---|
18 | |
---|
19 | flag_type wire out_flag0, out_flag1; |
---|
20 | wire out_turn0, out_turn1; |
---|
21 | |
---|
22 | wire perm0, perm1; |
---|
23 | reg st_perm0, st_perm1; |
---|
24 | // st_pterm? just show which process is chosen |
---|
25 | |
---|
26 | /* the current processes */ |
---|
27 | process p0(clk, perm0, flag0, flag1, out_flag0, turn, out_turn0, 0); |
---|
28 | process p1(clk, perm1, flag0, flag1, out_flag1, turn, out_turn1, 1); |
---|
29 | |
---|
30 | /* the processes are chosen to be executed by CPU nondeterministically */ |
---|
31 | assign perm0 = $NDset(@(posedge clk), 0, 1); |
---|
32 | assign perm1 = ~perm0; |
---|
33 | |
---|
34 | /* only OS/CPU can update system memory */ |
---|
35 | initial begin flag0=idle; flag1=idle; turn=0; end |
---|
36 | initial st_perm0 = $ND(0,1); |
---|
37 | initial st_perm1 = $ND(0,1); |
---|
38 | always @(posedge clk) begin |
---|
39 | st_perm0 = perm0; st_perm1 = perm1; |
---|
40 | if (perm0==1) begin flag0 = out_flag0; turn = out_turn0; end |
---|
41 | else if(perm1==1) begin flag1 = out_flag1; turn = out_turn1; end |
---|
42 | end |
---|
43 | |
---|
44 | endmodule |
---|
45 | |
---|
46 | |
---|
47 | /* individual process */ |
---|
48 | module process (clk, perm, flag0, flag1, out_flag, turn, out_turn, i); |
---|
49 | input clk; |
---|
50 | input perm; |
---|
51 | input flag0, flag1; |
---|
52 | output out_flag; |
---|
53 | input turn; |
---|
54 | output out_turn; |
---|
55 | input i; |
---|
56 | |
---|
57 | flag_type wire flag0, flag1; |
---|
58 | flag_type wire out_flag; |
---|
59 | |
---|
60 | // pc and j are local to each process |
---|
61 | loc reg pc; |
---|
62 | reg j; |
---|
63 | |
---|
64 | flag_type wire flagj, flagturn; |
---|
65 | wire nond_exit; |
---|
66 | |
---|
67 | assign flagj = (j==0) ? flag0 : flag1, |
---|
68 | flagturn = (turn==0) ? flag0 : flag1; |
---|
69 | |
---|
70 | /* if the process decide to change system wide data */ |
---|
71 | assign out_flag = (pc==L1) ? want_in : |
---|
72 | (pc==L7) ? in_cs : |
---|
73 | (pc==L16)? idle : |
---|
74 | (i==0) ? flag0 : flag1; |
---|
75 | assign out_turn = (pc==L11) ? i : (pc==L15) ? j : turn; |
---|
76 | assign nond_exit = $NDset(@(posedge clk), 0, 1); |
---|
77 | |
---|
78 | initial begin j=0; pc=L1; end |
---|
79 | |
---|
80 | // ----- the program is executed forever ----- |
---|
81 | always @(posedge clk) begin |
---|
82 | if (perm==1) begin |
---|
83 | case (pc) |
---|
84 | // repeat flag[i]=want_in; |
---|
85 | L1: begin pc=L2; end |
---|
86 | // j=turn; |
---|
87 | L2: begin j=turn; pc=L3; end |
---|
88 | // while (j != i) |
---|
89 | L3: begin if (j!=i) pc=L4; else pc=L7; end |
---|
90 | // do if (flag[j] != idle) |
---|
91 | L4: begin if (flagj != idle) pc=L5; else pc=L6; end |
---|
92 | // then j = turn; |
---|
93 | L5: begin j=turn; pc=L3; end |
---|
94 | // else j = j+1 mod `N; |
---|
95 | L6: begin if (j==`N-1) j=0; else j=j+1; pc=L3; end |
---|
96 | // flag[i] = in_cs; |
---|
97 | L7: begin pc=L8; end |
---|
98 | // j=0; |
---|
99 | L8: begin j=0; pc=L9; end |
---|
100 | // while ((j<`N) && (j==i || flag[j] != in_cs)) do j=j+1; |
---|
101 | L9: begin |
---|
102 | if ((j<`N) && ((j==i) || (flagj!=in_cs))) |
---|
103 | begin j=j+1; pc=L9; end |
---|
104 | else pc=L10; |
---|
105 | end |
---|
106 | // until (j>=`N) && ((turn==i) || flag[turn] == idle); |
---|
107 | L10: begin |
---|
108 | if ((j>=`N) && ((turn==i) || (flagturn==idle))) |
---|
109 | pc=L11; |
---|
110 | else |
---|
111 | pc=L1; |
---|
112 | end |
---|
113 | // turn = i; |
---|
114 | L11: begin pc=L12; end |
---|
115 | // critical section |
---|
116 | |
---|
117 | // ----- CRITICAL SECTION ----- |
---|
118 | L12: begin if (nond_exit==1) pc=L13; else pc=L12; end |
---|
119 | // j = turn+1 mod `N; |
---|
120 | L13: begin if (turn==`N-1) j=0; else j=turn+1; pc=L14; end |
---|
121 | // while (flag[j] == idle) do j=j+1 mod `N; |
---|
122 | L14: begin if (flagj==idle) |
---|
123 | begin |
---|
124 | if (j==`N-1) j=0; |
---|
125 | else j=j+1; |
---|
126 | pc=L14; |
---|
127 | end |
---|
128 | else pc=L15; |
---|
129 | end |
---|
130 | // turn = j; |
---|
131 | L15: begin pc=L16; end |
---|
132 | // flag[i] = idle; |
---|
133 | L16: begin if (nond_exit==1) pc=L1; else pc=L16; end |
---|
134 | |
---|
135 | // ----- REMAINDER SECTION ----- |
---|
136 | default: ; |
---|
137 | endcase |
---|
138 | end |
---|
139 | end |
---|
140 | |
---|
141 | endmodule |
---|