OpenCores
URL https://opencores.org/ocsvn/thor/thor/trunk

Subversion Repositories thor

[/] [thor/] [trunk/] [FT64/] [rtl/] [twoway/] [FT64_fetchbuf.v] - Blame information for rev 43

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 43 robfinch
// ============================================================================
2
//        __
3
//   \\__/ o\    (C) 2017-2018  Robert Finch, Waterloo
4
//    \  __ /    All rights reserved.
5
//     \/_//     robfinch<remove>@finitron.ca
6
//       ||
7
//
8
//      FT64_fetchbuf.v
9
//
10
// This source file is free software: you can redistribute it and/or modify 
11
// it under the terms of the GNU Lesser General Public License as published 
12
// by the Free Software Foundation, either version 3 of the License, or     
13
// (at your option) any later version.                                      
14
//                                                                          
15
// This source file is distributed in the hope that it will be useful,      
16
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
17
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
18
// GNU General Public License for more details.                             
19
//                                                                          
20
// You should have received a copy of the GNU General Public License        
21
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
22
//
23
// ============================================================================
24
//
25
`include "FT64_defines.vh"
26
 
27
// FETCH
28
//
29
// fetch exactly two instructions from memory into the fetch buffer
30
// unless either one of the buffers is still full, in which case we
31
// do nothing (kinda like alpha approach)
32
// Like to turn this into an independent module at some point.
33
//
34
module FT64_fetchbuf(rst, clk4x, clk, hirq, thread_en,
35
        regLR,
36
    insn0, insn1, phit,
37
    threadx,
38
    branchmiss, misspc, branchmiss_thrd, predict_taken0, predict_taken1,
39
    predict_takenA, predict_takenB, predict_takenC, predict_takenD,
40
    queued1, queued2, queuedNop,
41
    pc0, pc1, fetchbuf, fetchbufA_v, fetchbufB_v, fetchbufC_v, fetchbufD_v,
42
    fetchbufA_instr, fetchbufA_pc,
43
    fetchbufB_instr, fetchbufB_pc,
44
    fetchbufC_instr, fetchbufC_pc,
45
    fetchbufD_instr, fetchbufD_pc,
46
    fetchbuf0_instr, fetchbuf1_instr,
47
    fetchbuf0_thrd, fetchbuf1_thrd,
48
    fetchbuf0_pc, fetchbuf1_pc,
49
    fetchbuf0_v, fetchbuf1_v,
50
    codebuf0, codebuf1,
51
    btgtA, btgtB, btgtC, btgtD,
52
    nop_fetchbuf,
53
    take_branch0, take_branch1,
54
    stompedRets
55
);
56
parameter AMSB = 31;
57
parameter RSTPC = 32'hFFFC0100;
58
parameter TRUE = 1'b1;
59
parameter FALSE = 1'b0;
60
input rst;
61
input clk4x;
62
input clk;
63
input hirq;
64
input thread_en;
65
input [4:0] regLR;
66
input [31:0] insn0;
67
input [31:0] insn1;
68
input phit;
69
output threadx;
70
input branchmiss;
71
input [AMSB:0] misspc;
72
input branchmiss_thrd;
73
output predict_taken0;
74
output predict_taken1;
75
input predict_takenA;
76
input predict_takenB;
77
input predict_takenC;
78
input predict_takenD;
79
input queued1;
80
input queued2;
81
input queuedNop;
82
output reg [AMSB:0] pc0;
83
output reg [AMSB:0] pc1;
84
output reg fetchbuf;
85
output reg fetchbufA_v;
86
output reg fetchbufB_v;
87
output reg fetchbufC_v;
88
output reg fetchbufD_v;
89
output fetchbuf0_thrd;
90
output fetchbuf1_thrd;
91
output reg [31:0] fetchbufA_instr;
92
output reg [31:0] fetchbufB_instr;
93
output reg [31:0] fetchbufC_instr;
94
output reg [31:0] fetchbufD_instr;
95
output reg [AMSB:0] fetchbufA_pc;
96
output reg [AMSB:0] fetchbufB_pc;
97
output reg [AMSB:0] fetchbufC_pc;
98
output reg [AMSB:0] fetchbufD_pc;
99
output [31:0] fetchbuf0_instr;
100
output [31:0] fetchbuf1_instr;
101
output [AMSB:0] fetchbuf0_pc;
102
output [AMSB:0] fetchbuf1_pc;
103
output fetchbuf0_v;
104
output fetchbuf1_v;
105
input [31:0] codebuf0;
106
input [31:0] codebuf1;
107
input [AMSB:0] btgtA;
108
input [AMSB:0] btgtB;
109
input [AMSB:0] btgtC;
110
input [AMSB:0] btgtD;
111
input [3:0] nop_fetchbuf;
112
output take_branch0;
113
output take_branch1;
114
input [3:0] stompedRets;
115
 
116
integer n;
117
 
118
//`include "FT64_decode.vh"
119
 
120
function IsBranch;
121
input [31:0] isn;
122
casex(isn[`INSTRUCTION_OP])
123
`Bcc:   IsBranch = TRUE;
124
`BccR:  IsBranch = TRUE;
125
`BBc:   IsBranch = TRUE;
126
`BEQI:  IsBranch = TRUE;
127
default: IsBranch = FALSE;
128
endcase
129
endfunction
130
 
131
function IsJmp;
132
input [31:0] isn;
133
IsJmp = isn[`INSTRUCTION_OP]==`JMP;
134
endfunction
135
 
136
function IsCall;
137
input [31:0] isn;
138
IsCall = isn[`INSTRUCTION_OP]==`CALL;
139
endfunction
140
 
141
function IsRet;
142
input [31:0] isn;
143
IsRet = isn[`INSTRUCTION_OP]==`RET;
144
endfunction
145
 
146
function IsRTI;
147
input [31:0] isn;
148
IsRTI = isn[`INSTRUCTION_OP]==`RR && isn[`INSTRUCTION_S2]==`RTI;
149
endfunction
150
 
151
reg thread;
152
reg stompedRet;
153
reg ret0Counted, ret1Counted;
154
wire [AMSB:0] retpc0, retpc1;
155
 
156
reg did_branchback0;
157
reg did_branchback1;
158
 
159
assign predict_taken0 = (fetchbuf==1'b0) ? predict_takenA : predict_takenC;
160
assign predict_taken1 = (fetchbuf==1'b0) ? predict_takenB : predict_takenD;
161
 
162
wire [AMSB:0] branch_pcA = IsRet(fetchbufA_instr) ? retpc0 :
163
                         IsJmp(fetchbufA_instr) | IsCall(fetchbufA_instr) ? {fetchbufA_pc[31:28],fetchbufA_instr[31:6],2'b00} :
164
                         ((IsRTI(fetchbufA_instr) || fetchbufA_instr[`INSTRUCTION_OP]==`BccR || fetchbufA_instr[`INSTRUCTION_OP]==`BRK ||
165
                         fetchbufA_instr[`INSTRUCTION_OP]==`JAL) ? btgtA :
166
                         fetchbufA_pc + {{19{fetchbufA_instr[`INSTRUCTION_SB]}},fetchbufA_instr[31:22],fetchbufA_instr[0],2'b00} + 64'd4);
167
wire [AMSB:0] branch_pcB = IsRet(fetchbufB_instr) ? (thread_en ? retpc1 : retpc0) :
168
                         IsJmp(fetchbufB_instr) | IsCall(fetchbufB_instr) ? {fetchbufB_pc[31:28],fetchbufB_instr[31:6],2'b00} :
169
                         ((IsRTI(fetchbufB_instr) || fetchbufB_instr[`INSTRUCTION_OP]==`BccR || fetchbufB_instr[`INSTRUCTION_OP]==`BRK ||
170
                         fetchbufB_instr[`INSTRUCTION_OP]==`JAL) ? btgtB :
171
                         fetchbufB_pc + {{19{fetchbufB_instr[`INSTRUCTION_SB]}},fetchbufB_instr[31:22],fetchbufB_instr[0],2'b00} + 64'd4);
172
wire [AMSB:0] branch_pcC = IsRet(fetchbufC_instr) ? retpc0 :
173
                         IsJmp(fetchbufC_instr) | IsCall(fetchbufC_instr) ? {fetchbufC_pc[31:28],fetchbufC_instr[31:6],2'b00} :
174
                         ((IsRTI(fetchbufC_instr) || fetchbufC_instr[`INSTRUCTION_OP]==`BccR || fetchbufC_instr[`INSTRUCTION_OP]==`BRK ||
175
                         fetchbufC_instr[`INSTRUCTION_OP]==`JAL) ? btgtC :
176
                         fetchbufC_pc + {{19{fetchbufC_instr[`INSTRUCTION_SB]}},fetchbufC_instr[31:22],fetchbufC_instr[0],2'b00} + 64'd4);
177
wire [AMSB:0] branch_pcD = IsRet(fetchbufD_instr) ? (thread_en ? retpc1 : retpc0) :
178
                         IsJmp(fetchbufD_instr) | IsCall(fetchbufD_instr) ? {fetchbufD_pc[31:28],fetchbufD_instr[31:6],2'b00} :
179
                         ((IsRTI(fetchbufD_instr) || fetchbufD_instr[`INSTRUCTION_OP]==`BccR ||fetchbufD_instr[`INSTRUCTION_OP]==`BRK ||
180
                         fetchbufD_instr[`INSTRUCTION_OP]==`JAL) ? btgtD :
181
                         fetchbufD_pc + {{19{fetchbufD_instr[`INSTRUCTION_SB]}},fetchbufD_instr[31:22],fetchbufD_instr[0],2'b00} + 64'd4);
182
 
183
wire take_branchA = ({fetchbufA_v, IsBranch(fetchbufA_instr), predict_takenA}  == {`VAL, `TRUE, `TRUE}) ||
184
                        ((IsRet(fetchbufA_instr)||IsJmp(fetchbufA_instr)||IsCall(fetchbufA_instr)||
185
                        IsRTI(fetchbufA_instr)|| fetchbufA_instr[`INSTRUCTION_OP]==`BRK || fetchbufA_instr[`INSTRUCTION_OP]==`JAL) &&
186
                        fetchbufA_v);
187
wire take_branchB = ({fetchbufB_v, IsBranch(fetchbufB_instr), predict_takenB}  == {`VAL, `TRUE, `TRUE}) ||
188
                        ((IsRet(fetchbufB_instr)|IsJmp(fetchbufB_instr)|IsCall(fetchbufB_instr) ||
189
                        IsRTI(fetchbufB_instr)|| fetchbufB_instr[`INSTRUCTION_OP]==`BRK || fetchbufB_instr[`INSTRUCTION_OP]==`JAL) &&
190
                        fetchbufB_v);
191
wire take_branchC = ({fetchbufC_v, IsBranch(fetchbufC_instr), predict_takenC}  == {`VAL, `TRUE, `TRUE}) ||
192
                        ((IsRet(fetchbufC_instr)|IsJmp(fetchbufC_instr)|IsCall(fetchbufC_instr) ||
193
                        IsRTI(fetchbufC_instr)|| fetchbufC_instr[`INSTRUCTION_OP]==`BRK || fetchbufC_instr[`INSTRUCTION_OP]==`JAL) &&
194
                        fetchbufC_v);
195
wire take_branchD = ({fetchbufD_v, IsBranch(fetchbufD_instr), predict_takenD}  == {`VAL, `TRUE, `TRUE}) ||
196
                        ((IsRet(fetchbufD_instr)|IsJmp(fetchbufD_instr)|IsCall(fetchbufD_instr) ||
197
                        IsRTI(fetchbufD_instr)|| fetchbufD_instr[`INSTRUCTION_OP]==`BRK || fetchbufD_instr[`INSTRUCTION_OP]==`JAL) &&
198
                        fetchbufD_v);
199
 
200
assign take_branch0 = fetchbuf==1'b0 ? take_branchA : take_branchC;
201
assign take_branch1 = fetchbuf==1'b0 ? take_branchB : take_branchD;
202
wire take_branch = take_branch0 || take_branch1;
203
/*
204
always @*
205
begin
206
        pc0 <= thread_en ? (fetchbuf ? pc0b : pc0a) : pc0a;
207
        pc1 <= thread_en ? (fetchbuf ? pc1b : pc1a) : pc1a;
208
end
209
*/
210
assign threadx = thread_en ? fetchbuf : 1'b0;
211
 
212
FT64_RSB #(AMSB) ursb1
213
(
214
        .rst(rst),
215
        .clk(clk),
216
        .regLR(regLR),
217
        .queued1(queued1),
218
        .queued2(queued2),
219
        .fetchbuf0_v(fetchbuf0_v),
220
        .fetchbuf0_pc(fetchbuf0_pc),
221
        .fetchbuf0_instr(fetchbuf0_instr),
222
        .fetchbuf1_v(fetchbuf1_v),
223
        .fetchbuf1_pc(fetchbuf1_pc),
224
        .fetchbuf1_instr(fetchbuf1_instr),
225
        .stompedRets(thread_en ? stompedRets : stompedRets[3:1]),
226
        .stompedRet(stompedRet),
227
        .pc(retpc0)
228
);
229
 
230
FT64_RSB #(AMSB) ursb2
231
(
232
        .rst(rst),
233
        .clk(clk),
234
        .regLR(regLR),
235
        .queued1(queued1),
236
        .queued2(1'b0),
237
        .fetchbuf0_v(fetchbuf1_v),
238
        .fetchbuf0_pc(fetchbuf1_pc),
239
        .fetchbuf0_instr(fetchbuf1_instr),
240
        .fetchbuf1_v(1'b0),
241
        .fetchbuf1_pc(32'h00000000),
242
        .fetchbuf1_instr(`NOP_INSN),
243
        .stompedRets(stompedRets[3:1]),
244
        .stompedRet(stompedRet),
245
        .pc(retpc1)
246
);
247
 
248
wire peclk, neclk;
249
edge_det ued1 (.rst(rst), .clk(clk4x), .ce(1'b1), .i(clk), .pe(peclk), .ne(neclk), .ee());
250
 
251
always @(posedge clk)
252
if (rst) begin
253
          pc0 <= RSTPC;
254
      pc1 <= RSTPC + 32'd4;
255
     fetchbufA_v <= 0;
256
     fetchbufB_v <= 0;
257
     fetchbufC_v <= 0;
258
     fetchbufD_v <= 0;
259
      fetchbuf <= 0;
260
end
261
else begin
262
 
263
        did_branchback0 <= take_branch0;
264
        did_branchback1 <= take_branch1;
265
 
266
        stompedRet = FALSE;
267
 
268
        begin
269
 
270
        // On a branch miss with threading enabled all fectch buffers are
271
        // invalidated even though the data in the fetch buffer would be valid
272
        // for the thread that isn't in a branchmiss state. This is done to
273
        // keep things simple. For the thread that doesn't miss the current
274
        // data for the fetch buffer needs to be retrieved again, so the pc
275
        // for that thread is assigned the current fetchbuf pc.
276
        // For the thread that misses the pc is simply assigned the misspc.
277
        if (branchmiss) begin
278
                if (thread_en) begin
279
                        if (branchmiss_thrd) begin
280
                        pc0 <= fetchbuf0_pc;
281
                                pc1 <= misspc;
282
                        end
283
                        else begin
284
                                pc0 <= misspc;
285
                        pc1 <= fetchbuf1_pc;
286
                end
287
                end
288
                else begin
289
                        pc0 <= misspc;
290
                pc1 <= misspc + 32'd4;
291
        end
292
                fetchbufA_v <= `INV;
293
                fetchbufB_v <= `INV;
294
                fetchbufC_v <= `INV;
295
                fetchbufD_v <= `INV;
296
                fetchbuf <= 1'b0;
297
             $display("********************");
298
             $display("********************");
299
             $display("********************");
300
             $display("Branch miss");
301
             $display("misspc=%h", misspc);
302
             $display("********************");
303
             $display("********************");
304
             $display("********************");
305
        end
306
        // Some of the testing for valid branch conditions has been removed. In real
307
        // hardware it isn't needed, and just increases the size of the core. It's
308
        // assumed that the hardware is working.
309
        // The risk is an error will occur during simulation and go missed.
310
        else if (take_branch) begin
311
 
312
            // update the fetchbuf valid bits as well as fetchbuf itself
313
            // ... this must be based on which things are backwards branches, how many things
314
            // will get enqueued (0, 1, or 2), and how old the instructions are
315
            if (fetchbuf == 1'b0) case ({fetchbufA_v, fetchbufB_v, fetchbufC_v, fetchbufD_v})
316
 
317
                4'b0000 : ;     // do nothing
318
//              4'b0001 : panic <= `PANIC_INVALIDFBSTATE;
319
//              4'b0010 : panic <= `PANIC_INVALIDFBSTATE;
320
//              4'b0011 : panic <= `PANIC_INVALIDFBSTATE;       // this looks like it might be screwy fetchbuf logic
321
 
322
                // because the first instruction has been enqueued, 
323
                // we must have noted this in the previous cycle.
324
                // therefore, pc0 and pc1 have to have been set appropriately ... so do a regular fetch
325
                // this looks like the following:
326
                //   cycle 0 - fetched a INSTR+BEQ, with fbB holding a branchback
327
                //   cycle 1 - enqueued fbA, stomped on fbB, stalled fetch + updated pc0/pc1
328
                //   cycle 2 - where we are now ... fetch the two instructions & update fetchbufB_v appropriately
329
                4'b0100 :
330
                    begin
331
                            FetchCD();
332
                             fetchbufB_v <= !(queued1|queuedNop);       // if it can be queued, it will
333
                              fetchbuf <= fetchbuf + (queued1|queuedNop);
334
                        end
335
 
336
                // Can occur with threading enabled
337
                4'b0101:
338
                        fetchbufB_v <= !(queued1|queuedNop);
339
 
340
//              4'b0101 : panic <= `PANIC_INVALIDFBSTATE;
341
//              4'b0110 : panic <= `PANIC_INVALIDFBSTATE;
342
 
343
                // this looks like the following:
344
                //   cycle 0 - fetched an INSTR+BEQ, with fbB holding a branchback
345
                //   cycle 1 - enqueued fbA, but not fbB, recognized branchback in fbB, stalled fetch + updated pc0/pc1
346
                //   cycle 2 - still could not enqueue fbB, but fetched from backwards target
347
                //   cycle 3 - where we are now ... update fetchbufB_v appropriately
348
                //
349
                // however -- if there are backwards branches in the latter two slots, it is more complex.
350
                // simple solution: leave it alone and wait until we are through with the first two slots.
351
                4'b0111 :
352
                        begin
353
                            fetchbufB_v <= !(queued1|queuedNop);        // if it can be queued, it will
354
                                fetchbuf <= fetchbuf + (queued1|queuedNop);
355
                        end
356
 
357
                // this looks like the following:
358
                //   cycle 0 - fetched a BEQ+INSTR, with fbA holding a branchback
359
                //   cycle 1 - stomped on fbB, but could not enqueue fbA, stalled fetch + updated pc0/pc1
360
                //   cycle 2 - where we are now ... fetch the two instructions & update fetchbufA_v appropriately
361
                4'b1000 :
362
                        begin
363
                            FetchCD();
364
                             fetchbufA_v <= !(queued1|queuedNop);       // if it can be queued, it will
365
                              fetchbuf <= fetchbuf + (queued1|queuedNop);
366
                        end
367
 
368
//              4'b1001 : panic <= `PANIC_INVALIDFBSTATE;
369
//              4'b1010 : panic <= `PANIC_INVALIDFBSTATE;
370
 
371
                // this looks like the following:
372
                //   cycle 0 - fetched a BEQ+INSTR, with fbA holding a branchback
373
                //   cycle 1 - stomped on fbB, but could not enqueue fbA, stalled fetch + updated pc0/pc1
374
                //   cycle 2 - still could not enqueue fbA, but fetched from backwards target
375
                //   cycle 3 - where we are now ... set fetchbufA_v appropriately
376
                //
377
                // however -- if there are backwards branches in the latter two slots, it is more complex.
378
                // simple solution: leave it alone and wait until we are through with the first two slots.
379
                4'b1011 :
380
                        begin
381
                             fetchbufA_v <=!(queued1|queuedNop);        // if it can be queued, it will
382
                              fetchbuf <= fetchbuf + (queued1|queuedNop);
383
                        end
384
 
385
                // if fbB has the branchback, can't immediately tell which of the following scenarios it is:
386
                //   cycle 0 - fetched a pair of instructions, one or both of which is a branchback
387
                //   cycle 1 - where we are now.  stomp, enqueue, and update pc0/pc1
388
                // or
389
                //   cycle 0 - fetched a INSTR+BEQ, with fbB holding a branchback
390
                //   cycle 1 - could not enqueue fbA or fbB, stalled fetch + updated pc0/pc1
391
                //   cycle 2 - where we are now ... fetch the two instructions & update fetchbufX_v appropriately
392
                // if fbA has the branchback, then it is scenario 1.
393
                // if fbB has it: if pc0 == fbB_pc, then it is the former scenario, else it is the latter
394
                4'b1100 : begin
395
                        if(thread_en) begin
396
                                if (take_branchA && take_branchB) begin
397
                                        pc0 <= branch_pcA;
398
                                        pc1 <= branch_pcB;
399
                                        fetchbufA_v <= !(queued1|queuedNop);    // if it can be queued, it will
400
                                        fetchbufB_v <= !(queued2|queuedNop);    // if it can be queued, it will
401
                                        if ((queued2|queuedNop))   fetchbuf <= 1'b1;
402
                                end
403
                                else if (take_branchA) begin
404
                                        pc0 <= branch_pcA;
405
                                        fetchbufA_v <= !(queued1|queuedNop);    // if it can be queued, it will
406
                                        fetchbufB_v <= !(queued2|queuedNop);    // if it can be queued, it will
407
                                        if ((queued2|queuedNop))   fetchbuf <= 1'b1;
408
                                end
409
                                else if (take_branchB) begin
410
                                        pc1 <= branch_pcB;
411
                                        fetchbufA_v <= !(queued1|queuedNop);    // if it can be queued, it will
412
                                        fetchbufB_v <= !(queued2|queuedNop);    // if it can be queued, it will
413
                                        if ((queued2|queuedNop))   fetchbuf <= 1'b1;
414
                                end
415
                        end
416
                        else
417
                        begin
418
                                if (take_branchA) begin
419
                                    // has to be first scenario
420
                                        pc0 <= branch_pcA;
421
                                        pc1 <= branch_pcA + 4;
422
                                    fetchbufA_v <= !(queued1|queuedNop);        // if it can be queued, it will
423
                                fetchbufB_v <= `INV;            // stomp on it
424
                                     if (IsRet(fetchbufB_instr))
425
                                        stompedRet = `TRUE;
426
                                        if ((queued1|queuedNop))   fetchbuf <= 1'b1;
427
                                end
428
                                else if (take_branchB) begin
429
                                    if (did_branchback0) begin
430
                                    FetchCD();
431
                                         fetchbufA_v <= !(queued1|queuedNop);   // if it can be queued, it will
432
                                         fetchbufB_v <= !(queued2|queuedNop);   // if it can be queued, it will
433
                                          fetchbuf <= fetchbuf + (queued2|queuedNop);
434
                                    end
435
                                    else begin
436
                                                pc0 <= branch_pcB;
437
                                                pc1 <= branch_pcB + 4;
438
                                         fetchbufA_v <= !(queued1|queuedNop);   // if it can be queued, it will
439
                                         fetchbufB_v <= !(queued2|queuedNop);   // if it can be queued, it will
440
                                        if ((queued2|queuedNop))   fetchbuf <= 1'b1;
441
                                    end
442
                                end
443
                        end
444
//                      else panic <= `PANIC_BRANCHBACK;
445
                    end
446
 
447
//              4'b1101 : panic <= `PANIC_INVALIDFBSTATE;
448
//              4'b1110 : panic <= `PANIC_INVALIDFBSTATE;
449
 
450
                // this looks like the following:
451
                //   cycle 0 - fetched an INSTR+BEQ, with fbB holding a branchback
452
                //   cycle 1 - enqueued neither fbA nor fbB, recognized branchback in fbB, stalled fetch + updated pc0/pc1
453
                //   cycle 2 - still could not enqueue fbB, but fetched from backwards target
454
                //   cycle 3 - where we are now ... update fetchbufX_v appropriately
455
                //
456
                // however -- if there are backwards branches in the latter two slots, it is more complex.
457
                // simple solution: leave it alone and wait until we are through with the first two slots.
458
                4'b1111 :
459
                        begin
460
                             fetchbufA_v <= !(queued1|queuedNop);       // if it can be queued, it will
461
                             fetchbufB_v <= !(queued2|queuedNop);       // if it can be queued, it will
462
                              fetchbuf <= fetchbuf + (queued2|queuedNop);
463
                        end
464
        default:    ;
465
            endcase
466
            else case ({fetchbufC_v, fetchbufD_v, fetchbufA_v, fetchbufB_v})
467
 
468
                4'b0000 : ; // do nothing
469
//              4'b0001 : panic <= `PANIC_INVALIDFBSTATE;
470
//              4'b0010 : panic <= `PANIC_INVALIDFBSTATE;
471
//              4'b0011 : panic <= `PANIC_INVALIDFBSTATE;       // this looks like it might be screwy fetchbuf logic
472
 
473
                // because the first instruction has been enqueued, 
474
                // we must have noted this in the previous cycle.
475
                // therefore, pc0 and pc1 have to have been set appropriately ... so do a regular fetch
476
                // this looks like the following:
477
                //   cycle 0 - fetched a INSTR+BEQ, with fbD holding a branchback
478
                //   cycle 1 - enqueued fbC, stomped on fbD, stalled fetch + updated pc0/pc1
479
                //   cycle 2 - where we are now ... fetch the two instructions & update fetchbufB_v appropriately
480
                4'b0100 :
481
                        begin
482
                            FetchAB();
483
                             fetchbufD_v <= !(queued1|queuedNop);       // if it can be queued, it will
484
                              fetchbuf <= fetchbuf + (queued1|queuedNop);
485
                        end
486
 
487
                4'b0101:
488
                        fetchbufD_v <= !(queued1|queuedNop);
489
 
490
//              4'b0101 : panic <= `PANIC_INVALIDFBSTATE;
491
//              4'b0110 : panic <= `PANIC_INVALIDFBSTATE;
492
 
493
                // this looks like the following:
494
                //   cycle 0 - fetched an INSTR+BEQ, with fbD holding a branchback
495
                //   cycle 1 - enqueued fbC, but not fbD, recognized branchback in fbD, stalled fetch + updated pc0/pc1
496
                //   cycle 2 - still could not enqueue fbD, but fetched from backwards target
497
                //   cycle 3 - where we are now ... update fetchbufD_v appropriately
498
                //
499
                // however -- if there are backwards branches in the latter two slots, it is more complex.
500
                // simple solution: leave it alone and wait until we are through with the first two slots.
501
                4'b0111 :
502
                        begin
503
                             fetchbufD_v <= !(queued1|queuedNop);       // if it can be queued, it will
504
                              fetchbuf <= fetchbuf + (queued1|queuedNop);
505
                        end
506
 
507
                // this looks like the following:
508
                //   cycle 0 - fetched a BEQ+INSTR, with fbC holding a branchback
509
                //   cycle 1 - stomped on fbD, but could not enqueue fbC, stalled fetch + updated pc0/pc1
510
                //   cycle 2 - where we are now ... fetch the two instructions & update fetchbufC_v appropriately
511
                4'b1000 :
512
                        begin
513
                            FetchAB();
514
                             fetchbufC_v <= !(queued1|queuedNop);       // if it can be queued, it will
515
                              fetchbuf <= fetchbuf + (queued1|queuedNop);
516
                        end
517
 
518
//              4'b1001 : panic <= `PANIC_INVALIDFBSTATE;
519
//              4'b1010 : panic <= `PANIC_INVALIDFBSTATE;
520
 
521
                // this looks like the following:
522
                //   cycle 0 - fetched a BEQ+INSTR, with fbC holding a branchback
523
                //   cycle 1 - stomped on fbD, but could not enqueue fbC, stalled fetch + updated pc0/pc1
524
                //   cycle 2 - still could not enqueue fbC, but fetched from backwards target
525
                //   cycle 3 - where we are now ... set fetchbufC_v appropriately
526
                //
527
                // however -- if there are backwards branches in the latter two slots, it is more complex.
528
                // simple solution: leave it alone and wait until we are through with the first two slots.
529
                4'b1011 :
530
                        begin
531
                             fetchbufC_v <= !(queued1|queuedNop);       // if it can be queued, it will
532
                              fetchbuf <= fetchbuf + (queued1|queuedNop);
533
                        end
534
 
535
                // if fbD has the branchback, can't immediately tell which of the following scenarios it is:
536
                //   cycle 0 - fetched a pair of instructions, one or both of which is a branchback
537
                //   cycle 1 - where we are now.  stomp, enqueue, and update pc0/pc1
538
                // or
539
                //   cycle 0 - fetched a INSTR+BEQ, with fbD holding a branchback
540
                //   cycle 1 - could not enqueue fbC or fbD, stalled fetch + updated pc0/pc1
541
                //   cycle 2 - where we are now ... fetch the two instructions & update fetchbufX_v appropriately
542
                // if fbC has the branchback, then it is scenario 1.
543
                // if fbD has it: if pc0 == fbB_pc, then it is the former scenario, else it is the latter
544
                4'b1100 : begin
545
 
546
                        if(thread_en) begin
547
                                if (take_branchC & take_branchD) begin
548
                                        pc0 <= branch_pcC;
549
                                        pc1 <= branch_pcD;
550
                                        fetchbufC_v <= !(queued1|queuedNop);    // if it can be queued, it will
551
                                        fetchbufD_v <= !(queued2|queuedNop);    // if it can be queued, it will
552
                                    if ((queued2|queuedNop))   fetchbuf <= 1'b0;
553
                                end
554
                                else if (take_branchC) begin
555
                                        pc0 <= branch_pcC;
556
                                        fetchbufC_v <= !(queued1|queuedNop);    // if it can be queued, it will
557
                                        fetchbufD_v <= !(queued2|queuedNop);    // if it can be queued, it will
558
                                    if ((queued2|queuedNop))   fetchbuf <= 1'b0;
559
                                end
560
                                else if (take_branchD) begin
561
                                        pc1 <= branch_pcD;
562
                                        fetchbufC_v <= !(queued1|queuedNop);    // if it can be queued, it will
563
                                        fetchbufD_v <= !(queued2|queuedNop);    // if it can be queued, it will
564
                                    if ((queued2|queuedNop))   fetchbuf <= 1'b0;
565
                                end
566
                        end
567
                        else
568
                        begin
569
                                if (take_branchC) begin
570
                                         pc0 <= branch_pcC;
571
                                         pc1 <= branch_pcC + 4;
572
                                     fetchbufC_v <= !(queued1|queuedNop);       // if it can be queued, it will
573
                                     fetchbufD_v <= `INV;               // stomp on it
574
                                     if (IsRet(fetchbufD_instr))
575
                                        stompedRet = `TRUE;
576
                                    if ((queued1|queuedNop))   fetchbuf <= 1'b0;
577
                                end
578
                                else if (take_branchD) begin
579
                                    if (did_branchback1) begin
580
                                    FetchAB();
581
                                         fetchbufC_v <= !(queued1|queuedNop);   // if it can be queued, it will
582
                                         fetchbufD_v <= !(queued2|queuedNop);   // if it can be queued, it will
583
                                         fetchbuf <= fetchbuf + (queued2|queuedNop);
584
                                    end
585
                                    else begin
586
                                                 pc0 <= branch_pcD;
587
                                                 pc1 <= branch_pcD + 4;
588
                                         fetchbufC_v <= !(queued1|queuedNop);   // if it can be queued, it will
589
                                         fetchbufD_v <= !(queued2|queuedNop);   // if it can be queued, it will
590
                                        if ((queued2|queuedNop))   fetchbuf <= 1'b0;
591
                                    end
592
                                end
593
                        end
594
//                      else panic <= `PANIC_BRANCHBACK;
595
                    end
596
 
597
//              4'b1101 : panic <= `PANIC_INVALIDFBSTATE;
598
//              4'b1110 : panic <= `PANIC_INVALIDFBSTATE;
599
 
600
                // this looks like the following:
601
                //   cycle 0 - fetched an INSTR+BEQ, with fbD holding a branchback
602
                //   cycle 1 - enqueued neither fbC nor fbD, recognized branchback in fbD, stalled fetch + updated pc0/pc1
603
                //   cycle 2 - still could not enqueue fbD, but fetched from backwards target
604
                //   cycle 3 - where we are now ... update fetchbufX_v appropriately
605
                //
606
                // however -- if there are backwards branches in the latter two slots, it is more complex.
607
                // simple solution: leave it alone and wait until we are through with the first two slots.
608
                4'b1111 :
609
                        begin
610
                             fetchbufC_v <= !(queued1|queuedNop);       // if it can be queued, it will
611
                             fetchbufD_v <= !(queued2|queuedNop);       // if it can be queued, it will
612
                              fetchbuf <= fetchbuf + (queued2|queuedNop);
613
                        end
614
            default:   ;
615
            endcase
616
 
617
        end // if branchback
618
 
619
        else begin      // there is no branchback in the system
620
            //
621
            // update fetchbufX_v and fetchbuf ... relatively simple, as
622
            // there are no backwards branches in the mix
623
            if (fetchbuf == 1'b0) case ({fetchbufA_v, fetchbufB_v, (queued1|queuedNop), (queued2|queuedNop)})
624
                4'b00_00 : ;    // do nothing
625
//              4'b00_01 : panic <= `PANIC_INVALIDIQSTATE;
626
                4'b00_10 : ;    // do nothing
627
                4'b00_11 : ;    // do nothing
628
                4'b01_00 : ;    // do nothing
629
//              4'b01_01 : panic <= `PANIC_INVALIDIQSTATE;
630
 
631
                4'b01_10,
632
                4'b01_11 : begin        // enqueue fbB and flip fetchbuf
633
                         fetchbufB_v <= `INV;
634
                          fetchbuf <= ~fetchbuf;
635
                    end
636
 
637
                4'b10_00 : ;    // do nothing
638
//              4'b10_01 : panic <= `PANIC_INVALIDIQSTATE;
639
 
640
                4'b10_10,
641
                4'b10_11 : begin        // enqueue fbA and flip fetchbuf
642
                         fetchbufA_v <= `INV;
643
                          fetchbuf <= ~fetchbuf;
644
                    end
645
 
646
                4'b11_00 : ;    // do nothing
647
//              4'b11_01 : panic <= `PANIC_INVALIDIQSTATE;
648
 
649
                4'b11_10 : begin        // enqueue fbA but leave fetchbuf
650
                         fetchbufA_v <= `INV;
651
                    end
652
 
653
                4'b11_11 : begin        // enqueue both and flip fetchbuf
654
                         fetchbufA_v <= `INV;
655
                         fetchbufB_v <= `INV;
656
                          fetchbuf <= ~fetchbuf;
657
                    end
658
                default:  ;
659
            endcase
660
            else case ({fetchbufC_v, fetchbufD_v, (queued1|queuedNop), (queued2|queuedNop)})
661
                4'b00_00 : ;    // do nothing
662
//              4'b00_01 : panic <= `PANIC_INVALIDIQSTATE;
663
                4'b00_10 : ;    // do nothing
664
                4'b00_11 : ;    // do nothing
665
                4'b01_00 : ;    // do nothing
666
//              4'b01_01 : panic <= `PANIC_INVALIDIQSTATE;
667
 
668
                4'b01_10,
669
                4'b01_11 : begin        // enqueue fbD and flip fetchbuf
670
                         fetchbufD_v <= `INV;
671
                          fetchbuf <= ~fetchbuf;
672
                    end
673
 
674
                4'b10_00 : ;    // do nothing
675
//              4'b10_01 : panic <= `PANIC_INVALIDIQSTATE;
676
 
677
                4'b10_10,
678
                4'b10_11 : begin        // enqueue fbC and flip fetchbuf
679
                         fetchbufC_v <= `INV;
680
                          fetchbuf <= ~fetchbuf;
681
                    end
682
 
683
                4'b11_00 : ;    // do nothing
684
//              4'b11_01 : panic <= `PANIC_INVALIDIQSTATE;
685
 
686
                4'b11_10 : begin        // enqueue fbC but leave fetchbuf
687
                         fetchbufC_v <= `INV;
688
                    end
689
 
690
                4'b11_11 : begin        // enqueue both and flip fetchbuf
691
                         fetchbufC_v <= `INV;
692
                         fetchbufD_v <= `INV;
693
                          fetchbuf <= ~fetchbuf;
694
                    end
695
                default:  ;
696
            endcase
697
            //
698
            // get data iff the fetch buffers are empty
699
            //
700
            if (fetchbufA_v == `INV && fetchbufB_v == `INV) begin
701
                FetchAB();
702
                // fetchbuf steering logic correction
703
                if (fetchbufC_v==`INV && fetchbufD_v==`INV && phit)
704
                      fetchbuf <= 1'b0;
705
            end
706
            else if (fetchbufC_v == `INV && fetchbufD_v == `INV)
707
                    FetchCD();
708
        end
709
    //
710
    // get data iff the fetch buffers are empty
711
    //
712
    if (fetchbufA_v == `INV && fetchbufB_v == `INV && fetchbufC_v==`INV && fetchbufD_v==`INV) begin
713
        FetchAB();
714
         fetchbuf <= 1'b0;
715
    end
716
        end
717
 
718
        // The fetchbuffer is invalidated at the end of a vector instruction
719
        // queue.
720
        if (nop_fetchbuf[0])  fetchbufA_v <= `INV;
721
        if (nop_fetchbuf[1])  fetchbufB_v <= `INV;
722
        if (nop_fetchbuf[2])  fetchbufC_v <= `INV;
723
        if (nop_fetchbuf[3])  fetchbufD_v <= `INV;
724
end
725
 
726
assign fetchbuf0_instr = (fetchbuf == 1'b0) ? fetchbufA_instr : fetchbufC_instr;
727
assign fetchbuf0_v     = (fetchbuf == 1'b0) ? fetchbufA_v     : fetchbufC_v    ;
728
assign fetchbuf0_pc    = (fetchbuf == 1'b0) ? fetchbufA_pc    : fetchbufC_pc   ;
729
assign fetchbuf1_instr = (fetchbuf == 1'b0) ? fetchbufB_instr : fetchbufD_instr;
730
assign fetchbuf1_v     = (fetchbuf == 1'b0) ? fetchbufB_v     : fetchbufD_v    ;
731
assign fetchbuf1_pc    = (fetchbuf == 1'b0) ? fetchbufB_pc    : fetchbufD_pc   ;
732
assign fetchbuf0_thrd  = 1'b0;
733
assign fetchbuf1_thrd  = thread_en ? 1'b1 : 1'b0;
734
 
735
task FetchA;
736
begin
737
    if (insn0[`INSTRUCTION_OP]==`EXEC)
738
         fetchbufA_instr <= codebuf0;
739
    else
740
         fetchbufA_instr <= insn0;
741
     fetchbufA_v <= `VAL;
742
     fetchbufA_pc <= pc0;
743
    if (phit && ~hirq)
744
            pc0 <= pc0 + (thread_en ? 4 : 8);
745
end
746
endtask
747
 
748
task FetchB;
749
begin
750
    if (insn1[`INSTRUCTION_OP]==`EXEC)
751
         fetchbufB_instr <= codebuf1;
752
    else
753
         fetchbufB_instr <= insn1;
754
     fetchbufB_v <= `VAL;
755
     fetchbufB_pc <= pc1;
756
    if (phit && (~hirq || thread_en))
757
                pc1 <= pc1 + (thread_en ? 4 : 8);
758
end
759
endtask
760
 
761
 
762
task FetchAB;
763
begin
764
        FetchA();
765
        FetchB();
766
end
767
endtask
768
 
769
task FetchC;
770
begin
771
    if (insn0[`INSTRUCTION_OP]==`EXEC)
772
         fetchbufC_instr <= codebuf0;
773
    else
774
         fetchbufC_instr <= insn0;
775
     fetchbufC_v <= `VAL;
776
     fetchbufC_pc <= pc0;
777
    if (phit && ~hirq)
778
            pc0 <= pc0 + (thread_en ? 4 : 8);
779
end
780
endtask
781
 
782
task FetchD;
783
begin
784
    if (insn1[`INSTRUCTION_OP]==`EXEC)
785
         fetchbufD_instr <= codebuf1;
786
    else
787
         fetchbufD_instr <= insn1;
788
     fetchbufD_v <= `VAL;
789
     fetchbufD_pc <= pc1;
790
    if (phit && (~hirq || thread_en))
791
                pc1 <= pc1 + (thread_en ? 4 : 8);
792
end
793
endtask
794
 
795
task FetchCD;
796
begin
797
        FetchC();
798
        FetchD();
799
end
800
endtask
801
 
802
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.