Add basic support for lr/sc instructions from the A extension

This commit is contained in:
Luke Wren 2021-12-04 15:02:31 +00:00
parent c5d6be24f3
commit 5e17bb805e
16 changed files with 4937 additions and 3968 deletions

View File

@ -4,6 +4,7 @@ Hazard3 is a 3-stage RISC-V processor, implementing the `RV32I` instruction set
* `M`: integer multiply/divide/modulo
* `C`: compressed instructions
* `A` _(partial)_: load reserved/store conditional instructions, with AHB5 HEXCL/HEXOKAY signalling for global monitor queries
* `Zicsr`: CSR access
* `Zba`: address generation
* `Zbb`: basic bit manipulation
@ -23,7 +24,8 @@ _Note: the bit manipulation instructions don't have upstream compliance tests at
The following are planned for future implementation:
* `A` extension: atomic memory access
* Complete support for the `A` extension: atomic memory operations
* Debug trigger unit (breakpoint-only)
Hazard3 is still under development.

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
== Instruction Cycle Counts
All timings are given assuming perfect bus behaviour (no stalls). Stalling of the `I` bus can delay execution indefinitely, as can stalling of the `D` bus during a load or store.
All timings are given assuming perfect bus behaviour (no downstream bus stalls).
=== RV32I
@ -72,6 +72,17 @@ Timings assume the core is configured with `MULDIV_UNROLL = 2` and `MUL_FAST = 1
| `remu rd, rs1, rs2` | 18 |
|===
=== A Extension
[%autowidth.stretch, options="header"]
|===
| Instruction | Cycles | Note
| `lr.w rd, (rs1)` | 1 or 2 | 1 if next instruction is independent, 2 if dependent.footnote:data_dependency[]
| `sc.w rd, rs2, (rs1)` | 1 | `lr.w` followed by `sc.w` always inserts a dependency stall.footnote:lr_to_sc[A 1-cycle pipeline bubble is inserted in between an `lr.w` and an immediately-following `sc.w`, so that the store can be suppressed by a reservation failure on the load. It does not matter whether the `lr.w` and `sc.w` use the same registers. Load reservation may fail if the memory region does not support exclusive transfers.]
|===
AMOs are currently not supported.
=== C Extension
All C extension 16-bit instructions on Hazard3 are aliases of base RV32I instructions. They perform identically to their 32-bit counterparts.

View File

@ -221,8 +221,10 @@ wire [2:0] proc_hsize;
wire [2:0] proc_hburst;
wire [3:0] proc_hprot;
wire proc_hmastlock;
wire proc_hexcl;
wire proc_hready;
wire proc_hresp;
wire proc_hexokay = 1'b1; // No global monitor
wire [W_DATA-1:0] proc_hwdata;
wire [W_DATA-1:0] proc_hrdata;
@ -264,8 +266,10 @@ hazard3_cpu_1port #(
.ahblm_hburst (proc_hburst),
.ahblm_hprot (proc_hprot),
.ahblm_hmastlock (proc_hmastlock),
.ahblm_hexcl (proc_hexcl),
.ahblm_hready (proc_hready),
.ahblm_hresp (proc_hresp),
.ahblm_hexokay (proc_hexokay),
.ahblm_hwdata (proc_hwdata),
.ahblm_hrdata (proc_hrdata),

View File

@ -31,6 +31,10 @@ parameter MTVEC_INIT = 32'h00000000,
// ----------------------------------------------------------------------------
// RISC-V ISA and CSR support
// EXTENSION_A: Support for atomic read/modify/write instructions
// (currently, only lr.w/sc.w are supported)
parameter EXTENSION_A = 1,
// EXTENSION_C: Support for compressed (variable-width) instructions
parameter EXTENSION_C = 1,

View File

@ -4,6 +4,7 @@
.RESET_VECTOR (RESET_VECTOR),
.MTVEC_INIT (MTVEC_INIT),
.EXTENSION_A (EXTENSION_A),
.EXTENSION_C (EXTENSION_C),
.EXTENSION_M (EXTENSION_M),
.EXTENSION_ZBA (EXTENSION_ZBA),

View File

@ -43,9 +43,11 @@ module hazard3_core #(
// Load/store port
output reg bus_aph_req_d,
output wire bus_aph_excl_d,
input wire bus_aph_ready_d,
input wire bus_dph_ready_d,
input wire bus_dph_err_d,
input wire bus_dph_exokay_d,
output reg [W_ADDR-1:0] bus_haddr_d,
output reg [2:0] bus_hsize_d,
@ -300,6 +302,9 @@ always @ (*) begin
x_stall_raw =
|xm_rd && (xm_rd == d_rs1 || xm_rd == d_rs2) ||
|mw_rd && (mw_rd == d_rs1 || mw_rd == d_rs2);
end else if (|EXTENSION_A && xm_memop == MEMOP_LR_W && d_memop == MEMOP_SC_W) begin
// Conditional-store address phase depends on data-phase update of local monitor bit
x_stall_raw = 1'b1;
end else if (m_generating_result) begin
// With the full bypass network, load-use (or fast multiply-use) is the only RAW stall
if (|xm_rd && xm_rd == d_rs1) begin
@ -358,13 +363,24 @@ hazard3_alu #(
// AHB transaction request
wire x_memop_vld = !d_memop[3];
wire x_memop_write = d_memop == MEMOP_SW || d_memop == MEMOP_SH || d_memop == MEMOP_SB;
reg mw_local_exclusive_reserved;
wire x_memop_vld = d_memop != MEMOP_NONE && !(
|EXTENSION_A && d_memop == MEMOP_SC_W && !mw_local_exclusive_reserved
);
wire x_memop_write =
d_memop == MEMOP_SW || d_memop == MEMOP_SH || d_memop == MEMOP_SB ||
|EXTENSION_A && d_memop == MEMOP_SC_W;
wire x_unaligned_addr = d_memop != MEMOP_NONE && (
bus_hsize_d == HSIZE_WORD && |bus_haddr_d[1:0] ||
bus_hsize_d == HSIZE_HWORD && bus_haddr_d[0]
);
// Always query the global monitor, except for store-conditional suppressed by local monitor.
assign bus_aph_excl_d = |EXTENSION_A && (d_memop == MEMOP_LR_W || d_memop == MEMOP_SC_W);
always @ (*) begin
// Need to be careful not to use anything hready-sourced to gate htrans!
bus_haddr_d = x_alu_add;
@ -609,7 +625,9 @@ always @ (posedge clk or negedge rst_n) begin
`ifdef FORMAL
assert(xm_memop != MEMOP_NONE);
`endif
xm_except <= xm_memop <= MEMOP_LBU ? EXCEPT_LOAD_FAULT : EXCEPT_STORE_FAULT;
xm_except <=
|EXTENSION_A && xm_memop == MEMOP_LR_W ? EXCEPT_LOAD_FAULT :
xm_memop <= MEMOP_LBU ? EXCEPT_LOAD_FAULT : EXCEPT_STORE_FAULT;
xm_wfi <= 1'b0;
end
end
@ -648,7 +666,10 @@ assign f_jump_req = x_jump_req || m_trap_enter_vld;
assign f_jump_target = m_trap_enter_vld ? m_trap_addr : x_jump_target;
assign x_jump_not_except = !m_trap_enter_vld;
wire m_bus_stall = xm_memop != MEMOP_NONE && !bus_dph_ready_d;
wire m_bus_stall = xm_memop != MEMOP_NONE && !bus_dph_ready_d && !(
|EXTENSION_A && xm_memop == MEMOP_SC_W && !mw_local_exclusive_reserved
);
assign m_stall = m_bus_stall ||
(m_trap_enter_vld && !m_trap_enter_rdy && !m_trap_is_irq) ||
(xm_wfi && !m_wfi_stall_clear);
@ -672,10 +693,9 @@ always @ (*) begin
end
// Replicate store data to ensure appropriate byte lane is driven
case (xm_memop)
MEMOP_SW: bus_wdata_d = m_wdata;
MEMOP_SH: bus_wdata_d = {2{m_wdata[15:0]}};
MEMOP_SB: bus_wdata_d = {4{m_wdata[7:0]}};
default: bus_wdata_d = 32'h0;
default: bus_wdata_d = m_wdata; // TODO worth it to mask when not writing? Costs LUTs, saves energy
endcase
casez ({xm_memop, xm_result[1:0]})
@ -694,7 +714,10 @@ always @ (*) begin
default: m_rdata_pick_sext = bus_rdata_d;
endcase
if (xm_memop != MEMOP_NONE) begin
if (|EXTENSION_A && xm_memop == MEMOP_SC_W) begin
// sc.w may fail due to negative response from either local or global monitor.
m_result = {31'h0, mw_local_exclusive_reserved && bus_dph_exokay_d};
end else if (xm_memop != MEMOP_NONE) begin
m_result = m_rdata_pick_sext;
end else if (MUL_FAST && m_fast_mul_result_vld) begin
m_result = m_fast_mul_result;
@ -703,11 +726,28 @@ always @ (*) begin
end
end
// Local monitor update.
// - Set on a load-reserved with good response from global monitor
// - Cleared by any store-conditional
// - Not affected by trap entry (permitted by RISC-V spec)
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
mw_local_exclusive_reserved <= 1'b0;
end else if (|EXTENSION_A && !m_stall) begin
if (xm_memop == MEMOP_SC_W) begin
mw_local_exclusive_reserved <= 1'b0;
end else if (xm_memop == MEMOP_LR_W) begin
mw_local_exclusive_reserved <= bus_dph_exokay_d;
end
end
end
// Note that exception entry prevents writeback, because the exception entry
// replaces the instruction in M. Interrupt entry does not prevent writeback,
// because the interrupt is notionally inserted in between the instruction in
// M and the instruction in X.
wire m_reg_wen_if_nonzero = !m_bus_stall && xm_except == EXCEPT_NONE;
wire m_reg_wen = |xm_rd && m_reg_wen_if_nonzero;

View File

@ -40,8 +40,10 @@ module hazard3_cpu_1port #(
output wire [2:0] ahblm_hburst,
output reg [3:0] ahblm_hprot,
output wire ahblm_hmastlock,
output reg ahblm_hexcl,
input wire ahblm_hready,
input wire ahblm_hresp,
input wire ahblm_hexokay,
output wire [W_DATA-1:0] ahblm_hwdata,
input wire [W_DATA-1:0] ahblm_hrdata,
@ -85,9 +87,11 @@ wire [W_DATA-1:0] core_rdata_i;
// Load/store signals
wire core_aph_req_d;
wire core_aph_excl_d;
wire core_aph_ready_d;
wire core_dph_ready_d;
wire core_dph_err_d;
wire core_dph_exokay_d;
wire [W_ADDR-1:0] core_haddr_d;
wire [2:0] core_hsize_d;
@ -116,9 +120,11 @@ hazard3_core #(
.bus_rdata_i (core_rdata_i),
.bus_aph_req_d (core_aph_req_d),
.bus_aph_excl_d (core_aph_excl_d),
.bus_aph_ready_d (core_aph_ready_d),
.bus_dph_ready_d (core_dph_ready_d),
.bus_dph_err_d (core_dph_err_d),
.bus_dph_exokay_d (core_dph_exokay_d),
.bus_haddr_d (core_haddr_d),
.bus_hsize_d (core_hsize_d),
.bus_hwrite_d (core_hwrite_d),
@ -144,7 +150,6 @@ hazard3_core #(
.timer_irq (timer_irq)
);
// ----------------------------------------------------------------------------
// Arbitration state machine
@ -201,18 +206,21 @@ assign ahblm_hmastlock = 1'b0;
always @ (*) begin
if (bus_gnt_d) begin
ahblm_htrans = HTRANS_NSEQ;
ahblm_hexcl = core_aph_excl_d;
ahblm_haddr = core_haddr_d;
ahblm_hsize = core_hsize_d;
ahblm_hwrite = core_hwrite_d;
ahblm_hprot = HPROT_DATA;
end else if (bus_gnt_i) begin
ahblm_htrans = HTRANS_NSEQ;
ahblm_hexcl = 1'b0;
ahblm_haddr = core_haddr_i;
ahblm_hsize = core_hsize_i;
ahblm_hwrite = 1'b0;
ahblm_hprot = HPROT_INSTR;
end else begin
ahblm_htrans = HTRANS_IDLE;
ahblm_hexcl = 1'b0;
ahblm_haddr = {W_ADDR{1'b0}};
ahblm_hsize = 3'h0;
ahblm_hwrite = 1'b0;
@ -239,6 +247,7 @@ assign core_dph_err_i = bus_active_dph_i && ahblm_hresp;
assign core_aph_ready_d = ahblm_hready && bus_gnt_d;
assign core_dph_ready_d = ahblm_hready && bus_active_dph_d;
assign core_dph_err_d = bus_active_dph_d && ahblm_hresp;
assign core_dph_exokay_d = bus_active_dph_d && ahblm_hexokay;
endmodule

View File

@ -53,8 +53,10 @@ module hazard3_cpu_2port #(
output wire [2:0] d_hburst,
output wire [3:0] d_hprot,
output wire d_hmastlock,
output wire d_hexcl,
input wire d_hready,
input wire d_hresp,
input wire d_hexokay,
output wire [W_DATA-1:0] d_hwdata,
input wire [W_DATA-1:0] d_hrdata,
@ -98,9 +100,11 @@ wire [W_DATA-1:0] core_rdata_i;
// Load/store signals
wire core_aph_req_d;
wire core_aph_excl_d;
wire core_aph_ready_d;
wire core_dph_ready_d;
wire core_dph_err_d;
wire core_dph_exokay_d;
wire [W_ADDR-1:0] core_haddr_d;
wire [2:0] core_hsize_d;
@ -112,8 +116,8 @@ wire [W_DATA-1:0] core_rdata_d;
hazard3_core #(
`include "hazard3_config_inst.vh"
) core (
.clk (clk),
.rst_n (rst_n),
.clk (clk),
.rst_n (rst_n),
`ifdef RISCV_FORMAL
`RVFI_CONN ,
@ -129,9 +133,11 @@ hazard3_core #(
.bus_rdata_i (core_rdata_i),
.bus_aph_req_d (core_aph_req_d),
.bus_aph_excl_d (core_aph_excl_d),
.bus_aph_ready_d (core_aph_ready_d),
.bus_dph_ready_d (core_dph_ready_d),
.bus_dph_err_d (core_dph_err_d),
.bus_dph_exokay_d (core_dph_exokay_d),
.bus_haddr_d (core_haddr_d),
.bus_hsize_d (core_hsize_d),
.bus_hwrite_d (core_hwrite_d),
@ -193,6 +199,7 @@ assign d_haddr = core_haddr_d;
assign d_htrans = core_aph_req_d ? HTRANS_NSEQ : HTRANS_IDLE;
assign d_hwrite = core_hwrite_d;
assign d_hsize = core_hsize_d;
assign d_hexcl = core_aph_excl_d;
reg dphase_active_d;
always @ (posedge clk or negedge rst_n)
@ -207,6 +214,7 @@ always @ (posedge clk or negedge rst_n)
assign core_aph_ready_d = d_hready && core_aph_req_d;
assign core_dph_ready_d = d_hready && dphase_active_d;
assign core_dph_err_d = dphase_active_d && d_hresp;
assign core_dph_exokay_d = dphase_active_d && d_hexokay;
assign core_rdata_d = d_hrdata;
assign d_hwdata = core_wdata_d;

View File

@ -234,6 +234,7 @@ always @ (*) begin
RV_SB: begin d_aluop = ALUOP_ADD; d_imm = d_imm_s; d_alusrc_b = ALUSRCB_IMM; d_memop = MEMOP_SB; d_rd = X0; end
RV_SH: begin d_aluop = ALUOP_ADD; d_imm = d_imm_s; d_alusrc_b = ALUSRCB_IMM; d_memop = MEMOP_SH; d_rd = X0; end
RV_SW: begin d_aluop = ALUOP_ADD; d_imm = d_imm_s; d_alusrc_b = ALUSRCB_IMM; d_memop = MEMOP_SW; d_rd = X0; end
RV_MUL: if (EXTENSION_M) begin d_aluop = ALUOP_MULDIV; d_mulop = M_OP_MUL; end else begin d_invalid_32bit = 1'b1; end
RV_MULH: if (EXTENSION_M) begin d_aluop = ALUOP_MULDIV; d_mulop = M_OP_MULH; end else begin d_invalid_32bit = 1'b1; end
RV_MULHSU: if (EXTENSION_M) begin d_aluop = ALUOP_MULDIV; d_mulop = M_OP_MULHSU; end else begin d_invalid_32bit = 1'b1; end
@ -242,9 +243,14 @@ always @ (*) begin
RV_DIVU: if (EXTENSION_M) begin d_aluop = ALUOP_MULDIV; d_mulop = M_OP_DIVU; end else begin d_invalid_32bit = 1'b1; end
RV_REM: if (EXTENSION_M) begin d_aluop = ALUOP_MULDIV; d_mulop = M_OP_REM; end else begin d_invalid_32bit = 1'b1; end
RV_REMU: if (EXTENSION_M) begin d_aluop = ALUOP_MULDIV; d_mulop = M_OP_REMU; end else begin d_invalid_32bit = 1'b1; end
RV_LR_W: if (EXTENSION_A) begin d_imm = X0; d_alusrc_b = ALUSRCB_IMM; d_rs2 = X0; d_memop = MEMOP_LR_W; end
RV_SC_W: if (EXTENSION_A) begin d_imm = X0; d_alusrc_b = ALUSRCB_IMM; d_memop = MEMOP_SC_W; end
RV_SH1ADD: if (EXTENSION_ZBA) begin d_aluop = ALUOP_SH1ADD; end else begin d_invalid_32bit = 1'b1; end
RV_SH2ADD: if (EXTENSION_ZBA) begin d_aluop = ALUOP_SH2ADD; end else begin d_invalid_32bit = 1'b1; end
RV_SH3ADD: if (EXTENSION_ZBA) begin d_aluop = ALUOP_SH3ADD; end else begin d_invalid_32bit = 1'b1; end
RV_ANDN: if (EXTENSION_ZBB) begin d_aluop = ALUOP_ANDN; end else begin d_invalid_32bit = 1'b1; end
RV_CLZ: if (EXTENSION_ZBB) begin d_aluop = ALUOP_CLZ; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
RV_CPOP: if (EXTENSION_ZBB) begin d_aluop = ALUOP_CPOP; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
@ -263,6 +269,7 @@ always @ (*) begin
RV_SEXT_H: if (EXTENSION_ZBB) begin d_aluop = ALUOP_SEXT_H; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
RV_XNOR: if (EXTENSION_ZBB) begin d_aluop = ALUOP_XNOR; end else begin d_invalid_32bit = 1'b1; end
RV_ZEXT_H: if (EXTENSION_ZBB) begin d_aluop = ALUOP_ZEXT_H; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
RV_CLMUL: if (EXTENSION_ZBC) begin d_aluop = ALUOP_CLMUL; end else begin d_invalid_32bit = 1'b1; end
RV_CLMULH: if (EXTENSION_ZBC) begin d_aluop = ALUOP_CLMULH; end else begin d_invalid_32bit = 1'b1; end
RV_CLMULR: if (EXTENSION_ZBC) begin d_aluop = ALUOP_CLMULR; end else begin d_invalid_32bit = 1'b1; end
@ -274,6 +281,7 @@ always @ (*) begin
RV_BINVI: if (EXTENSION_ZBC) begin d_aluop = ALUOP_BINV; d_rs2 = X0; d_imm = d_imm_i; d_alusrc_b = ALUSRCB_IMM; end else begin d_invalid_32bit = 1'b1; end
RV_BSET: if (EXTENSION_ZBC) begin d_aluop = ALUOP_BSET; end else begin d_invalid_32bit = 1'b1; end
RV_BSETI: if (EXTENSION_ZBC) begin d_aluop = ALUOP_BSET; d_rs2 = X0; d_imm = d_imm_i; d_alusrc_b = ALUSRCB_IMM; end else begin d_invalid_32bit = 1'b1; end
RV_FENCE: begin d_rd = X0; end // NOP
RV_FENCE_I: begin d_invalid_32bit = DEBUG_SUPPORT && debug_mode; d_rd = X0; d_rs1 = X0; d_rs2 = X0; d_branchcond = BCOND_NZERO; d_imm[31] = 1'b1; end // FIXME this is probably busted now. Maybe implement as an exception?
RV_CSRRW: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = 1'b1 ; d_csr_ren = |d_rd; d_csr_wtype = CSR_WTYPE_W; end else begin d_invalid_32bit = 1'b1; end

View File

@ -0,0 +1,5 @@
SRCS := ../common/init.S main.c
APP := lr_sc_smoke
CCFLAGS = -march=rv32imac -Os
include ../common/src_only_app.mk

View File

@ -0,0 +1,43 @@
[*]
[*] GTKWave Analyzer v3.3.103 (w)1999-2019 BSI
[*] Sat Dec 4 14:31:51 2021
[*]
[dumpfile] "/home/luke/proj/hazard3/test/sim/lr_sc_smoke/lr_sc_smoke_run.vcd"
[dumpfile_mtime] "Sat Dec 4 14:20:04 2021"
[dumpfile_size] 2577335
[savefile] "/home/luke/proj/hazard3/test/sim/lr_sc_smoke/lr_sc_smoke.gtkw"
[timestart] 842
[size] 1975 1095
[pos] -1 -1
*-2.000000 856 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[sst_width] 233
[signals_width] 246
[sst_expanded] 1
[sst_vpaned_height] 317
@22
core.d_pc[31:0]
@28
core.mw_local_exclusive_reserved
core.m_stall
core.x_stall
core.x_stall_raw
@200
-
@22
d_haddr[31:0]
@28
d_htrans[1:0]
d_hsize[2:0]
d_hexcl
d_hwrite
d_hready
@22
d_hwdata[31:0]
d_hrdata[31:0]
@200
-
@22
core.x_rs2_bypass[31:0]
core.xm_store_data[31:0]
[pattern_trace] 1
[pattern_trace] 0

View File

@ -0,0 +1,65 @@
#include "tb_cxxrtl_io.h"
#include <stdint.h>
volatile uint32_t scratch[2];
#define test_assert(cond, ...) if (!(cond)) {tb_printf(__VA_ARGS__); return -1;}
int main() {
uint32_t load_result, success;
tb_puts("Test 1: lr.w -> nop -> sc.w\n");
scratch[0] = 0x1234;
asm volatile (
"lr.w %0, (%2)\n"
"nop\n"
"sc.w %1, %3, (%2)\n"
: "=r" (load_result), "=r" (success)
: "r" (&scratch[0]), "r" (0x5678)
);
test_assert(load_result == 0x1234, "Bad load result %08x\n", load_result);
test_assert(scratch[0] == 0x5678, "Store didn't write memory\n");
test_assert(success == 1, "Should report success\n");
tb_puts("OK\n");
tb_puts("Test 2: lr.w -> sc.w\n");
scratch[0] = 0xabcd;
asm volatile (
"lr.w %0, (%2)\n"
"sc.w %1, %3, (%2)\n"
: "=r" (load_result), "=r" (success)
: "r" (&scratch[0]), "r" (0xa5a5)
);
test_assert(load_result == 0xabcd, "Bad load result %08x\n", load_result);
test_assert(scratch[0] == 0xa5a5, "Store didn't write memory\n");
test_assert(success == 1, "Should report success\n");
tb_puts("OK\n");
tb_puts("Test 3: sc.w with no preceding lr.w\n");
scratch[0] = 0x1234;
asm volatile (
"sc.w %0, %2, (%1)\n"
: "=r" (success)
: "r" (&scratch[0]), "r" (0x5678)
);
test_assert(scratch[0] == 0x1234, "Store shouldn't write memory\n");
test_assert(success == 0, "Should report failure\n");
tb_puts("OK\n");
// Reservation is only cleared by other harts' stores.
tb_puts("Test 4: lr.w -> sw -> sc.w\n");
scratch[0] = 0x1234;
scratch[1] = 0;
asm volatile (
"lr.w %0, (%2)\n"
"sw %3, 4(%2)\n"
"sc.w %1, %4, (%2)\n"
: "=r" (load_result), "=r" (success)
: "r" (&scratch[0]), "r" (0xabcd), "r" (0x5678)
);
test_assert(scratch[1] == 0xabcd, "Regular store should succeed\n");
test_assert(scratch[0] == 0x5678, "sc didn't write memory\n");
test_assert(success == 1, "Should report success\n");
tb_puts("OK\n");
return 0;
}

View File

@ -153,6 +153,7 @@ int main(int argc, char **argv) {
// Never generate bus stalls
top.p_i__hready.set<bool>(true);
top.p_d__hready.set<bool>(true);
top.p_d__hexokay.set<bool>(true);
uint64_t mtime = 0;
uint64_t mtimecmp = 0;

View File

@ -36,12 +36,14 @@ module tb #(
output wire [W_ADDR-1:0] d_haddr,
output wire d_hwrite,
output wire [1:0] d_htrans,
output wire d_hexcl,
output wire [2:0] d_hsize,
output wire [2:0] d_hburst,
output wire [3:0] d_hprot,
output wire d_hmastlock,
input wire d_hready,
input wire d_hresp,
input wire d_hexokay,
output wire [W_DATA-1:0] d_hwdata,
input wire [W_DATA-1:0] d_hrdata,
@ -213,6 +215,7 @@ hazard3_cpu_2port #(
.i_hrdata (i_hrdata),
.d_haddr (d_haddr),
.d_hexcl (d_hexcl),
.d_hwrite (d_hwrite),
.d_htrans (d_htrans),
.d_hsize (d_hsize),
@ -221,6 +224,7 @@ hazard3_cpu_2port #(
.d_hmastlock (d_hmastlock),
.d_hready (d_hready),
.d_hresp (d_hresp),
.d_hexokay (d_hexokay),
.d_hwdata (d_hwdata),
.d_hrdata (d_hrdata),

View File

@ -115,8 +115,10 @@ int main(int argc, char **argv) {
#ifdef DUAL_PORT
top.p_i__hready.set<bool>(true);
top.p_d__hready.set<bool>(true);
top.p_d__hexokay.set<bool>(true);
#else
top.p_ahblm__hready.set<bool>(true);
top.p_ahblm__hexokay.set<bool>(true);
#endif
uint64_t mtime = 0;