package synthesijer.hdl; import java.util.ArrayList; import synthesijer.hdl.sequencer.SequencerState; public class HDLSignal implements HDLTree, HDLExpr, HDLVariable, HDLPortPairItem{ private final HDLModule module; private final String name; private final HDLType type; private ResourceKind kind; private HDLExpr resetValue; private HDLExpr defaultValue; private ArrayList<AssignmentCondition> conditions = new ArrayList<>(); private boolean assignAlwaysFlag; private HDLExpr assignAlwaysExpr; private boolean assignSignalEventFlag; private HDLSignal assignSignalEventSignal; private HDLExpr assignSignalEventExpr; private boolean assignPortEventFlag; private HDLPort assignPortEventPort; private HDLExpr assignPortEventExpr; private final HDLExpr equivExpr; private final boolean equivFlag; private boolean ignoreFlag = false; private boolean debugFlag = false; public enum ResourceKind{ REGISTER("reg"), WIRE("wire"); String sym; private ResourceKind(String v){ this.sym = v; } public String toString(){ return sym; } } HDLSignal(HDLModule module, String name, HDLType type, ResourceKind kind){ this(module, name, type, kind, null, false); } HDLSignal(HDLModule module, String name, HDLType type, ResourceKind kind, HDLExpr equivExpr, boolean equivFlag){ this.module = module; this.name = name; this.type = type; this.kind = kind; defaultValue = null; assignAlwaysFlag = false; assignSignalEventFlag = false; assignPortEventFlag = false; this.equivExpr = equivExpr; this.equivFlag = equivFlag; } public String getName(){ return name; } public HDLType getType(){ return type; } public int getWidth(){ if(type instanceof HDLPrimitiveType){ return ((HDLPrimitiveType)type).getWidth(); }else{ return -1; } } public ResourceKind getKind(){ return kind; } public boolean isRegister(){ return kind == ResourceKind.REGISTER; } public HDLModule getModule(){ return module; } @Override public void setResetValue(HDLExpr s){ this.resetValue = s; } @Override public void setDefaultValue(HDLExpr s){ this.defaultValue = s; } public HDLExpr getResetValue(){ if(resetValue != null){ return resetValue; }else if(type != null){ return type.getDefaultValue(); }else{ return null; } } public boolean hasDefaultValue(){ return defaultValue != null; } public HDLExpr getDefaultValue(){ return defaultValue; } public String toString(){ return String.format("HDLSignal:: name=%s, type=%s, kind=%s", name, type, kind); } public void setIgnore(boolean flag){ ignoreFlag = flag; } public boolean isIgnore(){ return ignoreFlag; } private void remove(SequencerState s){ ArrayList<AssignmentCondition> dup = new ArrayList<>(); for(AssignmentCondition c: conditions){ if(c.getSequencerState().equals(s)){ dup.add(c); } } for(AssignmentCondition d: dup){ conditions.remove(d); } } @Override public void setAssignForSequencer(HDLSequencer s, HDLExpr cond, HDLExpr expr) { s.addSeqCondExpr(this, cond, expr); } @Override public void setAssignForSequencer(HDLSequencer s, HDLExpr expr){ s.addSeqExpr(this, expr); } @Override public void setAssign(SequencerState s, HDLExpr expr){ if(s != null){ remove(s); AssignmentCondition c = new AssignmentCondition(s, expr); conditions.add(c); }else{ kind = ResourceKind.WIRE; // change resource kind to allow using "assign" statement assignAlwaysFlag = true; assignAlwaysExpr = expr; } } @Override public void setAssign(SequencerState s, int counter, HDLExpr expr){ if(s != null){ AssignmentCondition c = new AssignmentCondition(s, counter, expr); conditions.add(c); }else{ kind = ResourceKind.WIRE; // change resource kind to allow using "assign" statement assignAlwaysFlag = true; assignAlwaysExpr = expr; } } @Override public void setAssign(SequencerState s, HDLExpr cond, HDLExpr expr){ if(s != null){ AssignmentCondition c = new AssignmentCondition(s, cond, expr); conditions.add(c); }else{ kind = ResourceKind.WIRE; // change resource kind to allow using "assign" statement assignAlwaysFlag = true; assignAlwaysExpr = expr; } } public boolean isAssignAlways(){ return assignAlwaysFlag; } public HDLExpr getAssignAlwaysExpr(){ return assignAlwaysExpr; } public AssignmentCondition[] getConditions(){ return conditions.toArray(new AssignmentCondition[]{}); } private void getSrcSignals(HDLExpr expr, ArrayList<HDLSignal> list){ if(expr != null){ HDLSignal[] src = expr.getSrcSignals(); if(src != null){ for(HDLSignal s: src){ list.add(s); } } } } public HDLSignal[] getDriveSignals(){ ArrayList<HDLSignal> list = new ArrayList<>(); for(AssignmentCondition c: conditions){ if(!list.contains(c.getStateKey())){ list.add(c.getStateKey()); } /* if(c.getValue() instanceof HDLSignal){ list.add((HDLSignal)c.getValue()); }else{ HDLSignal[] src = c.getValue().getSrcSignals(); // TODO call getDriverSignals, recursively? if(src != null){ for(HDLSignal s: src){ list.add(s); } } } */ } return list.toArray(new HDLSignal[]{}); } @Override public HDLSignal[] getSrcSignals(){ ArrayList<HDLSignal> list = new ArrayList<>(); //System.out.println("getSrcSignal:" + getName()); /* for(AssignmentCondition c: conditions){ if(!list.contains(c.getStateKey())){ list.add(c.getStateKey()); } HDLSignal[] src = c.getValue().getSrcSignals(); if(src != null){ for(HDLSignal s: src){ list.add(s); } } } */ getSrcSignals(assignAlwaysExpr, list); getSrcSignals(resetValue, list); getSrcSignals(defaultValue, list); getSrcSignals(equivExpr, list); return list.toArray(new HDLSignal[]{}); } //////////////////////////////////////////////////////////////////////////// public boolean isAssignSignalEvent(){ return assignSignalEventFlag; } public void setAssignForSignalEvent(HDLSignal sig, HDLExpr expr){ assignSignalEventFlag = true; assignSignalEventSignal = sig; assignSignalEventExpr = expr; } public HDLSignal getAssignSignalEventSignal(){ return assignSignalEventSignal; } public HDLExpr getAssignSignalEventExpr(){ return assignSignalEventExpr; } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public boolean isAssignPortEvent(){ return assignPortEventFlag; } public void setAssignForPortEvent(HDLPort port, HDLExpr expr){ assignPortEventFlag = true; assignPortEventPort = port; assignPortEventExpr = expr; } public HDLPort getAssignPortEventPort(){ return assignPortEventPort; } public HDLExpr getAssignPortEventExpr(){ return assignPortEventExpr; } //////////////////////////////////////////////////////////////////////////// public class AssignmentCondition{ private final SequencerState s; private final HDLExpr value; private final int count; private final HDLExpr cond; private AssignmentCondition(SequencerState s, HDLExpr cond, int count, HDLExpr value) { this.s = s; this.value = value; this.count = count; this.cond = cond; } public AssignmentCondition(SequencerState s, HDLExpr value) { this(s, null, -1, value); } public AssignmentCondition(SequencerState s, int count, HDLExpr value) { this(s, null, count, value); } public AssignmentCondition(SequencerState s, HDLExpr cond, HDLExpr value) { this(s, cond, -1, value); } public String getCondExprAsVHDL(){ String str = ""; if(count < 0){ String c = String.format("%s = %s", s.getKey().getName(), s.getStateId().getValue()); String ext = s.getExitConditionAsVHDL(); if(!ext.equals("")) c += " and " + ext; str = c; }else{ str = String.format("%s = %s and %s = %d", s.getKey().getName(), s.getStateId().getValue(), s.getSequencer().getDelayCounter().getName(), count); } if(cond != null){ if(cond.getResultExpr().getType().isBit()){ str += " and " + cond.getResultExpr().getVHDL() + " = '1'"; }else{ if(cond.getResultExpr().getType().isVector()){ str += " and singed(" + cond.getResultExpr().getVHDL() + ")" + " /= 0"; }else{ str += " and " + cond.getResultExpr().getVHDL() + " /= 0"; } } } return str; } public String getCondExprAsVerilogHDL(){ String str; if(count < 0){ String c = String.format("%s == %s", s.getKey().getName(), s.getStateId().getValue()); String ext = s.getExitConditionAsVerilogHDL(); if(!ext.equals("")) c += " && " + ext; str = c; }else{ str = String.format("%s == %s && %s == %d", s.getKey().getName(), s.getStateId().getValue(), s.getSequencer().getDelayCounter().getName(), count); } if(cond != null){ if(cond.getResultExpr().getType().isBit()){ str += " && " + cond.getResultExpr().getVerilogHDL() + " == 1'b1"; }else{ str += " && " + cond.getResultExpr().getVerilogHDL() + " != 0"; } } return str; } public HDLExpr getValue(){ return value.getResultExpr(); } public HDLSignal getStateKey(){ return s.getKey(); } public SequencerState getSequencerState(){ return s; } } @Override public void accept(HDLTreeVisitor v) { v.visitHDLSignal(this); } @Override public String getVHDL() { return name; } @Override public String getVerilogHDL() { return name; } @Override public HDLExpr getResultExpr() { return this; } public void setDebugFlag(boolean flag){ debugFlag = flag; } public boolean isDebugFlag(){ return debugFlag; } }