Commit ea69b7e8591c615cda59a99247864bd1667f5b09

Authored by Sumiran Shubhi
1 parent 1329579e04

Added support for LL/SC instructions

Showing 8 changed files with 152 additions and 17 deletions Side-by-side Diff

mips_cpu/mips_core/alu.sv View file @ ea69b7e
... ... @@ -17,18 +17,25 @@
17 17 mips_core_pkg::AluCtl alu_ctl;
18 18 logic signed [`DATA_WIDTH - 1 : 0] op1;
19 19 logic signed [`DATA_WIDTH - 1 : 0] op2;
  20 + logic is_ll;
  21 + logic is_sc;
  22 + logic is_sw;
20 23  
21   - modport in (input valid, alu_ctl, op1, op2);
22   - modport out (output valid, alu_ctl, op1, op2);
  24 + modport in (input valid, alu_ctl, op1, op2, is_ll, is_sc, is_sw);
  25 + modport out (output valid, alu_ctl, op1, op2, is_ll, is_sc, is_sw);
23 26 endinterface
24 27  
25 28 interface alu_output_ifc ();
26 29 logic valid;
27 30 logic [`DATA_WIDTH - 1 : 0] result;
28 31 mips_core_pkg::BranchOutcome branch_outcome;
  32 + logic is_ll;
  33 + logic is_sc;
  34 + logic is_sw;
29 35  
30   - modport in (input valid, result, branch_outcome);
31   - modport out (output valid, result, branch_outcome);
  36 +
  37 + modport in (input valid, result, branch_outcome, is_ll, is_sc, is_sw);
  38 + modport out (output valid, result, branch_outcome, is_ll, is_sc, is_sw);
32 39 endinterface
33 40  
34 41 module alu (
35 42  
... ... @@ -42,13 +49,21 @@
42 49 out.valid <= 1'b0;
43 50 out.result <= '0;
44 51 out.branch_outcome <= NOT_TAKEN;
  52 +
  53 + out.is_ll <= 1'b0;
  54 + out.is_sc <= 1'b0;
  55 + out.is_sw <= 1'b0;
  56 +
45 57 pass_done.value <= '0;
46 58 pass_done.code <= MTC0_NOOP;
47 59  
48 60 if (in.valid)
49 61 begin
50 62 out.valid <= 1'b1;
51   -
  63 + out.is_ll <= in.is_ll;
  64 + out.is_sc <= in.is_sc;
  65 + out.is_sw <= in.is_sw;
  66 +
52 67 case (in.alu_ctl)
53 68 ALUCTL_NOP: out.result <= '0;
54 69 ALUCTL_ADD: out.result <= in.op1 + in.op2;
mips_cpu/mips_core/d_cache.sv View file @ ea69b7e
... ... @@ -30,6 +30,7 @@
30 30 logic [`ADDR_WIDTH - 1 : 0] addr;
31 31 logic [`ADDR_WIDTH - 1 : 0] addr_next;
32 32 logic [`DATA_WIDTH - 1 : 0] data;
  33 +
33 34  
34 35 modport in (input valid, mem_action, addr, addr_next, data);
35 36 modport out (output valid, mem_action, addr, addr_next, data);
... ... @@ -42,6 +43,9 @@
42 43 // General signals
43 44 input clk, // Clock
44 45 input rst_n, // Asynchronous reset active low
  46 +
  47 + //Input from LLSC module
  48 + llsc_output_ifc.in llsc_mem_in,
45 49  
46 50 // Request
47 51 d_cache_input_ifc.in in,
... ... @@ -201,7 +205,7 @@
201 205 databank_we <= '0;
202 206 if (mem_read.user_available) // We are refilling data
203 207 databank_we <= databank_select;
204   - else if (hit & (in.mem_action == WRITE)) // We are storing a word
  208 + else if (hit & (in.mem_action == WRITE) && (llsc_mem_in.atomic != ATOMIC_FAIL)) // We are storing a word
205 209 databank_we[i_block_offset] <= 1'b1;
206 210 end
207 211  
... ... @@ -238,7 +242,7 @@
238 242 always_comb
239 243 begin
240 244 out.valid = hit;
241   - out.data = databank_rdata[i_block_offset];
  245 + out.data = (llsc_mem_in.atomic == ATOMIC_PASS) ? 32'b1 : (llsc_mem_in.atomic == ATOMIC_FAIL) ? 32'b0 : databank_rdata[i_block_offset];
242 246 end
243 247  
244 248 always_comb
mips_cpu/mips_core/decoder.sv View file @ ea69b7e
... ... @@ -33,13 +33,17 @@
33 33  
34 34 logic uses_rw;
35 35 mips_core_pkg::MipsReg rw_addr;
  36 +
  37 + logic is_ll;
  38 + logic is_sc;
  39 + logic is_sw;
36 40  
37 41 modport in (input valid, alu_ctl, is_branch_jump, is_jump, is_jump_reg,
38 42 branch_target, is_mem_access, mem_action, uses_rs, rs_addr, uses_rt,
39   - rt_addr, uses_immediate, immediate, uses_rw, rw_addr);
  43 + rt_addr, uses_immediate, immediate, uses_rw, rw_addr, is_ll, is_sc, is_sw);
40 44 modport out (output valid, alu_ctl, is_branch_jump, is_jump, is_jump_reg,
41 45 branch_target, is_mem_access, mem_action, uses_rs, rs_addr, uses_rt,
42   - rt_addr, uses_immediate, immediate, uses_rw, rw_addr);
  46 + rt_addr, uses_immediate, immediate, uses_rw, rw_addr, is_ll, is_sc, is_sw);
43 47 endinterface
44 48  
45 49 module decoder (
... ... @@ -168,7 +172,11 @@
168 172  
169 173 out.uses_rw <= 1'b0;
170 174 out.rw_addr <= zero;
171   -
  175 +
  176 + out.is_ll <= 1'b0;
  177 + out.is_sc <= 1'b0;
  178 + out.is_sw <= 1'b0;
  179 +
172 180 if (i_inst.valid)
173 181 begin
174 182 case(i_inst.data[31:26])
175 183  
... ... @@ -486,10 +494,29 @@
486 494 begin
487 495 out.alu_ctl <= ALUCTL_ADD;
488 496 out.is_mem_access <= 1'b1;
  497 + out.is_sw <= 1'b1;
489 498 out.mem_action <= WRITE;
490 499 uses_rs();
491 500 uses_rt();
492 501 uses_immediate_signed_extend();
  502 + end
  503 +
  504 + 6'h30: //ll
  505 + begin
  506 + out.alu_ctl <= ALUCTL_ADD;
  507 + out.is_mem_access <= 1'b1;
  508 + out.is_ll <= 1'b1;
  509 + out.mem_action <= READ;
  510 + signed_extend_itype();
  511 + end
  512 +
  513 + 6'h38: //sc
  514 + begin
  515 + out.alu_ctl <= ALUCTL_ADD;
  516 + out.is_mem_access <= 1'b1;
  517 + out.is_sc <= 1'b1;
  518 + out.mem_action <= WRITE;
  519 + signed_extend_itype();
493 520 end
494 521  
495 522 6'h10: //mtc0
mips_cpu/mips_core/glue_circuits.sv View file @ ea69b7e
... ... @@ -26,8 +26,12 @@
26 26 o_alu_input.alu_ctl = i_decoded.alu_ctl;
27 27 o_alu_input.op1 = i_reg_data.rs_data;
28 28 o_alu_input.op2 = i_decoded.uses_immediate
29   - ? i_decoded.immediate
30   - : i_reg_data.rt_data;
  29 + ? i_decoded.immediate
  30 + : i_reg_data.rt_data;
  31 + o_alu_input.is_ll = i_decoded.is_ll;
  32 + o_alu_input.is_sc = i_decoded.is_sc;
  33 + o_alu_input.is_sw = i_decoded.is_sw;
  34 +
31 35  
32 36 branch_decoded.valid = i_decoded.is_branch_jump;
33 37 branch_decoded.is_jump = i_decoded.is_jump;
... ... @@ -53,7 +57,8 @@
53 57 module ex_stage_glue (
54 58 alu_output_ifc.in i_alu_output,
55 59 alu_pass_through_ifc.in i_alu_pass_through,
56   -
  60 +
  61 + llsc_input_ifc.out o_llsc_input,
57 62 branch_result_ifc.out o_branch_result,
58 63 d_cache_input_ifc.out o_d_cache_input,
59 64 d_cache_pass_through_ifc.out o_d_cache_pass_through
... ... @@ -61,6 +66,11 @@
61 66  
62 67 always_comb
63 68 begin
  69 + o_llsc_input.is_sw = i_alu_output.is_sw;
  70 + o_llsc_input.lladdr_wr = i_alu_output.is_ll;
  71 + o_llsc_input.is_sc = i_alu_output.is_sc;
  72 + o_llsc_input.wr_reg_val = {6'b0,i_alu_output.result[`ADDR_WIDTH - 1 : 0]};
  73 +
64 74 o_branch_result.valid = i_alu_output.valid
65 75 & i_alu_pass_through.is_branch;
66 76 o_branch_result.prediction = i_alu_pass_through.prediction;
... ... @@ -83,7 +93,7 @@
83 93 module mem_stage_glue (
84 94 cache_output_ifc.in i_d_cache_output,
85 95 d_cache_pass_through_ifc.in i_d_cache_pass_through,
86   -
  96 +
87 97 output logic o_done,
88 98 write_back_ifc.out o_write_back
89 99 );
mips_cpu/mips_core/llsc_module.sv View file @ ea69b7e
  1 +/*
  2 + * lladdr.sv
  3 + * Author: Sumiran Shubhi
  4 + * Last Revision: 04/03/2020
  5 + *
  6 + * Module to store current LLADDR register value for processing LL and SC
  7 + * instructions.
  8 + */
  9 + `include "mips_core.svh"
  10 +
  11 + interface llsc_input_ifc();
  12 + logic is_sw;
  13 + logic lladdr_wr;
  14 + logic [`DATA_WIDTH - 1 : 0] wr_reg_val;
  15 + logic is_sc;
  16 +
  17 + modport in (input wr_reg_val, lladdr_wr, is_sw, is_sc);
  18 + modport out (output wr_reg_val, lladdr_wr, is_sw, is_sc);
  19 + endinterface
  20 +
  21 + interface llsc_output_ifc();
  22 + mips_core_pkg::AtomicStatus atomic;
  23 +
  24 + modport in (input atomic);
  25 + modport out (output atomic);
  26 + endinterface
  27 +
  28 + module llsc_module (
  29 + input clk, // Clock
  30 + // Input from ALU stage
  31 + llsc_input_ifc.in i_llsc,
  32 +
  33 + // Output to MEM stage
  34 + llsc_output_ifc.out o_llsc
  35 +);
  36 + logic [`DATA_WIDTH - 1 : 0] LLAddr;
  37 + logic LLbit;
  38 +
  39 + always_comb begin
  40 + o_llsc.atomic = (LLbit && i_llsc.is_sc && (LLAddr==i_llsc.wr_reg_val)) ? ATOMIC_PASS
  41 + : (LLbit && i_llsc.is_sc && (LLAddr!= i_llsc.wr_reg_val)) ? ATOMIC_FAIL
  42 + : NOT_ATOMIC ;
  43 + end
  44 +
  45 + always_ff @(posedge clk) begin
  46 + if (i_llsc.is_sw && LLbit && (LLAddr==i_llsc.wr_reg_val)) begin
  47 + LLAddr <= 0;
  48 + LLbit <= 0;
  49 + end
  50 + else if(i_llsc.lladdr_wr) begin
  51 + LLAddr <= i_llsc.wr_reg_val;
  52 + LLbit <= 1;
  53 + end
  54 +
  55 + end
  56 +endmodule
mips_cpu/mips_core/mips_core.sv View file @ ea69b7e
... ... @@ -50,12 +50,14 @@
50 50  
51 51 // |||| EX Stage
52 52 alu_output_ifc ex_alu_output();
  53 + llsc_input_ifc ex_llsc_input();
53 54 branch_result_ifc ex_branch_result();
54 55 d_cache_input_ifc ex_d_cache_input();
55 56 d_cache_pass_through_ifc ex_d_cache_pass_through();
56 57  
57 58 // ==== EX to MEM
58 59 pc_ifc e2m_pc();
  60 + llsc_output_ifc llsc_mem_output();
59 61 d_cache_input_ifc e2m_d_cache_input();
60 62 d_cache_pass_through_ifc e2m_d_cache_pass_through();
61 63  
62 64  
63 65  
... ... @@ -182,11 +184,18 @@
182 184 .out(ex_alu_output),
183 185 .pass_done
184 186 );
  187 +
  188 + llsc_module LLSC_mod(
  189 + .clk(clk),
  190 + .i_llsc(ex_llsc_input),
  191 + .o_llsc(llsc_mem_output)
  192 +);
185 193  
  194 +
186 195 ex_stage_glue EX_STAGE_GLUE (
187 196 .i_alu_output (ex_alu_output),
188 197 .i_alu_pass_through (d2e_alu_pass_through),
189   -
  198 + .o_llsc_input (ex_llsc_input),
190 199 .o_branch_result (ex_branch_result),
191 200 .o_d_cache_input (ex_d_cache_input),
192 201 .o_d_cache_pass_through (ex_d_cache_pass_through)
... ... @@ -215,7 +224,7 @@
215 224  
216 225 .in(e2m_d_cache_input),
217 226 .out(mem_d_cache_output),
218   -
  227 + .llsc_mem_in(llsc_mem_output),
219 228 .mem_read(d_cache_read),
220 229 .mem_write(d_cache_write)
221 230 );
mips_cpu/mips_core/mips_core_pkg.sv View file @ ea69b7e
... ... @@ -86,5 +86,11 @@
86 86 TAKEN
87 87 } BranchOutcome;
88 88  
  89 +typedef enum logic [1:0] {
  90 + NOT_ATOMIC,
  91 + ATOMIC_FAIL,
  92 + ATOMIC_PASS
  93 +} AtomicStatus;
  94 +
89 95 endpackage
mips_cpu/mips_core/pipeline_registers.sv View file @ ea69b7e
... ... @@ -81,6 +81,9 @@
81 81 o_alu_input.alu_ctl <= ALUCTL_NOP;
82 82 o_alu_input.op1 <= '0;
83 83 o_alu_input.op2 <= '0;
  84 + o_alu_input.is_ll <= '0;
  85 + o_alu_input.is_sc <= '0;
  86 + o_alu_input.is_sw <= '0;
84 87  
85 88  
86 89 o_alu_pass_through.is_branch <= 1'b0;
... ... @@ -107,6 +110,9 @@
107 110 o_alu_input.alu_ctl <= ALUCTL_NOP;
108 111 o_alu_input.op1 <= '0;
109 112 o_alu_input.op2 <= '0;
  113 + o_alu_input.is_ll <= '0;
  114 + o_alu_input.is_sc <= '0;
  115 + o_alu_input.is_sw <= '0;
110 116  
111 117  
112 118 o_alu_pass_through.is_branch <= 1'b0;
... ... @@ -129,7 +135,9 @@
129 135 o_alu_input.alu_ctl <= i_alu_input.alu_ctl;
130 136 o_alu_input.op1 <= i_alu_input.op1;
131 137 o_alu_input.op2 <= i_alu_input.op2;
132   -
  138 + o_alu_input.is_ll <= i_alu_input.is_ll;
  139 + o_alu_input.is_sc <= i_alu_input.is_sc;
  140 + o_alu_input.is_sw <= i_alu_input.is_sw;
133 141  
134 142 o_alu_pass_through.is_branch <= i_alu_pass_through.is_branch;
135 143 o_alu_pass_through.prediction <= i_alu_pass_through.prediction;