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

Subversion Repositories thor

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

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

powered by: WebSVN 2.1.0

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