Initial wasm simulator checkpoint

This commit is contained in:
CNC Local
2026-05-22 04:43:21 +08:00
commit 55d9fff9f0
54 changed files with 5523 additions and 0 deletions

120
core/tools/cnc_sim_dump.cpp Normal file
View File

@@ -0,0 +1,120 @@
#include "cnc_sim_api.h"
#include <fstream>
#include <iostream>
#include <sstream>
namespace {
const char *event_type_name(CncSimEventType type) {
switch (type) {
case CNC_SIM_EVENT_ERROR:
return "error";
case CNC_SIM_EVENT_COMMENT:
return "comment";
case CNC_SIM_EVENT_SET_UNITS:
return "set-units";
case CNC_SIM_EVENT_SET_PLANE:
return "set-plane";
case CNC_SIM_EVENT_SET_FEED:
return "set-feed";
case CNC_SIM_EVENT_SET_SPINDLE:
return "set-spindle";
case CNC_SIM_EVENT_TOOL_CHANGE:
return "tool-change";
case CNC_SIM_EVENT_DWELL:
return "dwell";
case CNC_SIM_EVENT_RAPID:
return "rapid";
case CNC_SIM_EVENT_LINEAR_FEED:
return "linear-feed";
case CNC_SIM_EVENT_ARC_FEED:
return "arc-feed";
case CNC_SIM_EVENT_PROBE:
return "probe";
case CNC_SIM_EVENT_PROGRAM_END:
return "program-end";
case CNC_SIM_EVENT_RTCP_PIVOT:
return "rtcp-pivot";
case CNC_SIM_EVENT_KINEMATICS_SWITCH:
return "kinematics-switch";
case CNC_SIM_EVENT_RTCP_STATE:
return "rtcp-state";
case CNC_SIM_EVENT_SET_G5X_OFFSET:
return "set-g5x-offset";
case CNC_SIM_EVENT_SET_G92_OFFSET:
return "set-g92-offset";
case CNC_SIM_EVENT_SET_XY_ROTATION:
return "set-xy-rotation";
default:
return "none";
}
}
void print_pose(const CncSimPose &pose) {
std::cout << "{\"x\":" << pose.x
<< ",\"y\":" << pose.y
<< ",\"z\":" << pose.z
<< ",\"a\":" << pose.a
<< ",\"b\":" << pose.b
<< ",\"c\":" << pose.c
<< ",\"u\":" << pose.u
<< ",\"v\":" << pose.v
<< ",\"w\":" << pose.w << '}';
}
int print_event(const CncSimEvent *event, void *user_data) {
auto *first = static_cast<bool *>(user_data);
if (!*first) {
std::cout << ",\n";
}
*first = false;
std::cout << " {\"type\":\"" << event_type_name(event->type)
<< "\",\"line\":" << event->line
<< ",\"plane\":" << event->plane
<< ",\"tool\":" << event->tool
<< ",\"feed\":" << event->feed
<< ",\"spindle\":" << event->spindle
<< ",\"dwellSeconds\":" << event->dwell_seconds
<< ",\"arcTurns\":" << event->arc_turns
<< ",\"reserved\":" << event->reserved
<< ",\"start\":";
print_pose(event->start);
std::cout << ",\"end\":";
print_pose(event->end);
std::cout << ",\"center\":";
print_pose(event->center);
std::cout << '}';
return 0;
}
std::string read_all(const char *path) {
if (!path || std::string(path) == "-") {
std::ostringstream out;
out << std::cin.rdbuf();
return out.str();
}
std::ifstream file(path);
std::ostringstream out;
out << file.rdbuf();
return out.str();
}
} // namespace
int main(int argc, char **argv) {
std::string program = read_all(argc > 1 ? argv[1] : "-");
CncSimHandle *sim = cnc_sim_create();
bool first = true;
cnc_sim_set_event_callback(sim, print_event, &first);
std::cout << "[\n";
const int rc = cnc_sim_parse_program(sim, program.c_str(), program.size());
std::cout << "\n]\n";
if (rc != 0) {
std::cerr << cnc_sim_last_error(sim) << '\n';
}
cnc_sim_destroy(sim);
return rc == 0 ? 0 : 1;
}

View File

@@ -0,0 +1,250 @@
#include <Python.h>
#include "canon_event_sink.h"
#include "linuxcnc_canon_bridge.h"
#include "simulator_gcode_controls.h"
#include "linuxcnc.h"
#include "nml_intf/interp_return.hh"
#include "nml_intf/canon.hh"
#include "rs274ngc/interp_base.hh"
#include "emc/tooldata/tooldata.hh"
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <cstdlib>
int _task = 0;
char _parameter_file_name[LINELEN];
extern "C" PyObject *PyInit_interpreter(void);
extern "C" PyObject *PyInit_emccanon(void);
extern "C" struct _inittab builtin_modules[];
struct _inittab builtin_modules[] = {
{"interpreter", PyInit_interpreter},
{"emccanon", PyInit_emccanon},
{nullptr, nullptr},
};
namespace {
const char *event_type_name(CncSimEventType type) {
switch (type) {
case CNC_SIM_EVENT_ERROR:
return "error";
case CNC_SIM_EVENT_COMMENT:
return "comment";
case CNC_SIM_EVENT_SET_UNITS:
return "set-units";
case CNC_SIM_EVENT_SET_PLANE:
return "set-plane";
case CNC_SIM_EVENT_SET_FEED:
return "set-feed";
case CNC_SIM_EVENT_SET_SPINDLE:
return "set-spindle";
case CNC_SIM_EVENT_TOOL_CHANGE:
return "tool-change";
case CNC_SIM_EVENT_DWELL:
return "dwell";
case CNC_SIM_EVENT_RAPID:
return "rapid";
case CNC_SIM_EVENT_LINEAR_FEED:
return "linear-feed";
case CNC_SIM_EVENT_ARC_FEED:
return "arc-feed";
case CNC_SIM_EVENT_PROBE:
return "probe";
case CNC_SIM_EVENT_PROGRAM_END:
return "program-end";
case CNC_SIM_EVENT_RTCP_PIVOT:
return "rtcp-pivot";
case CNC_SIM_EVENT_KINEMATICS_SWITCH:
return "kinematics-switch";
case CNC_SIM_EVENT_RTCP_STATE:
return "rtcp-state";
case CNC_SIM_EVENT_SET_G5X_OFFSET:
return "set-g5x-offset";
case CNC_SIM_EVENT_SET_G92_OFFSET:
return "set-g92-offset";
case CNC_SIM_EVENT_SET_XY_ROTATION:
return "set-xy-rotation";
default:
return "none";
}
}
void print_pose(const CncSimPose &pose) {
std::cout << "{\"x\":" << pose.x
<< ",\"y\":" << pose.y
<< ",\"z\":" << pose.z
<< ",\"a\":" << pose.a
<< ",\"b\":" << pose.b
<< ",\"c\":" << pose.c
<< ",\"u\":" << pose.u
<< ",\"v\":" << pose.v
<< ",\"w\":" << pose.w << '}';
}
int print_event(const CncSimEvent *event, void *user_data) {
auto *first = static_cast<bool *>(user_data);
if (!*first) {
std::cout << ",\n";
}
*first = false;
std::cout << " {\"type\":\"" << event_type_name(event->type)
<< "\",\"line\":" << event->line
<< ",\"plane\":" << event->plane
<< ",\"tool\":" << event->tool
<< ",\"feed\":" << event->feed
<< ",\"spindle\":" << event->spindle
<< ",\"dwellSeconds\":" << event->dwell_seconds
<< ",\"arcTurns\":" << event->arc_turns
<< ",\"reserved\":" << event->reserved
<< ",\"start\":";
print_pose(event->start);
std::cout << ",\"end\":";
print_pose(event->end);
std::cout << ",\"center\":";
print_pose(event->center);
std::cout << '}';
return 0;
}
std::string read_all(const char *path) {
if (!path || std::string(path) == "-") {
std::ostringstream out;
out << std::cin.rdbuf();
return out.str();
}
std::ifstream file(path);
std::ostringstream out;
out << file.rdbuf();
return out.str();
}
bool trace_enabled() {
return std::getenv("CNC_SIM_TRACE_RS274") != nullptr;
}
bool execute_line(InterpBase *interp,
CanonEventSink &sink,
const std::string &line,
int line_number,
bool *program_done) {
std::vector<SimulatorGcodeControlAction> control_actions;
if (parse_simulator_gcode_control_line(line, &control_actions)) {
for (const auto &action : control_actions) {
emit_simulator_gcode_control_action(sink, action, line_number);
if (sink.callback_aborted()) {
std::cerr << "event callback aborted parsing\n";
return false;
}
}
return true;
}
if (trace_enabled()) {
std::cerr << "rs274:read line " << line_number << ": " << line << '\n';
}
const int read_rc = interp->read(line.c_str());
if (read_rc == INTERP_ENDFILE || read_rc == INTERP_EXIT) {
*program_done = true;
return true;
}
if (read_rc != 0) {
char error[1024]{};
interp->error_text(read_rc, error, sizeof(error));
std::cerr << "read failed: " << error << '\n';
return false;
}
if (trace_enabled()) {
std::cerr << "rs274:execute line " << line_number << '\n';
}
const int exec_rc = interp->execute();
if (exec_rc == INTERP_EXIT || exec_rc == INTERP_ENDFILE) {
*program_done = true;
return true;
}
if (exec_rc == INTERP_EXECUTE_FINISH) {
return true;
}
if (exec_rc != 0) {
char error[1024]{};
interp->error_text(exec_rc, error, sizeof(error));
std::cerr << "execute failed: " << error << '\n';
return false;
}
if (trace_enabled()) {
std::cerr << "rs274:done line " << line_number << '\n';
}
return true;
}
void init_minimal_tooldata() {
tool_mmap_creator(nullptr, 0);
tooldata_reset();
CANON_TOOL_TABLE spindle = tooldata_entry_init();
spindle.toolno = 0;
spindle.pocketno = 0;
tooldata_put(spindle, 0);
CANON_TOOL_TABLE tool = tooldata_entry_init();
tool.toolno = 1;
tool.pocketno = 1;
tool.diameter = 6.0;
tooldata_put(tool, 1);
}
} // namespace
int main(int argc, char **argv) {
const std::string program = read_all(argc > 1 ? argv[1] : "-");
if (const char *parameter_file = std::getenv("CNC_SIM_RS274_VAR")) {
SET_PARAMETER_FILE_NAME(parameter_file);
}
init_minimal_tooldata();
CanonEventSink sink;
bool first = true;
sink.set_callback(print_event, &first);
cnc_sim_linuxcnc_set_canon_sink(&sink);
std::cout << "[\n";
InterpBase *interp = makeInterp();
if (trace_enabled()) {
std::cerr << "rs274:init\n";
}
const int init_rc = interp->init();
if (init_rc != 0) {
char error[1024]{};
interp->error_text(init_rc, error, sizeof(error));
std::cerr << "init failed: " << error << '\n';
std::cout << "\n]\n";
return 1;
}
if (trace_enabled()) {
std::cerr << "rs274:init done\n";
}
std::istringstream input(program);
std::string line;
bool ok = true;
bool program_done = false;
int line_number = 0;
while (!program_done && std::getline(input, line)) {
++line_number;
if (!execute_line(interp, sink, line, line_number, &program_done)) {
ok = false;
break;
}
}
std::cout << "\n]\n";
interp->exit();
delete interp;
cnc_sim_linuxcnc_set_canon_sink(nullptr);
return ok ? 0 : 1;
}