summaryrefslogtreecommitdiff
path: root/rtl/core
diff options
context:
space:
mode:
Diffstat (limited to 'rtl/core')
-rw-r--r--rtl/core/control/control.sv4
-rw-r--r--rtl/core/control/cycles.sv4
-rw-r--r--rtl/core/control/ldst/ldst.sv36
-rw-r--r--rtl/core/control/writeback.sv5
-rw-r--r--rtl/core/decode/decode.sv10
-rw-r--r--rtl/core/decode/isa.sv13
-rw-r--r--rtl/core/decode/ldst/exclusive.sv27
-rw-r--r--rtl/core/decode/ldst/misc.sv1
-rw-r--r--rtl/core/decode/ldst/multiple.sv1
-rw-r--r--rtl/core/decode/ldst/single.sv1
-rw-r--r--rtl/core/decode/mux.sv20
-rw-r--r--rtl/core/uarch.sv1
12 files changed, 101 insertions, 22 deletions
diff --git a/rtl/core/control/control.sv b/rtl/core/control/control.sv
index 6090f2d..27be940 100644
--- a/rtl/core/control/control.sv
+++ b/rtl/core/control/control.sv
@@ -112,8 +112,8 @@ module core_control
.*
);
- word mem_offset, ldst_read;
- logic ldst, ldst_next, ldst_writeback, pop_valid;
+ word mem_offset, ldst_read, strex_ok;
+ logic ldst, ldst_next, ldst_reject, ldst_writeback, pop_valid;
reg_num popped;
logic[1:0] ldst_shift;
diff --git a/rtl/core/control/cycles.sv b/rtl/core/control/cycles.sv
index 5779990..772697d 100644
--- a/rtl/core/control/cycles.sv
+++ b/rtl/core/control/cycles.sv
@@ -18,6 +18,7 @@ module core_control_cycles
mul_ready,
pop_valid,
trivial_shift,
+ ldst_reject,
ldst_writeback,
data_snd_shift_by_reg,
@@ -109,6 +110,9 @@ module core_control_cycles
if(mem_ready && mem_fault)
next_state = ESCALATE;
+
+ if(ldst_reject)
+ next_state = ISSUE;
end
MUL:
diff --git a/rtl/core/control/ldst/ldst.sv b/rtl/core/control/ldst/ldst.sv
index 0e0a39c..aa5c957 100644
--- a/rtl/core/control/ldst/ldst.sv
+++ b/rtl/core/control/ldst/ldst.sv
@@ -29,24 +29,26 @@ module core_control_ldst
pop_valid,
ldst,
ldst_next,
+ ldst_reject,
ldst_writeback,
output logic[1:0] ldst_shift,
output word ldst_read,
+ strex_ok,
output reg_num popped
);
word base;
- logic pre, increment, sign_extend;
+ logic block_strex, increment, pre, sign_extend;
reg_num popped_upper, popped_lower;
reg_list mem_regs, next_regs_upper, next_regs_lower;
ldst_size size;
assign popped = increment ? popped_lower : popped_upper;
assign ldst_next = !cycle.transfer || mem_ready;
- assign mem_data_wr = q_shifter;
+ assign mem_data_wr = mem_ex_lock ? alu_b : q_shifter;
- //TODO
- assign mem_ex_lock = 0;
+ assign strex_ok = {31'd0, mem_ex_fail || block_strex};
+ assign ldst_reject = mem_ex_lock && mem_write && block_strex;
core_control_ldst_pop pop
(
@@ -69,11 +71,12 @@ module core_control_ldst
);
always_ff @(posedge clk or negedge rst_n)
- if(!rst_n) begin
+ if (!rst_n) begin
pre <= 0;
ldst <= 0;
size <= LDST_WORD;
increment <= 0;
+ block_strex <= 1;
sign_extend <= 0;
ldst_writeback <= 0;
@@ -83,12 +86,13 @@ module core_control_ldst
mem_write <= 0;
mem_start <= 0;
mem_offset <= 0;
+ mem_ex_lock <= 0;
end else begin
- if(mem_start)
+ if (mem_start)
mem_start <= 0;
- if(next_cycle.issue) begin
- if(issue) begin
+ if (next_cycle.issue) begin
+ if (issue) begin
ldst <= dec.ctrl.ldst;
mem_user <= dec.ldst.unprivileged;
end
@@ -101,19 +105,25 @@ module core_control_ldst
mem_regs <= dec.ldst.regs;
mem_write <= !dec.ldst.load;
- end else if(next_cycle.transfer) begin
- if(!cycle.transfer) begin
+ mem_ex_lock <= dec.ldst.exclusive;
+ end else if (next_cycle.transfer) begin
+ if (!cycle.transfer) begin
ldst <= 0;
mem_offset <= alu_b;
end
- if(ldst_next) begin
+ if (ldst_next) begin
base <= pre ? q_alu : alu_a;
mem_regs <= increment ? next_regs_lower : next_regs_upper;
end
- mem_start <= !cycle.transfer || (mem_ready && pop_valid);
- end else if(cycle.escalate)
+ mem_start <= (!cycle.transfer || (mem_ready && pop_valid)) && !ldst_reject;
+
+ if (block_strex)
+ block_strex <= !mem_ex_lock || mem_write;
+ end else if (cycle.escalate) begin
ldst <= 0;
+ block_strex <= 1;
+ end
end
endmodule
diff --git a/rtl/core/control/writeback.sv b/rtl/core/control/writeback.sv
index a7738fb..027a7d7 100644
--- a/rtl/core/control/writeback.sv
+++ b/rtl/core/control/writeback.sv
@@ -10,9 +10,11 @@ module core_control_writeback
input word q_alu,
ldst_read,
input logic mem_ready,
+ mem_ex_lock,
mem_write,
input word mul_q_hi,
mul_q_lo,
+ strex_ok,
input ctrl_cycle cycle,
next_cycle,
@@ -26,6 +28,7 @@ module core_control_writeback
input logic issue,
pop_valid,
ldst_next,
+ ldst_reject,
output reg_num rd,
final_rd,
@@ -62,7 +65,7 @@ module core_control_writeback
writeback = 0;
if(cycle.transfer)
- wr_value = ldst_read;
+ wr_value = (mem_ex_lock && mem_write) ? strex_ok : ldst_read;
else if(cycle.base_writeback)
wr_value = saved_base;
else if(cycle.mul || cycle.mul_hi_wb)
diff --git a/rtl/core/decode/decode.sv b/rtl/core/decode/decode.sv
index b00e06f..219f975 100644
--- a/rtl/core/decode/decode.sv
+++ b/rtl/core/decode/decode.sv
@@ -127,6 +127,16 @@ module core_decode
.*
);
+ reg_num ldst_ex_snd_r;
+ ldst_decode ldst_exclusive;
+
+ core_decode_ldst_exclusive group_ldst_ex
+ (
+ .snd_r(ldst_ex_snd_r),
+ .decode(ldst_exclusive),
+ .*
+ );
+
ldst_decode ldst_addr;
data_decode data_ldst;
diff --git a/rtl/core/decode/isa.sv b/rtl/core/decode/isa.sv
index 2ad5b40..6784eca 100644
--- a/rtl/core/decode/isa.sv
+++ b/rtl/core/decode/isa.sv
@@ -162,7 +162,18 @@
`define FIELD_LDST_MULT_RN [19:16]
`define FIELD_LDST_MULT_LIST [15:0]
-// Instrucciones atómicas de intercambio registro-memoria
+// Instrucciones para operaciones atómicas optimistas (monitor exclusivo)
+
+`define INSN_LDREX 28'b0001100_1_????_????_1111_1001_1111
+`define INSN_STREX 28'b0001100_0_????_????_1111_1001_????
+`define GROUP_LDST_EX `INSN_LDREX, `INSN_STREX
+
+`define FIELD_LDST_EX_LD [20]
+`define FIELD_LDST_EX_RN [19:16]
+`define FIELD_LDST_EX_RD [15:12]
+`define FIELD_LDST_EX_R_OK [3:0]
+
+// Instrucciones atómicas de intercambio registro-memoria (deprecadas)
`define INSN_SWP 28'b00010000_????_????_0000_1001_????
`define INSN_SWPB 28'b00010100_????_????_0000_1001_????
diff --git a/rtl/core/decode/ldst/exclusive.sv b/rtl/core/decode/ldst/exclusive.sv
new file mode 100644
index 0000000..7942a04
--- /dev/null
+++ b/rtl/core/decode/ldst/exclusive.sv
@@ -0,0 +1,27 @@
+`include "core/decode/isa.sv"
+`include "core/uarch.sv"
+
+module core_decode_ldst_exclusive
+(
+ input word insn,
+
+ output ldst_decode decode,
+ output reg_num snd_r
+);
+
+ assign snd_r = insn `FIELD_LDST_EX_R_OK;
+
+ assign decode.rn = insn `FIELD_LDST_EX_RN;
+ assign decode.rd = insn `FIELD_LDST_EX_RD;
+ assign decode.size = LDST_WORD;
+ assign decode.load = insn `FIELD_LDST_EX_LD;
+ assign decode.increment = 0;
+ assign decode.writeback = 0;
+ assign decode.exclusive = 1;
+ assign decode.sign_extend = 0;
+ assign decode.pre_indexed = 0;
+ assign decode.unprivileged = 0;
+ assign decode.user_regs = 0;
+ assign decode.regs = 16'b0;
+
+endmodule
diff --git a/rtl/core/decode/ldst/misc.sv b/rtl/core/decode/ldst/misc.sv
index 4e4a17e..72d648c 100644
--- a/rtl/core/decode/ldst/misc.sv
+++ b/rtl/core/decode/ldst/misc.sv
@@ -19,6 +19,7 @@ module core_decode_ldst_misc
assign decode.load = insn `FIELD_LDST_LD;
assign decode.increment = insn `FIELD_LDST_MISC_U;
assign decode.writeback = !p || w;
+ assign decode.exclusive = 0;
assign decode.sign_extend = insn `FIELD_LDST_MISC_S;
assign decode.pre_indexed = p;
assign decode.unprivileged = 0;
diff --git a/rtl/core/decode/ldst/multiple.sv b/rtl/core/decode/ldst/multiple.sv
index 0ecd674..c822ab0 100644
--- a/rtl/core/decode/ldst/multiple.sv
+++ b/rtl/core/decode/ldst/multiple.sv
@@ -18,6 +18,7 @@ module core_decode_ldst_multiple
assign decode.load = l;
assign decode.increment = insn `FIELD_LDST_MULT_U;
assign decode.writeback = insn `FIELD_LDST_MULT_W;
+ assign decode.exclusive = 0;
assign decode.sign_extend = 0;
assign decode.pre_indexed = insn `FIELD_LDST_MULT_P;
assign decode.unprivileged = 0;
diff --git a/rtl/core/decode/ldst/single.sv b/rtl/core/decode/ldst/single.sv
index 402c17b..af096a7 100644
--- a/rtl/core/decode/ldst/single.sv
+++ b/rtl/core/decode/ldst/single.sv
@@ -17,6 +17,7 @@ module core_decode_ldst_single
assign decode.load = insn `FIELD_LDST_LD;
assign decode.increment = insn `FIELD_LDST_SINGLE_U;
assign decode.writeback = !p || w;
+ assign decode.exclusive = 0;
assign decode.sign_extend = 0;
assign decode.pre_indexed = p;
assign decode.unprivileged = !p && w;
diff --git a/rtl/core/decode/mux.sv b/rtl/core/decode/mux.sv
index 297ad33..6f0451a 100644
--- a/rtl/core/decode/mux.sv
+++ b/rtl/core/decode/mux.sv
@@ -18,12 +18,14 @@ module core_decode_mux
data_is_imm,
data_shift_by_reg_if_reg,
- input ldst_decode ldst_single,
- ldst_misc,
+ input ldst_decode ldst_misc,
+ ldst_single,
ldst_multiple,
+ ldst_exclusive,
input logic ldst_single_is_imm,
ldst_misc_off_is_imm,
- input reg_num ldst_misc_off_reg,
+ input reg_num ldst_ex_snd_r,
+ ldst_misc_off_reg,
input logic[7:0] ldst_misc_off_imm,
input logic ldst_mult_restore_spsr,
input data_decode data_ldst,
@@ -135,6 +137,14 @@ module core_decode_mux
update_flags = mul_update_flags;
end
+ `GROUP_LDST_EX: begin
+ dec_ldst = ldst_exclusive;
+ ldst_addr = ldst_exclusive;
+
+ dec_snd.r = ldst_ex_snd_r;
+ dec_snd.is_imm = ldst_exclusive.load;
+ end
+
`GROUP_LDST_MISC: begin
dec_ldst = ldst_misc;
ldst_addr = ldst_misc;
@@ -255,10 +265,10 @@ module core_decode_mux
// Codificación coincide con ldst
`GROUP_MUL: ;
- `GROUP_LDST_SINGLE, `GROUP_LDST_MISC, `GROUP_LDST_MULT: begin
+ `GROUP_LDST_SINGLE, `GROUP_LDST_MISC, `GROUP_LDST_MULT, `GROUP_LDST_EX: begin
ldst = 1;
dec_data = data_ldst;
- writeback = dec_ldst.writeback || dec_ldst.load;
+ writeback = dec_ldst.writeback || dec_ldst.load || dec_ldst.exclusive;
end
default: ;
diff --git a/rtl/core/uarch.sv b/rtl/core/uarch.sv
index 38b0130..a474274 100644
--- a/rtl/core/uarch.sv
+++ b/rtl/core/uarch.sv
@@ -150,6 +150,7 @@ typedef struct packed
logic load,
increment,
writeback,
+ exclusive,
sign_extend,
pre_indexed,
unprivileged,