Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 3 additions & 9 deletions m2isar/backends/etiss/instruction_transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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:
Expand Down
20 changes: 8 additions & 12 deletions m2isar/frontends/coredsl2/architecture_model_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]"
Expand All @@ -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 = {}
Expand Down Expand Up @@ -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:
Expand All @@ -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
Expand Down Expand Up @@ -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

Expand Down
39 changes: 3 additions & 36 deletions m2isar/frontends/coredsl2/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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()
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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")

Expand All @@ -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)
Expand Down Expand Up @@ -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:
Expand Down
42 changes: 10 additions & 32 deletions m2isar/metamodel/arch.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
36 changes: 7 additions & 29 deletions m2isar/metamodel/behav.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Expand All @@ -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:
Expand All @@ -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"""
Expand Down Expand Up @@ -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."""
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Loading