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

Subversion Repositories thor

[/] [thor/] [trunk/] [FT64v7/] [rtl/] [twoway/] [FT64_fetchbuf_x1.v] - Blame information for rev 66

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 60 robfinch
// ============================================================================
2
//        __
3 61 robfinch
//   \\__/ o\    (C) 2018-2019  Robert Finch, Waterloo
4 60 robfinch
//    \  __ /    All rights reserved.
5
//     \/_//     robfinch<remove>@finitron.ca
6
//       ||
7
//
8
//      FT64_fetchbuf_x1.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_config.vh"
26
`include "FT64_defines.vh"
27
 
28
// FETCH
29
//
30
// fetch exactly one 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
//
34
module FT64_fetchbuf_x1(rst, clk4x, clk, fcu_clk,
35
        cs_i, cyc_i, stb_i, ack_o, we_i, adr_i, dat_i,
36
        cmpgrp,
37
        freezePC, thread_en, pred_on,
38
        regLR,
39
  insn0, phit,
40
  threadx,
41
  branchmiss, misspc, branchmiss_thrd, predict_taken0,
42
  predict_takenA, predict_takenB,
43
  queued1, queuedNop,
44
  pc0, fetchbuf, fetchbufA_v, fetchbufB_v,
45
  fetchbufA_instr, fetchbufA_pc, fetchbufA_pbyte,
46
  fetchbufB_instr, fetchbufB_pc, fetchbufB_pbyte,
47
  fetchbuf0_instr, fetchbuf0_insln,
48
  fetchbuf0_thrd,
49
  fetchbuf0_pc,
50
  fetchbuf0_v,
51
  fetchbuf0_pbyte,
52
  codebuf0,
53
  btgtA, btgtB,
54
  nop_fetchbuf,
55
  take_branch0,
56
  stompedRets,
57
  panic
58
);
59
parameter AMSB = `AMSB;
60
parameter RSTPC = 64'hFFFFFFFFFFFC0100;
61
parameter TRUE = 1'b1;
62
parameter FALSE = 1'b0;
63
input rst;
64
input clk4x;
65
input clk;
66
input fcu_clk;
67
input cs_i;
68
input cyc_i;
69
input stb_i;
70
output ack_o;
71
input we_i;
72
input [15:0] adr_i;
73
input [55:0] dat_i;
74
input [2:0] cmpgrp;
75
input freezePC;
76
input thread_en;
77
input pred_on;
78
input [4:0] regLR;
79
input [55:0] insn0;
80
input phit;
81
output threadx;
82
input branchmiss;
83
input [AMSB:0] misspc;
84
input branchmiss_thrd;
85
output predict_taken0;
86
input predict_takenA;
87
input predict_takenB;
88
input queued1;
89
input queuedNop;
90
output reg [AMSB:0] pc0;
91
output reg fetchbuf;
92
output reg fetchbufA_v;
93
output reg fetchbufB_v;
94
output fetchbuf0_thrd;
95
output reg [47:0] fetchbufA_instr;
96
output reg [7:0] fetchbufA_pbyte;
97
output reg [47:0] fetchbufB_instr;
98
output reg [7:0] fetchbufB_pbyte;
99
output reg [AMSB:0] fetchbufA_pc;
100
output reg [AMSB:0] fetchbufB_pc;
101
output [47:0] fetchbuf0_instr;
102
output [AMSB:0] fetchbuf0_pc;
103
output [2:0] fetchbuf0_insln;
104
output fetchbuf0_v;
105
output [7:0] fetchbuf0_pbyte;
106
input [55:0] codebuf0;
107
input [AMSB:0] btgtA;
108
input [AMSB:0] btgtB;
109
input [3:0] nop_fetchbuf;
110
output take_branch0;
111
input [3:0] stompedRets;
112
output reg [3:0] panic;
113
integer n;
114
 
115
reg [55:0] cinsn0;
116
 
117 66 robfinch
wire iclk = clk;
118
//BUFH ucb1 (.I(clk), .O(iclk));
119
 
120 60 robfinch
//`include "FT64_decode.vh"
121
 
122
function IsBranch;
123
input [47:0] isn;
124
casex(isn[`INSTRUCTION_OP])
125
`Bcc:   IsBranch = TRUE;
126 61 robfinch
`BLcc:  IsBranch = TRUE;
127 60 robfinch
`BBc:   IsBranch = TRUE;
128
`BEQI:  IsBranch = TRUE;
129 61 robfinch
`BNEI:  IsBranch = TRUE;
130 60 robfinch
`BCHK:  IsBranch = TRUE;
131
default: IsBranch = FALSE;
132
endcase
133
endfunction
134
 
135
function IsJAL;
136
input [47:0] isn;
137
IsJAL = isn[`INSTRUCTION_OP]==`JAL;
138
endfunction
139
 
140
function IsJmp;
141
input [47:0] isn;
142 61 robfinch
IsJmp = isn[`INSTRUCTION_OP]==`JMP && isn[7]==1'b0;
143 60 robfinch
endfunction
144
 
145
function IsCall;
146
input [47:0] isn;
147 61 robfinch
IsCall = isn[`INSTRUCTION_OP]==`CALL && isn[7]==1'b0;
148 60 robfinch
endfunction
149
 
150
function IsRet;
151
input [47:0] isn;
152
IsRet = isn[`INSTRUCTION_OP]==`RET;
153
endfunction
154
 
155
function IsBrk;
156
input [47:0] isn;
157
IsBrk = isn[`INSTRUCTION_OP]==`BRK;
158
endfunction
159
 
160
function IsRTI;
161
input [47:0] isn;
162
IsRTI = isn[`INSTRUCTION_OP]==`R2 && isn[`INSTRUCTION_S2]==`RTI;
163
endfunction
164
 
165 61 robfinch
function IsExec;
166
input [47:0] isn;
167
if (isn[7:6]==2'b00)
168
        case(isn[`INSTRUCTION_OP])
169
        `R2:
170
                case(isn[`INSTRUCTION_S2])
171
                `R1:
172
                        case(isn[22:18])
173
                        `EXEC:  IsExec = TRUE;
174
                        default:        IsExec = FALSE;
175
                        endcase
176
                default:        IsExec = FALSE;
177
                endcase
178
        default:        IsExec = FALSE;
179
        endcase
180
else
181
        IsExec = FALSE;
182
endfunction
183
 
184 60 robfinch
function [2:0] fnInsLength;
185
input [47:0] ins;
186
`ifdef SUPPORT_DCI
187
if (ins[`INSTRUCTION_OP]==`CMPRSSD)
188
        fnInsLength = 3'd2 | pred_on;
189
else
190
`endif
191
        case(ins[7:6])
192
        2'd0:   fnInsLength = 3'd4 | pred_on;
193
        2'd1:   fnInsLength = 3'd6 | pred_on;
194
        default:        fnInsLength = 3'd2 | pred_on;
195
        endcase
196
endfunction
197
 
198
wire [2:0] fetchbufA_inslen;
199
wire [2:0] fetchbufB_inslen;
200
FT64_InsLength uilA (fetchbufA_instr, fetchbufA_inslen, pred_on);
201
FT64_InsLength uilB (fetchbufB_instr, fetchbufB_inslen, pred_on);
202
 
203
wire [47:0] xinsn0;
204
 
205
FT64_iexpander ux1
206
(
207
        .cinstr(pred_on ? insn0[23:8] : insn0[15:0]),
208
        .expand(xinsn0)
209
);
210
 
211
 
212
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
213
// Table of decompressed instructions.
214
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
215
assign ack_o = cs_i & cyc_i & stb_i;
216
`ifdef SUPPORT_DCI
217
reg [47:0] DecompressTable [0:2047];
218
always @(posedge clk)
219
        if (cs_i & cyc_i & stb_i & we_i)
220
                DecompressTable[adr_i[12:3]] <= dat_i[47:0];
221
wire [47:0] expand0 = DecompressTable[{cmpgrp,pred_on ? insn0[23:16]:insn0[15:8]}];
222
`endif
223
 
224
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
225
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
226
 
227
reg thread;
228
reg stompedRet;
229
reg ret0Counted;
230
wire [AMSB:0] retpc0;
231
 
232
assign predict_taken0 = (fetchbuf==1'b0) ? ({fetchbufA_v, IsBranch(fetchbufA_instr), predict_takenA}  == {`VAL, `TRUE, `TRUE})
233
                                                                                                                                                                 : ({fetchbufB_v, IsBranch(fetchbufB_instr), predict_takenB}  == {`VAL, `TRUE, `TRUE});
234
 
235
reg [AMSB:0] branch_pcA;
236
reg [AMSB:0] branch_pcB;
237
 
238
always @*
239
begin
240
case(fetchbufA_instr[`INSTRUCTION_OP])
241
`RET:           branch_pcA = retpc0;
242
`JMP,`CALL:
243
        begin
244 61 robfinch
`ifdef JMP40
245 60 robfinch
        branch_pcA[39:0] = fetchbufA_instr[6] ? {fetchbufA_instr[47:8]} : {fetchbufA_pc[39:24],fetchbufA_instr[31:8]};
246 61 robfinch
`else
247
        branch_pcA[39:0] = {fetchbufA_pc[39:24],fetchbufA_instr[31:8]};
248
`endif
249 60 robfinch
        branch_pcA[63:40] = fetchbufA_pc[63:40];
250
        end
251
`R2:            branch_pcA = btgtA;     // RTI
252
`BRK,`JAL:      branch_pcA = btgtA;
253
default:
254
        begin
255 61 robfinch
        branch_pcA[31:0] = fetchbufA_pc[31:0] +
256
                ((fetchbufA_instr[7:6]==2'b01) ? {{4{fetchbufA_instr[47]}},fetchbufA_instr[47:23],fetchbufA_instr[17:16],1'b0} : {{20{fetchbufA_instr[31]}},fetchbufA_instr[31:23],fetchbufA_instr[17:16],1'b0});
257 60 robfinch
        branch_pcA[63:32] = fetchbufA_pc[63:32];
258
        end
259
endcase
260
end
261
 
262
always @*
263
begin
264
case(fetchbufB_instr[`INSTRUCTION_OP])
265
`RET:           branch_pcB = retpc0;
266
`JMP,`CALL:
267
        begin
268 61 robfinch
`ifdef JMP40
269 60 robfinch
                branch_pcB[39:0] = fetchbufB_instr[6] ? {fetchbufB_instr[47:8]} : {fetchbufB_pc[39:24],fetchbufB_instr[31:8]};
270 61 robfinch
`else
271
                branch_pcB[39:0] = {fetchbufB_pc[39:24],fetchbufB_instr[31:8]};
272
`endif
273 60 robfinch
                branch_pcB[63:40] = fetchbufB_pc[63:40];
274
        end
275
`R2:            branch_pcB = btgtB;     // RTI
276
`BRK,`JAL:      branch_pcB = btgtB;
277
default:
278
        begin
279 61 robfinch
        branch_pcB[31:0] = fetchbufB_pc[31:0] +
280
                ((fetchbufB_instr[7:6]==2'b01) ? {{4{fetchbufB_instr[47]}},fetchbufB_instr[47:23],fetchbufB_instr[17:16],1'b0} : {{20{fetchbufB_instr[31]}},fetchbufB_instr[31:23],fetchbufB_instr[17:16],1'b0});
281 60 robfinch
        branch_pcB[63:32] = fetchbufB_pc[63:32];
282
        end
283
endcase
284
end
285
 
286
wire take_branchA = ({fetchbufA_v, IsBranch(fetchbufA_instr), predict_takenA}  == {`VAL, `TRUE, `TRUE}) || ((
287
`ifdef FCU_ENH
288
                           IsRet(fetchbufA_instr)
289
                        || IsRTI(fetchbufA_instr)|| IsBrk(fetchbufA_instr) || IsJAL(fetchbufA_instr) ||
290
`endif
291
                           IsJmp(fetchbufA_instr)||IsCall(fetchbufA_instr)) &&
292
                        fetchbufA_v);
293
wire take_branchB = ({fetchbufB_v, IsBranch(fetchbufB_instr), predict_takenB}  == {`VAL, `TRUE, `TRUE}) || ((
294
`ifdef FCU_ENH
295
                           IsRet(fetchbufB_instr)
296
                        || IsRTI(fetchbufB_instr)|| IsBrk(fetchbufB_instr) || IsJAL(fetchbufB_instr) ||
297
`endif
298
                           IsJmp(fetchbufB_instr)||IsCall(fetchbufB_instr)) &&
299
                        fetchbufB_v);
300
 
301
wire take_branch = (fetchbuf==1'b0) ? take_branchA : take_branchB;
302
assign take_branch0 = take_branch;
303
 
304
/*
305
always @*
306
begin
307
        pc0 <= thread_en ? (fetchbuf ? pc0b : pc0a) : pc0a;
308
        pc1 <= thread_en ? (fetchbuf ? pc1b : pc1a) : pc1a;
309
end
310
*/
311
assign threadx = fetchbuf;
312
 
313
`ifdef FCU_ENH
314
FT64_RSB #(AMSB) ursb1
315
(
316
        .rst(rst),
317
        .clk(fcu_clk),
318
        .regLR(regLR),
319
        .queued1(queued1),
320
        .queued2(1'b0),
321
        .fetchbuf0_v(fetchbuf0_v),
322
        .fetchbuf0_pc(fetchbuf0_pc),
323
        .fetchbuf0_instr(fetchbuf0_instr),
324
        .fetchbuf1_v(1'b0),
325
        .fetchbuf1_pc(RSTPC),
326
        .fetchbuf1_instr(`NOP_INSN),
327
        .stompedRets(stompedRets),
328
        .stompedRet(stompedRet),
329
        .pc(retpc0)
330
);
331
 
332
`else
333
assign retpc0 = RSTPC;
334
assign retpc1 = RSTPC;
335
`endif
336
 
337
wire peclk, neclk;
338
edge_det ued1 (.rst(rst), .clk(clk4x), .ce(1'b1), .i(clk), .pe(peclk), .ne(neclk), .ee());
339
 
340
reg did_branch;
341
 
342 66 robfinch
always @(posedge iclk)
343 60 robfinch
if (rst) begin
344
        pc0 <= RSTPC;
345
        fetchbufA_v <= 1'b0;
346
        fetchbufB_v <= 1'b0;
347
        fetchbuf <= 1'b0;
348
        panic <= `PANIC_NONE;
349
        did_branch <= 1'b0;
350
end
351
else begin
352
 
353
        did_branch <= take_branch & ~branchmiss;
354
 
355
        begin
356
 
357
        // On a branch miss with threading enabled all fectch buffers are
358
        // invalidated even though the data in the fetch buffer would be valid
359
        // for the thread that isn't in a branchmiss state. This is done to
360
        // keep things simple. For the thread that doesn't miss the current
361
        // data for the fetch buffer needs to be retrieved again, so the pc
362
        // for that thread is assigned the current fetchbuf pc.
363
        // For the thread that misses the pc is simply assigned the misspc.
364
        if (branchmiss) begin
365
                pc0 <= misspc;
366
                fetchbufA_v <= `INV;
367
                fetchbufB_v <= `INV;
368
                fetchbuf <= 1'b0;
369
                $display("********************");
370
                $display("********************");
371
                $display("********************");
372
                $display("Branch miss");
373
                $display("misspc=%h", misspc);
374
                $display("********************");
375
                $display("********************");
376
                $display("********************");
377
        end
378
//      else if (cinsn0[`INSTRUCTION_OP]==`CALL || cinsn0[`INSTRUCTION_OP]==`JMP) begin
379
//              pc0[31:0] = cinsn0[6] ? {cinsn0[47:8]} : {pc0[31:24],cinsn0[31:8]};
380
//              fetchbufA_v <= `INV;
381
//              fetchbufB_v <= `INV;
382
//              fetchbuf <= 1'b0;
383
//      end
384
        else if (take_branch) begin
385
    if (fetchbuf == 1'b0) begin
386
        // In this case fetchbufA must be valid, or take_branch wouldn't be.
387
        case(fetchbufB_v)
388
        1'b0:
389
                begin
390
                                        pc0 <= branch_pcA;
391
                                  fetchbufA_v <= !(queued1|queuedNop);  // if it can be queued, it will
392
                                  fetchbuf <= (queued1|queuedNop);
393
                end
394
        1'b1:
395
                        if (did_branch) begin
396
                                  fetchbufA_v <= !(queued1|queuedNop);  // if it can be queued, it will
397
                                  fetchbuf <= (queued1|queuedNop);
398
                                  FetchB();
399
                        end
400
                        else
401
                        begin
402
                                        pc0 <= branch_pcA;
403
                                  fetchbufA_v <= !(queued1|queuedNop);  // if it can be queued, it will
404
                                        fetchbufB_v <= `INV;
405
                                  fetchbuf <= (queued1|queuedNop);
406
                        end
407
        endcase
408
                end
409
    else begin
410
        case(fetchbufA_v)
411
        1'b0:
412
                begin
413
                                        pc0 <= branch_pcB;
414
                                  fetchbufB_v <= !(queued1|queuedNop);
415
                                  fetchbuf <= !(queued1|queuedNop);
416
                                end
417
                        1'b1:
418
                                if (did_branch) begin
419
                                  fetchbufB_v <= !(queued1|queuedNop);
420
                                  fetchbuf <= ~(queued1|queuedNop);
421
                                  FetchA();
422
                                end
423
                                else
424
                                begin
425
                                        pc0 <= branch_pcB;
426
                                  fetchbufB_v <= !(queued1|queuedNop);
427
                                        fetchbufA_v <= `INV;
428
                                  fetchbuf <= !(queued1|queuedNop);
429
                                end
430
                        endcase
431
                end
432
        end // if branch
433
 
434
        else begin      // there is no branchback in the system
435
    // update fetchbufX_v and fetchbuf ... relatively simple, as
436
    // there are no backwards branches in the mix
437
          if (fetchbuf == 1'b0) case ({fetchbufA_v, (queued1|queuedNop)})
438
                2'b00: ;        // do nothing
439
                2'b10: ;
440
                2'b11: begin fetchbufA_v <= `INV; fetchbuf <= ~fetchbuf; end
441
                default:  panic <= `PANIC_INVALIDIQSTATE;
442
                endcase
443
          else case ({fetchbufB_v, (queued1|queuedNop)})
444
                2'b00: ;        // do nothing
445
                2'b10: ;
446
                2'b11: begin fetchbufB_v <= `INV; fetchbuf <= ~fetchbuf; end
447
                default:  panic <= `PANIC_INVALIDIQSTATE;
448
                endcase
449
    //
450
    // get data iff the fetch buffers are empty
451
    //
452
    if (fetchbufA_v == `INV) begin
453
        FetchA();
454
        // fetchbuf steering logic correction
455
        if (fetchbufB_v==`INV && phit)
456
          fetchbuf <= 1'b0;
457
    end
458
    else if (fetchbufB_v == `INV) begin
459
            FetchB();
460
          end
461
        end
462
  //
463
  // get data iff the fetch buffers are empty
464
  //
465
  if (fetchbufA_v == `INV && fetchbufB_v == `INV) begin
466
        FetchA();
467
    fetchbuf <= 1'b0;
468
  end
469
//  // Steer fetchbuf to the valid buffer.
470
//  else if (fetchbufB_v == `INV)
471
//      fetchbuf <= 1'b0;
472
//  else if (fetchbufA_v == `INV)
473
//              fetchbuf <= 1'b1;
474
//  else if (fetchbufA_v == `INV) begin
475
//      FetchA();
476
//      end
477
//      else if (fetchbufB_v == `INV) begin
478
//              FetchB();
479
//      end
480
end
481
 
482
        // The fetchbuffer is invalidated at the end of a vector instruction
483
        // queue.
484
        if (nop_fetchbuf[0])  fetchbufA_v <= `INV;
485
        if (nop_fetchbuf[1])  fetchbufB_v <= `INV;
486
end
487
 
488
assign fetchbuf0_instr = (fetchbuf == 1'b0) ? fetchbufA_instr : fetchbufB_instr;
489
assign fetchbuf0_insln = (fetchbuf == 1'b0) ? fetchbufA_inslen: fetchbufB_inslen;
490
assign fetchbuf0_v     = (fetchbuf == 1'b0) ? fetchbufA_v     : fetchbufB_v    ;
491
assign fetchbuf0_pc    = (fetchbuf == 1'b0) ? fetchbufA_pc    : fetchbufB_pc   ;
492
assign fetchbuf0_thrd  = 1'b0;
493
assign fetchbuf0_pbyte = (fetchbuf == 1'b0) ? fetchbufA_pbyte : fetchbufB_pbyte;
494
 
495
reg [2:0] insln0;
496
always @*
497
begin
498
`ifdef SUPPORT_DCI
499
        if (insn0[5:0]==`CMPRSSD)
500
                insln0 <= 3'd2 | pred_on;
501
        else
502
`endif
503 61 robfinch
        if (IsExec(insn0))
504
                insln0 <= fnInsLength(codebuf0);        //???? should be 4?
505 60 robfinch
        else
506
                insln0 <= fnInsLength(insn0);
507
end
508
 
509
 
510
always @*
511
begin
512
`ifdef SUPPORT_DCI
513
        if (insn0[13:8]==`CMPRSSD && pred_on)
514
                cinsn0 <= expand0;
515
        else if (insn0[5:0]==`CMPRSSD && !pred_on)
516
                cinsn0 <= expand0;
517
        else
518
`endif
519 61 robfinch
        if (IsExec(insn0) && !pred_on)
520 60 robfinch
                cinsn0 <= codebuf0;
521 61 robfinch
        else if (IsExec(insn0[55:8]) && pred_on)
522 60 robfinch
                cinsn0 <= codebuf0;
523
        else if (insn0[15] & pred_on)
524
                cinsn0 <= {xinsn0,insn0[7:0]};
525
        else if (insn0[7] & ~pred_on)
526
                cinsn0 <= xinsn0;
527
        else
528
                cinsn0 <= insn0;
529
end
530
 
531
task FetchA;
532
begin
533
        fetchbufA_instr <= pred_on ? cinsn0[55:8] : cinsn0[47:0];
534
        fetchbufA_pbyte = cinsn0[7:0];
535
        fetchbufA_v <= `VAL;
536
        fetchbufA_pc <= pc0;
537
        if (phit && ~freezePC)
538 66 robfinch
                pc0[31:0] <= pc0[31:0] + insln0;
539
//      else
540
//              pc0 <= pc0;
541 60 robfinch
end
542
endtask
543
 
544
task FetchB;
545
begin
546
        fetchbufB_instr <= pred_on ? cinsn0[55:8] : cinsn0[47:0];
547
        fetchbufB_pbyte = cinsn0[7:0];
548
        fetchbufB_v <= `VAL;
549
        fetchbufB_pc <= pc0;
550
        if (phit && ~freezePC)
551 66 robfinch
                pc0[31:0] <= pc0[31:0] + insln0;
552
//      else
553
//              pc0 <= pc0;
554 60 robfinch
end
555
endtask
556
 
557
endmodule

powered by: WebSVN 2.1.0

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