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

Subversion Repositories thor

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

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

powered by: WebSVN 2.1.0

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