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

Subversion Repositories thor

[/] [thor/] [trunk/] [FT64v5/] [rtl/] [twoway/] [FT64_fetchbuf.v] - Blame information for rev 52

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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