Added count and pin validators

This commit is contained in:
Borna Rajković 2022-05-20 00:44:40 +02:00
parent 1100a9f0b9
commit 0a658a4aba
6 changed files with 138 additions and 80 deletions

View File

@ -1,4 +1,5 @@
#include "comdelvalidator.h"
#include "library.h"
namespace domain {
@ -15,6 +16,78 @@ std::vector<ValidationError> ComdelValidator::validateSchema(Schema &schema, Val
return errors;
}
std::vector<ValidationError> ComdelValidator::validateInstanceCount(Schema& schema, Library& library, ValidationContext context) {
std::vector<ValidationError> errors;
// validate instance count
std::map<std::string, int> instanceMap;
for(auto& inst: schema.componentInstances) {
instanceMap[inst->component.getName()]++;
}
for(auto comp: library.getComponents()) {
int count = instanceMap[comp.getName()];
context.attributes["componentName"] = Value::fromString(comp.getName());
context.attributes["min"] = Value::fromInt(comp.getCount().first);
context.attributes["max"] = Value::fromInt(comp.getCount().second);
context.attributes["count"] = Value::fromInt(count);
if(count < comp.getCount().first) {
auto message = populateMessage("Not enough instances of component '{componentName}' required at least {min}, found {count}", context);
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
} else if(count > comp.getCount().second) {
auto message = populateMessage("To many instances of component '{componentName}' allow at most {max}, found {count}", context);
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
}
}
// validate bus instance count
std::map<std::string, int> busInstanceMap;
for(auto& inst: schema.busInstances) {
busInstanceMap[inst->bus.getName()]++;
}
for(auto bus: library.getBuses()) {
int count = busInstanceMap[bus.getName()];
context.attributes["busName"] = Value::fromString(bus.getName());
context.attributes["min"] = Value::fromInt(bus.getCount().first);
context.attributes["max"] = Value::fromInt(bus.getCount().second);
context.attributes["count"] = Value::fromInt(count);
if(count < bus.getCount().first) {
auto message = populateMessage("Not enough instances of bus '{busName}' required at least {min}, found {count}", context);
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
} else if(count > bus.getCount().second) {
auto message = populateMessage("To many instances of bus '{busName}' allow at most {max}, found {count}", context);
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
}
}
return errors;
}
std::vector<ValidationError> ComdelValidator::validatePinConnections(Schema &schema, Library &library, ValidationContext context) {
std::vector<ValidationError> errors;
for(auto& inst: schema.componentInstances) {
for(auto& pin: inst->component.getPins()) {
if(pin.getConnection().getType() == PinConnection::REQUIRED) {
if(!connectionExists(schema, inst, pin)) {
context.instance = inst.get();
context.attributes["instanceName"] = Value::fromString(inst->name);
auto message = populateMessage(pin.getConnection().getMessage(), context);
errors.push_back(ValidationError{nullptr, nullptr, Action::ERROR, message});
}
}
}
}
return errors;
}
std::vector<ValidationError> ComdelValidator::validateComponent(ComponentInstance* instance, ValidationContext context) {
std::vector<ValidationError> errors;
@ -89,4 +162,26 @@ string ComdelValidator::replacePlaceholder(string source, string key, Value valu
return source;
}
bool ComdelValidator::connectionExists(Schema &schema, shared_ptr<ComponentInstance> &component, Pin &pin) {
for(auto conn: schema.connections) {
auto busConnection = dynamic_cast<BusConnectionInstance*>(conn.get());
if(busConnection != nullptr) {
if(busConnection->instance->name == component->name && busConnection->connection.getComponent().pin == pin.getName()) {
return true;
}
}
auto directConnection = dynamic_cast<DirectConnectionInstance*>(conn.get());
if(directConnection != nullptr) {
if(directConnection->instance->name == component->name && busConnection->connection.getComponent().pin == pin.getName()) {
return true;
}
if(directConnection->secondInstance->name == component->name && busConnection->connection.getSecondComponent()->pin == pin.getName()) {
return true;
}
}
}
return false;
}
}

View File

@ -3,6 +3,7 @@
#include "instance.h"
#include "schema.h"
#include "library.h"
namespace domain {
@ -29,6 +30,9 @@ public:
std::vector<ValidationError> validateAttribute(InstanceAttribute *attribute, ValidationContext context);
std::optional<ValidationError> validateRule(Rule rule, ValidationContext context);
std::vector<ValidationError> validateInstanceCount(Schema &schema, Library& library, ValidationContext context);
std::vector<ValidationError> validatePinConnections(Schema &schema, Library& library, ValidationContext context);
ComdelValidator(std::vector<FunctionValidator*> validators) {
for(auto* validator: validators) {
validator->clear();
@ -42,6 +46,8 @@ private:
std::string populateMessage(string message, ValidationContext context);
string replacePlaceholder(string message, const string name, Value value);
bool connectionExists(Schema &schema, shared_ptr <ComponentInstance> &component, Pin &pin);
};
}

View File

@ -51,22 +51,14 @@
x: 0; y:0; w:100; h:100;
}
}
@pin glavniPin inOut {
@pin glavniPin in {
@tooltip "pin za spajanje na glavnu sabirnicu"
@connection required("COMDEL se ne može stvoriti. FRISC nije spojen na sabirnicu")
@display {
/*
pin {
x: 100; y: 50;
fillColor: white;
lineColor: red;
fillColorConnected: white;
lineColorConnected: black;
side: left;
size: 20;
}*/
pin {
x: 42; y: 100; w: 16; h:16;
type: "in";
orientation: "bottom";
}
}
}
@ -183,7 +175,9 @@
}
*/
pin {
x: 42; y: -16; w: 16; h: 16;
x: 42; y: -16; w: 16; h:16;
type: "out";
orientation: "top";
}
}
}
@ -192,7 +186,7 @@
@component DMA {
@instanceName "dma"
@tooltip "DMA-kontroler"
@count (1,1000)
@count (0,1000)
@source "dma.cdl"
@attribute pocetnaAdresa int default 0 {
@ -303,20 +297,13 @@
}
}
@bus PIOSabirnica automatic {
@count (0, 20)
@wires {
PIO_DATA<8>,
READY,
STROBE
}
}
@bus Test singleAutomatic {
@tooltip "sabirnica za spajanje FRISC a s memorijama i UI/jedinicama"
@count (1,1)
@wires {
CONNECTOR,
}
}
@connection (FRISC.glavniPin, glavnaSabirnica) {
@wires{ADR, DATA, READ, WRITE, SIZE, WAIT, INT0, INT1, INT2, INT3, IACK, 1, null}
@ -344,23 +331,4 @@
@connection (DMA.glavniPin, PIOSabirnica, FRISC.glavniPin) {
@wires{PIO_DATA, READY, STROBE}
@wires{PIO_DATA, READY, STROBE}
}
@connection (FRISC.glavniPin, Test, Memorija.glavniPin) {
@wires{null, "READY", null}
@wires{"PIO_DATA", null, null}
@attribute dmaPoveznica string default "" {
@popup automatic {
@title "Spoji DMA kraj"
@text "Odaberite poveznicu za dma kraja"
}
}
@attribute mmaPoveznica string default "" {
@popup automatic {
@title "Spoji MMA kraj"
@text "Odaberite poveznicu za mma kraja"
}
}
}

View File

@ -1,33 +1,27 @@
@source "frisc_library.csl"
@schema {
@instance proc FRISC {
@position (0, 0)
@attribute _memory null
}
@instance proc FRISC {
@position (0, 0)
@attribute _memory null
}
@instance mem Memorija {
@position (0, 250)
@attribute sinkroniziran false
@attribute brzina 1
@attribute kapacitet 1024
@attribute size 8
@attribute pocetnaAdresa 1023
}
@instance mem Memorija {
@position (0, 250)
@attribute sinkroniziran false
@attribute brzina 1
@attribute kapacitet 1024
@attribute size 8
@attribute pocetnaAdresa 1024
}
@instance bus glavnaSabirnica {
@position (0, 200)
@size 100
}
@instance bus glavnaSabirnica {
@position (0, 200)
@size 100
}
@instance testBus Test {}
@connection (proc.glavniPin, bus) {}
@connection (mem.glavniPin, bus) {}
@connection (proc.glavniPin, testBus, mem.glavniPin) {
@attribute dmaPoveznica "READY"
@attribute mmaPoveznica "PIO_DATA"
}
}
@connection (proc.glavniPin, bus) {
}
@connection (mem.glavniPin, bus) {
}
}

View File

@ -3,7 +3,7 @@
@schema {
@instance proc FRISC {
@position (0, 0)
@attribute _memory mem
@attribute _memory null
}
@instance mem Memorija {
@ -12,7 +12,7 @@
@attribute brzina 1
@attribute kapacitet 1024
@attribute size 8
@attribute pocetnaAdresa 1023
@attribute pocetnaAdresa 1024
}
@instance bus glavnaSabirnica {
@ -20,17 +20,6 @@
@size 100
}
@instance testBus Test {
@position (0, 200)
@size 0
}
@connection (proc.glavniPin, bus) {
}
@connection (mem.glavniPin, bus) {
}
@connection (proc.glavniPin, testBus, mem.glavniPin) {
@attribute dmaPoveznica "READY"
@attribute mmaPoveznica "PIO_DATA"
}
}

View File

@ -209,6 +209,12 @@ void MainWindow::onValidateSchema(bool /*toggled*/) {
}
auto errors = validator.validateSchema(*schema, context);
auto countValidation = validator.validateInstanceCount(*schema, *library, context);
errors.insert(errors.end(), countValidation.begin(), countValidation.end());
auto pinValidation = validator.validatePinConnections(*schema, *library, context);
errors.insert(errors.end(), pinValidation.begin(), pinValidation.end());
errors.erase(std::remove_if(
errors.begin(), errors.end(), [](const domain::ValidationError& error) { return error.type == domain::Action::WARNING;}),
errors.end());