Skip to content

Commit 395bf6f

Browse files
committed
Add modm style pioasm output
1 parent 08b5f66 commit 395bf6f

File tree

2 files changed

+129
-0
lines changed

2 files changed

+129
-0
lines changed

pioasm/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ target_sources(pioasm PRIVATE c_sdk_output.cpp)
2424
target_sources(pioasm PRIVATE python_output.cpp)
2525
target_sources(pioasm PRIVATE hex_output.cpp)
2626
target_sources(pioasm PRIVATE ada_output.cpp)
27+
target_sources(pioasm PRIVATE modm_output.cpp)
2728
target_sources(pioasm PRIVATE ${PIOASM_EXTRA_SOURCE_FILES})
2829

2930
if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND

pioasm/modm_output.cpp

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/*
2+
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
#include <algorithm>
8+
#include <iostream>
9+
#include "output_format.h"
10+
#include "pio_disassembler.h"
11+
12+
struct modm_output : public output_format {
13+
struct factory {
14+
factory() {
15+
output_format::add(new modm_output());
16+
}
17+
};
18+
19+
modm_output() : output_format("modm") {}
20+
21+
std::string get_description() override {
22+
return "C++ header suitable for use with the modm library";
23+
}
24+
25+
void output_symbols(FILE *out, std::string prefix, const std::vector<compiled_source::symbol> &symbols) {
26+
int count = 0;
27+
for (const auto &s : symbols) {
28+
if (!s.is_label) {
29+
fprintf(out, "static constexpr auto %s%s = %d;\n", prefix.c_str(), s.name.c_str(), s.value);
30+
count++;
31+
}
32+
}
33+
if (count) {
34+
fprintf(out, "\n");
35+
count = 0;
36+
}
37+
for (const auto &s : symbols) {
38+
if (s.is_label) {
39+
fprintf(out, "static constexpr uint8_t %soffset_%s %du\n", prefix.c_str(), s.name.c_str(), s.value);
40+
count++;
41+
}
42+
}
43+
if (count) {
44+
fprintf(out, "\n");
45+
}
46+
}
47+
48+
void header(FILE *out, std::string msg) {
49+
std::string dashes = std::string(msg.length(), '-');
50+
fprintf(out, "// %s\n", dashes.c_str());
51+
fprintf(out, "// %s\n", msg.c_str());
52+
fprintf(out, "// %s\n", dashes.c_str());
53+
fprintf(out, "\n");
54+
}
55+
56+
int output(std::string destination, std::vector<std::string> output_options,
57+
const compiled_source &source) override {
58+
59+
for (const auto &program : source.programs) {
60+
for(const auto &p : program.lang_opts) {
61+
if (p.first.size() >= name.size() && p.first.compare(0, name.size(), name) == 0) {
62+
std::cerr << "warning: " << name << " does not support output options; " << p.first << " lang_opt ignored.\n";
63+
}
64+
}
65+
}
66+
FILE *out = open_single_output(destination);
67+
if (!out) return 1;
68+
69+
header(out, "This file is autogenerated by pioasm; do not edit!");
70+
71+
fprintf(out, "#pragma once\n");
72+
fprintf(out, "#include <modm/platform/pio/program.hpp>\n\n");
73+
fprintf(out, "namespace modm::generated\n{\n\n");
74+
75+
output_symbols(out, "", source.global_symbols);
76+
77+
for (const auto &program : source.programs) {
78+
fprintf(out, "namespace %s\n{\n\n", program.name.c_str());
79+
80+
std::string prefix = "";
81+
82+
output_symbols(out, prefix, program.symbols);
83+
84+
fprintf(out, "static constinit uint16_t %sinstructions[] =\n{\n", prefix.c_str());
85+
for (int i = 0; i < (int)program.instructions.size(); i++) {
86+
const auto &inst = program.instructions[i];
87+
if (i == program.wrap_target) {
88+
fprintf(out, "\t\t\t//\t\t.wrap_target\n");
89+
}
90+
fprintf(out, "\t0x%04x,\t// %2d:\t%s\n", inst, i,
91+
disassemble(inst, program.sideset_bits_including_opt.get(), program.sideset_opt).c_str());
92+
if (i == program.wrap) {
93+
fprintf(out, "\t\t\t//\t\t.wrap\n");
94+
}
95+
}
96+
fprintf(out, "};\n");
97+
fprintf(out, "\n");
98+
99+
fprintf(out, "static constinit PioProgram %sprogram\n{\n", prefix.c_str());
100+
fprintf(out, "\t%sinstructions,\n", prefix.c_str());
101+
fprintf(out, "\t%d,\t\t// offset\n", program.origin.get());
102+
fprintf(out, "\t%d,\t\t// wrap_target\n", program.wrap_target);
103+
fprintf(out, "\t%d,\t\t// wrap\n", program.wrap);
104+
fprintf(out, "\t%d,\t\t// size_set_count\n", program.sideset_bits_including_opt.get());
105+
fprintf(out, "\t%s,\t// side_set_optional\n", program.sideset_opt ? "true" : "false");
106+
fprintf(out, "\t%s,\t// side_set_pindir\n", program.sideset_pindirs ? "true" : "false");
107+
fprintf(out, "};\n\n");
108+
109+
// todo maybe have some code blocks inside or outside here?
110+
for(const auto& o : program.code_blocks) {
111+
fprintf(out, "\n");
112+
if (o.first == name) {
113+
for(const auto &contents : o.second) {
114+
fprintf(out, "%s", contents.c_str());
115+
fprintf(out, "\n");
116+
}
117+
}
118+
}
119+
120+
fprintf(out, "} // namespace %s\n\n", program.name.c_str());
121+
}
122+
fprintf(out, "} // namespace modm::generated\n");
123+
if (out != stdout) { fclose(out); }
124+
return 0;
125+
}
126+
};
127+
128+
static modm_output::factory creator;

0 commit comments

Comments
 (0)