added support for xml schemas
This commit is contained in:
parent
84b935c898
commit
f5ddbf4a69
68
example4.xml
Normal file
68
example4.xml
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<schema>
|
||||||
|
<structure id="main" bits="32">
|
||||||
|
<range start="28" end="31" name="cond"></range>
|
||||||
|
<range start="27" end="27" name="0"></range>
|
||||||
|
<range start="26" end="26" name="1"></range>
|
||||||
|
<range start="25" end="25" name="I"></range>
|
||||||
|
<range start="24" end="24" name="P">
|
||||||
|
<description>pre / post indexing bit</description>
|
||||||
|
<values>
|
||||||
|
<case value="0">post, add offset after transfer</case>
|
||||||
|
<case value="1">pre, add offset before transfer</case>
|
||||||
|
</values>
|
||||||
|
</range>
|
||||||
|
<range start="23" end="23" name="U">
|
||||||
|
<description>up / down bit</description>
|
||||||
|
<values>
|
||||||
|
<case value="0">down, subtract offset from base</case>
|
||||||
|
<case value="1">up, addition offset to base</case>
|
||||||
|
</values>
|
||||||
|
</range>
|
||||||
|
<range start="22" end="22" name="B">
|
||||||
|
<description>byte / word bit</description>
|
||||||
|
<values>
|
||||||
|
<case value="0">transfer word quantity</case>
|
||||||
|
<case value="1">transfer byte quantity</case>
|
||||||
|
</values>
|
||||||
|
</range>
|
||||||
|
<range start="21" end="21" name="W">
|
||||||
|
<description>write-back bit</description>
|
||||||
|
<values>
|
||||||
|
<case value="0">no write-back</case>
|
||||||
|
<case value="1">write address into base</case>
|
||||||
|
</values>
|
||||||
|
</range>
|
||||||
|
<range start="20" end="20" name="L">
|
||||||
|
<description>load / store bit</description>
|
||||||
|
<values>
|
||||||
|
<case value="0">store to memory</case>
|
||||||
|
<case value="1">load from memory</case>
|
||||||
|
</values>
|
||||||
|
</range>
|
||||||
|
<range start="16" end="19" name="Rn">
|
||||||
|
<description>base register</description>
|
||||||
|
</range>
|
||||||
|
<range start="12" end="15" name="Rd">
|
||||||
|
<description>source / destination register</description>
|
||||||
|
</range>
|
||||||
|
<range start="0" end="11" name="offset" depends-on="25">
|
||||||
|
<values>
|
||||||
|
<case value="0" structure="immediateOffset">offset is an immediate value</case>
|
||||||
|
<case value="1" structure="registerOffset">offset is a register</case>
|
||||||
|
</values>
|
||||||
|
</range>
|
||||||
|
</structure>
|
||||||
|
<structure id="immediateOffset" bits="12">
|
||||||
|
<range start="0" end="11" name="12-bit immediate offset">
|
||||||
|
<description>unsigned number</description>
|
||||||
|
</range>
|
||||||
|
</structure>
|
||||||
|
<structure id="registerOffset" bits="12">
|
||||||
|
<range start="4" end="11" name="shift">
|
||||||
|
<description>shift applied to Rm</description>
|
||||||
|
</range>
|
||||||
|
<range start="0" end="3" name="Rm">
|
||||||
|
<description>offset register</description>
|
||||||
|
</range>
|
||||||
|
</structure>
|
||||||
|
</schema>
|
@ -5,12 +5,13 @@ import yaml
|
|||||||
from config import Config
|
from config import Config
|
||||||
from renderer import Renderer
|
from renderer import Renderer
|
||||||
from structure import Structure
|
from structure import Structure
|
||||||
|
from xml_loader import XMLLoader
|
||||||
|
|
||||||
class UnsupportedFormatException(Exception):
|
class UnsupportedFormatException(Exception):
|
||||||
...
|
...
|
||||||
|
|
||||||
class InstructionSetSchema:
|
class InstructionSetSchema:
|
||||||
VALID_EXTENSIONS = ("yaml", "json")
|
VALID_EXTENSIONS = ("yaml", "json", "xml")
|
||||||
|
|
||||||
def __init__(self, path: str, configPath: str = "config.json") -> None:
|
def __init__(self, path: str, configPath: str = "config.json") -> None:
|
||||||
self.config = Config(configPath)
|
self.config = Config(configPath)
|
||||||
@ -31,6 +32,9 @@ class InstructionSetSchema:
|
|||||||
|
|
||||||
elif ext == "json":
|
elif ext == "json":
|
||||||
schema = json.load(f)
|
schema = json.load(f)
|
||||||
|
|
||||||
|
elif ext == "xml":
|
||||||
|
schema = XMLLoader.load(f)
|
||||||
|
|
||||||
self.structures = {}
|
self.structures = {}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ class Structure:
|
|||||||
values[v] = d
|
values[v] = d
|
||||||
range_.values = values
|
range_.values = values
|
||||||
|
|
||||||
return Structure(id_, data["bits"], ranges, data.get("start", 0))
|
return Structure(id_, int(data["bits"]), ranges, data.get("start", 0))
|
||||||
|
|
||||||
def getSortedRanges(self) -> list[Range]:
|
def getSortedRanges(self) -> list[Range]:
|
||||||
ranges = self.ranges.values()
|
ranges = self.ranges.values()
|
||||||
|
65
xml_loader.py
Normal file
65
xml_loader.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from io import TextIOWrapper
|
||||||
|
|
||||||
|
class XMLLoader:
|
||||||
|
def load(file_: TextIOWrapper) -> dict:
|
||||||
|
schema = {}
|
||||||
|
bs = BeautifulSoup(file_.read(), "xml")
|
||||||
|
structElmts = bs.findAll("structure")
|
||||||
|
structures = {}
|
||||||
|
|
||||||
|
for structElmt in structElmts:
|
||||||
|
structures[structElmt.get("id")] = XMLLoader.parseStructure(structElmt)
|
||||||
|
|
||||||
|
schema["structures"] = structures
|
||||||
|
return schema
|
||||||
|
|
||||||
|
def parseStructure(structElmt: any) -> dict:
|
||||||
|
struct = {}
|
||||||
|
struct["bits"] = structElmt.get("bits")
|
||||||
|
ranges = {}
|
||||||
|
rangeElmts = structElmt.findAll("range")
|
||||||
|
for rangeElmt in rangeElmts:
|
||||||
|
span = rangeElmt.get("end") + "-" + rangeElmt.get("start")
|
||||||
|
ranges[span] = XMLLoader.parseRange(rangeElmt)
|
||||||
|
|
||||||
|
struct["ranges"] = ranges
|
||||||
|
return struct
|
||||||
|
|
||||||
|
def parseRange(rangeElmt: any) -> dict:
|
||||||
|
range_ = {}
|
||||||
|
range_["name"] = rangeElmt.get("name")
|
||||||
|
desc = rangeElmt.find("description")
|
||||||
|
if desc is not None: range_["description"] = desc.getText()
|
||||||
|
|
||||||
|
valuesElmt = rangeElmt.find("values")
|
||||||
|
if valuesElmt is not None:
|
||||||
|
range_["values"] = XMLLoader.parseValues(valuesElmt)
|
||||||
|
|
||||||
|
if rangeElmt.get("depends-on"):
|
||||||
|
range_["depends-on"] = rangeElmt.get("depends-on")
|
||||||
|
|
||||||
|
return range_
|
||||||
|
|
||||||
|
def parseValues(valuesElmt: any) -> dict:
|
||||||
|
values = {}
|
||||||
|
caseElmts = valuesElmt.findAll("case")
|
||||||
|
|
||||||
|
for caseElmt in caseElmts:
|
||||||
|
val = caseElmt.get("value")
|
||||||
|
desc = caseElmt.getText()
|
||||||
|
struct = caseElmt.get("structure")
|
||||||
|
|
||||||
|
if struct:
|
||||||
|
values[val] = {
|
||||||
|
"description": desc,
|
||||||
|
"structure": struct
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
values[val] = desc
|
||||||
|
|
||||||
|
return values
|
Loading…
Reference in New Issue
Block a user