/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.atolsystems.HwModeling;
import com.atolsystems.atolutilities.MutableInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
/**
*
* @author sebastien.riou
*/
public class VerilogModule implements Comparable{
String name;
//ArrayList<VerilogPort> ports;
TreeMap<String,VerilogPort> inputPorts;
TreeMap<String,VerilogPort> outputPorts;
TreeMap<String,VerilogPort> inOutPorts;
TreeMap<Integer,TreeMap<String,VerilogPort>> ports;
String body;
boolean primitive;
protected boolean verilog1995 = false;
/**
* Get the value of verilog1995
*
* @return the value of verilog1995
*/
public boolean isVerilog1995() {
return verilog1995;
}
/**
* Set the value of verilog1995
*
* @param verilog1995 new value of verilog1995
*/
public void setVerilog1995(boolean verilog1995) {
this.verilog1995 = verilog1995;
}
public VerilogModule(VerilogModule module) {
this.name=module.name;
initPorts(module.getPorts());
this.body=module.body;
this.primitive=module.primitive;
}
public VerilogModule(String name, ArrayList<VerilogPort> ports, String body, boolean isPrimitive) {
this.name = name;
initPorts(ports);
this.body = body;
this.primitive=isPrimitive;
}
final void initPorts(Collection<VerilogPort> ports){
inputPorts=new TreeMap<String, VerilogPort>();
outputPorts=new TreeMap<String, VerilogPort>();
inOutPorts=new TreeMap<String, VerilogPort>();
this.ports=new TreeMap<Integer,TreeMap<String, VerilogPort>>();
this.ports.put(VerilogPort.INPUT, inputPorts);
this.ports.put(VerilogPort.OUTPUT, outputPorts);
this.ports.put(VerilogPort.OUTPUT_REG, outputPorts);
this.ports.put(VerilogPort.INOUT, inOutPorts);
if(null==ports) return;
for(VerilogPort p:ports){
if(p.isPort()){
if(hasPort(p.getName())) throw new RuntimeException("Port '"+p.getName()+"' already defined in module "+this.getName());
this.ports.get(p.getType()).put(p.getName(), p);
} else {
if(!p.isWire()) throw new RuntimeException("Port '"+p.getName()+"': unknown port type "+p.getType());
}
}
}
public VerilogModule(String name) {
this.name = name;
body="";
initPorts(null);
}
public VerilogModule() {
body="";
initPorts(null);
}
public boolean isPrimitive() {
return primitive;
}
public void setPrimitive(boolean primitive) {
this.primitive = primitive;
}
public String getBody() {
return body;
}
/**
* body should not be null
* @param body
*/
public void setBody(String body) {
this.body = body;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* Remove ports which are defined as port in this module
* @param ports
*/
public void excludePorts(Collection<VerilogPort> ports){
ArrayList<VerilogPort> toRemove=new ArrayList<VerilogPort>();
for(VerilogPort p:ports){
if(null!=this.inputPorts.get(p.getName()))
toRemove.add(p);
if(null!=this.outputPorts.get(p.getName()))
toRemove.add(p);
if(null!=this.inOutPorts.get(p.getName()))
toRemove.add(p);
}
ports.removeAll(toRemove);
}
/*public ArrayList<VerilogPort> getPorts() {
ArrayList<VerilogPort> out=getInputs();
out.addAll(getOutputs());
out.addAll(getInOuts());
return out;
}*/
public ArrayList<VerilogPort> getPorts() {
ArrayList<VerilogPort> out=new ArrayList<VerilogPort>();
out.addAll(getInputs());
out.addAll(getOutputs());
out.addAll(getInOuts());
return out;
}
VerilogPort getPort(String portName) {
VerilogPort out = this.getInput(portName);
if(null!=out) return out;
out=this.getOutput(portName);
if(null!=out) return out;
out=this.getInOut(portName);
return out;
}
public void setPorts(ArrayList<VerilogPort> ports) {
initPorts(ports);
}
/*public ArrayList<VerilogPort> getInputs(){
return inputPorts.values();
}
public ArrayList<VerilogPort> getOutputs(){
return outputPorts;
}
public ArrayList<VerilogPort> getInOuts(){
return inOutPorts;
}*/
public Collection<VerilogPort> getInputs(){
return inputPorts.values();
}
public ArrayList<VerilogPort> getInputsArrayList(){
ArrayList<VerilogPort> out=new ArrayList<VerilogPort>();
out.addAll(inputPorts.values());
return out;
}
public VerilogPort getFirstInput(){
return inputPorts.firstEntry().getValue();
}
public String getFirstInputName(){
return inputPorts.firstKey();
}
public Collection<VerilogPort> getOutputs(){
return outputPorts.values();
}
public ArrayList<VerilogPort> getOutputsArrayList(){
ArrayList<VerilogPort> out=new ArrayList<VerilogPort>();
out.addAll(outputPorts.values());
return out;
}
public VerilogPort getFirstOutput(){
return outputPorts.firstEntry().getValue();
}
public String getFirstOutputName(){
return outputPorts.firstKey();
}
public Collection<VerilogPort> getInOuts(){
return inOutPorts.values();
}
public ArrayList<VerilogPort> getOutputsInOuts(){
ArrayList<VerilogPort> outPorts=new ArrayList<VerilogPort>();
outPorts.addAll(getOutputs());
outPorts.addAll(getInOuts());
return outPorts;
}
public ArrayList<VerilogPort> getInputsInOuts(){
ArrayList<VerilogPort> inPorts=new ArrayList<VerilogPort>();
inPorts.addAll(getInputs());
inPorts.addAll(getInOuts());
return inPorts;
}
public VerilogPort getInput(String name){
return inputPorts.get(name);
}
public VerilogPort getInputInOut(String name){
VerilogPort out=inputPorts.get(name);
if(null==out) out=inOutPorts.get(name);
return out;
}
public VerilogPort getOutput(String name){
return outputPorts.get(name);
}
public VerilogPort getOutputInOut(String name){
VerilogPort out=outputPorts.get(name);
if(null==out) out=inOutPorts.get(name);
return out;
}
public VerilogPort getInOut(String name){
return inOutPorts.get(name);
}
public boolean isInOut(String name){
VerilogPort p=inOutPorts.get(name);
if(null!=p) return true;
if(outputPorts.containsKey(name) | inputPorts.containsKey(name)) return false;
throw new RuntimeException("Port '"+name+"' is not declared in module '"+this.getName()+"'");
}
public boolean isInput(String name){
VerilogPort p=inputPorts.get(name);
if(null!=p) return true;
if(outputPorts.containsKey(name) | inOutPorts.containsKey(name)) return false;
throw new RuntimeException("Port '"+name+"' is not declared in module '"+this.getName()+"'");
}
public boolean isOutput(String name){
VerilogPort p=outputPorts.get(name);
if(null!=p) return true;
if(inputPorts.containsKey(name) | inOutPorts.containsKey(name)) return false;
throw new RuntimeException("Port '"+name+"' is not declared in module '"+this.getName()+"'");
}
public boolean hasPort(String name){
if(outputPorts.containsKey(name) | inputPorts.containsKey(name) | inOutPorts.containsKey(name)) return true;
return false;
}
public String instantiate(String instanceName){
TreeMap<String,String> connections=new TreeMap<String,String>();
for(VerilogPort p:getInputs())
connections.put(p.getName(), p.getName());
for(VerilogPort p:getOutputs())
connections.put(p.getName(), p.getName());
for(VerilogPort p:getInOuts())
connections.put(p.getName(), p.getName());
return instantiate(instanceName,connections);
}
public String instantiate(String instanceName, Map<String,String> connections){
StringBuilder sb=new StringBuilder();
int remaining=connections.entrySet().size();
if(remaining!=getPorts().size()){
if(0==remaining) throw new RuntimeException("No connections defined for instance '"+instanceName+"' ("+this.getName()+")");
sb.append("//WARNING: ");
sb.append(getPorts().size()-remaining);
sb.append(" unconnected ports\n");
int unconnectedCnt=0;
for(VerilogPort p:getPorts()){
if(!connections.containsKey(p.getName())){
connections.put(p.getName(), instanceName+"_unconnected"+unconnectedCnt);
unconnectedCnt++;
}
}
}
sb.append(name);
sb.append(" ");
sb.append(instanceName);
sb.append(" (\n .");
for(Entry<String,String> e:connections.entrySet()){
sb.append(e.getKey());
sb.append("(");
sb.append(e.getValue());
sb.append(")");
if(1==remaining)
sb.append("\n );");
else
sb.append(",\n .");
remaining--;
}
return sb.toString();
}
protected void addPortDeclaration(StringBuilder sb, VerilogPort p, boolean justName){
if(!justName){
if(verilog1995 && p.isOutputReg()){
sb.append("output ");
sb.append(p.getName());
sb.append("; reg");
}else
sb.append(p.getTypeString());
sb.append(" ");
if(p.getWidth()!=1){
sb.append("[");
sb.append(p.getWidth()-1);
sb.append(":0]");
}
}
sb.append(p.getName());
}
protected void addPortsDeclaration(StringBuilder sb, MutableInteger remaining, Collection<VerilogPort> ports){
if(null==remaining) remaining=new MutableInteger(ports.size());
for(VerilogPort p:ports){
addPortDeclaration(sb, p, verilog1995);
if(1!=remaining.value)
sb.append(",\n ");
remaining.value=remaining.value-1;
}
}
protected void addPortsTypeDeclaration(StringBuilder sb, MutableInteger remaining, Collection<VerilogPort> ports){
if(null==remaining) remaining=new MutableInteger(ports.size());
for(VerilogPort p:ports){
addPortDeclaration(sb, p, false);
if(1==remaining.value)
sb.append(";\n");
else
sb.append(";\n ");
remaining.value=remaining.value-1;
}
}
@Override
public String toString() {
StringBuilder sb=new StringBuilder();
if(primitive)
sb.append("primitive ");
else
sb.append("module ");
sb.append(name);
sb.append("(\n");
//MutableInteger remaining=null;//new MutableInteger(ports.size());
if(hasInputs()) sb.append("//inputs:\n ");
addPortsDeclaration(sb,null,getInputs());
if(hasOutputs()){
if(hasInputs()) sb.append(",\n");
sb.append("//outputs:\n ");
addPortsDeclaration(sb,null,getOutputs());
}
if(hasInOuts()){
if(hasOutputs()) sb.append(",\n");
if(hasInOuts()) sb.append("//inouts:\n ");
addPortsDeclaration(sb,null,getInOuts());
}
sb.append("\n );\n");
if(verilog1995){
//remaining.value=ports.size();
if(hasInputs()) sb.append("//inputs:\n ");
addPortsTypeDeclaration(sb,null,getInputs());
if(hasOutputs()) sb.append("//outputs:\n ");
addPortsTypeDeclaration(sb,null,getOutputs());
if(hasInOuts()) sb.append("//inouts:\n ");
addPortsTypeDeclaration(sb,null,getInOuts());
}
if(!body.isEmpty()){
sb.append("\n");
sb.append(body);
if(!body.endsWith("\n"))
sb.append("\n");
if(primitive)
sb.append("endprimitive");
else
sb.append("endmodule");
}
return sb.toString();
}
public boolean hasInputs() {
return !inputPorts.isEmpty();
}
public boolean hasOutputs() {
return !outputPorts.isEmpty();
}
public boolean hasInOuts() {
return !inOutPorts.isEmpty();
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final VerilogModule other = (VerilogModule) obj;
if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
return false;
}
if (this.inputPorts != other.inputPorts && (this.inputPorts == null || !this.inputPorts.equals(other.inputPorts))) {
return false;
}
if (this.outputPorts != other.outputPorts && (this.outputPorts == null || !this.outputPorts.equals(other.outputPorts))) {
return false;
}
if (this.inOutPorts != other.inOutPorts && (this.inOutPorts == null || !this.inOutPorts.equals(other.inOutPorts))) {
return false;
}
if ((this.body == null) ? (other.body != null) : !this.body.equals(other.body)) {
return false;
}
if (this.primitive != other.primitive) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 5;
hash = 19 * hash + (this.name != null ? this.name.hashCode() : 0);
hash = 19 * hash + (this.inputPorts != null ? this.inputPorts.hashCode() : 0);
hash = 19 * hash + (this.outputPorts != null ? this.outputPorts.hashCode() : 0);
hash = 19 * hash + (this.inOutPorts != null ? this.inOutPorts.hashCode() : 0);
hash = 19 * hash + (this.ports != null ? this.ports.hashCode() : 0);
hash = 19 * hash + (this.body != null ? this.body.hashCode() : 0);
return hash;
}
@Override
public int compareTo(Object o) {
if(equals(o)) return 0;//ensure consistency with equals
final VerilogModule other = (VerilogModule) o;
int out = name.compareTo(other.name);
if(0==out)
out=inputPorts.size()-other.inputPorts.size();
if(0==out)
out=outputPorts.size()-other.outputPorts.size();
if(0==out)
out=inOutPorts.size()-other.inOutPorts.size();
if(0==out){
Iterator<VerilogPort> in=inputPorts.values().iterator();
Iterator<VerilogPort> inOther=other.inputPorts.values().iterator();
while(in.hasNext()){
out=in.next().compareTo(inOther.next());
if(0!=out) break;
}
}
if(0==out){
Iterator<VerilogPort> in=outputPorts.values().iterator();
Iterator<VerilogPort> inOther=other.outputPorts.values().iterator();
while(in.hasNext()){
out=in.next().compareTo(inOther.next());
if(0!=out) break;
}
}
if(0==out){
Iterator<VerilogPort> in=inOutPorts.values().iterator();
Iterator<VerilogPort> inOther=other.inOutPorts.values().iterator();
while(in.hasNext()){
out=in.next().compareTo(inOther.next());
if(0!=out) break;
}
}
if(0==out){
out=body.compareTo(other.body);
}
return out;
}
static public HashMap<String,VerilogModule> buildMap(Collection<VerilogModule> c){
HashMap<String,VerilogModule> out=new HashMap<String,VerilogModule>();
for(VerilogModule m:c){
out.put(m.getName(), m);
}
return out;
}
static public VerilogModule find(Collection<VerilogModule> c, String name){
for(VerilogModule m:c){
if(m.getName().equals(name)) return m;
}
return null;
}
}