Skip to content

Instantly share code, notes, and snippets.

@jbush001
Last active January 28, 2018 02:20
Show Gist options
  • Save jbush001/636812836911d5c7873893a1d0ae517e to your computer and use it in GitHub Desktop.
Save jbush001/636812836911d5c7873893a1d0ae517e to your computer and use it in GitHub Desktop.
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