udb 0.1.9 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (275) hide show
  1. checksums.yaml +4 -4
  2. data/.data/cfgs/example_rv64_with_overlay.yaml +5 -2
  3. data/.data/cfgs/mc100-32-full-example.yaml +1 -0
  4. data/.data/cfgs/profile/README.adoc +10 -0
  5. data/.data/cfgs/profile/RVA20S64.yaml +26 -6
  6. data/.data/cfgs/profile/RVA20U64.yaml +18 -4
  7. data/.data/cfgs/profile/RVA22S64.yaml +27 -7
  8. data/.data/cfgs/profile/RVA22U64.yaml +18 -4
  9. data/.data/cfgs/profile/RVA23S64.yaml +61 -7
  10. data/.data/cfgs/profile/RVA23U64.yaml +36 -4
  11. data/.data/cfgs/profile/RVB23S64.yaml +27 -7
  12. data/.data/cfgs/profile/RVB23U64.yaml +18 -4
  13. data/.data/cfgs/profile/RVI20U32.yaml +10 -4
  14. data/.data/cfgs/profile/RVI20U64.yaml +10 -4
  15. data/.data/cfgs/qc_iu.yaml +4 -1
  16. data/.data/cfgs/rv32-riscv-tests.yaml +2 -1
  17. data/.data/cfgs/rv32-vector.yaml +2 -1
  18. data/.data/cfgs/rv64-riscv-tests.yaml +2 -1
  19. data/.data/cfgs/rv64-vector.yaml +2 -1
  20. data/.data/spec/custom/isa/qc_iu/csr/Smrnmi/mnepc.yaml +17 -0
  21. data/.data/spec/custom/isa/qc_iu/csr/Xqccmi/qc.itba.yaml +45 -0
  22. data/.data/spec/custom/isa/qc_iu/csr/Xqccmi/qc.itdec.yaml +39 -0
  23. data/.data/spec/custom/isa/qc_iu/csr/jvt.yaml +11 -0
  24. data/.data/spec/custom/isa/qc_iu/csr/mepc.yaml +16 -0
  25. data/.data/spec/custom/isa/qc_iu/ext/Xqccmi.yaml +219 -0
  26. data/.data/spec/custom/isa/qc_iu/ext/Xqccmt.yaml +127 -0
  27. data/.data/spec/custom/isa/qc_iu/inst/Xqccmi/qc.cm.ilut.yaml +153 -0
  28. data/.data/spec/custom/isa/qc_iu/inst/Xqccmt/qc.cm.jalt.yaml +84 -0
  29. data/.data/spec/custom/isa/qc_iu/inst/Xqccmt/qc.cm.jt.yaml +60 -0
  30. data/.data/spec/custom/isa/qc_iu/isa/globals.isa +112 -0
  31. data/.data/spec/schemas/config_schema.json +219 -26
  32. data/.data/spec/schemas/csr_schema.json +0 -6
  33. data/.data/spec/schemas/ext_schema.json +80 -24
  34. data/.data/spec/schemas/inst_schema.json +0 -3
  35. data/.data/spec/schemas/profile_release_schema.json +1 -1
  36. data/.data/spec/schemas/profile_schema.json +0 -3
  37. data/.data/spec/schemas/register_file_schema.json +8 -3
  38. data/.data/spec/schemas/schema_defs.json +8 -27
  39. data/.data/spec/std/isa/csr/I/pmpcfg0.yaml +8 -8
  40. data/.data/spec/std/isa/csr/I/pmpcfg1.yaml +4 -4
  41. data/.data/spec/std/isa/csr/I/pmpcfg10.yaml +8 -8
  42. data/.data/spec/std/isa/csr/I/pmpcfg11.yaml +4 -4
  43. data/.data/spec/std/isa/csr/I/pmpcfg12.yaml +8 -8
  44. data/.data/spec/std/isa/csr/I/pmpcfg13.yaml +4 -4
  45. data/.data/spec/std/isa/csr/I/pmpcfg14.yaml +8 -8
  46. data/.data/spec/std/isa/csr/I/pmpcfg15.yaml +4 -4
  47. data/.data/spec/std/isa/csr/I/pmpcfg2.yaml +8 -8
  48. data/.data/spec/std/isa/csr/I/pmpcfg3.yaml +4 -4
  49. data/.data/spec/std/isa/csr/I/pmpcfg4.yaml +8 -8
  50. data/.data/spec/std/isa/csr/I/pmpcfg5.yaml +4 -4
  51. data/.data/spec/std/isa/csr/I/pmpcfg6.yaml +8 -8
  52. data/.data/spec/std/isa/csr/I/pmpcfg7.yaml +4 -4
  53. data/.data/spec/std/isa/csr/I/pmpcfg8.yaml +8 -8
  54. data/.data/spec/std/isa/csr/I/pmpcfg9.yaml +4 -4
  55. data/.data/spec/std/isa/csr/I/pmpcfgN.layout +1 -1
  56. data/.data/spec/std/isa/csr/Zicntr/mcountinhibit.layout +6 -2
  57. data/.data/spec/std/isa/csr/Zicntr/mcountinhibit.yaml +6 -2
  58. data/.data/spec/std/isa/csr/hstatus.yaml +16 -0
  59. data/.data/spec/std/isa/csr/mcycleh.yaml +1 -1
  60. data/.data/spec/std/isa/csr/misa.yaml +0 -12
  61. data/.data/spec/std/isa/csr/mstatus.yaml +38 -0
  62. data/.data/spec/std/isa/csr/mstatush.yaml +17 -15
  63. data/.data/spec/std/isa/csr/senvcfg.yaml +16 -0
  64. data/.data/spec/std/isa/csr/sstatus.yaml +12 -0
  65. data/.data/spec/std/isa/csr/vsstatus.yaml +24 -0
  66. data/.data/spec/std/isa/ext/A.yaml +5 -7
  67. data/.data/spec/std/isa/ext/S.yaml +12 -0
  68. data/.data/spec/std/isa/ext/Smpmpmt.yaml +52 -0
  69. data/.data/spec/std/isa/ext/Sv32.yaml +7 -19
  70. data/.data/spec/std/isa/ext/Sv39.yaml +7 -19
  71. data/.data/spec/std/isa/ext/Sv48.yaml +4 -20
  72. data/.data/spec/std/isa/ext/Sv57.yaml +4 -20
  73. data/.data/spec/std/isa/ext/Svukte.yaml +71 -0
  74. data/.data/spec/std/isa/ext/Zawrs.yaml +1 -1
  75. data/.data/spec/std/isa/ext/Zihpm.yaml +0 -12
  76. data/.data/spec/std/isa/inst/C/c.addi.yaml +1 -0
  77. data/.data/spec/std/isa/inst/C/c.addi16sp.yaml +1 -0
  78. data/.data/spec/std/isa/inst/C/c.addiw.yaml +1 -0
  79. data/.data/spec/std/isa/inst/C/c.andi.yaml +1 -0
  80. data/.data/spec/std/isa/inst/C/c.ldsp.yaml +1 -1
  81. data/.data/spec/std/isa/inst/C/c.li.yaml +1 -0
  82. data/.data/spec/std/isa/inst/C/c.lui.yaml +1 -0
  83. data/.data/spec/std/isa/inst/C/c.mv.yaml +1 -1
  84. data/.data/spec/std/isa/inst/C/c.sdsp.yaml +1 -1
  85. data/.data/spec/std/isa/inst/D/fsgnj.d.yaml +3 -0
  86. data/.data/spec/std/isa/inst/D/fsgnjn.d.yaml +3 -0
  87. data/.data/spec/std/isa/inst/D/fsgnjx.d.yaml +3 -0
  88. data/.data/spec/std/isa/inst/F/fadd.s.yaml +5 -5
  89. data/.data/spec/std/isa/inst/F/fclass.s.yaml +2 -2
  90. data/.data/spec/std/isa/inst/F/fcvt.l.s.yaml +1 -1
  91. data/.data/spec/std/isa/inst/F/fcvt.lu.s.yaml +1 -1
  92. data/.data/spec/std/isa/inst/F/fcvt.s.l.yaml +1 -1
  93. data/.data/spec/std/isa/inst/F/fcvt.s.lu.yaml +1 -1
  94. data/.data/spec/std/isa/inst/F/fcvt.s.w.yaml +1 -1
  95. data/.data/spec/std/isa/inst/F/fcvt.s.wu.yaml +1 -1
  96. data/.data/spec/std/isa/inst/F/fcvt.w.s.yaml +1 -1
  97. data/.data/spec/std/isa/inst/F/fcvt.wu.s.yaml +1 -1
  98. data/.data/spec/std/isa/inst/F/fdiv.s.yaml +1 -1
  99. data/.data/spec/std/isa/inst/F/feq.s.yaml +2 -2
  100. data/.data/spec/std/isa/inst/F/fle.s.yaml +2 -2
  101. data/.data/spec/std/isa/inst/F/fleq.s.yaml +2 -2
  102. data/.data/spec/std/isa/inst/F/flt.s.yaml +2 -2
  103. data/.data/spec/std/isa/inst/F/fltq.s.yaml +2 -2
  104. data/.data/spec/std/isa/inst/F/flw.yaml +2 -2
  105. data/.data/spec/std/isa/inst/F/fmadd.s.yaml +1 -1
  106. data/.data/spec/std/isa/inst/F/fmax.s.yaml +6 -6
  107. data/.data/spec/std/isa/inst/F/fmin.s.yaml +6 -6
  108. data/.data/spec/std/isa/inst/F/fmsub.s.yaml +1 -1
  109. data/.data/spec/std/isa/inst/F/fmul.s.yaml +1 -1
  110. data/.data/spec/std/isa/inst/F/fmv.w.x.yaml +2 -2
  111. data/.data/spec/std/isa/inst/F/fmv.x.w.yaml +1 -1
  112. data/.data/spec/std/isa/inst/F/fnmadd.s.yaml +2 -2
  113. data/.data/spec/std/isa/inst/F/fnmsub.s.yaml +1 -1
  114. data/.data/spec/std/isa/inst/F/fsgnj.s.yaml +4 -4
  115. data/.data/spec/std/isa/inst/F/fsgnjn.s.yaml +3 -3
  116. data/.data/spec/std/isa/inst/F/fsgnjx.s.yaml +4 -4
  117. data/.data/spec/std/isa/inst/F/fsqrt.s.yaml +1 -1
  118. data/.data/spec/std/isa/inst/F/fsub.s.yaml +1 -1
  119. data/.data/spec/std/isa/inst/F/fsw.yaml +1 -1
  120. data/.data/spec/std/isa/inst/I/addi.yaml +1 -1
  121. data/.data/spec/std/isa/inst/I/addiw.yaml +1 -1
  122. data/.data/spec/std/isa/inst/I/andi.yaml +1 -1
  123. data/.data/spec/std/isa/inst/I/beq.yaml +1 -1
  124. data/.data/spec/std/isa/inst/I/bge.yaml +4 -2
  125. data/.data/spec/std/isa/inst/I/bgeu.yaml +3 -0
  126. data/.data/spec/std/isa/inst/I/blt.yaml +4 -2
  127. data/.data/spec/std/isa/inst/I/bltu.yaml +3 -0
  128. data/.data/spec/std/isa/inst/I/bne.yaml +1 -1
  129. data/.data/spec/std/isa/inst/I/slt.yaml +2 -2
  130. data/.data/spec/std/isa/inst/I/sltiu.yaml +1 -1
  131. data/.data/spec/std/isa/inst/I/sltu.yaml +1 -1
  132. data/.data/spec/std/isa/inst/I/sub.yaml +1 -1
  133. data/.data/spec/std/isa/inst/I/subw.yaml +1 -1
  134. data/.data/spec/std/isa/inst/I/xori.yaml +1 -1
  135. data/.data/spec/std/isa/inst/M/mul.yaml +0 -19
  136. data/.data/spec/std/isa/inst/Q/fsgnj.q.yaml +1 -1
  137. data/.data/spec/std/isa/inst/S/sret.yaml +3 -1
  138. data/.data/spec/std/isa/inst/V/vadd.vv.yaml +1 -5
  139. data/.data/spec/std/isa/inst/V/vfsgnjn.vv.yaml +3 -0
  140. data/.data/spec/std/isa/inst/V/vfsgnjx.vv.yaml +3 -0
  141. data/.data/spec/std/isa/inst/V/vl1re8.v.yaml +3 -0
  142. data/.data/spec/std/isa/inst/V/vl2re8.v.yaml +3 -0
  143. data/.data/spec/std/isa/inst/V/vl4re8.v.yaml +3 -0
  144. data/.data/spec/std/isa/inst/V/vl8re8.v.yaml +3 -0
  145. data/.data/spec/std/isa/inst/V/vle8.v.yaml +3 -8
  146. data/.data/spec/std/isa/inst/V/vmand.mm.yaml +3 -0
  147. data/.data/spec/std/isa/inst/V/vmfle.vv.yaml +3 -0
  148. data/.data/spec/std/isa/inst/V/vmflt.vv.yaml +3 -0
  149. data/.data/spec/std/isa/inst/V/vmnand.mm.yaml +3 -0
  150. data/.data/spec/std/isa/inst/V/vmsgt.vi.yaml +3 -0
  151. data/.data/spec/std/isa/inst/V/vmsgtu.vi.yaml +3 -0
  152. data/.data/spec/std/isa/inst/V/vmsle.vi.yaml +3 -0
  153. data/.data/spec/std/isa/inst/V/vmsle.vv.yaml +3 -0
  154. data/.data/spec/std/isa/inst/V/vmsleu.vi.yaml +3 -0
  155. data/.data/spec/std/isa/inst/V/vmsleu.vv.yaml +3 -0
  156. data/.data/spec/std/isa/inst/V/vmslt.vv.yaml +3 -0
  157. data/.data/spec/std/isa/inst/V/vmsltu.vv.yaml +3 -0
  158. data/.data/spec/std/isa/inst/V/vmv.v.i.yaml +2 -13
  159. data/.data/spec/std/isa/inst/V/vmv.x.s.yaml +1 -1
  160. data/.data/spec/std/isa/inst/V/vmxnor.mm.yaml +3 -0
  161. data/.data/spec/std/isa/inst/V/vmxor.mm.yaml +3 -0
  162. data/.data/spec/std/isa/inst/V/vnsrl.wx.yaml +3 -0
  163. data/.data/spec/std/isa/inst/V/vrsub.vx.yaml +3 -0
  164. data/.data/spec/std/isa/inst/V/vse8.v.yaml +3 -4
  165. data/.data/spec/std/isa/inst/V/vwadd.vx.yaml +3 -0
  166. data/.data/spec/std/isa/inst/V/vwaddu.vx.yaml +3 -0
  167. data/.data/spec/std/isa/inst/V/vxor.vi.yaml +4 -0
  168. data/.data/spec/std/isa/inst/Zalasr/lSIZE.AQRL.layout +40 -5
  169. data/.data/spec/std/isa/inst/Zalasr/lb.aq.yaml +17 -1
  170. data/.data/spec/std/isa/inst/Zalasr/lb.aqrl.yaml +17 -1
  171. data/.data/spec/std/isa/inst/Zalasr/ld.aq.yaml +17 -1
  172. data/.data/spec/std/isa/inst/Zalasr/ld.aqrl.yaml +17 -1
  173. data/.data/spec/std/isa/inst/Zalasr/lh.aq.yaml +17 -1
  174. data/.data/spec/std/isa/inst/Zalasr/lh.aqrl.yaml +17 -1
  175. data/.data/spec/std/isa/inst/Zalasr/lw.aq.yaml +17 -1
  176. data/.data/spec/std/isa/inst/Zalasr/lw.aqrl.yaml +17 -1
  177. data/.data/spec/std/isa/inst/Zalasr/sSIZE.AQRL.layout +46 -5
  178. data/.data/spec/std/isa/inst/Zalasr/sb.aqrl.yaml +16 -1
  179. data/.data/spec/std/isa/inst/Zalasr/sb.rl.yaml +16 -1
  180. data/.data/spec/std/isa/inst/Zalasr/sd.aqrl.yaml +16 -1
  181. data/.data/spec/std/isa/inst/Zalasr/sd.rl.yaml +16 -1
  182. data/.data/spec/std/isa/inst/Zalasr/sh.aqrl.yaml +16 -1
  183. data/.data/spec/std/isa/inst/Zalasr/sh.rl.yaml +16 -1
  184. data/.data/spec/std/isa/inst/Zalasr/sw.aqrl.yaml +16 -1
  185. data/.data/spec/std/isa/inst/Zalasr/sw.rl.yaml +16 -1
  186. data/.data/spec/std/isa/inst/Zbkb/packw.yaml +1 -1
  187. data/.data/spec/std/isa/inst/Zcd/c.fld.yaml +1 -1
  188. data/.data/spec/std/isa/inst/Zcd/c.fldsp.yaml +1 -1
  189. data/.data/spec/std/isa/inst/Zcd/c.fsdsp.yaml +1 -1
  190. data/.data/spec/std/isa/inst/Zcf/c.flwsp.yaml +1 -1
  191. data/.data/spec/std/isa/inst/Zcf/c.fswsp.yaml +1 -1
  192. data/.data/spec/std/isa/inst/Zcmp/cm.pop.yaml +1 -1
  193. data/.data/spec/std/isa/inst/Zcmp/cm.popret.yaml +1 -1
  194. data/.data/spec/std/isa/inst/Zcmp/cm.popretz.yaml +1 -1
  195. data/.data/spec/std/isa/inst/Zcmp/cm.push.yaml +2 -3
  196. data/.data/spec/std/isa/inst/Zfa/fround.s.yaml +1 -1
  197. data/.data/spec/std/isa/inst/Zfh/fcvt.h.s.yaml +6 -6
  198. data/.data/spec/std/isa/inst/Zfh/fcvt.s.h.yaml +5 -5
  199. data/.data/spec/std/isa/inst/Zfh/flh.yaml +1 -1
  200. data/.data/spec/std/isa/inst/Zfh/fmv.h.x.yaml +1 -1
  201. data/.data/spec/std/isa/inst/Zfh/fmv.x.h.yaml +1 -1
  202. data/.data/spec/std/isa/inst/Zfh/fsh.yaml +1 -1
  203. data/.data/spec/std/isa/inst/Zicsr/csrrc.yaml +1 -1
  204. data/.data/spec/std/isa/inst/Zicsr/csrrci.yaml +1 -1
  205. data/.data/spec/std/isa/inst/Zicsr/csrrs.yaml +2 -2
  206. data/.data/spec/std/isa/inst/Zicsr/csrrsi.yaml +1 -1
  207. data/.data/spec/std/isa/inst/Zicsr/csrrw.yaml +1 -1
  208. data/.data/spec/std/isa/inst/Zicsr/csrrwi.yaml +1 -1
  209. data/.data/spec/std/isa/isa/builtin_functions.idl +17 -0
  210. data/.data/spec/std/isa/isa/fp.idl +1 -5
  211. data/.data/spec/std/isa/isa/globals.isa +45 -14
  212. data/.data/spec/std/isa/isa/vec.idl +1 -2
  213. data/.data/spec/std/isa/manual_version/isa/20240411/isa_20240411.yaml +5 -5
  214. data/.data/spec/std/isa/param/COUNTINHIBIT_EN.yaml +8 -2
  215. data/.data/spec/std/isa/param/JVT_BASE_MASK.yaml +1 -1
  216. data/.data/spec/std/isa/param/MCOUNTINHIBIT_IMPLEMENTED.yaml +25 -0
  217. data/.data/spec/std/isa/param/MTVEC_MODES.yaml +10 -3
  218. data/.data/spec/std/isa/param/VLEN.yaml +2 -0
  219. data/.data/spec/std/isa/profile/RVA20S64.yaml +11 -4
  220. data/.data/spec/std/isa/profile/RVA20U64.yaml +14 -5
  221. data/.data/spec/std/isa/profile/RVA22S64.yaml +14 -3
  222. data/.data/spec/std/isa/profile/RVA22U64.yaml +8 -1
  223. data/.data/spec/std/isa/profile/RVA23S64.yaml +13 -0
  224. data/.data/spec/std/isa/profile/RVA23U64.yaml +15 -1
  225. data/.data/spec/std/isa/profile/RVB23S64.yaml +15 -3
  226. data/.data/spec/std/isa/profile/RVB23U64.yaml +8 -1
  227. data/.data/spec/std/isa/profile/RVI20U32.yaml +8 -1
  228. data/.data/spec/std/isa/profile/RVI20U64.yaml +7 -0
  229. data/.data/spec/std/isa/register_file/F.yaml +3 -2
  230. data/.data/spec/std/isa/register_file/V.yaml +2 -2
  231. data/.data/spec/std/isa/register_file/X.yaml +2 -1
  232. data/lib/udb/architecture.rb +4 -25
  233. data/lib/udb/cfg_arch.rb +171 -59
  234. data/lib/udb/cli.rb +10 -1
  235. data/lib/udb/condition.rb +38 -37
  236. data/lib/udb/config.rb +72 -6
  237. data/lib/udb/logic.rb +29 -56
  238. data/lib/udb/obj/csr.rb +23 -5
  239. data/lib/udb/obj/csr_field.rb +36 -21
  240. data/lib/udb/obj/database_obj.rb +2 -5
  241. data/lib/udb/obj/extension.rb +0 -3
  242. data/lib/udb/obj/instruction.rb +1 -4
  243. data/lib/udb/obj/portfolio.rb +75 -20
  244. data/lib/udb/obj/profile.rb +0 -4
  245. data/lib/udb/obj/register_file.rb +63 -2
  246. data/lib/udb/portfolio_design.rb +3 -6
  247. data/lib/udb/resolver.rb +84 -23
  248. data/lib/udb/version.rb +1 -1
  249. data/lib/udb/version_spec.rb +8 -0
  250. data/lib/udb/z3.rb +23 -0
  251. data/lib/udb.rb +0 -3
  252. metadata +25 -37
  253. data/.data/cfgs/profile/RVA23M64.yaml +0 -159
  254. data/.data/cfgs/profile/RVB23M64.yaml +0 -149
  255. data/.data/spec/schemas/proc_cert_class_schema.json +0 -35
  256. data/.data/spec/schemas/proc_cert_model_schema.json +0 -336
  257. data/.data/spec/std/isa/proc_cert_class/AC.yaml +0 -13
  258. data/.data/spec/std/isa/proc_cert_class/MC.yaml +0 -13
  259. data/.data/spec/std/isa/proc_cert_class/RVI.yaml +0 -16
  260. data/.data/spec/std/isa/proc_cert_model/AC100.yaml +0 -72
  261. data/.data/spec/std/isa/proc_cert_model/AC200.yaml +0 -58
  262. data/.data/spec/std/isa/proc_cert_model/MC100-32.yaml +0 -155
  263. data/.data/spec/std/isa/proc_cert_model/MC100-64.yaml +0 -21
  264. data/.data/spec/std/isa/proc_cert_model/MC200-32.yaml +0 -60
  265. data/.data/spec/std/isa/proc_cert_model/MC200-64.yaml +0 -21
  266. data/.data/spec/std/isa/proc_cert_model/MC300-32.yaml +0 -40
  267. data/.data/spec/std/isa/proc_cert_model/MC300-64.yaml +0 -21
  268. data/.data/spec/std/isa/proc_cert_model/RVI20-32.yaml +0 -39
  269. data/.data/spec/std/isa/proc_cert_model/RVI20-64.yaml +0 -19
  270. data/.data/spec/std/isa/profile/RVA23M64.yaml +0 -24
  271. data/.data/spec/std/isa/profile/RVB23M64.yaml +0 -86
  272. data/lib/udb/cert_normative_rule.rb +0 -41
  273. data/lib/udb/obj/certifiable_obj.rb +0 -21
  274. data/lib/udb/obj/certificate.rb +0 -230
  275. data/lib/udb/proc_cert_design.rb +0 -77
@@ -23,6 +23,7 @@ module Udb
23
23
  class PortfolioExtensionRequirement
24
24
  extend T::Sig
25
25
  extend Forwardable
26
+ include Comparable
26
27
 
27
28
  def_delegators :@ext_req,
28
29
  :name,
@@ -41,12 +42,22 @@ module Udb
41
42
  presence: T.nilable(Presence)
42
43
  ).void
43
44
  }
44
- def initialize(name, requirements, arch:, note:, req_id:, presence:)
45
+ def initialize(name, requirements, arch:, note: nil, req_id: nil, presence: nil)
45
46
  @ext_req = arch.extension_requirement(name, requirements)
46
47
  @note = note
47
48
  @req_id = req_id
48
49
  @presence = presence
49
50
  end
51
+
52
+ sig { params(other: T.any(PortfolioExtensionRequirement, ExtensionRequirement)).returns(T.nilable(Integer)) }
53
+ def <=>(other)
54
+ case other
55
+ when PortfolioExtensionRequirement
56
+ @ext_req <=> other.ext_req
57
+ when ExtensionRequirement
58
+ @ext_req <=> other
59
+ end
60
+ end
50
61
  end
51
62
 
52
63
  ##################
@@ -440,22 +451,22 @@ module Udb
440
451
  end
441
452
  end
442
453
 
443
- sig { returns(T::Hash[String, T.untyped]) }
444
- def to_config
445
- {
454
+ sig { params(mandatory: T::Array[PortfolioExtensionRequirement]).returns(T::Hash[String, T.untyped]) }
455
+ def to_config(mandatory: mandatory_ext_reqs)
456
+ c = {
446
457
  "$schema" => "config_schema.json#",
447
458
  "kind" => "architecture configuration",
448
459
  "type" => "partially configured",
449
460
  "name" => name,
450
461
  "description" => description,
451
- "params" => all_in_scope_params.map do |p|
462
+ "params" => all_in_scope_params.sort.map do |p|
452
463
  if p.single_value?
453
464
  [p.name, p.value]
454
465
  else
455
466
  nil
456
467
  end
457
468
  end.compact.to_h,
458
- "mandatory_extensions" => mandatory_ext_reqs.map do |ext_req|
469
+ "mandatory_extensions" => mandatory.sort.map do |ext_req|
459
470
  {
460
471
  "name" => ext_req.name,
461
472
  "version" => \
@@ -466,7 +477,7 @@ module Udb
466
477
  end
467
478
  }
468
479
  end,
469
- "non_mandatory_extensions" => optional_ext_reqs.map do |ext_req|
480
+ "non_mandatory_extensions" => optional_ext_reqs.sort.map do |ext_req|
470
481
  {
471
482
  "name" => ext_req.name,
472
483
  "version" => \
@@ -479,19 +490,41 @@ module Udb
479
490
  end,
480
491
  "additional_extensions" => true
481
492
  }
493
+ c["requirements"] = requirements_condition.to_h unless requirements_condition.empty?
494
+ c
482
495
  end
483
496
 
484
- # returns a config arch that treats the Portfolio like a partial config
485
- sig { returns(ConfiguredArchitecture) }
486
- def to_cfg_arch
487
- @cfg_arch_for_mandatory ||= begin
488
- Tempfile.create do |f|
489
- f.write YAML.dump(to_config)
490
- f.fsync
497
+ # @return portfolio in config form, with requirements of mandatory extensions expanded
498
+ sig { returns(T::Hash[String, T.untyped]) }
499
+ def to_strict_config
500
+ strict_mandatory_ext_reqs = mandatory_ext_reqs
501
+ mandatory_ext_req_names = strict_mandatory_ext_reqs.map(&:name).to_set
502
+ cfg_arch_obj = to_cfg_arch
503
+
504
+ cfg_arch_obj.extensions.each do |ext|
505
+ next if mandatory_ext_req_names.include?(ext.name)
506
+
507
+ if (-ext.to_ext_req.to_condition & cfg_arch_obj.to_condition).unsatisfiable_by_cfg_arch?(cfg_arch_obj)
508
+ # what's the minimum?
509
+ min_ext_ver = ext.versions.find do |ext_ver|
510
+ compat_with_ext_ver = Condition.new({ "extension" => { "name" => ext.name, "version" => "= #{ext_ver.version_str}" } }, cfg_arch_obj)
511
+ c = (compat_with_ext_ver & cfg_arch_obj.to_condition)
512
+ c.satisfiable_by_cfg_arch?(cfg_arch_obj)
513
+ end
514
+ raise "condition problem: ext is required but none of the versions are" if min_ext_ver.nil?
491
515
 
492
- @cfg_arch.config.info.resolver.cfg_arch_for(Pathname.new f.path)
516
+ strict_mandatory_ext_reqs << PortfolioExtensionRequirement.new(ext.name, "~> #{min_ext_ver.version_str}", arch: cfg_arch_obj)
517
+ mandatory_ext_req_names.add(ext.name)
493
518
  end
494
519
  end
520
+
521
+ to_config(mandatory: strict_mandatory_ext_reqs)
522
+ end
523
+
524
+ # returns a config arch that treats the Portfolio like a partial config
525
+ sig { returns(ConfiguredArchitecture) }
526
+ def to_cfg_arch
527
+ @cfg_arch_for_mandatory ||= cfg_arch_for_config_data(to_config)
495
528
  end
496
529
 
497
530
  # returns a config arch that treats the *optional* extensions in Portfolio like a partial config
@@ -525,15 +558,38 @@ module Udb
525
558
  end,
526
559
  "additional_extensions" => true
527
560
  }
561
+ contents["requirements"] = requirements_condition.to_h unless requirements_condition.empty?
562
+ cfg_arch_for_config_data(contents)
563
+ end
564
+ end
565
+
566
+ # Build a ConfiguredArchitecture from an in-memory config data hash.
567
+ # Uses the fast path (no disk round-trip) when the parent has no overlay;
568
+ # falls back to the full pipeline when the parent's resolved spec differs.
569
+ sig { params(config_data: T::Hash[String, T.untyped]).returns(ConfiguredArchitecture) }
570
+ def cfg_arch_for_config_data(config_data)
571
+ resolver = @cfg_arch.config.info.resolver
572
+ if @cfg_arch.config.info.overlay_path.nil?
573
+ resolver.cfg_arch_for_data(config_data)
574
+ else
528
575
  Tempfile.create do |f|
529
- f.write YAML.dump(contents)
576
+ f.write YAML.dump(config_data)
530
577
  f.fsync
531
-
532
- @cfg_arch.config.info.resolver.cfg_arch_for(Pathname.new f.path)
578
+ resolver.cfg_arch_for(Pathname.new f.path)
533
579
  end
534
580
  end
535
581
  end
536
582
 
583
+ sig { returns(AbstractCondition) }
584
+ def requirements_condition
585
+ @requirements_condition ||=
586
+ if @data.key?("requirements")
587
+ Condition.new(@data.fetch("requirements"), cfg_arch)
588
+ else
589
+ AlwaysTrueCondition.new(cfg_arch)
590
+ end
591
+ end
592
+
537
593
  # @return [String] Given an instruction +inst_name+, return the presence as a string.
538
594
  # If the instruction name isn't found in the portfolio, return "-".
539
595
  sig { params(inst_name: String).returns(T.nilable(Presence)) }
@@ -739,8 +795,7 @@ module Udb
739
795
 
740
796
  return @in_scope_csrs unless @in_scope_csrs.nil?
741
797
 
742
- @in_scope_csrs =
743
- in_scope_min_satisfying_extension_versions.map { |ext_ver| ext_ver.in_scope_csrs(design.possible_xlens) }.flatten.uniq
798
+ @in_scope_csrs = to_cfg_arch.in_scope_csrs()
744
799
  end
745
800
 
746
801
  # @param design [Design] The design
@@ -196,10 +196,6 @@ module Udb
196
196
  @data["base"]
197
197
  end
198
198
 
199
- def all_in_scope_params
200
- [Portfolio::InScopeParameter.new(@cfg_arch.param("MXLEN"), { "const" => @data["base"] }, "")]
201
- end
202
-
203
199
  # Too complicated to put in profile ERB template.
204
200
  # @param presence_type [String]
205
201
  # @param heading_level [Integer]
@@ -49,6 +49,12 @@ class RegisterFile < TopLevelDatabaseObject
49
49
  sig { returns(T::Array[String]) }
50
50
  def abi_mnemonics = @data.fetch("abi_mnemonics", [])
51
51
 
52
+ sig { returns(T.nilable(String)) }
53
+ def reset_value = @data["reset_value"]
54
+
55
+ sig { returns(RegisterFile) }
56
+ def register_file = @file
57
+
52
58
  sig { returns(T.any(Integer, String)) }
53
59
  def index = @index
54
60
 
@@ -97,8 +103,63 @@ class RegisterFile < TopLevelDatabaseObject
97
103
  end
98
104
  end
99
105
 
100
- sig { returns(T.any(Integer, String)) }
101
- def register_length = @data.fetch("register_length")
106
+ # Returns the IDL function body string for the register_length() field.
107
+ # e.g. "return MXLEN;" or "return implemented?(ExtensionName::D) ? 64 : 32;"
108
+ sig { returns(String) }
109
+ def register_length = @data.fetch("register_length()")
110
+
111
+ # Returns the stripped IDL expression (no 'return' keyword or trailing semicolon).
112
+ sig { returns(String) }
113
+ def register_length_expr
114
+ register_length.strip.sub(/\Areturn\s+/, "").sub(/;\z/, "").strip
115
+ end
116
+
117
+ # Evaluate the register_length() IDL body against the given cfg_arch parameter context.
118
+ # Returns an Integer if the width is statically determined, or a String param name
119
+ # if the width depends on a runtime parameter (e.g. "VLEN").
120
+ sig { params(cfg_arch: ConfiguredArchitecture).returns(T.any(Integer, String)) }
121
+ def eval_register_length(cfg_arch)
122
+ expr = register_length_expr
123
+
124
+ # Literal integer
125
+ return Integer(expr) if expr =~ /\A\d+\z/
126
+
127
+ # Simple MXLEN reference
128
+ if expr == "MXLEN"
129
+ mxlen = cfg_arch.mxlen
130
+ return mxlen || "MXLEN" # Return String "MXLEN" for dynamic-XLEN configs
131
+ end
132
+
133
+ # Check for a fixed parameter
134
+ fixed = cfg_arch.params_with_value.find { |p| p.name == expr }
135
+ return T.cast(fixed.value, Integer).to_i if fixed
136
+
137
+ # Check if it's a free parameter name
138
+ free = cfg_arch.params_without_value.find { |p| p.name == expr }
139
+ return expr if free
140
+
141
+ # Complex expression — fall back to the architectural maximum.
142
+ max_register_length
143
+ end
144
+
145
+ # Maximum value register_length() can return across all valid configurations.
146
+ # Derived by compiling the register_length() expression against the full symtab
147
+ # and calling max_value — unknown conditions (e.g. implemented?) cause the ternary
148
+ # to return the max of both branches.
149
+ sig { returns(Integer) }
150
+ def max_register_length
151
+ @max_register_length ||= _compute_max_register_length
152
+ end
153
+
154
+ private def _compute_max_register_length
155
+ node = cfg_arch.idl_compiler.compile_expression(
156
+ register_length_expr, cfg_arch.symtab, pass_error: true
157
+ )
158
+ max = node.max_value(cfg_arch.symtab)
159
+ raise "Cannot determine max_register_length for register file '#{name}' " \
160
+ "(register_length() expression: '#{register_length_expr}')" if max == :unknown
161
+ Integer(max)
162
+ end
102
163
 
103
164
  sig { returns(T.nilable(String)) }
104
165
  def summary = @data["summary"]
@@ -4,13 +4,12 @@
4
4
 
5
5
  # frozen_string_literal: true
6
6
 
7
- # Combines knowledge of the architecture database with one or more portfolios (profile or certificate).
7
+ # Combines knowledge of the architecture database with one or more portfolios (profile).
8
8
  #
9
9
  # Used in portfolio-based ERB templates to gather information about the "portfolio_design".
10
10
  # The "portfolio_design" corresponds to the file being created by the ERB template and facilitates
11
11
  # sharing ERB template fragments between different kinds of portfolios (mostly in the appendices).
12
- # For example, a processor certificate model has one portfolio but a profile release has multiple portfolios
13
- # but they both have just one PortfolioDesign object.
12
+ # For example, a profile release has multiple portfolios but just one PortfolioDesign object.
14
13
 
15
14
  require "forwardable"
16
15
 
@@ -66,9 +65,7 @@ module Udb
66
65
 
67
66
  # Class methods
68
67
  def self.profile_release_type = "Profile Release"
69
- def self.proc_crd_type = "Certification Requirements Document"
70
- def self.proc_ctp_type = "Certification Test Plan"
71
- def self.portfolio_design_types = [profile_release_type, proc_crd_type, proc_ctp_type]
68
+ def self.portfolio_design_types = [profile_release_type]
72
69
 
73
70
  # @param name [#to_s] The name of the portfolio design (i.e., backend filename without a suffix)
74
71
  # @param cfg_arch [ConfiguredArchitecture] The database of RISC-V standards for a particular configuration
data/lib/udb/resolver.rb CHANGED
@@ -15,6 +15,9 @@ require_relative "yaml/yaml_resolver"
15
15
  module Udb
16
16
  # resolves the specification in the context of a config, and writes to a generation folder
17
17
  #
18
+ # Raised by Resolver#cfg_info when a config name or path cannot be found.
19
+ class ConfigNotFoundError < StandardError; end
20
+
18
21
  # The primary interface for users will be #cfg_arch_for
19
22
  class Resolver
20
23
  extend T::Sig
@@ -186,15 +189,20 @@ module Udb
186
189
  end
187
190
  raise "custom directory '#{overlay_path}' does not exist" if !overlay_path.nil? && !overlay_path.directory?
188
191
 
189
- if any_newer?(merged_spec_path(config_name) / ".stamp", deps)
190
- # Use Ruby YAML resolver instead of Python
191
- yaml_resolver = Udb::Yaml::Resolver.new(quiet: @quiet, compile_idl: @compile_idl)
192
- yaml_resolver.merge_files(
193
- std_path.to_s,
194
- overlay_path&.to_s,
195
- merged_spec_path(config_name).to_s
196
- )
197
- FileUtils.touch(merged_spec_path(config_name) / ".stamp")
192
+ FileUtils.mkdir_p(@gen_path / "spec")
193
+ merge_lock_name = merged_spec_path(config_name).basename
194
+ File.open(@gen_path / "spec" / ".#{merge_lock_name}.lock", File::CREAT | File::RDWR) do |f|
195
+ f.flock(File::LOCK_EX)
196
+ if any_newer?(merged_spec_path(config_name) / ".stamp", deps)
197
+ # Use Ruby YAML resolver instead of Python
198
+ yaml_resolver = Udb::Yaml::Resolver.new(quiet: @quiet, compile_idl: @compile_idl)
199
+ yaml_resolver.merge_files(
200
+ std_path.to_s,
201
+ overlay_path&.to_s,
202
+ merged_spec_path(config_name).to_s
203
+ )
204
+ FileUtils.touch(merged_spec_path(config_name) / ".stamp")
205
+ end
198
206
  end
199
207
  end
200
208
  end
@@ -205,19 +213,24 @@ module Udb
205
213
  @mutex.synchronize do
206
214
  config_name = config_yaml["name"]
207
215
 
208
- deps = Dir[merged_spec_path(config_name) / "**" / "*.yaml"].map { |p| Pathname.new(p) }
209
- if any_newer?(resolved_spec_path(config_name) / ".stamp", deps)
210
- # Use Ruby YAML resolver instead of Python
211
- yaml_resolver = Udb::Yaml::Resolver.new(quiet: @quiet, compile_idl: @compile_idl)
212
- yaml_resolver.resolve_files(
213
- merged_spec_path(config_name).to_s,
214
- resolved_spec_path(config_name).to_s,
215
- no_checks: false
216
- )
217
- FileUtils.touch(resolved_spec_path(config_name) / ".stamp")
218
- end
216
+ FileUtils.mkdir_p(@gen_path / "resolved_spec")
217
+ resolve_lock_name = resolved_spec_path(config_name).basename
218
+ File.open(@gen_path / "resolved_spec" / ".#{resolve_lock_name}.lock", File::CREAT | File::RDWR) do |f|
219
+ f.flock(File::LOCK_EX)
220
+ deps = Dir[merged_spec_path(config_name) / "**" / "*.yaml"].map { |p| Pathname.new(p) }
221
+ if any_newer?(resolved_spec_path(config_name) / ".stamp", deps)
222
+ # Use Ruby YAML resolver instead of Python
223
+ yaml_resolver = Udb::Yaml::Resolver.new(quiet: @quiet, compile_idl: @compile_idl)
224
+ yaml_resolver.resolve_files(
225
+ merged_spec_path(config_name).to_s,
226
+ resolved_spec_path(config_name).to_s,
227
+ no_checks: false
228
+ )
229
+ FileUtils.touch(resolved_spec_path(config_name) / ".stamp")
230
+ end
219
231
 
220
- FileUtils.cp_r(std_path / "isa", resolved_spec_path(config_name))
232
+ FileUtils.cp_r(std_path / "isa", resolved_spec_path(config_name))
233
+ end
221
234
  end
222
235
  end
223
236
 
@@ -240,8 +253,7 @@ module Udb
240
253
  if (@cfgs_path / "#{config_path_or_name}.yaml").file?
241
254
  (@cfgs_path / "#{config_path_or_name}.yaml").realpath
242
255
  else
243
- Udb.logger.error "Could not find config: #{config_path_or_name}"
244
- exit 1
256
+ raise ConfigNotFoundError, "Could not find config: #{config_path_or_name}"
245
257
  end
246
258
  else
247
259
  T.absurd(config_path_or_name)
@@ -291,6 +303,33 @@ module Udb
291
303
  end
292
304
  end
293
305
 
306
+ # Resolve a config pointer (name or file path) to a ConfiguredArchitecture.
307
+ # Resolution order:
308
+ # 1. If <cfgs_path>/<pointer>.yaml exists on disk, treat as a repo config name
309
+ # (handles names that contain '/', e.g. "profile/RVA23U64").
310
+ # 2. If the pointer ends in .yaml/.yml, is absolute, or starts with ./ or ../,
311
+ # treat as a file path resolved relative to +relative_dir+.
312
+ # 3. Otherwise raise ArgumentError — the pointer is neither a known config name
313
+ # nor a recognisable file path.
314
+ sig { params(pointer: String, relative_dir: Pathname).returns(Udb::ConfiguredArchitecture) }
315
+ def cfg_arch_for_pointer(pointer, relative_dir:)
316
+ if (@cfgs_path / "#{pointer}.yaml").file?
317
+ # Repo config name — may contain '/' for nested configs (e.g. "profile/RVA23U64").
318
+ cfg_arch_for(pointer)
319
+ elsif pointer.end_with?(".yaml", ".yml") ||
320
+ Pathname.new(pointer).absolute? ||
321
+ pointer.start_with?("./", "../")
322
+ # Explicit file path — resolve relative to the caller's directory.
323
+ path = Pathname.new(pointer)
324
+ cfg_arch_for(path.absolute? ? path : (relative_dir / path).cleanpath)
325
+ else
326
+ raise ArgumentError,
327
+ "Cannot resolve config pointer '#{pointer}': not a known config name " \
328
+ "under '#{@cfgs_path}' and not a recognisable file path " \
329
+ "(.yaml/.yml extension, absolute, or starting with ./ or ../)"
330
+ end
331
+ end
332
+
294
333
  # resolve the specification for a config, and return a ConfiguredArchitecture
295
334
  sig { params(config_path_or_name: T.any(Pathname, String)).returns(Udb::ConfiguredArchitecture) }
296
335
  def cfg_arch_for(config_path_or_name)
@@ -312,6 +351,28 @@ module Udb
312
351
  end
313
352
  end
314
353
 
354
+ # Create a ConfiguredArchitecture directly from an in-memory config data hash,
355
+ # bypassing resolve_config and resolve_arch entirely. Only valid when the config
356
+ # has no arch_overlay (i.e., it uses the standard spec at gen/resolved_spec/_).
357
+ # Callers must ensure this precondition holds before calling this method.
358
+ sig { params(config_data: T::Hash[String, T.untyped]).returns(Udb::ConfiguredArchitecture) }
359
+ def cfg_arch_for_data(config_data)
360
+ info = ConfigInfo.new(
361
+ name: config_data["name"],
362
+ path: Pathname.new("portfolio/#{config_data["name"]}"),
363
+ overlay_path: nil,
364
+ unresolved_yaml: config_data,
365
+ spec_path: std_path,
366
+ merged_spec_path: @gen_path / "spec" / "_",
367
+ resolved_spec_path: @gen_path / "resolved_spec" / "_",
368
+ resolver: self
369
+ )
370
+ Udb::ConfiguredArchitecture.new(
371
+ config_data["name"],
372
+ Udb::AbstractConfig.create_from_data(config_data, info)
373
+ )
374
+ end
375
+
315
376
  SCHEMAS_BASE_URL = "https://riscv.github.io/riscv-unified-db/schemas"
316
377
 
317
378
  # Resolve schema files by rewriting their $id to the full published URL and
data/lib/udb/version.rb CHANGED
@@ -5,5 +5,5 @@
5
5
  # frozen_string_literal: true
6
6
 
7
7
  module Udb
8
- def self.version = "0.1.9"
8
+ def self.version = "0.1.13"
9
9
  end
@@ -192,6 +192,14 @@ module Udb
192
192
  REQUIREMENT_OP_REGEX = /((?:>=)|(?:>)|(?:~>)|(?:<)|(?:<=)|(?:!=)|(?:=))/
193
193
  REQUIREMENT_REGEX = /#{REQUIREMENT_OP_REGEX}\s*(#{VersionSpec::VERSION_REGEX})/
194
194
 
195
+ # Intern cache: RequirementSpec.new with the same string returns the same object.
196
+ @intern_cache = T.let({}, T::Hash[String, RequirementSpec])
197
+
198
+ sig { params(requirement: String).returns(RequirementSpec) }
199
+ def self.new(requirement)
200
+ @intern_cache[requirement] ||= super
201
+ end
202
+
195
203
  sig { returns(String) }
196
204
  attr_reader :op
197
205
 
data/lib/udb/z3.rb CHANGED
@@ -23,6 +23,29 @@ Udb::Z3Loader.ensure_z3_loaded
23
23
 
24
24
  require "z3"
25
25
 
26
+ # Patch Z3::AST#ast_kind to use a constant hash instead of allocating a new one on every call
27
+ module Z3
28
+ class AST
29
+ extend T::Sig
30
+
31
+ AST_KIND_LOOKUP = T.let({
32
+ 0 => :numeral,
33
+ 1 => :app,
34
+ 2 => :var,
35
+ 3 => :quantifier,
36
+ 4 => :sort,
37
+ 5 => :func_decl,
38
+ 1000 => :unknown,
39
+ }.freeze, T::Hash[Integer, Symbol])
40
+
41
+ sig { returns(Symbol).checked(:never) }
42
+ def ast_kind
43
+ kind_id = LowLevel.get_ast_kind(self)
44
+ AST_KIND_LOOKUP[kind_id] or raise Z3::Exception, "Unknown AST kind #{kind_id}"
45
+ end
46
+ end
47
+ end
48
+
26
49
  module Z3
27
50
  # Extension to the Z3::Solver class to add tracked assertions
28
51
  class Solver
data/lib/udb.rb CHANGED
@@ -6,14 +6,11 @@
6
6
 
7
7
  module Udb; end
8
8
 
9
- require_relative "udb/cert_normative_rule"
10
9
  require_relative "udb/doc_link"
11
10
  require_relative "udb/condition"
12
11
  require_relative "udb/schema"
13
12
  require_relative "udb/version"
14
13
 
15
- require_relative "udb/obj/certifiable_obj"
16
- require_relative "udb/obj/certificate"
17
14
  require_relative "udb/obj/csr_field"
18
15
  require_relative "udb/obj/csr"
19
16
  require_relative "udb/obj/database_obj"