Added support for direct buses

This commit is contained in:
Borna Rajkovic committed 2022-04-09 19:44:02 +02:00
1 parent 7fcfb8c977
commit c65d12a2a1
7 files changed
+335 -108

No files matched your search

+181 -53
View File
@@ -224,62 +224,151 @@ std::optional<Connection> ComdelGenerator::loadConnection(ConnectionNode node)
{
push(ComdelContext("connection", false, true, false));
std::string component = node.component.value;
std::string pin = node.pin.value;
std::string bus = node.bus.value;
auto componentInstance = getComponentPin(component, pin);
if(!componentInstance) {
errors.emplace_back(node.span, "pin does not exist");
}
auto busInstance = getBus(bus);
if(!busInstance) {
errors.emplace_back(node.span, "bus does not exist");
}
std::set<std::string> wireNames;
for(auto &wire: busInstance->getWires()) {
wireNames.insert(wire.getName());
current().wires.push_back(wire.getName());
}
if(busInstance->getType() == Bus::REGULAR) {
ConnectionComponent first{node.first.component.value, node.first.pin.value};
std::vector<Attribute> attributes;
for(uint i=0; i<node.attributes.size(); i++) {
auto attr = loadAttribute(node.attributes[i]);
if(!attr) {
return nullopt;
auto componentInstance = getComponentPin(first.component, first.pin);
if(!componentInstance) {
errors.emplace_back(node.span, "pin does not exist");
}
attributes.push_back(*attr);
}
std::set<std::string> attributeNames;
for(auto attribute: attributes) {
attributeNames.insert(attribute.getName());
}
if(node.second.has_value()) {
errors.emplace_back(node.span, "regular bus doesn't allow direct connections");
}
std::vector<Value> wires;
for(uint i=0; i<node.wires.size(); i++) {
if(node.wires[i].is(ValueNode::NIL)) {
wires.push_back(Value::fromNull());
} else if(node.wires[i].is(ValueNode::INT)) {
wires.push_back(Value::fromInt(node.wires[i].asInt()));
} else if(node.wires[i].is(ValueNode::IDENTIFIER)) {
if(attributeNames.count(node.wires[i].asIdentifier())) {
wires.push_back(Value::fromReference(node.wires[i].asIdentifier(), Value::ATTRIBUTE_REFERENCE));
} else if(wireNames.count(node.wires[i].asIdentifier())) {
wires.push_back(Value::fromReference(node.wires[i].asIdentifier(), Value::WIRE_REFERENCE));
} else {
errors.emplace_back(node.wires[i].span, "unknown identifier");
std::set<std::string> wireNames;
for(auto &wire: busInstance->getWires()) {
wireNames.insert(wire.getName());
current().wires.push_back(wire.getName());
}
std::vector<Attribute> attributes;
for(auto & attribute : node.attributes) {
auto attr = loadAttribute(attribute);
if(!attr) {
return nullopt;
}
} else {
errors.emplace_back(node.wires[i].span, "unknown value type");
attributes.push_back(*attr);
}
std::set<std::string> attributeNames;
for(auto attribute: attributes) {
attributeNames.insert(attribute.getName());
}
std::vector<Value> wires;
for(auto & firstWire : node.firstWires) {
if(firstWire.is(ValueNode::NIL)) {
wires.push_back(Value::fromNull());
} else if(firstWire.is(ValueNode::INT)) {
wires.push_back(Value::fromInt(firstWire.asInt()));
} else if(firstWire.is(ValueNode::IDENTIFIER)) {
if(attributeNames.count(firstWire.asIdentifier())) {
wires.push_back(Value::fromReference(firstWire.asIdentifier(), Value::ATTRIBUTE_REFERENCE));
} else if(wireNames.count(firstWire.asIdentifier())) {
wires.push_back(Value::fromReference(firstWire.asIdentifier(), Value::WIRE_REFERENCE));
} else {
errors.emplace_back(firstWire.span, "unknown identifier");
}
} else {
errors.emplace_back(firstWire.span, "unknown value type");
}
}
pop();
return Connection(first, nullopt, bus, attributes, wires, nullopt);
} else if(busInstance->getType() == Bus::AUTOMATIC || busInstance->getType() == Bus::AUTOMATIC_SINGLE) {
ConnectionComponent first{node.first.component.value, node.first.pin.value};
if(!node.second.has_value()) {
errors.emplace_back(node.span, "missing second component");
}
ConnectionComponent second{node.second->component.value, node.second->pin.value};
auto firstComponentInstance = getComponentPin(first.component, first.pin);
if(!firstComponentInstance) {
errors.emplace_back(node.span, "pin does not exist");
}
auto secondComponentInstance = getComponentPin(second.component, second.pin);
if(!secondComponentInstance) {
errors.emplace_back(node.span, "pin does not exist");
}
std::set<std::string> wireNames;
for(auto &wire: busInstance->getWires()) {
wireNames.insert(wire.getName());
current().wires.push_back(wire.getName());
}
std::vector<Attribute> attributes;
for(auto & attribute : node.attributes) {
auto attr = loadAttribute(attribute);
if(!attr) {
return nullopt;
}
attributes.push_back(*attr);
}
std::set<std::string> attributeNames;
for(auto attribute: attributes) {
attributeNames.insert(attribute.getName());
}
std::vector<Value> firstWires;
for(auto & firstWire : node.firstWires) {
if(firstWire.is(ValueNode::NIL)) {
firstWires.push_back(Value::fromNull());
} else if(firstWire.is(ValueNode::INT)) {
firstWires.push_back(Value::fromInt(firstWire.asInt()));
} else if(firstWire.is(ValueNode::IDENTIFIER)) {
if(attributeNames.count(firstWire.asIdentifier())) {
firstWires.push_back(Value::fromReference(firstWire.asIdentifier(), Value::ATTRIBUTE_REFERENCE));
} else if(wireNames.count(firstWire.asIdentifier())) {
firstWires.push_back(Value::fromReference(firstWire.asIdentifier(), Value::WIRE_REFERENCE));
} else {
errors.emplace_back(firstWire.span, "unknown identifier");
}
} else {
errors.emplace_back(firstWire.span, "unknown value type");
}
}
std::vector<Value> secondWires;
for(auto & secondWire : *node.secondWires) {
if(secondWire.is(ValueNode::NIL)) {
secondWires.push_back(Value::fromNull());
} else if(secondWire.is(ValueNode::INT)) {
secondWires.push_back(Value::fromInt(secondWire.asInt()));
} else if(secondWire.is(ValueNode::IDENTIFIER)) {
if(attributeNames.count(secondWire.asIdentifier())) {
secondWires.push_back(Value::fromReference(secondWire.asIdentifier(), Value::ATTRIBUTE_REFERENCE));
} else if(wireNames.count(secondWire.asIdentifier())) {
secondWires.push_back(Value::fromReference(secondWire.asIdentifier(), Value::WIRE_REFERENCE));
} else {
errors.emplace_back(secondWire.span, "unknown identifier");
}
} else {
errors.emplace_back(secondWire.span, "unknown value type");
}
}
pop();
return Connection(first, second, bus, attributes, firstWires, secondWires);
}
pop();
errors.emplace_back(node.span, "unsupported connection type");
return Connection(component, pin, bus, attributes, wires);
}
std::optional<Component> ComdelGenerator::loadComponent(ComponentNode node)
@@ -659,25 +748,60 @@ std::optional<Schema> ComdelGenerator::loadSchema(SchemaNode node, Library &libr
}
for(auto &conn: node.connections) {
auto component = dynamic_cast<ComponentInstance*>(schema.getInstance(conn.instance.value));
if(component == NULL) {
errors.push_back(SourceError{conn.instance.span, "unknown component"});
auto firstComponent = dynamic_cast<ComponentInstance*>(schema.getInstance(conn.first.instance.value));
if(firstComponent == NULL) {
errors.push_back(SourceError{conn.first.instance.span, "unknown component"});
continue;
}
if(!component->component.hasPin(conn.pin.value)) {
errors.push_back(SourceError{conn.pin.span, "unknown pin"});
if(!firstComponent->component.hasPin(conn.first.pin.value)) {
errors.push_back(SourceError{conn.first.pin.span, "unknown pin"});
continue;
}
ComponentInstance *secondComponent = NULL;
if(conn.second.has_value()) {
secondComponent = dynamic_cast<ComponentInstance*>(schema.getInstance(conn.second->instance.value));
if(secondComponent == NULL) {
errors.push_back(SourceError{conn.second->instance.span, "unknown component"});
continue;
}
if(!secondComponent->component.hasPin(conn.second->pin.value)) {
errors.push_back(SourceError{conn.second->pin.span, "unknown pin"});
continue;
}
}
auto bus = dynamic_cast<BusInstance*>(schema.getInstance(conn.bus.value));
if(bus == NULL) {
errors.push_back(SourceError{conn.bus.span, "unknown bus"});
continue;
}
if(!library.hasConnection(component->component.getName(), conn.pin.value, bus->bus.getName())) {
errors.push_back(SourceError{conn.span, "unknown connection"});
continue;
std::optional<Connection> connection = std::nullopt;
if(secondComponent != NULL) {
ConnectionComponent firstConn{firstComponent->component.getName(), conn.first.pin.value};
ConnectionComponent secondConn{secondComponent->component.getName(), conn.second->pin.value};
if(library.hasConnection(firstConn,
bus->bus.getName(),
secondConn)) {
connection = *library.getConnection(firstConn, bus->bus.getName(), secondConn);
} else {
errors.push_back(SourceError{conn.span, "unknown connection"});
continue;
}
} else {
ConnectionComponent firstConn{firstComponent->name, conn.first.pin.value};
if(library.hasConnection(firstConn,
bus->bus.getName())) {
connection = *library.getConnection(firstConn, bus->bus.getName());
} else {
errors.push_back(SourceError{conn.span, "unknown connection"});
continue;
}
}
auto connection = *library.getConnection(component->component.getName(), conn.pin.value, bus->bus.getName());
if(!conn.wire) {
errors.push_back(SourceError{conn.span, "missing @wire"});
@@ -692,8 +816,8 @@ std::optional<Schema> ComdelGenerator::loadSchema(SchemaNode node, Library &libr
std::vector<InstanceAttribute*> attributes;
for(auto& attr: conn.attributes) {
if(connection.hasAttribute(attr.name.value)) {
auto attribute = connection.getAttribute(attr.name.value);
if(connection->hasAttribute(attr.name.value)) {
auto attribute = connection->getAttribute(attr.name.value);
auto value = toType(attr.value);
for(auto& en: attribute.getPopup()->getEnumeration()) {
@@ -711,7 +835,11 @@ std::optional<Schema> ComdelGenerator::loadSchema(SchemaNode node, Library &libr
}
}
schema.connections.push_back(new BusConnectionInstance(component, attributes, bus, wire, connection));
if(secondComponent == NULL) {
schema.connections.push_back(new BusConnectionInstance(firstComponent, attributes, bus, wire, *connection));
} else {
schema.connections.push_back(new DirectConnectionInstance(firstComponent, secondComponent, attributes, bus, wire, *connection));
}
}
return schema;
+29 -11
View File
@@ -2,20 +2,19 @@
namespace domain {
Connection::Connection(std::string component, std::string pin, std::string bus, std::vector<Attribute> attributes, std::vector<Value> wires)
: component(component), pin(pin), bus(bus), attributes(attributes), wires(wires)
Connection::Connection(ConnectionComponent first, std::optional<ConnectionComponent> second,
std::string bus, std::vector<Attribute> attributes,
std::vector<Value> firstWires, std::optional<std::vector<Value>> secondWires)
: first(first), second(second), bus(bus), attributes(attributes), firstWires(firstWires), secondWires(secondWires)
{}
bool Connection::isConnecting(std::string component, std::string pin, std::string bus) {
return this->component == component && this->pin == pin && this->bus == bus;
ConnectionComponent Connection::getComponent() {
return first;
}
std::optional<ConnectionComponent> Connection::getSecondComponent() {
return second;
}
std::string Connection::getComponent() {
return component;
}
std::string Connection::getPin() {
return pin;
}
std::string Connection::getBus() {
return bus;
}
@@ -24,7 +23,10 @@ std::vector<Attribute> Connection::getAttributes() {
return attributes;
}
std::vector<Value> Connection::getWires() {
return wires;
return firstWires;
}
std::optional<std::vector<Value>> Connection::getSecondWires() {
return secondWires;
}
Attribute Connection::getAttribute(std::string name) {
@@ -45,4 +47,20 @@ bool Connection::hasAttribute(std::string name) {
return false;
}
bool Connection::isConnecting(ConnectionComponent component) {
return first == component || (second.has_value() && *second == component);
}
bool Connection::isConnecting(ConnectionComponent component, std::string bus) {
return this->bus == bus && (first == component || (second.has_value() && *second == component));
}
bool Connection::isConnecting(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent) {
if(!second.has_value()) {
return false;
}
return (this->first == component && this->bus == bus && this->second == secondComponent) ||
(this->first == secondComponent && this->bus == bus && this->second == component);
}
} // namespace domain
+31 -7
View File
@@ -8,25 +8,49 @@
namespace domain {
class Connection
struct ConnectionComponent
{
std::string component;
std::string pin;
bool operator==(const ConnectionComponent& rhs) const
{
return (component == rhs.component) && (pin == rhs.pin);
}
bool operator!=(const ConnectionComponent& rhs) const
{
return !operator==(rhs);
}
};
class Connection
{
ConnectionComponent first;
std::optional<ConnectionComponent> second;
std::string bus;
std::vector<Attribute> attributes;
std::vector<Value> wires;
std::vector<Value> firstWires;
std::optional<std::vector<Value>> secondWires;
public:
Connection(std::string component, std::string pin, std::string bus, std::vector<Attribute> attributes, std::vector<Value> wires);
Connection(ConnectionComponent first, std::optional<ConnectionComponent> second,
std::string bus, std::vector<Attribute> attributes,
std::vector<Value> firstWires, std::optional<std::vector<Value>> secondWires);
bool isConnecting(std::string component, std::string pin, std::string bus);
bool isConnecting(ConnectionComponent first);
bool isConnecting(ConnectionComponent first, std::string bus);
bool isConnecting(ConnectionComponent first, std::string bus, ConnectionComponent second);
ConnectionComponent getComponent();
std::optional<ConnectionComponent> getSecondComponent();
std::string getComponent();
std::string getPin();
std::string getBus();
std::vector<Attribute> getAttributes();
std::vector<Value> getWires();
std::optional<std::vector<Value>> getSecondWires();
Attribute getAttribute(std::string name);
bool hasAttribute(std::string name);
+17 -4
View File
@@ -81,16 +81,29 @@ Bus &Library::getBus(std::string bus) {
throw std::exception();
}
std::optional<Connection> Library::getConnection(std::string component, std::string pin, std::string bus) {
bool Library::hasConnection(ConnectionComponent component, std::string bus) {
return getConnection(component, bus).has_value();
}
std::optional<Connection> Library::getConnection(ConnectionComponent component, std::string bus) {
for(uint i=0; i<connections.size(); i++) {
if(connections[i].isConnecting(component, pin, bus)) {
if(connections[i].isConnecting(component, bus)) {
return connections[i];
}
}
return nullopt;
}
bool Library::hasConnection(std::string component, std::string pin, std::string bus) {
return getConnection(component, pin, bus).has_value();
bool Library::hasConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent) {
return getConnection(component, bus, secondComponent).has_value();
}
std::optional<Connection> Library::getConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent) {
for(uint i=0; i<connections.size(); i++) {
if(connections[i].isConnecting(component, bus, secondComponent)) {
return connections[i];
}
}
return nullopt;
}
std::string Library::getMessage(std::string key) {
+4 -3
View File
@@ -45,18 +45,19 @@ public:
bool hasComponent(std::string name);
bool hasBus(std::string name);
bool hasConnection(std::string component, std::string pin, std::string bus);
std::map<std::string, std::string> getMessages();
AddressSpace &getAddressSpace(std::string name);
Component &getComponent(std::string name);
Bus &getBus(std::string bus);
std::optional<Connection> getConnection(std::string component, std::string pin, std::string bus);
std::string getMessage(std::string key);
bool hasConnection(ConnectionComponent component, std::string bus);
std::optional<Connection> getConnection(ConnectionComponent component, std::string bus);
bool hasConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent);
std::optional<Connection> getConnection(ConnectionComponent component, std::string bus, ConnectionComponent secondComponent);
};
} // namespace domain