Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
f3c1eb0
print warning for implicit truncations (asignment only) (TODO: cli)
PhilippvK Jun 15, 2025
fb24735
print warning for shift width overflows (TODO: cli & LOC)
PhilippvK Jun 15, 2025
e495b58
add warnings manager
PhilippvK Jul 4, 2025
234df0c
warnings: fixes
PhilippvK Apr 13, 2026
b284f1c
warnings: drop comment
PhilippvK Apr 13, 2026
790a44d
warnings: add shift-signed & sign-compare
PhilippvK Apr 13, 2026
ba433c0
fix warnings manager
PhilippvK Apr 15, 2026
5d0f39c
m2isar/metamodel/__init__.py: add helpers load_model & dump_model
PhilippvK Apr 15, 2026
9b511fb
m2isar/metamodel/arch.py: add __repr__ method for DataType
PhilippvK Apr 15, 2026
d65c335
add m2isar/transforms/__init__.py
PhilippvK Apr 15, 2026
963db92
add m2isar/transforms/infer_types
PhilippvK Apr 15, 2026
fd497e2
add m2isar/transforms/validate_behav
PhilippvK Apr 15, 2026
37e874c
m2isar/backends/etiss/warnings.py: add bit-op-missmatch
PhilippvK Apr 15, 2026
94642be
move common warnings code to toplevel
PhilippvK Apr 15, 2026
857f25f
m2isar/backends/etiss/writer.py: add comment
PhilippvK Apr 15, 2026
8ffa0ed
add --validate flag for parser
PhilippvK Apr 15, 2026
a83a381
comment out prints in transforms
PhilippvK Apr 15, 2026
64fa03d
remove redundant warnings code from etiss writer
PhilippvK Apr 15, 2026
9383448
remove print
PhilippvK Apr 15, 2026
aa4a9b9
load_model cleanup
PhilippvK Apr 15, 2026
ff3b867
validate_behav: cleanup visitor
PhilippvK Apr 15, 2026
da1b076
coredsl parser: expose --infer-types (on by default)
PhilippvK Apr 15, 2026
611fea1
infer_types: cleanup
PhilippvK Apr 15, 2026
0a15f88
infer_types: cleanup prints
PhilippvK Apr 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion m2isar/backends/etiss/instruction_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ def generate_instruction_callback(core: arch.CoreDef, instr_def: arch.Instructio
callback_template = Template(filename=str(template_dir/'etiss_instruction_callback.mako'))

context = instruction_utils.TransformerContext(core.constants, core.memories, core.memory_aliases, instr_def.fields, instr_def.attributes,
core.functions, enc_idx, core_default_width, core_name, static_scalars, core.intrinsics, generate_coverage)
core.functions, enc_idx, core_default_width, core_name, static_scalars, core.intrinsics, generate_coverage, False)

# force a block end if necessary
if ((arch.InstrAttribute.NO_CONT in instr_def.attributes
Expand Down
2 changes: 1 addition & 1 deletion m2isar/backends/etiss/instruction_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ class TransformerContext:

def __init__(self, constants: "dict[str, arch.Constant]", memories: "dict[str, arch.Memory]", memory_aliases: "dict[str, arch.Memory]",
fields: "dict[str, arch.BitFieldDescr]", attributes: "list[arch.InstrAttribute]", functions: "dict[str, arch.Function]",
instr_size: int, native_size: int, arch_name: str, static_scalars: bool, intrinsics, generate_coverage: bool, ignore_static=False):
instr_size: int, native_size: int, arch_name: str, static_scalars: bool, intrinsics, generate_coverage: bool, ignore_static: bool = False):

self.constants = constants
self.memories = memories
Expand Down
1 change: 1 addition & 0 deletions m2isar/backends/etiss/writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from .instruction_writer import write_functions, write_instructions


# TODO: not required anymore for Python >= v3.9
class BooleanOptionalAction(argparse.Action):
"""A boolean optional action for argparse, supports automatic generation of --no-x flags."""

Expand Down
28 changes: 22 additions & 6 deletions m2isar/frontends/coredsl2/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,20 @@
from .importer import recursive_import
from .load_order import LoadOrder
from .utils import make_parser
from ...backends.etiss.writer import BooleanOptionalAction # TODO: refactor
from ...transforms.infer_types.transform import infer_types
from ...transforms.validate_behav.validate import validate_behav
from ...warnings import add_warnings_flags, KNOWN_WARNINGS


def main():
parser = argparse.ArgumentParser()
parser.add_argument("top_level", help="The top-level CoreDSL file.")
parser.add_argument("--log", default="info", choices=["critical", "error", "warning", "info", "debug"])
parser.add_argument("-I", dest="includes", action="append", default=[], help="Extra include directories")
parser.add_argument('--infer-types', action=BooleanOptionalAction, default=True, help="Run type inference after parsing.")
parser.add_argument('--validate', action=BooleanOptionalAction, default=False, help="Run validator after parsing.")
add_warnings_flags(parser, KNOWN_WARNINGS, KNOWN_WARNINGS) # only if --validate

args = parser.parse_args()

Expand Down Expand Up @@ -251,14 +258,23 @@ def main():
op.statements = always_block_statements + op.statements
instr_def.operation = op

model_obj = M2Model(
M2_METAMODEL_VERSION,
models,
{},
CodeInfoBase.database
)

if args.infer_types or args.validate:
logger.info("Running type inference")
model_obj = infer_types(model_obj)
if args.validate:
logger.info("Running validator")
warnings_info = args.warnings
validate_behav(model_obj, warnings_info)

logger.info("dumping model")
with open(model_path / (abs_top_level.stem + '.m2isarmodel'), 'wb') as f:
model_obj = M2Model(
M2_METAMODEL_VERSION,
models,
{},
CodeInfoBase.database
)

pickle.dump(model_obj, f)

Expand Down
36 changes: 36 additions & 0 deletions m2isar/metamodel/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,11 @@
the hierarchy.
"""

import pickle
import inspect
import logging
from typing import Union
from pathlib import Path
from dataclasses import dataclass

from . import arch, behav, code_info
Expand Down Expand Up @@ -91,3 +94,36 @@ def __post_init__(self):
self.line_infos[idx] = c
elif isinstance(c, code_info.FunctionInfo):
self.function_infos[idx] = c


def load_model(
model_path: Union[str, Path], allow_missmatch: bool = False
) -> M2Model:
logger = logging.getLogger("load_model")
logger.debug("loading model: %s", str(model_path))
with open(model_path, "rb") as f:
model_obj: M2Model = pickle.load(f)
assert isinstance(model_obj, M2Model), "Expected M2Model"
required_version = M2_METAMODEL_VERSION
if model_obj.model_version != required_version:
err_handler = logger.warning if allow_missmatch else RuntimeError
err_handler("Loaded model version mismatch")
return model_obj


def dump_model(
model_obj: M2Model, out_path: Union[str, Path], ignore_suffix: bool = False
):
logger = logging.getLogger("dump_model")
if not ignore_suffix:
out_path = Path(out_path)
suffix = out_path.suffix
required_suffix = ".m2isarmodel"
if suffix not in [required_suffix]:
assert len(suffix) == 0, f"Invalid suffix: {suffix}"
out_path = out_path.parent / f"{out_path.stem}{required_suffix}"
else:
assert suffix == required_suffix, f"Invalid suffix: {suffix}, Expected: {required_suffix}"
logger.debug("dumping model: %s", out_path)
with open(out_path, "wb") as f:
pickle.dump(model_obj, f)
7 changes: 7 additions & 0 deletions m2isar/metamodel/arch.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,13 @@ def width(self):

return get_const_or_val(self._width)

def __str__(self) -> str:
return f'{super().__repr__()}, width={self.width}, signed={self.signed}'

def __repr__(self):
return self.__str__()


@property
def actual_width(self):
"""Returns the resolved width value rounded to the nearest multiple of 8."""
Expand Down
9 changes: 9 additions & 0 deletions m2isar/transforms/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# SPDX-License-Identifier: Apache-2.0
#
# This file is part of the M2-ISA-R project: https://github.com/tum-ei-eda/M2-ISA-R
#
# Copyright (C) 2024
# Chair of Electrical Design Automation
# Technical University of Munich

"""This module contains various transforms for M2-ISA-R models."""
9 changes: 9 additions & 0 deletions m2isar/transforms/infer_types/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# SPDX-License-Identifier: Apache-2.0
#
# This file is part of the M2-ISA-R project: https://github.com/tum-ei-eda/M2-ISA-R
#
# Copyright (C) 2024
# Chair of Electrical Design Automation
# Technical University of Munich

"""This module contains a type inference pass for M2-ISA-R models."""
70 changes: 70 additions & 0 deletions m2isar/transforms/infer_types/transform.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# SPDX-License-Identifier: Apache-2.0
#
# This file is part of the M2-ISA-R project: https://github.com/tum-ei-eda/M2-ISA-R
#
# Copyright (C) 2022
# Chair of Electrical Design Automation
# Technical University of Munich

"""Type inference for M2-ISA-R metamodel."""

import sys
import argparse
import logging
import pathlib

from m2isar.metamodel import patch_model, load_model, dump_model

from . import visitor


def get_parser():
# read command line args
parser = argparse.ArgumentParser()
parser.add_argument("top_level", help="A .m2isarmodel file.")
parser.add_argument("--log", default="info", choices=["critical", "error", "warning", "info", "debug"])
parser.add_argument("--output", "-o", type=str, default=None)
return parser


def infer_types(model_obj):
logger = logging.getLogger("infer_types")
for _, core_def in model_obj.cores.items():
logger.debug("inferring types for core %s", core_def.name)
patch_model(visitor)
for _, instr_def in core_def.instructions.items():
logger.debug("inferring types for instr %s", instr_def.name)
instr_def.operation.generate(None)
for _, set_def in model_obj.sets.items():
logger.debug("inferring types for set %s", set_def.name)
patch_model(visitor)
for _, instr_def in set_def.instructions.items():
logger.debug("inferring types for instr %s", instr_def.name)
instr_def.operation.generate(None)
return model_obj


def run(args):
# initialize logging
logging.basicConfig(level=getattr(logging, args.log.upper()))

# resolve model paths
top_level = pathlib.Path(args.top_level)

out_path = (top_level.parent / top_level.stem) if args.output is None else args.output
print("out_path", out_path)

model_obj = load_model(top_level)
model_obj = infer_types(model_obj)

dump_model(model_obj, out_path)


def main(argv):
parser = get_parser()
args = parser.parse_args(argv)
run(args)


if __name__ == "__main__":
main(sys.argv[1:])
Loading
Loading