diff --git a/m2isar/backends/etiss/instruction_transform.py b/m2isar/backends/etiss/instruction_transform.py index cecfb79b..0e0d62c5 100644 --- a/m2isar/backends/etiss/instruction_transform.py +++ b/m2isar/backends/etiss/instruction_transform.py @@ -313,13 +313,7 @@ def conditional(self: behav.Conditional, context: TransformerContext): cond.mem_ids.clear() for stmt in self.stmts: - if isinstance(stmt, list): - ret = [] - for stmt_ in stmt: - ret_ = stmt_.generate(context) - ret.append(ret_) - else: - ret = stmt.generate(context) + ret = stmt.generate(context) if isinstance(ret, list): stmts.append(ret) @@ -747,8 +741,8 @@ def type_conv(self: behav.TypeConv, context: TransformerContext): # if only data type should be changed assume width remains unchanged if self.size is None: - self._size = expr.size - self._actual_size = expr.actual_size + self.size = expr.size + self.actual_size = expr.actual_size # save access size for memory access if expr.is_mem_access: diff --git a/m2isar/frontends/coredsl2/architecture_model_builder.py b/m2isar/frontends/coredsl2/architecture_model_builder.py index 120f4db5..22bcfd6e 100644 --- a/m2isar/frontends/coredsl2/architecture_model_builder.py +++ b/m2isar/frontends/coredsl2/architecture_model_builder.py @@ -24,7 +24,7 @@ class ArchitectureModelBuilder(CoreDSL2Visitor): """ANTLR visitor to build an M2-ISA-R architecture model of a CoreDSL 2 specification.""" _constants: "dict[str, arch.Constant]" - _instructions: "list[arch.Instruction]" + _instructions: "dict[str, arch.Instruction]" _functions: "dict[str, arch.Function]" _always_blocks: "dict[str, arch.AlwaysBlock]" _instruction_sets: "dict[str, arch.InstructionSet]" @@ -38,8 +38,7 @@ class ArchitectureModelBuilder(CoreDSL2Visitor): def __init__(self): super().__init__() self._constants = {} - # self._instructions = {} - self._instructions = [] + self._instructions = {} self._functions = {} self._always_blocks = {} self._instruction_sets = {} @@ -85,8 +84,7 @@ def visitInstruction_set(self, ctx: CoreDSL2Parser.Instruction_setContext): constants = {} memories = {} functions = {} - # instructions = {} - instructions = [] + instructions = {} # group contents by type for item in contents: @@ -98,8 +96,7 @@ def visitInstruction_set(self, ctx: CoreDSL2Parser.Instruction_setContext): functions[item.name] = item item.ext_name = name elif isinstance(item, arch.Instruction): - # instructions[(item.code, item.mask)] = item - instructions.append(item) + instructions[(item.code, item.mask)] = item item.ext_name = name elif isinstance(item, arch.AlwaysBlock): pass @@ -175,18 +172,17 @@ def visitInstruction(self, ctx: CoreDSL2Parser.InstructionContext): i = arch.Instruction(ctx.name.text, attributes, encoding, mnemonic, assembly, ctx.behavior, None) self._instr_classes.add(i.size) - # instr_id = (i.code, i.mask) + instr_id = (i.code, i.mask) opcode_str = "{code:0{width}x}:{mask:0{width}x}".format(code=i.code, mask=i.mask, width=i.size//4) i.function_info = FunctionInfoFactory.make(ctx.start.source[1].fileName, ctx.start.start, ctx.stop.stop, ctx.start.line, ctx.stop.line, f"instr_{i.name}_{opcode_str}") # check for duplicate instructions - # if instr_id in self._instructions: - # self._overwritten_instrs.append((self._instructions[instr_id], i)) + if instr_id in self._instructions: + self._overwritten_instrs.append((self._instructions[instr_id], i)) # keep track of instruction - # self._instructions[instr_id] = i - self._instructions.append(i) + self._instructions[instr_id] = i return i diff --git a/m2isar/frontends/coredsl2/parser.py b/m2isar/frontends/coredsl2/parser.py index c4438af4..bcc88501 100644 --- a/m2isar/frontends/coredsl2/parser.py +++ b/m2isar/frontends/coredsl2/parser.py @@ -16,7 +16,6 @@ from ... import M2Error, M2SyntaxError from ...metamodel import (M2_METAMODEL_VERSION, M2Model, arch, behav, patch_model) -from ...metamodel.utils import expr_simplifier from ...metamodel.code_info import CodeInfoBase from . import expr_interpreter from .architecture_model_builder import ArchitectureModelBuilder @@ -25,14 +24,6 @@ from .load_order import LoadOrder from .utils import make_parser -def try_eval_bool(operation, constants: "dict[str, arch.Constant]", memories: "dict[str, arch.Memory]", memory_aliases: "dict[str, arch.Memory]", - fields: "dict[str, arch.BitFieldDescr]", functions: "dict[str, arch.Function]", warned_fns: "set[str]"): - patch_model(expr_simplifier) - op = operation.generate(None) - if not isinstance(op, behav.IntLiteral): - return None - return op.value != 0 - def main(): parser = argparse.ArgumentParser() @@ -86,8 +77,8 @@ def main(): except M2Error as e: logger.critical("Error building architecture model of core %s: %s", core_name, e) - # for orig, overwritten in arch_builder._overwritten_instrs: - # logger.warning("instr %s from extension %s was overwritten by %s from %s", orig.name, orig.ext_name, overwritten.name, overwritten.ext_name) + for orig, overwritten in arch_builder._overwritten_instrs: + logger.warning("instr %s from extension %s was overwritten by %s from %s", orig.name, orig.ext_name, overwritten.name, overwritten.ext_name) temp_save[core_name] = (c, arch_builder) models[core_name] = c[-1] @@ -213,11 +204,7 @@ def main(): logger.debug("generating instruction behavior") - assert isinstance(core_def.instructions, list) - instructions_by_enc = {} - overwritten_instrs: "list[tuple[arch.Instruction, arch.Instruction]]" = [] - # for instr_def in core_def.instructions.values(): - for instr_def in core_def.instructions: + for instr_def in core_def.instructions.values(): logger.debug("generating instruction %s", instr_def.name) logger.debug("generating attributes") @@ -234,17 +221,6 @@ def main(): sys.exit(1) instr_def.attributes[attr_name] = ops - if arch.InstrAttribute.ENABLE in instr_def.attributes: - enable_attr = instr_def.attributes[arch.InstrAttribute.ENABLE] - assert isinstance(enable_attr, list) - assert len(enable_attr) == 1 - enable_attr = enable_attr[0] - enable = try_eval_bool(enable_attr, core_def.constants, core_def.memories, core_def.memory_aliases, instr_def.fields, core_def.functions, warned_fns) - if enable is not None: - assert isinstance(enable, bool) - instr_def.attributes.pop(arch.InstrAttribute.ENABLE) - if not enable: - continue behav_builder = BehaviorModelBuilder(core_def.constants, core_def.memories, core_def.memory_aliases, instr_def.fields, core_def.functions, warned_fns) @@ -274,15 +250,6 @@ def main(): #op.statements.insert(0, pc_inc) op.statements = always_block_statements + op.statements instr_def.operation = op - instr_id = (instr_def.code, instr_def.mask) - # check for duplicate instructions - if instr_id in instructions_by_enc: - overwritten_instrs.append((instructions_by_enc[instr_id], instr_def)) - instructions_by_enc[instr_id] = instr_def - core_def.instructions = instructions_by_enc - assert isinstance(core_def.instructions, dict) - for orig, overwritten in overwritten_instrs: - logger.warning("instr %s from extension %s was overwritten by %s from %s", orig.name, orig.ext_name, overwritten.name, overwritten.ext_name) logger.info("dumping model") with open(model_path / (abs_top_level.stem + '.m2isarmodel'), 'wb') as f: diff --git a/m2isar/metamodel/arch.py b/m2isar/metamodel/arch.py index 5d809274..adcd7e9f 100644 --- a/m2isar/metamodel/arch.py +++ b/m2isar/metamodel/arch.py @@ -18,7 +18,7 @@ from typing import TYPE_CHECKING, Any, Union from .. import M2TypeError -from .behav import BaseNode, Operation, NumberLiteral +from .behav import BaseNode, Operation if TYPE_CHECKING: from .code_info import FunctionInfo @@ -28,11 +28,8 @@ def get_const_or_val(arg) -> int: if isinstance(arg, Constant): return arg.value - if isinstance(arg, NumberLiteral): - arg = arg.value - if isinstance(arg, BaseNode): - arg = arg.generate(None) + return arg.generate(None) return arg @@ -70,10 +67,7 @@ def __init__(self, name, size: ValOrConst): def size(self) -> int: """Returns the resolved size, by calling get_const_or_val on _size.""" - ret = get_const_or_val(self._size) - if ret is None: - return None - return int(ret) + return get_const_or_val(self._size) @property def actual_size(self): @@ -566,7 +560,7 @@ class CoreDef(Named): """A class representing an entire CPU core. Contains the collected attributes of multiple InstructionSets.""" def __init__(self, name, contributing_types: "list[str]", template: str, constants: "dict[str, Constant]", memories: "dict[str, Memory]", - memory_aliases: "dict[str, Memory]", functions: "dict[str, Function]", instructions: "dict[tuple[int, int], Instruction] | list[Instruction]", + memory_aliases: "dict[str, Memory]", functions: "dict[str, Function]", instructions: "dict[tuple[int, int], Instruction]", instr_classes: "set[int]", intrinsics: "dict[str, Intrinsic]"): self.contributing_types = contributing_types @@ -587,9 +581,13 @@ def __init__(self, name, contributing_types: "list[str]", template: str, constan self.irq_pending_memory = None self.intrinsics = intrinsics - self._instructions_by_ext = None + self.instructions_by_ext = defaultdict(dict) self.functions_by_ext = defaultdict(dict) - self._instructions_by_class = None + self.instructions_by_class = defaultdict(dict) + + for (code, mask), instr_def in self.instructions.items(): + self.instructions_by_ext[instr_def.ext_name][(code, mask)] = instr_def + self.instructions_by_class[instr_def.size][(code, mask)] = instr_def for fn_name, fn_def in self.functions.items(): self.functions_by_ext[fn_def.ext_name][fn_name] = fn_def @@ -611,23 +609,3 @@ def __init__(self, name, contributing_types: "list[str]", template: str, constan self.irq_pending_memory = mem super().__init__(name) - - @property - def instructions_by_ext(self): - if self._instructions_by_ext is not None: - return self._instructions_by_ext - assert isinstance(self.instructions, dict) - self._instructions_by_ext = defaultdict(dict) - for (code, mask), instr_def in self.instructions.items(): - self._instructions_by_ext[instr_def.ext_name][(code, mask)] = instr_def - return self._instructions_by_ext - - @property - def instructions_by_class(self): - if self._instructions_by_class is not None: - return self._instructions_by_class - assert isinstance(self.instructions, dict) - self._instructions_by_class = defaultdict(dict) - for (code, mask), instr_def in self.instructions.items(): - self._instructions_by_class[instr_def.size][(code, mask)] = instr_def - return self._instructions_by_class diff --git a/m2isar/metamodel/behav.py b/m2isar/metamodel/behav.py index c6b7660d..0d43a901 100644 --- a/m2isar/metamodel/behav.py +++ b/m2isar/metamodel/behav.py @@ -93,18 +93,11 @@ class NumberLiteral(BaseNode): def __init__(self, value, line_info=None): super().__init__(line_info) - self._value = value + self.value = value def __repr__(self): return f"NumberLiteral({self.value})" - @property - def value(self) -> int: - """Returns the resolved value.""" - if isinstance(self, IntLiteral): - return int(self._value) - return self._value - class IntLiteral(NumberLiteral): """A more precise class holding only integer literals.""" @@ -117,9 +110,6 @@ def __init__(self, value: int, bit_size: int=None, signed: bool=None, line_info= else: self.bit_size = bit_size - if isinstance(self.bit_size, IntLiteral): - self.bit_size = self.bit_size.value - self.bit_size = max(1, self.bit_size) if signed is None: @@ -130,9 +120,6 @@ def __init__(self, value: int, bit_size: int=None, signed: bool=None, line_info= def __repr__(self): return f"IntLiteral({self.value}, {self.bit_size}, {self.signed})" - def __int__(self): - return self.value - class StringLiteral(BaseNode): """A string constant""" @@ -235,24 +222,15 @@ class TypeConv(BaseNode): def __init__(self, data_type, size, expr: BaseNode, line_info=None): super().__init__(line_info) self.data_type = data_type - self._size = size + self.size = size self.expr = expr - @property - def size(self) -> int: - """Returns the resolved size.""" - if isinstance(self._size, IntLiteral): - return int(self._size) - return self._size - - @property - def actual_size(self) -> int: - """Returns the actual size.""" if self.size is not None: - actual_size = 1 << (int(self.size) - 1).bit_length() - actual_size = max(actual_size, 8) - return actual_size - return None + self.actual_size = 1 << (self.size - 1).bit_length() + self.actual_size = max(self.actual_size, 8) + + else: + self.actual_size = None class Callable(BaseNode): """A generic invocation of a callable.""" diff --git a/pyproject.toml b/pyproject.toml index 7772c995..f71860d4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,7 @@ maintainers = [ ] dynamic = ["version"] requires-python = ">=3.8" -license = "Apache-2.0" +license = {text = "Apache-2.0"} readme = "README.md" dependencies = [ "mako",