[11] | 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 |
---|