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
|
improved metric is not sufficient to replace `balanced`. Metrics policy remains
|
||||||
in `observe` mode while recipe baselines are collected and reviewed.
|
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
|
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
|
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>`.
|
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 PROJ_NAME=$(APU_BLOCK_TOP) --env WORK=$(APU_BLOCK_TMP) \
|
||||||
--env BUILD=$(APU_BLOCK_OUT) --env REPORTS=$(APU_BLOCK_RPT) \
|
--env BUILD=$(APU_BLOCK_OUT) --env REPORTS=$(APU_BLOCK_RPT) \
|
||||||
--env NETLIST=$(APU_BLOCK_NETLIST) -- \
|
--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)
|
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)
|
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 \
|
.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 PROJ_NAME=$(GA2D_BLOCK_TOP) --env WORK=$(GA2D_BLOCK_TMP) \
|
||||||
--env BUILD=$(GA2D_BLOCK_OUT) --env REPORTS=$(GA2D_BLOCK_RPT) \
|
--env BUILD=$(GA2D_BLOCK_OUT) --env REPORTS=$(GA2D_BLOCK_RPT) \
|
||||||
--env NETLIST=$(GA2D_BLOCK_NETLIST) -- \
|
--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
|
# Fails loudly on inferred latches or non-PDK (black-box/unmapped) cells and
|
||||||
# records the register/FIFO mapping summary consumed by the evidence section.
|
# 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)
|
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 \
|
.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 alumacc
|
||||||
yosys share
|
yosys share
|
||||||
yosys opt
|
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 memory
|
||||||
yosys opt -fast
|
yosys opt -fast
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,10 @@ yosys booth
|
|||||||
yosys alumacc
|
yosys alumacc
|
||||||
yosys share
|
yosys share
|
||||||
yosys opt
|
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 memory
|
||||||
yosys opt -fast
|
yosys opt -fast
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ YOSYS_BUILD := $(SYN_BUILD_ROOT)
|
|||||||
YOSYS_OUT := $(YOSYS_BUILD)/out
|
YOSYS_OUT := $(YOSYS_BUILD)/out
|
||||||
YOSYS_TMP := $(YOSYS_BUILD)/tmp
|
YOSYS_TMP := $(YOSYS_BUILD)/tmp
|
||||||
YOSYS_RPT := $(YOSYS_BUILD)/rpt
|
YOSYS_RPT := $(YOSYS_BUILD)/rpt
|
||||||
|
YOSYS_TIMEOUT ?= 10800
|
||||||
|
|
||||||
include $(YOSYS_DIR)/synth_config.mk
|
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 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 PROJ_NAME=$(RTL_NAME) --env WORK=$(YOSYS_TMP) --env BUILD=$(YOSYS_OUT) \
|
||||||
--env REPORTS=$(YOSYS_RPT) --env NETLIST=$(NETLIST) -- \
|
--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)
|
$(NETLIST_DEBUG): $(NETLIST)
|
||||||
@test -f $@
|
@test -f $@
|
||||||
@@ -77,4 +79,4 @@ $(NETLIST_DEBUG): $(NETLIST)
|
|||||||
synth_clean:
|
synth_clean:
|
||||||
python3 $(ROOT_PATH)/scripts/clean.py --root $(ROOT_PATH) --path $(YOSYS_BUILD)
|
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 s_mc_proof_memo_full_unused;
|
||||||
logic [ 31:0] s_kws_sram_data_unused;
|
logic [ 31:0] s_kws_sram_data_unused;
|
||||||
logic s_kws_sram_valid_unused, s_kws_sram_err_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 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][15:0] s_kws_scratch_read_addr;
|
||||||
logic [19:0][31:0] s_kws_scratch_read_data;
|
logic [19:0][31:0] s_kws_scratch_read_data;
|
||||||
logic [ 5:0] s_kws_scratch_write_valid;
|
logic [ 5:0] s_kws_scratch_write_valid;
|
||||||
@@ -718,9 +722,16 @@ module apb4_apu #(
|
|||||||
.memory_input_used_o (s_kws_mem_input_used),
|
.memory_input_used_o (s_kws_mem_input_used),
|
||||||
.kws_config_i (s_codec_kws_config_valid ? s_codec_kws_config : s_kws_config),
|
.kws_config_i (s_codec_kws_config_valid ? s_codec_kws_config : s_kws_config),
|
||||||
.input_config_i (s_kws_input_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_addr_o (s_kws_model_read_addr),
|
||||||
.model_data_i (s_kws_model_read_data),
|
.model_data_i (s_kws_model_read_data),
|
||||||
.scratch_clear_o (s_kws_scratch_clear),
|
.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_addr_o (s_kws_scratch_read_addr),
|
||||||
.scratch_read_data_i (s_kws_scratch_read_data),
|
.scratch_read_data_i (s_kws_scratch_read_data),
|
||||||
.scratch_write_valid_o (s_kws_scratch_write_valid),
|
.scratch_write_valid_o (s_kws_scratch_write_valid),
|
||||||
@@ -920,9 +931,16 @@ module apb4_apu #(
|
|||||||
.data_o (s_kws_sram_data_unused),
|
.data_o (s_kws_sram_data_unused),
|
||||||
.valid_o (s_kws_sram_valid_unused),
|
.valid_o (s_kws_sram_valid_unused),
|
||||||
.access_err_o (s_kws_sram_err_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_addr_i (s_kws_model_read_addr),
|
||||||
.model_data_o (s_kws_model_read_data),
|
.model_data_o (s_kws_model_read_data),
|
||||||
.scratch_clear_i (s_kws_scratch_clear),
|
.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_addr_i (s_kws_scratch_read_addr),
|
||||||
.scratch_read_data_o (s_kws_scratch_read_data),
|
.scratch_read_data_o (s_kws_scratch_read_data),
|
||||||
.scratch_write_valid_i(s_kws_scratch_write_valid),
|
.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,
|
output logic [31:0] memory_input_used_o,
|
||||||
input logic [15:0] kws_config_i,
|
input logic [15:0] kws_config_i,
|
||||||
input logic [31:0] input_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,
|
output logic [15:0][14:0] model_addr_o,
|
||||||
input logic [15:0][ 7:0] model_data_i,
|
input logic [15:0][ 7:0] model_data_i,
|
||||||
output logic scratch_clear_o,
|
output logic scratch_clear_o,
|
||||||
|
output logic [19:0] scratch_read_valid_o,
|
||||||
output logic [19:0][15:0] scratch_read_addr_o,
|
output logic [19:0][15:0] scratch_read_addr_o,
|
||||||
input logic [19:0][31:0] scratch_read_data_i,
|
input logic [19:0][31:0] scratch_read_data_i,
|
||||||
output logic [ 5:0] scratch_write_valid_o,
|
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_fault_addr_q, s_fault_detail_q;
|
||||||
logic [31:0] s_front_watchdog_q, s_infer_watchdog_q;
|
logic [31:0] s_front_watchdog_q, s_infer_watchdog_q;
|
||||||
logic s_front_progress, s_infer_progress;
|
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_config_valid, s_continuous_active, s_listening, s_capture_available;
|
||||||
logic s_stream_accept, s_stream_legal, s_window_deadline, s_mel_overwrite;
|
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;
|
!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_listening = s_continuous_active && s_en_q && !flush_busy_i;
|
||||||
assign s_capture_available = (s_front_state_q == FrontIdle) && !s_frame_pending_q &&
|
assign s_capture_available = (s_front_state_q == FrontIdle) && !s_frame_pending_q &&
|
||||||
!s_window_pending_q && (s_fir_tap_q == 6'd0);
|
!s_window_pending_q && (s_infer_state_q == InferIdle) && (s_fir_tap_q == 6'd0);
|
||||||
assign rx_ready_o = s_listening && s_capture_available;
|
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_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_stream_legal = (stream_i.tkeep == 4'hf) && (stream_i.tstrb == 4'hf) && !stream_i.tlast;
|
||||||
assign s_window_deadline = s_commit_valid &&
|
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;
|
assign s_mac_total = s_mac_q + s_lane_sum;
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
model_addr_o = '0;
|
model_read_valid_o = 16'd0;
|
||||||
scratch_read_addr_o = '0;
|
model_addr_o = '0;
|
||||||
s_lane_active = 16'd0;
|
scratch_read_valid_o = 20'd0;
|
||||||
|
scratch_read_addr_o = '0;
|
||||||
|
s_lane_active = 16'd0;
|
||||||
for (int lane = 0; lane < 16; lane++) begin
|
for (int lane = 0; lane < 16; lane++) begin
|
||||||
s_lane_term[lane] = {1'b0, s_term_q} + 9'(lane);
|
s_lane_term[lane] = {1'b0, s_term_q} + 9'(lane);
|
||||||
s_lane_input_index[lane] = 13'd0;
|
s_lane_input_index[lane] = 13'd0;
|
||||||
@@ -766,14 +778,17 @@ module apu_kws_engine (
|
|||||||
end
|
end
|
||||||
unique case (s_front_state_q)
|
unique case (s_front_state_q)
|
||||||
FrontFir: begin
|
FrontFir: begin
|
||||||
|
scratch_read_valid_o[0] = 1'b1;
|
||||||
scratch_read_addr_o[0] = `RETROSOC_APU_KWS__SCRATCH_FIR_BASE +
|
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};
|
{9'd0, fir_history_index(s_fir_write_q, s_fir_tap_q), 1'b0};
|
||||||
end
|
end
|
||||||
FrontFftLoad: begin
|
FrontFftLoad: begin
|
||||||
|
scratch_read_valid_o[0] = 1'b1;
|
||||||
scratch_read_addr_o[0] = `RETROSOC_APU_KWS__SCRATCH_INGRESS_BASE +
|
scratch_read_addr_o[0] = `RETROSOC_APU_KWS__SCRATCH_INGRESS_BASE +
|
||||||
16'(ingress_add(s_frame_start_q, s_front_index_q) * 2);
|
16'(ingress_add(s_frame_start_q, s_front_index_q) * 2);
|
||||||
end
|
end
|
||||||
FrontFftRun: begin
|
FrontFftRun: begin
|
||||||
|
scratch_read_valid_o[3:0] = 4'hf;
|
||||||
scratch_read_addr_o[0] =
|
scratch_read_addr_o[0] =
|
||||||
`RETROSOC_APU_KWS__SCRATCH_FFT_REAL_BASE + 16'(s_fft_left_index * 4);
|
`RETROSOC_APU_KWS__SCRATCH_FFT_REAL_BASE + 16'(s_fft_left_index * 4);
|
||||||
scratch_read_addr_o[1] =
|
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);
|
`RETROSOC_APU_KWS__SCRATCH_FFT_IMAG_BASE + 16'(s_fft_right_index * 4);
|
||||||
end
|
end
|
||||||
FrontMagnitude: begin
|
FrontMagnitude: begin
|
||||||
|
scratch_read_valid_o[1:0] = 2'b11;
|
||||||
scratch_read_addr_o[0] =
|
scratch_read_addr_o[0] =
|
||||||
`RETROSOC_APU_KWS__SCRATCH_FFT_REAL_BASE + 16'(s_front_index_q * 4);
|
`RETROSOC_APU_KWS__SCRATCH_FFT_REAL_BASE + 16'(s_front_index_q * 4);
|
||||||
scratch_read_addr_o[1] =
|
scratch_read_addr_o[1] =
|
||||||
`RETROSOC_APU_KWS__SCRATCH_FFT_IMAG_BASE + 16'(s_front_index_q * 4);
|
`RETROSOC_APU_KWS__SCRATCH_FFT_IMAG_BASE + 16'(s_front_index_q * 4);
|
||||||
end
|
end
|
||||||
FrontMel: begin
|
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
|
end
|
||||||
FrontPeak: begin
|
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
|
end
|
||||||
FrontLog: begin
|
FrontLog: begin
|
||||||
|
scratch_read_valid_o[0] = 1'b1;
|
||||||
scratch_read_addr_o[0] = `RETROSOC_APU_KWS__SCRATCH_MEL_BASE +
|
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);
|
16'((16'(s_log_row_index) * 16'd40 + 16'(s_mfcc_band_q)) * 16'd4);
|
||||||
end
|
end
|
||||||
FrontDct: begin
|
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
|
end
|
||||||
default: begin
|
default: begin
|
||||||
end
|
end
|
||||||
@@ -808,34 +828,42 @@ module apu_kws_engine (
|
|||||||
if (s_infer_state_q == InferPool) begin
|
if (s_infer_state_q == InferPool) begin
|
||||||
for (int lane = 0; lane < 16; lane++) begin
|
for (int lane = 0; lane < 16; lane++) begin
|
||||||
if (({1'b0, s_term_q} + 9'(lane)) < 9'd125) 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 +
|
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));
|
16'((32'(s_term_q) + 32'(lane)) * 32'd64 + 32'(s_output_q));
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end else if ((s_infer_state_q == InferSoftmaxMax) || (s_infer_state_q == InferSoftmaxSum)) begin
|
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
|
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] =
|
scratch_read_addr_o[4] =
|
||||||
`RETROSOC_APU_KWS__SCRATCH_LOGITS_BASE + 16'(s_softmax_index_q - 1'b1);
|
`RETROSOC_APU_KWS__SCRATCH_LOGITS_BASE + 16'(s_softmax_index_q - 1'b1);
|
||||||
end else if (s_infer_state_q == InferComplete) begin
|
end else if (s_infer_state_q == InferComplete) begin
|
||||||
for (int class_index = 0; class_index < 12; class_index++) 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] =
|
scratch_read_addr_o[class_index+4] =
|
||||||
`RETROSOC_APU_KWS__SCRATCH_SOFTMAX_BASE + 16'(class_index);
|
`RETROSOC_APU_KWS__SCRATCH_SOFTMAX_BASE + 16'(class_index);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if (s_infer_state_q == InferBias) begin
|
if (s_infer_state_q == InferBias) begin
|
||||||
for (int lane = 0; lane < 4; lane++) 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
|
||||||
end else if (s_infer_state_q == InferQuant) begin
|
end else if (s_infer_state_q == InferQuant) begin
|
||||||
for (int lane = 0; lane < 4; lane++) 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_read_valid_o[lane] = 1'b1;
|
||||||
model_addr_o[lane+4] = s_shift_base + 15'(s_output_channel) * 15'd4 + 15'(lane);
|
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
|
||||||
end else if (s_infer_state_q == InferMac) begin
|
end else if (s_infer_state_q == InferMac) begin
|
||||||
for (int lane = 0; lane < 16; lane++) begin
|
for (int lane = 0; lane < 16; lane++) begin
|
||||||
if (s_lane_term[lane] < {1'b0, s_term_count}) 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
|
if (s_operator_q == 4'd0) begin
|
||||||
s_lane_input_h[lane] = 7'($signed({1'b0, s_output_height_index})) * 7'sd2 +
|
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;
|
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]);
|
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) &&
|
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
|
(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] =
|
s_lane_input_index[lane] =
|
||||||
13'(s_lane_input_h[lane]) * 13'd10 + 13'(s_lane_input_w[lane]);
|
13'(s_lane_input_h[lane]) * 13'd10 + 13'(s_lane_input_w[lane]);
|
||||||
scratch_read_addr_o[lane+4] =
|
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);
|
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) &&
|
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
|
(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] =
|
s_lane_input_index[lane] =
|
||||||
(13'(s_lane_input_h[lane]) * 13'd5 + 13'(s_lane_input_w[lane])) *
|
(13'(s_lane_input_h[lane]) * 13'd5 + 13'(s_lane_input_w[lane])) *
|
||||||
13'd64 + 13'(s_output_channel);
|
13'd64 + 13'(s_output_channel);
|
||||||
@@ -865,6 +895,7 @@ module apu_kws_engine (
|
|||||||
16'(s_lane_input_index[lane]);
|
16'(s_lane_input_index[lane]);
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
|
scratch_read_valid_o[lane+4] = 1'b1;
|
||||||
s_lane_input_index[lane] = (s_operator_q == 4'd10) ?
|
s_lane_input_index[lane] = (s_operator_q == 4'd10) ?
|
||||||
13'(s_lane_term[lane]) :
|
13'(s_lane_term[lane]) :
|
||||||
(13'(s_output_spatial_index) * 13'd64 + 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
|
||||||
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_dma_request_valid_o = s_mem_req_q;
|
||||||
assign memory_start_ready_o = enable_i && memory_window_i && model_valid_i && model_lock_i &&
|
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 &&
|
!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;
|
s_mem_err_detail_q <= 32'd0;
|
||||||
end
|
end
|
||||||
end else begin
|
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;
|
s_front_watchdog_q <= 32'd0;
|
||||||
end else if (!(&s_front_watchdog_q)) begin
|
end else if (!(&s_front_watchdog_q)) begin
|
||||||
s_front_watchdog_q <= s_front_watchdog_q + 1'b1;
|
s_front_watchdog_q <= s_front_watchdog_q + 1'b1;
|
||||||
end
|
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;
|
s_infer_watchdog_q <= 32'd0;
|
||||||
end else if (!(&s_infer_watchdog_q)) begin
|
end else if (!(&s_infer_watchdog_q)) begin
|
||||||
s_infer_watchdog_q <= s_infer_watchdog_q + 1'b1;
|
s_infer_watchdog_q <= s_infer_watchdog_q + 1'b1;
|
||||||
@@ -1493,7 +1562,7 @@ module apu_kws_engine (
|
|||||||
s_s24_pending_q <= 1'b0;
|
s_s24_pending_q <= 1'b0;
|
||||||
end
|
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_ingress_write_q <= s_next_write;
|
||||||
s_epoch_samples_q <= s_next_samples;
|
s_epoch_samples_q <= s_next_samples;
|
||||||
s_timestamp_q <= s_timestamp_q + 1'b1;
|
s_timestamp_q <= s_timestamp_q + 1'b1;
|
||||||
@@ -1528,295 +1597,297 @@ module apu_kws_engine (
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
unique case (s_front_state_q)
|
if (s_storage_state_step) begin
|
||||||
FrontIdle: begin
|
unique case (s_front_state_q)
|
||||||
if (s_frame_pending_q) begin
|
FrontIdle: begin
|
||||||
s_frame_pending_q <= 1'b0;
|
if (s_frame_pending_q) begin
|
||||||
s_front_index_q <= 10'd0;
|
s_frame_pending_q <= 1'b0;
|
||||||
s_front_state_q <= FrontFftLoad;
|
s_front_index_q <= 10'd0;
|
||||||
end else if (s_window_pending_q && (s_mel_count_q >= 6'd49) &&
|
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_infer_state_q == InferIdle)) begin
|
||||||
s_window_pending_q <= 1'b0;
|
s_window_pending_q <= 1'b0;
|
||||||
s_peak_scan_q <= 7'd0;
|
s_peak_scan_q <= 7'd0;
|
||||||
s_window_peak_q <= 16'd1;
|
s_window_peak_q <= 16'd1;
|
||||||
s_front_state_q <= FrontPeak;
|
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;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
FrontFir: begin
|
||||||
FrontMagnitude: begin
|
if (s_fir_tap_q == 6'd62) begin
|
||||||
if (s_front_index_q == 10'd256) begin
|
s_fir_tap_q <= 6'd0;
|
||||||
s_mel_band_q <= 8'd0;
|
s_fir_acc_q <= 64'sd0;
|
||||||
s_mel_bin_q <= 9'd0;
|
s_fir_phase_q <= (s_fir_phase_q == (s_decimation - 1'b1)) ?
|
||||||
s_mel_acc_q <= 64'd0;
|
3'd0 : s_fir_phase_q + 1'b1;
|
||||||
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
|
|
||||||
s_front_state_q <= FrontIdle;
|
s_front_state_q <= FrontIdle;
|
||||||
end else begin
|
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
|
||||||
end else begin
|
|
||||||
s_mel_acc_q <= s_mel_total;
|
|
||||||
s_mel_bin_q <= s_mel_bin_q + 1'b1;
|
|
||||||
end
|
end
|
||||||
end
|
FrontFftLoad: begin
|
||||||
FrontPeak: begin
|
if (s_front_index_q == 10'd511) begin
|
||||||
if (s_peak_data > s_window_peak_q) begin
|
s_fft_len_q <= 10'd2;
|
||||||
s_window_peak_q <= s_peak_data;
|
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
|
end
|
||||||
if (s_peak_scan_q == 7'd99) begin
|
FrontFftRun: begin
|
||||||
s_mfcc_row_q <= 6'd0;
|
if (s_fft_overflow) begin
|
||||||
s_mfcc_band_q <= 6'd0;
|
s_fault_q <= 1'b1;
|
||||||
s_front_state_q <= FrontLog;
|
s_fault_code_q <= `APB4_APU__ERROR_CODE_KWS_ARITHMETIC;
|
||||||
end else begin
|
s_fault_stage_q <= `APB4_APU__ERROR_STAGE_KWS_FRONTEND;
|
||||||
s_peak_scan_q <= s_peak_scan_q + 1'b1;
|
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
|
||||||
end
|
FrontMagnitude: begin
|
||||||
FrontLog: begin
|
if (s_front_index_q == 10'd256) begin
|
||||||
if (s_mfcc_band_q == 6'd39) begin
|
s_mel_band_q <= 8'd0;
|
||||||
s_mfcc_band_q <= 6'd0;
|
s_mel_bin_q <= 9'd0;
|
||||||
s_mfcc_coefficient_q <= 4'd0;
|
s_mel_acc_q <= 64'd0;
|
||||||
s_dct_acc_q <= 64'sd0;
|
s_front_state_q <= FrontMel;
|
||||||
s_front_state_q <= FrontDct;
|
end else begin
|
||||||
end else begin
|
s_front_index_q <= s_front_index_q + 1'b1;
|
||||||
s_mfcc_band_q <= s_mfcc_band_q + 1'b1;
|
end
|
||||||
end
|
end
|
||||||
end
|
FrontMel: begin
|
||||||
FrontDct: begin
|
if (s_mel_total < s_mel_acc_q) begin
|
||||||
if (s_mfcc_band_q == 6'd39) begin
|
s_fault_q <= 1'b1;
|
||||||
s_mfcc_band_q <= 6'd0;
|
s_fault_code_q <= `APB4_APU__ERROR_CODE_KWS_ARITHMETIC;
|
||||||
s_dct_acc_q <= 64'sd0;
|
s_fault_stage_q <= `APB4_APU__ERROR_STAGE_KWS_FRONTEND;
|
||||||
if (s_mfcc_coefficient_q == 4'd9) begin
|
s_fault_detail_q <= 32'h0700_0015;
|
||||||
s_mfcc_coefficient_q <= 4'd0;
|
s_stop_latched_q <= 1'b1;
|
||||||
if (s_mfcc_row_q == 6'd48) begin
|
s_front_state_q <= FrontIdle;
|
||||||
s_operator_q <= 4'd0;
|
end else if (s_mel_overwrite) begin
|
||||||
s_output_q <= 14'd0;
|
s_front_state_q <= FrontIdle;
|
||||||
s_infer_state_q <= InferBias;
|
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;
|
s_front_state_q <= FrontIdle;
|
||||||
end else begin
|
end else begin
|
||||||
s_mfcc_row_q <= s_mfcc_row_q + 1'b1;
|
s_mel_band_q <= s_mel_band_q + 1'b1;
|
||||||
s_front_state_q <= FrontLog;
|
|
||||||
end
|
end
|
||||||
end else begin
|
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
|
||||||
end else begin
|
|
||||||
s_dct_acc_q <= s_dct_total;
|
|
||||||
s_mfcc_band_q <= s_mfcc_band_q + 1'b1;
|
|
||||||
end
|
end
|
||||||
end
|
FrontPeak: begin
|
||||||
default: s_front_state_q <= FrontIdle;
|
if (s_peak_data > s_window_peak_q) begin
|
||||||
endcase
|
s_window_peak_q <= s_peak_data;
|
||||||
|
end
|
||||||
unique case (s_infer_state_q)
|
if (s_peak_scan_q == 7'd99) begin
|
||||||
InferIdle: begin
|
s_mfcc_row_q <= 6'd0;
|
||||||
end
|
s_mfcc_band_q <= 6'd0;
|
||||||
InferBias: begin
|
s_front_state_q <= FrontLog;
|
||||||
s_mac_q <= 64'($signed(s_bias_word));
|
end else begin
|
||||||
s_term_q <= 8'd0;
|
s_peak_scan_q <= s_peak_scan_q + 1'b1;
|
||||||
s_infer_state_q <= InferMac;
|
end
|
||||||
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
|
||||||
end
|
FrontLog: begin
|
||||||
InferQuant: begin
|
if (s_mfcc_band_q == 6'd39) begin
|
||||||
if (s_requant_overflow) begin
|
s_mfcc_band_q <= 6'd0;
|
||||||
s_fault_q <= 1'b1;
|
s_mfcc_coefficient_q <= 4'd0;
|
||||||
s_fault_code_q <= `APB4_APU__ERROR_CODE_KWS_ARITHMETIC;
|
s_dct_acc_q <= 64'sd0;
|
||||||
s_fault_stage_q <= `APB4_APU__ERROR_STAGE_KWS_INFERENCE;
|
s_front_state_q <= FrontDct;
|
||||||
s_fault_detail_q <= 32'h0700_0017;
|
end else begin
|
||||||
s_stop_latched_q <= 1'b1;
|
s_mfcc_band_q <= s_mfcc_band_q + 1'b1;
|
||||||
s_infer_state_q <= InferIdle;
|
end
|
||||||
end else begin
|
end
|
||||||
if (s_output_q + 1'b1 == s_output_count) begin
|
FrontDct: begin
|
||||||
s_output_q <= 14'd0;
|
if (s_mfcc_band_q == 6'd39) begin
|
||||||
if (s_operator_q == 4'd8) begin
|
s_mfcc_band_q <= 6'd0;
|
||||||
s_operator_q <= 4'd9;
|
s_dct_acc_q <= 64'sd0;
|
||||||
s_term_q <= 8'd0;
|
if (s_mfcc_coefficient_q == 4'd9) begin
|
||||||
s_mac_q <= 64'sd0;
|
s_mfcc_coefficient_q <= 4'd0;
|
||||||
s_infer_state_q <= InferPool;
|
if (s_mfcc_row_q == 6'd48) begin
|
||||||
end else if (s_operator_q == 4'd10) begin
|
s_operator_q <= 4'd0;
|
||||||
s_operator_q <= 4'd11;
|
s_output_q <= 14'd0;
|
||||||
s_softmax_index_q <= 4'd0;
|
s_infer_state_q <= InferBias;
|
||||||
s_softmax_max_q <= -8'sd128;
|
s_front_state_q <= FrontIdle;
|
||||||
s_infer_state_q <= InferSoftmaxMax;
|
end else begin
|
||||||
|
s_mfcc_row_q <= s_mfcc_row_q + 1'b1;
|
||||||
|
s_front_state_q <= FrontLog;
|
||||||
|
end
|
||||||
end else begin
|
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;
|
s_infer_state_q <= InferBias;
|
||||||
end
|
end
|
||||||
end else begin
|
|
||||||
s_output_q <= s_output_q + 1'b1;
|
|
||||||
s_infer_state_q <= InferBias;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
InferPool: begin
|
||||||
InferPool: begin
|
if (s_term_q + 8'd16 >= 8'd125) begin
|
||||||
if (s_term_q + 8'd16 >= 8'd125) begin
|
s_term_q <= 8'd0;
|
||||||
s_term_q <= 8'd0;
|
s_mac_q <= 64'sd0;
|
||||||
s_mac_q <= 64'sd0;
|
if (s_output_q == 14'd63) begin
|
||||||
if (s_output_q == 14'd63) begin
|
s_output_q <= 14'd0;
|
||||||
s_output_q <= 14'd0;
|
s_operator_q <= 4'd10;
|
||||||
s_operator_q <= 4'd10;
|
s_infer_state_q <= InferBias;
|
||||||
s_infer_state_q <= InferBias;
|
end else begin
|
||||||
|
s_output_q <= s_output_q + 1'b1;
|
||||||
|
end
|
||||||
end else begin
|
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
|
||||||
end else begin
|
|
||||||
s_mac_q <= s_pool_sum;
|
|
||||||
s_term_q <= s_term_q + 8'd16;
|
|
||||||
end
|
end
|
||||||
end
|
InferSoftmaxMax: begin
|
||||||
InferSoftmaxMax: begin
|
if (s_logit_data > s_softmax_max_q) begin
|
||||||
if (s_logit_data > s_softmax_max_q) begin
|
s_softmax_max_q <= s_logit_data;
|
||||||
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
|
end
|
||||||
if (s_softmax_index_q == 4'd11) begin
|
InferSoftmaxSum: begin
|
||||||
s_softmax_index_q <= 4'd0;
|
if (s_softmax_sum_diff >= -9'sd124) begin
|
||||||
s_softmax_sum_q <= 32'd0;
|
s_softmax_sum_q <= s_softmax_sum_q +
|
||||||
s_infer_state_q <= InferSoftmaxSum;
|
rounding_divide_pot(apu_kws_softmax_exp_q31(-s_softmax_sum_diff[6:0]), 12);
|
||||||
end else begin
|
end
|
||||||
s_softmax_index_q <= s_softmax_index_q + 1'b1;
|
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
|
||||||
end
|
InferSoftmaxScale: begin
|
||||||
InferSoftmaxSum: begin
|
if (s_softmax_index_q == 0) begin
|
||||||
if (s_softmax_sum_diff >= -9'sd124) begin
|
s_softmax_scale_q <= reciprocal_q31(s_softmax_shifted_sum);
|
||||||
s_softmax_sum_q <= s_softmax_sum_q +
|
s_softmax_bits_q <= 6'(7'sd12 - $signed({1'b0, s_softmax_headroom}));
|
||||||
rounding_divide_pot(apu_kws_softmax_exp_q31(-s_softmax_sum_diff[6:0]), 12);
|
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
|
end
|
||||||
if (s_softmax_index_q == 4'd11) begin
|
InferComplete: begin
|
||||||
s_softmax_index_q <= 4'd0;
|
s_result_q <= {15'd0, s_stable_hit, s_best_score, s_best_class};
|
||||||
s_infer_state_q <= InferSoftmaxScale;
|
s_result_valid_q <= 1'b1;
|
||||||
end else begin
|
s_timestamp_lo_q <= s_timestamp_q;
|
||||||
s_softmax_index_q <= s_softmax_index_q + 1'b1;
|
s_timestamp_hi_q <= 32'd0;
|
||||||
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
|
|
||||||
if (!counter_clear_i) begin
|
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;
|
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
|
end
|
||||||
s_hit_irq_q <= 1'b1;
|
|
||||||
end
|
end
|
||||||
s_infer_state_q <= InferIdle;
|
default: s_infer_state_q <= InferIdle;
|
||||||
if (s_mem_job_q) begin
|
endcase
|
||||||
s_mem_job_q <= 1'b0;
|
end
|
||||||
s_mem_done_q <= 1'b1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
default: s_infer_state_q <= InferIdle;
|
|
||||||
endcase
|
|
||||||
|
|
||||||
if ((s_mem_job_q && s_mem_dma_done_q && !s_mem_word_valid_q) &&
|
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
|
((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 [31:0] data_o,
|
||||||
output logic valid_o,
|
output logic valid_o,
|
||||||
output logic access_err_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,
|
input logic [15:0][14:0] model_addr_i,
|
||||||
output logic [15:0][ 7:0] model_data_o,
|
output logic [15:0][ 7:0] model_data_o,
|
||||||
input logic scratch_clear_i,
|
input logic scratch_clear_i,
|
||||||
|
input logic [19:0] scratch_read_valid_i,
|
||||||
input logic [19:0][15:0] scratch_read_addr_i,
|
input logic [19:0][15:0] scratch_read_addr_i,
|
||||||
output logic [19:0][31:0] scratch_read_data_o,
|
output logic [19:0][31:0] scratch_read_data_o,
|
||||||
input logic [ 5:0] scratch_write_valid_i,
|
input logic [ 5:0] scratch_write_valid_i,
|
||||||
@@ -28,108 +35,328 @@ module apu_kws_sram_client (
|
|||||||
output logic scratch_access_err_o
|
output logic scratch_access_err_o
|
||||||
// verilog_format: on
|
// verilog_format: on
|
||||||
);
|
);
|
||||||
localparam int unsigned ModelWordCount = `RETROSOC_APU_KWS__MODEL_BYTES / 4;
|
localparam int unsigned BankCount = 16;
|
||||||
localparam int unsigned ScratchWordCount = `RETROSOC_APU_KWS__SCRATCH_BYTES / 4;
|
|
||||||
localparam int unsigned KwsWordCount = ModelWordCount + ScratchWordCount;
|
|
||||||
localparam int unsigned FirEntryCount = 63;
|
localparam int unsigned FirEntryCount = 63;
|
||||||
|
|
||||||
logic [ 31:0] mem [0:KwsWordCount-1];
|
logic [ BankCount-1:0] s_bank_cs;
|
||||||
logic [FirEntryCount-1:0] s_fir_valid_q;
|
logic [ BankCount-1:0] s_bank_wren;
|
||||||
logic s_pending_q;
|
logic [ BankCount-1:0][ 9:0] s_bank_addr;
|
||||||
logic s_err_q;
|
logic [ BankCount-1:0][31:0] s_bank_wdata;
|
||||||
logic [ 31:0] s_data_q;
|
logic [ BankCount-1:0][ 3:0] s_bank_wmask;
|
||||||
logic s_range_ok;
|
logic [ BankCount-1:0][31:0] s_bank_rdata;
|
||||||
logic [ 13:0] s_word_addr;
|
|
||||||
|
|
||||||
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) &&
|
||||||
(addr_i < (`APB4_APU__LOCAL_KWS_BASE + `RETROSOC_APU_KWS__MODEL_BYTES));
|
(addr_i < (`APB4_APU__LOCAL_KWS_BASE + `RETROSOC_APU_KWS__MODEL_BYTES));
|
||||||
assign s_word_addr = 14'(addr_i[15:2] - 14'h2800);
|
assign s_loader_offset = 15'(addr_i - `APB4_APU__LOCAL_KWS_BASE);
|
||||||
assign ready_o = rst_n_i && !s_pending_q;
|
assign s_loader_bank = model_bank(s_loader_offset);
|
||||||
assign data_o = s_data_q;
|
assign s_loader_row = s_loader_offset[14:5];
|
||||||
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);
|
|
||||||
|
|
||||||
for (genvar lane = 0; lane < 16; lane++) begin : gen_model_read
|
assign ready_o = rst_n_i && !s_busy_q && !s_loader_read_pending_q;
|
||||||
assign model_data_o[lane] = mem[{1'b0, model_addr_i[lane][14:2]}][8*model_addr_i[lane][1:0]+:8];
|
assign data_o = s_bank_rdata[s_loader_read_bank_q];
|
||||||
end
|
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) ||
|
||||||
for (genvar lane = 0; lane < 20; lane++) begin : gen_scratch_read
|
(s_loader_read_pending_q && s_loader_read_err_q);
|
||||||
logic s_fir_range;
|
assign access_ready_o = rst_n_i && !s_busy_q && !s_loader_read_pending_q;
|
||||||
logic [ 5:0] s_fir_index;
|
assign access_done_o = s_busy_q && (s_model_pending_q == 16'd0) &&
|
||||||
logic [13:0] s_memory_word;
|
(s_scratch_read_pending_q == 20'd0) && (s_scratch_write_pending_q == 6'd0) &&
|
||||||
|
(s_read_pipe_valid_q == BankCount'(0));
|
||||||
assign s_fir_range =
|
assign access_progress_o = |s_issue_write || |s_issue_read;
|
||||||
(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
|
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
scratch_access_err_o = 1'b0;
|
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
|
for (int lane = 0; lane < 6; lane++) begin
|
||||||
scratch_access_err_o |= scratch_write_valid_i[lane] && scratch_write_addr_i[lane][15];
|
scratch_access_err_o |= scratch_write_valid_i[lane] && scratch_write_addr_i[lane][15];
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
always_ff @(posedge clk_i or negedge rst_n_i) begin
|
always_comb begin
|
||||||
if (!rst_n_i) begin
|
s_bank_cs = BankCount'(0);
|
||||||
s_fir_valid_q <= FirEntryCount'(0);
|
s_bank_wren = BankCount'(0);
|
||||||
s_pending_q <= 1'b0;
|
s_bank_addr = '0;
|
||||||
s_err_q <= 1'b0;
|
s_bank_wdata = '0;
|
||||||
s_data_q <= 32'd0;
|
s_bank_wmask = '0;
|
||||||
end else begin
|
s_issue_write = BankCount'(0);
|
||||||
s_pending_q <= 1'b0;
|
s_issue_write_lane = '0;
|
||||||
s_err_q <= 1'b0;
|
s_issue_read = BankCount'(0);
|
||||||
if (scratch_clear_i) begin
|
s_issue_model_mask = '0;
|
||||||
s_fir_valid_q <= FirEntryCount'(0);
|
s_issue_scratch_mask = '0;
|
||||||
end
|
|
||||||
if (req_i && ready_o) begin
|
if (req_i && ready_o && s_loader_range_ok) begin
|
||||||
if (!s_range_ok) begin
|
s_bank_cs[s_loader_bank] = 1'b1;
|
||||||
s_pending_q <= 1'b1;
|
s_bank_wren[s_loader_bank] = write_i;
|
||||||
s_err_q <= 1'b1;
|
s_bank_addr[s_loader_bank] = s_loader_row;
|
||||||
end else if (write_i) begin
|
s_bank_wdata[s_loader_bank] = data_i;
|
||||||
if (strb_i[0]) mem[s_word_addr][7:0] <= data_i[7:0];
|
s_bank_wmask[s_loader_bank] = strb_i;
|
||||||
if (strb_i[1]) mem[s_word_addr][15:8] <= data_i[15:8];
|
end else if (s_busy_q) begin
|
||||||
if (strb_i[2]) mem[s_word_addr][23:16] <= data_i[23:16];
|
for (int bank = 0; bank < BankCount; bank++) begin
|
||||||
if (strb_i[3]) mem[s_word_addr][31:24] <= data_i[31:24];
|
for (int lane = 0; lane < 6; lane++) begin
|
||||||
end else begin
|
if (!s_bank_cs[bank] && s_scratch_write_pending_q[lane] && (scratch_bank(
|
||||||
s_data_q <= mem[s_word_addr];
|
s_scratch_write_addr_q[lane]
|
||||||
s_pending_q <= 1'b1;
|
) == 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
|
||||||
end
|
end
|
||||||
for (int lane = 0; lane < 6; lane++) begin
|
for (int bank = 0; bank < BankCount; bank++) begin
|
||||||
if (scratch_write_valid_i[lane] && !scratch_write_addr_i[lane][15]) begin
|
for (int lane = 0; lane < 20; lane++) begin
|
||||||
if (scratch_write_strb_i[lane][0]) begin
|
if (s_issue_read[bank] && s_scratch_read_pending_q[lane] && (scratch_bank(
|
||||||
mem[14'(ModelWordCount)+{1'b0, scratch_write_addr_i[lane][14:2]}][7:0] <=
|
s_scratch_read_addr_q[lane]
|
||||||
scratch_write_data_i[lane][7:0];
|
) == 4'(bank)) && (s_scratch_read_addr_q[lane][14:5] == s_bank_addr[bank])) begin
|
||||||
|
s_issue_scratch_mask[bank][lane] = 1'b1;
|
||||||
end
|
end
|
||||||
if (scratch_write_strb_i[lane][1]) begin
|
end
|
||||||
mem[14'(ModelWordCount)+{1'b0, scratch_write_addr_i[lane][14:2]}][15:8] <=
|
for (int lane = 0; lane < 16; lane++) begin
|
||||||
scratch_write_data_i[lane][15:8];
|
if (s_issue_read[bank] && s_model_pending_q[lane] && (model_bank(
|
||||||
end
|
s_model_addr_q[lane]
|
||||||
if (scratch_write_strb_i[lane][2]) begin
|
) == 4'(bank)) && (s_model_addr_q[lane][14:5] == s_bank_addr[bank])) begin
|
||||||
mem[14'(ModelWordCount)+{1'b0, scratch_write_addr_i[lane][14:2]}][23:16] <=
|
s_issue_model_mask[bank][lane] = 1'b1;
|
||||||
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
|
end
|
||||||
end
|
end
|
||||||
end
|
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
|
endmodule
|
||||||
@@ -18,62 +18,86 @@ module jpeg_table_register_bank (
|
|||||||
output logic [1279:0] ac_length_o
|
output logic [1279:0] ac_length_o
|
||||||
// verilog_format: on
|
// verilog_format: on
|
||||||
);
|
);
|
||||||
for (genvar index = 0; index < 64; index++) begin : gen_quant_entry
|
logic [ 511:0] s_quant_d;
|
||||||
dffl #(
|
logic [1599:0] s_reciprocal_d;
|
||||||
.DATA_WIDTH(8)
|
logic [ 191:0] s_dc_code_d;
|
||||||
) u_quant_dffl (
|
logic [ 59:0] s_dc_len_d;
|
||||||
.clk_i(clk_i),
|
logic [4095:0] s_ac_code_d;
|
||||||
.en_i (write_i && (entry_kind_i < 4'd4) && (entry_index_i == 8'(index))),
|
logic [1279:0] s_ac_len_d;
|
||||||
.dat_i(entry_data_i[7:0]),
|
logic s_quant_write, s_dc_write, s_ac_write;
|
||||||
.dat_o(quant_o[index*8+:8])
|
|
||||||
);
|
assign s_quant_write = write_i && (entry_kind_i < 4'd4) && (entry_index_i < 8'd64);
|
||||||
dffl #(
|
assign s_dc_write = write_i && (entry_kind_i >= 4'd4) && (entry_kind_i < 4'd8) &&
|
||||||
.DATA_WIDTH(25)
|
(entry_index_i < 8'd12);
|
||||||
) u_reciprocal_dffl (
|
assign s_ac_write = write_i && (entry_kind_i >= 4'd8);
|
||||||
.clk_i(clk_i),
|
|
||||||
.en_i (write_i && (entry_kind_i < 4'd4) && (entry_index_i == 8'(index))),
|
always_comb begin
|
||||||
.dat_i(entry_reciprocal_i),
|
s_quant_d = quant_o;
|
||||||
.dat_o(reciprocal_o[index*25+:25])
|
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
|
end
|
||||||
|
|
||||||
for (genvar index = 0; index < 12; index++) begin : gen_dc_entry
|
dffl #(
|
||||||
dffl #(
|
.DATA_WIDTH(512)
|
||||||
.DATA_WIDTH(16)
|
) u_quant_dffl (
|
||||||
) u_code_dffl (
|
.clk_i(clk_i),
|
||||||
.clk_i(clk_i),
|
.en_i (s_quant_write),
|
||||||
.en_i (write_i && (entry_kind_i >= 4'd4) && (entry_kind_i < 4'd8) &&
|
.dat_i(s_quant_d),
|
||||||
(entry_index_i == 8'(index))),
|
.dat_o(quant_o)
|
||||||
.dat_i(entry_data_i[15:0]),
|
);
|
||||||
.dat_o(dc_code_o[index*16+:16])
|
dffl #(
|
||||||
);
|
.DATA_WIDTH(1600)
|
||||||
dffl #(
|
) u_reciprocal_dffl (
|
||||||
.DATA_WIDTH(5)
|
.clk_i(clk_i),
|
||||||
) u_length_dffl (
|
.en_i (s_quant_write),
|
||||||
.clk_i(clk_i),
|
.dat_i(s_reciprocal_d),
|
||||||
.en_i (write_i && (entry_kind_i >= 4'd4) && (entry_kind_i < 4'd8) &&
|
.dat_o(reciprocal_o)
|
||||||
(entry_index_i == 8'(index))),
|
);
|
||||||
.dat_i(entry_data_i[20:16]),
|
dffl #(
|
||||||
.dat_o(dc_length_o[index*5+:5])
|
.DATA_WIDTH(192)
|
||||||
);
|
) u_dc_code_dffl (
|
||||||
end
|
.clk_i(clk_i),
|
||||||
|
.en_i (s_dc_write),
|
||||||
for (genvar index = 0; index < 256; index++) begin : gen_ac_entry
|
.dat_i(s_dc_code_d),
|
||||||
dffl #(
|
.dat_o(dc_code_o)
|
||||||
.DATA_WIDTH(16)
|
);
|
||||||
) u_code_dffl (
|
dffl #(
|
||||||
.clk_i(clk_i),
|
.DATA_WIDTH(60)
|
||||||
.en_i (write_i && (entry_kind_i >= 4'd8) && (entry_index_i == 8'(index))),
|
) u_dc_length_dffl (
|
||||||
.dat_i(entry_data_i[15:0]),
|
.clk_i(clk_i),
|
||||||
.dat_o(ac_code_o[index*16+:16])
|
.en_i (s_dc_write),
|
||||||
);
|
.dat_i(s_dc_len_d),
|
||||||
dffl #(
|
.dat_o(dc_length_o)
|
||||||
.DATA_WIDTH(5)
|
);
|
||||||
) u_length_dffl (
|
dffl #(
|
||||||
.clk_i(clk_i),
|
.DATA_WIDTH(4096)
|
||||||
.en_i (write_i && (entry_kind_i >= 4'd8) && (entry_index_i == 8'(index))),
|
) u_ac_code_dffl (
|
||||||
.dat_i(entry_data_i[20:16]),
|
.clk_i(clk_i),
|
||||||
.dat_o(ac_length_o[index*5+:5])
|
.en_i (s_ac_write),
|
||||||
);
|
.dat_i(s_ac_code_d),
|
||||||
end
|
.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
|
endmodule
|
||||||
+40
-13
@@ -6,6 +6,8 @@ import argparse
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import resource
|
||||||
|
import signal
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import termios
|
import termios
|
||||||
@@ -75,6 +77,17 @@ def write_console_bytes(chunk: bytes) -> None:
|
|||||||
sys.stdout.buffer.flush()
|
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:
|
def main() -> int:
|
||||||
parser = argparse.ArgumentParser(description="Run a flow command with structured results")
|
parser = argparse.ArgumentParser(description="Run a flow command with structured results")
|
||||||
parser.add_argument("--tool", required=True)
|
parser.add_argument("--tool", required=True)
|
||||||
@@ -111,6 +124,28 @@ def main() -> int:
|
|||||||
args.result.parent.mkdir(parents=True, exist_ok=True)
|
args.result.parent.mkdir(parents=True, exist_ok=True)
|
||||||
started = datetime.now(timezone.utc)
|
started = datetime.now(timezone.utc)
|
||||||
start_clock = time.monotonic()
|
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
|
returncode = 127
|
||||||
error_message = None
|
error_message = None
|
||||||
process: subprocess.Popen[str] | subprocess.Popen[bytes] | None = 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",
|
errors=None if args.stream_bytes else "replace",
|
||||||
bufsize=0 if args.stream_bytes else 1,
|
bufsize=0 if args.stream_bytes else 1,
|
||||||
pass_fds=jobserver_fds(),
|
pass_fds=jobserver_fds(),
|
||||||
|
start_new_session=True,
|
||||||
)
|
)
|
||||||
assert process.stdout is not None
|
assert process.stdout is not None
|
||||||
if args.stream_bytes:
|
if args.stream_bytes:
|
||||||
@@ -150,25 +186,15 @@ def main() -> int:
|
|||||||
write_console_output(line)
|
write_console_output(line)
|
||||||
if args.terminate_on_success_marker and args.success_marker in line:
|
if args.terminate_on_success_marker and args.success_marker in line:
|
||||||
marker_seen = True
|
marker_seen = True
|
||||||
process.terminate()
|
terminate_process_group(process)
|
||||||
try:
|
|
||||||
process.wait(timeout=5)
|
|
||||||
except subprocess.TimeoutExpired:
|
|
||||||
process.kill()
|
|
||||||
process.wait()
|
|
||||||
returncode = 1 if rejected_matches else 0
|
returncode = 1 if rejected_matches else 0
|
||||||
break
|
break
|
||||||
if not marker_seen:
|
if not marker_seen:
|
||||||
returncode = process.wait()
|
returncode = process.wait()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
error_message = "interrupted"
|
error_message = "interrupted"
|
||||||
if process is not None and process.poll() is None:
|
if process is not None:
|
||||||
process.terminate()
|
terminate_process_group(process)
|
||||||
try:
|
|
||||||
process.wait(timeout=5)
|
|
||||||
except subprocess.TimeoutExpired:
|
|
||||||
process.kill()
|
|
||||||
process.wait()
|
|
||||||
returncode = 130
|
returncode = 130
|
||||||
except (OSError, subprocess.SubprocessError) as error:
|
except (OSError, subprocess.SubprocessError) as error:
|
||||||
error_message = str(error)
|
error_message = str(error)
|
||||||
@@ -182,6 +208,7 @@ def main() -> int:
|
|||||||
"started_at": started.isoformat(),
|
"started_at": started.isoformat(),
|
||||||
"finished_at": finished.isoformat(),
|
"finished_at": finished.isoformat(),
|
||||||
"duration_seconds": round(time.monotonic() - start_clock, 3),
|
"duration_seconds": round(time.monotonic() - start_clock, 3),
|
||||||
|
"peak_rss_kib": resource.getrusage(resource.RUSAGE_CHILDREN).ru_maxrss,
|
||||||
"exit_code": returncode,
|
"exit_code": returncode,
|
||||||
"status": "passed" if returncode == 0 else "failed",
|
"status": "passed" if returncode == 0 else "failed",
|
||||||
"log": str(args.log.resolve()),
|
"log": str(args.log.resolve()),
|
||||||
|
|||||||
@@ -40,7 +40,10 @@ module apu_kws_engine_tb;
|
|||||||
logic [31:0] fault_addr_o, fault_detail_o;
|
logic [31:0] fault_addr_o, fault_detail_o;
|
||||||
logic [15:0][14:0] model_addr_o;
|
logic [15:0][14:0] model_addr_o;
|
||||||
logic [15:0][7:0] model_data_i, model_store_data;
|
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 scratch_clear;
|
||||||
|
logic [19:0] scratch_read_valid;
|
||||||
logic [19:0][15:0] scratch_read_addr;
|
logic [19:0][15:0] scratch_read_addr;
|
||||||
logic [19:0][31:0] scratch_read_data;
|
logic [19:0][31:0] scratch_read_data;
|
||||||
logic [ 5:0] scratch_write_valid;
|
logic [ 5:0] scratch_write_valid;
|
||||||
@@ -138,9 +141,16 @@ module apu_kws_engine_tb;
|
|||||||
.data_o (),
|
.data_o (),
|
||||||
.valid_o (),
|
.valid_o (),
|
||||||
.access_err_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_addr_i (model_addr_o),
|
||||||
.model_data_o (model_store_data),
|
.model_data_o (model_store_data),
|
||||||
.scratch_clear_i (scratch_clear),
|
.scratch_clear_i (scratch_clear),
|
||||||
|
.scratch_read_valid_i (scratch_read_valid),
|
||||||
.scratch_read_addr_i (scratch_read_addr),
|
.scratch_read_addr_i (scratch_read_addr),
|
||||||
.scratch_read_data_o (scratch_read_data),
|
.scratch_read_data_o (scratch_read_data),
|
||||||
.scratch_write_valid_i(scratch_write_valid),
|
.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_error_detail_o (memory_error_detail_o),
|
||||||
.memory_input_used_o (memory_input_used_o),
|
.memory_input_used_o (memory_input_used_o),
|
||||||
.input_config_i (32'h01043e80),
|
.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_addr_o (model_addr_o),
|
||||||
.model_data_i (model_data_i),
|
.model_data_i (model_data_i),
|
||||||
.scratch_clear_o (scratch_clear),
|
.scratch_clear_o (scratch_clear),
|
||||||
|
.scratch_read_valid_o (scratch_read_valid),
|
||||||
.scratch_read_addr_o (scratch_read_addr),
|
.scratch_read_addr_o (scratch_read_addr),
|
||||||
.scratch_read_data_i (scratch_read_data),
|
.scratch_read_data_i (scratch_read_data),
|
||||||
.scratch_write_valid_o (scratch_write_valid),
|
.scratch_write_valid_o (scratch_write_valid),
|
||||||
@@ -474,15 +491,22 @@ module apu_kws_engine_tb;
|
|||||||
enable_i = 1'b1;
|
enable_i = 1'b1;
|
||||||
accepted_samples = 0;
|
accepted_samples = 0;
|
||||||
elapsed_cycles = 0;
|
elapsed_cycles = 0;
|
||||||
while ((accepted_samples < 16000) && (elapsed_cycles < 2000000)) begin
|
while ((accepted_samples < 16000) && (elapsed_cycles < 4000000)) begin
|
||||||
@(posedge clk_i);
|
@(posedge clk_i);
|
||||||
if (stream_i.tvalid && stream_i.tready) accepted_samples++;
|
if (stream_i.tvalid && stream_i.tready) accepted_samples++;
|
||||||
elapsed_cycles++;
|
elapsed_cycles++;
|
||||||
end
|
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);
|
@(negedge clk_i);
|
||||||
enable_i = 1'b0;
|
enable_i = 1'b0;
|
||||||
while ((inference_count_o == 0) && (elapsed_cycles < 3000000)) begin
|
elapsed_cycles = 0;
|
||||||
|
while ((inference_count_o == 0) && (elapsed_cycles < 4000000)) begin
|
||||||
@(negedge clk_i);
|
@(negedge clk_i);
|
||||||
elapsed_cycles++;
|
elapsed_cycles++;
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -9,10 +9,15 @@ module apu_kws_sram_client_tb;
|
|||||||
logic [31:0] data_i = 32'd0;
|
logic [31:0] data_i = 32'd0;
|
||||||
logic [ 3:0] strb_i = 4'd0;
|
logic [ 3:0] strb_i = 4'd0;
|
||||||
logic ready_o, valid_o, access_err_o;
|
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][14:0] model_addr_i = '0;
|
||||||
logic [15:0][ 7:0] model_data_o;
|
logic [15:0][ 7:0] model_data_o;
|
||||||
logic scratch_clear_i = 1'b0;
|
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][15:0] scratch_read_addr_i = '0;
|
||||||
logic [19:0][31:0] scratch_read_data_o;
|
logic [19:0][31:0] scratch_read_data_o;
|
||||||
logic [ 5:0] scratch_write_valid_i = 6'd0;
|
logic [ 5:0] scratch_write_valid_i = 6'd0;
|
||||||
@@ -39,9 +44,16 @@ module apu_kws_sram_client_tb;
|
|||||||
.data_o (data_o),
|
.data_o (data_o),
|
||||||
.valid_o (valid_o),
|
.valid_o (valid_o),
|
||||||
.access_err_o (access_err_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_addr_i (model_addr_i),
|
||||||
.model_data_o (model_data_o),
|
.model_data_o (model_data_o),
|
||||||
.scratch_clear_i (scratch_clear_i),
|
.scratch_clear_i (scratch_clear_i),
|
||||||
|
.scratch_read_valid_i (scratch_read_valid_i),
|
||||||
.scratch_read_addr_i (scratch_read_addr_i),
|
.scratch_read_addr_i (scratch_read_addr_i),
|
||||||
.scratch_read_data_o (scratch_read_data_o),
|
.scratch_read_data_o (scratch_read_data_o),
|
||||||
.scratch_write_valid_i(scratch_write_valid_i),
|
.scratch_write_valid_i(scratch_write_valid_i),
|
||||||
@@ -88,6 +100,20 @@ module apu_kws_sram_client_tb;
|
|||||||
end
|
end
|
||||||
endtask
|
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,
|
task automatic write_scratch(input logic [15:0] address_i, input logic [31:0] value_i,
|
||||||
input logic [3:0] strobe_i);
|
input logic [3:0] strobe_i);
|
||||||
begin
|
begin
|
||||||
@@ -96,11 +122,13 @@ module apu_kws_sram_client_tb;
|
|||||||
scratch_write_addr_i[0] = address_i;
|
scratch_write_addr_i[0] = address_i;
|
||||||
scratch_write_data_i[0] = value_i;
|
scratch_write_data_i[0] = value_i;
|
||||||
scratch_write_strb_i[0] = strobe_i;
|
scratch_write_strb_i[0] = strobe_i;
|
||||||
@(negedge clk_i);
|
run_access(1'b1);
|
||||||
scratch_write_valid_i[0] = 1'b0;
|
scratch_write_valid_i[0] = 1'b0;
|
||||||
scratch_write_strb_i[0] = 4'd0;
|
scratch_write_strb_i[0] = 4'd0;
|
||||||
scratch_read_addr_i[0] = address_i;
|
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
|
if (scratch_read_data_o[0] != value_i) begin
|
||||||
$fatal(1, "scratch layout write mismatch at %04x", address_i);
|
$fatal(1, "scratch layout write mismatch at %04x", address_i);
|
||||||
end
|
end
|
||||||
@@ -126,25 +154,29 @@ module apu_kws_sram_client_tb;
|
|||||||
rst_n_i = 1'b1;
|
rst_n_i = 1'b1;
|
||||||
|
|
||||||
write_model(`APB4_APU__LOCAL_KWS_BASE, 32'h4433_2211);
|
write_model(`APB4_APU__LOCAL_KWS_BASE, 32'h4433_2211);
|
||||||
model_addr_i[0] = 15'd0;
|
model_addr_i[0] = 15'd0;
|
||||||
model_addr_i[1] = 15'd1;
|
model_addr_i[1] = 15'd1;
|
||||||
model_addr_i[2] = 15'd2;
|
model_addr_i[2] = 15'd2;
|
||||||
model_addr_i[3] = 15'd3;
|
model_addr_i[3] = 15'd3;
|
||||||
#1;
|
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
|
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");
|
$fatal(1, "banks10..17 model readback mismatch");
|
||||||
end
|
end
|
||||||
write_model(17'h1_0000, 32'h8877_6655);
|
write_model(17'h1_0000, 32'h8877_6655);
|
||||||
write_model(`APB4_APU__LOCAL_KWS_BASE + `RETROSOC_APU_KWS__MODEL_BYTES - 4, 32'hccbb_aa99);
|
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[0] = 15'h6000;
|
||||||
model_addr_i[1] = 15'h6001;
|
model_addr_i[1] = 15'h6001;
|
||||||
model_addr_i[2] = 15'h6002;
|
model_addr_i[2] = 15'h6002;
|
||||||
model_addr_i[3] = 15'h6003;
|
model_addr_i[3] = 15'h6003;
|
||||||
model_addr_i[4] = 15'h7ffc;
|
model_addr_i[4] = 15'h7ffc;
|
||||||
model_addr_i[5] = 15'h7ffd;
|
model_addr_i[5] = 15'h7ffd;
|
||||||
model_addr_i[6] = 15'h7ffe;
|
model_addr_i[6] = 15'h7ffe;
|
||||||
model_addr_i[7] = 15'h7fff;
|
model_addr_i[7] = 15'h7fff;
|
||||||
#1;
|
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
|
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");
|
$fatal(1, "APUM model address crossing 0x10000 did not map to bank16");
|
||||||
end
|
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(`RETROSOC_APU_KWS__SCRATCH_PEAK_BASE, 32'h6162_6364, 4'hf);
|
||||||
write_scratch(16'h7ffc, 32'h7172_7374, 4'hf);
|
write_scratch(16'h7ffc, 32'h7172_7374, 4'hf);
|
||||||
|
|
||||||
model_addr_i[0] = 15'd0;
|
model_addr_i[0] = 15'd0;
|
||||||
#1;
|
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");
|
if (model_data_o[0] != 8'h11) $fatal(1, "scratch write corrupted APUM storage");
|
||||||
|
|
||||||
@(negedge clk_i);
|
@(negedge clk_i);
|
||||||
@@ -185,12 +219,16 @@ module apu_kws_sram_client_tb;
|
|||||||
@(negedge clk_i);
|
@(negedge clk_i);
|
||||||
scratch_clear_i = 1'b1;
|
scratch_clear_i = 1'b1;
|
||||||
@(negedge clk_i);
|
@(negedge clk_i);
|
||||||
scratch_clear_i = 1'b0;
|
scratch_clear_i = 1'b0;
|
||||||
scratch_read_addr_i[0] = `RETROSOC_APU_KWS__SCRATCH_FIR_BASE;
|
scratch_read_addr_i[0] = `RETROSOC_APU_KWS__SCRATCH_FIR_BASE;
|
||||||
#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] != 32'd0) $fatal(1, "FIR lifecycle clear exposed stale data");
|
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;
|
scratch_read_addr_i[0] = `RETROSOC_APU_KWS__SCRATCH_A_BASE;
|
||||||
#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] != 32'h0102_0304) begin
|
if (scratch_read_data_o[0] != 32'h0102_0304) begin
|
||||||
$fatal(1, "history clear corrupted non-history scratch");
|
$fatal(1, "history clear corrupted non-history scratch");
|
||||||
end
|
end
|
||||||
@@ -203,5 +241,5 @@ module apu_kws_sram_client_tb;
|
|||||||
end
|
end
|
||||||
|
|
||||||
logic s_unused;
|
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
|
endmodule
|
||||||
@@ -46,7 +46,10 @@ module apu_p7_accuracy_tb;
|
|||||||
logic [31:0] fault_addr_o, fault_detail_o;
|
logic [31:0] fault_addr_o, fault_detail_o;
|
||||||
logic [15:0][14:0] model_addr_o;
|
logic [15:0][14:0] model_addr_o;
|
||||||
logic [15:0][ 7:0] model_store_data;
|
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 scratch_clear;
|
||||||
|
logic [19:0] scratch_read_valid;
|
||||||
logic [19:0][15:0] scratch_read_addr;
|
logic [19:0][15:0] scratch_read_addr;
|
||||||
logic [19:0][31:0] scratch_read_data;
|
logic [19:0][31:0] scratch_read_data;
|
||||||
logic [ 5:0] scratch_write_valid;
|
logic [ 5:0] scratch_write_valid;
|
||||||
@@ -86,9 +89,16 @@ module apu_p7_accuracy_tb;
|
|||||||
.data_o (),
|
.data_o (),
|
||||||
.valid_o (),
|
.valid_o (),
|
||||||
.access_err_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_addr_i (model_addr_o),
|
||||||
.model_data_o (model_store_data),
|
.model_data_o (model_store_data),
|
||||||
.scratch_clear_i (scratch_clear),
|
.scratch_clear_i (scratch_clear),
|
||||||
|
.scratch_read_valid_i (scratch_read_valid),
|
||||||
.scratch_read_addr_i (scratch_read_addr),
|
.scratch_read_addr_i (scratch_read_addr),
|
||||||
.scratch_read_data_o (scratch_read_data),
|
.scratch_read_data_o (scratch_read_data),
|
||||||
.scratch_write_valid_i(scratch_write_valid),
|
.scratch_write_valid_i(scratch_write_valid),
|
||||||
@@ -143,9 +153,16 @@ module apu_p7_accuracy_tb;
|
|||||||
.memory_input_used_o (memory_input_used_o),
|
.memory_input_used_o (memory_input_used_o),
|
||||||
.kws_config_i (KwsConfig),
|
.kws_config_i (KwsConfig),
|
||||||
.input_config_i (InputConfig),
|
.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_addr_o (model_addr_o),
|
||||||
.model_data_i (model_store_data),
|
.model_data_i (model_store_data),
|
||||||
.scratch_clear_o (scratch_clear),
|
.scratch_clear_o (scratch_clear),
|
||||||
|
.scratch_read_valid_o (scratch_read_valid),
|
||||||
.scratch_read_addr_o (scratch_read_addr),
|
.scratch_read_addr_o (scratch_read_addr),
|
||||||
.scratch_read_data_i (scratch_read_data),
|
.scratch_read_data_i (scratch_read_data),
|
||||||
.scratch_write_valid_o (scratch_write_valid),
|
.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 [31:0] fault_addr_o, fault_detail_o;
|
||||||
logic [15:0][14:0] model_addr_o;
|
logic [15:0][14:0] model_addr_o;
|
||||||
logic [15:0][ 7:0] model_store_data;
|
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 scratch_clear;
|
||||||
|
logic [19:0] scratch_read_valid;
|
||||||
logic [19:0][15:0] scratch_read_addr;
|
logic [19:0][15:0] scratch_read_addr;
|
||||||
logic [19:0][31:0] scratch_read_data;
|
logic [19:0][31:0] scratch_read_data;
|
||||||
logic [ 5:0] scratch_write_valid;
|
logic [ 5:0] scratch_write_valid;
|
||||||
@@ -89,9 +92,16 @@ module apu_p7_frontend_dump_tb;
|
|||||||
.data_o (),
|
.data_o (),
|
||||||
.valid_o (),
|
.valid_o (),
|
||||||
.access_err_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_addr_i (model_addr_o),
|
||||||
.model_data_o (model_store_data),
|
.model_data_o (model_store_data),
|
||||||
.scratch_clear_i (scratch_clear),
|
.scratch_clear_i (scratch_clear),
|
||||||
|
.scratch_read_valid_i (scratch_read_valid),
|
||||||
.scratch_read_addr_i (scratch_read_addr),
|
.scratch_read_addr_i (scratch_read_addr),
|
||||||
.scratch_read_data_o (scratch_read_data),
|
.scratch_read_data_o (scratch_read_data),
|
||||||
.scratch_write_valid_i(scratch_write_valid),
|
.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),
|
.memory_input_used_o (memory_input_used_o),
|
||||||
.kws_config_i (KwsConfig),
|
.kws_config_i (KwsConfig),
|
||||||
.input_config_i (InputConfig),
|
.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_addr_o (model_addr_o),
|
||||||
.model_data_i (model_store_data),
|
.model_data_i (model_store_data),
|
||||||
.scratch_clear_o (scratch_clear),
|
.scratch_clear_o (scratch_clear),
|
||||||
|
.scratch_read_valid_o (scratch_read_valid),
|
||||||
.scratch_read_addr_o (scratch_read_addr),
|
.scratch_read_addr_o (scratch_read_addr),
|
||||||
.scratch_read_data_i (scratch_read_data),
|
.scratch_read_data_i (scratch_read_data),
|
||||||
.scratch_write_valid_o (scratch_write_valid),
|
.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["status"] == "passed"
|
||||||
assert data["exit_code"] == 0
|
assert data["exit_code"] == 0
|
||||||
assert data["duration_seconds"] >= 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"
|
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 "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 SYNTH_RECIPE=$(SYNTH_RECIPE)" in yosys_mk
|
||||||
assert "--env YOSYS_TARGET_PERIOD_PS=$(YOSYS_TARGET_PERIOD_PS)" 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 "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 "yosys abc {*}$tech_cells_args -D $period_ps -script $abc_script -constr $abc_constr" in synth_tcl
|
||||||
assert "S110" not in synth_tcl
|
assert "S110" not in synth_tcl
|
||||||
assert "$(SYN_BUILD_ROOT)/out/retrosoc_asic_yosys.v" in opensta
|
assert "$(SYN_BUILD_ROOT)/out/retrosoc_asic_yosys.v" in opensta
|
||||||
|
|||||||
Reference in new issue
Block a user