icache bug fixes (was emitting extraneous instructions)
[fleet.git] / src / edu / berkeley / fleet / slipway / icache.v
1 `include "macros.v"
2 `define BRAM_ADDR_WIDTH 14
3 `define BRAM_DATA_WIDTH `INSTRUCTION_WIDTH
4 `define BRAM_NAME icache_bram
5 `include "bram.inc"
6
7 module icache (clk, 
8                write_addr_r,   write_addr_a_,  write_addr_d,
9                write_data_r,   write_data_a_,  write_data_d,
10                write_done_r_,  write_done_a,   write_done_d_,
11                cbd_r,          cbd_a_,         cbd_d,
12                preload_r,      preload_a_,     preload_d,
13                ihorn_r_,       ihorn_a,        ihorn_d_,
14                dhorn_r_,       dhorn_a,        dhorn_d_
15            );
16
17   input  clk;
18   `input(write_addr_r,   write_addr_a,  write_addr_a_,  [(`DATAWIDTH-1):0],         write_addr_d)
19   `input(write_data_r,   write_data_a,  write_data_a_,  [(`DATAWIDTH-1):0],         write_data_d)
20   `output(write_done_r,  write_done_r_, write_done_a,   [(`DATAWIDTH-1):0],         write_done_d_)
21   `defreg(write_done_d_,                                [(`DATAWIDTH-1):0],         write_done_d)
22
23   `input(preload_r,      preload_a,     preload_a_,     [(`DATAWIDTH-1):0],         preload_d)
24   `input(cbd_r,          cbd_a,         cbd_a_,         [(`DATAWIDTH-1):0],         cbd_d)
25   `output(ihorn_r,       ihorn_r_,      ihorn_a,        [(`INSTRUCTION_WIDTH-1):0], ihorn_d_)
26   `defreg(ihorn_d_,                                     [(`INSTRUCTION_WIDTH-1):0], ihorn_d)
27   `output(dhorn_r,       dhorn_r_,      dhorn_a,        [(`PACKET_WIDTH-1):0],      dhorn_d_)
28   `defreg(dhorn_d_,                                     [(`PACKET_WIDTH-1):0],      dhorn_d)
29
30   reg ihorn_full;
31   initial ihorn_full = 0;
32   reg dhorn_full;
33   initial dhorn_full = 0;
34   reg command_valid;
35   initial command_valid = 0;
36
37   reg [(`BRAM_ADDR_WIDTH-1):0]    preload_pos;
38   reg [(`BRAM_ADDR_WIDTH-1):0]    preload_size;
39   initial preload_size = 0;
40
41   reg [(`BRAM_ADDR_WIDTH-1):0]    current_instruction_read_from;
42   reg [(`BRAM_ADDR_WIDTH-1):0]    temp_base;
43   reg [(`CODEBAG_SIZE_BITS-1):0]  temp_size;
44   reg [(`BRAM_ADDR_WIDTH-1):0]    cbd_base;
45   reg [(`CODEBAG_SIZE_BITS-1):0]  cbd_size;
46   reg [(`CODEBAG_SIZE_BITS-1):0]  cbd_pos;
47   reg [(`INSTRUCTION_WIDTH-1):0]  command;
48   reg [(`BRAM_DATA_WIDTH-1):0]    ram [((1<<(`BRAM_ADDR_WIDTH))-1):0];
49   reg                             send_done;
50
51   reg [(`INSTRUCTION_WIDTH-(2+`DESTINATION_ADDRESS_BITS)):0] temp;
52   reg [(`DATAWIDTH-1):0]                                     data;
53
54   reg                             write_flag;
55   reg [(`BRAM_ADDR_WIDTH-1):0]    write_addr;
56   reg [(`BRAM_DATA_WIDTH-1):0]    write_data;
57
58   wire [(`BRAM_DATA_WIDTH-1):0]   ramread;
59
60   reg command_valid_read;
61   initial command_valid_read = 0;
62
63   reg launched;
64   initial launched = 0;
65
66   icache_bram mybram(clk, write_flag, write_addr, current_instruction_read_from, write_data, not_connected, ramread);
67
68   always @(posedge clk) begin
69
70     write_flag <= 0;
71
72     if (!write_addr_r && write_addr_a) write_addr_a = 0;
73     if (!write_data_r && write_data_a) write_data_a = 0;
74
75     if (command_valid_read) begin
76       command_valid_read  <= 0;
77       command_valid       <= 1;
78
79     end else  if (send_done) begin
80       `onwrite(write_done_r, write_done_a)
81         send_done <= 0;
82       end
83
84     end else if (write_addr_r && write_data_r) begin
85       write_addr_a       = 1;
86       write_data_a       = 1;
87       send_done         <= 1;
88       write_flag        <= 1;
89       write_addr        <= write_addr_d;
90       write_data        <= write_data_d;
91
92     end else if (ihorn_full && launched) begin
93       `onwrite(ihorn_r, ihorn_a)
94         ihorn_full <= 0;
95       end
96
97     end else if (dhorn_full) begin
98       `onwrite(dhorn_r, dhorn_a)
99         dhorn_full <= 0;
100       end
101
102     end else if (command_valid) begin
103       command_valid <= 0;
104       command = ramread;
105       case (command[(`INSTRUCTION_WIDTH-1):(`INSTRUCTION_WIDTH-2)])
106         0: begin
107             ihorn_full  <= 1;
108             ihorn_d     <= command;
109            end
110         1: begin
111             dhorn_full  <= 1;
112             temp    = command[(`INSTRUCTION_WIDTH-(2+`DESTINATION_ADDRESS_BITS)):0];
113             temp    = temp + ( { current_instruction_read_from, {(`CODEBAG_SIZE_BITS){1'b0}} });
114             data[(`DATAWIDTH-1):(`CODEBAG_SIZE_BITS)] = temp;
115             data[(`CODEBAG_SIZE_BITS-1):0]            = command[(`CODEBAG_SIZE_BITS-1):0];
116             `packet_data(dhorn_d) <= temp;
117             `packet_dest(dhorn_d) <=
118                   command[(`INSTRUCTION_WIDTH-3):(`INSTRUCTION_WIDTH-(3+`DESTINATION_ADDRESS_BITS)+1)];
119            end
120         2: begin
121             dhorn_full            <= 1;
122             `packet_data(dhorn_d) <= command[23:0];
123             `packet_dest(dhorn_d) <= command[34:24];
124            end
125         3: begin
126             dhorn_full            <= 1;
127             `packet_data(dhorn_d) <= command[23:0] + current_instruction_read_from;
128             `packet_dest(dhorn_d) <= command[34:24];
129            end
130       endcase
131
132     end else if (cbd_pos < cbd_size) begin
133       current_instruction_read_from <= cbd_base+cbd_pos;
134       command_valid_read            <= 1;
135       cbd_pos                       <= cbd_pos + 1;
136
137     end else begin
138       `onread(cbd_r, cbd_a)
139         cbd_pos       <= 0;
140         cbd_size      <= cbd_d[(`CODEBAG_SIZE_BITS-1):0];
141         cbd_base      <= cbd_d[(`INSTRUCTION_WIDTH-1):(`CODEBAG_SIZE_BITS)];
142
143       end else begin
144         `onread(preload_r, preload_a)
145           if (preload_size == 0) begin
146             preload_size     <= preload_d;
147           end else if (!launched) begin
148             write_flag <= 1;
149             write_data <= preload_d;
150             write_addr <= preload_pos;
151             if (preload_pos == 0) begin
152               temp_base = preload_d[(`INSTRUCTION_WIDTH-(3+`DESTINATION_ADDRESS_BITS)):(`CODEBAG_SIZE_BITS)];
153               temp_size = preload_d[(`CODEBAG_SIZE_BITS-1):0];
154             end
155             if ((preload_pos+1) == preload_size) begin
156               cbd_pos  <= 0;
157               cbd_base <= temp_base;
158               cbd_size <= temp_size;
159               launched <= 1;
160             end
161             preload_pos      <= preload_pos + 1;
162           end
163         end
164       end
165     end
166   end
167 endmodule
168
169