simdref 0.0.0__py3-none-any.whl
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.
- simdref/__init__.py +6 -0
- simdref/__main__.py +6 -0
- simdref/annotate.py +448 -0
- simdref/arm_instructions.py +417 -0
- simdref/cli.py +1598 -0
- simdref/display.py +963 -0
- simdref/filters.py +318 -0
- simdref/ingest.py +113 -0
- simdref/ingest_catalog.py +1172 -0
- simdref/ingest_pdf.py +188 -0
- simdref/ingest_sources.py +580 -0
- simdref/lsp.py +208 -0
- simdref/manpages.py +139 -0
- simdref/models.py +225 -0
- simdref/pdfparse/__init__.py +13 -0
- simdref/pdfparse/base.py +116 -0
- simdref/pdfparse/intel.py +614 -0
- simdref/pdfparse/registry.py +19 -0
- simdref/pdfparse/types.py +77 -0
- simdref/pdfrefs.py +95 -0
- simdref/perf.py +220 -0
- simdref/perf_sources/__init__.py +51 -0
- simdref/perf_sources/cores.py +101 -0
- simdref/perf_sources/llvm_mca.py +176 -0
- simdref/perf_sources/llvm_scheduling.py +625 -0
- simdref/perf_sources/merge.py +121 -0
- simdref/queries.py +207 -0
- simdref/riscv.py +446 -0
- simdref/search.py +288 -0
- simdref/storage.py +504 -0
- simdref/templates/__init__.py +0 -0
- simdref/templates/app.js +1590 -0
- simdref/templates/favicon.svg +5 -0
- simdref/templates/index.html +112 -0
- simdref/templates/logo.svg +12 -0
- simdref/templates/style.css +680 -0
- simdref/tui.py +2366 -0
- simdref/web.py +403 -0
- simdref-0.0.0.dist-info/METADATA +240 -0
- simdref-0.0.0.dist-info/RECORD +44 -0
- simdref-0.0.0.dist-info/WHEEL +5 -0
- simdref-0.0.0.dist-info/entry_points.txt +4 -0
- simdref-0.0.0.dist-info/licenses/LICENSE +674 -0
- simdref-0.0.0.dist-info/top_level.txt +1 -0
simdref/riscv.py
ADDED
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
"""RISC-V RVV instruction/intrinsic parsing and normalization."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import html
|
|
6
|
+
import json
|
|
7
|
+
import re
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from simdref.models import InstructionRecord, IntrinsicRecord
|
|
11
|
+
|
|
12
|
+
RISCV_RVV_INTRINSICS_PROJECT_URL = "https://github.com/riscv-non-isa/riscv-rvv-intrinsic-doc"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _normalize_isa(value: Any) -> list[str]:
|
|
16
|
+
if isinstance(value, dict):
|
|
17
|
+
normalized: list[str] = []
|
|
18
|
+
for key in ("isa", "extensions", "extension", "name", "value"):
|
|
19
|
+
normalized.extend(_normalize_isa(value.get(key)))
|
|
20
|
+
if normalized:
|
|
21
|
+
return list(dict.fromkeys(normalized))
|
|
22
|
+
return [str(key).strip() for key, enabled in value.items() if enabled and str(key).strip()]
|
|
23
|
+
if isinstance(value, list):
|
|
24
|
+
normalized: list[str] = []
|
|
25
|
+
for item in value:
|
|
26
|
+
normalized.extend(_normalize_isa(item))
|
|
27
|
+
return list(dict.fromkeys(normalized))
|
|
28
|
+
if isinstance(value, str):
|
|
29
|
+
return [part.strip() for part in re.split(r"[,/|]\s*|\s{2,}", value) if part.strip()]
|
|
30
|
+
return []
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _string(value: Any) -> str:
|
|
34
|
+
return str(value or "").strip()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _string_map(value: Any) -> dict[str, str]:
|
|
38
|
+
if not isinstance(value, dict):
|
|
39
|
+
return {}
|
|
40
|
+
return {
|
|
41
|
+
str(key).strip(): str(item).strip()
|
|
42
|
+
for key, item in value.items()
|
|
43
|
+
if str(key).strip() and str(item).strip()
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _string_list(value: Any) -> list[str]:
|
|
48
|
+
if isinstance(value, list):
|
|
49
|
+
return [str(item).strip() for item in value if str(item).strip()]
|
|
50
|
+
if isinstance(value, str):
|
|
51
|
+
return [value.strip()] if value.strip() else []
|
|
52
|
+
return []
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _strip_tags(text: str) -> str:
|
|
56
|
+
clean = re.sub(r"<br\s*/?>", "\n", text, flags=re.IGNORECASE)
|
|
57
|
+
clean = re.sub(r"</p\s*>", "\n\n", clean, flags=re.IGNORECASE)
|
|
58
|
+
clean = re.sub(r"</?(?:code|span|strong|em)[^>]*>", "", clean, flags=re.IGNORECASE)
|
|
59
|
+
clean = re.sub(r"</?(?:pre|div|section|article|ul|ol|li)[^>]*>", "\n", clean, flags=re.IGNORECASE)
|
|
60
|
+
clean = re.sub(r"<[^>]+>", " ", clean)
|
|
61
|
+
clean = html.unescape(clean)
|
|
62
|
+
clean = clean.replace("\r", "")
|
|
63
|
+
clean = re.sub(r"[ \t]+\n", "\n", clean)
|
|
64
|
+
clean = re.sub(r"\n{3,}", "\n\n", clean)
|
|
65
|
+
clean = re.sub(r"[ \t]{2,}", " ", clean)
|
|
66
|
+
clean = re.sub(r"\s*\n\s*", "\n", clean)
|
|
67
|
+
clean = re.sub(r"\n+", "\n", clean)
|
|
68
|
+
return clean.strip()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _extract_html_section(doc: str, title: str) -> str:
|
|
72
|
+
pattern = re.compile(
|
|
73
|
+
rf"<h[1-6][^>]*>\s*{re.escape(title)}\s*</h[1-6]>(?P<body>.*?)(?=<h[1-6][^>]*>|$)",
|
|
74
|
+
re.IGNORECASE | re.DOTALL,
|
|
75
|
+
)
|
|
76
|
+
match = pattern.search(doc)
|
|
77
|
+
if not match:
|
|
78
|
+
return ""
|
|
79
|
+
return _strip_tags(match.group("body"))
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _section_slice(doc: str, mnemonic: str) -> str:
|
|
83
|
+
lowered = doc.casefold()
|
|
84
|
+
needle = mnemonic.casefold()
|
|
85
|
+
index = lowered.find(needle)
|
|
86
|
+
if index < 0:
|
|
87
|
+
return ""
|
|
88
|
+
start = max(
|
|
89
|
+
doc.rfind('<div class="sect4">', 0, index),
|
|
90
|
+
doc.rfind('<div class="sect3">', 0, index),
|
|
91
|
+
doc.rfind('<div class="sect2">', 0, index),
|
|
92
|
+
)
|
|
93
|
+
if start < 0:
|
|
94
|
+
start = max(0, index - 4000)
|
|
95
|
+
end_candidates = [
|
|
96
|
+
candidate
|
|
97
|
+
for marker in ('<div class="sect4">', '<div class="sect3">', '<div class="sect2">')
|
|
98
|
+
if (candidate := doc.find(marker, index + len(needle))) >= 0
|
|
99
|
+
]
|
|
100
|
+
end = min(end_candidates) if end_candidates else min(len(doc), index + 12000)
|
|
101
|
+
return doc[start:end]
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _extract_instruction_section_semantics(doc: str, mnemonic: str) -> dict[str, str]:
|
|
105
|
+
section = _section_slice(doc, mnemonic)
|
|
106
|
+
if not section:
|
|
107
|
+
return {}
|
|
108
|
+
|
|
109
|
+
description = ""
|
|
110
|
+
paragraphs = re.findall(r"<div class=\"paragraph\">(.*?)</div>", section, re.IGNORECASE | re.DOTALL)
|
|
111
|
+
for raw in paragraphs:
|
|
112
|
+
text = _strip_tags(raw)
|
|
113
|
+
if not text:
|
|
114
|
+
continue
|
|
115
|
+
description = text
|
|
116
|
+
if mnemonic.casefold() in text.casefold():
|
|
117
|
+
break
|
|
118
|
+
|
|
119
|
+
operation = ""
|
|
120
|
+
op_heading = re.search(r"<dt[^>]*>\s*Operation\s*</dt>", section, re.IGNORECASE | re.DOTALL)
|
|
121
|
+
if op_heading:
|
|
122
|
+
pre_match = re.search(r"<pre[^>]*>(.*?)</pre>", section[op_heading.end():], re.IGNORECASE | re.DOTALL)
|
|
123
|
+
if pre_match:
|
|
124
|
+
operation = _strip_tags(pre_match.group(1))
|
|
125
|
+
if not operation:
|
|
126
|
+
for pre in re.findall(r"<pre[^>]*>(.*?)</pre>", section, re.IGNORECASE | re.DOTALL):
|
|
127
|
+
text = _strip_tags(pre)
|
|
128
|
+
if mnemonic.casefold() in text.casefold():
|
|
129
|
+
operation = text
|
|
130
|
+
break
|
|
131
|
+
if not operation:
|
|
132
|
+
listings = re.findall(r"<div class=\"listingblock\">(.*?)</div>\s*</div>", section, re.IGNORECASE | re.DOTALL)
|
|
133
|
+
for listing in listings:
|
|
134
|
+
text = _strip_tags(listing)
|
|
135
|
+
if mnemonic.casefold() in text.casefold():
|
|
136
|
+
operation = text
|
|
137
|
+
break
|
|
138
|
+
result: dict[str, str] = {}
|
|
139
|
+
if description:
|
|
140
|
+
result["Description"] = description
|
|
141
|
+
if operation:
|
|
142
|
+
result["Operation"] = operation
|
|
143
|
+
return result
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _normalize_sections(item: dict[str, Any]) -> dict[str, str]:
|
|
147
|
+
sections: dict[str, str] = {}
|
|
148
|
+
for key in ("description", "doc_sections", "sections", "descriptions"):
|
|
149
|
+
value = item.get(key)
|
|
150
|
+
if isinstance(value, dict):
|
|
151
|
+
sections.update(_string_map(value))
|
|
152
|
+
if not sections:
|
|
153
|
+
description = _string(item.get("description_text") or item.get("description"))
|
|
154
|
+
if description:
|
|
155
|
+
sections["Description"] = description
|
|
156
|
+
operation = _string(item.get("operation") or item.get("operation_text") or item.get("pseudocode"))
|
|
157
|
+
if operation:
|
|
158
|
+
sections["Operation"] = operation
|
|
159
|
+
return sections
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def _docs_page_map(payload: Any) -> dict[str, str]:
|
|
163
|
+
if not isinstance(payload, dict):
|
|
164
|
+
return {}
|
|
165
|
+
docs_pages = payload.get("docs_pages") or payload.get("doc_pages") or payload.get("docs")
|
|
166
|
+
if isinstance(docs_pages, dict):
|
|
167
|
+
return {
|
|
168
|
+
_string(key): _string(value)
|
|
169
|
+
for key, value in docs_pages.items()
|
|
170
|
+
if _string(key) and _string(value)
|
|
171
|
+
}
|
|
172
|
+
if isinstance(docs_pages, list):
|
|
173
|
+
mapped: dict[str, str] = {}
|
|
174
|
+
for item in docs_pages:
|
|
175
|
+
if not isinstance(item, dict):
|
|
176
|
+
continue
|
|
177
|
+
url = _string(item.get("url") or item.get("reference_url"))
|
|
178
|
+
page = _string(item.get("html") or item.get("content"))
|
|
179
|
+
if url and page:
|
|
180
|
+
mapped[url] = page
|
|
181
|
+
return mapped
|
|
182
|
+
return {}
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def _doc_candidates(url: str, docs_pages: dict[str, str]) -> list[str]:
|
|
186
|
+
if not url:
|
|
187
|
+
return []
|
|
188
|
+
base = url.split("#", 1)[0]
|
|
189
|
+
candidates = [url]
|
|
190
|
+
if base != url:
|
|
191
|
+
candidates.append(base)
|
|
192
|
+
return [candidate for candidate in candidates if candidate in docs_pages]
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def _instruction_semantics(item: dict[str, Any], url: str, docs_pages: dict[str, str]) -> dict[str, str]:
|
|
196
|
+
sections = _normalize_sections(item)
|
|
197
|
+
if sections.get("Description") and sections.get("Operation"):
|
|
198
|
+
return sections
|
|
199
|
+
mnemonic = _string(item.get("mnemonic") or item.get("name") or item.get("instruction") or item.get("syntax")).casefold()
|
|
200
|
+
for candidate in _doc_candidates(url, docs_pages):
|
|
201
|
+
page = docs_pages[candidate]
|
|
202
|
+
if not sections.get("Description"):
|
|
203
|
+
description = _extract_html_section(page, "Description")
|
|
204
|
+
if description:
|
|
205
|
+
sections["Description"] = description
|
|
206
|
+
if not sections.get("Operation"):
|
|
207
|
+
operation = _extract_html_section(page, "Operation")
|
|
208
|
+
if operation:
|
|
209
|
+
sections["Operation"] = operation
|
|
210
|
+
if not sections.get("Description") or not sections.get("Operation"):
|
|
211
|
+
extracted = _extract_instruction_section_semantics(page, mnemonic)
|
|
212
|
+
for key, value in extracted.items():
|
|
213
|
+
if not sections.get(key):
|
|
214
|
+
sections[key] = value
|
|
215
|
+
if sections.get("Description") and sections.get("Operation"):
|
|
216
|
+
break
|
|
217
|
+
return sections
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def _normalize_policy(value: Any) -> str:
|
|
221
|
+
normalized = _string(value).casefold().replace("-", "").replace("_", "")
|
|
222
|
+
aliases = {
|
|
223
|
+
"": "agnostic",
|
|
224
|
+
"ta": "agnostic",
|
|
225
|
+
"ma": "agnostic",
|
|
226
|
+
"tama": "agnostic",
|
|
227
|
+
"tum": "tum",
|
|
228
|
+
"tu": "tu",
|
|
229
|
+
"mu": "mu",
|
|
230
|
+
"tumu": "tumu",
|
|
231
|
+
}
|
|
232
|
+
return aliases.get(normalized, normalized)
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def _normalize_masking(value: Any) -> str:
|
|
236
|
+
normalized = _string(value).casefold().replace("-", "").replace("_", "")
|
|
237
|
+
if normalized in {"", "nomask", "unmasked", "false"}:
|
|
238
|
+
return "unmasked"
|
|
239
|
+
if normalized in {"mask", "masked", "true"}:
|
|
240
|
+
return "masked"
|
|
241
|
+
return normalized
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def _tail_policy(policy: str) -> str:
|
|
245
|
+
if "tu" in policy:
|
|
246
|
+
return "undisturbed"
|
|
247
|
+
return "agnostic"
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def _mask_policy(policy: str, masking: str) -> str:
|
|
251
|
+
if masking != "masked":
|
|
252
|
+
return ""
|
|
253
|
+
if "mu" in policy:
|
|
254
|
+
return "undisturbed"
|
|
255
|
+
return "agnostic"
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def _instruction_form(item: dict[str, Any], mnemonic: str) -> str:
|
|
259
|
+
explicit = _string(item.get("form"))
|
|
260
|
+
if explicit:
|
|
261
|
+
return explicit
|
|
262
|
+
policy = _normalize_policy(item.get("policy") or item.get("tail_policy"))
|
|
263
|
+
masking = _normalize_masking(item.get("masking"))
|
|
264
|
+
suffix: list[str] = []
|
|
265
|
+
if masking and masking != "unmasked":
|
|
266
|
+
suffix.append(masking)
|
|
267
|
+
if policy and policy not in {"agnostic", "default"}:
|
|
268
|
+
suffix.append(policy)
|
|
269
|
+
if suffix:
|
|
270
|
+
return f"{mnemonic} [{' '.join(suffix)}]"
|
|
271
|
+
return mnemonic
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def parse_riscv_instruction_payload(text: str) -> list[InstructionRecord]:
|
|
275
|
+
payload = json.loads(text)
|
|
276
|
+
docs_pages = _docs_page_map(payload)
|
|
277
|
+
if isinstance(payload, dict) and payload.get("format") == "riscv-unified-db-v1":
|
|
278
|
+
candidates = payload.get("instructions") or []
|
|
279
|
+
elif isinstance(payload, list):
|
|
280
|
+
candidates = payload
|
|
281
|
+
else:
|
|
282
|
+
candidates = payload.get("instructions") or payload.get("records") or []
|
|
283
|
+
|
|
284
|
+
records: list[InstructionRecord] = []
|
|
285
|
+
for item in candidates:
|
|
286
|
+
if not isinstance(item, dict):
|
|
287
|
+
continue
|
|
288
|
+
mnemonic = _string(
|
|
289
|
+
item.get("mnemonic")
|
|
290
|
+
or item.get("name")
|
|
291
|
+
or item.get("instruction")
|
|
292
|
+
or item.get("syntax")
|
|
293
|
+
or item.get("asm")
|
|
294
|
+
).casefold()
|
|
295
|
+
if not mnemonic:
|
|
296
|
+
continue
|
|
297
|
+
metadata = _string_map(item.get("metadata"))
|
|
298
|
+
url = _string(item.get("url") or item.get("reference_url") or item.get("reference"))
|
|
299
|
+
if url:
|
|
300
|
+
metadata["url"] = url
|
|
301
|
+
policy = _normalize_policy(
|
|
302
|
+
item.get("policy")
|
|
303
|
+
or item.get("tail_policy")
|
|
304
|
+
or metadata.get("policy")
|
|
305
|
+
or metadata.get("tail_policy")
|
|
306
|
+
or "agnostic"
|
|
307
|
+
)
|
|
308
|
+
masking = _normalize_masking(item.get("masking") or metadata.get("masking") or "unmasked")
|
|
309
|
+
metadata.setdefault("policy", policy)
|
|
310
|
+
metadata.setdefault("masking", masking)
|
|
311
|
+
metadata.setdefault("tail_policy", _tail_policy(policy))
|
|
312
|
+
mask_policy = _string(item.get("mask_policy") or metadata.get("mask_policy") or _mask_policy(policy, masking))
|
|
313
|
+
if mask_policy:
|
|
314
|
+
metadata.setdefault("mask_policy", mask_policy)
|
|
315
|
+
if item.get("extension"):
|
|
316
|
+
metadata.setdefault("extension", _string(item.get("extension")))
|
|
317
|
+
description = _instruction_semantics(item, url, docs_pages)
|
|
318
|
+
records.append(
|
|
319
|
+
InstructionRecord(
|
|
320
|
+
mnemonic=mnemonic,
|
|
321
|
+
form=_instruction_form(item, mnemonic),
|
|
322
|
+
summary=_string(
|
|
323
|
+
item.get("summary")
|
|
324
|
+
or item.get("brief")
|
|
325
|
+
or item.get("description_text")
|
|
326
|
+
or f"{mnemonic} instruction."
|
|
327
|
+
).rstrip(".") + ".",
|
|
328
|
+
architecture="riscv",
|
|
329
|
+
isa=_normalize_isa(
|
|
330
|
+
item.get("isa")
|
|
331
|
+
or item.get("extensions")
|
|
332
|
+
or item.get("extension")
|
|
333
|
+
or metadata.get("extensions")
|
|
334
|
+
or ["V"]
|
|
335
|
+
),
|
|
336
|
+
operand_details=[
|
|
337
|
+
{
|
|
338
|
+
key: str(value).strip()
|
|
339
|
+
for key, value in operand.items()
|
|
340
|
+
if str(value).strip()
|
|
341
|
+
}
|
|
342
|
+
for operand in (item.get("operand_details") or [])
|
|
343
|
+
if isinstance(operand, dict)
|
|
344
|
+
],
|
|
345
|
+
metadata=metadata,
|
|
346
|
+
aliases=_string_list(item.get("aliases")),
|
|
347
|
+
description=description,
|
|
348
|
+
source="riscv-unified-db",
|
|
349
|
+
)
|
|
350
|
+
)
|
|
351
|
+
return records
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
def _infer_intrinsic_policy(name: str) -> tuple[str, str]:
|
|
355
|
+
lowered = name.casefold()
|
|
356
|
+
policy = "agnostic"
|
|
357
|
+
masking = "masked" if lowered.endswith(("_m", "_mu", "_tum", "_tumu")) or "_m_" in lowered else "unmasked"
|
|
358
|
+
for suffix in ("_tumu", "_tum", "_mu", "_tu"):
|
|
359
|
+
if lowered.endswith(suffix):
|
|
360
|
+
policy = suffix.removeprefix("_")
|
|
361
|
+
break
|
|
362
|
+
return policy, masking
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
def _normalize_instruction_ref(raw_ref: dict[str, Any], intrinsic_name: str) -> dict[str, str]:
|
|
366
|
+
ref_name = _string(raw_ref.get("name") or raw_ref.get("mnemonic") or raw_ref.get("instruction"))
|
|
367
|
+
form = _string(raw_ref.get("form") or raw_ref.get("syntax") or ref_name)
|
|
368
|
+
inferred_policy, inferred_masking = _infer_intrinsic_policy(intrinsic_name)
|
|
369
|
+
policy = _normalize_policy(raw_ref.get("policy") or raw_ref.get("tail_policy") or inferred_policy)
|
|
370
|
+
masking = _normalize_masking(raw_ref.get("masking") or inferred_masking)
|
|
371
|
+
ref = {
|
|
372
|
+
"architecture": "riscv",
|
|
373
|
+
"name": ref_name,
|
|
374
|
+
"form": form or ref_name,
|
|
375
|
+
"isa": _string(raw_ref.get("isa") or raw_ref.get("extension")),
|
|
376
|
+
"policy": policy,
|
|
377
|
+
"masking": masking,
|
|
378
|
+
"tail_policy": _string(raw_ref.get("tail_policy") or _tail_policy(policy)),
|
|
379
|
+
"mask_policy": _string(raw_ref.get("mask_policy") or _mask_policy(policy, masking)),
|
|
380
|
+
}
|
|
381
|
+
return {key: value for key, value in ref.items() if value}
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
def parse_riscv_intrinsics_payload(text: str) -> list[IntrinsicRecord]:
|
|
385
|
+
payload = json.loads(text)
|
|
386
|
+
if isinstance(payload, dict) and payload.get("format") == "riscv-rvv-intrinsics-v1":
|
|
387
|
+
candidates = payload.get("intrinsics") or []
|
|
388
|
+
elif isinstance(payload, list):
|
|
389
|
+
candidates = payload
|
|
390
|
+
else:
|
|
391
|
+
candidates = payload.get("intrinsics") or payload.get("records") or []
|
|
392
|
+
|
|
393
|
+
records: list[IntrinsicRecord] = []
|
|
394
|
+
for item in candidates:
|
|
395
|
+
if not isinstance(item, dict):
|
|
396
|
+
continue
|
|
397
|
+
name = _string(item.get("name"))
|
|
398
|
+
if not name:
|
|
399
|
+
continue
|
|
400
|
+
refs: list[dict[str, str]] = []
|
|
401
|
+
rendered_instructions: list[str] = []
|
|
402
|
+
for raw_ref in item.get("instruction_refs") or []:
|
|
403
|
+
if not isinstance(raw_ref, dict):
|
|
404
|
+
continue
|
|
405
|
+
ref = _normalize_instruction_ref(raw_ref, name)
|
|
406
|
+
if not ref["name"]:
|
|
407
|
+
continue
|
|
408
|
+
if not ref["form"]:
|
|
409
|
+
ref["form"] = ref["name"]
|
|
410
|
+
rendered_instructions.append(ref["form"])
|
|
411
|
+
refs.append(ref)
|
|
412
|
+
if not refs:
|
|
413
|
+
for raw_instruction in item.get("instructions") or []:
|
|
414
|
+
ref = _normalize_instruction_ref({"name": raw_instruction, "form": raw_instruction}, name)
|
|
415
|
+
if ref["name"]:
|
|
416
|
+
rendered_instructions.append(ref["form"])
|
|
417
|
+
refs.append(ref)
|
|
418
|
+
inferred_policy, inferred_masking = _infer_intrinsic_policy(name)
|
|
419
|
+
metadata = _string_map(item.get("metadata"))
|
|
420
|
+
metadata.setdefault("policy", inferred_policy)
|
|
421
|
+
metadata.setdefault("masking", inferred_masking)
|
|
422
|
+
metadata.setdefault("tail_policy", _tail_policy(inferred_policy))
|
|
423
|
+
mask_policy = _mask_policy(inferred_policy, inferred_masking)
|
|
424
|
+
if mask_policy:
|
|
425
|
+
metadata.setdefault("mask_policy", mask_policy)
|
|
426
|
+
records.append(
|
|
427
|
+
IntrinsicRecord(
|
|
428
|
+
name=name,
|
|
429
|
+
signature=_string(item.get("signature") or name),
|
|
430
|
+
description=_string(item.get("description")),
|
|
431
|
+
header=_string(item.get("header") or "riscv_vector.h"),
|
|
432
|
+
url=_string(item.get("url") or item.get("reference_url") or RISCV_RVV_INTRINSICS_PROJECT_URL),
|
|
433
|
+
architecture="riscv",
|
|
434
|
+
isa=_normalize_isa(item.get("isa") or ["V"]),
|
|
435
|
+
category=_string(item.get("category") or "RVV"),
|
|
436
|
+
subcategory=_string(item.get("subcategory")),
|
|
437
|
+
instructions=rendered_instructions,
|
|
438
|
+
instruction_refs=refs,
|
|
439
|
+
metadata=metadata,
|
|
440
|
+
doc_sections=_string_map(item.get("doc_sections") or item.get("sections")),
|
|
441
|
+
notes=_string_list(item.get("notes")),
|
|
442
|
+
aliases=_string_list(item.get("aliases")),
|
|
443
|
+
source="rvv-intrinsic-doc",
|
|
444
|
+
)
|
|
445
|
+
)
|
|
446
|
+
return records
|