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

Subversion Repositories rv01_riscv_core

[/] [rv01_riscv_core/] [trunk/] [VHDL/] [RV01_sbuf_2w.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 madsilicon
-----------------------------------------------------------------
2
--                                                             --
3
-----------------------------------------------------------------
4
--                                                             --
5
-- Copyright (C) 2017 Stefano Tonello                          --
6
--                                                             --
7
-- This source file may be used and distributed without        --
8
-- restriction provided that this copyright statement is not   --
9
-- removed from the file and that any derivative work contains --
10
-- the original copyright notice and the associated disclaimer.--
11
--                                                             --
12
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY         --
13
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   --
14
-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   --
15
-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      --
16
-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         --
17
-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    --
18
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   --
19
-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        --
20
-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  --
21
-- LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  --
22
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  --
23
-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         --
24
-- POSSIBILITY OF SUCH DAMAGE.                                 --
25
--                                                             --
26
-----------------------------------------------------------------
27
 
28
---------------------------------------------------------------
29
-- RV01 Store buffer
30
---------------------------------------------------------------
31
 
32
library IEEE;
33
use IEEE.std_logic_1164.all;
34
use IEEE.numeric_std.all;
35
 
36
library work;
37
use work.RV01_CONSTS_PKG.all;
38
use work.RV01_TYPES_PKG.all;
39
use work.RV01_FUNCS_PKG.all;
40
use work.RV01_OP_PKG.all;
41
 
42
entity RV01_SBUF_2W is
43
  generic(
44
    NW : natural := 2;
45
    DEPTH : natural := 4;
46
    SIMULATION_ONLY : std_logic := '0'
47
  );
48
  port(
49
    CLK_i : in std_logic;
50
    RST_i : in std_logic;
51
    CLRB_i : in std_logic; -- clear buffer flag
52
    KTS_i : in std_logic; -- kill top store
53
    RE_i : in std_logic_vector(NW-1 downto 0); -- SB read enable
54
    WE_i : in std_logic_vector(NW-1 downto 0); -- SB write enable
55
    BE0_i : in std_logic_vector(4-1 downto 0); -- inst #0 byte enable
56
    BE1_i : in std_logic_vector(4-1 downto 0); -- inst #1 byte enable
57
    D0_i : in std_logic_vector(SDLEN-1 downto 0); -- inst #0 store data
58
    D1_i : in std_logic_vector(SDLEN-1 downto 0); -- inst #1 store data
59
    IX1_V_i : std_logic_vector(2-1 downto 0);
60
    LS_OP0_i : in LS_OP_T;
61
    LS_OP1_i : in LS_OP_T;
62
    DADR0_i : in ADR_T;
63
    DADR1_i : in ADR_T;
64
    -- just for debugging purpose
65
    SADR0_i : in ADR_T;
66
    SADR1_i : in ADR_T;
67
 
68
    BF_o : out std_logic; -- buffer full flag
69
    NOPR_o : out std_logic; -- no pending reads flag
70
    S2LAC_o : out std_logic_vector(2-1 downto 0); -- store-2-load conflict
71
    WE_o : out std_logic;
72
    LS_OP_o : out LS_OP_T;
73
    BE_o : out std_logic_vector(4-1 downto 0);
74
    Q_o : out std_logic_vector(SDLEN-1 downto 0);
75
    SADR_o : out ADR_T
76
  );
77
end RV01_SBUF_2W;
78
 
79
architecture ARC of RV01_SBUF_2W is
80
 
81
  constant ZERO : std_logic_vector(DEPTH-1 downto 0) := (others => '0');
82
  constant MTCH_WIDTH : natural := 8;
83
 
84
  -- store buffer entry type
85
  type SB_ENTRY_T is record
86
    LS_OP : LS_OP_T;
87
    BE : std_logic_vector(4-1 downto 0);
88
    DATA : std_logic_vector(SDLEN-1 downto 0);
89
    ADR : ADR_T;
90
  end record;
91
 
92
  -- store buffer type
93
  type SB_T is array (natural range<>) of SB_ENTRY_T;
94
 
95
  signal SB,SB_q : SB_T(DEPTH-1 downto 0);
96
  signal SBV_q,SBV : std_logic_vector(DEPTH-1 downto 0);
97
  signal SB_NEW0,SB_NEW1 : SB_ENTRY_T;
98
  signal TP,TP_q : integer range -1 to DEPTH+2;
99
  signal PUSH : std_logic_vector(NW-1 downto 0);
100
  signal POP,BF : std_logic;
101
  signal MTCH0 : std_logic_vector(DEPTH-1 downto 0);
102
  signal MTCH1 : std_logic_vector(DEPTH downto 0);
103
  signal LD0,LD1,ST0,LS0 : std_logic;
104
  signal PR_CNT_q : natural range 0 to DEPTH-1;
105
  signal PR_CNT : integer range -1 to DEPTH+1;
106
  signal S2LAC : std_logic_vector(2-1 downto 0);
107
  signal PRV_q,PRV : std_logic_vector(DEPTH-1 downto 0);
108
 
109
  function wired_or(V : std_logic_vector) return std_logic is
110
    variable WO : std_logic;
111
  begin
112
    WO := '0';
113
    for i in V'LOW to V'HIGH loop
114
      WO := WO or V(i);
115
    end loop;
116
    return(WO);
117
  end function;
118
 
119
begin
120
 
121
  ----------------------------------------------------
122
  -- Notes
123
  ----------------------------------------------------
124
 
125
  -- Store buffer is organised like a queue which is
126
  -- written when a store reaches IX1 stage and read
127
  -- when a store reaches IX3 stage (but only if memory
128
  -- write port is not occupied by an active load, in 
129
  -- order to minimize pipe stalls).
130
 
131
  -- Buffered stores are always read from entry zero
132
  -- and written on entry pointed by TP_q (the tail
133
  -- pointer).
134
 
135
  -- In order to detect store-to-load conflicts, both
136
  -- load addresses must be compared against buffered
137
  -- store addresses. In addition, IX1 instruction #1
138
  -- load address must be compared to IX1 instruction
139
  -- #0 store adddress.
140
  -- When a conflict is detected, the involved store
141
  -- must be allowed to proceed in order to remove
142
  -- the conflict. If the store is buffered, a buffer
143
  -- read is forced, while, if it's still in IX1 , 
144
  -- it's allowed to move to next pipe stages.
145
 
146
  -- CLRB_i and NOPR_o signals have been added to
147
  -- support exception processing: CLRB_i allows to
148
  -- empty the buffer when an exception is raised and
149
  -- NOPR_o tells exception logic that is safe to raise
150
  -- exceptions because stores eventually remaining in
151
  -- the buffer are newer than IX3 instructions ready
152
  -- to raise exceptions.
153
 
154
  -- This "2w" version support dual stores.
155
 
156
  -- 10/11/2015
157
  -- CLRB_i is now coincident with CLRP signal, as 
158
  -- NOPR_o has ben permanently set to '1'. In this
159
  -- way re-fetch, exception servicing and return from
160
  -- exception can start even if there're still pending
161
  -- read in store buffer. Such result is obtained by
162
  -- invalidating, on CLRB_i assertion, store buffer
163
  -- entries for which no read request is pending (the
164
  -- remaining ones are related to instructions older
165
  -- the one(s) in IX3 and therefore can be completed
166
  -- safely). 
167
 
168
  -- 11/02/2017
169
  -- KTS_i input is added to B/J handle mis-predictions
170
  -- (and some special case of jalr instruction)
171
  -- triggering a B/J in IX2.
172
  -- KTS_i is set if, in the previous cycle, IX1
173
  -- instruction #0 triggered a B/J when instruction
174
  -- #1 was a store (under such condition an entry
175
  -- corresponding to a nullified store has been written
176
  -- to be buffer.
177
  -- If KTS_i is set, current top entry must be
178
  -- invalidated. 
179
  -- Note: when KTS_i is set, WE_i is always equal to
180
  -- "00". 
181
 
182
  ----------------------------------------------------
183
  -- Pending read counter
184
  ----------------------------------------------------
185
 
186
  -- If a buffer read is requested (RE_i  = '1') but the
187
  -- buffer can't be read because memory write port is
188
  -- in use by a valid load/store instruction, the read
189
  -- request is recorded by incrementing the pending
190
  -- read counter PR_CNT_q.
191
  -- A pending read is actually performed when the memory
192
  -- write port is available (no valid load/store is using
193
  -- it), when this event occurs, the pending read counter
194
  -- is decremented.
195
  -- If a read is requested in the same cycle where a
196
  -- pending read is performed, the pending read counter
197
  -- remains un-changed.
198
 
199
  process(CLK_i)
200
  begin
201
    if(CLK_i = '1' and CLK_i'event) then
202
      --if(RST_i = '1' or CLRB_i = '1') then
203
      if(RST_i = '1') then
204
        PR_CNT_q <= 0;
205
        PRV_q <= (others => '0');
206
      else
207
        PR_CNT_q <= PR_CNT;
208
        PRV_q <= PRV;
209
      end if;
210
    end if;
211
  end process;
212
 
213
  process(PR_CNT_q,RE_i,POP)
214
    variable TMP : std_logic_vector(3-1 downto 0);
215
  begin
216
    TMP := POP & RE_i;
217
    case TMP is
218
      when "001"|"010"|"111" => PR_CNT <= PR_CNT_q + 1;
219
      when "011" => PR_CNT <= PR_CNT_q + 2;
220
      when "100" => PR_CNT <= PR_CNT_q - 1;
221
      when others => PR_CNT <= PR_CNT_q;
222
    end case;
223
  end process;
224
 
225
  -- PRV_q is an "alternative" view of PR_CNT_q: if
226
  -- PR_CNT_q = n, PRV_q(n-1:0) = all-1. PRV_q is
227
  -- used to set SBV_q when CLRB_i gets asserted.
228
 
229
  process(PRV_q,RE_i,POP)
230
    variable TMP : std_logic_vector(3-1 downto 0);
231
  begin
232
    TMP := POP & RE_i;
233
    case TMP is
234
      when "001"|"010"|"111" =>
235
        PRV <= PRV_q(DEPTH-2 downto 0) & '1';
236
      when "011" =>
237
        PRV <= PRV_q(DEPTH-3 downto 0) & "11";
238
      when "100" =>
239
        PRV <= '0' & PRV_q(DEPTH-1 downto 1);
240
      when others =>
241
        PRV <= PRV_q;
242
    end case;
243
  end process;
244
 
245
  NOPR_o <= '1' when (PR_CNT_q = 0 and RE_i = "00") else '0';
246
  --NOPR_o <= '1';
247
 
248
  ----------------------------------------------------
249
  -- Buffer data registers
250
  ----------------------------------------------------
251
 
252
  -- When CLRB_i gets asserted, SBV_q is set to PRV_q
253
  -- thereby invalidating all entries for which there's
254
  -- no pending read, remaining entries are older than
255
  -- instruction(s) in IX3 and can be completed safely.
256
  -- Such "trick" allow instruction flow change to run
257
  -- in parallel with buffer entries completion.
258
 
259
  process(CLK_i)
260
  begin
261
    if(CLK_i = '1' and CLK_i'event) then
262
      --if(RST_i = '1' or CLRB_i = '1') then
263
      if(RST_i = '1') then
264
        SBV_q <= (others => '0');
265
        TP_q <= 0;
266
      elsif(CLRB_i = '1') then
267
        TP_q <= PR_CNT;
268
        SBV_q <= PRV;
269
      else
270
        SBV_q <= SBV;
271
        TP_q <= TP;
272
      end if;
273
      SB_q <= SB;
274
    end if;
275
  end process;
276
 
277
  ----------------------------------------------------
278
  -- Buffer data updating logic
279
  ----------------------------------------------------
280
 
281
  -- store buffer new entry
282
 
283
  SB_NEW0 <= (
284
    LS_OP0_i,
285
    BE0_i,
286
    D0_i,
287
    DADR0_i
288
  );
289
 
290
  SB_NEW1 <= (
291
    LS_OP1_i,
292
    BE1_i,
293
    D1_i,
294
    DADR1_i
295
  );
296
 
297
  -- Buffer is written when a valid store instruction
298
  -- reaches stage IX1.
299
 
300
  PUSH <= WE_i;
301
 
302
  -- Buffer is read when:
303
  -- 1) IX1 instruction #0 is not a valid L/S and there's an
304
  -- active read request (RE_i = '1'), OR
305
  -- 2) IX1 instruction #0 is not a valid L/S and there's a
306
  -- pending read request (PR_CNT_q > 0), OR
307
  -- 3) a forced pop is needed.
308
 
309
  POP <= not(CLRB_i) when (
310
    LS0 = '0' and (RE_i /= "00" or PR_CNT_q > 0)
311
  ) else '0';
312
 
313
  -- store buffer data updating logic
314
 
315
  process(SB_q,SBV_q,TP_q,PUSH,POP,KTS_i,SB_NEW0,SB_NEW1)
316
  begin
317
    for k in 0 to DEPTH-1 loop
318
      if(PUSH = "11" and POP = '1') then
319
        -- used entries are shifted down one position
320
        -- (deleting bottom one end emptying top),
321
        -- emptied top entry and entry above it are
322
        -- loaded with new data.
323
        if(k = TP_q) then
324
          SBV(k) <= '1';
325
          SB(k) <= SB_NEW1;
326
        elsif(k = TP_q-1) then
327
          SBV(k) <= '1';
328
          SB(k) <= SB_NEW0;
329
        elsif(k < DEPTH-1) then
330
          SBV(k) <= SBV_q(k+1);
331
          SB(k) <= SB_q(k+1);
332
        else
333
          SBV(k) <= '0';
334
          SB(k) <= SB_q(k);
335
        end if;
336
        TP <= TP_q + 1;
337
      elsif((PUSH = "01" or PUSH = "10") and POP = '1') then
338
        -- used entries are shifted down one position
339
        -- (deleting bottom one end emptying top),
340
        -- emptied top entry is loaded with new data.
341
        if(k = TP_q-1) then
342
          SBV(k) <= '1';
343
          if(PUSH = "01") then
344
            SB(k) <= SB_NEW0;
345
          else
346
            SB(k) <= SB_NEW1;
347
          end if;
348
        elsif(k < DEPTH-1) then
349
          SBV(k) <= SBV_q(k+1);
350
          SB(k) <= SB_q(k+1);
351
        else
352
          SBV(k) <= '0';
353
          SB(k) <= SB_q(k);
354
        end if;
355
        TP <= TP_q;
356
      elsif(PUSH = "11") then
357
        -- top empty entry and entry above it are
358
        -- loaded with new data, other entries remain
359
        -- unchanged.
360
        if(k = TP_q+1) then
361
          SBV(k) <= '1';
362
          SB(k) <= SB_NEW1;
363
        elsif(k = TP_q) then
364
          SBV(k) <= '1';
365
          SB(k) <= SB_NEW0;
366
        else
367
          SBV(k) <= SBV_q(k);
368
          SB(k) <= SB_q(k);
369
        end if;
370
        TP <= TP_q + 2;
371
      elsif(PUSH = "01" or PUSH = "10") then
372
        -- top empty entry is loaded with new data,
373
        -- other entries remain unchanged.
374
        if(k = TP_q) then
375
          SBV(k) <= '1';
376
          if(PUSH = "01") then
377
            SB(k) <= SB_NEW0;
378
          else
379
            SB(k) <= SB_NEW1;
380
          end if;
381
        else
382
          SBV(k) <= SBV_q(k);
383
          SB(k) <= SB_q(k);
384
        end if;
385
        TP <= TP_q + 1;
386
      elsif(POP = '1') then
387
        -- used entries are shifted down one position
388
        -- (deleting bottom one end emptying top).
389
        if(k = TP_q-1) then
390
          SBV(k) <= '0';
391
          SB(k) <= SB_q(k); -- don't care!
392
        elsif(k = TP_q-2 and KTS_i = '1') then
393
          SBV(k) <= '0';
394
          SB(k) <= SB_q(k); -- don't care       
395
        elsif(k < DEPTH-1) then
396
          SBV(k) <= SBV_q(k+1);
397
          SB(k) <= SB_q(k+1);
398
        else
399
          SBV(k) <= '0';
400
          SB(k) <= SB_q(k);
401
        end if;
402
        if(KTS_i = '1') then
403
          TP <= TP_q - 2;
404
        else
405
          TP <= TP_q - 1;
406
        end if;
407
      else
408
        if(k = TP_q-1 and KTS_i = '1') then
409
          SBV(k) <= '0';
410
        else
411
          SBV(k) <= SBV_q(k);
412
        end if;
413
        SB(k) <= SB_q(k);
414
        if(KTS_i = '1') then
415
          TP <= TP_q - 1;
416
        else
417
          TP <= TP_q;
418
        end if;
419
      end if;
420
    end loop;
421
  end process;
422
 
423
  ----------------------------------------------------
424
  -- Store-to-load conflict check
425
  ----------------------------------------------------
426
 
427
  -- MTCHm(n) flag is set if store buffer n-th entry is
428
  -- valid and slot #m load addresses matches entry
429
  -- address. MTCH(DEPTH) is set if inst. #0 is a store
430
  -- and inst. #1 load addr. matches inst #0 store one.
431
 
432
  -- Comparison is restricted to MTCH_WIDTH bits, at the 
433
  -- cost of possible "fake" matches, in order to reduce
434
  -- delay.
435
 
436
  process(SB_q,SBV_q,DADR0_i,DADR1_i,ST0)
437
  begin
438
 
439
    for k in 0 to DEPTH-1 loop
440
      if(DADR0_i((MTCH_WIDTH+2)-1 downto 2) =
441
        SB_q(k).ADR((MTCH_WIDTH+2)-1 downto 2)
442
      ) then
443
        MTCH0(k) <= SBV_q(k);
444
      else
445
        MTCH0(k) <= '0';
446
      end if;
447
      if(DADR1_i((MTCH_WIDTH+2)-1 downto 2) =
448
        SB_q(k).ADR((MTCH_WIDTH+2)-1 downto 2)
449
      ) then
450
        MTCH1(k) <= SBV_q(k);
451
      else
452
        MTCH1(k) <= '0';
453
      end if;
454
    end loop;
455
 
456
    if(DADR0_i((MTCH_WIDTH+2)-1 downto 2) =
457
      DADR1_i((MTCH_WIDTH+2)-1 downto 2)
458
    ) then
459
      MTCH1(DEPTH) <= ST0;
460
    else
461
      MTCH1(DEPTH) <= '0';
462
    end if;
463
 
464
  end process;
465
 
466
  -- inst. #0 store flag
467
  ST0 <= IX1_V_i(0) when (
468
    LS_OP0_i = LS_SB or
469
    LS_OP0_i = LS_SH or
470
    LS_OP0_i = LS_SW
471
  ) else '0';
472
 
473
  -- inst. #0 load flag
474
  LD0 <= IX1_V_i(0) when (
475
    LS_OP0_i = LS_LB or
476
    LS_OP0_i = LS_LH or
477
    LS_OP0_i = LS_LW
478
  ) else '0';
479
 
480
  -- inst. #1 load flag
481
  LD1 <= IX1_V_i(1) when (
482
    LS_OP1_i = LS_LB or
483
    LS_OP1_i = LS_LH or
484
    LS_OP1_i = LS_LW
485
  ) else '0';
486
 
487
  -- inst. #0 load/store flag
488
  LS0 <= LD0 or ST0;
489
 
490
  -- Buffer full flag (buffer is treated as full
491
  -- when less than the number of empty entries
492
  -- equals the number of pushed ones).
493
 
494
  --BF <= '1' when (
495
    --(SBV_q(DEPTH-3) = '1' and (PUSH = "11")) or
496
    --(SBV_q(DEPTH-2) = '1' and (PUSH = "10" or PUSH = "01"))
497
  --) else '0';
498
 
499
  BF <= SBV_q(DEPTH-4);
500
 
501
  -- A conflict is detected if an active load address
502
  -- matches a buffered store one.
503
  -- A force-pop creates a special case of conflict
504
  -- because the load in slot #0 can't be performed
505
  -- in order to execute the pending store which is
506
  -- force-popped.
507
 
508
  S2LAC(0) <= LD0 and wired_or(MTCH0);
509
  S2LAC(1) <= LD1 and wired_or(MTCH1);
510
 
511
  ----------------------------------------------------
512
  -- outputs
513
  ----------------------------------------------------
514
 
515
  BF_o <= BF;
516
 
517
  S2LAC_o(0) <= S2LAC(0);
518
  S2LAC_o(1) <= S2LAC(1);
519
 
520
  WE_o <= POP;
521
  LS_OP_o <= SB_q(0).LS_OP;
522
  BE_o <= SB_q(0).BE;
523
  Q_o <= SB_q(0).DATA;
524
  SADR_o <= SB_q(0).ADR;
525
 
526
  ----------------------------------------------------
527
  -- Checkers
528
  ----------------------------------------------------
529
 
530
  -- synthesis translate_off
531
 
532
  GCHK0: if SIMULATION_ONLY = '1' generate
533
 
534
  --assert not(
535
  --  (WE_i /= "00" and BF = '1') and 
536
  --  (CLK_i = '1' and CLK_i'event)and
537
  --  (RST_i = '0')
538
  --) 
539
  --report "attempted write when store buffer is full!"
540
  --severity FAILURE;
541
 
542
  assert not(
543
    (RE_i /= "00" and SBV_q(0) = '0') and
544
    (CLK_i = '1' and CLK_i'event)and
545
    (RST_i = '0')
546
  )
547
  report "attempted read when store buffer is empty!"
548
  severity FAILURE;
549
 
550
  assert not(
551
    (
552
      (PR_CNT_q > TP_q) or
553
      (PR_CNT_q > TP_q-1 and (RE_i = "01" or RE_i ="10")) or
554
      (PR_CNT_q > TP_q-2 and RE_i = "11")
555
    ) and
556
    (CLK_i = '1' and CLK_i'event) and
557
    (RST_i = '0')
558
  )
559
  report "pending read count + read requests > tail pointer in store buffer!"
560
  severity FAILURE;
561
 
562
  assert not(
563
    (
564
      (RE_i = "01" and SADR0_i /= SB_q(PR_CNT_q).ADR) or
565
      (RE_i = "10" and SADR1_i /= SB_q(PR_CNT_q).ADR) or
566
      (RE_i = "11" and (SADR0_i /= SB_q(PR_CNT_q).ADR or SADR1_i /= SB_q(PR_CNT_q+1).ADR))
567
    ) and
568
    (CLK_i = '1' and CLK_i'event) and
569
    (RST_i = '0')
570
  )
571
  report "invalid read requests!"
572
  severity FAILURE;
573
 
574
  end generate;
575
 
576
  -- synthesis translate_on
577
 
578
end ARC;

powered by: WebSVN 2.1.0

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