Skip to content

Commit

Permalink
add flag to enable coverage generation
Browse files Browse the repository at this point in the history
  • Loading branch information
wysiwyng committed Apr 4, 2024
1 parent b6f4d99 commit a5c1bd9
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 23 deletions.
2 changes: 1 addition & 1 deletion m2isar/backends/etiss/architecture_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ def write_arch_specific_cpp(core: arch.CoreDef, start_time: str, output_path: pa
error_instr._size = bitsize # pylint: disable=protected-access

error_fields = generate_fields(32, error_instr)
error_callbacks[bitsize] = generate_instruction_callback(core, error_instr, error_fields, True, BlockEndType.NONE)
error_callbacks[bitsize] = generate_instruction_callback(core, error_instr, error_fields, True, BlockEndType.NONE, False)

logger.info("writing architecture specific file")

Expand Down
12 changes: 6 additions & 6 deletions m2isar/backends/etiss/instruction_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def generate_arg_str(arg: arch.FnParam):
arg_name = f" {arg.name}" if arg.name is not None else ""
return f'{instruction_utils.data_type_map[arg.data_type]}{arg.actual_size}{arg_name}'

def generate_functions(core: arch.CoreDef, static_scalars: bool, decls_only: bool):
def generate_functions(core: arch.CoreDef, static_scalars: bool, decls_only: bool, generate_coverage: bool):
"""Return a generator object to generate function behavior code. Uses function
definitions in the core object.
"""
Expand All @@ -47,7 +47,7 @@ def generate_functions(core: arch.CoreDef, static_scalars: bool, decls_only: boo

# set up a transformer context and generate code
context = instruction_utils.TransformerContext(core.constants, core.memories, core.memory_aliases, fn_def.args, fn_def.attributes,
core.functions, 0, core_default_width, core_name, static_scalars, core.intrinsics, True)
core.functions, 0, core_default_width, core_name, static_scalars, core.intrinsics, generate_coverage, True)

logger.debug("generating code for %s", fn_name)

Expand Down Expand Up @@ -139,7 +139,7 @@ def generate_fields(core_default_width, instr_def: arch.Instruction):

return (fields_code, asm_printer_code, seen_fields, enc_idx)

def generate_instruction_callback(core: arch.CoreDef, instr_def: arch.Instruction, fields, static_scalars: bool, block_end_on: BlockEndType):
def generate_instruction_callback(core: arch.CoreDef, instr_def: arch.Instruction, fields, static_scalars: bool, block_end_on: BlockEndType, generate_coverage: bool):
patch_model(instruction_transform)

instr_name = instr_def.name
Expand All @@ -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)
core.functions, enc_idx, core_default_width, core_name, static_scalars, core.intrinsics, generate_coverage)

# force a block end if necessary
if ((arch.InstrAttribute.NO_CONT in instr_def.attributes
Expand Down Expand Up @@ -186,7 +186,7 @@ def generate_instruction_callback(core: arch.CoreDef, instr_def: arch.Instructio

return callback_str

def generate_instructions(core: arch.CoreDef, static_scalars: bool, block_end_on: BlockEndType):
def generate_instructions(core: arch.CoreDef, static_scalars: bool, block_end_on: BlockEndType, generate_coverage: bool):
"""Return a generator object to generate instruction behavior code. Uses instruction
definitions in the core object.
"""
Expand Down Expand Up @@ -230,7 +230,7 @@ def generate_instructions(core: arch.CoreDef, static_scalars: bool, block_end_on
instr_def.operation = new_op
instr_def.throws = True

callback_str = generate_instruction_callback(core, instr_def, fields, static_scalars, block_end_on)
callback_str = generate_instruction_callback(core, instr_def, fields, static_scalars, block_end_on, generate_coverage)

# render code for whole instruction
templ_str = instr_template.render(
Expand Down
17 changes: 9 additions & 8 deletions m2isar/backends/etiss/instruction_transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def operation(self: behav.Operation, context: TransformerContext):
else:
args.append(c)

if self.line_info is not None:
if self.line_info is not None and context.generate_coverage:
CodeInfoTracker.insert(context.arch_name, self.line_info)
code_lines.append(context.wrap_codestring(f"etiss_coverage_count(1, {self.line_info.id});"))

Expand All @@ -59,15 +59,16 @@ def operation(self: behav.Operation, context: TransformerContext):
before_line_infos = []
after_line_infos = []

for l in flatten(arg.line_infos):
if l is not None:
CodeInfoTracker.insert(context.arch_name, l)
if context.generate_coverage:
for l in flatten(arg.line_infos):
if l is not None:
CodeInfoTracker.insert(context.arch_name, l)

if l.placement == LineInfoPlacement.BEFORE:
before_line_infos.append(str(l.id))
if l.placement == LineInfoPlacement.BEFORE:
before_line_infos.append(str(l.id))

elif l.placement == LineInfoPlacement.AFTER:
after_line_infos.append(str(l.id))
elif l.placement == LineInfoPlacement.AFTER:
after_line_infos.append(str(l.id))

if len(before_line_infos) > 0:
code_lines.append(context.wrap_codestring(f"etiss_coverage_count({len(before_line_infos)}, {', '.join(before_line_infos)});"))
Expand Down
3 changes: 2 additions & 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, ignore_static=False):
instr_size: int, native_size: int, arch_name: str, static_scalars: bool, intrinsics, generate_coverage: bool, ignore_static=False):

self.constants = constants
self.memories = memories
Expand All @@ -154,6 +154,7 @@ def __init__(self, constants: "dict[str, arch.Constant]", memories: "dict[str, a
self.arch_name = arch_name
self.intrinsics = intrinsics
self.static_scalars = static_scalars
self.generate_coverage = generate_coverage

self.ignore_static = ignore_static

Expand Down
10 changes: 5 additions & 5 deletions m2isar/backends/etiss/instruction_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

logger = logging.getLogger("instruction_writer")

def write_functions(core: arch.CoreDef, start_time: str, output_path: pathlib.Path, static_scalars: bool):
def write_functions(core: arch.CoreDef, start_time: str, output_path: pathlib.Path, static_scalars: bool, generate_coverage: bool):
"""Generate and write the {CoreName}Funcs.h file for ETISS."""

fn_set_header_template = Template(filename=str(template_dir/'etiss_function_set_header.mako'))
Expand All @@ -42,7 +42,7 @@ def write_functions(core: arch.CoreDef, start_time: str, output_path: pathlib.Pa
funcs_f.write(fn_set_str)

# generate and write function declarations
for fn_name, templ_str in generate_functions(core, static_scalars, True):
for fn_name, templ_str in generate_functions(core, static_scalars, True, generate_coverage):
logger.debug("writing function decl %s", fn_name)
funcs_f.write(templ_str)

Expand All @@ -59,12 +59,12 @@ def write_functions(core: arch.CoreDef, start_time: str, output_path: pathlib.Pa
funcs_f.write(fn_impl_str)

# generate and write function definitions
for fn_name, templ_str in generate_functions(core, static_scalars, False):
for fn_name, templ_str in generate_functions(core, static_scalars, False, generate_coverage):
logger.debug("writing function def %s", fn_name)
funcs_f.write(templ_str)

def write_instructions(core: arch.CoreDef, start_time: str, output_path: pathlib.Path, separate: bool, static_scalars: bool,
block_end_on: BlockEndType):
block_end_on: BlockEndType, generate_coverage: bool):
"""Generate and write the instruction model C++ files for ETISS."""

instr_set_template = Template(filename=str(template_dir/'etiss_instruction_set.mako'))
Expand Down Expand Up @@ -96,6 +96,6 @@ def write_instructions(core: arch.CoreDef, start_time: str, output_path: pathlib
out_f.write(instr_set_str)

# generate instruction behavior models
for instr_name, _, ext_name, templ_str in generate_instructions(core, static_scalars, block_end_on):
for instr_name, _, ext_name, templ_str in generate_instructions(core, static_scalars, block_end_on, generate_coverage):
logger.debug("writing instruction %s", instr_name)
outfiles.get(ext_name, outfiles['default']).write(templ_str)
5 changes: 3 additions & 2 deletions m2isar/backends/etiss/writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ def setup():
parser.add_argument("--static-scalars", action=BooleanOptionalAction, default=True, help="Enable static detection for scalars.")
parser.add_argument("--block-end-on", default="none", choices=[x.name.lower() for x in BlockEndType],
help="Force end translation blocks on no instructions, uncoditional jumps or all jumps.")
parser.add_argument("--coverage", action=BooleanOptionalAction, default=False, help="Generate coverage tracking code into model.")
parser.add_argument("--log", default="info", choices=["critical", "error", "warning", "info", "debug"])
args = parser.parse_args()

Expand Down Expand Up @@ -168,8 +169,8 @@ def main():
write_arch_lib(core, start_time, output_path)
write_arch_cmake(core, start_time, output_path, args.separate)
write_arch_gdbcore(core, start_time, output_path)
write_functions(core, start_time, output_path, args.static_scalars)
write_instructions(core, start_time, output_path, args.separate, args.static_scalars, BlockEndType[args.block_end_on.upper()])
write_functions(core, start_time, output_path, args.static_scalars, args.coverage)
write_instructions(core, start_time, output_path, args.separate, args.static_scalars, BlockEndType[args.block_end_on.upper()], args.coverage)

with open(output_path / "coverage.csv", "w") as f:
for c_id, c_info in sorted(CodeInfoTracker.tracker[core_name].items()):
Expand Down

0 comments on commit a5c1bd9

Please sign in to comment.