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

Subversion Repositories thor

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 57 robfinch
// ============================================================================
2
//        __
3
//   \\__/ o\    (C) 2018  Robert Finch, Waterloo
4
//    \  __ /    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,
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,
46
    fetchbufB_instr, fetchbufB_pc,
47
    fetchbuf0_instr, fetchbuf0_insln,
48
    fetchbuf0_thrd,
49
    fetchbuf0_pc,
50
    fetchbuf0_v,
51
    codebuf0,
52
    btgtA, btgtB,
53
    nop_fetchbuf,
54
    take_branch0,
55
    stompedRets,
56
    panic
57
);
58
parameter AMSB = `AMSB;
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 fcu_clk;
66
input cs_i;
67
input cyc_i;
68
input stb_i;
69
output ack_o;
70
input we_i;
71
input [15:0] adr_i;
72
input [47:0] dat_i;
73
input [2:0] cmpgrp;
74
input freezePC;
75
input thread_en;
76
input [4:0] regLR;
77
input [47:0] insn0;
78
input phit;
79
output threadx;
80
input branchmiss;
81
input [AMSB:0] misspc;
82
input branchmiss_thrd;
83
output predict_taken0;
84
input predict_takenA;
85
input predict_takenB;
86
input queued1;
87
input queuedNop;
88
output reg [AMSB:0] pc0;
89
output reg fetchbuf;
90
output reg fetchbufA_v;
91
output reg fetchbufB_v;
92
output fetchbuf0_thrd;
93
output reg [47:0] fetchbufA_instr;
94
output reg [47:0] fetchbufB_instr;
95
output reg [AMSB:0] fetchbufA_pc;
96
output reg [AMSB:0] fetchbufB_pc;
97
output [47:0] fetchbuf0_instr;
98
output [AMSB:0] fetchbuf0_pc;
99
output [2:0] fetchbuf0_insln;
100
output fetchbuf0_v;
101
input [47:0] codebuf0;
102
input [AMSB:0] btgtA;
103
input [AMSB:0] btgtB;
104
input [3:0] nop_fetchbuf;
105
output take_branch0;
106
input [3:0] stompedRets;
107
output reg [3:0] panic;
108
integer n;
109
 
110
//`include "FT64_decode.vh"
111
 
112
function IsBranch;
113
input [47:0] isn;
114
casex(isn[`INSTRUCTION_OP])
115
`Bcc:   IsBranch = TRUE;
116
`BBc:   IsBranch = TRUE;
117
`BEQI:  IsBranch = TRUE;
118
`BCHK:  IsBranch = TRUE;
119
default: IsBranch = FALSE;
120
endcase
121
endfunction
122
 
123
function IsJmp;
124
input [47:0] isn;
125
IsJmp = isn[`INSTRUCTION_OP]==`JMP;
126
endfunction
127
 
128
function IsCall;
129
input [47:0] isn;
130
IsCall = isn[`INSTRUCTION_OP]==`CALL;
131
endfunction
132
 
133
function IsRet;
134
input [47:0] isn;
135
IsRet = isn[`INSTRUCTION_OP]==`RET;
136
endfunction
137
 
138
function IsRTI;
139
input [47:0] isn;
140
IsRTI = isn[`INSTRUCTION_OP]==`R2 && isn[`INSTRUCTION_S2]==`RTI;
141
endfunction
142
 
143
function [2:0] fnInsLength;
144
input [47:0] ins;
145
`ifdef SUPPORT_DCI
146
if (ins[`INSTRUCTION_OP]==`CMPRSSD)
147
        fnInsLength = 3'd2;
148
else
149
`endif
150
        case(ins[7:6])
151
        2'd0:   fnInsLength = 3'd4;
152
        2'd1:   fnInsLength = 3'd6;
153
        default:        fnInsLength = 3'd2;
154
        endcase
155
endfunction
156
 
157
wire [2:0] fetchbufA_inslen;
158
wire [2:0] fetchbufB_inslen;
159
FT64_InsLength uilA (fetchbufA_instr, fetchbufA_inslen);
160
FT64_InsLength uilB (fetchbufB_instr, fetchbufB_inslen);
161
 
162
wire [47:0] xinsn0;
163
 
164
FT64_iexpander ux1
165
(
166
        .cinstr(insn0[15:0]),
167
        .expand(xinsn0)
168
);
169
 
170
 
171
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
172
// Table of decompressed instructions.
173
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
174
assign ack_o = cs_i & cyc_i & stb_i;
175
`ifdef SUPPORT_DCI
176
reg [47:0] DecompressTable [0:2047];
177
always @(posedge clk)
178
        if (cs_i & cyc_i & stb_i & we_i)
179
                DecompressTable[adr_i[12:3]] <= dat_i[47:0];
180
wire [47:0] expand0 = DecompressTable[{cmpgrp,insn0[15:8]}];
181
`endif
182
 
183
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
184
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
185
 
186
reg thread;
187
reg stompedRet;
188
reg ret0Counted;
189
wire [AMSB:0] retpc0;
190
 
191
reg did_branchback0;
192
 
193
assign predict_taken0 = (fetchbuf==1'b0) ? predict_takenA : predict_takenB;
194
 
195
reg [AMSB:0] branch_pcA;
196
reg [AMSB:0] branch_pcB;
197
 
198
always @*
199
case(fetchbufA_instr[`INSTRUCTION_OP])
200
`RET:           branch_pcA = retpc0;
201
`JMP,`CALL: branch_pcA = fetchbufA_instr[6] ? {fetchbufA_instr[39:8],1'b0} : {fetchbufA_pc[31:25],fetchbufA_instr[31:8],1'b0};
202
`R2:            branch_pcA = btgtA;     // RTI
203
`BRK,`JAL:      branch_pcA = btgtA;
204
default:        branch_pcA = fetchbufA_pc + {{20{fetchbufA_instr[31]}},fetchbufA_instr[31:21],1'b0} + fetchbufA_inslen;
205
endcase
206
 
207
always @*
208
case(fetchbufB_instr[`INSTRUCTION_OP])
209
`RET:           branch_pcB = retpc0;
210
`JMP,`CALL: branch_pcB = fetchbufB_instr[6] ? {fetchbufB_instr[39:8],1'b0} : {fetchbufB_pc[31:25],fetchbufB_instr[31:8],1'b0};
211
`R2:            branch_pcB = btgtB;     // RTI
212
`BRK,`JAL:      branch_pcB = btgtB;
213
default:        branch_pcB = fetchbufB_pc + {{20{fetchbufB_instr[31]}},fetchbufB_instr[31:21],1'b0} + fetchbufB_inslen;
214
endcase
215
 
216
wire take_branchA = ({fetchbufA_v, IsBranch(fetchbufA_instr), predict_takenA}  == {`VAL, `TRUE, `TRUE}) ||
217
                        ((IsRet(fetchbufA_instr)||IsJmp(fetchbufA_instr)||IsCall(fetchbufA_instr)||
218
                        IsRTI(fetchbufA_instr)|| fetchbufA_instr[`INSTRUCTION_OP]==`BRK || fetchbufA_instr[`INSTRUCTION_OP]==`JAL) &&
219
                        fetchbufA_v);
220
wire take_branchB = ({fetchbufB_v, IsBranch(fetchbufB_instr), predict_takenB}  == {`VAL, `TRUE, `TRUE}) ||
221
                        ((IsRet(fetchbufB_instr)|IsJmp(fetchbufB_instr)|IsCall(fetchbufB_instr) ||
222
                        IsRTI(fetchbufB_instr)|| fetchbufB_instr[`INSTRUCTION_OP]==`BRK || fetchbufB_instr[`INSTRUCTION_OP]==`JAL) &&
223
                        fetchbufB_v);
224
 
225
wire take_branch = fetchbuf==1'b0 ? take_branchA : take_branchB;
226
assign take_branch0 = take_branch;
227
 
228
/*
229
always @*
230
begin
231
        pc0 <= thread_en ? (fetchbuf ? pc0b : pc0a) : pc0a;
232
        pc1 <= thread_en ? (fetchbuf ? pc1b : pc1a) : pc1a;
233
end
234
*/
235
assign threadx = fetchbuf;
236
 
237
`ifdef FCU_ENH
238
FT64_RSB #(AMSB) ursb1
239
(
240
        .rst(rst),
241
        .clk(fcu_clk),
242
        .regLR(regLR),
243
        .queued1(queued1),
244
        .queued2(1'b0),
245
        .fetchbuf0_v(fetchbuf0_v),
246
        .fetchbuf0_pc(fetchbuf0_pc),
247
        .fetchbuf0_instr(fetchbuf0_instr),
248
        .fetchbuf1_v(1'b0),
249
        .fetchbuf1_pc(RSTPC),
250
        .fetchbuf1_instr(`NOP_INSN),
251
        .stompedRets(stompedRets),
252
        .stompedRet(stompedRet),
253
        .pc(retpc0)
254
);
255
 
256
`else
257
assign retpc0 = RSTPC;
258
assign retpc1 = RSTPC;
259
`endif
260
 
261
wire peclk, neclk;
262
edge_det ued1 (.rst(rst), .clk(clk4x), .ce(1'b1), .i(clk), .pe(peclk), .ne(neclk), .ee());
263
 
264
always @(posedge clk)
265
if (rst) begin
266
        pc0 <= RSTPC;
267
        fetchbufA_v <= 0;
268
        fetchbufB_v <= 0;
269
        fetchbuf <= 0;
270
        panic <= `PANIC_NONE;
271
end
272
else begin
273
 
274
        did_branchback0 <= take_branch0;
275
 
276
        begin
277
 
278
        // On a branch miss with threading enabled all fectch buffers are
279
        // invalidated even though the data in the fetch buffer would be valid
280
        // for the thread that isn't in a branchmiss state. This is done to
281
        // keep things simple. For the thread that doesn't miss the current
282
        // data for the fetch buffer needs to be retrieved again, so the pc
283
        // for that thread is assigned the current fetchbuf pc.
284
        // For the thread that misses the pc is simply assigned the misspc.
285
        if (branchmiss) begin
286
                $display("***********");
287
                $display("Branch miss");
288
                $display("***********");
289
                pc0 <= misspc;
290
                fetchbufA_v <= `INV;
291
                fetchbufB_v <= `INV;
292
                fetchbuf <= 1'b0;
293
             $display("********************");
294
             $display("********************");
295
             $display("********************");
296
             $display("Branch miss");
297
             $display("misspc=%h", misspc);
298
             $display("********************");
299
             $display("********************");
300
             $display("********************");
301
        end
302
        else if (take_branch) begin
303
    if (fetchbuf == 1'b0) case ({fetchbufA_v, fetchbufB_v})
304
                2'b00: ;        // do nothing
305
//              2'b01   : panic <= `PANIC_INVALIDFBSTATE;
306
                2'b10:
307
                        begin
308
                                pc0 <= branch_pcA;
309
                          fetchbufA_v <= !(queued1|queuedNop);  // if it can be queued, it will
310
                          fetchbuf <= fetchbuf + (queued1|queuedNop);
311
                        end
312
                2'b11:
313
                        begin
314
                                pc0 <= branch_pcA;
315
                                fetchbufA_v <= !(queued1|queuedNop);    // if it can be queued, it will
316
                                fetchbufB_v <= `INV;
317
              fetchbuf <= fetchbuf + (queued1|queuedNop);
318
                        end
319
    default:    ;
320
          endcase
321
    else case ({fetchbufB_v, fetchbufA_v})
322
                2'b00: ; // do nothing
323
                2'b10:
324
                        begin
325
                                pc0 <= branch_pcB;
326
                          fetchbufB_v <= !(queued1|queuedNop);
327
                          fetchbuf <= fetchbuf + (queued1|queuedNop);
328
                        end
329
                2'b11:
330
                        begin
331
                                pc0 <= branch_pcB;
332
                                fetchbufB_v <= !(queued1|queuedNop);
333
                                fetchbufA_v <= `INV;
334
              fetchbuf <= fetchbuf + (queued1|queuedNop);
335
                        end
336
    default:    ;
337
    endcase
338
 
339
        end // if branchback
340
 
341
        else begin      // there is no branchback in the system
342
    // update fetchbufX_v and fetchbuf ... relatively simple, as
343
    // there are no backwards branches in the mix
344
          if (fetchbuf == 1'b0) case ({fetchbufA_v, (queued1|queuedNop)})
345
                2'b00: ;        // do nothing
346
                2'b10: ;
347
                2'b11: begin fetchbufA_v <= `INV; fetchbuf <= ~fetchbuf; end
348
                default:  panic <= `PANIC_INVALIDIQSTATE;
349
                endcase
350
          else case ({fetchbufB_v, (queued1|queuedNop)})
351
                2'b00: ;        // do nothing
352
                2'b10: ;
353
                2'b11: begin fetchbufB_v <= `INV; fetchbuf <= ~fetchbuf; end
354
                default:  panic <= `PANIC_INVALIDIQSTATE;
355
                endcase
356
    //
357
    // get data iff the fetch buffers are empty
358
    //
359
    if (fetchbufA_v == `INV) begin
360
        FetchA();
361
        // fetchbuf steering logic correction
362
        if (fetchbufB_v==`INV && phit)
363
          fetchbuf <= 1'b0;
364
    end
365
    else if (fetchbufB_v == `INV)
366
            FetchB();
367
        end
368
  //
369
  // get data iff the fetch buffers are empty
370
  //
371
  if (fetchbufA_v == `INV && fetchbufB_v == `INV) begin
372
        FetchA();
373
    fetchbuf <= 1'b0;
374
  end
375
end
376
 
377
        // The fetchbuffer is invalidated at the end of a vector instruction
378
        // queue.
379
        if (nop_fetchbuf[0])  fetchbufA_v <= `INV;
380
        if (nop_fetchbuf[1])  fetchbufB_v <= `INV;
381
end
382
 
383
assign fetchbuf0_instr = (fetchbuf == 1'b0) ? fetchbufA_instr : fetchbufB_instr;
384
assign fetchbuf0_insln = (fetchbuf == 1'b0) ? fetchbufA_inslen: fetchbufB_inslen;
385
assign fetchbuf0_v     = (fetchbuf == 1'b0) ? fetchbufA_v     : fetchbufB_v    ;
386
assign fetchbuf0_pc    = (fetchbuf == 1'b0) ? fetchbufA_pc    : fetchbufB_pc   ;
387
assign fetchbuf0_thrd  = 1'b0;
388
 
389
reg [2:0] insln0;
390
always @*
391
begin
392
`ifdef SUPPORT_DCI
393
        if (insn0[5:0]==`CMPRSSD)
394
                insln0 <= 3'd2;
395
        else
396
`endif
397
        if (insn0[7:6]==2'b00 && insn0[`INSTRUCTION_OP]==`EXEC)
398
                insln0 <= fnInsLength(codebuf0);
399
        else
400
                insln0 <= fnInsLength(insn0);
401
end
402
 
403
reg [47:0] cinsn0;
404
 
405
always @*
406
begin
407
`ifdef SUPPORT_DCI
408
        if (insn0[5:0]==`CMPRSSD)
409
                cinsn0 <= expand0;
410
        else
411
`endif
412
        if (insn0[7:6]==2'b00 && insn0[`INSTRUCTION_OP]==`EXEC)
413
                cinsn0 <= codebuf0;
414
        else if (insn0[7])
415
                cinsn0 <= xinsn0;
416
        else
417
                cinsn0 <= insn0;
418
end
419
 
420
task FetchA;
421
begin
422
        fetchbufA_instr <= cinsn0;
423
        fetchbufA_v <= `VAL;
424
        fetchbufA_pc <= pc0;
425
        if (phit && ~freezePC)
426
                pc0 <= pc0 + insln0;
427
end
428
endtask
429
 
430
task FetchB;
431
begin
432
        fetchbufB_instr <= cinsn0;
433
        fetchbufB_v <= `VAL;
434
        fetchbufB_pc <= pc0;
435
        if (phit && ~freezePC)
436
                pc0 <= pc0 + insln0;
437
end
438
endtask
439
 
440
endmodule
441
 

powered by: WebSVN 2.1.0

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