package synthesijer.hdl.verilog; import java.io.PrintWriter; import synthesijer.Constant; import synthesijer.SynthesijerUtils; import synthesijer.hdl.HDLExpr; import synthesijer.hdl.HDLInstance; import synthesijer.hdl.HDLInstanceRef; import synthesijer.hdl.HDLInstance.ParamPair; import synthesijer.hdl.HDLLiteral; import synthesijer.hdl.HDLModule; import synthesijer.hdl.HDLParameter; import synthesijer.hdl.HDLPort; import synthesijer.hdl.HDLPrimitiveType; import synthesijer.hdl.HDLSequencer; import synthesijer.hdl.HDLSignal; import synthesijer.hdl.HDLTreeVisitor; import synthesijer.hdl.HDLUserDefinedType; import synthesijer.hdl.HDLUtils; import synthesijer.hdl.sequencer.SequencerState; import synthesijer.hdl.sequencer.StateTransitCondition; public class GenerateVerilogVisitor implements HDLTreeVisitor{ private final PrintWriter dest; private final int offset; public GenerateVerilogVisitor(PrintWriter dest, int offset){ this.dest = dest; this.offset = offset; } @Override public void visitHDLExpr(HDLExpr o) { String str = String.format("assign %s = %s;", o.getResultExpr().getVerilogHDL(), o.getVerilogHDL()); HDLUtils.println(dest, offset, str); } private void genParameterMap(HDLInstance o){ HDLUtils.println(dest, offset, String.format("#(")); String sep = ""; for(ParamPair pair: o.getParameterPairs()){ if(pair.getValue() != null){ HDLUtils.print(dest, 0, sep); HDLUtils.print(dest, offset+2, String.format(".%s(%s)", pair.param.getName(), pair.getValue().getVerilogHDL())); }else{ HDLUtils.print(dest, 0, sep); HDLUtils.print(dest, offset+2, String.format(".%s(%s)", pair.param.getName(), pair.param.getValue().getVerilogHDL())); } sep = "," + Constant.BR; } HDLUtils.println(dest, 0, ""); HDLUtils.println(dest, offset, ")"); } private void genPortMap(HDLInstance o){ HDLUtils.println(dest, offset, String.format("(")); String sep = ""; for(HDLInstance.PortPair pair: o.getPairs()){ HDLUtils.print(dest, 0, sep); if(o.getSubModule().getSysClkPairItem() != null && pair.port.getName().equals(o.getSubModule().getSysClkPairItem().getName())){ // target port to connect is system clock, the port should be connected system clock in this module directly. if(o.getModule().getSysClkPairItem() == null){ SynthesijerUtils.warn(o.getModule().getName() + " does not have system clock, but sub-module requires system clock"); SynthesijerUtils.warn("system clock of sub-module is remained as open, so the sub-module will not work well."); }else{ HDLUtils.print(dest, offset+2, String.format(".%s(%s)", pair.port.getName(), o.getModule().getSysClkPairItem().getName())); } }else if(o.getSubModule().getSysResetPairItem() != null && pair.port.getName().equals(o.getSubModule().getSysResetPairItem().getName())){ // target port to connect is system reset, the port should be connected system reset in this module directly. if(o.getModule().getSysResetPairItem() == null){ SynthesijerUtils.warn(o.getModule().getName() + " does not have system reset, but sub-module requires system reset"); SynthesijerUtils.warn("system reset of sub-module is remained as open, so the sub-module will not work well."); }else{ HDLUtils.print(dest, offset+2, String.format(".%s(%s)", pair.port.getName(), o.getModule().getSysResetPairItem().getName())); } }else{ HDLUtils.print(dest, offset+2, String.format(".%s(%s)", pair.port.getName(), pair.item.getName())); } sep = "," + Constant.BR; } HDLUtils.println(dest, 0, ""); HDLUtils.println(dest, offset, ");"); } @Override public void visitHDLInstance(HDLInstance o) { HDLUtils.println(dest, offset, o.getSubModule().getName()); if(o.getSubModule().getParameters().length > 0){ genParameterMap(o); } HDLUtils.println(dest, offset, o.getName()); genPortMap(o); HDLUtils.nl(dest); } @Override public void visitHDLLitral(HDLLiteral o) { // TODO Auto-generated method stub } private void genParameterList(HDLModule o){ HDLUtils.println(dest, offset, String.format("#(")); String sep = ""; for(HDLParameter p: o.getParameters()){ dest.print(sep); p.accept(new GenerateVerilogDefVisitor(dest, offset+2)); sep = "," + Constant.BR; } HDLUtils.println(dest, offset, Constant.BR + ")"); } private void genPortList(HDLModule o){ HDLUtils.println(dest, offset, String.format("(")); String sep = ""; for(HDLPort p: o.getPorts()){ dest.print(sep); p.accept(new GenerateVerilogDefVisitor(dest, offset+2)); sep = "," + Constant.BR; } HDLUtils.println(dest, offset, Constant.BR + ");"); } @Override public void visitHDLModule(HDLModule o) { HDLUtils.println(dest, offset, String.format("module %s", o.getName())); if(o.getParameters().length > 0){ genParameterList(o); } genPortList(o); HDLUtils.nl(dest); // definitions o.accept(new GenerateVerilogDefVisitor(dest, offset+2)); // body for(HDLPort p: o.getPorts()){ p.accept(new GenerateVerilogVisitor(dest, offset+2)); } HDLUtils.nl(dest); for(HDLExpr expr : o.getExprs()){ expr.accept(new GenerateVerilogVisitor(dest, offset+2)); } HDLUtils.nl(dest); for(HDLSequencer m: o.getSequencers()){ m.accept(new GenerateVerilogVisitor(dest, offset+2)); } HDLUtils.nl(dest); for(HDLSignal s: o.getSignals()){ s.accept(new GenerateVerilogVisitor(dest, offset+2)); } HDLUtils.nl(dest); for(HDLInstance i: o.getModuleInstances()){ i.accept(new GenerateVerilogVisitor(dest, offset+2)); } HDLUtils.nl(dest); HDLUtils.println(dest, offset, "endmodule"); } @Override public void visitHDLPort(HDLPort o) { if(o.isSet(HDLPort.OPTION.NO_SIG) || o.isSet(HDLPort.OPTION.EXPORT_PATH)) return; // nothing to do if(o.getDir() == HDLPort.DIR.INOUT){ return; // nothing to do }else if(o.isOutput()){ HDLUtils.println(dest, offset, String.format("assign %s = %s;", o.getName(), o.getSignal().getName())); }else{ HDLUtils.println(dest, offset, String.format("assign %s = %s;", o.getSignal().getName(), o.getName())); } o.getSignal().accept(this); } @Override public void visitHDLParameter(HDLParameter o) { } private void genSyncSequencerHeader(HDLSequencer o, int offset){ HDLUtils.println(dest, offset, String.format("always @(posedge %s) begin", o.getModule().getSysClkName())); } private void genAsyncSequencerHeader(HDLSequencer o, int offset){ HDLUtils.println(dest, offset, String.format("always begin")); } private void genSyncSequencerSwitch(HDLSequencer o, int offset){ if(o.getStates().size() > 0){ HDLUtils.println(dest, offset, String.format("case (%s)", o.getStateKey().getName())); for(SequencerState s: o.getStates()){ HDLUtils.println(dest, offset+2, String.format("%s : begin", s.getStateId().getVerilogHDL())); if(s.hasExitCondition()){ HDLUtils.println(dest, offset+4, String.format("if (%s) begin", s.getExitConditionAsVerilogHDL())); HDLUtils.println(dest, offset+6, String.format("%s <= 32'h0;", o.getDelayCounter().getName())); HDLUtils.println(dest, offset+6, String.format("%s <= %s;", o.getDelayCounter().getName(), o.getDelayCounter().getDefaultValue().getVerilogHDL())); genStateTransition(dest, offset+6, s); HDLUtils.println(dest, offset+4, String.format("end else begin")); HDLUtils.println(dest, offset+6, String.format("%s <= %s + 1;", o.getDelayCounter().getName(), o.getDelayCounter().getName())); HDLUtils.println(dest, offset+4, String.format("end")); }else{ genStateTransition(dest, offset+4, s); } HDLUtils.println(dest, offset+2, String.format("end")); } HDLUtils.println(dest, offset, String.format("endcase")); } for(HDLSequencer.Pair p: o.getSeqExprList()){ HDLUtils.println(dest, offset, String.format("%s <= %s;", p.dest.getVerilogHDL(), p.expr.getResultExpr().getVerilogHDL())); } for(HDLSequencer.Triple t: o.getSeqCondExprList()){ HDLUtils.println(dest, offset, String.format("if(%s == 1'b1) begin", t.cond.getVerilogHDL())); HDLUtils.println(dest, offset + 2, String.format("%s <= %s;", t.dest.getVerilogHDL(), t.expr.getResultExpr().getVerilogHDL())); HDLUtils.println(dest, offset, String.format("end")); } } private void genSyncSequencerBody(HDLSequencer o, int offset){ // reset if(o.getModule().isNegativeReset()){ HDLUtils.println(dest, offset+2, String.format("if(%s == 1'b0) begin", o.getModule().getSysResetName())); }else{ HDLUtils.println(dest, offset+2, String.format("if(%s == 1'b1) begin", o.getModule().getSysResetName())); } HDLUtils.println(dest, offset+4, String.format("%s <= %s;", o.getStateKey().getName(), o.getIdleState().getStateId().getVerilogHDL())); HDLUtils.println(dest, offset+4, String.format("%s <= 32'h0;", o.getDelayCounter().getName())); HDLUtils.println(dest, offset+2, String.format("end else begin")); genSyncSequencerSwitch(o, offset+4); HDLUtils.println(dest, offset+2, String.format("end")); } private void genAsyncSequencerBody(HDLSequencer o, int offset){ if(o.getStates().size() > 0){ for(SequencerState s: o.getStates()){ HDLUtils.println(dest, offset, String.format("// state %s = %s", o.getStateKey().getName(), s.getStateId().getVerilogHDL())); if(o.getTransitionTime() > 0) HDLUtils.println(dest, offset, String.format("#%d", o.getTransitionTime())); genStateTransition(dest, offset, s); } } } @Override public void visitHDLSequencer(HDLSequencer o) { if(o.getModule().isSynchronous()){ genSyncSequencerHeader(o, offset); }else{ genAsyncSequencerHeader(o, offset); } if(o.getModule().isSynchronous()){ genSyncSequencerBody(o, offset); }else{ genAsyncSequencerBody(o, offset); } HDLUtils.println(dest, offset, String.format("end")); HDLUtils.nl(dest); } public void genStateTransition(PrintWriter dest, int offset, SequencerState s){ if(s.getTransitions().size() > 0){ String sep = ""; int cnt = 0; for(StateTransitCondition c: s.getTransitions()){ String str = String.format("%s <= %s;", s.getKey().getName(), c.getDestState().getStateId().getVerilogHDL()); if(c.hasCondition()){ HDLUtils.println(dest, offset, String.format("%sif (%s) begin", sep, c.getCondExprAsVerilogHDL())); HDLUtils.println(dest, offset+2, str); sep = "end else "; cnt++; }else{ if(cnt == 0){ HDLUtils.println(dest, offset, str); }else{ HDLUtils.println(dest, offset, "end else begin"); HDLUtils.println(dest, offset+2, str); } } } if(cnt > 0){ HDLUtils.println(dest, offset, String.format("end")); } }else{ } } private void genSyncProcess(HDLSignal o, int offset){ if(o.getModule().isNegativeReset()){ HDLUtils.println(dest, offset, String.format("if(%s == 1'b0) begin", o.getModule().getSysResetName())); }else{ HDLUtils.println(dest, offset, String.format("if(%s == 1'b1) begin", o.getModule().getSysResetName())); } if(o.getResetValue() != null){ HDLUtils.println(dest, offset+2, String.format("%s <= %s;", o.getName(), o.getResetValue().getVerilogHDL())); } HDLUtils.println(dest, offset, String.format("end else begin")); if(o.getConditions().length > 0){ String sep = ""; for(HDLSignal.AssignmentCondition c: o.getConditions()){ HDLUtils.println(dest, offset+2, String.format("%sif (%s) begin", sep, c.getCondExprAsVerilogHDL())); if(c.getValue() != null){ HDLUtils.println(dest, offset+4, String.format("%s <= %s;", o.getName(), c.getValue().getVerilogHDL())); }else{ SynthesijerUtils.warn("Assignment value is not found for " + o.getName()); } sep = "end else "; } if(o.hasDefaultValue()){ HDLUtils.println(dest, offset+2, String.format("end else begin")); HDLUtils.println(dest, offset+4, String.format("%s <= %s;", o.getName(), o.getDefaultValue().getVerilogHDL())); } HDLUtils.println(dest, offset+2, String.format("end")); }else{ if(o.hasDefaultValue()){ HDLUtils.println(dest, offset+2, String.format("%s <= %s;", o.getName(), o.getDefaultValue().getVerilogHDL())); } } HDLUtils.println(dest, offset, String.format("end")); } private void genAsyncProcess(HDLSignal o, int offset){ /* if(o.getConditions().length == 1){ HDLUtils.println(dest, offset, String.format("%s <= %s;", o.getName(), o.getConditions()[0].getValue().getVerilogHDL())); }else if(o.getConditions().length > 1){ */ if(o.getConditions().length > 0){ String sep = ""; for(HDLSignal.AssignmentCondition c: o.getConditions()){ HDLUtils.println(dest, offset, String.format("%s if (%s) begin", sep, c.getCondExprAsVerilogHDL())); HDLUtils.println(dest, offset+2, String.format("%s <= %s;", o.getName(), c.getValue().getVerilogHDL())); sep = "end else"; } HDLUtils.println(dest, offset, String.format("end")); }else{ HDLUtils.println(dest, offset, String.format("")); } } private void genSyncProcessHeader(HDLSignal o){ HDLUtils.println(dest, offset, String.format("always @(posedge %s) begin", o.getModule().getSysClkName())); } private void genAsyncProcessHeader(HDLSignal o){ String s = ""; String sep = ""; for(HDLSignal src: o.getDriveSignals()){ s += sep + src.getName(); sep = " or "; } HDLUtils.println(dest, offset, String.format("always @(%s) begin", s)); } private void genSignalRegisterProcess(HDLSignal o){ if(o.getModule().isSynchronous()){ genSyncProcessHeader(o); }else{ genAsyncProcessHeader(o); } if(o.getModule().isSynchronous()){ genSyncProcess(o, offset+2); }else{ genAsyncProcess(o, offset+2); } HDLUtils.println(dest, offset, "end"); HDLUtils.nl(dest); } @Override public void visitHDLSignal(HDLSignal o) { if(o.isRegister() && o.isAssignSignalEvent()){ HDLUtils.println(dest, offset, String.format("always @(posedge %s) begin", o.getAssignSignalEventSignal().getName())); HDLUtils.println(dest, offset+2, String.format("%s <= %s;", o.getName(), o.getAssignSignalEventExpr().getResultExpr().getVerilogHDL())); HDLUtils.println(dest, offset, "end"); HDLUtils.nl(dest); }else if(o.isRegister() && o.isAssignPortEvent()){ HDLUtils.println(dest, offset, String.format("always @(posedge %s) begin", o.getAssignPortEventPort().getName())); HDLUtils.println(dest, offset+2, String.format("%s <= %s;", o.getName(), o.getAssignPortEventExpr().getResultExpr().getVerilogHDL())); HDLUtils.println(dest, offset, "end"); HDLUtils.nl(dest); }else if(o.isRegister()){ if(o.isIgnore()) return; if(o.getConditions().length == 0 && o.hasDefaultValue() == false) return; genSignalRegisterProcess(o); }else if(o.isAssignAlways()){ HDLUtils.println(dest, offset, String.format("assign %s = %s;", o.getName(), o.getAssignAlwaysExpr().getResultExpr().getVerilogHDL())); HDLUtils.nl(dest); } } @Override public void visitHDLType(HDLPrimitiveType o) { // TODO Auto-generated method stub } @Override public void visitHDLUserDefinedType(HDLUserDefinedType o) { // TODO Auto-generated method stub } @Override public void visitHDLInstanceRef(HDLInstanceRef o){ } }