summaryrefslogtreecommitdiff
path: root/rtl
diff options
context:
space:
mode:
Diffstat (limited to 'rtl')
-rw-r--r--rtl/cache/cache.sv26
-rw-r--r--rtl/cache/cache_control.sv152
-rw-r--r--rtl/cache/cache_debug.sv71
-rw-r--r--rtl/cache/defs.sv19
-rw-r--r--rtl/cache/monitor.sv103
-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
17 files changed, 393 insertions, 101 deletions
diff --git a/rtl/cache/cache.sv b/rtl/cache/cache.sv
index 29403e2..6d5a204 100644
--- a/rtl/cache/cache.sv
+++ b/rtl/cache/cache.sv
@@ -16,13 +16,12 @@ module cache
output logic[1:0] core_response,
output word core_readdata,
- //TODO
- /*input TODO/ dbg_address,
+ input logic[2:0] dbg_address,
input logic dbg_read,
dbg_write,
input word dbg_writedata,
output logic dbg_waitrequest,
- output word dbg_readdata,*/
+ output word dbg_readdata,
input logic mem_waitrequest,
input line mem_readdata,
@@ -47,9 +46,6 @@ module cache
output logic out_token_valid
);
- //TODO
- //assign dbg_waitrequest = 1;
-
logic write_data, write_state;
line data_wr, data_rd;
addr_tag tag_wr, tag_rd;
@@ -63,7 +59,8 @@ module cache
word cache_mem_address;
line cache_mem_writedata;
- logic cache_core_waitrequest, cache_mem_waitrequest, cache_mem_read, cache_mem_write;
+ logic cache_core_waitrequest, cache_mem_waitrequest, cache_mem_read, cache_mem_write,
+ debug_ready;
cache_control #(.TOKEN_AT_RESET(TOKEN_AT_RESET)) control
(
@@ -97,4 +94,19 @@ module cache
.*
);
+ line monitor_update;
+ logic monitor_acquire, monitor_commit, monitor_fail, monitor_release;
+
+ cache_monitor monitor
+ (
+ .*
+ );
+
+ addr_index debug_index;
+
+ cache_debug debug
+ (
+ .*
+ );
+
endmodule
diff --git a/rtl/cache/cache_control.sv b/rtl/cache/cache_control.sv
index fb7896a..33d380a 100644
--- a/rtl/cache/cache_control.sv
+++ b/rtl/cache/cache_control.sv
@@ -3,51 +3,60 @@
module cache_control
#(parameter TOKEN_AT_RESET=0)
(
- input logic clk,
- rst_n,
+ input logic clk,
+ rst_n,
- input addr_tag core_tag,
- input addr_index core_index,
- input logic core_read,
- core_write,
- core_lock,
- input line core_data_wr,
- output logic core_waitrequest,
- output logic[1:0] core_response,
+ input addr_tag core_tag,
+ input addr_index core_index,
+ input logic core_read,
+ core_write,
+ core_lock,
+ input line core_data_wr,
+ output logic core_waitrequest,
- input ring_req in_data,
- input logic in_data_valid,
- output logic in_data_ready,
+ input ring_req in_data,
+ input logic in_data_valid,
+ output logic in_data_ready,
- input logic out_data_ready,
- output ring_req out_data,
- output logic out_data_valid,
+ input logic out_data_ready,
+ output ring_req out_data,
+ output logic out_data_valid,
- input ring_token in_token,
- input logic in_token_valid,
+ input ring_token in_token,
+ input logic in_token_valid,
- output ring_token out_token,
- output logic out_token_valid,
+ output ring_token out_token,
+ output logic out_token_valid,
// Señales para la SRAM
- input addr_tag tag_rd,
- input line data_rd,
- input line_state state_rd,
-
- output addr_index index_rd,
- index_wr,
- output logic write_data,
- write_state,
- output addr_tag tag_wr,
- output line data_wr,
- output line_state state_wr,
-
- input logic mem_waitrequest,
- input line mem_readdata,
- output word mem_address,
- output logic mem_read,
- mem_write,
- output line mem_writedata
+ input addr_tag tag_rd,
+ input line data_rd,
+ input line_state state_rd,
+
+ input line monitor_update,
+ input logic monitor_commit,
+ output logic monitor_acquire,
+ monitor_fail,
+ monitor_release,
+
+ output addr_index index_rd,
+ index_wr,
+ output logic write_data,
+ write_state,
+ output addr_tag tag_wr,
+ output line data_wr,
+ output line_state state_wr,
+
+ input logic mem_waitrequest,
+ input line mem_readdata,
+ output word mem_address,
+ output logic mem_read,
+ mem_write,
+ output line mem_writedata,
+
+ input logic dbg_write,
+ input addr_index debug_index,
+ output logic debug_ready
);
enum int unsigned
@@ -58,24 +67,15 @@ module cache_control
REPLY
} state, next_state;
- logic accept_snoop, end_reply, in_hold_valid, last_hop, lock_line, locked,
- may_send, may_send_if_token_held, mem_begin, mem_end, mem_read_end, mem_wait,
- monitor_acquire, monitor_commit, monitor_fail, out_stall, wait_reply, replace,
- retry, send, send_inval, send_read, snoop_hit, set_reply, unlock_line, writeback;
+ logic accept_snoop, debug, end_reply, in_hold_valid, last_hop, lock_line,
+ locked, may_send, may_send_if_token_held, mem_begin, mem_end, mem_read_end,
+ mem_wait, out_stall, wait_reply, replace, retry, send, send_inval,
+ send_read, snoop_hit, set_reply, unlock_line, writeback;
ring_req in_hold, send_data, fwd_data, stall_data, out_data_next;
- line monitor_data_rd, monitor_data_wr;
- addr_tag mem_tag, monitor_tag;
- addr_index mem_index, monitor_index;
-
- /* Avalon p. 15:
- * - 00: OKAY - Successful response for a transaction.
- * - 10: SLVERR - Error from an endpoint agent. Indicates an unsuccessful transaction.
- */
- assign core_response = {monitor_fail, 1'b0};
- assign monitor_commit = !core_lock || (monitor_tag == core_tag && monitor_index == core_index
- && monitor_data_rd == data_rd);
+ addr_tag mem_tag;
+ addr_index mem_index;
assign mem_end = (mem_read || mem_write) && !mem_waitrequest;
assign mem_wait = (mem_read || mem_write) && mem_waitrequest;
@@ -135,6 +135,7 @@ module cache_control
monitor_fail = 0;
monitor_acquire = 0;
+ monitor_release = 0;
core_waitrequest = 1;
in_data_ready = !in_hold_valid;
@@ -146,17 +147,19 @@ module cache_control
end_reply = in_hold_valid; // Se termina el paso de ese mensaje
in_data_ready = 1;
end
+
// Si no es el último salto y hay reply
- if (!last_hop && in_hold.reply)
+ if (!last_hop && in_hold.reply && !in_hold.inval)
in_data_ready = 1;
if (accept_snoop)
index_rd = in_hold.index;
+
+ if (debug)
+ index_rd = debug_index;
end
CORE: begin
- monitor_acquire = core_read && core_lock;
-
if (replace) begin
state_wr = INVALID;
write_state = 1;
@@ -175,8 +178,10 @@ module cache_control
send_inval = 1;
end
- {SHARED, 1'b0}:
+ {SHARED, 1'b0}: begin
+ monitor_acquire = core_lock;
core_waitrequest = 0;
+ end
{SHARED, 1'b1}: begin
/* No hacemos write_data ya que reintentaremos el
@@ -192,8 +197,10 @@ module cache_control
send_inval = 1;
end
- {EXCLUSIVE, 1'b0}:
+ {EXCLUSIVE, 1'b0}: begin
+ monitor_acquire = core_lock;
core_waitrequest = 0;
+ end
{EXCLUSIVE, 1'b1}: begin
state_wr = MODIFIED;
@@ -201,19 +208,28 @@ module cache_control
write_state = monitor_commit;
monitor_fail = !monitor_commit;
+ monitor_release = core_lock;
+
core_waitrequest = 0;
end
- {MODIFIED, 1'b0}:
+ {MODIFIED, 1'b0}: begin
+ monitor_acquire = core_lock;
core_waitrequest = 0;
+ end
{MODIFIED, 1'b1}: begin
write_data = monitor_commit;
monitor_fail = !monitor_commit;
+ monitor_release = core_lock;
+
core_waitrequest = 0;
end
endcase
+
+ if (monitor_release)
+ data_wr = monitor_update;
end
SNOOP: begin
@@ -286,6 +302,9 @@ module cache_control
write_data = 0;
write_state = 0;
+ monitor_acquire = 0;
+ monitor_release = 0;
+
in_data_ready = !in_hold_valid;
core_waitrequest = 1;
end
@@ -314,6 +333,7 @@ module cache_control
end
always_comb begin
+ debug = 0;
next_state = ACCEPT;
unique case (state)
@@ -322,6 +342,8 @@ module cache_control
next_state = SNOOP;
else if (in_hold_valid && last_hop && in_hold.read)
next_state = REPLY;
+ else if (dbg_write && !debug_ready)
+ debug = 1;
else if ((core_read || core_write) && !wait_reply && (!locked || may_send))
next_state = CORE;
@@ -349,6 +371,8 @@ module cache_control
mem_read <= 0;
mem_write <= 0;
+
+ debug_ready <= 0;
end else begin
out_token.e0.tag <= core_tag;
out_token.e0.index <= core_index;
@@ -384,6 +408,8 @@ module cache_control
mem_read <= !writeback;
mem_write <= writeback;
end
+
+ debug_ready <= debug;
end
always_ff @(posedge clk) begin
@@ -398,14 +424,6 @@ module cache_control
mem_index <= index_wr;
mem_writedata <= data_rd;
end
-
- if (monitor_acquire && !core_waitrequest) begin
- monitor_tag <= core_tag;
- monitor_index <= core_index;
-
- monitor_data_rd <= data_rd;
- monitor_data_wr <= data_rd;
- end
end
endmodule
diff --git a/rtl/cache/cache_debug.sv b/rtl/cache/cache_debug.sv
new file mode 100644
index 0000000..14b73e5
--- /dev/null
+++ b/rtl/cache/cache_debug.sv
@@ -0,0 +1,71 @@
+`include "cache/defs.sv"
+
+module cache_debug
+(
+ input logic clk,
+ rst_n,
+
+ input logic[2:0] dbg_address,
+ input logic dbg_read,
+ input word dbg_writedata,
+ output logic dbg_waitrequest,
+ output word dbg_readdata,
+
+ input logic debug_ready,
+ input addr_tag tag_rd,
+ input line data_rd,
+ input line_state state_rd,
+ output addr_index debug_index
+);
+
+ struct packed
+ {
+ logic[2:0] mbz_0;
+ addr_tag tag;
+ addr_index index;
+ line_state state;
+ logic cached,
+ mbz_1;
+ } status;
+
+ line line_dump;
+ word word_dump, word_3, word_2, word_1, word_0;
+ addr_bits debug_addr_bits;
+
+ logic cached;
+ addr_tag tag;
+ addr_index index;
+ line_state state;
+
+ assign debug_index = debug_addr_bits.index;
+ assign dbg_readdata = dbg_address[2] ? word_dump : status;
+ assign dbg_waitrequest = !debug_ready && !dbg_read;
+
+ assign status.tag = tag;
+ assign status.index = index;
+ assign status.state = state;
+ assign status.mbz_0 = 3'b000;
+ assign status.mbz_1 = 0;
+ assign status.cached = cached;
+ assign debug_addr_bits = dbg_writedata;
+
+ assign {word_3, word_2, word_1, word_0} = line_dump;
+
+ always_comb
+ unique case (dbg_address[1:0])
+ 2'b00: word_dump = word_0;
+ 2'b01: word_dump = word_1;
+ 2'b10: word_dump = word_2;
+ 2'b11: word_dump = word_3;
+ endcase
+
+ always @(posedge clk)
+ if (debug_ready) begin
+ tag <= tag_rd;
+ index <= debug_addr_bits.index;
+ state <= state_rd;
+ cached <= !(|debug_addr_bits.io);
+ line_dump <= data_rd;
+ end
+
+endmodule
diff --git a/rtl/cache/defs.sv b/rtl/cache/defs.sv
index e21e587..d7c43dc 100644
--- a/rtl/cache/defs.sv
+++ b/rtl/cache/defs.sv
@@ -13,21 +13,30 @@ typedef logic[31:0] word;
`endif
/* Tenemos 512MiB de SDRAM, el resto del espacio es I/O (uncached). Usamos
- * 512 líneas direct-mapped de 16 bytes cada una. El core solo realiza
+ * 4096 líneas direct-mapped de 16 bytes cada una. El core solo realiza
* operaciones alineadas. Por tanto, cada dirección de 32 bits consta de:
* - 2 bits que siempre son 0 (traducidos a byteenable por core)
* - 2 bits de offset (ya que para cache la unidad direccionable es la word)
- * - 9 bits de index
- * - 16 bits de tag
+ * - 12 bits de index
+ * - 13 bits de tag
* - 3 bits que son == 0 si cached, != 0 si uncached
*/
typedef logic[1:0] addr_mbz;
typedef logic[1:0] addr_offset;
-typedef logic[8:0] addr_index;
-typedef logic[15:0] addr_tag;
+typedef logic[11:0] addr_index;
+typedef logic[12:0] addr_tag;
typedef logic[2:0] addr_io_region;
typedef logic[26:0] addr_cacheable;
+typedef struct packed
+{
+ addr_io_region io;
+ addr_tag tag;
+ addr_index index;
+ addr_offset offset;
+ addr_mbz mbz;
+} addr_bits;
+
typedef enum logic[1:0]
{
INVALID,
diff --git a/rtl/cache/monitor.sv b/rtl/cache/monitor.sv
new file mode 100644
index 0000000..b7f0d15
--- /dev/null
+++ b/rtl/cache/monitor.sv
@@ -0,0 +1,103 @@
+`include "cache/defs.sv"
+
+module cache_monitor
+(
+ input logic clk,
+ rst_n,
+
+ input addr_tag core_tag,
+ input addr_index core_index,
+ input addr_offset core_offset,
+ input logic core_lock,
+ input word core_writedata,
+ output logic[1:0] core_response,
+
+ input line data_rd,
+
+ input logic monitor_acquire,
+ monitor_fail,
+ monitor_release,
+ output line monitor_update,
+ output logic monitor_commit
+);
+
+ line monitor_rd, monitor_wr;
+ word update_3, update_2, update_1, update_0;
+ logic dirty, done, hit, known;
+ addr_tag tag;
+ addr_index index;
+
+ logic[3:0] mask, mask_clear, core_ex_mask;
+
+ assign monitor_commit = !core_lock || (hit && known && done);
+ assign monitor_update = {update_3, update_2, update_1, update_0};
+
+ /* Avalon p. 15:
+ * - 00: OKAY - Successful response for a transaction.
+ * - 10: SLVERR - Error from an endpoint agent. Indicates an unsuccessful transaction.
+ */
+ assign core_response = {monitor_fail, 1'b0};
+
+ assign hit = tag == core_tag && index == core_index;
+ assign done = monitor_rd == data_rd && mask_clear == 4'b0000;
+ assign known = mask[core_offset];
+ assign mask_clear = mask & ~core_ex_mask;
+
+ always_comb begin
+ {update_3, update_2, update_1, update_0} = monitor_wr;
+
+ unique case (core_offset)
+ 2'b00: begin
+ update_0 = core_writedata;
+ core_ex_mask = 4'b0001;
+ end
+
+ 2'b01: begin
+ update_1 = core_writedata;
+ core_ex_mask = 4'b0010;
+ end
+
+ 2'b10: begin
+ update_2 = core_writedata;
+ core_ex_mask = 4'b0100;
+ end
+
+ 2'b11: begin
+ update_3 = core_writedata;
+ core_ex_mask = 4'b1000;
+ end
+ endcase
+ end
+
+ always @(posedge clk or negedge rst_n)
+ if (!rst_n) begin
+ mask <= 4'b0000;
+ dirty <= 0;
+ end else begin
+ if (monitor_acquire) begin
+ mask <= hit && !known && !dirty ? mask | core_ex_mask : core_ex_mask;
+ dirty <= 0;
+ end
+
+ if (monitor_release) begin
+ mask <= hit && known ? mask_clear : 4'b0000;
+ dirty <= hit && known;
+ end
+ end
+
+ always_ff @(posedge clk) begin
+ if (monitor_acquire) begin
+ tag <= core_tag;
+ index <= core_index;
+
+ if (!hit || known || dirty || mask == 4'b0000) begin
+ monitor_rd <= data_rd;
+ monitor_wr <= data_rd;
+ end
+ end
+
+ if (monitor_release)
+ monitor_wr <= monitor_update;
+ end
+
+endmodule
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,