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

Subversion Repositories thor

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

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

powered by: WebSVN 2.1.0

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