mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-04 22:32:36 +00:00
feat: refactor JPEG table register bank and enhance flow script
- Updated the JPEG table register bank module to use combinational logic for data handling and simplified the write logic for quantization, DC, and AC entries. - Introduced a new function in the run_flow script to handle process termination more gracefully, including signal handling for interrupts. - Enhanced the flow script to log peak RSS memory usage during execution. - Modified multiple testbench files to include new storage access signals and improved the test logic for better validation of KWS and SRAM interactions. - Updated tests to validate the new peak RSS memory logging in the flow script. - Adjusted Yosys synthesis recipes to include timeout settings and ensure proper reporting of pre-memory synthesis outputs.
This commit is contained in:
17 files changed
+954
-459
No files matched your search
@@ -172,6 +172,18 @@ duration, warning signatures, and netlist simulation verdict together. The
|
||||
improved metric is not sufficient to replace `balanced`. Metrics policy remains
|
||||
in `observe` mode while recipe baselines are collected and reviewed.
|
||||
|
||||
Every Yosys run writes `yosys-perf.json`, `<top>_pre_memory.rpt`, and
|
||||
`<top>_pre_memory.json` immediately before memory lowering. These reports are
|
||||
the authoritative pass-timing and inferred-memory inventory for memories that
|
||||
would otherwise be expanded into registers and muxes. Structured flow results
|
||||
also record `peak_rss_kib`, the operating system's maximum resident-set
|
||||
observation for the child tool. Keep both artifacts when a synthesis run times
|
||||
out or is interrupted; a missing final netlist is never a successful synthesis
|
||||
result.
|
||||
The full and block Yosys flows enforce `YOSYS_TIMEOUT=10800` seconds by
|
||||
default. Override it only for an explicitly reviewed diagnostic run; timeout
|
||||
exit 124 remains a failed synthesis verdict.
|
||||
|
||||
Generated filelists and MPW output are flow-local. Make depfiles track expanded RTL sources and
|
||||
included headers. The shared MPW generator is protected by a file lock. Default tool parallelism is
|
||||
capped at 16 and can be set with `JOBS=<n>` or `MAX_JOBS=<n>`.
|
||||
|
||||
@@ -120,7 +120,8 @@ $(APU_BLOCK_NETLIST): $(APU_BLOCK_FL) $(APU_BLOCK_YOSYS_SCRIPTS)
|
||||
--env PROJ_NAME=$(APU_BLOCK_TOP) --env WORK=$(APU_BLOCK_TMP) \
|
||||
--env BUILD=$(APU_BLOCK_OUT) --env REPORTS=$(APU_BLOCK_RPT) \
|
||||
--env NETLIST=$(APU_BLOCK_NETLIST) -- \
|
||||
yosys -c $(APU_BLOCK_SYNTH_TCL)
|
||||
timeout --foreground --kill-after=5s $(YOSYS_TIMEOUT)s \
|
||||
yosys -t --perffile $(APU_BLOCK_SYN)/yosys-perf.json -c $(APU_BLOCK_SYNTH_TCL)
|
||||
|
||||
apu-block-synth: $(APU_BLOCK_NETLIST)
|
||||
|
||||
@@ -170,4 +171,4 @@ apu-block-clean:
|
||||
python3 $(ROOT_PATH)/scripts/clean.py --root $(ROOT_PATH) --path $(APU_BLOCK_REPORT_DIR)
|
||||
|
||||
.PHONY: apu-block-filelist apu-block-synth apu-block-sta apu-block-report \
|
||||
apu-block-evidence apu-block-clean
|
||||
apu-block-evidence apu-block-clean
|
||||
@@ -83,7 +83,8 @@ $(GA2D_BLOCK_NETLIST): $(GA2D_BLOCK_FLIST) $(GA2D_BLOCK_SCRIPTS)
|
||||
--env PROJ_NAME=$(GA2D_BLOCK_TOP) --env WORK=$(GA2D_BLOCK_TMP) \
|
||||
--env BUILD=$(GA2D_BLOCK_OUT) --env REPORTS=$(GA2D_BLOCK_RPT) \
|
||||
--env NETLIST=$(GA2D_BLOCK_NETLIST) -- \
|
||||
yosys -c $(YOSYS_DIR)/script/synth.tcl
|
||||
timeout --foreground --kill-after=5s $(YOSYS_TIMEOUT)s \
|
||||
yosys -t --perffile $(GA2D_BLOCK_BUILD)/yosys-perf.json -c $(YOSYS_DIR)/script/synth.tcl
|
||||
|
||||
# Fails loudly on inferred latches or non-PDK (black-box/unmapped) cells and
|
||||
# records the register/FIFO mapping summary consumed by the evidence section.
|
||||
@@ -175,4 +176,4 @@ sta-ga2d-block-clean:
|
||||
python3 $(ROOT_PATH)/scripts/clean.py --root $(ROOT_PATH) --path $(GA2D_BLOCK_STA_DIR)
|
||||
|
||||
.PHONY: synth-ga2d-block synth-ga2d-block-clean netsim-ga2d-block netsim-ga2d-block-clean \
|
||||
sta-ga2d-block sta-ga2d-block-clean
|
||||
sta-ga2d-block sta-ga2d-block-clean
|
||||
@@ -87,6 +87,10 @@ yosys booth
|
||||
yosys alumacc
|
||||
yosys share
|
||||
yosys opt
|
||||
# Capture the hierarchy and inferred-memory inventory immediately before the
|
||||
# memory lowering pass. This report survives a later timeout or resource abort.
|
||||
yosys tee -q -o "${report_dir}/${proj_name}_pre_memory.rpt" stat
|
||||
yosys tee -q -o "${report_dir}/${proj_name}_pre_memory.json" stat -json
|
||||
yosys memory
|
||||
yosys opt -fast
|
||||
|
||||
|
||||
@@ -68,6 +68,10 @@ yosys booth
|
||||
yosys alumacc
|
||||
yosys share
|
||||
yosys opt
|
||||
# Capture the hierarchy and inferred-memory inventory immediately before the
|
||||
# memory lowering pass. This report survives a later timeout or resource abort.
|
||||
yosys tee -q -o "${report_dir}/${proj_name}_pre_memory.rpt" stat
|
||||
yosys tee -q -o "${report_dir}/${proj_name}_pre_memory.json" stat -json
|
||||
yosys memory
|
||||
yosys opt -fast
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ YOSYS_BUILD := $(SYN_BUILD_ROOT)
|
||||
YOSYS_OUT := $(YOSYS_BUILD)/out
|
||||
YOSYS_TMP := $(YOSYS_BUILD)/tmp
|
||||
YOSYS_RPT := $(YOSYS_BUILD)/rpt
|
||||
YOSYS_TIMEOUT ?= 10800
|
||||
|
||||
include $(YOSYS_DIR)/synth_config.mk
|
||||
|
||||
@@ -69,7 +70,8 @@ $(NETLIST): $(SV_FLIST) $(YOSYS_SCRIPTS)
|
||||
--env SV_FLIST=$(SV_FLIST) --env TOP_DESIGN=$(TOP_DESIGN) --env CONFIG=$(NETLIST_CONFIG) \
|
||||
--env PROJ_NAME=$(RTL_NAME) --env WORK=$(YOSYS_TMP) --env BUILD=$(YOSYS_OUT) \
|
||||
--env REPORTS=$(YOSYS_RPT) --env NETLIST=$(NETLIST) -- \
|
||||
yosys -c $(YOSYS_DIR)/script/synth.tcl
|
||||
timeout --foreground --kill-after=5s $(YOSYS_TIMEOUT)s \
|
||||
yosys -t --perffile $(YOSYS_BUILD)/yosys-perf.json -c $(YOSYS_DIR)/script/synth.tcl
|
||||
|
||||
$(NETLIST_DEBUG): $(NETLIST)
|
||||
@test -f $@
|
||||
@@ -77,4 +79,4 @@ $(NETLIST_DEBUG): $(NETLIST)
|
||||
synth_clean:
|
||||
python3 $(ROOT_PATH)/scripts/clean.py --root $(ROOT_PATH) --path $(YOSYS_BUILD)
|
||||
|
||||
.PHONY: gen_synth_filelist synth_clean synth
|
||||
.PHONY: gen_synth_filelist synth_clean synth
|
||||
@@ -248,7 +248,11 @@ module apb4_apu #(
|
||||
logic s_mc_proof_memo_full_unused;
|
||||
logic [ 31:0] s_kws_sram_data_unused;
|
||||
logic s_kws_sram_valid_unused, s_kws_sram_err_unused;
|
||||
logic s_kws_storage_req, s_kws_storage_ready, s_kws_storage_done;
|
||||
logic s_kws_storage_progress, s_kws_storage_write;
|
||||
logic [15:0] s_kws_model_read_valid;
|
||||
logic s_kws_scratch_clear, s_kws_scratch_err;
|
||||
logic [19:0] s_kws_scratch_read_valid;
|
||||
logic [19:0][15:0] s_kws_scratch_read_addr;
|
||||
logic [19:0][31:0] s_kws_scratch_read_data;
|
||||
logic [ 5:0] s_kws_scratch_write_valid;
|
||||
@@ -718,9 +722,16 @@ module apb4_apu #(
|
||||
.memory_input_used_o (s_kws_mem_input_used),
|
||||
.kws_config_i (s_codec_kws_config_valid ? s_codec_kws_config : s_kws_config),
|
||||
.input_config_i (s_kws_input_config),
|
||||
.storage_req_o (s_kws_storage_req),
|
||||
.storage_ready_i (s_kws_storage_ready),
|
||||
.storage_done_i (s_kws_storage_done),
|
||||
.storage_progress_i (s_kws_storage_progress),
|
||||
.storage_write_o (s_kws_storage_write),
|
||||
.model_read_valid_o (s_kws_model_read_valid),
|
||||
.model_addr_o (s_kws_model_read_addr),
|
||||
.model_data_i (s_kws_model_read_data),
|
||||
.scratch_clear_o (s_kws_scratch_clear),
|
||||
.scratch_read_valid_o (s_kws_scratch_read_valid),
|
||||
.scratch_read_addr_o (s_kws_scratch_read_addr),
|
||||
.scratch_read_data_i (s_kws_scratch_read_data),
|
||||
.scratch_write_valid_o (s_kws_scratch_write_valid),
|
||||
@@ -920,9 +931,16 @@ module apb4_apu #(
|
||||
.data_o (s_kws_sram_data_unused),
|
||||
.valid_o (s_kws_sram_valid_unused),
|
||||
.access_err_o (s_kws_sram_err_unused),
|
||||
.access_req_i (s_kws_storage_req),
|
||||
.access_ready_o (s_kws_storage_ready),
|
||||
.access_done_o (s_kws_storage_done),
|
||||
.access_progress_o (s_kws_storage_progress),
|
||||
.access_write_i (s_kws_storage_write),
|
||||
.model_read_valid_i (s_kws_model_read_valid),
|
||||
.model_addr_i (s_kws_model_read_addr),
|
||||
.model_data_o (s_kws_model_read_data),
|
||||
.scratch_clear_i (s_kws_scratch_clear),
|
||||
.scratch_read_valid_i (s_kws_scratch_read_valid),
|
||||
.scratch_read_addr_i (s_kws_scratch_read_addr),
|
||||
.scratch_read_data_o (s_kws_scratch_read_data),
|
||||
.scratch_write_valid_i(s_kws_scratch_write_valid),
|
||||
|
||||
+344
-273
@@ -49,9 +49,16 @@ module apu_kws_engine (
|
||||
output logic [31:0] memory_input_used_o,
|
||||
input logic [15:0] kws_config_i,
|
||||
input logic [31:0] input_config_i,
|
||||
output logic storage_req_o,
|
||||
input logic storage_ready_i,
|
||||
input logic storage_done_i,
|
||||
input logic storage_progress_i,
|
||||
output logic storage_write_o,
|
||||
output logic [15:0] model_read_valid_o,
|
||||
output logic [15:0][14:0] model_addr_o,
|
||||
input logic [15:0][ 7:0] model_data_i,
|
||||
output logic scratch_clear_o,
|
||||
output logic [19:0] scratch_read_valid_o,
|
||||
output logic [19:0][15:0] scratch_read_addr_o,
|
||||
input logic [19:0][31:0] scratch_read_data_i,
|
||||
output logic [ 5:0] scratch_write_valid_o,
|
||||
@@ -175,6 +182,9 @@ module apu_kws_engine (
|
||||
logic [31:0] s_fault_addr_q, s_fault_detail_q;
|
||||
logic [31:0] s_front_watchdog_q, s_infer_watchdog_q;
|
||||
logic s_front_progress, s_infer_progress;
|
||||
logic s_storage_wait_q, s_storage_write_phase_q, s_storage_state_owned_q;
|
||||
logic s_storage_read_access, s_storage_write_access, s_storage_has_access;
|
||||
logic s_storage_final_done, s_storage_state_step;
|
||||
|
||||
logic s_config_valid, s_continuous_active, s_listening, s_capture_available;
|
||||
logic s_stream_accept, s_stream_legal, s_window_deadline, s_mel_overwrite;
|
||||
@@ -578,8 +588,8 @@ module apu_kws_engine (
|
||||
!s_stop_latched_q && model_valid_i && model_lock_i && s_config_valid;
|
||||
assign s_listening = s_continuous_active && s_en_q && !flush_busy_i;
|
||||
assign s_capture_available = (s_front_state_q == FrontIdle) && !s_frame_pending_q &&
|
||||
!s_window_pending_q && (s_fir_tap_q == 6'd0);
|
||||
assign rx_ready_o = s_listening && s_capture_available;
|
||||
!s_window_pending_q && (s_infer_state_q == InferIdle) && (s_fir_tap_q == 6'd0);
|
||||
assign rx_ready_o = s_listening && s_capture_available && !s_storage_wait_q && storage_ready_i;
|
||||
assign s_stream_accept = stream_i.tvalid && rx_ready_o;
|
||||
assign s_stream_legal = (stream_i.tkeep == 4'hf) && (stream_i.tstrb == 4'hf) && !stream_i.tlast;
|
||||
assign s_window_deadline = s_commit_valid &&
|
||||
@@ -754,9 +764,11 @@ module apu_kws_engine (
|
||||
assign s_mac_total = s_mac_q + s_lane_sum;
|
||||
|
||||
always_comb begin
|
||||
model_addr_o = '0;
|
||||
scratch_read_addr_o = '0;
|
||||
s_lane_active = 16'd0;
|
||||
model_read_valid_o = 16'd0;
|
||||
model_addr_o = '0;
|
||||
scratch_read_valid_o = 20'd0;
|
||||
scratch_read_addr_o = '0;
|
||||
s_lane_active = 16'd0;
|
||||
for (int lane = 0; lane < 16; lane++) begin
|
||||
s_lane_term[lane] = {1'b0, s_term_q} + 9'(lane);
|
||||
s_lane_input_index[lane] = 13'd0;
|
||||
@@ -766,14 +778,17 @@ module apu_kws_engine (
|
||||
end
|
||||
unique case (s_front_state_q)
|
||||
FrontFir: begin
|
||||
scratch_read_valid_o[0] = 1'b1;
|
||||
scratch_read_addr_o[0] = `RETROSOC_APU_KWS__SCRATCH_FIR_BASE +
|
||||
{9'd0, fir_history_index(s_fir_write_q, s_fir_tap_q), 1'b0};
|
||||
end
|
||||
FrontFftLoad: begin
|
||||
scratch_read_valid_o[0] = 1'b1;
|
||||
scratch_read_addr_o[0] = `RETROSOC_APU_KWS__SCRATCH_INGRESS_BASE +
|
||||
16'(ingress_add(s_frame_start_q, s_front_index_q) * 2);
|
||||
end
|
||||
FrontFftRun: begin
|
||||
scratch_read_valid_o[3:0] = 4'hf;
|
||||
scratch_read_addr_o[0] =
|
||||
`RETROSOC_APU_KWS__SCRATCH_FFT_REAL_BASE + 16'(s_fft_left_index * 4);
|
||||
scratch_read_addr_o[1] =
|
||||
@@ -784,23 +799,28 @@ module apu_kws_engine (
|
||||
`RETROSOC_APU_KWS__SCRATCH_FFT_IMAG_BASE + 16'(s_fft_right_index * 4);
|
||||
end
|
||||
FrontMagnitude: begin
|
||||
scratch_read_valid_o[1:0] = 2'b11;
|
||||
scratch_read_addr_o[0] =
|
||||
`RETROSOC_APU_KWS__SCRATCH_FFT_REAL_BASE + 16'(s_front_index_q * 4);
|
||||
scratch_read_addr_o[1] =
|
||||
`RETROSOC_APU_KWS__SCRATCH_FFT_IMAG_BASE + 16'(s_front_index_q * 4);
|
||||
end
|
||||
FrontMel: begin
|
||||
scratch_read_addr_o[0] = `RETROSOC_APU_KWS__SCRATCH_FFT_REAL_BASE + 16'(s_mel_bin_q * 4);
|
||||
scratch_read_valid_o[0] = 1'b1;
|
||||
scratch_read_addr_o[0] = `RETROSOC_APU_KWS__SCRATCH_FFT_REAL_BASE + 16'(s_mel_bin_q * 4);
|
||||
end
|
||||
FrontPeak: begin
|
||||
scratch_read_addr_o[0] = `RETROSOC_APU_KWS__SCRATCH_PEAK_BASE + 16'(s_peak_scan_q * 2);
|
||||
scratch_read_valid_o[0] = 1'b1;
|
||||
scratch_read_addr_o[0] = `RETROSOC_APU_KWS__SCRATCH_PEAK_BASE + 16'(s_peak_scan_q * 2);
|
||||
end
|
||||
FrontLog: begin
|
||||
scratch_read_valid_o[0] = 1'b1;
|
||||
scratch_read_addr_o[0] = `RETROSOC_APU_KWS__SCRATCH_MEL_BASE +
|
||||
16'((16'(s_log_row_index) * 16'd40 + 16'(s_mfcc_band_q)) * 16'd4);
|
||||
end
|
||||
FrontDct: begin
|
||||
scratch_read_addr_o[0] = `RETROSOC_APU_KWS__SCRATCH_FFT_IMAG_BASE + 16'(s_mfcc_band_q * 4);
|
||||
scratch_read_valid_o[0] = 1'b1;
|
||||
scratch_read_addr_o[0] = `RETROSOC_APU_KWS__SCRATCH_FFT_IMAG_BASE + 16'(s_mfcc_band_q * 4);
|
||||
end
|
||||
default: begin
|
||||
end
|
||||
@@ -808,34 +828,42 @@ module apu_kws_engine (
|
||||
if (s_infer_state_q == InferPool) begin
|
||||
for (int lane = 0; lane < 16; lane++) begin
|
||||
if (({1'b0, s_term_q} + 9'(lane)) < 9'd125) begin
|
||||
scratch_read_valid_o[lane+4] = 1'b1;
|
||||
scratch_read_addr_o[lane+4] = `RETROSOC_APU_KWS__SCRATCH_A_BASE +
|
||||
16'((32'(s_term_q) + 32'(lane)) * 32'd64 + 32'(s_output_q));
|
||||
end
|
||||
end
|
||||
end else if ((s_infer_state_q == InferSoftmaxMax) || (s_infer_state_q == InferSoftmaxSum)) begin
|
||||
scratch_read_addr_o[4] = `RETROSOC_APU_KWS__SCRATCH_LOGITS_BASE + 16'(s_softmax_index_q);
|
||||
scratch_read_valid_o[4] = 1'b1;
|
||||
scratch_read_addr_o[4] = `RETROSOC_APU_KWS__SCRATCH_LOGITS_BASE + 16'(s_softmax_index_q);
|
||||
end else if ((s_infer_state_q == InferSoftmaxScale) && (s_softmax_index_q > 0)) begin
|
||||
scratch_read_valid_o[4] = 1'b1;
|
||||
scratch_read_addr_o[4] =
|
||||
`RETROSOC_APU_KWS__SCRATCH_LOGITS_BASE + 16'(s_softmax_index_q - 1'b1);
|
||||
end else if (s_infer_state_q == InferComplete) begin
|
||||
for (int class_index = 0; class_index < 12; class_index++) begin
|
||||
scratch_read_valid_o[class_index+4] = 1'b1;
|
||||
scratch_read_addr_o[class_index+4] =
|
||||
`RETROSOC_APU_KWS__SCRATCH_SOFTMAX_BASE + 16'(class_index);
|
||||
end
|
||||
end
|
||||
if (s_infer_state_q == InferBias) begin
|
||||
for (int lane = 0; lane < 4; lane++) begin
|
||||
model_addr_o[lane] = s_bias_base + 15'(s_output_channel) * 15'd4 + 15'(lane);
|
||||
model_read_valid_o[lane] = 1'b1;
|
||||
model_addr_o[lane] = s_bias_base + 15'(s_output_channel) * 15'd4 + 15'(lane);
|
||||
end
|
||||
end else if (s_infer_state_q == InferQuant) begin
|
||||
for (int lane = 0; lane < 4; lane++) begin
|
||||
model_addr_o[lane] = s_multiplier_base + 15'(s_output_channel) * 15'd4 + 15'(lane);
|
||||
model_addr_o[lane+4] = s_shift_base + 15'(s_output_channel) * 15'd4 + 15'(lane);
|
||||
model_read_valid_o[lane] = 1'b1;
|
||||
model_read_valid_o[lane+4] = 1'b1;
|
||||
model_addr_o[lane] = s_multiplier_base + 15'(s_output_channel) * 15'd4 + 15'(lane);
|
||||
model_addr_o[lane+4] = s_shift_base + 15'(s_output_channel) * 15'd4 + 15'(lane);
|
||||
end
|
||||
end else if (s_infer_state_q == InferMac) begin
|
||||
for (int lane = 0; lane < 16; lane++) begin
|
||||
if (s_lane_term[lane] < {1'b0, s_term_count}) begin
|
||||
s_lane_active[lane] = 1'b1;
|
||||
s_lane_active[lane] = 1'b1;
|
||||
model_read_valid_o[lane] = 1'b1;
|
||||
if (s_operator_q == 4'd0) begin
|
||||
s_lane_input_h[lane] = 7'($signed({1'b0, s_output_height_index})) * 7'sd2 +
|
||||
7'($signed(s_lane_term[lane] / 9'd4)) - 7'sd4;
|
||||
@@ -844,6 +872,7 @@ module apu_kws_engine (
|
||||
s_lane_weight_index[lane] = 15'(s_output_channel) * 15'd40 + 15'(s_lane_term[lane]);
|
||||
if ((s_lane_input_h[lane] >= 0) && (s_lane_input_h[lane] < 7'sd49) &&
|
||||
(s_lane_input_w[lane] >= 0) && (s_lane_input_w[lane] < 5'sd10)) begin
|
||||
scratch_read_valid_o[lane+4] = 1'b1;
|
||||
s_lane_input_index[lane] =
|
||||
13'(s_lane_input_h[lane]) * 13'd10 + 13'(s_lane_input_w[lane]);
|
||||
scratch_read_addr_o[lane+4] =
|
||||
@@ -858,6 +887,7 @@ module apu_kws_engine (
|
||||
s_lane_weight_index[lane] = 15'(s_lane_term[lane]) * 15'd64 + 15'(s_output_channel);
|
||||
if ((s_lane_input_h[lane] >= 0) && (s_lane_input_h[lane] < 7'sd25) &&
|
||||
(s_lane_input_w[lane] >= 0) && (s_lane_input_w[lane] < 5'sd5)) begin
|
||||
scratch_read_valid_o[lane+4] = 1'b1;
|
||||
s_lane_input_index[lane] =
|
||||
(13'(s_lane_input_h[lane]) * 13'd5 + 13'(s_lane_input_w[lane])) *
|
||||
13'd64 + 13'(s_output_channel);
|
||||
@@ -865,6 +895,7 @@ module apu_kws_engine (
|
||||
16'(s_lane_input_index[lane]);
|
||||
end
|
||||
end else begin
|
||||
scratch_read_valid_o[lane+4] = 1'b1;
|
||||
s_lane_input_index[lane] = (s_operator_q == 4'd10) ?
|
||||
13'(s_lane_term[lane]) :
|
||||
(13'(s_output_spatial_index) * 13'd64 + 13'(s_lane_term[lane]));
|
||||
@@ -1134,6 +1165,42 @@ module apu_kws_engine (
|
||||
end
|
||||
end
|
||||
|
||||
assign s_storage_read_access = |model_read_valid_o || |scratch_read_valid_o;
|
||||
assign s_storage_write_access = |scratch_write_valid_o;
|
||||
assign s_storage_has_access = s_storage_read_access || s_storage_write_access;
|
||||
assign storage_write_o = s_storage_write_phase_q || !s_storage_read_access;
|
||||
assign storage_req_o = !s_storage_wait_q && s_storage_has_access;
|
||||
assign s_storage_final_done = storage_done_i &&
|
||||
(s_storage_write_phase_q || !s_storage_read_access || !s_storage_write_access);
|
||||
assign s_storage_state_step = (!s_storage_wait_q && !s_storage_has_access) ||
|
||||
(s_storage_final_done && s_storage_state_owned_q);
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_n_i) begin
|
||||
if (!rst_n_i) begin
|
||||
s_storage_wait_q <= 1'b0;
|
||||
s_storage_write_phase_q <= 1'b0;
|
||||
s_storage_state_owned_q <= 1'b0;
|
||||
end else if (soft_reset_i || resource_reset_i || abort_i) begin
|
||||
s_storage_wait_q <= 1'b0;
|
||||
s_storage_write_phase_q <= 1'b0;
|
||||
s_storage_state_owned_q <= 1'b0;
|
||||
end else begin
|
||||
if (storage_req_o && storage_ready_i) begin
|
||||
s_storage_wait_q <= 1'b1;
|
||||
s_storage_state_owned_q <= (s_front_state_q != FrontIdle) || (s_infer_state_q != InferIdle);
|
||||
end
|
||||
if (storage_done_i && s_storage_wait_q) begin
|
||||
s_storage_wait_q <= 1'b0;
|
||||
if (!s_storage_write_phase_q && s_storage_read_access && s_storage_write_access) begin
|
||||
s_storage_write_phase_q <= 1'b1;
|
||||
end else begin
|
||||
s_storage_write_phase_q <= 1'b0;
|
||||
s_storage_state_owned_q <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign memory_dma_request_valid_o = s_mem_req_q;
|
||||
assign memory_start_ready_o = enable_i && memory_window_i && model_valid_i && model_lock_i &&
|
||||
!abort_i && !soft_reset_i && !resource_reset_i && !s_mem_job_q &&
|
||||
@@ -1338,12 +1405,14 @@ module apu_kws_engine (
|
||||
s_mem_err_detail_q <= 32'd0;
|
||||
end
|
||||
end else begin
|
||||
if (s_front_state_q == FrontIdle || s_front_progress) begin
|
||||
if (s_front_state_q == FrontIdle || storage_progress_i ||
|
||||
(s_storage_state_step && s_front_progress)) begin
|
||||
s_front_watchdog_q <= 32'd0;
|
||||
end else if (!(&s_front_watchdog_q)) begin
|
||||
s_front_watchdog_q <= s_front_watchdog_q + 1'b1;
|
||||
end
|
||||
if (s_infer_state_q == InferIdle || s_infer_progress) begin
|
||||
if (s_infer_state_q == InferIdle || storage_progress_i ||
|
||||
(s_storage_state_step && s_infer_progress)) begin
|
||||
s_infer_watchdog_q <= 32'd0;
|
||||
end else if (!(&s_infer_watchdog_q)) begin
|
||||
s_infer_watchdog_q <= s_infer_watchdog_q + 1'b1;
|
||||
@@ -1493,7 +1562,7 @@ module apu_kws_engine (
|
||||
s_s24_pending_q <= 1'b0;
|
||||
end
|
||||
|
||||
if (s_commit_valid) begin
|
||||
if (s_commit_valid && ((s_front_state_q == FrontIdle) || s_storage_state_step)) begin
|
||||
s_ingress_write_q <= s_next_write;
|
||||
s_epoch_samples_q <= s_next_samples;
|
||||
s_timestamp_q <= s_timestamp_q + 1'b1;
|
||||
@@ -1528,295 +1597,297 @@ module apu_kws_engine (
|
||||
end
|
||||
end
|
||||
|
||||
unique case (s_front_state_q)
|
||||
FrontIdle: begin
|
||||
if (s_frame_pending_q) begin
|
||||
s_frame_pending_q <= 1'b0;
|
||||
s_front_index_q <= 10'd0;
|
||||
s_front_state_q <= FrontFftLoad;
|
||||
end else if (s_window_pending_q && (s_mel_count_q >= 6'd49) &&
|
||||
if (s_storage_state_step) begin
|
||||
unique case (s_front_state_q)
|
||||
FrontIdle: begin
|
||||
if (s_frame_pending_q) begin
|
||||
s_frame_pending_q <= 1'b0;
|
||||
s_front_index_q <= 10'd0;
|
||||
s_front_state_q <= FrontFftLoad;
|
||||
end else if (s_window_pending_q && (s_mel_count_q >= 6'd49) &&
|
||||
(s_infer_state_q == InferIdle)) begin
|
||||
s_window_pending_q <= 1'b0;
|
||||
s_peak_scan_q <= 7'd0;
|
||||
s_window_peak_q <= 16'd1;
|
||||
s_front_state_q <= FrontPeak;
|
||||
end
|
||||
end
|
||||
FrontFir: begin
|
||||
if (s_fir_tap_q == 6'd62) begin
|
||||
s_fir_tap_q <= 6'd0;
|
||||
s_fir_acc_q <= 64'sd0;
|
||||
s_fir_phase_q <= (s_fir_phase_q == (s_decimation - 1'b1)) ?
|
||||
3'd0 : s_fir_phase_q + 1'b1;
|
||||
s_front_state_q <= FrontIdle;
|
||||
end else begin
|
||||
s_fir_acc_q <= s_fir_total;
|
||||
s_fir_tap_q <= s_fir_tap_q + 1'b1;
|
||||
end
|
||||
end
|
||||
FrontFftLoad: begin
|
||||
if (s_front_index_q == 10'd511) begin
|
||||
s_fft_len_q <= 10'd2;
|
||||
s_fft_half_q <= 9'd1;
|
||||
s_fft_group_q <= 9'd0;
|
||||
s_fft_j_q <= 8'd0;
|
||||
s_front_state_q <= FrontFftRun;
|
||||
end else begin
|
||||
s_front_index_q <= s_front_index_q + 1'b1;
|
||||
end
|
||||
end
|
||||
FrontFftRun: begin
|
||||
if (s_fft_overflow) begin
|
||||
s_fault_q <= 1'b1;
|
||||
s_fault_code_q <= `APB4_APU__ERROR_CODE_KWS_ARITHMETIC;
|
||||
s_fault_stage_q <= `APB4_APU__ERROR_STAGE_KWS_FRONTEND;
|
||||
s_fault_detail_q <= 32'h0700_0014;
|
||||
s_stop_latched_q <= 1'b1;
|
||||
s_front_state_q <= FrontIdle;
|
||||
end else begin
|
||||
if (s_fft_j_q + 1'b1 == s_fft_half_q) begin
|
||||
s_fft_j_q <= 8'd0;
|
||||
if (s_fft_group_q + s_fft_len_q == 10'd512) begin
|
||||
s_fft_group_q <= 9'd0;
|
||||
if (s_fft_len_q == 10'd512) begin
|
||||
s_front_index_q <= 10'd0;
|
||||
s_front_state_q <= FrontMagnitude;
|
||||
end else begin
|
||||
s_fft_len_q <= s_fft_len_q << 1;
|
||||
s_fft_half_q <= s_fft_half_q << 1;
|
||||
end
|
||||
end else begin
|
||||
s_fft_group_q <= 9'(s_fft_group_q + s_fft_len_q);
|
||||
end
|
||||
end else begin
|
||||
s_fft_j_q <= s_fft_j_q + 1'b1;
|
||||
s_window_pending_q <= 1'b0;
|
||||
s_peak_scan_q <= 7'd0;
|
||||
s_window_peak_q <= 16'd1;
|
||||
s_front_state_q <= FrontPeak;
|
||||
end
|
||||
end
|
||||
end
|
||||
FrontMagnitude: begin
|
||||
if (s_front_index_q == 10'd256) begin
|
||||
s_mel_band_q <= 8'd0;
|
||||
s_mel_bin_q <= 9'd0;
|
||||
s_mel_acc_q <= 64'd0;
|
||||
s_front_state_q <= FrontMel;
|
||||
end else begin
|
||||
s_front_index_q <= s_front_index_q + 1'b1;
|
||||
end
|
||||
end
|
||||
FrontMel: begin
|
||||
if (s_mel_total < s_mel_acc_q) begin
|
||||
s_fault_q <= 1'b1;
|
||||
s_fault_code_q <= `APB4_APU__ERROR_CODE_KWS_ARITHMETIC;
|
||||
s_fault_stage_q <= `APB4_APU__ERROR_STAGE_KWS_FRONTEND;
|
||||
s_fault_detail_q <= 32'h0700_0015;
|
||||
s_stop_latched_q <= 1'b1;
|
||||
s_front_state_q <= FrontIdle;
|
||||
end else if (s_mel_overwrite) begin
|
||||
s_front_state_q <= FrontIdle;
|
||||
end else if (s_mel_bin_q == 9'd256) begin
|
||||
s_mel_bin_q <= 9'd0;
|
||||
s_mel_acc_q <= 64'd0;
|
||||
if (s_mel_band_q == 8'd39) begin
|
||||
s_mel_band_q <= 8'd0;
|
||||
s_mel_write_q <= (s_mel_write_q == 6'd49) ? 6'd0 : s_mel_write_q + 1'b1;
|
||||
if (s_mel_count_q < 6'd50) s_mel_count_q <= s_mel_count_q + 1'b1;
|
||||
if (!counter_clear_i) begin
|
||||
s_frame_count_q <= (s_frame_count_q == 32'hffff_ffff) ?
|
||||
s_frame_count_q : s_frame_count_q + 1'b1;
|
||||
end
|
||||
FrontFir: begin
|
||||
if (s_fir_tap_q == 6'd62) begin
|
||||
s_fir_tap_q <= 6'd0;
|
||||
s_fir_acc_q <= 64'sd0;
|
||||
s_fir_phase_q <= (s_fir_phase_q == (s_decimation - 1'b1)) ?
|
||||
3'd0 : s_fir_phase_q + 1'b1;
|
||||
s_front_state_q <= FrontIdle;
|
||||
end else begin
|
||||
s_mel_band_q <= s_mel_band_q + 1'b1;
|
||||
s_fir_acc_q <= s_fir_total;
|
||||
s_fir_tap_q <= s_fir_tap_q + 1'b1;
|
||||
end
|
||||
end else begin
|
||||
s_mel_acc_q <= s_mel_total;
|
||||
s_mel_bin_q <= s_mel_bin_q + 1'b1;
|
||||
end
|
||||
end
|
||||
FrontPeak: begin
|
||||
if (s_peak_data > s_window_peak_q) begin
|
||||
s_window_peak_q <= s_peak_data;
|
||||
FrontFftLoad: begin
|
||||
if (s_front_index_q == 10'd511) begin
|
||||
s_fft_len_q <= 10'd2;
|
||||
s_fft_half_q <= 9'd1;
|
||||
s_fft_group_q <= 9'd0;
|
||||
s_fft_j_q <= 8'd0;
|
||||
s_front_state_q <= FrontFftRun;
|
||||
end else begin
|
||||
s_front_index_q <= s_front_index_q + 1'b1;
|
||||
end
|
||||
end
|
||||
if (s_peak_scan_q == 7'd99) begin
|
||||
s_mfcc_row_q <= 6'd0;
|
||||
s_mfcc_band_q <= 6'd0;
|
||||
s_front_state_q <= FrontLog;
|
||||
end else begin
|
||||
s_peak_scan_q <= s_peak_scan_q + 1'b1;
|
||||
FrontFftRun: begin
|
||||
if (s_fft_overflow) begin
|
||||
s_fault_q <= 1'b1;
|
||||
s_fault_code_q <= `APB4_APU__ERROR_CODE_KWS_ARITHMETIC;
|
||||
s_fault_stage_q <= `APB4_APU__ERROR_STAGE_KWS_FRONTEND;
|
||||
s_fault_detail_q <= 32'h0700_0014;
|
||||
s_stop_latched_q <= 1'b1;
|
||||
s_front_state_q <= FrontIdle;
|
||||
end else begin
|
||||
if (s_fft_j_q + 1'b1 == s_fft_half_q) begin
|
||||
s_fft_j_q <= 8'd0;
|
||||
if (s_fft_group_q + s_fft_len_q == 10'd512) begin
|
||||
s_fft_group_q <= 9'd0;
|
||||
if (s_fft_len_q == 10'd512) begin
|
||||
s_front_index_q <= 10'd0;
|
||||
s_front_state_q <= FrontMagnitude;
|
||||
end else begin
|
||||
s_fft_len_q <= s_fft_len_q << 1;
|
||||
s_fft_half_q <= s_fft_half_q << 1;
|
||||
end
|
||||
end else begin
|
||||
s_fft_group_q <= 9'(s_fft_group_q + s_fft_len_q);
|
||||
end
|
||||
end else begin
|
||||
s_fft_j_q <= s_fft_j_q + 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
FrontLog: begin
|
||||
if (s_mfcc_band_q == 6'd39) begin
|
||||
s_mfcc_band_q <= 6'd0;
|
||||
s_mfcc_coefficient_q <= 4'd0;
|
||||
s_dct_acc_q <= 64'sd0;
|
||||
s_front_state_q <= FrontDct;
|
||||
end else begin
|
||||
s_mfcc_band_q <= s_mfcc_band_q + 1'b1;
|
||||
FrontMagnitude: begin
|
||||
if (s_front_index_q == 10'd256) begin
|
||||
s_mel_band_q <= 8'd0;
|
||||
s_mel_bin_q <= 9'd0;
|
||||
s_mel_acc_q <= 64'd0;
|
||||
s_front_state_q <= FrontMel;
|
||||
end else begin
|
||||
s_front_index_q <= s_front_index_q + 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
FrontDct: begin
|
||||
if (s_mfcc_band_q == 6'd39) begin
|
||||
s_mfcc_band_q <= 6'd0;
|
||||
s_dct_acc_q <= 64'sd0;
|
||||
if (s_mfcc_coefficient_q == 4'd9) begin
|
||||
s_mfcc_coefficient_q <= 4'd0;
|
||||
if (s_mfcc_row_q == 6'd48) begin
|
||||
s_operator_q <= 4'd0;
|
||||
s_output_q <= 14'd0;
|
||||
s_infer_state_q <= InferBias;
|
||||
FrontMel: begin
|
||||
if (s_mel_total < s_mel_acc_q) begin
|
||||
s_fault_q <= 1'b1;
|
||||
s_fault_code_q <= `APB4_APU__ERROR_CODE_KWS_ARITHMETIC;
|
||||
s_fault_stage_q <= `APB4_APU__ERROR_STAGE_KWS_FRONTEND;
|
||||
s_fault_detail_q <= 32'h0700_0015;
|
||||
s_stop_latched_q <= 1'b1;
|
||||
s_front_state_q <= FrontIdle;
|
||||
end else if (s_mel_overwrite) begin
|
||||
s_front_state_q <= FrontIdle;
|
||||
end else if (s_mel_bin_q == 9'd256) begin
|
||||
s_mel_bin_q <= 9'd0;
|
||||
s_mel_acc_q <= 64'd0;
|
||||
if (s_mel_band_q == 8'd39) begin
|
||||
s_mel_band_q <= 8'd0;
|
||||
s_mel_write_q <= (s_mel_write_q == 6'd49) ? 6'd0 : s_mel_write_q + 1'b1;
|
||||
if (s_mel_count_q < 6'd50) s_mel_count_q <= s_mel_count_q + 1'b1;
|
||||
if (!counter_clear_i) begin
|
||||
s_frame_count_q <= (s_frame_count_q == 32'hffff_ffff) ?
|
||||
s_frame_count_q : s_frame_count_q + 1'b1;
|
||||
end
|
||||
s_front_state_q <= FrontIdle;
|
||||
end else begin
|
||||
s_mfcc_row_q <= s_mfcc_row_q + 1'b1;
|
||||
s_front_state_q <= FrontLog;
|
||||
s_mel_band_q <= s_mel_band_q + 1'b1;
|
||||
end
|
||||
end else begin
|
||||
s_mfcc_coefficient_q <= s_mfcc_coefficient_q + 1'b1;
|
||||
s_mel_acc_q <= s_mel_total;
|
||||
s_mel_bin_q <= s_mel_bin_q + 1'b1;
|
||||
end
|
||||
end else begin
|
||||
s_dct_acc_q <= s_dct_total;
|
||||
s_mfcc_band_q <= s_mfcc_band_q + 1'b1;
|
||||
end
|
||||
end
|
||||
default: s_front_state_q <= FrontIdle;
|
||||
endcase
|
||||
|
||||
unique case (s_infer_state_q)
|
||||
InferIdle: begin
|
||||
end
|
||||
InferBias: begin
|
||||
s_mac_q <= 64'($signed(s_bias_word));
|
||||
s_term_q <= 8'd0;
|
||||
s_infer_state_q <= InferMac;
|
||||
end
|
||||
InferMac: begin
|
||||
if ((s_mac_total > 64'sh0000_0000_7fff_ffff) ||
|
||||
(s_mac_total < -64'sh0000_0000_8000_0000)) begin
|
||||
s_fault_q <= 1'b1;
|
||||
s_fault_code_q <= `APB4_APU__ERROR_CODE_KWS_ARITHMETIC;
|
||||
s_fault_stage_q <= `APB4_APU__ERROR_STAGE_KWS_INFERENCE;
|
||||
s_fault_detail_q <= 32'h0700_0016;
|
||||
s_stop_latched_q <= 1'b1;
|
||||
s_infer_state_q <= InferIdle;
|
||||
end else if (s_term_q + 8'd16 >= s_term_count) begin
|
||||
s_mac_q <= s_mac_total;
|
||||
s_infer_state_q <= InferQuant;
|
||||
end else begin
|
||||
s_mac_q <= s_mac_total;
|
||||
s_term_q <= s_term_q + 8'd16;
|
||||
FrontPeak: begin
|
||||
if (s_peak_data > s_window_peak_q) begin
|
||||
s_window_peak_q <= s_peak_data;
|
||||
end
|
||||
if (s_peak_scan_q == 7'd99) begin
|
||||
s_mfcc_row_q <= 6'd0;
|
||||
s_mfcc_band_q <= 6'd0;
|
||||
s_front_state_q <= FrontLog;
|
||||
end else begin
|
||||
s_peak_scan_q <= s_peak_scan_q + 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
InferQuant: begin
|
||||
if (s_requant_overflow) begin
|
||||
s_fault_q <= 1'b1;
|
||||
s_fault_code_q <= `APB4_APU__ERROR_CODE_KWS_ARITHMETIC;
|
||||
s_fault_stage_q <= `APB4_APU__ERROR_STAGE_KWS_INFERENCE;
|
||||
s_fault_detail_q <= 32'h0700_0017;
|
||||
s_stop_latched_q <= 1'b1;
|
||||
s_infer_state_q <= InferIdle;
|
||||
end else begin
|
||||
if (s_output_q + 1'b1 == s_output_count) begin
|
||||
s_output_q <= 14'd0;
|
||||
if (s_operator_q == 4'd8) begin
|
||||
s_operator_q <= 4'd9;
|
||||
s_term_q <= 8'd0;
|
||||
s_mac_q <= 64'sd0;
|
||||
s_infer_state_q <= InferPool;
|
||||
end else if (s_operator_q == 4'd10) begin
|
||||
s_operator_q <= 4'd11;
|
||||
s_softmax_index_q <= 4'd0;
|
||||
s_softmax_max_q <= -8'sd128;
|
||||
s_infer_state_q <= InferSoftmaxMax;
|
||||
FrontLog: begin
|
||||
if (s_mfcc_band_q == 6'd39) begin
|
||||
s_mfcc_band_q <= 6'd0;
|
||||
s_mfcc_coefficient_q <= 4'd0;
|
||||
s_dct_acc_q <= 64'sd0;
|
||||
s_front_state_q <= FrontDct;
|
||||
end else begin
|
||||
s_mfcc_band_q <= s_mfcc_band_q + 1'b1;
|
||||
end
|
||||
end
|
||||
FrontDct: begin
|
||||
if (s_mfcc_band_q == 6'd39) begin
|
||||
s_mfcc_band_q <= 6'd0;
|
||||
s_dct_acc_q <= 64'sd0;
|
||||
if (s_mfcc_coefficient_q == 4'd9) begin
|
||||
s_mfcc_coefficient_q <= 4'd0;
|
||||
if (s_mfcc_row_q == 6'd48) begin
|
||||
s_operator_q <= 4'd0;
|
||||
s_output_q <= 14'd0;
|
||||
s_infer_state_q <= InferBias;
|
||||
s_front_state_q <= FrontIdle;
|
||||
end else begin
|
||||
s_mfcc_row_q <= s_mfcc_row_q + 1'b1;
|
||||
s_front_state_q <= FrontLog;
|
||||
end
|
||||
end else begin
|
||||
s_operator_q <= s_operator_q + 1'b1;
|
||||
s_mfcc_coefficient_q <= s_mfcc_coefficient_q + 1'b1;
|
||||
end
|
||||
end else begin
|
||||
s_dct_acc_q <= s_dct_total;
|
||||
s_mfcc_band_q <= s_mfcc_band_q + 1'b1;
|
||||
end
|
||||
end
|
||||
default: s_front_state_q <= FrontIdle;
|
||||
endcase
|
||||
|
||||
unique case (s_infer_state_q)
|
||||
InferIdle: begin
|
||||
end
|
||||
InferBias: begin
|
||||
s_mac_q <= 64'($signed(s_bias_word));
|
||||
s_term_q <= 8'd0;
|
||||
s_infer_state_q <= InferMac;
|
||||
end
|
||||
InferMac: begin
|
||||
if ((s_mac_total > 64'sh0000_0000_7fff_ffff) ||
|
||||
(s_mac_total < -64'sh0000_0000_8000_0000)) begin
|
||||
s_fault_q <= 1'b1;
|
||||
s_fault_code_q <= `APB4_APU__ERROR_CODE_KWS_ARITHMETIC;
|
||||
s_fault_stage_q <= `APB4_APU__ERROR_STAGE_KWS_INFERENCE;
|
||||
s_fault_detail_q <= 32'h0700_0016;
|
||||
s_stop_latched_q <= 1'b1;
|
||||
s_infer_state_q <= InferIdle;
|
||||
end else if (s_term_q + 8'd16 >= s_term_count) begin
|
||||
s_mac_q <= s_mac_total;
|
||||
s_infer_state_q <= InferQuant;
|
||||
end else begin
|
||||
s_mac_q <= s_mac_total;
|
||||
s_term_q <= s_term_q + 8'd16;
|
||||
end
|
||||
end
|
||||
InferQuant: begin
|
||||
if (s_requant_overflow) begin
|
||||
s_fault_q <= 1'b1;
|
||||
s_fault_code_q <= `APB4_APU__ERROR_CODE_KWS_ARITHMETIC;
|
||||
s_fault_stage_q <= `APB4_APU__ERROR_STAGE_KWS_INFERENCE;
|
||||
s_fault_detail_q <= 32'h0700_0017;
|
||||
s_stop_latched_q <= 1'b1;
|
||||
s_infer_state_q <= InferIdle;
|
||||
end else begin
|
||||
if (s_output_q + 1'b1 == s_output_count) begin
|
||||
s_output_q <= 14'd0;
|
||||
if (s_operator_q == 4'd8) begin
|
||||
s_operator_q <= 4'd9;
|
||||
s_term_q <= 8'd0;
|
||||
s_mac_q <= 64'sd0;
|
||||
s_infer_state_q <= InferPool;
|
||||
end else if (s_operator_q == 4'd10) begin
|
||||
s_operator_q <= 4'd11;
|
||||
s_softmax_index_q <= 4'd0;
|
||||
s_softmax_max_q <= -8'sd128;
|
||||
s_infer_state_q <= InferSoftmaxMax;
|
||||
end else begin
|
||||
s_operator_q <= s_operator_q + 1'b1;
|
||||
s_infer_state_q <= InferBias;
|
||||
end
|
||||
end else begin
|
||||
s_output_q <= s_output_q + 1'b1;
|
||||
s_infer_state_q <= InferBias;
|
||||
end
|
||||
end else begin
|
||||
s_output_q <= s_output_q + 1'b1;
|
||||
s_infer_state_q <= InferBias;
|
||||
end
|
||||
end
|
||||
end
|
||||
InferPool: begin
|
||||
if (s_term_q + 8'd16 >= 8'd125) begin
|
||||
s_term_q <= 8'd0;
|
||||
s_mac_q <= 64'sd0;
|
||||
if (s_output_q == 14'd63) begin
|
||||
s_output_q <= 14'd0;
|
||||
s_operator_q <= 4'd10;
|
||||
s_infer_state_q <= InferBias;
|
||||
InferPool: begin
|
||||
if (s_term_q + 8'd16 >= 8'd125) begin
|
||||
s_term_q <= 8'd0;
|
||||
s_mac_q <= 64'sd0;
|
||||
if (s_output_q == 14'd63) begin
|
||||
s_output_q <= 14'd0;
|
||||
s_operator_q <= 4'd10;
|
||||
s_infer_state_q <= InferBias;
|
||||
end else begin
|
||||
s_output_q <= s_output_q + 1'b1;
|
||||
end
|
||||
end else begin
|
||||
s_output_q <= s_output_q + 1'b1;
|
||||
s_mac_q <= s_pool_sum;
|
||||
s_term_q <= s_term_q + 8'd16;
|
||||
end
|
||||
end else begin
|
||||
s_mac_q <= s_pool_sum;
|
||||
s_term_q <= s_term_q + 8'd16;
|
||||
end
|
||||
end
|
||||
InferSoftmaxMax: begin
|
||||
if (s_logit_data > s_softmax_max_q) begin
|
||||
s_softmax_max_q <= s_logit_data;
|
||||
InferSoftmaxMax: begin
|
||||
if (s_logit_data > s_softmax_max_q) begin
|
||||
s_softmax_max_q <= s_logit_data;
|
||||
end
|
||||
if (s_softmax_index_q == 4'd11) begin
|
||||
s_softmax_index_q <= 4'd0;
|
||||
s_softmax_sum_q <= 32'd0;
|
||||
s_infer_state_q <= InferSoftmaxSum;
|
||||
end else begin
|
||||
s_softmax_index_q <= s_softmax_index_q + 1'b1;
|
||||
end
|
||||
end
|
||||
if (s_softmax_index_q == 4'd11) begin
|
||||
s_softmax_index_q <= 4'd0;
|
||||
s_softmax_sum_q <= 32'd0;
|
||||
s_infer_state_q <= InferSoftmaxSum;
|
||||
end else begin
|
||||
s_softmax_index_q <= s_softmax_index_q + 1'b1;
|
||||
InferSoftmaxSum: begin
|
||||
if (s_softmax_sum_diff >= -9'sd124) begin
|
||||
s_softmax_sum_q <= s_softmax_sum_q +
|
||||
rounding_divide_pot(apu_kws_softmax_exp_q31(-s_softmax_sum_diff[6:0]), 12);
|
||||
end
|
||||
if (s_softmax_index_q == 4'd11) begin
|
||||
s_softmax_index_q <= 4'd0;
|
||||
s_infer_state_q <= InferSoftmaxScale;
|
||||
end else begin
|
||||
s_softmax_index_q <= s_softmax_index_q + 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
InferSoftmaxSum: begin
|
||||
if (s_softmax_sum_diff >= -9'sd124) begin
|
||||
s_softmax_sum_q <= s_softmax_sum_q +
|
||||
rounding_divide_pot(apu_kws_softmax_exp_q31(-s_softmax_sum_diff[6:0]), 12);
|
||||
InferSoftmaxScale: begin
|
||||
if (s_softmax_index_q == 0) begin
|
||||
s_softmax_scale_q <= reciprocal_q31(s_softmax_shifted_sum);
|
||||
s_softmax_bits_q <= 6'(7'sd12 - $signed({1'b0, s_softmax_headroom}));
|
||||
end
|
||||
if (s_softmax_index_q == 4'd12) begin
|
||||
s_softmax_index_q <= 4'd0;
|
||||
s_infer_state_q <= InferComplete;
|
||||
end else begin
|
||||
s_softmax_index_q <= s_softmax_index_q + 1'b1;
|
||||
end
|
||||
end
|
||||
if (s_softmax_index_q == 4'd11) begin
|
||||
s_softmax_index_q <= 4'd0;
|
||||
s_infer_state_q <= InferSoftmaxScale;
|
||||
end else begin
|
||||
s_softmax_index_q <= s_softmax_index_q + 1'b1;
|
||||
end
|
||||
end
|
||||
InferSoftmaxScale: begin
|
||||
if (s_softmax_index_q == 0) begin
|
||||
s_softmax_scale_q <= reciprocal_q31(s_softmax_shifted_sum);
|
||||
s_softmax_bits_q <= 6'(7'sd12 - $signed({1'b0, s_softmax_headroom}));
|
||||
end
|
||||
if (s_softmax_index_q == 4'd12) begin
|
||||
s_softmax_index_q <= 4'd0;
|
||||
s_infer_state_q <= InferComplete;
|
||||
end else begin
|
||||
s_softmax_index_q <= s_softmax_index_q + 1'b1;
|
||||
end
|
||||
end
|
||||
InferComplete: begin
|
||||
s_result_q <= {15'd0, s_stable_hit, s_best_score, s_best_class};
|
||||
s_result_valid_q <= 1'b1;
|
||||
s_timestamp_lo_q <= s_timestamp_q;
|
||||
s_timestamp_hi_q <= 32'd0;
|
||||
if (!counter_clear_i) begin
|
||||
s_inference_count_q <= (s_inference_count_q == 32'hffff_ffff) ?
|
||||
s_inference_count_q : s_inference_count_q + 1'b1;
|
||||
end
|
||||
s_debounce_run_q <= s_next_debounce_run[7:0];
|
||||
s_last_class_q <= s_best_class;
|
||||
s_last_match_q <= s_match;
|
||||
s_stable_hit_q <= s_stable_hit;
|
||||
if (s_hit_event) begin
|
||||
InferComplete: begin
|
||||
s_result_q <= {15'd0, s_stable_hit, s_best_score, s_best_class};
|
||||
s_result_valid_q <= 1'b1;
|
||||
s_timestamp_lo_q <= s_timestamp_q;
|
||||
s_timestamp_hi_q <= 32'd0;
|
||||
if (!counter_clear_i) begin
|
||||
s_hit_count_q <= (s_hit_count_q == 32'hffff_ffff) ?
|
||||
s_inference_count_q <= (s_inference_count_q == 32'hffff_ffff) ?
|
||||
s_inference_count_q : s_inference_count_q + 1'b1;
|
||||
end
|
||||
s_debounce_run_q <= s_next_debounce_run[7:0];
|
||||
s_last_class_q <= s_best_class;
|
||||
s_last_match_q <= s_match;
|
||||
s_stable_hit_q <= s_stable_hit;
|
||||
if (s_hit_event) begin
|
||||
if (!counter_clear_i) begin
|
||||
s_hit_count_q <= (s_hit_count_q == 32'hffff_ffff) ?
|
||||
s_hit_count_q : s_hit_count_q + 1'b1;
|
||||
end
|
||||
s_hit_irq_q <= 1'b1;
|
||||
end
|
||||
s_infer_state_q <= InferIdle;
|
||||
if (s_mem_job_q) begin
|
||||
s_mem_job_q <= 1'b0;
|
||||
s_mem_done_q <= 1'b1;
|
||||
end
|
||||
s_hit_irq_q <= 1'b1;
|
||||
end
|
||||
s_infer_state_q <= InferIdle;
|
||||
if (s_mem_job_q) begin
|
||||
s_mem_job_q <= 1'b0;
|
||||
s_mem_done_q <= 1'b1;
|
||||
end
|
||||
end
|
||||
default: s_infer_state_q <= InferIdle;
|
||||
endcase
|
||||
default: s_infer_state_q <= InferIdle;
|
||||
endcase
|
||||
end
|
||||
|
||||
if ((s_mem_job_q && s_mem_dma_done_q && !s_mem_word_valid_q) &&
|
||||
((s_mem_received_q != 32'd32000) || s_mem_err_q)) begin
|
||||
|
||||
@@ -16,9 +16,16 @@ module apu_kws_sram_client (
|
||||
output logic [31:0] data_o,
|
||||
output logic valid_o,
|
||||
output logic access_err_o,
|
||||
input logic access_req_i,
|
||||
output logic access_ready_o,
|
||||
output logic access_done_o,
|
||||
output logic access_progress_o,
|
||||
input logic access_write_i,
|
||||
input logic [15:0] model_read_valid_i,
|
||||
input logic [15:0][14:0] model_addr_i,
|
||||
output logic [15:0][ 7:0] model_data_o,
|
||||
input logic scratch_clear_i,
|
||||
input logic [19:0] scratch_read_valid_i,
|
||||
input logic [19:0][15:0] scratch_read_addr_i,
|
||||
output logic [19:0][31:0] scratch_read_data_o,
|
||||
input logic [ 5:0] scratch_write_valid_i,
|
||||
@@ -28,108 +35,328 @@ module apu_kws_sram_client (
|
||||
output logic scratch_access_err_o
|
||||
// verilog_format: on
|
||||
);
|
||||
localparam int unsigned ModelWordCount = `RETROSOC_APU_KWS__MODEL_BYTES / 4;
|
||||
localparam int unsigned ScratchWordCount = `RETROSOC_APU_KWS__SCRATCH_BYTES / 4;
|
||||
localparam int unsigned KwsWordCount = ModelWordCount + ScratchWordCount;
|
||||
localparam int unsigned BankCount = 16;
|
||||
localparam int unsigned FirEntryCount = 63;
|
||||
|
||||
logic [ 31:0] mem [0:KwsWordCount-1];
|
||||
logic [FirEntryCount-1:0] s_fir_valid_q;
|
||||
logic s_pending_q;
|
||||
logic s_err_q;
|
||||
logic [ 31:0] s_data_q;
|
||||
logic s_range_ok;
|
||||
logic [ 13:0] s_word_addr;
|
||||
logic [ BankCount-1:0] s_bank_cs;
|
||||
logic [ BankCount-1:0] s_bank_wren;
|
||||
logic [ BankCount-1:0][ 9:0] s_bank_addr;
|
||||
logic [ BankCount-1:0][31:0] s_bank_wdata;
|
||||
logic [ BankCount-1:0][ 3:0] s_bank_wmask;
|
||||
logic [ BankCount-1:0][31:0] s_bank_rdata;
|
||||
|
||||
assign s_range_ok = (addr_i[1:0] == 2'd0) &&
|
||||
logic s_busy_q;
|
||||
logic [ 15:0] s_model_pending_q;
|
||||
logic [ 15:0][14:0] s_model_addr_q;
|
||||
logic [ 19:0] s_scratch_read_pending_q;
|
||||
logic [ 19:0][15:0] s_scratch_read_addr_q;
|
||||
logic [ 5:0] s_scratch_write_pending_q;
|
||||
logic [ 5:0][15:0] s_scratch_write_addr_q;
|
||||
logic [ 5:0][31:0] s_scratch_write_data_q;
|
||||
logic [ 5:0][ 3:0] s_scratch_write_strb_q;
|
||||
logic [ BankCount-1:0] s_read_pipe_valid_q;
|
||||
logic [ BankCount-1:0][15:0] s_read_pipe_model_q;
|
||||
logic [ BankCount-1:0][19:0] s_read_pipe_scratch_q;
|
||||
|
||||
logic [ BankCount-1:0] s_issue_write;
|
||||
logic [ BankCount-1:0][ 2:0] s_issue_write_lane;
|
||||
logic [ BankCount-1:0] s_issue_read;
|
||||
logic [ BankCount-1:0][15:0] s_issue_model_mask;
|
||||
logic [ BankCount-1:0][19:0] s_issue_scratch_mask;
|
||||
logic [FirEntryCount-1:0] s_fir_valid_q;
|
||||
|
||||
logic s_loader_range_ok;
|
||||
logic [ 14:0] s_loader_offset;
|
||||
logic [ 3:0] s_loader_bank;
|
||||
logic [ 9:0] s_loader_row;
|
||||
logic s_loader_read_pending_q;
|
||||
logic [ 3:0] s_loader_read_bank_q;
|
||||
logic s_loader_read_err_q;
|
||||
|
||||
`ifndef SYNTHESIS
|
||||
// Kept as a simulation-loading boundary for the existing APUM/MFCC fixtures.
|
||||
// The synthesizable macro path below contains only the sixteen physical banks.
|
||||
logic [31:0] mem[0:16383];
|
||||
`endif
|
||||
|
||||
function automatic logic [3:0] model_bank(input logic [14:0] address_i);
|
||||
model_bank = {1'b0, address_i[4:2] ^ address_i[8:6]};
|
||||
endfunction
|
||||
|
||||
function automatic logic [3:0] scratch_bank(input logic [15:0] address_i);
|
||||
scratch_bank = {1'b1, address_i[4:2] ^ address_i[8:6]};
|
||||
endfunction
|
||||
|
||||
function automatic logic [13:0] bank_word(input logic [3:0] bank_i, input logic [9:0] row_i);
|
||||
bank_word = {bank_i[3], row_i, bank_i[2:0] ^ row_i[3:1]};
|
||||
endfunction
|
||||
|
||||
assign s_loader_range_ok = (addr_i[1:0] == 2'd0) &&
|
||||
(addr_i >= `APB4_APU__LOCAL_KWS_BASE) &&
|
||||
(addr_i < (`APB4_APU__LOCAL_KWS_BASE + `RETROSOC_APU_KWS__MODEL_BYTES));
|
||||
assign s_word_addr = 14'(addr_i[15:2] - 14'h2800);
|
||||
assign ready_o = rst_n_i && !s_pending_q;
|
||||
assign data_o = s_data_q;
|
||||
assign valid_o = s_pending_q && !s_err_q;
|
||||
assign access_err_o = (req_i && ready_o && !s_range_ok) || (s_pending_q && s_err_q);
|
||||
assign s_loader_offset = 15'(addr_i - `APB4_APU__LOCAL_KWS_BASE);
|
||||
assign s_loader_bank = model_bank(s_loader_offset);
|
||||
assign s_loader_row = s_loader_offset[14:5];
|
||||
|
||||
for (genvar lane = 0; lane < 16; lane++) begin : gen_model_read
|
||||
assign model_data_o[lane] = mem[{1'b0, model_addr_i[lane][14:2]}][8*model_addr_i[lane][1:0]+:8];
|
||||
end
|
||||
|
||||
for (genvar lane = 0; lane < 20; lane++) begin : gen_scratch_read
|
||||
logic s_fir_range;
|
||||
logic [ 5:0] s_fir_index;
|
||||
logic [13:0] s_memory_word;
|
||||
|
||||
assign s_fir_range =
|
||||
(scratch_read_addr_i[lane] >= `RETROSOC_APU_KWS__SCRATCH_FIR_BASE) &&
|
||||
(scratch_read_addr_i[lane] <
|
||||
(`RETROSOC_APU_KWS__SCRATCH_FIR_BASE + 16'(FirEntryCount * 2)));
|
||||
assign s_fir_index = 6'((scratch_read_addr_i[lane] - `RETROSOC_APU_KWS__SCRATCH_FIR_BASE) >> 1);
|
||||
assign s_memory_word = 14'(ModelWordCount) + {1'b0, scratch_read_addr_i[lane][14:2]};
|
||||
assign scratch_read_data_o[lane] =
|
||||
scratch_read_addr_i[lane][15] || (s_fir_range && !s_fir_valid_q[s_fir_index]) ?
|
||||
32'd0 : mem[s_memory_word];
|
||||
end
|
||||
assign ready_o = rst_n_i && !s_busy_q && !s_loader_read_pending_q;
|
||||
assign data_o = s_bank_rdata[s_loader_read_bank_q];
|
||||
assign valid_o = s_loader_read_pending_q && !s_loader_read_err_q;
|
||||
assign access_err_o = (req_i && ready_o && !s_loader_range_ok) ||
|
||||
(s_loader_read_pending_q && s_loader_read_err_q);
|
||||
assign access_ready_o = rst_n_i && !s_busy_q && !s_loader_read_pending_q;
|
||||
assign access_done_o = s_busy_q && (s_model_pending_q == 16'd0) &&
|
||||
(s_scratch_read_pending_q == 20'd0) && (s_scratch_write_pending_q == 6'd0) &&
|
||||
(s_read_pipe_valid_q == BankCount'(0));
|
||||
assign access_progress_o = |s_issue_write || |s_issue_read;
|
||||
|
||||
always_comb begin
|
||||
scratch_access_err_o = 1'b0;
|
||||
for (int lane = 0; lane < 20; lane++) begin
|
||||
scratch_access_err_o |= scratch_read_valid_i[lane] && scratch_read_addr_i[lane][15];
|
||||
end
|
||||
for (int lane = 0; lane < 6; lane++) begin
|
||||
scratch_access_err_o |= scratch_write_valid_i[lane] && scratch_write_addr_i[lane][15];
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_n_i) begin
|
||||
if (!rst_n_i) begin
|
||||
s_fir_valid_q <= FirEntryCount'(0);
|
||||
s_pending_q <= 1'b0;
|
||||
s_err_q <= 1'b0;
|
||||
s_data_q <= 32'd0;
|
||||
end else begin
|
||||
s_pending_q <= 1'b0;
|
||||
s_err_q <= 1'b0;
|
||||
if (scratch_clear_i) begin
|
||||
s_fir_valid_q <= FirEntryCount'(0);
|
||||
end
|
||||
if (req_i && ready_o) begin
|
||||
if (!s_range_ok) begin
|
||||
s_pending_q <= 1'b1;
|
||||
s_err_q <= 1'b1;
|
||||
end else if (write_i) begin
|
||||
if (strb_i[0]) mem[s_word_addr][7:0] <= data_i[7:0];
|
||||
if (strb_i[1]) mem[s_word_addr][15:8] <= data_i[15:8];
|
||||
if (strb_i[2]) mem[s_word_addr][23:16] <= data_i[23:16];
|
||||
if (strb_i[3]) mem[s_word_addr][31:24] <= data_i[31:24];
|
||||
end else begin
|
||||
s_data_q <= mem[s_word_addr];
|
||||
s_pending_q <= 1'b1;
|
||||
always_comb begin
|
||||
s_bank_cs = BankCount'(0);
|
||||
s_bank_wren = BankCount'(0);
|
||||
s_bank_addr = '0;
|
||||
s_bank_wdata = '0;
|
||||
s_bank_wmask = '0;
|
||||
s_issue_write = BankCount'(0);
|
||||
s_issue_write_lane = '0;
|
||||
s_issue_read = BankCount'(0);
|
||||
s_issue_model_mask = '0;
|
||||
s_issue_scratch_mask = '0;
|
||||
|
||||
if (req_i && ready_o && s_loader_range_ok) begin
|
||||
s_bank_cs[s_loader_bank] = 1'b1;
|
||||
s_bank_wren[s_loader_bank] = write_i;
|
||||
s_bank_addr[s_loader_bank] = s_loader_row;
|
||||
s_bank_wdata[s_loader_bank] = data_i;
|
||||
s_bank_wmask[s_loader_bank] = strb_i;
|
||||
end else if (s_busy_q) begin
|
||||
for (int bank = 0; bank < BankCount; bank++) begin
|
||||
for (int lane = 0; lane < 6; lane++) begin
|
||||
if (!s_bank_cs[bank] && s_scratch_write_pending_q[lane] && (scratch_bank(
|
||||
s_scratch_write_addr_q[lane]
|
||||
) == 4'(bank))) begin
|
||||
s_issue_write[bank] = 1'b1;
|
||||
s_issue_write_lane[bank] = 3'(lane);
|
||||
s_bank_cs[bank] = 1'b1;
|
||||
s_bank_wren[bank] = 1'b1;
|
||||
s_bank_addr[bank] = s_scratch_write_addr_q[lane][14:5];
|
||||
s_bank_wdata[bank] = s_scratch_write_data_q[lane];
|
||||
s_bank_wmask[bank] = s_scratch_write_strb_q[lane];
|
||||
end
|
||||
end
|
||||
for (int lane = 0; lane < 20; lane++) begin
|
||||
if (!s_bank_cs[bank] && s_scratch_read_pending_q[lane] && (scratch_bank(
|
||||
s_scratch_read_addr_q[lane]
|
||||
) == 4'(bank))) begin
|
||||
s_issue_read[bank] = 1'b1;
|
||||
s_bank_cs[bank] = 1'b1;
|
||||
s_bank_addr[bank] = s_scratch_read_addr_q[lane][14:5];
|
||||
end
|
||||
end
|
||||
for (int lane = 0; lane < 16; lane++) begin
|
||||
if (!s_bank_cs[bank] && s_model_pending_q[lane] && (model_bank(
|
||||
s_model_addr_q[lane]
|
||||
) == 4'(bank))) begin
|
||||
s_issue_read[bank] = 1'b1;
|
||||
s_bank_cs[bank] = 1'b1;
|
||||
s_bank_addr[bank] = s_model_addr_q[lane][14:5];
|
||||
end
|
||||
end
|
||||
end
|
||||
for (int lane = 0; lane < 6; lane++) begin
|
||||
if (scratch_write_valid_i[lane] && !scratch_write_addr_i[lane][15]) begin
|
||||
if (scratch_write_strb_i[lane][0]) begin
|
||||
mem[14'(ModelWordCount)+{1'b0, scratch_write_addr_i[lane][14:2]}][7:0] <=
|
||||
scratch_write_data_i[lane][7:0];
|
||||
for (int bank = 0; bank < BankCount; bank++) begin
|
||||
for (int lane = 0; lane < 20; lane++) begin
|
||||
if (s_issue_read[bank] && s_scratch_read_pending_q[lane] && (scratch_bank(
|
||||
s_scratch_read_addr_q[lane]
|
||||
) == 4'(bank)) && (s_scratch_read_addr_q[lane][14:5] == s_bank_addr[bank])) begin
|
||||
s_issue_scratch_mask[bank][lane] = 1'b1;
|
||||
end
|
||||
if (scratch_write_strb_i[lane][1]) begin
|
||||
mem[14'(ModelWordCount)+{1'b0, scratch_write_addr_i[lane][14:2]}][15:8] <=
|
||||
scratch_write_data_i[lane][15:8];
|
||||
end
|
||||
if (scratch_write_strb_i[lane][2]) begin
|
||||
mem[14'(ModelWordCount)+{1'b0, scratch_write_addr_i[lane][14:2]}][23:16] <=
|
||||
scratch_write_data_i[lane][23:16];
|
||||
end
|
||||
if (scratch_write_strb_i[lane][3]) begin
|
||||
mem[14'(ModelWordCount)+{1'b0, scratch_write_addr_i[lane][14:2]}][31:24] <=
|
||||
scratch_write_data_i[lane][31:24];
|
||||
end
|
||||
if ((scratch_write_addr_i[lane] >= `RETROSOC_APU_KWS__SCRATCH_FIR_BASE) &&
|
||||
(scratch_write_addr_i[lane] <
|
||||
(`RETROSOC_APU_KWS__SCRATCH_FIR_BASE + 16'(FirEntryCount * 2)))) begin
|
||||
s_fir_valid_q[6'(
|
||||
(scratch_write_addr_i[lane] - `RETROSOC_APU_KWS__SCRATCH_FIR_BASE) >> 1
|
||||
)] <= 1'b1;
|
||||
end
|
||||
for (int lane = 0; lane < 16; lane++) begin
|
||||
if (s_issue_read[bank] && s_model_pending_q[lane] && (model_bank(
|
||||
s_model_addr_q[lane]
|
||||
) == 4'(bank)) && (s_model_addr_q[lane][14:5] == s_bank_addr[bank])) begin
|
||||
s_issue_model_mask[bank][lane] = 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for (genvar bank = 0; bank < BankCount; bank++) begin : gen_kws_bank
|
||||
`ifdef HAVE_SRAM_MACRO
|
||||
tc_sram_1024x32 u_kws_sram (
|
||||
.clk_i (clk_i),
|
||||
.cs_i (s_bank_cs[bank]),
|
||||
.addr_i(s_bank_addr[bank]),
|
||||
.data_i(s_bank_wdata[bank]),
|
||||
.mask_i(s_bank_wmask[bank]),
|
||||
.wren_i(s_bank_wren[bank]),
|
||||
.data_o(s_bank_rdata[bank])
|
||||
);
|
||||
`elsif PDK_BEHAV
|
||||
tc_sram_1024x32 u_kws_sram (
|
||||
.clk_i (clk_i),
|
||||
.cs_i (s_bank_cs[bank]),
|
||||
.addr_i(s_bank_addr[bank]),
|
||||
.data_i(s_bank_wdata[bank]),
|
||||
.mask_i(s_bank_wmask[bank]),
|
||||
.wren_i(s_bank_wren[bank]),
|
||||
.data_o(s_bank_rdata[bank])
|
||||
);
|
||||
`else
|
||||
`ifndef SYNTHESIS
|
||||
logic [31:0] s_read_data_q;
|
||||
|
||||
assign s_bank_rdata[bank] = s_read_data_q;
|
||||
always_ff @(posedge clk_i) begin
|
||||
if (s_bank_cs[bank]) begin
|
||||
if (s_bank_wren[bank]) begin
|
||||
if (s_bank_wmask[bank][0]) begin
|
||||
mem[bank_word(4'(bank), s_bank_addr[bank])][7:0] <= s_bank_wdata[bank][7:0];
|
||||
end
|
||||
if (s_bank_wmask[bank][1]) begin
|
||||
mem[bank_word(4'(bank), s_bank_addr[bank])][15:8] <= s_bank_wdata[bank][15:8];
|
||||
end
|
||||
if (s_bank_wmask[bank][2]) begin
|
||||
mem[bank_word(4'(bank), s_bank_addr[bank])][23:16] <= s_bank_wdata[bank][23:16];
|
||||
end
|
||||
if (s_bank_wmask[bank][3]) begin
|
||||
mem[bank_word(4'(bank), s_bank_addr[bank])][31:24] <= s_bank_wdata[bank][31:24];
|
||||
end
|
||||
end else begin
|
||||
s_read_data_q <= mem[bank_word(4'(bank), s_bank_addr[bank])];
|
||||
end
|
||||
end
|
||||
end
|
||||
`else
|
||||
logic [31:0] s_storage_q [0:1023];
|
||||
logic [31:0] s_read_data_q;
|
||||
|
||||
assign s_bank_rdata[bank] = s_read_data_q;
|
||||
always_ff @(posedge clk_i) begin
|
||||
if (s_bank_cs[bank]) begin
|
||||
if (s_bank_wren[bank]) begin
|
||||
if (s_bank_wmask[bank][0]) begin
|
||||
s_storage_q[s_bank_addr[bank]][7:0] <= s_bank_wdata[bank][7:0];
|
||||
end
|
||||
if (s_bank_wmask[bank][1]) begin
|
||||
s_storage_q[s_bank_addr[bank]][15:8] <= s_bank_wdata[bank][15:8];
|
||||
end
|
||||
if (s_bank_wmask[bank][2]) begin
|
||||
s_storage_q[s_bank_addr[bank]][23:16] <= s_bank_wdata[bank][23:16];
|
||||
end
|
||||
if (s_bank_wmask[bank][3]) begin
|
||||
s_storage_q[s_bank_addr[bank]][31:24] <= s_bank_wdata[bank][31:24];
|
||||
end
|
||||
end else begin
|
||||
s_read_data_q <= s_storage_q[s_bank_addr[bank]];
|
||||
end
|
||||
end
|
||||
end
|
||||
`endif
|
||||
`endif
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_n_i) begin
|
||||
if (!rst_n_i) begin
|
||||
s_busy_q <= 1'b0;
|
||||
s_model_pending_q <= 16'd0;
|
||||
s_model_addr_q <= '0;
|
||||
s_scratch_read_pending_q <= 20'd0;
|
||||
s_scratch_read_addr_q <= '0;
|
||||
s_scratch_write_pending_q <= 6'd0;
|
||||
s_scratch_write_addr_q <= '0;
|
||||
s_scratch_write_data_q <= '0;
|
||||
s_scratch_write_strb_q <= '0;
|
||||
s_read_pipe_valid_q <= BankCount'(0);
|
||||
s_read_pipe_model_q <= '0;
|
||||
s_read_pipe_scratch_q <= '0;
|
||||
s_fir_valid_q <= FirEntryCount'(0);
|
||||
model_data_o <= '0;
|
||||
scratch_read_data_o <= '0;
|
||||
s_loader_read_pending_q <= 1'b0;
|
||||
s_loader_read_bank_q <= 4'd0;
|
||||
s_loader_read_err_q <= 1'b0;
|
||||
end else begin
|
||||
if (scratch_clear_i) s_fir_valid_q <= FirEntryCount'(0);
|
||||
|
||||
if (access_done_o) begin
|
||||
s_busy_q <= 1'b0;
|
||||
end else if (access_req_i && access_ready_o) begin
|
||||
s_busy_q <= 1'b1;
|
||||
s_model_pending_q <= access_write_i ? 16'd0 : model_read_valid_i;
|
||||
s_model_addr_q <= model_addr_i;
|
||||
s_scratch_read_pending_q <= access_write_i ? 20'd0 : scratch_read_valid_i;
|
||||
s_scratch_read_addr_q <= scratch_read_addr_i;
|
||||
s_scratch_write_pending_q <= access_write_i ? scratch_write_valid_i : 6'd0;
|
||||
s_scratch_write_addr_q <= scratch_write_addr_i;
|
||||
s_scratch_write_data_q <= scratch_write_data_i;
|
||||
s_scratch_write_strb_q <= scratch_write_strb_i;
|
||||
end
|
||||
|
||||
for (int bank = 0; bank < BankCount; bank++) begin
|
||||
if (s_issue_write[bank]) begin
|
||||
s_scratch_write_pending_q[s_issue_write_lane[bank]] <= 1'b0;
|
||||
if ((s_scratch_write_addr_q[s_issue_write_lane[bank]] >=
|
||||
`RETROSOC_APU_KWS__SCRATCH_FIR_BASE) &&
|
||||
(s_scratch_write_addr_q[s_issue_write_lane[bank]] <
|
||||
(`RETROSOC_APU_KWS__SCRATCH_FIR_BASE + 16'(FirEntryCount * 2)))) begin
|
||||
s_fir_valid_q[6'((s_scratch_write_addr_q[s_issue_write_lane[bank]] -
|
||||
`RETROSOC_APU_KWS__SCRATCH_FIR_BASE) >> 1)] <= 1'b1;
|
||||
end
|
||||
end
|
||||
if (s_issue_read[bank]) begin
|
||||
for (int lane = 0; lane < 16; lane++) begin
|
||||
if (s_issue_model_mask[bank][lane]) s_model_pending_q[lane] <= 1'b0;
|
||||
end
|
||||
for (int lane = 0; lane < 20; lane++) begin
|
||||
if (s_issue_scratch_mask[bank][lane]) begin
|
||||
s_scratch_read_pending_q[lane] <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
s_read_pipe_valid_q[bank] <= s_issue_read[bank];
|
||||
s_read_pipe_model_q[bank] <= s_issue_model_mask[bank];
|
||||
s_read_pipe_scratch_q[bank] <= s_issue_scratch_mask[bank];
|
||||
if (s_read_pipe_valid_q[bank]) begin
|
||||
for (int lane = 0; lane < 16; lane++) begin
|
||||
if (s_read_pipe_model_q[bank][lane]) begin
|
||||
model_data_o[lane] <= s_bank_rdata[bank][8*s_model_addr_q[lane][1:0]+:8];
|
||||
end
|
||||
end
|
||||
for (int lane = 0; lane < 20; lane++) begin
|
||||
if (s_read_pipe_scratch_q[bank][lane]) begin
|
||||
if ((s_scratch_read_addr_q[lane] >= `RETROSOC_APU_KWS__SCRATCH_FIR_BASE) &&
|
||||
(s_scratch_read_addr_q[lane] <
|
||||
(`RETROSOC_APU_KWS__SCRATCH_FIR_BASE + 16'(FirEntryCount * 2))) &&
|
||||
!s_fir_valid_q[6'((s_scratch_read_addr_q[lane] -
|
||||
`RETROSOC_APU_KWS__SCRATCH_FIR_BASE) >> 1)]) begin
|
||||
scratch_read_data_o[lane] <= 32'd0;
|
||||
end else begin
|
||||
scratch_read_data_o[lane] <= s_bank_rdata[bank];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
s_loader_read_pending_q <= 1'b0;
|
||||
if (req_i && ready_o && s_loader_range_ok && !write_i) begin
|
||||
s_loader_read_pending_q <= 1'b1;
|
||||
s_loader_read_bank_q <= s_loader_bank;
|
||||
s_loader_read_err_q <= 1'b0;
|
||||
end else if (req_i && ready_o && !s_loader_range_ok) begin
|
||||
s_loader_read_pending_q <= 1'b1;
|
||||
s_loader_read_err_q <= 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
@@ -18,62 +18,86 @@ module jpeg_table_register_bank (
|
||||
output logic [1279:0] ac_length_o
|
||||
// verilog_format: on
|
||||
);
|
||||
for (genvar index = 0; index < 64; index++) begin : gen_quant_entry
|
||||
dffl #(
|
||||
.DATA_WIDTH(8)
|
||||
) u_quant_dffl (
|
||||
.clk_i(clk_i),
|
||||
.en_i (write_i && (entry_kind_i < 4'd4) && (entry_index_i == 8'(index))),
|
||||
.dat_i(entry_data_i[7:0]),
|
||||
.dat_o(quant_o[index*8+:8])
|
||||
);
|
||||
dffl #(
|
||||
.DATA_WIDTH(25)
|
||||
) u_reciprocal_dffl (
|
||||
.clk_i(clk_i),
|
||||
.en_i (write_i && (entry_kind_i < 4'd4) && (entry_index_i == 8'(index))),
|
||||
.dat_i(entry_reciprocal_i),
|
||||
.dat_o(reciprocal_o[index*25+:25])
|
||||
);
|
||||
logic [ 511:0] s_quant_d;
|
||||
logic [1599:0] s_reciprocal_d;
|
||||
logic [ 191:0] s_dc_code_d;
|
||||
logic [ 59:0] s_dc_len_d;
|
||||
logic [4095:0] s_ac_code_d;
|
||||
logic [1279:0] s_ac_len_d;
|
||||
logic s_quant_write, s_dc_write, s_ac_write;
|
||||
|
||||
assign s_quant_write = write_i && (entry_kind_i < 4'd4) && (entry_index_i < 8'd64);
|
||||
assign s_dc_write = write_i && (entry_kind_i >= 4'd4) && (entry_kind_i < 4'd8) &&
|
||||
(entry_index_i < 8'd12);
|
||||
assign s_ac_write = write_i && (entry_kind_i >= 4'd8);
|
||||
|
||||
always_comb begin
|
||||
s_quant_d = quant_o;
|
||||
s_reciprocal_d = reciprocal_o;
|
||||
s_dc_code_d = dc_code_o;
|
||||
s_dc_len_d = dc_length_o;
|
||||
s_ac_code_d = ac_code_o;
|
||||
s_ac_len_d = ac_length_o;
|
||||
if (s_quant_write) begin
|
||||
s_quant_d[entry_index_i*8+:8] = entry_data_i[7:0];
|
||||
s_reciprocal_d[entry_index_i*25+:25] = entry_reciprocal_i;
|
||||
end
|
||||
if (s_dc_write) begin
|
||||
s_dc_code_d[entry_index_i*16+:16] = entry_data_i[15:0];
|
||||
s_dc_len_d[entry_index_i*5+:5] = entry_data_i[20:16];
|
||||
end
|
||||
if (s_ac_write) begin
|
||||
s_ac_code_d[entry_index_i*16+:16] = entry_data_i[15:0];
|
||||
s_ac_len_d[entry_index_i*5+:5] = entry_data_i[20:16];
|
||||
end
|
||||
end
|
||||
|
||||
for (genvar index = 0; index < 12; index++) begin : gen_dc_entry
|
||||
dffl #(
|
||||
.DATA_WIDTH(16)
|
||||
) u_code_dffl (
|
||||
.clk_i(clk_i),
|
||||
.en_i (write_i && (entry_kind_i >= 4'd4) && (entry_kind_i < 4'd8) &&
|
||||
(entry_index_i == 8'(index))),
|
||||
.dat_i(entry_data_i[15:0]),
|
||||
.dat_o(dc_code_o[index*16+:16])
|
||||
);
|
||||
dffl #(
|
||||
.DATA_WIDTH(5)
|
||||
) u_length_dffl (
|
||||
.clk_i(clk_i),
|
||||
.en_i (write_i && (entry_kind_i >= 4'd4) && (entry_kind_i < 4'd8) &&
|
||||
(entry_index_i == 8'(index))),
|
||||
.dat_i(entry_data_i[20:16]),
|
||||
.dat_o(dc_length_o[index*5+:5])
|
||||
);
|
||||
end
|
||||
|
||||
for (genvar index = 0; index < 256; index++) begin : gen_ac_entry
|
||||
dffl #(
|
||||
.DATA_WIDTH(16)
|
||||
) u_code_dffl (
|
||||
.clk_i(clk_i),
|
||||
.en_i (write_i && (entry_kind_i >= 4'd8) && (entry_index_i == 8'(index))),
|
||||
.dat_i(entry_data_i[15:0]),
|
||||
.dat_o(ac_code_o[index*16+:16])
|
||||
);
|
||||
dffl #(
|
||||
.DATA_WIDTH(5)
|
||||
) u_length_dffl (
|
||||
.clk_i(clk_i),
|
||||
.en_i (write_i && (entry_kind_i >= 4'd8) && (entry_index_i == 8'(index))),
|
||||
.dat_i(entry_data_i[20:16]),
|
||||
.dat_o(ac_length_o[index*5+:5])
|
||||
);
|
||||
end
|
||||
dffl #(
|
||||
.DATA_WIDTH(512)
|
||||
) u_quant_dffl (
|
||||
.clk_i(clk_i),
|
||||
.en_i (s_quant_write),
|
||||
.dat_i(s_quant_d),
|
||||
.dat_o(quant_o)
|
||||
);
|
||||
dffl #(
|
||||
.DATA_WIDTH(1600)
|
||||
) u_reciprocal_dffl (
|
||||
.clk_i(clk_i),
|
||||
.en_i (s_quant_write),
|
||||
.dat_i(s_reciprocal_d),
|
||||
.dat_o(reciprocal_o)
|
||||
);
|
||||
dffl #(
|
||||
.DATA_WIDTH(192)
|
||||
) u_dc_code_dffl (
|
||||
.clk_i(clk_i),
|
||||
.en_i (s_dc_write),
|
||||
.dat_i(s_dc_code_d),
|
||||
.dat_o(dc_code_o)
|
||||
);
|
||||
dffl #(
|
||||
.DATA_WIDTH(60)
|
||||
) u_dc_length_dffl (
|
||||
.clk_i(clk_i),
|
||||
.en_i (s_dc_write),
|
||||
.dat_i(s_dc_len_d),
|
||||
.dat_o(dc_length_o)
|
||||
);
|
||||
dffl #(
|
||||
.DATA_WIDTH(4096)
|
||||
) u_ac_code_dffl (
|
||||
.clk_i(clk_i),
|
||||
.en_i (s_ac_write),
|
||||
.dat_i(s_ac_code_d),
|
||||
.dat_o(ac_code_o)
|
||||
);
|
||||
dffl #(
|
||||
.DATA_WIDTH(1280)
|
||||
) u_ac_length_dffl (
|
||||
.clk_i(clk_i),
|
||||
.en_i (s_ac_write),
|
||||
.dat_i(s_ac_len_d),
|
||||
.dat_o(ac_length_o)
|
||||
);
|
||||
endmodule
|
||||
+40
-13
@@ -6,6 +6,8 @@ import argparse
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import resource
|
||||
import signal
|
||||
import subprocess
|
||||
import sys
|
||||
import termios
|
||||
@@ -75,6 +77,17 @@ def write_console_bytes(chunk: bytes) -> None:
|
||||
sys.stdout.buffer.flush()
|
||||
|
||||
|
||||
def terminate_process_group(process: subprocess.Popen[str] | subprocess.Popen[bytes]) -> None:
|
||||
if process.poll() is not None:
|
||||
return
|
||||
os.killpg(process.pid, signal.SIGTERM)
|
||||
try:
|
||||
process.wait(timeout=5)
|
||||
except subprocess.TimeoutExpired:
|
||||
os.killpg(process.pid, signal.SIGKILL)
|
||||
process.wait()
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description="Run a flow command with structured results")
|
||||
parser.add_argument("--tool", required=True)
|
||||
@@ -111,6 +124,28 @@ def main() -> int:
|
||||
args.result.parent.mkdir(parents=True, exist_ok=True)
|
||||
started = datetime.now(timezone.utc)
|
||||
start_clock = time.monotonic()
|
||||
atomic_write(
|
||||
args.result,
|
||||
json.dumps(
|
||||
{
|
||||
"schema_version": 1,
|
||||
"tool": args.tool,
|
||||
"command": command,
|
||||
"started_at": started.isoformat(),
|
||||
"status": "running",
|
||||
"log": str(args.log.resolve()),
|
||||
},
|
||||
indent=2,
|
||||
sort_keys=True,
|
||||
)
|
||||
+ "\n",
|
||||
)
|
||||
|
||||
def interrupt_flow(_signum: int, _frame: object) -> None:
|
||||
raise KeyboardInterrupt
|
||||
|
||||
signal.signal(signal.SIGINT, interrupt_flow)
|
||||
signal.signal(signal.SIGTERM, interrupt_flow)
|
||||
returncode = 127
|
||||
error_message = None
|
||||
process: subprocess.Popen[str] | subprocess.Popen[bytes] | None = None
|
||||
@@ -132,6 +167,7 @@ def main() -> int:
|
||||
errors=None if args.stream_bytes else "replace",
|
||||
bufsize=0 if args.stream_bytes else 1,
|
||||
pass_fds=jobserver_fds(),
|
||||
start_new_session=True,
|
||||
)
|
||||
assert process.stdout is not None
|
||||
if args.stream_bytes:
|
||||
@@ -150,25 +186,15 @@ def main() -> int:
|
||||
write_console_output(line)
|
||||
if args.terminate_on_success_marker and args.success_marker in line:
|
||||
marker_seen = True
|
||||
process.terminate()
|
||||
try:
|
||||
process.wait(timeout=5)
|
||||
except subprocess.TimeoutExpired:
|
||||
process.kill()
|
||||
process.wait()
|
||||
terminate_process_group(process)
|
||||
returncode = 1 if rejected_matches else 0
|
||||
break
|
||||
if not marker_seen:
|
||||
returncode = process.wait()
|
||||
except KeyboardInterrupt:
|
||||
error_message = "interrupted"
|
||||
if process is not None and process.poll() is None:
|
||||
process.terminate()
|
||||
try:
|
||||
process.wait(timeout=5)
|
||||
except subprocess.TimeoutExpired:
|
||||
process.kill()
|
||||
process.wait()
|
||||
if process is not None:
|
||||
terminate_process_group(process)
|
||||
returncode = 130
|
||||
except (OSError, subprocess.SubprocessError) as error:
|
||||
error_message = str(error)
|
||||
@@ -182,6 +208,7 @@ def main() -> int:
|
||||
"started_at": started.isoformat(),
|
||||
"finished_at": finished.isoformat(),
|
||||
"duration_seconds": round(time.monotonic() - start_clock, 3),
|
||||
"peak_rss_kib": resource.getrusage(resource.RUSAGE_CHILDREN).ru_maxrss,
|
||||
"exit_code": returncode,
|
||||
"status": "passed" if returncode == 0 else "failed",
|
||||
"log": str(args.log.resolve()),
|
||||
|
||||
@@ -40,7 +40,10 @@ module apu_kws_engine_tb;
|
||||
logic [31:0] fault_addr_o, fault_detail_o;
|
||||
logic [15:0][14:0] model_addr_o;
|
||||
logic [15:0][7:0] model_data_i, model_store_data;
|
||||
logic storage_req, storage_ready, storage_done, storage_progress, storage_write;
|
||||
logic [15:0] model_read_valid;
|
||||
logic scratch_clear;
|
||||
logic [19:0] scratch_read_valid;
|
||||
logic [19:0][15:0] scratch_read_addr;
|
||||
logic [19:0][31:0] scratch_read_data;
|
||||
logic [ 5:0] scratch_write_valid;
|
||||
@@ -138,9 +141,16 @@ module apu_kws_engine_tb;
|
||||
.data_o (),
|
||||
.valid_o (),
|
||||
.access_err_o (),
|
||||
.access_req_i (storage_req),
|
||||
.access_ready_o (storage_ready),
|
||||
.access_done_o (storage_done),
|
||||
.access_progress_o (storage_progress),
|
||||
.access_write_i (storage_write),
|
||||
.model_read_valid_i (model_read_valid),
|
||||
.model_addr_i (model_addr_o),
|
||||
.model_data_o (model_store_data),
|
||||
.scratch_clear_i (scratch_clear),
|
||||
.scratch_read_valid_i (scratch_read_valid),
|
||||
.scratch_read_addr_i (scratch_read_addr),
|
||||
.scratch_read_data_o (scratch_read_data),
|
||||
.scratch_write_valid_i(scratch_write_valid),
|
||||
@@ -195,9 +205,16 @@ module apu_kws_engine_tb;
|
||||
.memory_error_detail_o (memory_error_detail_o),
|
||||
.memory_input_used_o (memory_input_used_o),
|
||||
.input_config_i (32'h01043e80),
|
||||
.storage_req_o (storage_req),
|
||||
.storage_ready_i (storage_ready),
|
||||
.storage_done_i (storage_done),
|
||||
.storage_progress_i (storage_progress),
|
||||
.storage_write_o (storage_write),
|
||||
.model_read_valid_o (model_read_valid),
|
||||
.model_addr_o (model_addr_o),
|
||||
.model_data_i (model_data_i),
|
||||
.scratch_clear_o (scratch_clear),
|
||||
.scratch_read_valid_o (scratch_read_valid),
|
||||
.scratch_read_addr_o (scratch_read_addr),
|
||||
.scratch_read_data_i (scratch_read_data),
|
||||
.scratch_write_valid_o (scratch_write_valid),
|
||||
@@ -474,15 +491,22 @@ module apu_kws_engine_tb;
|
||||
enable_i = 1'b1;
|
||||
accepted_samples = 0;
|
||||
elapsed_cycles = 0;
|
||||
while ((accepted_samples < 16000) && (elapsed_cycles < 2000000)) begin
|
||||
while ((accepted_samples < 16000) && (elapsed_cycles < 4000000)) begin
|
||||
@(posedge clk_i);
|
||||
if (stream_i.tvalid && stream_i.tready) accepted_samples++;
|
||||
elapsed_cycles++;
|
||||
end
|
||||
if (accepted_samples != 16000) $fatal(1, "KWS did not consume exactly one diagnostic window");
|
||||
if (accepted_samples != 16000) begin
|
||||
$fatal(
|
||||
1,
|
||||
"KWS input timeout accepted=%0d front=%0d infer=%0d wait=%0b req=%0b ready=%0b done=%0b",
|
||||
accepted_samples, dut.s_front_state_q, dut.s_infer_state_q, dut.s_storage_wait_q,
|
||||
storage_req, storage_ready, storage_done);
|
||||
end
|
||||
@(negedge clk_i);
|
||||
enable_i = 1'b0;
|
||||
while ((inference_count_o == 0) && (elapsed_cycles < 3000000)) begin
|
||||
enable_i = 1'b0;
|
||||
elapsed_cycles = 0;
|
||||
while ((inference_count_o == 0) && (elapsed_cycles < 4000000)) begin
|
||||
@(negedge clk_i);
|
||||
elapsed_cycles++;
|
||||
end
|
||||
|
||||
@@ -9,10 +9,15 @@ module apu_kws_sram_client_tb;
|
||||
logic [31:0] data_i = 32'd0;
|
||||
logic [ 3:0] strb_i = 4'd0;
|
||||
logic ready_o, valid_o, access_err_o;
|
||||
logic [31:0] data_o;
|
||||
logic [31:0] data_o;
|
||||
logic access_req_i = 1'b0;
|
||||
logic access_ready_o, access_done_o, access_progress_o;
|
||||
logic access_write_i = 1'b0;
|
||||
logic [15:0] model_read_valid_i = 16'd0;
|
||||
logic [15:0][14:0] model_addr_i = '0;
|
||||
logic [15:0][ 7:0] model_data_o;
|
||||
logic scratch_clear_i = 1'b0;
|
||||
logic [19:0] scratch_read_valid_i = 20'd0;
|
||||
logic [19:0][15:0] scratch_read_addr_i = '0;
|
||||
logic [19:0][31:0] scratch_read_data_o;
|
||||
logic [ 5:0] scratch_write_valid_i = 6'd0;
|
||||
@@ -39,9 +44,16 @@ module apu_kws_sram_client_tb;
|
||||
.data_o (data_o),
|
||||
.valid_o (valid_o),
|
||||
.access_err_o (access_err_o),
|
||||
.access_req_i (access_req_i),
|
||||
.access_ready_o (access_ready_o),
|
||||
.access_done_o (access_done_o),
|
||||
.access_progress_o (access_progress_o),
|
||||
.access_write_i (access_write_i),
|
||||
.model_read_valid_i (model_read_valid_i),
|
||||
.model_addr_i (model_addr_i),
|
||||
.model_data_o (model_data_o),
|
||||
.scratch_clear_i (scratch_clear_i),
|
||||
.scratch_read_valid_i (scratch_read_valid_i),
|
||||
.scratch_read_addr_i (scratch_read_addr_i),
|
||||
.scratch_read_data_o (scratch_read_data_o),
|
||||
.scratch_write_valid_i(scratch_write_valid_i),
|
||||
@@ -88,6 +100,20 @@ module apu_kws_sram_client_tb;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic run_access(input logic write_access_i);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
access_write_i = write_access_i;
|
||||
access_req_i = 1'b1;
|
||||
if (!access_ready_o) $fatal(1, "KWS SRAM transaction was not accepted");
|
||||
@(negedge clk_i);
|
||||
access_req_i = 1'b0;
|
||||
wait (access_done_o);
|
||||
@(negedge clk_i);
|
||||
access_write_i = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic write_scratch(input logic [15:0] address_i, input logic [31:0] value_i,
|
||||
input logic [3:0] strobe_i);
|
||||
begin
|
||||
@@ -96,11 +122,13 @@ module apu_kws_sram_client_tb;
|
||||
scratch_write_addr_i[0] = address_i;
|
||||
scratch_write_data_i[0] = value_i;
|
||||
scratch_write_strb_i[0] = strobe_i;
|
||||
@(negedge clk_i);
|
||||
run_access(1'b1);
|
||||
scratch_write_valid_i[0] = 1'b0;
|
||||
scratch_write_strb_i[0] = 4'd0;
|
||||
scratch_read_addr_i[0] = address_i;
|
||||
#1;
|
||||
scratch_read_valid_i[0] = 1'b1;
|
||||
run_access(1'b0);
|
||||
scratch_read_valid_i[0] = 1'b0;
|
||||
if (scratch_read_data_o[0] != value_i) begin
|
||||
$fatal(1, "scratch layout write mismatch at %04x", address_i);
|
||||
end
|
||||
@@ -126,25 +154,29 @@ module apu_kws_sram_client_tb;
|
||||
rst_n_i = 1'b1;
|
||||
|
||||
write_model(`APB4_APU__LOCAL_KWS_BASE, 32'h4433_2211);
|
||||
model_addr_i[0] = 15'd0;
|
||||
model_addr_i[1] = 15'd1;
|
||||
model_addr_i[2] = 15'd2;
|
||||
model_addr_i[3] = 15'd3;
|
||||
#1;
|
||||
model_addr_i[0] = 15'd0;
|
||||
model_addr_i[1] = 15'd1;
|
||||
model_addr_i[2] = 15'd2;
|
||||
model_addr_i[3] = 15'd3;
|
||||
model_read_valid_i[3:0] = 4'hf;
|
||||
run_access(1'b0);
|
||||
model_read_valid_i = 16'd0;
|
||||
if ({model_data_o[3], model_data_o[2], model_data_o[1], model_data_o[0]} != 32'h4433_2211) begin
|
||||
$fatal(1, "banks10..17 model readback mismatch");
|
||||
end
|
||||
write_model(17'h1_0000, 32'h8877_6655);
|
||||
write_model(`APB4_APU__LOCAL_KWS_BASE + `RETROSOC_APU_KWS__MODEL_BYTES - 4, 32'hccbb_aa99);
|
||||
model_addr_i[0] = 15'h6000;
|
||||
model_addr_i[1] = 15'h6001;
|
||||
model_addr_i[2] = 15'h6002;
|
||||
model_addr_i[3] = 15'h6003;
|
||||
model_addr_i[4] = 15'h7ffc;
|
||||
model_addr_i[5] = 15'h7ffd;
|
||||
model_addr_i[6] = 15'h7ffe;
|
||||
model_addr_i[7] = 15'h7fff;
|
||||
#1;
|
||||
model_addr_i[0] = 15'h6000;
|
||||
model_addr_i[1] = 15'h6001;
|
||||
model_addr_i[2] = 15'h6002;
|
||||
model_addr_i[3] = 15'h6003;
|
||||
model_addr_i[4] = 15'h7ffc;
|
||||
model_addr_i[5] = 15'h7ffd;
|
||||
model_addr_i[6] = 15'h7ffe;
|
||||
model_addr_i[7] = 15'h7fff;
|
||||
model_read_valid_i[7:0] = 8'hff;
|
||||
run_access(1'b0);
|
||||
model_read_valid_i = 16'd0;
|
||||
if ({model_data_o[3], model_data_o[2], model_data_o[1], model_data_o[0]} != 32'h8877_6655) begin
|
||||
$fatal(1, "APUM model address crossing 0x10000 did not map to bank16");
|
||||
end
|
||||
@@ -161,8 +193,10 @@ module apu_kws_sram_client_tb;
|
||||
write_scratch(`RETROSOC_APU_KWS__SCRATCH_PEAK_BASE, 32'h6162_6364, 4'hf);
|
||||
write_scratch(16'h7ffc, 32'h7172_7374, 4'hf);
|
||||
|
||||
model_addr_i[0] = 15'd0;
|
||||
#1;
|
||||
model_addr_i[0] = 15'd0;
|
||||
model_read_valid_i[0] = 1'b1;
|
||||
run_access(1'b0);
|
||||
model_read_valid_i = 16'd0;
|
||||
if (model_data_o[0] != 8'h11) $fatal(1, "scratch write corrupted APUM storage");
|
||||
|
||||
@(negedge clk_i);
|
||||
@@ -185,12 +219,16 @@ module apu_kws_sram_client_tb;
|
||||
@(negedge clk_i);
|
||||
scratch_clear_i = 1'b1;
|
||||
@(negedge clk_i);
|
||||
scratch_clear_i = 1'b0;
|
||||
scratch_read_addr_i[0] = `RETROSOC_APU_KWS__SCRATCH_FIR_BASE;
|
||||
#1;
|
||||
scratch_clear_i = 1'b0;
|
||||
scratch_read_addr_i[0] = `RETROSOC_APU_KWS__SCRATCH_FIR_BASE;
|
||||
scratch_read_valid_i[0] = 1'b1;
|
||||
run_access(1'b0);
|
||||
scratch_read_valid_i[0] = 1'b0;
|
||||
if (scratch_read_data_o[0] != 32'd0) $fatal(1, "FIR lifecycle clear exposed stale data");
|
||||
scratch_read_addr_i[0] = `RETROSOC_APU_KWS__SCRATCH_A_BASE;
|
||||
#1;
|
||||
scratch_read_addr_i[0] = `RETROSOC_APU_KWS__SCRATCH_A_BASE;
|
||||
scratch_read_valid_i[0] = 1'b1;
|
||||
run_access(1'b0);
|
||||
scratch_read_valid_i[0] = 1'b0;
|
||||
if (scratch_read_data_o[0] != 32'h0102_0304) begin
|
||||
$fatal(1, "history clear corrupted non-history scratch");
|
||||
end
|
||||
@@ -203,5 +241,5 @@ module apu_kws_sram_client_tb;
|
||||
end
|
||||
|
||||
logic s_unused;
|
||||
assign s_unused = valid_o ^ ^data_o ^ codec_valid_o ^ ^codec_data_o;
|
||||
assign s_unused = valid_o ^ ^data_o ^ codec_valid_o ^ ^codec_data_o ^ access_progress_o;
|
||||
endmodule
|
||||
@@ -46,7 +46,10 @@ module apu_p7_accuracy_tb;
|
||||
logic [31:0] fault_addr_o, fault_detail_o;
|
||||
logic [15:0][14:0] model_addr_o;
|
||||
logic [15:0][ 7:0] model_store_data;
|
||||
logic storage_req, storage_ready, storage_done, storage_progress, storage_write;
|
||||
logic [15:0] model_read_valid;
|
||||
logic scratch_clear;
|
||||
logic [19:0] scratch_read_valid;
|
||||
logic [19:0][15:0] scratch_read_addr;
|
||||
logic [19:0][31:0] scratch_read_data;
|
||||
logic [ 5:0] scratch_write_valid;
|
||||
@@ -86,9 +89,16 @@ module apu_p7_accuracy_tb;
|
||||
.data_o (),
|
||||
.valid_o (),
|
||||
.access_err_o (),
|
||||
.access_req_i (storage_req),
|
||||
.access_ready_o (storage_ready),
|
||||
.access_done_o (storage_done),
|
||||
.access_progress_o (storage_progress),
|
||||
.access_write_i (storage_write),
|
||||
.model_read_valid_i (model_read_valid),
|
||||
.model_addr_i (model_addr_o),
|
||||
.model_data_o (model_store_data),
|
||||
.scratch_clear_i (scratch_clear),
|
||||
.scratch_read_valid_i (scratch_read_valid),
|
||||
.scratch_read_addr_i (scratch_read_addr),
|
||||
.scratch_read_data_o (scratch_read_data),
|
||||
.scratch_write_valid_i(scratch_write_valid),
|
||||
@@ -143,9 +153,16 @@ module apu_p7_accuracy_tb;
|
||||
.memory_input_used_o (memory_input_used_o),
|
||||
.kws_config_i (KwsConfig),
|
||||
.input_config_i (InputConfig),
|
||||
.storage_req_o (storage_req),
|
||||
.storage_ready_i (storage_ready),
|
||||
.storage_done_i (storage_done),
|
||||
.storage_progress_i (storage_progress),
|
||||
.storage_write_o (storage_write),
|
||||
.model_read_valid_o (model_read_valid),
|
||||
.model_addr_o (model_addr_o),
|
||||
.model_data_i (model_store_data),
|
||||
.scratch_clear_o (scratch_clear),
|
||||
.scratch_read_valid_o (scratch_read_valid),
|
||||
.scratch_read_addr_o (scratch_read_addr),
|
||||
.scratch_read_data_i (scratch_read_data),
|
||||
.scratch_write_valid_o (scratch_write_valid),
|
||||
|
||||
@@ -49,7 +49,10 @@ module apu_p7_frontend_dump_tb;
|
||||
logic [31:0] fault_addr_o, fault_detail_o;
|
||||
logic [15:0][14:0] model_addr_o;
|
||||
logic [15:0][ 7:0] model_store_data;
|
||||
logic storage_req, storage_ready, storage_done, storage_progress, storage_write;
|
||||
logic [15:0] model_read_valid;
|
||||
logic scratch_clear;
|
||||
logic [19:0] scratch_read_valid;
|
||||
logic [19:0][15:0] scratch_read_addr;
|
||||
logic [19:0][31:0] scratch_read_data;
|
||||
logic [ 5:0] scratch_write_valid;
|
||||
@@ -89,9 +92,16 @@ module apu_p7_frontend_dump_tb;
|
||||
.data_o (),
|
||||
.valid_o (),
|
||||
.access_err_o (),
|
||||
.access_req_i (storage_req),
|
||||
.access_ready_o (storage_ready),
|
||||
.access_done_o (storage_done),
|
||||
.access_progress_o (storage_progress),
|
||||
.access_write_i (storage_write),
|
||||
.model_read_valid_i (model_read_valid),
|
||||
.model_addr_i (model_addr_o),
|
||||
.model_data_o (model_store_data),
|
||||
.scratch_clear_i (scratch_clear),
|
||||
.scratch_read_valid_i (scratch_read_valid),
|
||||
.scratch_read_addr_i (scratch_read_addr),
|
||||
.scratch_read_data_o (scratch_read_data),
|
||||
.scratch_write_valid_i(scratch_write_valid),
|
||||
@@ -146,9 +156,16 @@ module apu_p7_frontend_dump_tb;
|
||||
.memory_input_used_o (memory_input_used_o),
|
||||
.kws_config_i (KwsConfig),
|
||||
.input_config_i (InputConfig),
|
||||
.storage_req_o (storage_req),
|
||||
.storage_ready_i (storage_ready),
|
||||
.storage_done_i (storage_done),
|
||||
.storage_progress_i (storage_progress),
|
||||
.storage_write_o (storage_write),
|
||||
.model_read_valid_o (model_read_valid),
|
||||
.model_addr_o (model_addr_o),
|
||||
.model_data_i (model_store_data),
|
||||
.scratch_clear_o (scratch_clear),
|
||||
.scratch_read_valid_o (scratch_read_valid),
|
||||
.scratch_read_addr_o (scratch_read_addr),
|
||||
.scratch_read_data_i (scratch_read_data),
|
||||
.scratch_write_valid_o (scratch_write_valid),
|
||||
|
||||
@@ -1898,6 +1898,8 @@ def test_run_flow_writes_structured_result(tmp_path: Path) -> None:
|
||||
assert data["status"] == "passed"
|
||||
assert data["exit_code"] == 0
|
||||
assert data["duration_seconds"] >= 0
|
||||
assert isinstance(data["peak_rss_kib"], int)
|
||||
assert data["peak_rss_kib"] > 0
|
||||
assert log.read_text(encoding="utf-8") == "flow output\n"
|
||||
|
||||
|
||||
|
||||
@@ -55,7 +55,13 @@ def test_yosys_recipe_scripts_and_public_slot_are_stable() -> None:
|
||||
assert "SYNTH_RECIPE" not in makefile.split("CONFIG_KEY_VARS", 1)[1].split("VARIANT_ID", 1)[0]
|
||||
assert "--env SYNTH_RECIPE=$(SYNTH_RECIPE)" in yosys_mk
|
||||
assert "--env YOSYS_TARGET_PERIOD_PS=$(YOSYS_TARGET_PERIOD_PS)" in yosys_mk
|
||||
assert "YOSYS_TIMEOUT ?= 10800" in yosys_mk
|
||||
assert "timeout --foreground --kill-after=5s $(YOSYS_TIMEOUT)s" in yosys_mk
|
||||
assert "yosys -t --perffile $(YOSYS_BUILD)/yosys-perf.json" in yosys_mk
|
||||
assert "abc_${synth_recipe}.script" in synth_tcl
|
||||
assert '${proj_name}_pre_memory.rpt' in synth_tcl
|
||||
assert '${proj_name}_pre_memory.json' in synth_tcl
|
||||
assert synth_tcl.index('${proj_name}_pre_memory.json') < synth_tcl.index("yosys memory")
|
||||
assert "yosys abc {*}$tech_cells_args -D $period_ps -script $abc_script -constr $abc_constr" in synth_tcl
|
||||
assert "S110" not in synth_tcl
|
||||
assert "$(SYN_BUILD_ROOT)/out/retrosoc_asic_yosys.v" in opensta
|
||||
|
||||
Reference in new issue
Block a user