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
6cf6e75
support is_float_reg attr
PhilippvK Mar 23, 2023
f60a420
fix typos in FloatRegfields
PhilippvK Apr 19, 2023
814466a
float_reg_file fixes
PhilippvK Sep 16, 2025
261032a
introduce CSRField and IS_CSR_REG
PhilippvK Sep 16, 2025
ab479db
m2isar/backends/etiss/templates/etiss_arch_cmake.mako: add code to co…
PhilippvK Sep 16, 2025
236aebe
m2isar/backends/etiss/writer.py: parse gdb xml descriptions (wip)
PhilippvK Sep 17, 2025
d5f5ffe
add automated generation of virtualstruct fields based on aliases and…
PhilippvK Sep 17, 2025
ba542f4
Merge branch 'coredsl2' into etiss-gdbserver-xml
PhilippvK Mar 30, 2026
0c03de0
lint templates
PhilippvK Mar 30, 2026
c762b4f
m2isar/backends/etiss/templates/etiss_arch_specific_h.mako: add missi…
PhilippvK Mar 30, 2026
481fecf
m2isar/backends/etiss/virtualstruct_utils.py: improve assert msg
PhilippvK Mar 30, 2026
5cec8e3
add and handle IS_VECTOR_REG attribute
PhilippvK Apr 7, 2026
c6e8505
annotate gdb mapping with reg/alias names
PhilippvK Apr 7, 2026
2888a84
improve csr detection
PhilippvK Apr 7, 2026
7fed191
update virtualstruct _read and _write for new api
PhilippvK Apr 7, 2026
a338b36
fix etiss_arch_specific_h.mako template (float_reg -> csr_reg)
PhilippvK Apr 7, 2026
50f7d99
Support ETISS Writer --fill-mode arg to auto-fill otherwise hardcoded…
PhilippvK Apr 24, 2026
d19fbee
Merge pull request #86 from tum-ei-eda/etiss-gdbserver-xml
PhilippvK Apr 27, 2026
529f0c4
m2isar/backends/etiss/templates: lint
PhilippvK Apr 27, 2026
7ee8471
m2isar/backends/etiss/templates: implement jitFiles and helpers to su…
PhilippvK May 6, 2026
b4873b3
Merge remote-tracking branch 'tumeda/coredsl2' into develop
PhilippvK Jun 15, 2026
333bdf4
Merge pull request #93 from tum-ei-eda/etiss-arch-plugins-outoftree
PhilippvK Jun 15, 2026
618113e
Merge remote-tracking branch 'tumeda/coredsl2' into develop
PhilippvK Jun 15, 2026
03b8ccd
Merge branch 'coredsl2' into develop
PhilippvK Jun 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
79 changes: 62 additions & 17 deletions m2isar/backends/etiss/architecture_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def build_reg_hierarchy(reg: arch.Memory, ptr_regs: "list[arch.Memory]", actual_
def write_arch_cpp(core: arch.CoreDef, start_time: str, output_path: pathlib.Path, aliased_regnames: bool=True):
"""Generate {CoreName}Arch.cpp file. Contains mainly register initialization code."""

arch_header_template = Template(filename=str(template_dir/'etiss_arch_cpp.mako'))
arch_cpp_template = Template(filename=str(template_dir/'etiss_arch_cpp.mako'))

ptr_regs = []
actual_regs = []
Expand All @@ -122,13 +122,17 @@ def write_arch_cpp(core: arch.CoreDef, start_time: str, output_path: pathlib.Pat

# generate main register file names for ETISS's 'char* reg_name[]'
reg_names = [f"{core.main_reg_file.name}{n}" for n in range(core.main_reg_file.data_range.length)]
if core.float_reg_file is not None:
reg_names += [f"{core.float_reg_file.name}{n}" for n in range(core.float_reg_file.data_range.length)]
# TODO(annnnna42): add float reg names (F0-F31) here

# if main register file entries have aliases optionally use these for 'char* reg_name[]'
if aliased_regnames:
for child in core.main_reg_file.children:
reg_names[child.range.lower] = child.name
# TODO(annnnna42): add float reg aliases here

txt = arch_header_template.render(
txt = arch_cpp_template.render(
start_time=start_time,
core_name=core.name,
instr_classes=sorted(core.instr_classes),
Expand All @@ -145,11 +149,11 @@ def write_arch_cpp(core: arch.CoreDef, start_time: str, output_path: pathlib.Pat
f.write(txt)

def write_arch_lib(core: arch.CoreDef, start_time: str, output_path: pathlib.Path):
arch_header_template = Template(filename=str(template_dir/'etiss_arch_lib.mako'))
arch_lib_template = Template(filename=str(template_dir/'etiss_arch_lib.mako'))

logger.info("writing architecture lib")

txt = arch_header_template.render(
txt = arch_lib_template.render(
start_time=start_time,
core_name=core.name
)
Expand All @@ -158,21 +162,55 @@ def write_arch_lib(core: arch.CoreDef, start_time: str, output_path: pathlib.Pat
f.write(txt)

def write_arch_specific_header(core: arch.CoreDef, start_time: str, output_path: pathlib.Path):
arch_header_template = Template(filename=str(template_dir/'etiss_arch_specific_h.mako'))
arch_specific_header_template = Template(filename=str(template_dir/'etiss_arch_specific_h.mako'))

logger.info("writing architecture specific header")

txt = arch_header_template.render(
txt = arch_specific_header_template.render(
start_time=start_time,
core_name=core.name,
main_reg=core.main_reg_file
main_reg=core.main_reg_file,
float_reg=core.float_reg_file,
vector_reg=core.vector_reg_file,
csr_reg=core.csr_reg_file
)

with open(output_path / f"{core.name}ArchSpecificImp.h", "w", encoding="utf-8") as f:
f.write(txt)

def write_arch_specific_cpp(core: arch.CoreDef, start_time: str, output_path: pathlib.Path):
arch_header_template = Template(filename=str(template_dir/'etiss_arch_specific_cpp.mako'))
def write_arch_specific_cpp(core: arch.CoreDef, start_time: str, output_path: pathlib.Path, virtualstruct_regs: dict, fill_mode: str):
fill_jit_extensions=None
fill_length_updater=None
fill_endianess_compensation=None
assert isinstance(fill_mode, str)
fill_mode = fill_mode.lower()
if fill_mode == "auto":
extra_headers = set()
extra_libs = set()
extra_header_paths = set()
extra_lib_paths = set()
has_softfloat = core.float_reg_file is not None
has_softvector = core.vector_reg_file is not None
extra_header_paths.add("etiss/jit")
extra_lib_paths.add("etiss/jit")
if has_softfloat:
extra_headers.add("etiss/jit/libsoftfloat.h")
extra_libs.add("softfloat")
if has_softvector:
extra_headers.add("etiss/jit/libsoftvector.h")
extra_headers.add("etiss/jit/softvector.h")
extra_libs.add("softvector")
extra_libs.add("etiss_softvector")
fill_jit_extensions = Template(filename=str(template_dir/'etiss_jit_extensions.mako')).render(
extra_headers=";".join(sorted(list(extra_headers))),
extra_libs=";".join(sorted(list(extra_libs))),
extra_header_paths=";".join(sorted(list(extra_header_paths))),
extra_lib_paths=";".join(sorted(list(extra_lib_paths))),
)
fill_length_updater = Template(filename=str(template_dir/'etiss_length_updater.mako')).render(core_name=core.name)
else:
assert fill_mode == "empty", f"Unsupported fill_mode: {fill_mode}"
arch_source_template = Template(filename=str(template_dir/'etiss_arch_specific_cpp.mako'))

error_fn = None

Expand Down Expand Up @@ -212,37 +250,44 @@ def write_arch_specific_cpp(core: arch.CoreDef, start_time: str, output_path: pa
raise M2TypeError(f"IRQ enable mask of {core.global_irq_en_memory.name} is not compile static")
global_irq_en_mask = attr.value

txt = arch_header_template.render(
txt = arch_source_template.render(
start_time=start_time,
core_name=core.name,
main_reg=core.main_reg_file,
float_reg=core.float_reg_file,
irq_en_reg=core.irq_en_memory,
irq_pending_reg=core.irq_pending_memory,
global_irq_en_reg=core.global_irq_en_memory,
global_irq_en_mask=global_irq_en_mask,
error_callbacks=error_callbacks,
error_fn=error_fn
error_fn=error_fn,
virtualstruct_regs=virtualstruct_regs,
fill_jit_extensions=fill_jit_extensions,
fill_length_updater=fill_length_updater,
fill_endianess_compensation=fill_endianess_compensation,
)

with open(output_path / f"{core.name}ArchSpecificImp.cpp", "w", encoding="utf-8") as f:
f.write(txt)

def write_arch_gdbcore(core: arch.CoreDef, start_time: str, output_path: pathlib.Path):
arch_header_template = Template(filename=str(template_dir/'etiss_arch_gdbcore.mako'))
def write_arch_gdbcore(core: arch.CoreDef, start_time: str, output_path: pathlib.Path, gdb_mapping: dict):
arch_gdbcore_template = Template(filename=str(template_dir/'etiss_arch_gdbcore.mako'))

logger.info("writing gdbcore")

txt = arch_header_template.render(
txt = arch_gdbcore_template.render(
start_time=start_time,
core_name=core.name,
main_reg=core.main_reg_file
main_reg=core.main_reg_file,
float_reg=core.float_reg_file,
mapping=gdb_mapping,
)

with open(output_path / f"{core.name}GDBCore.h", "w", encoding="utf-8") as f:
f.write(txt)

def write_arch_cmake(core: arch.CoreDef, start_time: str, output_path: pathlib.Path, separate: bool):
arch_header_template = Template(filename=str(template_dir/'etiss_arch_cmake.mako'))
arch_cmake_template = Template(filename=str(template_dir/'etiss_arch_cmake.mako'))

logger.info("writing CMakeLists")

Expand All @@ -253,7 +298,7 @@ def write_arch_cmake(core: arch.CoreDef, start_time: str, output_path: pathlib.P
if separate:
arch_files += [f'{core.name}_{ext_name}Instr.cpp' for ext_name in core.contributing_types if len(core.instructions_by_ext[ext_name]) > 0]

txt = arch_header_template.render(
txt = arch_cmake_template.render(
start_time=start_time,
core_name=core.name,
arch_files=arch_files
Expand Down
15 changes: 14 additions & 1 deletion m2isar/backends/etiss/templates/etiss_arch_cmake.mako
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,17 @@ add_custom_command(
)
INSTALL(FILES "$${}{CMAKE_CURRENT_LIST_DIR}/$${}{PROJECT_NAME}Funcs.h" DESTINATION "include/jit/Arch/$${}{PROJECT_NAME}")

ETISSPluginArch($${}{PROJECT_NAME})
# handle gdbserver xml files
if(EXISTS "$${}{CMAKE_CURRENT_SOURCE_DIR}/xml")
add_custom_target(copy_$${}{PROJECT_NAME}_xml ALL
COMMAND $${}{CMAKE_COMMAND} -E make_directory
"$${}{CMAKE_CURRENT_LIST_DIR}/xml"
COMMAND $${}{CMAKE_COMMAND} -E copy_directory
"$${}{CMAKE_CURRENT_LIST_DIR}/xml"
"$${}{ETISS_BINARY_DIR}/xml/$${}{PROJECT_NAME}"
)
add_dependencies($${}{PROJECT_NAME} copy_$${}{PROJECT_NAME}_xml)
install(DIRECTORY $${}{CMAKE_CURRENT_SOURCE_DIR}/xml/ DESTINATION xml/$${}{PROJECT_NAME})
endif()

ETISSPluginArch($${}{PROJECT_NAME})
27 changes: 25 additions & 2 deletions m2isar/backends/etiss/templates/etiss_arch_gdbcore.mako
Original file line number Diff line number Diff line change
Expand Up @@ -43,22 +43,45 @@ class ${core_name}GDBCore : public etiss::plugin::gdb::GDBCore
public:
std::string mapRegister(unsigned index)
{
% if mapping is None:
if (index < ${main_reg.range.length})
{
std::stringstream ss;
ss << "${main_reg.name}" << index;
return ss.str();
}
% if float_reg is not None:
if ((${main_reg.range.length} < index) && (index < ${main_reg.range.length + float_reg.range.length + 1}))
{
std::stringstream ss;
ss << "${float_reg.name}" << (index - ${main_reg.range.length + 1});
return ss.str();
}
if ((${main_reg.range.length + float_reg.range.length} < index) && (index < ${main_reg.range.length + float_reg.range.length + 5}))
{ // FCSR
std::stringstream ss;
ss << "CSR" << (index - ${main_reg.range.length + float_reg.range.length + 1});
return ss.str();
}
% endif
% endif
switch (index)
{
% if mapping is not None:
% for regnum, (name, name2) in mapping.items():
case ${regnum}:
return "${name2}"; // ${name}
% endfor
% else:
case ${main_reg.range.length}:
return "instructionPointer";
% endif
/**************************************************************************
* Further register should be added here to send data over gdbserver *
* Further register should be added here to send data over gdbserver *
**************************************************************************/
}
return "";
}
}

unsigned mapRegister(std::string name) { return INVALIDMAPPING; }

Expand Down
14 changes: 14 additions & 0 deletions m2isar/backends/etiss/templates/etiss_arch_h.mako
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,20 @@ class ${core_name}Arch : public etiss::CPUArch
*/
virtual etiss::int32 handleException(etiss::int32 code, ETISS_CPU *cpu);

/**
@brief This function will return the base installation directory of the ArchLib

@see ${core_name}ArchSpecificImp.h
*/
virtual std::string installDir() const;

/**
@brief This function will return the include prefix relative to the base installation directory of the ArchLib

@see ${core_name}ArchSpecificImp.h
*/
virtual std::string jitFiles() const;

/**
@brief This function is called during CPUArch initialization

Expand Down
85 changes: 82 additions & 3 deletions m2isar/backends/etiss/templates/etiss_arch_specific_cpp.mako
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "${core_name}Arch.h"
#include "${core_name}ArchSpecificImp.h"
#include "${core_name}Funcs.h"
#include "etiss/Memory.h"

/**
@brief This function will be called automatically in order to handling exceptions such as interrupt, system call,
Expand Down Expand Up @@ -48,6 +49,58 @@ etiss::int32 ${core_name}Arch::handleException(etiss::int32 cause, ETISS_CPU *cp
return 0;
}

/**
@brief See etiss/src/Misc.cpp
*/
static etiss::ModuleHandle GetCurrentModule()
{
static etiss::ModuleHandle hModule = 0;

if (!hModule)
{
hModule = etiss::GetModuleByAddress((uintptr_t)GetCurrentModule);
}

return hModule;
}

/**
@brief See etiss/src/Misc.cpp
*/
static std::string GetCurrentModulePath()
{
static std::string modulePath;

if (modulePath == "")
{
modulePath = etiss::GetModulePath(GetCurrentModule());
}

return modulePath;
}

/**
@brief Resolves the ETISS install dir for both in-tree as well as out-of-tree builds
*/
std::string ${core_name}Arch::installDir() const
{
auto archLib = GetCurrentModulePath();
auto libPathLoc = archLib.find_last_of("/\\");
auto libPath = archLib.substr(0, libPathLoc);
auto pluginsPathLoc = libPath.find_last_of("/\\");
auto pluginsPath = libPath.substr(0, pluginsPathLoc);
auto archPathLoc = pluginsPath.find_last_of("/\\");
return libPath.substr(0, archPathLoc);
}

/**
@brief This function is called during InstrSet initialization returns path to jit includes
*/
std::string ${core_name}Arch::jitFiles() const
{
return installDir() + "/include/jit";
}

/**
@brief This function is called during CPUArch initialization

Expand All @@ -74,6 +127,13 @@ etiss::int32 ${core_name}Arch::handleException(etiss::int32 cause, ETISS_CPU *cp
*/
void ${core_name}Arch::initInstrSet(etiss::instr::ModedInstructionSet &mis) const
{
% if fill_jit_extensions is not None:
${fill_jit_extensions}
% else:
/**************************************************************************
* JIT extensions should be defined here *
**************************************************************************/
% endif
if (false) {
// Pre-compilation of instruction set to view instruction tree. Enable by setting 'true' above.

Expand Down Expand Up @@ -104,9 +164,13 @@ ${callback},

%endfor

% if fill_length_updater is not None:
${fill_length_updater}
% else:
/**************************************************************************
* vis->length_updater_ should be replaced here *
**************************************************************************/
% endif
}

/**
Expand Down Expand Up @@ -134,21 +198,36 @@ ${callback},
*/
void ${core_name}Arch::compensateEndianess(ETISS_CPU *cpu, etiss::instr::BitArray &ba) const
{
% if fill_endianess_compensation is not None:
${fill_endianess_compensation}
% else:
/**************************************************************************
* Endianess compensation *
**************************************************************************/
% endif
}

std::shared_ptr<etiss::VirtualStruct> ${core_name}Arch::getVirtualStruct(ETISS_CPU *cpu)
{
auto ret = etiss::VirtualStruct::allocate(cpu, [](etiss::VirtualStruct::Field *f) { delete f; });

for (uint32_t i = 0; i < ${main_reg.range.length}; ++i)
% if virtualstruct_regs is not None:
% for virtualstruct_class, idxs in virtualstruct_regs.items():
% for idx in idxs:
% if isinstance(idx, range):
for (uint32_t i = ${idx.start}; i < ${idx.stop}; i += ${idx.step})
{
ret->addField(new RegField_${core_name}(*ret, i));
ret->addField(new ${virtualstruct_class}_${core_name}(*ret, i));
}
% elif idx is None:
ret->addField(new ${virtualstruct_class}_${core_name}(*ret));
% else:
ret->addField(new ${virtualstruct_class}_${core_name}(*ret, ${idx}));
% endif
% endfor
% endfor
% endif

ret->addField(new pcField_${core_name}(*ret));
return ret;
}

Expand Down
Loading
Loading