// // Created by bbr on 08.05.22.. // #include #include "comdel_generator.h" namespace domain { void generate_schema(std::string &librarySource, Schema *schema, std::ostream &buffer) { buffer << "@source \"" << librarySource << "\"" << std::endl << std::endl; buffer << "@schema {" << std::endl; for (auto &componentInstance: schema->componentInstances) { buffer << "\t" << "@instance " << componentInstance->name << " " << componentInstance->component.getName() << " {" << std::endl; buffer << "\t\t" << "@position (" << componentInstance->position.first << ", " << componentInstance->position.second << ")" << std::endl; for (auto &attribute: componentInstance->attributes) { buffer << "\t\t" << "@attribute " << attribute.name << " " << attribute.value.stringify() << std::endl; } buffer << "\t}" << std::endl << std::endl; } for (auto &busInstance: schema->busInstances) { buffer << "\t" << "@instance " << busInstance->name << " " << busInstance->bus.getName() << " {" << std::endl; buffer << "\t\t" << "@position (" << busInstance->position.first << ", " << busInstance->position.second << ")" << std::endl; buffer << "\t\t" << "@size " << busInstance->size << std::endl; buffer << "\t}" << std::endl << std::endl; } for (auto &conn: schema->connections) { auto busConn = dynamic_cast(conn.get()); if (busConn) { buffer << "\t" << "@connection (" << busConn->instance->name << "." << busConn->connection.getComponent().pin << ", " << busConn->bus->name << ") {" << std::endl; for (auto attribute: busConn->attributes) { buffer << "\t\t" << "@attribute " << attribute.name << " " << attribute.value.stringify() << std::endl; } buffer << "\t" << "}" << std::endl; } auto dirConn = dynamic_cast(conn.get()); if (dirConn) { buffer << "\t" << "@connection (" << dirConn->instance->name << "." << dirConn->connection.getComponent().pin << ", " << dirConn->bus->name << ", " << dirConn->secondInstance->name << "." << dirConn->connection.getSecondComponent()->pin << ") {" << std::endl; for (auto attribute: dirConn->attributes) { buffer << "\t\t" << "@attribute " << attribute.name << " " << attribute.value.stringify() << std::endl; } buffer << "\t" << "}" << std::endl; } } buffer << "}" << std::endl; } std::set createImports(Schema *schema); std::map generateWires(Schema *schema, ostream &ostream); void generateSubComponents(Schema *schema, map &wires, ostream &buffer); void generateDisplay(Schema *schema, ostream &buffer); void generate_comdel(Schema *schema, Library &library, std::ostream &buffer) { buffer << library.getHeader() << std::endl; std::set imports = createImports(schema); for (auto &import: imports) { buffer << "#include \"" << library.getComponentDirectory() << "\\" << import << "\"" << std::endl; } buffer << "\n\n" << std::endl; buffer << "component System" << std::endl << "{" << std::endl; if (library.getComponentHeader().has_value()) { buffer << library.getComponentHeader().value() << endl; } auto wires = generateWires(schema, buffer); generateSubComponents(schema, wires, buffer); generateDisplay(schema, buffer); buffer << "}"; } void generateBus(BusInstance *bus, ostream &buffer); void generateConnection(ConnectionInstance *connection, ostream &buffer); void generateDisplay(Schema *schema, ostream &buffer) { buffer << "\n\tdisplay {\n"; for (auto &component: schema->componentInstances) { buffer << "\t\tcomponent { x: " << component->position.first << "; y: " << component->position.second << "; ref: \"" << component->name << "\"; }" << std::endl; } for (auto &bus: schema->busInstances) { generateBus(bus.get(), buffer); } buffer << "\n"; for (auto &connection: schema->connections) { generateConnection(connection.get(), buffer); } buffer << "\t}\n"; } void generateConnection(ConnectionInstance *connection, ostream &buffer) { buffer << "\t\tline {x1:" << connection->start.first << "; y1:" << connection->start.second << "; " << "x2:" << connection->end.first << "; y2:" << connection->end.second << ";}" << "\n"; } void generateBus(BusInstance *bus, ostream &buffer) { buffer << "\n"; buffer << "\t\t// " << bus->name << " bus\n\n"; if (bus->bus.getDisplayBus().has_value()) { bus->bus.getDisplayBus()->comdel(buffer, bus->position.first, bus->position.second, bus->size); } } void generateWire(std::string &name, Wire &wire, ostream &buffer); std::map generateWires(Schema *schema, ostream &buffer) { std::set usedNames; std::map usedMappings; for (auto &bus: schema->busInstances) { buffer << "\t//" << bus->name << std::endl; for (auto &wire: bus->bus.getWires()) { std::string name = wire.getName(); if (usedNames.count(wire.getName()) > 0) { name = bus->name + "__" + wire.getName(); } if (wire.isHidden()) { name = "--" + name; } usedNames.insert(name); usedMappings.insert(std::make_pair(bus->name + "." + wire.getName(), name)); generateWire(name, wire, buffer); } buffer << std::endl << std::endl; } return usedMappings; } void generateWire(std::string &name, Wire &wire, ostream &buffer) { buffer << "\t"; switch (wire.getType()) { case Wire::R_WIRE: buffer << "r_wire"; break; case Wire::WIRED_AND: buffer << "wired_and"; break; case Wire::WIRED_OR: buffer << "wired_or"; break; default: buffer << "wire"; } if (wire.getWidth() != 1) { buffer << "<" << wire.getWidth() << ">"; } buffer << " " << name << ";" << std::endl; } std::set createImports(Schema *schema) { std::set importSet; for (auto &component: schema->componentInstances) { importSet.insert(component->component.getSource()); } return importSet; } void generateAutomaticPin(DirectConnectionInstance *connection, string name, string pin, map wireNames, stringstream &buffer); void generateSingleAutomaticPin(DirectConnectionInstance *instance, string name, string pin, map &wireNames, stringstream &buffer); void generateComponent(Schema *schema, map &wires, ostream &buffer, shared_ptr &component); void generateSubComponents(Schema *schema, map &wires, ostream &buffer) { buffer << "\t// components --------------------------------------------" << std::endl; for (auto &component: schema->componentInstances) { if (component->component.getType() == Component::MEMORY) { generateComponent(schema, wires, buffer, component); } } for (auto &component: schema->componentInstances) { if (component->component.getType() != Component::MEMORY) { generateComponent(schema, wires, buffer, component); } } } void generateComponent(Schema *schema, map &wires, ostream &buffer, shared_ptr &component) { buffer << "\tsubcomponent " << component->component.getName() << " " << component->name; std::optional memory; std::vector attributes; for (auto &attr: component->attributes) { if (attr.name != "_memory") { attributes.push_back(attr); } else if (attr.name == "_memory" && attr.value.asMemoryReference().has_value()) { memory = attr; } } if (!attributes.empty()) { buffer << "<"; buffer << attributes[0].value.stringify(); for (int i = 1; i < attributes.size(); i++) { buffer << ", " << attributes[i].value.stringify(); } buffer << ">"; } stringstream tempOutput; for (auto &pin: component->component.getPins()) { if (schema->hasConnection(component->name, pin.getName())) { auto conn = schema->getConnection(component->name, pin.getName()); auto busConn = dynamic_cast(conn); if (busConn != nullptr) { for (auto wire: busConn->connection.getWires()) { if (wire.isType(Value::ATTRIBUTE_REFERENCE)) { auto attribute = busConn->getAttribute(wire.asReference()); if (wire.isType(Value::WIRE_REFERENCE)) { tempOutput << wires[busConn->bus->name + "." + attribute.value.asReference()] << ", "; } else if (wire.isType(Value::NIL)) { tempOutput << "*, "; } else { tempOutput << attribute.value.stringify() << ", "; } } else { if (wire.isType(Value::WIRE_REFERENCE)) { tempOutput << wires[busConn->bus->name + "." + wire.asReference()] << ", "; } else if (wire.isType(Value::NIL)) { tempOutput << "*, "; } else { tempOutput << wire.stringify() << ", "; } } } } auto dirConn = dynamic_cast(conn); if (dirConn != nullptr) { if (dirConn->bus->bus.getType() == Bus::AUTOMATIC) { generateAutomaticPin(dirConn, component->name, pin.getName(), wires, tempOutput); } else { generateSingleAutomaticPin(dirConn, component->name, pin.getName(), wires, tempOutput); } } } else { // if no connection exists than defaults must exist for (auto &wire: *pin.getWires()) { tempOutput << wire.stringify() << ", "; } } } auto wireList = tempOutput.str(); wireList.pop_back(); wireList.pop_back(); // remove last COMMA(", ") buffer << "(" << wireList << ")"; if (memory.has_value()) { buffer << " uses " << *memory->value.asMemoryReference(); } buffer << ";" << std::endl; } void generateSingleAutomaticPin(DirectConnectionInstance *connection, string name, string pin, map &wireNames, stringstream &buffer) { std::vector wires; std::string selected; std::vector defaults; if (connection->instance->name == name && connection->connection.getComponent().pin == pin) { wires = connection->connection.getWires(); selected = connection->attributes[0].value.asReference(); defaults = *connection->instance->component.getPin(pin).getWires(); } else { wires = *connection->connection.getSecondWires(); selected = connection->attributes[1].value.asReference(); defaults = *connection->secondInstance->component.getPin(pin).getWires(); } for (int i = 0; i < wires.size(); i++) { if (wires[i].isType(Value::STRING)) { if (wires[i].asString() == selected) { buffer << wireNames[connection->bus->name + "." + connection->bus->bus.getWires()[0].getName()] << ", "; } else { buffer << defaults[i].stringify(); } } else { buffer << wires[i].stringify() << ", "; } } } void generateAutomaticPin(DirectConnectionInstance *connection, string name, string pin, map wireNames, stringstream &buffer) { std::vector wires; if (connection->instance->name == name && connection->connection.getComponent().pin == pin) { wires = connection->connection.getWires(); } else { wires = *connection->connection.getSecondWires(); } for (auto &wire: wires) { if (wire.isType(Value::ATTRIBUTE_REFERENCE)) { auto attribute = connection->getAttribute(wire.asReference()); if (wire.isType(Value::WIRE_REFERENCE)) { buffer << wireNames[connection->bus->name + "." + attribute.value.asReference()] << ", "; } else if (wire.isType(Value::NIL)) { buffer << "*, "; } else { buffer << attribute.value.stringify() << ", "; } } else { if (wire.isType(Value::WIRE_REFERENCE)) { buffer << wireNames[connection->bus->name + "." + wire.asReference()] << ", "; } else if (wire.isType(Value::NIL)) { buffer << "*, "; } else { buffer << wire.stringify() << ", "; } } } } } // domain