-
-
Save jbush001/636812836911d5c7873893a1d0ae517e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/hardware/core/core.sv b/hardware/core/core.sv | |
index 3b40e196..91911fb8 100644 | |
--- a/hardware/core/core.sv | |
+++ b/hardware/core/core.sv | |
@@ -51,6 +51,9 @@ module core | |
output logic ior_request_valid, | |
output ioreq_packet_t ior_request, | |
+ // To/From coprocessor | |
+ coprocessor_bus_interface.master coprocessor_bus, | |
+ | |
// From debug_controller | |
input ocd_halt, | |
input local_thread_idx_t ocd_thread, | |
@@ -84,6 +87,12 @@ module core | |
cache_line_index_t dd_cache_miss_addr; // From dcache_data_stage of dcache_data_stage.v | |
logic dd_cache_miss_sync; // From dcache_data_stage of dcache_data_stage.v | |
local_thread_idx_t dd_cache_miss_thread_idx;// From dcache_data_stage of dcache_data_stage.v | |
+ logic dd_coproc_access; // From dcache_data_stage of dcache_data_stage.v | |
+ scalar_t dd_coproc_address; // From dcache_data_stage of dcache_data_stage.v | |
+ logic dd_coproc_read_en; // From dcache_data_stage of dcache_data_stage.v | |
+ local_thread_idx_t dd_coproc_thread_idx; // From dcache_data_stage of dcache_data_stage.v | |
+ vector_t dd_coproc_write_data; // From dcache_data_stage of dcache_data_stage.v | |
+ logic dd_coproc_write_en; // From dcache_data_stage of dcache_data_stage.v | |
control_register_t dd_creg_index; // From dcache_data_stage of dcache_data_stage.v | |
logic dd_creg_read_en; // From dcache_data_stage of dcache_data_stage.v | |
logic dd_creg_write_en; // From dcache_data_stage of dcache_data_stage.v | |
@@ -346,6 +355,10 @@ module core | |
logic wb_writeback_vector; // From writeback_stage of writeback_stage.v | |
// End of automatics | |
+ local_thread_bitmap_t coproc_wake_bitmap; | |
+ vector_t coproc_read_data; | |
+ logic coproc_ack; | |
+ | |
// | |
// Instruction Execution Pipeline | |
// | |
@@ -379,6 +392,15 @@ module core | |
injected_rollback <= wb_inst_injected & wb_rollback_en; | |
end | |
+ assign coproc_wake_bitmap = coprocessor_bus.wake_bitmap; | |
+ assign coproc_read_data = coprocessor_bus.read_data; | |
+ assign coproc_ack = coprocessor_bus.ack; | |
+ assign coprocessor_bus.write_en = dd_coproc_write_en; | |
+ assign coprocessor_bus.read_en = dd_coproc_read_en; | |
+ assign coprocessor_bus.address = dd_coproc_address; | |
+ assign coprocessor_bus.thread_idx = dd_coproc_thread_idx; | |
+ assign coprocessor_bus.write_data = dd_coproc_write_data; | |
+ | |
// The number of signals in this assignment must match CORE_PERF_EVENTS | |
// in defines.sv. | |
assign core_perf_events = { | |
diff --git a/hardware/core/dcache_data_stage.sv b/hardware/core/dcache_data_stage.sv | |
index 142311dc..0b59880b 100644 | |
--- a/hardware/core/dcache_data_stage.sv | |
+++ b/hardware/core/dcache_data_stage.sv | |
@@ -60,6 +60,13 @@ module dcache_data_stage( | |
output scalar_t dd_io_addr, | |
output scalar_t dd_io_write_value, | |
+ // To coprocessor | |
+ output logic dd_coproc_write_en, | |
+ output logic dd_coproc_read_en, | |
+ output scalar_t dd_coproc_address, | |
+ output local_thread_idx_t dd_coproc_thread_idx, | |
+ output vector_t dd_coproc_write_data, | |
+ | |
// To writeback_stage | |
output logic dd_instruction_valid, | |
output decoded_instruction_t dd_instruction, | |
@@ -72,6 +79,7 @@ module dcache_data_stage( | |
output cache_line_data_t dd_load_data, | |
output logic dd_suspend_thread, | |
output logic dd_io_access, | |
+ output logic dd_coproc_access, | |
output logic dd_trap, | |
output trap_cause_t dd_trap_cause, | |
@@ -129,6 +137,7 @@ module dcache_data_stage( | |
logic cached_store_req; | |
logic creg_access_req; | |
logic io_access_req; | |
+ logic coproc_access_req; | |
logic sync_access_req; | |
logic cache_control_req; | |
logic tlb_update_req; | |
@@ -137,6 +146,7 @@ module dcache_data_stage( | |
logic dinvalidate_req; | |
logic membar_req; | |
logic addr_in_io_region; | |
+ logic addr_in_coproc_region; | |
logic unaligned_address; | |
logic supervisor_fault; | |
logic alignment_fault; | |
@@ -191,6 +201,7 @@ module dcache_data_stage( | |
// dt_instruction_valid being false). These do not consider if the | |
// request is legal or possible, just what the instruction is asking to do. | |
assign addr_in_io_region = dt_request_paddr ==? 32'hffff????; | |
+ assign addr_in_coproc_region = dt_request_paddr ==? 32'hfffe????; | |
assign sync_access_req = dt_instruction.memory_access_type == MEM_SYNC; | |
// Note the last part that checks the store mask. If the store mask is zero | |
@@ -202,7 +213,9 @@ module dcache_data_stage( | |
&& dt_instruction.memory_access_type != MEM_CONTROL_REG | |
&& lane_enabled; | |
assign io_access_req = memory_access_req && addr_in_io_region; | |
- assign cached_access_req = memory_access_req && !addr_in_io_region; | |
+ assign coproc_access_req = memory_access_req && addr_in_coproc_region; | |
+ assign cached_access_req = memory_access_req && !addr_in_io_region | |
+ && !addr_in_coproc_region; | |
assign cached_load_req = cached_access_req && dt_instruction.load; | |
assign cached_store_req = cached_access_req && !dt_instruction.load; | |
assign cache_control_req = dt_instruction_valid | |
@@ -210,13 +223,16 @@ module dcache_data_stage( | |
&& dt_instruction.cache_control; | |
assign flush_req = cache_control_req | |
&& dt_instruction.cache_control_op == CACHE_DFLUSH | |
- && !addr_in_io_region; | |
+ && !addr_in_io_region | |
+ && !addr_in_coproc_region; | |
assign iinvalidate_req = cache_control_req | |
&& dt_instruction.cache_control_op == CACHE_IINVALIDATE | |
- && !addr_in_io_region; | |
+ && !addr_in_io_region | |
+ && !addr_in_coproc_region; | |
assign dinvalidate_req = cache_control_req | |
&& dt_instruction.cache_control_op == CACHE_DINVALIDATE | |
- && !addr_in_io_region; | |
+ && !addr_in_io_region | |
+ && !addr_in_coproc_region; | |
assign membar_req = cache_control_req | |
&& dt_instruction.cache_control_op == CACHE_MEMBAR; | |
assign tlb_update_req = cache_control_req | |
@@ -552,6 +568,7 @@ module dcache_data_stage( | |
dd_subcycle <= dt_subcycle; | |
dd_rollback_pc <= dt_instruction.pc; | |
dd_io_access <= io_access_req; | |
+ dd_coproc_access <= coproc_access_req; | |
// Check for TLB miss first, since permission bits are not valid if | |
// there is a TLB miss. The order of the remaining items should match | |
diff --git a/hardware/core/defines.sv b/hardware/core/defines.sv | |
index 3c52be12..4642ed82 100644 | |
--- a/hardware/core/defines.sv | |
+++ b/hardware/core/defines.sv | |
@@ -465,6 +465,22 @@ interface axi4_interface; | |
output s_awready, s_wready, s_bvalid, s_arready, s_rvalid, s_rdata); | |
endinterface | |
+interface coprocessor_bus_interface; | |
+ logic write_en; | |
+ logic read_en; | |
+ defines::scalar_t address; | |
+ defines::local_thread_idx_t thread_idx; | |
+ defines::vector_t write_data; | |
+ defines::vector_t read_data; | |
+ logic ack; | |
+ defines::local_thread_bitmap_t wake_bitmap; | |
+ | |
+ modport master(output write_en, read_en, address, thread_idx, write_data, | |
+ input read_data, ack, wake_bitmap); | |
+ modport slave(input write_en, read_en, address, thread_idx, write_data, | |
+ output read_data, ack, wake_bitmap); | |
+endinterface | |
+ | |
interface jtag_interface; | |
logic tck; | |
logic trst_n; | |
diff --git a/hardware/core/ifetch_data_stage.sv b/hardware/core/ifetch_data_stage.sv | |
index 314b903a..aab38af8 100644 | |
--- a/hardware/core/ifetch_data_stage.sv | |
+++ b/hardware/core/ifetch_data_stage.sv | |
@@ -186,7 +186,6 @@ module ifetch_data_stage( | |
begin | |
/*AUTORESET*/ | |
// Beginning of autoreset for uninitialized flops | |
- ocd_halt_latched <= '0; | |
ifd_alignment_fault <= '0; | |
ifd_executable_fault <= '0; | |
ifd_inst_injected <= '0; | |
@@ -197,6 +196,7 @@ module ifetch_data_stage( | |
ifd_perf_itlb_miss <= '0; | |
ifd_supervisor_fault <= '0; | |
ifd_tlb_miss <= '0; | |
+ ocd_halt_latched <= '0; | |
// End of automatics | |
end | |
else | |
diff --git a/hardware/core/nyuzi.sv b/hardware/core/nyuzi.sv | |
index 2e8d6325..04495de0 100644 | |
--- a/hardware/core/nyuzi.sv | |
+++ b/hardware/core/nyuzi.sv | |
@@ -27,13 +27,14 @@ module nyuzi | |
#(parameter RESET_PC = 0, | |
parameter NUM_INTERRUPTS = 16) | |
- (input clk, | |
- input reset, | |
- axi4_interface.master axi_bus, | |
- io_bus_interface.master io_bus, | |
- jtag_interface.target jtag, | |
- output logic processor_halt, | |
- input [NUM_INTERRUPTS - 1:0] interrupt_req); | |
+ (input clk, | |
+ input reset, | |
+ axi4_interface.master axi_bus, | |
+ io_bus_interface.master io_bus, | |
+ jtag_interface.target jtag, | |
+ output logic processor_halt, | |
+ coprocessor_bus_interface.master coprocessor_bus[`NUM_CORES - 1:0], | |
+ input [NUM_INTERRUPTS - 1:0] interrupt_req); | |
l2req_packet_t l2i_request[`NUM_CORES]; | |
logic[`NUM_CORES - 1:0] l2i_request_valid; | |
@@ -54,6 +55,12 @@ module nyuzi | |
/*AUTOLOGIC*/ | |
// Beginning of automatic wires (for undeclared instantiated-module outputs) | |
+ logic ii_ready [`NUM_CORES]; // From io_interconnect of io_interconnect.v | |
+ iorsp_packet_t ii_response; // From io_interconnect of io_interconnect.v | |
+ logic ii_response_valid; // From io_interconnect of io_interconnect.v | |
+ logic l2_ready [`NUM_CORES]; // From l2_cache of l2_cache.v | |
+ l2rsp_packet_t l2_response; // From l2_cache of l2_cache.v | |
+ logic l2_response_valid; // From l2_cache of l2_cache.v | |
core_id_t ocd_core; // From on_chip_debugger of on_chip_debugger.v | |
scalar_t ocd_data_from_host; // From on_chip_debugger of on_chip_debugger.v | |
logic ocd_data_update; // From on_chip_debugger of on_chip_debugger.v | |
@@ -61,12 +68,6 @@ module nyuzi | |
logic ocd_inject_en; // From on_chip_debugger of on_chip_debugger.v | |
scalar_t ocd_inject_inst; // From on_chip_debugger of on_chip_debugger.v | |
local_thread_idx_t ocd_thread; // From on_chip_debugger of on_chip_debugger.v | |
- logic ii_ready [`NUM_CORES]; // From io_interconnect of io_interconnect.v | |
- iorsp_packet_t ii_response; // From io_interconnect of io_interconnect.v | |
- logic ii_response_valid; // From io_interconnect of io_interconnect.v | |
- logic l2_ready [`NUM_CORES]; // From l2_cache of l2_cache.v | |
- l2rsp_packet_t l2_response; // From l2_cache of l2_cache.v | |
- logic l2_response_valid; // From l2_cache of l2_cache.v | |
// End of automatics | |
initial | |
@@ -173,6 +174,7 @@ module nyuzi | |
.ii_response(ii_response), | |
.cr_data_to_host(cr_data_to_host[core_idx]), | |
.core_perf_events(perf_events[L2_PERF_EVENTS + CORE_PERF_EVENTS * core_idx+:CORE_PERF_EVENTS]), | |
+ .coprocessor_bus(coprocessor_bus[core_idx]), | |
.injected_complete(core_injected_complete[core_idx]), | |
.injected_rollback(core_injected_rollback[core_idx]), | |
.*); | |
diff --git a/hardware/core/thread_select_stage.sv b/hardware/core/thread_select_stage.sv | |
index 3d928059..12a5314c 100644 | |
--- a/hardware/core/thread_select_stage.sv | |
+++ b/hardware/core/thread_select_stage.sv | |
@@ -67,6 +67,7 @@ module thread_select_stage( | |
input local_thread_bitmap_t wb_suspend_thread_oh, | |
input local_thread_bitmap_t l2i_dcache_wake_bitmap, | |
input local_thread_bitmap_t ior_wake_bitmap, | |
+ input local_thread_bitmap_t coproc_wake_bitmap, | |
// To performance_counters | |
output logic ts_perf_instruction_issue); | |
@@ -273,8 +274,10 @@ module thread_select_stage( | |
// Check for suspending a thread that isn't running | |
assert((wb_suspend_thread_oh & thread_blocked) == 0); | |
- // Check for waking a thread that isn't suspended (or about to be suspended, see note below) | |
- assert(((l2i_dcache_wake_bitmap | ior_wake_bitmap) & ~(thread_blocked | wb_suspend_thread_oh)) == 0); | |
+ // Check for waking a thread that isn't suspended (or about to be | |
+ // suspended, see note below) | |
+ assert(((l2i_dcache_wake_bitmap | ior_wake_bitmap | coproc_wake_bitmap) | |
+ & ~(thread_blocked | wb_suspend_thread_oh)) == 0); | |
// Don't issue blocked threads | |
assert((thread_issue_oh & thread_blocked) == 0); | |
@@ -291,7 +294,7 @@ module thread_select_stage( | |
// because of the order of this expression. This is intended, since | |
// cache data is now available and the thread won't be rolled back. | |
thread_blocked <= (thread_blocked | wb_suspend_thread_oh) | |
- & ~(l2i_dcache_wake_bitmap | ior_wake_bitmap); | |
+ & ~(l2i_dcache_wake_bitmap | ior_wake_bitmap | coproc_wake_bitmap); | |
writeback_allocate <= writeback_allocate_nxt; | |
ts_perf_instruction_issue <= |thread_issue_oh; | |
diff --git a/hardware/core/writeback_stage.sv b/hardware/core/writeback_stage.sv | |
index 694a3089..b128acb5 100644 | |
--- a/hardware/core/writeback_stage.sv | |
+++ b/hardware/core/writeback_stage.sv | |
@@ -74,6 +74,7 @@ module writeback_stage( | |
input cache_line_data_t dd_load_data, | |
input dd_suspend_thread, | |
input dd_io_access, | |
+ input dd_coproc_access, | |
input logic dd_trap, | |
input trap_cause_t dd_trap_cause, | |
@@ -87,6 +88,10 @@ module writeback_stage( | |
input scalar_t ior_read_value, | |
input logic ior_rollback_en, | |
+ // From coprocessor | |
+ input vector_t coproc_read_data, | |
+ input logic coproc_ack, | |
+ | |
// From control_registers | |
input scalar_t cr_creg_read_val, | |
input scalar_t cr_trap_handler, | |
@@ -150,6 +155,7 @@ module writeback_stage( | |
vector_mask_t writeback_mask_nxt; | |
register_idx_t writeback_reg_nxt; | |
logic writeback_last_subcycle_nxt; | |
+ logic coproc_rollback_en; | |
// | |
// Rollback control logic | |
@@ -159,6 +165,9 @@ module writeback_stage( | |
// This stage handles all rollbacks, so there can be only one asserted at a | |
// time. | |
// | |
+ assign coproc_rollback_en = !coproc_ack && dd_coproc_access | |
+ && dd_instruction_valid; | |
+ | |
always_comb | |
begin | |
wb_rollback_en = 0; | |
@@ -227,10 +236,12 @@ module writeback_stage( | |
else | |
wb_rollback_subcycle = ix_subcycle; | |
end | |
- else if (dd_instruction_valid && (dd_rollback_en || sq_rollback_en || ior_rollback_en)) | |
+ else if (dd_instruction_valid | |
+ && (dd_rollback_en || sq_rollback_en || ior_rollback_en | |
+ || coproc_rollback_en)) | |
begin | |
// Rollback from memory pipeline because of a data cache miss, | |
- // store queue full, or when an IO request is sent. | |
+ // store queue full, IO request, or coprocessor busy. | |
wb_rollback_en = 1; | |
wb_rollback_pc = dd_rollback_pc; | |
wb_rollback_thread_idx = dd_thread_idx; | |
@@ -260,7 +271,8 @@ module writeback_stage( | |
.index(dd_thread_idx)); | |
// Suspend thread if necessary | |
- assign wb_suspend_thread_oh = (dd_suspend_thread || sq_rollback_en || ior_rollback_en) | |
+ assign wb_suspend_thread_oh = (dd_suspend_thread || sq_rollback_en | |
+ || ior_rollback_en || coproc_rollback_en) | |
? thread_dd_oh : local_thread_bitmap_t'(0); | |
// If there is a pending store for the value that was just read, merge it into | |
@@ -446,7 +458,10 @@ module writeback_stage( | |
MEM_BLOCK_M: | |
begin | |
writeback_mask_nxt = dd_lane_mask; | |
- writeback_value_nxt = endian_twiddled_data; | |
+ if (dd_coproc_access) | |
+ writeback_value_nxt = coproc_read_data; | |
+ else | |
+ writeback_value_nxt = endian_twiddled_data; | |
end | |
default: | |
diff --git a/hardware/fpga/de2-115/de2_115_top.sv b/hardware/fpga/de2-115/de2_115_top.sv | |
index 8c3c4b01..eb824125 100644 | |
--- a/hardware/fpga/de2-115/de2_115_top.sv | |
+++ b/hardware/fpga/de2-115/de2_115_top.sv | |
@@ -89,6 +89,7 @@ module de2_115_top( | |
io_bus_interface peripheral_io_bus[NUM_PERIPHERALS - 1:0](); | |
io_bus_interface nyuzi_io_bus(); | |
jtag_interface jtag(); | |
+ coprocessor_bus_interface coprocessor_bus[`NUM_CORES - 1:0](); | |
enum logic[$clog2(NUM_PERIPHERALS) - 1:0] { | |
IO_UART, | |
IO_SDCARD, | |
@@ -274,6 +275,16 @@ module de2_115_top( | |
assign jtag.tms = 0; | |
assign jtag.trst_n = 0; | |
+ genvar coproc_core_idx; | |
+ generate | |
+ for (coproc_core_idx = 0; coproc_core_idx < `NUM_CORES; coproc_core_idx++) | |
+ begin : coproc_gen | |
+ assign coprocessor_bus[coproc_core_idx].ack = 1; | |
+ assign coprocessor_bus[coproc_core_idx].wake_bitmap = '0; | |
+ assign coprocessor_bus[coproc_core_idx].read_data = '0; | |
+ end | |
+ endgenerate | |
+ | |
// It's a little weird to have this in a VENDOR_ALTERA ifdef, since this file | |
// is Altera specific, but this is done so Verilator can still run a lint pass | |
// on this file to check for errors in CI. | |
diff --git a/hardware/testbench/soc_tb.sv b/hardware/testbench/soc_tb.sv | |
index 604b0d97..2531cdb4 100644 | |
--- a/hardware/testbench/soc_tb.sv | |
+++ b/hardware/testbench/soc_tb.sv | |
@@ -40,6 +40,8 @@ module soc_tb( | |
int profile_fd; | |
axi4_interface axi_bus_s[1:0](); | |
axi4_interface axi_bus_m[1:0](); | |
+ coprocessor_bus_interface coprocessor_bus[`NUM_CORES - 1:0](); | |
+ | |
scalar_t loopback_uart_read_data; | |
logic loopback_uart_tx; | |
logic loopback_uart_rx; | |
@@ -330,6 +332,27 @@ module soc_tb( | |
end | |
end | |
+ // | |
+ // Coprocessor instances | |
+ // | |
+ genvar coproc_core_idx; | |
+ generate | |
+ for (coproc_core_idx = 0; coproc_core_idx < `NUM_CORES; coproc_core_idx++) | |
+ begin : coproc_core_gen | |
+ vector_t value; | |
+ | |
+ always_ff @(posedge clk) | |
+ begin | |
+ if (coprocessor_bus[coproc_core_idx].write_en) | |
+ value <= ~coprocessor_bus[coproc_core_idx].write_data; | |
+ end | |
+ | |
+ assign coprocessor_bus[coproc_core_idx].read_data = value; | |
+ assign coprocessor_bus[coproc_core_idx].ack = 1; | |
+ assign coprocessor_bus[coproc_core_idx].wake_bitmap = '0; | |
+ end | |
+ endgenerate | |
+ | |
// | |
// Simulator option/execution handling | |
// | |
diff --git a/tests/unit/test_dcache_data_stage.sv b/tests/unit/test_dcache_data_stage.sv | |
index ac04ab58..29f0c643 100644 | |
--- a/tests/unit/test_dcache_data_stage.sv | |
+++ b/tests/unit/test_dcache_data_stage.sv | |
@@ -18,9 +18,13 @@ | |
import defines::*; | |
+// Does not test: | |
+// - read/write of L1 data memory | |
+// - That thread IDs are passed properly | |
module test_dcache_data_stage(input clk, input reset); | |
localparam NORMAL_ADDR = 'h80000020; | |
localparam IO_ADDR = 'hffff0010; | |
+ localparam COPROC_ADDR = 'hfffe0010; | |
local_thread_bitmap_t dd_load_sync_pending; | |
logic dt_instruction_valid; | |
@@ -92,6 +96,12 @@ module test_dcache_data_stage(input clk, input reset); | |
logic dd_perf_dcache_miss; | |
logic dd_perf_store; | |
logic dd_perf_dtlb_miss; | |
+ logic dd_coproc_write_en; | |
+ logic dd_coproc_read_en; | |
+ scalar_t dd_coproc_address; | |
+ local_thread_idx_t dd_coproc_thread_idx; | |
+ vector_t dd_coproc_write_data; | |
+ logic dd_coproc_access; | |
int cycle; | |
dcache_data_stage dcache_data_stage(.*); | |
@@ -204,6 +214,9 @@ module test_dcache_data_stage(input clk, input reset); | |
assert(!dd_perf_dcache_miss); | |
assert(!dd_perf_store); | |
assert(!dd_perf_dtlb_miss); | |
+ assert(!dd_coproc_write_en); | |
+ assert(!dd_coproc_read_en); | |
+ assert(!dd_coproc_access); | |
end | |
2: | |
@@ -217,6 +230,9 @@ module test_dcache_data_stage(input clk, input reset); | |
assert(!dd_perf_dcache_miss); | |
assert(!dd_perf_store); | |
assert(!dd_perf_dtlb_miss); | |
+ assert(!dd_coproc_write_en); | |
+ assert(!dd_coproc_read_en); | |
+ assert(!dd_coproc_access); | |
end | |
//////////////////////////////////////////////////////////// | |
@@ -245,6 +261,9 @@ module test_dcache_data_stage(input clk, input reset); | |
assert(!dd_perf_dcache_miss); | |
assert(!dd_perf_store); | |
assert(!dd_perf_dtlb_miss); | |
+ assert(!dd_coproc_write_en); | |
+ assert(!dd_coproc_read_en); | |
+ assert(!dd_coproc_access); | |
end | |
5: | |
@@ -258,6 +277,9 @@ module test_dcache_data_stage(input clk, input reset); | |
assert(!dd_perf_dcache_miss); | |
assert(dd_perf_store); | |
assert(!dd_perf_dtlb_miss); | |
+ assert(!dd_coproc_write_en); | |
+ assert(!dd_coproc_read_en); | |
+ assert(!dd_coproc_access); | |
end | |
//////////////////////////////////////////////////////////// | |
@@ -287,6 +309,9 @@ module test_dcache_data_stage(input clk, input reset); | |
assert(!dd_perf_dcache_miss); | |
assert(!dd_perf_store); | |
assert(!dd_perf_dtlb_miss); | |
+ assert(!dd_coproc_write_en); | |
+ assert(!dd_coproc_read_en); | |
+ assert(!dd_coproc_access); | |
end | |
8: | |
@@ -300,6 +325,9 @@ module test_dcache_data_stage(input clk, input reset); | |
assert(!dd_perf_dcache_miss); | |
assert(!dd_perf_store); | |
assert(!dd_perf_dtlb_miss); | |
+ assert(!dd_coproc_write_en); | |
+ assert(!dd_coproc_read_en); | |
+ assert(!dd_coproc_access); | |
end | |
//////////////////////////////////////////////////////////// | |
@@ -328,6 +356,9 @@ module test_dcache_data_stage(input clk, input reset); | |
assert(!dd_perf_dcache_miss); | |
assert(!dd_perf_store); | |
assert(!dd_perf_dtlb_miss); | |
+ assert(!dd_coproc_write_en); | |
+ assert(!dd_coproc_read_en); | |
+ assert(!dd_coproc_access); | |
end | |
11: | |
@@ -341,6 +372,9 @@ module test_dcache_data_stage(input clk, input reset); | |
assert(!dd_perf_dcache_miss); | |
assert(!dd_perf_store); | |
assert(!dd_perf_dtlb_miss); | |
+ assert(!dd_coproc_write_en); | |
+ assert(!dd_coproc_read_en); | |
+ assert(!dd_coproc_access); | |
end | |
//////////////////////////////////////////////////////////// | |
@@ -2157,7 +2191,103 @@ module test_dcache_data_stage(input clk, input reset); | |
assert(!dd_perf_dtlb_miss); | |
end | |
- 256: | |
+ //////////////////////////////////////////////////////////// | |
+ // Coprocessor Write | |
+ //////////////////////////////////////////////////////////// | |
+ 260: cache_hit(COPROC_ADDR, 0); | |
+ | |
+ 261: | |
+ begin | |
+ assert(!dd_coproc_access); | |
+ assert(!dd_io_read_en); | |
+ assert(!dd_update_lru_en); | |
+ assert(!dd_instruction_valid); | |
+ assert(!dd_io_write_en); | |
+ assert(!dd_creg_write_en); | |
+ assert(!dd_creg_read_en); | |
+ assert(!dd_store_en); | |
+ assert(!dd_flush_en); | |
+ assert(!dd_membar_en); | |
+ assert(!dd_iinvalidate_en); | |
+ assert(!dd_dinvalidate_en); | |
+ assert(!dd_cache_miss); | |
+ assert(!dd_trap); | |
+ assert(!dd_perf_dcache_hit); | |
+ assert(!dd_perf_dcache_miss); | |
+ assert(!dd_perf_store); | |
+ assert(!dd_perf_dtlb_miss); | |
+ assert(!dd_coproc_write_en); | |
+ assert(!dd_coproc_read_en); | |
+ assert(!dd_coproc_access); | |
+ end | |
+ | |
+ 262: | |
+ begin | |
+ assert(dd_instruction_valid); | |
+ assert(dd_coproc_access); | |
+ assert(!dd_io_read_en); | |
+ assert(!dd_io_write_en); | |
+ assert(!dd_trap); | |
+ assert(!dd_cache_miss); | |
+ assert(!dd_suspend_thread); | |
+ assert(!dd_rollback_en); | |
+ assert(!dd_perf_dcache_hit); | |
+ assert(!dd_perf_dcache_miss); | |
+ assert(!dd_perf_store); | |
+ assert(!dd_perf_dtlb_miss); | |
+ assert(!dd_coproc_write_en); | |
+ assert(!dd_coproc_read_en); | |
+ end | |
+ | |
+ //////////////////////////////////////////////////////////// | |
+ // Coprocessor Read | |
+ //////////////////////////////////////////////////////////// | |
+ 270: cache_hit(COPROC_ADDR, 1); | |
+ | |
+ 271: | |
+ begin | |
+ assert(!dd_coproc_access); | |
+ assert(!dd_io_read_en); | |
+ assert(!dd_update_lru_en); | |
+ assert(!dd_instruction_valid); | |
+ assert(!dd_io_write_en); | |
+ assert(!dd_creg_write_en); | |
+ assert(!dd_creg_read_en); | |
+ assert(!dd_store_en); | |
+ assert(!dd_flush_en); | |
+ assert(!dd_membar_en); | |
+ assert(!dd_iinvalidate_en); | |
+ assert(!dd_dinvalidate_en); | |
+ assert(!dd_cache_miss); | |
+ assert(!dd_trap); | |
+ assert(!dd_perf_dcache_hit); | |
+ assert(!dd_perf_dcache_miss); | |
+ assert(!dd_perf_store); | |
+ assert(!dd_perf_dtlb_miss); | |
+ assert(!dd_coproc_write_en); | |
+ assert(!dd_coproc_read_en); | |
+ assert(!dd_coproc_access); | |
+ end | |
+ | |
+ 272: | |
+ begin | |
+ assert(dd_instruction_valid); | |
+ assert(dd_coproc_access); | |
+ assert(!dd_io_read_en); | |
+ assert(!dd_io_write_en); | |
+ assert(!dd_trap); | |
+ assert(!dd_cache_miss); | |
+ assert(!dd_suspend_thread); | |
+ assert(!dd_rollback_en); | |
+ assert(!dd_perf_dcache_hit); | |
+ assert(!dd_perf_dcache_miss); | |
+ assert(!dd_perf_store); | |
+ assert(!dd_perf_dtlb_miss); | |
+ assert(!dd_coproc_write_en); | |
+ assert(!dd_coproc_read_en); | |
+ end | |
+ | |
+ 273: | |
begin | |
$display("PASS"); | |
$finish; | |
diff --git a/tests/unit/test_writeback_stage.sv b/tests/unit/test_writeback_stage.sv | |
index d5102f95..fc488a88 100644 | |
--- a/tests/unit/test_writeback_stage.sv | |
+++ b/tests/unit/test_writeback_stage.sv | |
@@ -18,6 +18,10 @@ | |
import defines::*; | |
+// Does not test: | |
+// - Memory alignment | |
+// - Ensuring I/O reads return proper data | |
+// ... | |
module test_writeback_stage(input clk, input reset); | |
localparam RESULT0 = 512'hc15bc3d97ebadf04f3754c0434ebef01d38de1280edbccf9ee36223e001fdf7efbf4dcfdb09130fd194b1bae6dfe0112817593e1b96b0e7383cd8ef45f0d36ca; | |
localparam RESULT1 = 512'hffffffff00000000000000000000000000000000ffffffffffffffff00000000ffffffffffffffff000000000000000000000000ffffffff00000000ffffffff; | |
@@ -45,6 +49,7 @@ module test_writeback_stage(input clk, input reset); | |
localparam PC8 = 32'he2fb8974; | |
localparam ACCESS_ADDR1 = 32'he814c094; | |
localparam ACCESS_ADDR2 = 32'h6ebf3224; | |
+ localparam RESULT5 = 512'hfeaf63d83243f10f5bf4d888e3efd664d48b996d14782b3ff011a10975a93c49e2611d72bca41e289827000b2417b31bbf2282c7d35a278acf46309cddfa5f0c; | |
logic fx5_instruction_valid; | |
decoded_instruction_t fx5_instruction; | |
@@ -107,6 +112,9 @@ module test_writeback_stage(input clk, input reset); | |
logic wb_perf_instruction_retire; | |
logic wb_perf_store_rollback; | |
logic wb_perf_interrupt; | |
+ logic dd_coproc_access; | |
+ vector_t coproc_read_data; | |
+ logic coproc_ack; | |
int cycle; | |
writeback_stage writeback_stage(.*); | |
@@ -143,6 +151,7 @@ module test_writeback_stage(input clk, input reset); | |
cr_creg_read_val <= '0; | |
cr_trap_handler <= '0; | |
cr_tlb_miss_handler <= '0; | |
+ coproc_read_data <= '0; | |
for (int i = 0; i < `THREADS_PER_CORE; i++) | |
cr_eret_subcycle[i] <= '0; | |
end | |
@@ -161,6 +170,8 @@ module test_writeback_stage(input clk, input reset); | |
fx5_instruction <= '0; | |
dd_instruction <= '0; | |
ix_privileged_op_fault <= '0; | |
+ dd_coproc_access <= '0; | |
+ coproc_ack <= '0; | |
cycle <= cycle + 1; | |
unique0 case (cycle) | |
@@ -795,8 +806,92 @@ module test_writeback_stage(input clk, input reset); | |
assert(wb_perf_interrupt); | |
end | |
+ //////////////////////////////////////////////////////////// | |
+ // Coprocessor read, ready | |
+ //////////////////////////////////////////////////////////// | |
+ 50: | |
+ begin | |
+ dd_instruction_valid <= 1; | |
+ dd_coproc_access <= 1; | |
+ dd_instruction.has_dest <= 1; | |
+ dd_instruction.dest_reg <= 4; | |
+ dd_instruction.memory_access_type <= MEM_BLOCK; | |
+ dd_instruction.load <= 1; | |
+ dd_instruction.dest_vector <= 1; | |
+ coproc_read_data <= RESULT5; | |
+ coproc_ack <= 1; | |
+ end | |
+ | |
+ 51: | |
+ begin | |
+ assert(!wb_trap); | |
+ assert(!wb_eret); | |
+ assert(!wb_rollback_en); | |
+ assert(!wb_writeback_en); | |
+ assert(wb_suspend_thread_oh == 0); | |
+ assert(!wb_perf_instruction_retire); | |
+ assert(!wb_perf_store_rollback); | |
+ end | |
+ | |
+ 52: | |
+ begin | |
+ assert(!wb_trap); | |
+ assert(!wb_eret); | |
+ assert(!wb_rollback_en); | |
+ assert(wb_writeback_en); | |
+ assert(wb_writeback_vector); | |
+ assert(wb_writeback_reg == 4); | |
+ assert(wb_writeback_last_subcycle); | |
+ assert(wb_suspend_thread_oh == 0); | |
+ assert(!wb_inst_injected); | |
+ assert(wb_perf_instruction_retire); | |
+ assert(!wb_perf_store_rollback); | |
+ assert(!wb_perf_interrupt); | |
+ | |
+ assert(wb_writeback_value == RESULT5); | |
+ end | |
+ | |
+ //////////////////////////////////////////////////////////// | |
+ // Coprocessor read, not ready | |
+ //////////////////////////////////////////////////////////// | |
+ 55: | |
+ begin | |
+ dd_instruction_valid <= 1; | |
+ dd_coproc_access <= 1; | |
+ dd_instruction.has_dest <= 1; | |
+ dd_instruction.dest_reg <= 4; | |
+ dd_instruction.memory_access_type <= MEM_BLOCK; | |
+ dd_instruction.load <= 1; | |
+ dd_instruction.dest_vector <= 1; | |
+ coproc_ack <= 0; | |
+ end | |
+ | |
+ 56: | |
+ begin | |
+ assert(!wb_trap); | |
+ assert(!wb_eret); | |
+ assert(wb_rollback_en); | |
+ assert(!wb_writeback_en); | |
+ assert(wb_suspend_thread_oh == 4'b0100); | |
+ assert(!wb_perf_instruction_retire); | |
+ assert(!wb_perf_store_rollback); | |
+ end | |
+ | |
+ 57: | |
+ begin | |
+ assert(!wb_trap); | |
+ assert(!wb_eret); | |
+ assert(!wb_rollback_en); | |
+ assert(!wb_writeback_en); | |
+ assert(wb_suspend_thread_oh == 0); | |
+ assert(!wb_inst_injected); | |
+ assert(!wb_perf_instruction_retire); | |
+ assert(!wb_perf_store_rollback); | |
+ assert(!wb_perf_interrupt); | |
+ end | |
+ | |
// Done | |
- 42: | |
+ 58: | |
begin | |
$display("PASS"); | |
$finish; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment