Skip to content

Commit

Permalink
Upd, general reformatting
Browse files Browse the repository at this point in the history
  • Loading branch information
dimi-it committed Oct 29, 2023
1 parent 28dc169 commit bd18081
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 78 deletions.
3 changes: 3 additions & 0 deletions byron/classes/evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ class MakefileEvaluator(EvaluatorABC):
* `make_flags`: Flags for make. Default is just ``'-s'`` (be quiet)
* `makefile`: Name of the Makefile itself
* `timeout`: Number of seconds to wait for make completion (default: 60, use ``None`` to wait indefinitely)
* `stdout_cleaner`: Callable function to clean the stdout, of the executed program, into an evaluable output if needed
Use option `strip_phenotypes` (see :py:class:`byron.classes.evaluator.EvaluatorABC`) to convert the phenotype into a
single-line string.
Expand Down Expand Up @@ -348,6 +349,8 @@ def __init__(
Name of the makefile
required_files
Files that need to be present for the makefile to work in addition to `makefile` and `filename`
stdout_cleaner
Callable function to clean the stdout
timeout
Seconds to wait for make completion (``None`` indefinitely)
kwargs
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,25 @@

COMMENT = '#'


def define_frame():
register = byron.f.choice_parameter([f"t{n}" for n in range(4)])
int8 = byron.f.integer_parameter(0, 2 ** 8)
register = byron.f.choice_parameter(["zero", *[f"t{n}" for n in range(4)]])
int8 = byron.f.integer_parameter(0, 2**8)

operations_rrr = byron.f.choice_parameter(['add', 'sub'])
operations_rri = byron.f.choice_parameter(['addi'])
op_rrr = byron.f.macro('{op} {r1}, {r2}, {r3}', op=operations_rrr, r1=register, r2=register, r3=register)
op_rri = byron.f.macro('{op} {r1}, {r2}, {imm:#x}', op=operations_rri, r1=register, r2=register, imm=int8)

conditions = byron.f.choice_parameter(
['eq', 'ne', 'ge', 'lt', 'geu', 'ltu']
)
conditions = byron.f.choice_parameter(['eq', 'ne', 'ge', 'lt', 'geu', 'ltu'])
branch = byron.f.macro(
'b{cond} {r1}, {r2}, {label}', cond=conditions, r1=register, r2=register, label=byron.f.local_reference(backward=True, loop=False, forward=True)
)
jump = byron.f.macro(
'j {label}', label=byron.f.local_reference(backward=True, loop=False, forward=True)
'b{cond} {r1}, {r2}, {label}',
cond=conditions,
r1=register,
r2=register,
label=byron.f.local_reference(backward=True, loop=False, forward=True),
)
jump = byron.f.macro('j {label}', label=byron.f.local_reference(backward=True, loop=False, forward=True))

prologue_main = byron.f.macro(
r"""# [prologue_main]
Expand Down Expand Up @@ -59,4 +60,4 @@ def define_frame():

main = byron.framework.sequence([prologue_main, core_main, epilogue_main])

return main
return main
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,23 @@

import byron
import library_riscv as library
from riscv import Riscv, RegisterMap
from riscv.riscv_evaluator import RiscvEvaluator
from riscv.register_map import RegisterMap


def evaluation_function(registers: Sequence[int]) -> int:
return sum(int(i) for i in "{0:b}".format(registers[0]))


def main():
top_frame = library.define_frame()
register_map = RegisterMap()
register_map.include_registers(("t0","t1"))
riscv = Riscv(register_map, evaluation_func=evaluation_function)
register_map.include_registers(("t0",))
riscv = RiscvEvaluator(register_map, evaluation_func=evaluation_function)

evaluator = byron.evaluator.MakefileEvaluator('onemax.s', stdout_cleaner=riscv.evaluate_riscv_int_stdout, make_flags=["name=onemax", "-s"], timeout=5)
evaluator = byron.evaluator.MakefileEvaluator(
'onemax.s', stdout_cleaner=riscv.evaluate_riscv_int_stdout, make_flags=["name=onemax", "-s"], timeout=5
)
final_population = byron.ea.vanilla_ea(
top_frame,
evaluator,
Expand Down
96 changes: 55 additions & 41 deletions examples/onemax/onemax-riscv/riscv/register_map.py
Original file line number Diff line number Diff line change
@@ -1,48 +1,22 @@
from __future__ import annotations

__all__ = ['RegisterMap']

from collections import namedtuple
from enum import Enum
from typing import Sequence

"""
_register_map = {
"zero": 0,
"rs": 1,
"sp": 2,
"gp": 3,
"tp": 4,
"t0": 5,
"t1": 6,
"t2": 7,
"s0": 8,
"s1": 9,
"a0": 10,
"a1": 11,
"a2": 12,
"a3": 13,
"a4": 14,
"a5": 15,
"a6": 16,
"a7": 17,
"s2": 18,
"s3": 19,
"s4": 20,
"s5": 21,
"s6": 22,
"s7": 23,
"s8": 24,
"s9": 25,
"s10": 26,
"s11": 27,
"t3": 28,
"t4": 29,
"t5": 30,
"t6": 31,
}
"""


class RegisterMap:
"""Register map of selected number of register for RISCV
The class allow an easy way to convert a subset of the RISCV registers names into a map {register_name: id}
where id is a monotonically increasing integer (starting from 0)
"""

class Sets(Enum):
"""Enum of the various subsets of the RISCV registers"""

temp_reg = 1
saved_reg = 2
argument_reg = 3
Expand All @@ -51,11 +25,43 @@ class Sets(Enum):
_register_sets_details = {
Sets.temp_reg: RegisterSetParameters("t", 7),
Sets.saved_reg: RegisterSetParameters("s", 12),
Sets.argument_reg: RegisterSetParameters("a", 8)
Sets.argument_reg: RegisterSetParameters("a", 8),
}

_register_available = (
"zero", "rs", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6")
"zero",
"rs",
"sp",
"gp",
"tp",
"t0",
"t1",
"t2",
"s0",
"s1",
"a0",
"a1",
"a2",
"a3",
"a4",
"a5",
"a6",
"a7",
"s2",
"s3",
"s4",
"s5",
"s6",
"s7",
"s8",
"s9",
"s10",
"s11",
"t3",
"t4",
"t5",
"t6",
)

def __init__(self):
self._register_map = dict()
Expand All @@ -64,22 +70,30 @@ def __str__(self):
return f"Register map: {str(self.register_map)}"

def include_sets_of_registers(self, registers_sets: Sequence[Sets]):
"""Include one or more subsets of RISCV register in the map"""
for r_set in registers_sets:
r_set_parameters = self._register_sets_details.get(r_set)
self._register_map.update(
{f"{r_set_parameters.name}{i}": i + len(self._register_map) for i in range(r_set_parameters.len) if
f"{r_set_parameters.name}{i}" not in self._register_map})
{
f"{r_set_parameters.name}{i}": i + len(self._register_map)
for i in range(r_set_parameters.len)
if f"{r_set_parameters.name}{i}" not in self._register_map
}
)

def include_registers(self, registers: Sequence[str]):
"""Include one or more RISCV register name in the map"""
for reg in registers:
assert self.check_register_availability(reg), f"Register {reg} not available"
if reg in self._register_map:
continue
self._register_map[reg] = len(self._register_map)

def check_register_availability(self, reg):
"""Check if the register name is a correct RISCV register"""
return reg in self._register_available

@property
def register_map(self):
"""Get the register map"""
return self._register_map
23 changes: 0 additions & 23 deletions examples/onemax/onemax-riscv/riscv/riscv.py

This file was deleted.

51 changes: 51 additions & 0 deletions examples/onemax/onemax-riscv/riscv/riscv_evaluator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
__all__ = ['RiscvEvaluator']

from typing import Sequence, Callable
from .register_map import RegisterMap


class RiscvEvaluator:
"""RISCV evaluator, evaluate the stdout coming from a RISCV program execution with --trace-register enabled"""

_wrote_keyword = "-wrote "
_equals_keyword = " = "

def __init__(
self,
covered_register: RegisterMap,
evaluation_func: Callable[[Sequence[int]], Sequence[int] | int] | None = None,
):
r"""
Parameters
----------
covered_register
Register map of the register to evaluate
evaluation_func
Callable function to further evaluate the register content
"""
self._covered_register = covered_register.register_map
self._evaluation_func = evaluation_func if evaluation_func is not None else lambda s: s

def evaluate_riscv_int_stdout(self, stdout: str):
"""Collect the last value present in the integer registers defined in the covered_register and evaluate they based on the
evaluation function
"""
written_registers = [
line.split(RiscvEvaluator._wrote_keyword)[1]
for line in stdout.split('\n')
if RiscvEvaluator._wrote_keyword in line
]
registers = [0 for i in range(len(self._covered_register))]
for write in written_registers:
parts = write.split(RiscvEvaluator._equals_keyword)
if parts[0] not in self._covered_register:
continue
registers[self._covered_register[parts[0]]] = int(parts[1], 16)
return self._evaluation_func(registers)

def evaluate_riscv_float_stdout(self, stdout: str):
"""Collect the last value present in the floating registers defined in the covered_register and evaluate they based on the
evaluation function
"""
"""TODO"""
raise NotImplementedError

0 comments on commit bd18081

Please sign in to comment.