From 7d80045d7d6ce892d8835bf730fa12da937a92a9 Mon Sep 17 00:00:00 2001 From: georg Date: Fri, 3 Jul 2026 10:57:22 +0200 Subject: [PATCH 1/3] Regs: Add `make_sw_all` target to make C regfile headers - This target generates C headers in `target/sw` with both the `raw-header` and `c-header` PeakRDL plugins - Also added to `deploy` CI job --- .github/workflows/deploy.yml | 2 +- idma.mk | 30 ++++++++++++++-- pyproject.toml | 1 + target/sw/.gitignore | 1 + util/deploy.py | 18 +++++----- uv.lock | 70 ++++++++++++++++++------------------ 6 files changed, 77 insertions(+), 45 deletions(-) create mode 100644 target/sw/.gitignore diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7fcac42b..47b8d32f 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -61,7 +61,7 @@ jobs: - name: Build hardware run: | - uv run --locked make -B idma_hw_all \ + uv run --locked make -B idma_hw_all idma_sw_all \ IDMA_BACKEND_IDS="${{ inputs.IDMA_BACKEND_IDS }}" \ IDMA_REG_CPUIF="${{ inputs.IDMA_REG_CPUIF }}" - diff --git a/idma.mk b/idma.mk index 1789fad9..bebcc422 100644 --- a/idma.mk +++ b/idma.mk @@ -60,6 +60,7 @@ IDMA_FE_IDS ?= $(IDMA_BASE_FE_IDS) $(IDMA_ADD_FE_IDS) # iDMA paths IDMA_UTIL_DIR := $(IDMA_ROOT)/util IDMA_RTL_DIR := $(IDMA_ROOT)/target/rtl +IDMA_SW_DIR := $(IDMA_ROOT)/target/sw # job file IDMA_JOBS_JSON := jobs/jobs.json @@ -233,6 +234,21 @@ $(IDMA_HTML_DIR)/regs/idma_reg%d_reg/index.html: $(IDMA_HTML_DIR)/regs/idma_desc64_reg/index.html: $(PEAKRDL) html $(IDMA_FE_DIR)/desc64/idma_desc64_reg.rdl -o $(IDMA_HTML_DIR)/regs/idma_desc64_reg +# C header +$(IDMA_SW_DIR)/idma_reg%d_regs.h: + $(PEAKRDL) c-header $(IDMA_FE_DIR)/reg/idma_reg.rdl -o $@ \ + -P SysAddrWidth=$(call regwidth,$*) \ + -P NumDims=$(call dimension,$*) \ + -P Log2NumDims=$(call log2dimension,$(call dimension,$*)) + + +$(IDMA_SW_DIR)/idma_reg%d_raw_regs.h: + $(PEAKRDL) raw-header $(IDMA_FE_DIR)/reg/idma_reg.rdl -o $@ \ + --format c \ + -P SysAddrWidth=$(call regwidth,$*) \ + -P NumDims=$(call dimension,$*) \ + -P Log2NumDims=$(call log2dimension,$(call dimension,$*)) + idma_reg_clean: rm -rf $(IDMA_HTML_DIR)/regs rm -f $(IDMA_RTL_DIR)/*_reg_top.sv @@ -247,6 +263,11 @@ IDMA_RTL_ALL += $(foreach Y,$(IDMA_FE_REGS),$(IDMA_RTL_DIR)/idma_$Y_addrmap_ IDMA_RTL_ALL += $(foreach Y,$(IDMA_FE_REGS),$(IDMA_RTL_DIR)/idma_$Y_top.sv) IDMA_RTL_DOC_ALL += $(foreach Y,$(IDMA_FE_REGS),$(IDMA_HTML_DIR)/regs/idma_$Y_reg/index.html) +# C headers +IDMA_SW_ALL += $(foreach Y,$(IDMA_FE_IDS),$(IDMA_SW_DIR)/idma_$Y_regs.h) + +# C headers with the "raw-header" plugin +IDMA_SW_ALL += $(foreach Y,$(IDMA_FE_IDS),$(IDMA_SW_DIR)/idma_$Y_raw_regs.h) # --------------- # RTL assembly @@ -556,9 +577,9 @@ idma_nonfree_clean: # Misc Clean # -------------- -.PHONY: idma_clean_all idma_clean idma_misc_clean +.PHONY: idma_clean_all idma_clean idma_misc_clean idma_sw_clean -idma_clean_all idma_clean: idma_rtl_clean idma_reg_clean idma_pickle_clean idma_sim_clean idma_vcs_clean idma_verilator_clean idma_spinx_doc_clean idma_trace_clean +idma_clean_all idma_clean: idma_rtl_clean idma_reg_clean idma_pickle_clean idma_sim_clean idma_vcs_clean idma_verilator_clean idma_spinx_doc_clean idma_trace_clean idma_sw_clean idma_misc_clean: rm -rf scripts/__pycache__ @@ -569,6 +590,9 @@ idma_misc_clean: idma_nuke: idma_clean idma_nonfree_clean rm -rf .bender +idma_sw_clean: + rm -rf IDMA_SW_DIR/*.h + # -------------- # Phony Targets @@ -582,6 +606,8 @@ idma_pickle_all: $(IDMA_PICKLE_ALL) idma_hw_all: $(IDMA_FULL_RTL) $(IDMA_INCLUDE_ALL) $(IDMA_FULL_TB) $(IDMA_HJSON_ALL) $(IDMA_WAVE_ALL) +idma_sw_all: $(IDMA_SW_ALL) + idma_sim_all: $(IDMA_VCS_DIR)/compile.sh $(IDMA_VSIM_DIR)/compile.tcl idma_all: idma_hw_all idma_sim_all idma_doc_all idma_pickle_all diff --git a/pyproject.toml b/pyproject.toml index a2ccfcdb..5eb63a5d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,4 +20,5 @@ dependencies = [ "pylint", "peakrdl>=1.5.0", "peakrdl-rawheader>=0.2.4", + "peakrdl-cheader>=1.1.0", ] diff --git a/target/sw/.gitignore b/target/sw/.gitignore new file mode 100644 index 00000000..424c745c --- /dev/null +++ b/target/sw/.gitignore @@ -0,0 +1 @@ +*.h diff --git a/util/deploy.py b/util/deploy.py index e35bded8..2f2cb82a 100644 --- a/util/deploy.py +++ b/util/deploy.py @@ -13,6 +13,7 @@ # Repo configuration ORIGIN = 'origin' +GITIGNORE_FILES = ['target/rtl/.gitignore', 'target/sw/.gitignore'] # Comment added to gitignore GITIGNORE_COMMENT = '# Deactivated by deploy.py' @@ -58,14 +59,15 @@ def get_current_branch(): git_run('checkout', '-b', deploy_branch, current_branch) # selectively deactivate gitignore to check in generated files -with open('target/rtl/.gitignore', 'r', encoding='utf-8') as f: - content = f.read().split('\n')[:-1] - -if content[0] != GITIGNORE_COMMENT: - with open('target/rtl/.gitignore', 'w', encoding='utf-8') as f: - f.write(f'{GITIGNORE_COMMENT}\n') - for line in content: - f.write(f'# {line}\n') +for gitignore_fn in GITIGNORE_FILES: + with open(gitignore_fn, 'r', encoding='utf-8') as f: + content = f.read().split('\n')[:-1] + + if content[0] != GITIGNORE_COMMENT: + with open(gitignore_fn, 'w', encoding='utf-8') as f: + f.write(f'{GITIGNORE_COMMENT}\n') + for line in content: + f.write(f'# {line}\n') # add and commit files git_run('add', '.') diff --git a/uv.lock b/uv.lock index 9b68b293..43c66a9a 100644 --- a/uv.lock +++ b/uv.lock @@ -266,6 +266,7 @@ dependencies = [ { name = "hjson" }, { name = "mako" }, { name = "peakrdl" }, + { name = "peakrdl-cheader" }, { name = "peakrdl-rawheader" }, { name = "pre-commit" }, { name = "pylint" }, @@ -284,6 +285,7 @@ requires-dist = [ { name = "hjson" }, { name = "mako" }, { name = "peakrdl", specifier = ">=1.5.0" }, + { name = "peakrdl-cheader", specifier = ">=1.1.0" }, { name = "peakrdl-rawheader", specifier = ">=0.2.4" }, { name = "pre-commit" }, { name = "pylint" }, @@ -775,23 +777,23 @@ resolution-markers = [ "python_full_version < '3.12'", ] dependencies = [ - { name = "alabaster", marker = "python_full_version < '3.12'" }, - { name = "babel", marker = "python_full_version < '3.12'" }, - { name = "colorama", marker = "python_full_version < '3.12' and sys_platform == 'win32'" }, - { name = "docutils", marker = "python_full_version < '3.12'" }, - { name = "imagesize", marker = "python_full_version < '3.12'" }, - { name = "jinja2", marker = "python_full_version < '3.12'" }, - { name = "packaging", marker = "python_full_version < '3.12'" }, - { name = "pygments", marker = "python_full_version < '3.12'" }, - { name = "requests", marker = "python_full_version < '3.12'" }, - { name = "roman-numerals", marker = "python_full_version < '3.12'" }, - { name = "snowballstemmer", marker = "python_full_version < '3.12'" }, - { name = "sphinxcontrib-applehelp", marker = "python_full_version < '3.12'" }, - { name = "sphinxcontrib-devhelp", marker = "python_full_version < '3.12'" }, - { name = "sphinxcontrib-htmlhelp", marker = "python_full_version < '3.12'" }, - { name = "sphinxcontrib-jsmath", marker = "python_full_version < '3.12'" }, - { name = "sphinxcontrib-qthelp", marker = "python_full_version < '3.12'" }, - { name = "sphinxcontrib-serializinghtml", marker = "python_full_version < '3.12'" }, + { name = "alabaster" }, + { name = "babel" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "docutils" }, + { name = "imagesize" }, + { name = "jinja2" }, + { name = "packaging" }, + { name = "pygments" }, + { name = "requests" }, + { name = "roman-numerals" }, + { name = "snowballstemmer" }, + { name = "sphinxcontrib-applehelp" }, + { name = "sphinxcontrib-devhelp" }, + { name = "sphinxcontrib-htmlhelp" }, + { name = "sphinxcontrib-jsmath" }, + { name = "sphinxcontrib-qthelp" }, + { name = "sphinxcontrib-serializinghtml" }, ] sdist = { url = "https://files.pythonhosted.org/packages/42/50/a8c6ccc36d5eacdfd7913ddccd15a9cee03ecafc5ee2bc40e1f168d85022/sphinx-9.0.4.tar.gz", hash = "sha256:594ef59d042972abbc581d8baa577404abe4e6c3b04ef61bd7fc2acbd51f3fa3", size = 8710502, upload-time = "2025-12-04T07:45:27.343Z" } wheels = [ @@ -806,23 +808,23 @@ resolution-markers = [ "python_full_version >= '3.12'", ] dependencies = [ - { name = "alabaster", marker = "python_full_version >= '3.12'" }, - { name = "babel", marker = "python_full_version >= '3.12'" }, - { name = "colorama", marker = "python_full_version >= '3.12' and sys_platform == 'win32'" }, - { name = "docutils", marker = "python_full_version >= '3.12'" }, - { name = "imagesize", marker = "python_full_version >= '3.12'" }, - { name = "jinja2", marker = "python_full_version >= '3.12'" }, - { name = "packaging", marker = "python_full_version >= '3.12'" }, - { name = "pygments", marker = "python_full_version >= '3.12'" }, - { name = "requests", marker = "python_full_version >= '3.12'" }, - { name = "roman-numerals", marker = "python_full_version >= '3.12'" }, - { name = "snowballstemmer", marker = "python_full_version >= '3.12'" }, - { name = "sphinxcontrib-applehelp", marker = "python_full_version >= '3.12'" }, - { name = "sphinxcontrib-devhelp", marker = "python_full_version >= '3.12'" }, - { name = "sphinxcontrib-htmlhelp", marker = "python_full_version >= '3.12'" }, - { name = "sphinxcontrib-jsmath", marker = "python_full_version >= '3.12'" }, - { name = "sphinxcontrib-qthelp", marker = "python_full_version >= '3.12'" }, - { name = "sphinxcontrib-serializinghtml", marker = "python_full_version >= '3.12'" }, + { name = "alabaster" }, + { name = "babel" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "docutils" }, + { name = "imagesize" }, + { name = "jinja2" }, + { name = "packaging" }, + { name = "pygments" }, + { name = "requests" }, + { name = "roman-numerals" }, + { name = "snowballstemmer" }, + { name = "sphinxcontrib-applehelp" }, + { name = "sphinxcontrib-devhelp" }, + { name = "sphinxcontrib-htmlhelp" }, + { name = "sphinxcontrib-jsmath" }, + { name = "sphinxcontrib-qthelp" }, + { name = "sphinxcontrib-serializinghtml" }, ] sdist = { url = "https://files.pythonhosted.org/packages/cd/bd/f08eb0f4eed5c83f1ba2a3bd18f7745a2b1525fad70660a1c00224ec468a/sphinx-9.1.0.tar.gz", hash = "sha256:7741722357dd75f8190766926071fed3bdc211c74dd2d7d4df5404da95930ddb", size = 8718324, upload-time = "2025-12-31T15:09:27.646Z" } wheels = [ From 21f089cc29d44b123d7825e8248e4a9015848cd4 Mon Sep 17 00:00:00 2001 From: Georg Rutishauser Date: Thu, 16 Jul 2026 16:15:15 +0200 Subject: [PATCH 2/3] Regs/makefile: Fix `idma_sw_clean`, generate "unpacked" header - the PeakRDL `c-header` plugin generates structs with `__attribute__((__packed__))` which ensures proper packing of fields but can also cause the compiler to emit byte loads/stores to access 32-bit registers, which is definitely not what we want. The `unpacked` version of the C header has the attribute removed. - The `idma_sw_clean` target had a typo and didn't actually clean anything, this is fixed now. --- idma.mk | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/idma.mk b/idma.mk index bebcc422..7391be19 100644 --- a/idma.mk +++ b/idma.mk @@ -235,12 +235,16 @@ $(IDMA_HTML_DIR)/regs/idma_desc64_reg/index.html: $(PEAKRDL) html $(IDMA_FE_DIR)/desc64/idma_desc64_reg.rdl -o $(IDMA_HTML_DIR)/regs/idma_desc64_reg # C header -$(IDMA_SW_DIR)/idma_reg%d_regs.h: - $(PEAKRDL) c-header $(IDMA_FE_DIR)/reg/idma_reg.rdl -o $@ \ +$(IDMA_SW_DIR)/idma_reg%d_regs.h : + $(PEAKRDL) c-header $(IDMA_FE_DIR)/reg/idma_reg.rdl -i -o $@ \ -P SysAddrWidth=$(call regwidth,$*) \ -P NumDims=$(call dimension,$*) \ -P Log2NumDims=$(call log2dimension,$(call dimension,$*)) +$(IDMA_SW_DIR)/idma_reg%d_regs_unpacked.h : $(IDMA_SW_DIR)/idma_reg%d_regs.h +# with `packed` structs, the compiler may get confused and generate byte loads/stores to access fields. + sed -e "s/__attribute__ ((__packed__)) //" $^ > $@ + $(IDMA_SW_DIR)/idma_reg%d_raw_regs.h: $(PEAKRDL) raw-header $(IDMA_FE_DIR)/reg/idma_reg.rdl -o $@ \ @@ -265,6 +269,7 @@ IDMA_RTL_DOC_ALL += $(foreach Y,$(IDMA_FE_REGS),$(IDMA_HTML_DIR)/regs/idma_$Y_re # C headers IDMA_SW_ALL += $(foreach Y,$(IDMA_FE_IDS),$(IDMA_SW_DIR)/idma_$Y_regs.h) +IDMA_SW_ALL += $(foreach Y,$(IDMA_FE_IDS),$(IDMA_SW_DIR)/idma_$Y_regs_unpacked.h) # C headers with the "raw-header" plugin IDMA_SW_ALL += $(foreach Y,$(IDMA_FE_IDS),$(IDMA_SW_DIR)/idma_$Y_raw_regs.h) @@ -591,7 +596,7 @@ idma_nuke: idma_clean idma_nonfree_clean rm -rf .bender idma_sw_clean: - rm -rf IDMA_SW_DIR/*.h + rm -rf $(IDMA_SW_DIR)/*.h # -------------- From 935314e7727a7a925968f5e8b77371f8ad71c743 Mon Sep 17 00:00:00 2001 From: Georg Rutishauser Date: Thu, 30 Jul 2026 16:48:07 +0200 Subject: [PATCH 3/3] SW: Implement PR feedback --- idma.mk | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/idma.mk b/idma.mk index 7391be19..5977d88d 100644 --- a/idma.mk +++ b/idma.mk @@ -192,6 +192,10 @@ regwidth = $(word 1,$(subst _, ,$1)) dimension = $(word 2,$(subst _, ,$1)) log2dimension = $(shell echo $$(( $$( echo "obase=2;$$(($(1)-1))" | bc | wc -c ) - 1 )) ) +# Shared SPDX license header (raw-header takes plain text; c-header gets the //-prefixed variant) +IDMA_LICENSE := Copyright 2026 ETH Zurich and University of Bologna.\nSolderpad Hardware License, Version 0.51, see LICENSE for details.\nSPDX-License-Identifier: SHL-0.51 +IDMA_C_HDR_LIC := // $(subst \n,\n// ,$(IDMA_LICENSE))\n + $(IDMA_RTL_DIR)/idma_reg%d_reg_pkg.sv $(IDMA_RTL_DIR)/idma_reg%d_reg_top.sv $(IDMA_RTL_DIR)/idma_reg%d_addrmap_pkg.sv: $(PEAKRDL) regblock $(IDMA_FE_DIR)/reg/idma_reg.rdl -o $(IDMA_RTL_DIR) \ --default-reset arst_n --cpuif $(IDMA_REG_CPUIF) \ @@ -236,10 +240,12 @@ $(IDMA_HTML_DIR)/regs/idma_desc64_reg/index.html: # C header $(IDMA_SW_DIR)/idma_reg%d_regs.h : - $(PEAKRDL) c-header $(IDMA_FE_DIR)/reg/idma_reg.rdl -i -o $@ \ + $(PEAKRDL) c-header $(IDMA_FE_DIR)/reg/idma_reg.rdl -o $@ \ + -b ltoh --type-style hier --rename idma_reg$*d \ -P SysAddrWidth=$(call regwidth,$*) \ -P NumDims=$(call dimension,$*) \ -P Log2NumDims=$(call log2dimension,$(call dimension,$*)) + sed -i '1i$(IDMA_C_HDR_LIC)' $@ $(IDMA_SW_DIR)/idma_reg%d_regs_unpacked.h : $(IDMA_SW_DIR)/idma_reg%d_regs.h # with `packed` structs, the compiler may get confused and generate byte loads/stores to access fields. @@ -249,10 +255,23 @@ $(IDMA_SW_DIR)/idma_reg%d_regs_unpacked.h : $(IDMA_SW_DIR)/idma_reg%d_regs.h $(IDMA_SW_DIR)/idma_reg%d_raw_regs.h: $(PEAKRDL) raw-header $(IDMA_FE_DIR)/reg/idma_reg.rdl -o $@ \ --format c \ + --license_str="$(IDMA_LICENSE)" \ -P SysAddrWidth=$(call regwidth,$*) \ -P NumDims=$(call dimension,$*) \ -P Log2NumDims=$(call log2dimension,$(call dimension,$*)) + +$(IDMA_SW_DIR)/idma_desc64_regs.h: + $(PEAKRDL) c-header $(IDMA_FE_DIR)/desc64/idma_desc64_reg.rdl -o $@ \ + -b ltoh --type-style hier --rename idma_desc64 + sed -i '1i$(IDMA_C_HDR_LIC)' $@ +$(IDMA_SW_DIR)/idma_desc64_regs_unpacked.h: $(IDMA_SW_DIR)/idma_desc64_regs.h + sed -e "s/__attribute__ ((__packed__)) //" $< > $@ +$(IDMA_SW_DIR)/idma_desc64_raw_regs.h: + $(PEAKRDL) raw-header $(IDMA_FE_DIR)/desc64/idma_desc64_reg.rdl -o $@ \ + --format c --base_name idma_desc64 \ + --license_str="$(IDMA_LICENSE)" + idma_reg_clean: rm -rf $(IDMA_HTML_DIR)/regs rm -f $(IDMA_RTL_DIR)/*_reg_top.sv @@ -268,11 +287,11 @@ IDMA_RTL_ALL += $(foreach Y,$(IDMA_FE_REGS),$(IDMA_RTL_DIR)/idma_$Y_top.sv) IDMA_RTL_DOC_ALL += $(foreach Y,$(IDMA_FE_REGS),$(IDMA_HTML_DIR)/regs/idma_$Y_reg/index.html) # C headers -IDMA_SW_ALL += $(foreach Y,$(IDMA_FE_IDS),$(IDMA_SW_DIR)/idma_$Y_regs.h) -IDMA_SW_ALL += $(foreach Y,$(IDMA_FE_IDS),$(IDMA_SW_DIR)/idma_$Y_regs_unpacked.h) +IDMA_SW_ALL += $(foreach Y,$(IDMA_FE_REGS),$(IDMA_SW_DIR)/idma_$Y_regs.h) +IDMA_SW_ALL += $(foreach Y,$(IDMA_FE_REGS),$(IDMA_SW_DIR)/idma_$Y_regs_unpacked.h) # C headers with the "raw-header" plugin -IDMA_SW_ALL += $(foreach Y,$(IDMA_FE_IDS),$(IDMA_SW_DIR)/idma_$Y_raw_regs.h) +IDMA_SW_ALL += $(foreach Y,$(IDMA_FE_REGS),$(IDMA_SW_DIR)/idma_$Y_raw_regs.h) # --------------- # RTL assembly