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

Subversion Repositories thor

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

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

powered by: WebSVN 2.1.0

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