ConfiguredArchitecture#multi_xlen_in_mode? (tools/ruby-gems/udb/lib/udb/cfg_arch.rb:103) answers "can the effective XLEN change in this mode" for M, S, U, VS and VU, with explicit handling for unconfigured, partially configured and fully configured architectures. CsrField#dynamic_location? (csr_field.rb:380) uses it, over Csr#modes_with_access.
Csr answers the same question itself, from the length token, in five places: dynamic_length?, max_length, length_cond32, length_cond64 and length_pretty. None of the five considers U or VU mode.
Everything below is on main at 858ae306, reproduced with the config at the end.
1. A register and its own fields disagree
In a config where the only mutable mode XLEN is UXLEN, 8 of 396 CSRs report dynamic_length? == false while at least one of their fields reports dynamic_location? == true:
ssp, jvt, vl, vlenb, vstart, vtype, vxrm, vxsat
All eight are priv_mode: U, so modes_with_access returns ["M", "S", "U", "VS", "VU"]. The field asks about five modes; the register asks about three.
The conditions that get emitted are wrong in U-mode:
ssp and jvt are length: XLEN, and length_cond32 produces
(priv_mode() == PrivilegeMode::M && CSR[misa].MXL == 0) || (priv_mode() == PrivilegeMode::S && CSR[mstatus].SXL == 0) || (priv_mode() == PrivilegeMode::VS && CSR[hstatus].VSXL == 0).
Executing in U-mode every disjunct is false regardless of mstatus.UXL.
vl, vlenb, vstart, vtype, vxrm, vxsat are length: MXLEN, and length_cond32 produces CSR[misa].MXL == 0, which is MXLEN for a register whose width follows the current mode.
Those strings reach backends/cfg_html_doc/templates/csr.adoc.erb, backends/portfolio/templates/csr_appendix.adoc.erb, backends/prm_pdf/templates/csr.adoc.erb, tools/ruby-gems/udb-gen/templates/common/csr.adoc.erb and tools/ruby-gems/udb-gen/templates/manual/csr.adoc.erb.
2. max_length tests for the multiply extension where it means M-mode
The XLEN branch of max_length opens with
if cfg_arch.possible_extensions.map(&:name).include?("M")
commented as "must always have M-mode". spec/std/isa/ext/M.yaml is Integer multiply and divide; machine mode is Sm. cfgs/qc_iu.yaml lists both as separate extensions.
Taking the config below and changing one thing, whether M is prohibited:
| prohibited |
max_length for the 9 length: XLEN CSRs |
S, H |
all return 64 |
S, H, M |
all raise RuntimeError: Unexpected from csr.rb:335 |
The nine are hcontext, jvt, mscontext, scontext, ssp, tdata1, tdata2, tdata3, tselect. A core without integer multiply is ordinary, and it cannot compute the width of tselect.
3. UXLEN and VUXLEN cannot be expressed
spec/std/isa/param/UXLEN.yaml and VUXLEN.yaml both exist, and config.rb:341 declares MODE_XLEN_PARAMS = %w[UXLEN SXLEN VSXLEN VUXLEN]. But spec/schemas/csr_schema.json allows length to be only [32, 64, "MXLEN", "SXLEN", "VSXLEN", "XLEN"], and csr.rb carries seven raise "Unexpected length" sites. A CSR cannot say its width follows U-mode.
Of the 76 CSRs with priv_mode: U, 67 carry a fixed 32 or 64 and nine carry a mode-relative length. Those nine split two ways: seven say length: MXLEN (vcsr, vl, vlenb, vstart, vtype, vxrm, vxsat) and two say length: XLEN (jvt, ssp). The schema describes XLEN as "the effective XLEN in the current execution mode", so those two groups answer the same question differently.
Reproducer
# repro.yaml
---
$schema: config_schema.json#
kind: architecture configuration
type: partially configured
name: uxl_only
description: RV64, only UXLEN mutable, S and H prohibited
params:
MXLEN: 64
UXLEN: [32, 64]
mandatory_extensions:
- name: "I"
version: ">= 0"
- name: "Sm"
version: ">= 0"
- name: "U"
version: ">= 0"
prohibited_extensions:
- name: "S"
version: ">= 0"
- name: "H"
version: ">= 0"
cfg_arch = resolver.cfg_arch_for(Pathname.new("repro.yaml"))
cfg_arch.multi_xlen_in_mode?("U") # => true
cfg_arch.possible_xlens # => [32, 64]
cfg_arch.csrs.select { |c|
c.dynamic_length? == false && c.fields.any?(&:dynamic_location?)
}.map(&:name).sort
# => ["jvt", "ssp", "vl", "vlenb", "vstart", "vtype", "vxrm", "vxsat"]
Adding M to prohibited_extensions turns every max_length call on a length: XLEN CSR into a RuntimeError.
Question before a fix
Is XLEN intended to mean the effective XLEN of whichever mode is executing, as the schema description says? If so, the seven vector CSRs carrying length: MXLEN are mis-tagged, and UXLEN/VUXLEN never need to enter the enum. If not, the enum needs them, the way MODE_XLEN_PARAMS already assumes.
The tooling fix looks the same either way: have Csr ask multi_xlen_in_mode? over modes_with_access instead of keeping a parallel implementation, which would also remove the condition string that is currently written out three times. The data change depends on the answer, so I would keep it to a separate PR.
ConfiguredArchitecture#multi_xlen_in_mode?(tools/ruby-gems/udb/lib/udb/cfg_arch.rb:103) answers "can the effective XLEN change in this mode" forM,S,U,VSandVU, with explicit handling for unconfigured, partially configured and fully configured architectures.CsrField#dynamic_location?(csr_field.rb:380) uses it, overCsr#modes_with_access.Csranswers the same question itself, from thelengthtoken, in five places:dynamic_length?,max_length,length_cond32,length_cond64andlength_pretty. None of the five considers U or VU mode.Everything below is on
mainat858ae306, reproduced with the config at the end.1. A register and its own fields disagree
In a config where the only mutable mode XLEN is
UXLEN, 8 of 396 CSRs reportdynamic_length? == falsewhile at least one of their fields reportsdynamic_location? == true:ssp,jvt,vl,vlenb,vstart,vtype,vxrm,vxsatAll eight are
priv_mode: U, somodes_with_accessreturns["M", "S", "U", "VS", "VU"]. The field asks about five modes; the register asks about three.The conditions that get emitted are wrong in U-mode:
sspandjvtarelength: XLEN, andlength_cond32produces(priv_mode() == PrivilegeMode::M && CSR[misa].MXL == 0) || (priv_mode() == PrivilegeMode::S && CSR[mstatus].SXL == 0) || (priv_mode() == PrivilegeMode::VS && CSR[hstatus].VSXL == 0).Executing in U-mode every disjunct is false regardless of
mstatus.UXL.vl,vlenb,vstart,vtype,vxrm,vxsatarelength: MXLEN, andlength_cond32producesCSR[misa].MXL == 0, which is MXLEN for a register whose width follows the current mode.Those strings reach
backends/cfg_html_doc/templates/csr.adoc.erb,backends/portfolio/templates/csr_appendix.adoc.erb,backends/prm_pdf/templates/csr.adoc.erb,tools/ruby-gems/udb-gen/templates/common/csr.adoc.erbandtools/ruby-gems/udb-gen/templates/manual/csr.adoc.erb.2.
max_lengthtests for the multiply extension where it means M-modeThe
XLENbranch ofmax_lengthopens withcommented as "must always have M-mode".
spec/std/isa/ext/M.yamlis Integer multiply and divide; machine mode isSm.cfgs/qc_iu.yamllists both as separate extensions.Taking the config below and changing one thing, whether
Mis prohibited:max_lengthfor the 9length: XLENCSRsS,H64S,H,MRuntimeError: Unexpectedfromcsr.rb:335The nine are
hcontext,jvt,mscontext,scontext,ssp,tdata1,tdata2,tdata3,tselect. A core without integer multiply is ordinary, and it cannot compute the width oftselect.3.
UXLENandVUXLENcannot be expressedspec/std/isa/param/UXLEN.yamlandVUXLEN.yamlboth exist, andconfig.rb:341declaresMODE_XLEN_PARAMS = %w[UXLEN SXLEN VSXLEN VUXLEN]. Butspec/schemas/csr_schema.jsonallowslengthto be only[32, 64, "MXLEN", "SXLEN", "VSXLEN", "XLEN"], andcsr.rbcarries sevenraise "Unexpected length"sites. A CSR cannot say its width follows U-mode.Of the 76 CSRs with
priv_mode: U, 67 carry a fixed32or64and nine carry a mode-relative length. Those nine split two ways: seven saylength: MXLEN(vcsr,vl,vlenb,vstart,vtype,vxrm,vxsat) and two saylength: XLEN(jvt,ssp). The schema describesXLENas "the effective XLEN in the current execution mode", so those two groups answer the same question differently.Reproducer
Adding
Mtoprohibited_extensionsturns everymax_lengthcall on alength: XLENCSR into aRuntimeError.Question before a fix
Is
XLENintended to mean the effective XLEN of whichever mode is executing, as the schema description says? If so, the seven vector CSRs carryinglength: MXLENare mis-tagged, andUXLEN/VUXLENnever need to enter the enum. If not, the enum needs them, the wayMODE_XLEN_PARAMSalready assumes.The tooling fix looks the same either way: have
Csraskmulti_xlen_in_mode?overmodes_with_accessinstead of keeping a parallel implementation, which would also remove the condition string that is currently written out three times. The data change depends on the answer, so I would keep it to a separate PR.