--- /dev/null
+package net.mograsim.logic.model.verilog.converter;
+
+import net.mograsim.logic.model.verilog.model.VerilogComponentImplementation;
+
+public class ComponentConversionResult
+{
+ private final ModelComponentToVerilogComponentDeclarationMapping mapping;
+ private final VerilogComponentImplementation implementation;
+
+ public ComponentConversionResult(ModelComponentToVerilogComponentDeclarationMapping mapping,
+ VerilogComponentImplementation implementation)
+ {
+ this.mapping = mapping;
+ this.implementation = implementation;
+ }
+
+ public ModelComponentToVerilogComponentDeclarationMapping getMapping()
+ {
+ return mapping;
+ }
+
+ public VerilogComponentImplementation getImplementation()
+ {
+ return implementation;
+ }
+}
import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;
import com.google.gson.JsonElement;
-import net.mograsim.logic.core.types.Bit;
-import net.mograsim.logic.core.types.BitVector;
import net.mograsim.logic.model.model.components.ModelComponent;
import net.mograsim.logic.model.model.components.atomic.ModelSplitter;
+import net.mograsim.logic.model.model.components.atomic.ModelTriStateBuffer;
import net.mograsim.logic.model.model.components.submodels.SubmodelComponent;
-import net.mograsim.logic.model.model.wires.ModelWire;
import net.mograsim.logic.model.model.wires.ModelWireCrossPoint;
import net.mograsim.logic.model.model.wires.Pin;
import net.mograsim.logic.model.serializing.IdentifyParams;
import net.mograsim.logic.model.verilog.converter.VerilogEmulatedModelPin.Type;
+import net.mograsim.logic.model.verilog.converter.components.SubmodelComponentConverter;
+import net.mograsim.logic.model.verilog.converter.components.TriStateBufferConverter;
import net.mograsim.logic.model.verilog.model.VerilogComponentDeclaration;
import net.mograsim.logic.model.verilog.model.VerilogComponentImplementation;
-import net.mograsim.logic.model.verilog.model.expressions.SignalReference;
-import net.mograsim.logic.model.verilog.model.signals.Constant;
import net.mograsim.logic.model.verilog.model.signals.IOPort;
import net.mograsim.logic.model.verilog.model.signals.Input;
-import net.mograsim.logic.model.verilog.model.signals.NamedSignal;
import net.mograsim.logic.model.verilog.model.signals.Output;
-import net.mograsim.logic.model.verilog.model.signals.Signal;
-import net.mograsim.logic.model.verilog.model.signals.Wire;
-import net.mograsim.logic.model.verilog.model.statements.Assign;
-import net.mograsim.logic.model.verilog.model.statements.ComponentReference;
-import net.mograsim.logic.model.verilog.model.statements.Statement;
-import net.mograsim.logic.model.verilog.model.statements.WireDeclaration;
import net.mograsim.logic.model.verilog.utils.IdentifierGenerator;
import net.mograsim.logic.model.verilog.utils.UnionFind;
ModelComponentToVerilogConverter::sanitizeVerilogID);
}
- private void convert(ModelComponent modelComponent)
+ public void convert(ModelComponent modelComponent)
{
// these are handled elsewhere
if (modelComponent instanceof ModelSplitter || modelComponent instanceof ModelWireCrossPoint)
String verilogID = verilogComponentIDGen.generateID(verilogComponentIDPrefix + modelID + (params.isJsonNull() ? "" : "_" + params));
+ ComponentConversionResult result;
// TODO don't rely on instanceof
+ // TODO improve!
if (modelComponent instanceof SubmodelComponent)
- convertSubmodelComponent((SubmodelComponent) modelComponent, modelID, params, verilogID);
+ result = new SubmodelComponentConverter(this).convert((SubmodelComponent) modelComponent, modelID, params, verilogID);
+ else if (modelComponent instanceof ModelTriStateBuffer)
+ result = new TriStateBufferConverter(this).convert((ModelTriStateBuffer) modelComponent, modelID, params, verilogID);
else
throw new IllegalArgumentException(
"Can only convert SubmodelComponents, tried to convert " + modelID + " with params " + params);
- }
-
- private void convertSubmodelComponent(SubmodelComponent modelComponent, String modelID, JsonElement params, String verilogID)
- {
- for (ModelComponent subcomponent : modelComponent.submodel.getComponentsByName().values())
- if (!subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME))
- convert(subcomponent);
-
- UnionFind<PinBit> connectedPins = findConnectedPins(modelComponent);
-
- ModelComponentToVerilogComponentDeclarationMapping mapping = mapDeclaration(modelComponent, connectedPins, modelID, params,
- verilogID);
- componentMappingsPerModelIDPerParams.computeIfAbsent(modelID, i -> new HashMap<>()).put(params, mapping);
-
- verilogComponents.add(mapImplementation(modelComponent, connectedPins, mapping));
- }
-
- private UnionFind<PinBit> findConnectedPins(SubmodelComponent modelComponent)
- {
- UnionFind<PinBit> connectedPins = new UnionFind<>();
- for (ModelWire w : modelComponent.submodel.getWiresByName().values())
- for (int bit = 0; bit < w.getPin1().logicWidth; bit++)
- connectedPins.union(new PinBit(w.getPin1(), bit), new PinBit(w.getPin2(), bit));
-
- for (ModelComponent subcomponent : modelComponent.submodel.getComponentsByName().values())
- if (subcomponent instanceof ModelSplitter)
- {
- ModelSplitter splitter = (ModelSplitter) subcomponent;
- for (int bit = 0; bit < splitter.logicWidth; bit++)
- connectedPins.union(new PinBit(splitter.getInputPin(), bit), new PinBit(splitter.getOutputPin(bit), 0));
- } else if (!(subcomponent instanceof ModelWireCrossPoint)
- && !subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME))
- {
- ModelComponentToVerilogComponentDeclarationMapping subcomponentMapping = getComponentMapping(subcomponent);
- for (Set<PinNameBit> connected : subcomponentMapping.getInternallyConnectedPins())
- connectedPins.unionAll(connected.stream().map(p -> p.toPinBit(subcomponent)).collect(Collectors.toList()));
- }
-
- return connectedPins;
- }
-
- private static ModelComponentToVerilogComponentDeclarationMapping mapDeclaration(SubmodelComponent modelComponent,
- UnionFind<PinBit> connectedPins, String modelID, JsonElement params, String verilogID)
- {
- // TODO this is probably slow
- Map<PinBit, PinNameBit> representantMapping = new HashMap<>();
- UnionFind<PinNameBit> connectedPinsByName = new UnionFind<>();
- for (Pin p : modelComponent.getSubmodelPins().values())
- for (int bit = 0; bit < p.logicWidth; bit++)
- {
- PinNameBit pinnamebit = new PinNameBit(p.name, bit);
- PinNameBit representative = representantMapping.computeIfAbsent(connectedPins.find(new PinBit(p, bit)), q -> pinnamebit);
- connectedPinsByName.union(pinnamebit, representative);
- }
- return generateCanonicalDeclarationMapping(modelComponent, connectedPinsByName, modelID, params, verilogID);
+ componentMappingsPerModelIDPerParams.computeIfAbsent(modelID, i -> new HashMap<>()).put(params, result.getMapping());
+ verilogComponents.add(result.getImplementation());
}
public static ModelComponentToVerilogComponentDeclarationMapping generateCanonicalDeclarationMapping(ModelComponent modelComponent,
}
}
- private VerilogComponentImplementation mapImplementation(SubmodelComponent modelComponent, UnionFind<PinBit> connectedPins,
- ModelComponentToVerilogComponentDeclarationMapping declarationMapping)
- {
- Map<PinBit, Signal> currentPreSignals = new HashMap<>();
- Map<PinBit, NamedSignal> finalOutSignals = new HashMap<>();
- Map<PinBit, NamedSignal> resSignals = new HashMap<>();
- for (Set<PinNameBit> connectedPinGroup : declarationMapping.getInternallyConnectedPins())
- {
- PinNameBit pinnamebit = connectedPinGroup.iterator().next();
- PinBit root = connectedPins.find(pinnamebit.toSubmodelPinBit(modelComponent));
- resSignals.put(root, declarationMapping.getResPinMapping().get(pinnamebit).getVerilogPort());
- finalOutSignals.put(root, declarationMapping.getOutPinMapping().get(pinnamebit).getVerilogPort());
- currentPreSignals.put(root, declarationMapping.getPrePinMapping().get(pinnamebit).getVerilogPort());
- }
-
- IdentifierGenerator idGen = new IdentifierGenerator(
- declarationMapping.getVerilogComponentDeclaration().getIOPorts().stream().map(IOPort::getName).collect(Collectors.toList()),
- ModelComponentToVerilogConverter::sanitizeVerilogID);
- List<Statement> statements = new ArrayList<>();
- for (ModelComponent subcomponent : modelComponent.submodel.getComponentsByName().values())
- {
- // TODO do we really want to use instanceof?
- if (subcomponent instanceof ModelSplitter || subcomponent instanceof ModelWireCrossPoint
- || subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME))
- continue;
-
- String subcomponentVerilogName = idGen.generateID(subcomponent.getName());
- ModelComponentToVerilogComponentDeclarationMapping subcomponentMapping = getComponentMapping(subcomponent);
- int parameterCount = subcomponentMapping.getVerilogComponentDeclaration().getIOPorts().size();
- List<Signal> arguments = new ArrayList<>(parameterCount);
- for (int i = 0; i < parameterCount; i++)
- arguments.add(null);
- for (Pin pin : subcomponent.getPins().values())
- for (int bit = 0; bit < pin.logicWidth; bit++)
- {
- PinBit pinbit = new PinBit(pin, bit);
- PinBit root = connectedPins.find(pinbit);
- Wire outSignal = new Wire(idGen.generateID(subcomponentVerilogName + "_" + pin.name + "_" + bit), 2);
- statements.add(new WireDeclaration(outSignal));
- Signal preSignal = currentPreSignals.put(root, outSignal);
- Signal resSignal = resSignals.get(root);
- if (resSignal == null)
- {
- preSignal = new Constant(BitVector.of(Bit.ZERO, 2));
- Wire resWire = new Wire(idGen.generateID(subcomponentVerilogName + "_" + pin.name + "_" + bit + "_res"), 2);
- resSignal = resWire;
- statements.add(new WireDeclaration(resWire));
- finalOutSignals.put(root, resWire);
- resSignals.put(root, resWire);
- }
- PinNameBit pinnamebit = pinbit.toPinNameBit();
- arguments.set(subcomponentMapping.getPrePinMapping().get(pinnamebit).getPortIndex(), preSignal);
- arguments.set(subcomponentMapping.getOutPinMapping().get(pinnamebit).getPortIndex(), outSignal);
- arguments.set(subcomponentMapping.getResPinMapping().get(pinnamebit).getPortIndex(), resSignal);
- }
- statements
- .add(new ComponentReference(subcomponentVerilogName, subcomponentMapping.getVerilogComponentDeclaration(), arguments));
- }
-
- for (Entry<PinBit, NamedSignal> e : finalOutSignals.entrySet())
- statements.add(new Assign(e.getValue(), new SignalReference(currentPreSignals.get(e.getKey()))));
-
- return new VerilogComponentImplementation(declarationMapping.getVerilogComponentDeclaration(), statements);
- }
-
- private ModelComponentToVerilogComponentDeclarationMapping getComponentMapping(ModelComponent component)
+ public ModelComponentToVerilogComponentDeclarationMapping getComponentMapping(ModelComponent component)
{
ModelComponentToVerilogComponentDeclarationMapping subcomponentMapping = componentMappingsPerModelIDPerParams
.get(component.getIDForSerializing(new IdentifyParams())).get(component.getParamsForSerializingJSON(new IdentifyParams()));
return subcomponentMapping;
}
- private Set<VerilogComponentImplementation> getVerilogComponents()
+ public Set<VerilogComponentImplementation> getVerilogComponents()
{
return verilogComponents;
}
return converter.getVerilogComponents();
}
+ public static IdentifierGenerator generateIdentifierGenerator(VerilogComponentDeclaration declaration)
+ {
+ IdentifierGenerator idGen = new IdentifierGenerator(
+ declaration.getIOPorts().stream().map(IOPort::getName).collect(Collectors.toList()),
+ ModelComponentToVerilogConverter::sanitizeVerilogID);
+ return idGen;
+ }
+
public static String sanitizeVerilogID(String id)
{
return (id.matches("[0-9].*") ? "_" + id : id).replaceAll("[^A-Za-z0-9_]", "_");
--- /dev/null
+package net.mograsim.logic.model.verilog.converter.components;
+
+import com.google.gson.JsonElement;
+
+import net.mograsim.logic.model.model.components.ModelComponent;
+import net.mograsim.logic.model.verilog.converter.ComponentConversionResult;
+
+public interface ComponentConverter<C extends ModelComponent>
+{
+ public ComponentConversionResult convert(C modelComponent, String modelID, JsonElement params, String verilogID);
+}
--- /dev/null
+package net.mograsim.logic.model.verilog.converter.components;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.function.BiFunction;
+import java.util.stream.Collectors;
+
+import com.google.gson.JsonElement;
+
+import net.mograsim.logic.core.types.Bit;
+import net.mograsim.logic.core.types.BitVector;
+import net.mograsim.logic.model.model.components.ModelComponent;
+import net.mograsim.logic.model.model.components.atomic.ModelSplitter;
+import net.mograsim.logic.model.model.components.submodels.SubmodelComponent;
+import net.mograsim.logic.model.model.wires.ModelWire;
+import net.mograsim.logic.model.model.wires.ModelWireCrossPoint;
+import net.mograsim.logic.model.model.wires.Pin;
+import net.mograsim.logic.model.verilog.converter.ComponentConversionResult;
+import net.mograsim.logic.model.verilog.converter.ModelComponentToVerilogComponentDeclarationMapping;
+import net.mograsim.logic.model.verilog.converter.ModelComponentToVerilogConverter;
+import net.mograsim.logic.model.verilog.converter.PinBit;
+import net.mograsim.logic.model.verilog.converter.PinNameBit;
+import net.mograsim.logic.model.verilog.converter.VerilogEmulatedModelPin;
+import net.mograsim.logic.model.verilog.converter.VerilogEmulatedModelPin.Type;
+import net.mograsim.logic.model.verilog.model.VerilogComponentDeclaration;
+import net.mograsim.logic.model.verilog.model.VerilogComponentImplementation;
+import net.mograsim.logic.model.verilog.model.expressions.Constant;
+import net.mograsim.logic.model.verilog.model.expressions.Expression;
+import net.mograsim.logic.model.verilog.model.expressions.SignalReference;
+import net.mograsim.logic.model.verilog.model.signals.IOPort;
+import net.mograsim.logic.model.verilog.model.signals.Input;
+import net.mograsim.logic.model.verilog.model.signals.Output;
+import net.mograsim.logic.model.verilog.model.signals.Signal;
+import net.mograsim.logic.model.verilog.model.signals.Wire;
+import net.mograsim.logic.model.verilog.model.statements.Assign;
+import net.mograsim.logic.model.verilog.model.statements.ComponentReference;
+import net.mograsim.logic.model.verilog.model.statements.Statement;
+import net.mograsim.logic.model.verilog.model.statements.WireDeclaration;
+import net.mograsim.logic.model.verilog.utils.IdentifierGenerator;
+import net.mograsim.logic.model.verilog.utils.UnionFind;
+
+public class SubmodelComponentConverter implements ComponentConverter<SubmodelComponent>
+{
+ private final ModelComponentToVerilogConverter converter;
+
+ public SubmodelComponentConverter(ModelComponentToVerilogConverter converter)
+ {
+ this.converter = converter;
+ }
+
+ @Override
+ public ComponentConversionResult convert(SubmodelComponent modelComponent, String modelID, JsonElement params, String verilogID)
+ {
+ for (ModelComponent subcomponent : modelComponent.submodel.getComponentsByName().values())
+ if (!subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME))
+ converter.convert(subcomponent);
+
+ UnionFind<PinBit> connectedPins = findConnectedPins(modelComponent);
+
+ ModelComponentToVerilogComponentDeclarationMapping mapping = mapDeclaration(modelComponent, connectedPins, modelID, params,
+ verilogID);
+
+ VerilogComponentImplementation implementation = mapImplementation(modelComponent, connectedPins, mapping);
+
+ return new ComponentConversionResult(mapping, implementation);
+ }
+
+ private UnionFind<PinBit> findConnectedPins(SubmodelComponent modelComponent)
+ {
+ UnionFind<PinBit> connectedPins = new UnionFind<>();
+ for (ModelWire w : modelComponent.submodel.getWiresByName().values())
+ for (int bit = 0; bit < w.getPin1().logicWidth; bit++)
+ connectedPins.union(new PinBit(w.getPin1(), bit), new PinBit(w.getPin2(), bit));
+
+ for (ModelComponent subcomponent : modelComponent.submodel.getComponentsByName().values())
+ if (subcomponent instanceof ModelSplitter)
+ {
+ ModelSplitter splitter = (ModelSplitter) subcomponent;
+ for (int bit = 0; bit < splitter.logicWidth; bit++)
+ connectedPins.union(new PinBit(splitter.getInputPin(), bit), new PinBit(splitter.getOutputPin(bit), 0));
+ } else if (!(subcomponent instanceof ModelWireCrossPoint)
+ && !subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME))
+ {
+ ModelComponentToVerilogComponentDeclarationMapping subcomponentMapping = converter.getComponentMapping(subcomponent);
+ for (Set<PinNameBit> connected : subcomponentMapping.getInternallyConnectedPins())
+ connectedPins.unionAll(connected.stream().map(p -> p.toPinBit(subcomponent)).collect(Collectors.toList()));
+ }
+
+ return connectedPins;
+ }
+
+ private static ModelComponentToVerilogComponentDeclarationMapping mapDeclaration(SubmodelComponent modelComponent,
+ UnionFind<PinBit> connectedPins, String modelID, JsonElement params, String verilogID)
+ {
+ // TODO this is probably slow
+ Map<PinBit, PinNameBit> representantMapping = new HashMap<>();
+ UnionFind<PinNameBit> connectedPinsByName = new UnionFind<>();
+ for (Pin p : modelComponent.getSubmodelPins().values())
+ for (int bit = 0; bit < p.logicWidth; bit++)
+ {
+ PinNameBit pinnamebit = new PinNameBit(p.name, bit);
+ PinNameBit representative = representantMapping.computeIfAbsent(connectedPins.find(new PinBit(p, bit)), q -> pinnamebit);
+ connectedPinsByName.union(pinnamebit, representative);
+ }
+
+ return generateCanonicalDeclarationMapping(modelComponent, connectedPinsByName, modelID, params, verilogID);
+ }
+
+ public static ModelComponentToVerilogComponentDeclarationMapping generateCanonicalDeclarationMapping(ModelComponent modelComponent,
+ UnionFind<PinNameBit> connectedPins, String modelID, JsonElement params, String verilogID)
+ {
+ IdentifierGenerator ioPortIDGen = new IdentifierGenerator(ModelComponentToVerilogConverter::sanitizeVerilogID);
+ List<IOPort> ioPorts = new ArrayList<>();
+ Map<Type, Map<PinNameBit, VerilogEmulatedModelPinBuilder>> pinMapping = new HashMap<>();
+ for (Type t : Type.values())
+ pinMapping.put(t, new HashMap<>());
+ for (Pin modelPin : modelComponent.getPins().values())
+ for (int bit = 0; bit < modelPin.logicWidth; bit++)
+ {
+ PinNameBit pinbit = new PinNameBit(modelPin.name, bit);
+ addPinMapping(ioPortIDGen, ioPorts, connectedPins, pinMapping, pinbit, Input::new, Type.PRE, "pre");
+ addPinMapping(ioPortIDGen, ioPorts, connectedPins, pinMapping, pinbit, Output::new, Type.OUT, "out");
+ addPinMapping(ioPortIDGen, ioPorts, connectedPins, pinMapping, pinbit, Input::new, Type.RES, "res");
+ }
+
+ VerilogComponentDeclaration declaration = new VerilogComponentDeclaration(verilogID, ioPorts);
+ Set<VerilogEmulatedModelPin> finalPinMapping = pinMapping.values().stream().map(Map::values).flatMap(Collection::stream)
+ .map(VerilogEmulatedModelPinBuilder::build).collect(Collectors.toSet());
+ return new ModelComponentToVerilogComponentDeclarationMapping(modelID, params, declaration, finalPinMapping);
+ }
+
+ private static void addPinMapping(IdentifierGenerator ioPortIDGen, List<IOPort> ioPorts, UnionFind<PinNameBit> connectedPins,
+ Map<Type, Map<PinNameBit, VerilogEmulatedModelPinBuilder>> pinMapping, PinNameBit pinbit,
+ BiFunction<String, Integer, IOPort> constr, Type type, String suffix)
+ {
+ Map<PinNameBit, VerilogEmulatedModelPinBuilder> pinMappingCorrectType = pinMapping.get(type);
+ pinMappingCorrectType.computeIfAbsent(connectedPins.find(pinbit), p ->
+ {
+ String portID = ioPortIDGen.generateID(p.getName() + "_" + p.getBit() + "_" + suffix);
+ IOPort ioPort = constr.apply(portID, 2);
+ int index = ioPorts.size();
+ ioPorts.add(ioPort);
+ return new VerilogEmulatedModelPinBuilder(ioPort, index, type);
+ }).addPinbit(pinbit);
+ }
+
+ private static class VerilogEmulatedModelPinBuilder
+ {
+ private final IOPort verilogPort;
+ private final int portIndex;
+ private final Set<PinNameBit> pinbits;
+ private final Type type;
+
+ public VerilogEmulatedModelPinBuilder(IOPort verilogPort, int portIndex, Type type)
+ {
+ this.verilogPort = verilogPort;
+ this.portIndex = portIndex;
+ this.pinbits = new HashSet<>();
+ this.type = type;
+ }
+
+ public void addPinbit(PinNameBit pinbit)
+ {
+ pinbits.add(pinbit);
+ }
+
+ public VerilogEmulatedModelPin build()
+ {
+ return new VerilogEmulatedModelPin(verilogPort, portIndex, pinbits, type);
+ }
+ }
+
+ private VerilogComponentImplementation mapImplementation(SubmodelComponent modelComponent, UnionFind<PinBit> connectedPins,
+ ModelComponentToVerilogComponentDeclarationMapping declarationMapping)
+ {
+ Map<PinBit, Expression> currentPreExprs = new HashMap<>();
+ Map<PinBit, Signal> finalOutSignals = new HashMap<>();
+ Map<PinBit, Expression> resExprs = new HashMap<>();
+ for (Set<PinNameBit> connectedPinGroup : declarationMapping.getInternallyConnectedPins())
+ {
+ PinNameBit pinnamebit = connectedPinGroup.iterator().next();
+ PinBit root = connectedPins.find(pinnamebit.toSubmodelPinBit(modelComponent));
+ resExprs.put(root, new SignalReference(declarationMapping.getResPinMapping().get(pinnamebit).getVerilogPort()));
+ finalOutSignals.put(root, declarationMapping.getOutPinMapping().get(pinnamebit).getVerilogPort());
+ currentPreExprs.put(root, new SignalReference(declarationMapping.getPrePinMapping().get(pinnamebit).getVerilogPort()));
+ }
+
+ IdentifierGenerator idGen = ModelComponentToVerilogConverter
+ .generateIdentifierGenerator(declarationMapping.getVerilogComponentDeclaration());
+ List<Statement> statements = new ArrayList<>();
+ for (ModelComponent subcomponent : modelComponent.submodel.getComponentsByName().values())
+ {
+ // TODO do we really want to use instanceof?
+ if (subcomponent instanceof ModelSplitter || subcomponent instanceof ModelWireCrossPoint
+ || subcomponent.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME))
+ continue;
+
+ String subcomponentVerilogName = idGen.generateID(subcomponent.getName());
+ ModelComponentToVerilogComponentDeclarationMapping subcomponentMapping = converter.getComponentMapping(subcomponent);
+ int parameterCount = subcomponentMapping.getVerilogComponentDeclaration().getIOPorts().size();
+ List<Expression> arguments = new ArrayList<>(parameterCount);
+ for (int i = 0; i < parameterCount; i++)
+ arguments.add(null);
+ for (Pin pin : subcomponent.getPins().values())
+ for (int bit = 0; bit < pin.logicWidth; bit++)
+ {
+ PinBit pinbit = new PinBit(pin, bit);
+ PinBit root = connectedPins.find(pinbit);
+ Wire outSignal = new Wire(idGen.generateID(subcomponentVerilogName + "_" + pin.name + "_" + bit), 2);
+ statements.add(new WireDeclaration(outSignal));
+ Expression preExpr = currentPreExprs.put(root, new SignalReference(outSignal));
+ Expression outExpr = new SignalReference(outSignal);
+ Expression resExpr = resExprs.get(root);
+ if (resExpr == null)
+ {
+ preExpr = new Constant(BitVector.of(Bit.ZERO, 2));
+ Wire resWire = new Wire(idGen.generateID(subcomponentVerilogName + "_" + pin.name + "_" + bit + "_res"), 2);
+ resExpr = new SignalReference(resWire);
+ statements.add(new WireDeclaration(resWire));
+ finalOutSignals.put(root, resWire);
+ resExprs.put(root, resExpr);
+ }
+ PinNameBit pinnamebit = pinbit.toPinNameBit();
+ arguments.set(subcomponentMapping.getPrePinMapping().get(pinnamebit).getPortIndex(), preExpr);
+ arguments.set(subcomponentMapping.getOutPinMapping().get(pinnamebit).getPortIndex(), outExpr);
+ arguments.set(subcomponentMapping.getResPinMapping().get(pinnamebit).getPortIndex(), resExpr);
+ }
+ statements
+ .add(new ComponentReference(subcomponentVerilogName, subcomponentMapping.getVerilogComponentDeclaration(), arguments));
+ }
+
+ for (Entry<PinBit, Signal> e : finalOutSignals.entrySet())
+ statements.add(new Assign(e.getValue(), currentPreExprs.get(e.getKey())));
+
+ return new VerilogComponentImplementation(declarationMapping.getVerilogComponentDeclaration(), statements);
+ }
+}
--- /dev/null
+package net.mograsim.logic.model.verilog.converter.components;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.gson.JsonElement;
+
+import net.mograsim.logic.core.types.Bit;
+import net.mograsim.logic.core.types.BitVector;
+import net.mograsim.logic.model.model.components.atomic.ModelTriStateBuffer;
+import net.mograsim.logic.model.model.wires.Pin;
+import net.mograsim.logic.model.verilog.converter.ComponentConversionResult;
+import net.mograsim.logic.model.verilog.converter.ModelComponentToVerilogComponentDeclarationMapping;
+import net.mograsim.logic.model.verilog.converter.ModelComponentToVerilogConverter;
+import net.mograsim.logic.model.verilog.converter.PinNameBit;
+import net.mograsim.logic.model.verilog.model.VerilogComponentDeclaration;
+import net.mograsim.logic.model.verilog.model.VerilogComponentImplementation;
+import net.mograsim.logic.model.verilog.model.expressions.Constant;
+import net.mograsim.logic.model.verilog.model.expressions.Expression;
+import net.mograsim.logic.model.verilog.model.expressions.SignalReference;
+import net.mograsim.logic.model.verilog.model.signals.IOPort;
+import net.mograsim.logic.model.verilog.model.signals.Input;
+import net.mograsim.logic.model.verilog.model.signals.Output;
+import net.mograsim.logic.model.verilog.model.signals.Wire;
+import net.mograsim.logic.model.verilog.model.statements.Assign;
+import net.mograsim.logic.model.verilog.model.statements.ComponentReference;
+import net.mograsim.logic.model.verilog.model.statements.Statement;
+import net.mograsim.logic.model.verilog.model.statements.WireDeclaration;
+import net.mograsim.logic.model.verilog.utils.IdentifierGenerator;
+import net.mograsim.logic.model.verilog.utils.UnionFind;
+
+public class TriStateBufferConverter implements ComponentConverter<ModelTriStateBuffer>
+{
+ // TODO don't hardcode this
+ private static final VerilogComponentDeclaration TSBW_COMBINE = new VerilogComponentDeclaration("tsbw_combine",
+ List.of(new Input("wA", 2), new Input("wB", 2), new Output("res", 2)));
+ private static final VerilogComponentDeclaration TSBW_CONDITIONAL = new VerilogComponentDeclaration("tsbw_conditional",
+ List.of(new Input("cond", 2), new Input("onTrue", 2), new Input("onFalse", 2), new Output("res", 2)));
+
+ private final ModelComponentToVerilogConverter converter;
+
+ public TriStateBufferConverter(ModelComponentToVerilogConverter converter)
+ {
+ this.converter = converter;
+ }
+
+ @Override
+ public ComponentConversionResult convert(ModelTriStateBuffer modelComponent, String modelID, JsonElement params, String verilogID)
+ {
+ UnionFind<PinNameBit> connectedPins = new UnionFind<>();
+ ModelComponentToVerilogComponentDeclarationMapping mapping = ModelComponentToVerilogConverter
+ .generateCanonicalDeclarationMapping(modelComponent, connectedPins, modelID, params, verilogID);
+ VerilogComponentDeclaration declaration = mapping.getVerilogComponentDeclaration();
+
+ List<Statement> statements = new ArrayList<>();
+
+ PinNameBit condPinbit = new PinNameBit(modelComponent.getEnablePin().name, 0);
+ IOPort condPre = mapping.getPrePinMapping().get(condPinbit).getVerilogPort();
+ IOPort condOut = mapping.getOutPinMapping().get(condPinbit).getVerilogPort();
+ IOPort condRes = mapping.getResPinMapping().get(condPinbit).getVerilogPort();
+ Expression condrResRef = new SignalReference(condRes);
+
+ statements.add(new Assign(condOut, new SignalReference(condPre)));
+
+ IdentifierGenerator idGen = ModelComponentToVerilogConverter.generateIdentifierGenerator(declaration);
+
+ Pin inputPin = modelComponent.getInputPin();
+ Pin outputPin = modelComponent.getOutputPin();
+ for (int bit = 0; bit < inputPin.logicWidth; bit++)
+ {
+ PinNameBit inputPinbit = new PinNameBit(inputPin.name, bit);
+ PinNameBit outputPinbit = new PinNameBit(outputPin.name, bit);
+
+ IOPort inPre = mapping.getPrePinMapping().get(inputPinbit).getVerilogPort();
+ IOPort inOut = mapping.getOutPinMapping().get(inputPinbit).getVerilogPort();
+ IOPort inRes = mapping.getResPinMapping().get(inputPinbit).getVerilogPort();
+ IOPort outPre = mapping.getPrePinMapping().get(outputPinbit).getVerilogPort();
+ IOPort outOut = mapping.getOutPinMapping().get(outputPinbit).getVerilogPort();
+ Expression inPreRef = new SignalReference(inPre);
+ Expression inResRef = new SignalReference(inRes);
+ Expression outPreRef = new SignalReference(outPre);
+ Expression outOutRef = new SignalReference(outOut);
+
+ Wire condTmp = new Wire(idGen.generateID("cond_tmp_" + bit), 2);
+ SignalReference condTmpRef = new SignalReference(condTmp);
+ statements.add(new WireDeclaration(condTmp));
+
+ statements.add(new Assign(inOut, inPreRef));
+ statements.add(new ComponentReference(idGen.generateID("cond_" + bit), TSBW_CONDITIONAL,
+ List.of(condrResRef, inResRef, new Constant(BitVector.of(Bit.ZERO, 2)), condTmpRef)));
+ statements
+ .add(new ComponentReference(idGen.generateID("comb_" + bit), TSBW_COMBINE, List.of(outPreRef, condTmpRef, outOutRef)));
+ }
+
+ VerilogComponentImplementation implementation = new VerilogComponentImplementation(declaration, statements);
+
+ return new ComponentConversionResult(mapping, implementation);
+ }
+}
--- /dev/null
+package net.mograsim.logic.model.verilog.model.expressions;
+
+import java.util.Set;
+
+import net.mograsim.logic.core.types.BitVector;
+import net.mograsim.logic.model.verilog.model.signals.Signal;
+
+public class Constant extends Expression
+{
+ private final BitVector constant;
+
+ public Constant(BitVector constant)
+ {
+ super(constant.length());
+ this.constant = constant;
+
+ check();
+ }
+
+ private void check()
+ {
+ if (!constant.isBinary())
+ throw new IllegalArgumentException("Constant is not binary: " + constant);
+ }
+
+ public BitVector getConstant()
+ {
+ return constant;
+ }
+
+ @Override
+ public String toVerilogCode()
+ {
+ return getWidth() + "'b" + constant.toBitstring();
+ }
+
+ @Override
+ public Set<Signal> getReferencedSignals()
+ {
+ return Set.of();
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((constant == null) ? 0 : constant.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Constant other = (Constant) obj;
+ if (constant == null)
+ {
+ if (other.constant != null)
+ return false;
+ } else if (!constant.equals(other.constant))
+ return false;
+ return true;
+ }
+}
public Expression(int width)
{
this.width = width;
+
+ check();
+ }
+
+ private void check()
+ {
+ if (width < 0)
+ throw new IllegalArgumentException("Width can't be negative");
}
public int getWidth()
+++ /dev/null
-package net.mograsim.logic.model.verilog.model.signals;
-
-import net.mograsim.logic.core.types.BitVector;
-
-public class Constant extends Signal
-{
- private final BitVector constant;
-
- public Constant(BitVector constant)
- {
- super(Type.CONSTANT, constant.length());
- this.constant = constant;
-
- check();
- }
-
- private void check()
- {
- if (!constant.isBinary())
- throw new IllegalArgumentException("Constant is not binary: " + constant);
- }
-
- public BitVector getConstant()
- {
- return constant;
- }
-
- @Override
- public String toReferenceVerilogCode()
- {
- return getWidth() + "'b" + constant.toBitstring();
- }
-
- @Override
- public int hashCode()
- {
- final int prime = 31;
- int result = super.hashCode();
- result = prime * result + ((constant == null) ? 0 : constant.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj)
- return true;
- if (!super.equals(obj))
- return false;
- if (getClass() != obj.getClass())
- return false;
- Constant other = (Constant) obj;
- if (constant == null)
- {
- if (other.constant != null)
- return false;
- } else if (!constant.equals(other.constant))
- return false;
- return true;
- }
-}
package net.mograsim.logic.model.verilog.model.signals;
-public abstract class IOPort extends NamedSignal
+public abstract class IOPort extends Signal
{
public IOPort(Type type, String name, int width)
{
+++ /dev/null
-package net.mograsim.logic.model.verilog.model.signals;
-
-import java.util.Objects;
-
-public abstract class NamedSignal extends Signal
-{
- private final String name;
-
- public NamedSignal(Type type, String name, int width)
- {
- super(type, width);
- this.name = Objects.requireNonNull(name);
- }
-
- public String getName()
- {
- return name;
- }
-
- @Override
- public String toReferenceVerilogCode()
- {
- return name;
- }
-
- @Override
- public String toString()
- {
- return name + "[" + getWidth() + "]";
- }
-
- @Override
- public int hashCode()
- {
- final int prime = 31;
- int result = super.hashCode();
- result = prime * result + ((name == null) ? 0 : name.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj)
- return true;
- if (!super.equals(obj))
- return false;
- if (getClass() != obj.getClass())
- return false;
- NamedSignal other = (NamedSignal) obj;
- if (name == null)
- {
- if (other.name != null)
- return false;
- } else if (!name.equals(other.name))
- return false;
- return true;
- }
-}
public abstract class Signal
{
private final Type type;
+ private final String name;
private final int width;
- public Signal(Type type, int width)
+ public Signal(Type type, String name, int width)
{
this.type = Objects.requireNonNull(type);
+ this.name = Objects.requireNonNull(name);
this.width = width;
check();
return type;
}
+ public String getName()
+ {
+ return name;
+ }
+
public int getWidth()
{
return width;
}
- public abstract String toReferenceVerilogCode();
+ public String toReferenceVerilogCode()
+ {
+ return name;
+ }
+
+ @Override
+ public String toString()
+ {
+ return name + "[" + getWidth() + "]";
+ }
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
result = prime * result + width;
return result;
if (getClass() != obj.getClass())
return false;
Signal other = (Signal) obj;
+ if (name == null)
+ {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
if (type != other.type)
return false;
if (width != other.width)
public static enum Type
{
- WIRE, IO_INPUT, IO_OUTPUT, CONSTANT;
+ WIRE, IO_INPUT, IO_OUTPUT;
}
}
package net.mograsim.logic.model.verilog.model.signals;
-public class Wire extends NamedSignal
+public class Wire extends Signal
{
public Wire(String name, int width)
{
import java.util.Set;
import net.mograsim.logic.model.verilog.model.expressions.Expression;
-import net.mograsim.logic.model.verilog.model.signals.NamedSignal;
import net.mograsim.logic.model.verilog.model.signals.Signal;
import net.mograsim.logic.model.verilog.utils.CollectionsUtils;
public class Assign extends Statement
{
- private final NamedSignal target;
+ private final Signal target;
private final Expression source;
- public Assign(NamedSignal target, Expression source)
+ public Assign(Signal target, Expression source)
{
this.target = Objects.requireNonNull(target);
this.source = Objects.requireNonNull(source);
import java.util.stream.Collectors;
import net.mograsim.logic.model.verilog.model.VerilogComponentDeclaration;
+import net.mograsim.logic.model.verilog.model.expressions.Expression;
import net.mograsim.logic.model.verilog.model.signals.IOPort;
import net.mograsim.logic.model.verilog.model.signals.Signal;
{
private final String name;
private final VerilogComponentDeclaration referencedComponent;
- private final List<Signal> arguments;
+ private final List<Expression> arguments;
- public ComponentReference(String name, VerilogComponentDeclaration referencedComponent, List<Signal> arguments)
+ public ComponentReference(String name, VerilogComponentDeclaration referencedComponent, List<Expression> arguments)
{
this.name = Objects.requireNonNull(name);
this.referencedComponent = Objects.requireNonNull(referencedComponent);
return referencedComponent;
}
- public List<Signal> getArguments()
+ public List<Expression> getArguments()
{
return arguments;
}
StringBuilder sb = new StringBuilder();
sb.append(referencedComponent.getID() + " " + name);
- sb.append(arguments.stream().map(Signal::toReferenceVerilogCode).collect(Collectors.joining(", ", "(", ")")));
+ sb.append(arguments.stream().map(Expression::toVerilogCode).collect(Collectors.joining(", ", "(", ")")));
sb.append(";");
return sb.toString();
@Override
public Set<Signal> getReferencedSignals()
{
- return Set.copyOf(arguments);
+ return arguments.stream().map(Expression::getReferencedSignals).flatMap(Set::stream).collect(Collectors.toUnmodifiableSet());
}
@Override
{
}
- public static <E> Set<E> union(Set<E> a, Set<E> b)
+ @SafeVarargs
+ public static <E> Set<E> union(Set<E>... sets)
{
Set<E> union = new HashSet<>();
- union.addAll(a);
- union.addAll(b);
+ for (Set<E> set : sets)
+ union.addAll(set);
return Set.copyOf(union);
}
}
import net.mograsim.logic.model.model.components.atomic.ModelFixedOutput;
import net.mograsim.logic.model.model.components.atomic.ModelNandGate;
import net.mograsim.logic.model.model.components.atomic.ModelTextComponent;
-import net.mograsim.logic.model.model.components.atomic.ModelTriStateBuffer;
-import net.mograsim.logic.model.model.components.atomic.ModelTriStateBuffer.ModelTriStateBufferParams;
import net.mograsim.logic.model.serializing.IdentifyParams;
import net.mograsim.logic.model.serializing.IndirectModelComponentCreator;
import net.mograsim.logic.model.verilog.converter.ModelComponentToVerilogComponentDeclarationMapping;
new ModelNandGate(model, 1), //
new ModelFixedOutput(model, BitVector.SINGLE_0, null), //
new ModelFixedOutput(model, BitVector.SINGLE_1, null), //
- new ModelTriStateBuffer(model, new ModelTriStateBufferParams(1, Orientation.RIGHT)), //
- new ModelTriStateBuffer(model, new ModelTriStateBufferParams(1, Orientation.RIGHT_ALT)), //
- new ModelTriStateBuffer(model, new ModelTriStateBufferParams(1, Orientation.DOWN)), //
- new ModelTriStateBuffer(model, new ModelTriStateBufferParams(4, Orientation.RIGHT)), //
- new ModelTriStateBuffer(model, new ModelTriStateBufferParams(12, Orientation.RIGHT_ALT)), //
- new ModelTriStateBuffer(model, new ModelTriStateBufferParams(12, Orientation.DOWN)), //
- new ModelTriStateBuffer(model, new ModelTriStateBufferParams(16, Orientation.LEFT)), //
- new ModelTriStateBuffer(model, new ModelTriStateBufferParams(16, Orientation.RIGHT_ALT)), //
new ModelClock(model, new ModelClockParams(7000, Orientation.RIGHT)), //
new ModelTextComponent(model, "A bus"), //
new ModelTextComponent(model, "MPM addr"), //