218 lines
6.0 KiB
Python
218 lines
6.0 KiB
Python
import os
|
|
import subprocess
|
|
from typing import List, Optional, Union
|
|
|
|
|
|
class ASL:
|
|
@staticmethod
|
|
def definition_block(kind: str, revision: int) -> str:
|
|
block = "DefinitionBlock "
|
|
block += f'("", "{kind}", {revision}, '
|
|
block += '"uTEST", "TESTTABL", 0xF0F0F0F0)'
|
|
|
|
return block
|
|
|
|
@staticmethod
|
|
def name(name: str, term_arg: Union[str, int]) -> str:
|
|
return f"Name({name}, {term_arg})"
|
|
|
|
@staticmethod
|
|
def buffer(
|
|
initializers: Optional[List[int]] = None,
|
|
count: Optional[int] = None
|
|
) -> str:
|
|
if count is not None:
|
|
buf_len = count
|
|
elif initializers is not None:
|
|
buf_len = len(initializers)
|
|
else:
|
|
buf_len = 0
|
|
|
|
buf = f"Buffer({buf_len})"
|
|
|
|
buf += " { "
|
|
if initializers is not None:
|
|
buf += ", ".join([str(x) for x in initializers])
|
|
buf += " }"
|
|
|
|
return buf
|
|
|
|
@staticmethod
|
|
def method(name: str, num_args: Optional[int] = None) -> str:
|
|
method = f"Method ({name}"
|
|
if num_args is not None:
|
|
method += f", {num_args}"
|
|
method += ")"
|
|
|
|
return method
|
|
|
|
@staticmethod
|
|
def invoke(name: str, args: List[str] = []) -> str:
|
|
invocation = f"{name}("
|
|
invocation += ", ".join(args)
|
|
invocation += ")"
|
|
return invocation
|
|
|
|
@staticmethod
|
|
def end_block() -> str:
|
|
return "}"
|
|
|
|
@staticmethod
|
|
def assign(dst: str, src: str) -> str:
|
|
return f"{dst} = {src}"
|
|
|
|
@staticmethod
|
|
def increment(name: str) -> str:
|
|
return f"{name}++"
|
|
|
|
@staticmethod
|
|
def create_field(buf: str, idx: int, field_size: int,
|
|
field_name: str) -> str:
|
|
return f"CreateField({buf}, {idx}, {field_size}, {field_name})"
|
|
|
|
@staticmethod
|
|
def iff(arg: str) -> str:
|
|
return f"If ({arg})"
|
|
|
|
@staticmethod
|
|
def elsee() -> str:
|
|
return "Else"
|
|
|
|
@staticmethod
|
|
def equal(arg0: str, arg1: str) -> str:
|
|
return f"{arg0} == {arg1}"
|
|
|
|
@staticmethod
|
|
def returnn(arg: str) -> str:
|
|
return f"Return ({arg})"
|
|
|
|
|
|
class ASLSource:
|
|
def __init__(self, revision: int = 0):
|
|
self.lines: List[str] = []
|
|
self.revision = revision
|
|
self.indentation = 0
|
|
|
|
self.l(ASL.definition_block("DSDT", 2))
|
|
self.block_begin()
|
|
|
|
def l(self, line: str) -> None:
|
|
line = " " * (self.indentation * 4) + line
|
|
self.lines.append(line)
|
|
|
|
def block_begin(self) -> None:
|
|
self.l("{")
|
|
self.indentation += 1
|
|
|
|
def block_end(self) -> None:
|
|
self.indentation -= 1
|
|
self.l("}\n")
|
|
|
|
def iff(self, arg: str) -> None:
|
|
self.l(ASL.iff(arg) + " {")
|
|
self.indentation += 1
|
|
|
|
def elsee(self) -> None:
|
|
self.indentation -= 1
|
|
self.l("} Else {")
|
|
self.indentation += 1
|
|
|
|
def finalize(self) -> None:
|
|
self.block_end()
|
|
|
|
def dump(self, path: str) -> None:
|
|
with open(path, "w") as f:
|
|
f.write("\n".join(self.lines))
|
|
|
|
def dump_as_test_case(
|
|
self, path: str, case_name: str,
|
|
expected_type: str, expected_value: Union[str, int]
|
|
) -> None:
|
|
with open(path, "w") as f:
|
|
f.write(f"// Name: (generated) {case_name}\n")
|
|
f.write(f"// Expect: {expected_type} => {expected_value}\n")
|
|
f.write("\n".join(self.lines))
|
|
|
|
@staticmethod
|
|
def compile(path: str, compiler: str, bin_dir: str) -> str:
|
|
case_aml_name = os.path.basename(path).rsplit(".", 1)[0] + ".aml"
|
|
out_case = os.path.join(bin_dir, case_aml_name)
|
|
|
|
ignored_warnings = [
|
|
# Warning 3144 Method Local is set but never used
|
|
"-vw", "3144",
|
|
# Remark 2098 Recursive method call
|
|
"-vw", "2098",
|
|
|
|
# Invalid type [Reference] found, RefOf operator requires
|
|
# [Integer|String|Buffer|Package|FieldUnit|Device|Event|
|
|
# Method|Mutex|Region|Power|Processor|Thermal|BufferField|
|
|
# DdbHandle|DebugObject]
|
|
"-vw", "6058",
|
|
|
|
# One or more objects within the Pathname do not exist
|
|
"-vw", "6161",
|
|
# Too few arguments
|
|
"-vw", "6005",
|
|
# Called method returns no value
|
|
"-vw", "6080",
|
|
# Object does not exist
|
|
"-vw", "6084",
|
|
|
|
# Not a control method, cannot invoke
|
|
"-vw", "6086",
|
|
|
|
# Object is not referenced
|
|
"-vw", "2089",
|
|
|
|
# Creation of named objects within a method is highly inefficient
|
|
"-vw", "2173",
|
|
|
|
# Existing object has invalid type for Scope operator
|
|
"-vw", "6117",
|
|
|
|
# Switch expression is not a static Integer/Buffer/String data
|
|
"-vw", "3124",
|
|
|
|
# Static OperationRegion should be declared outside control method
|
|
"-vw", "3175",
|
|
|
|
# Missing dependency
|
|
# (for some reason it has two different error codes)
|
|
"-vw", "3141",
|
|
"-vw", "6141",
|
|
|
|
# Field Unit extends beyond region limit
|
|
"-vw", "6031",
|
|
|
|
# Name already exists in scope
|
|
"-vw", "6074",
|
|
|
|
# Object not found or not accessible from current scope
|
|
"-vw", "6085",
|
|
|
|
# Legacy Processor() keyword detected. Use Device() keyword instead
|
|
"-vw", "3168",
|
|
|
|
# Local or Arg used outside a control method
|
|
"-vw", "2067",
|
|
]
|
|
|
|
args = [compiler, *ignored_warnings, "-oa", "-p", out_case, path]
|
|
proc = subprocess.Popen(args, stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
universal_newlines=True)
|
|
|
|
proc.wait(10)
|
|
|
|
stdout = proc.stdout
|
|
assert stdout
|
|
stderr = proc.stderr
|
|
assert stderr
|
|
|
|
if proc.returncode != 0:
|
|
raise RuntimeError(f"Compiler error:\nstdout:\n{stdout.read()}"
|
|
f"\nstderr:\n{stderr.read()}")
|
|
|
|
return out_case
|