package synthesijer.scheduler; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; import java.util.Hashtable; import java.util.ArrayList; import synthesijer.ast.type.PrimitiveTypeKind; public class IrohaWriter { private final String name; public IrohaWriter(String name){ this.name = name; } public void generate(SchedulerInfo info) throws IOException{ try( PrintStream ir = new PrintStream(new FileOutputStream(new File(name + ".iroha"))); ){ ir.println("(MODULE " + info.getName()); //genVariables(ir, info.getModuleVarList().toArray(new VariableOperand[]{})); //genVariables(ir, info.getModuleVarList().toArray(new Operand[]{})); ir.println("(PARAMS (RESET-POLARITY true) (RESET-NAME reset))"); for(SchedulerBoard b: info.getBoardsList()){ genSchedulerBoard(ir, b); } ir.println(")"); ir.close(); }catch(IOException e){ throw new IOException(e); } } private String pad(int w){ String s = ""; for(int i = 0; i < w; i++) s += " "; return s; } private void println(PrintStream ir, int offset, String mesg){ ir.println(pad(offset)+mesg); } private int table_id = 1; private void genSchedulerBoard(PrintStream ir, SchedulerBoard b){ println(ir, 2, "(TABLE " + (table_id++)); genRegisters(ir, b); genResources(ir, b); println(ir, 2, " (INITIAL 1)"); int insn_id = 1; for(SchedulerSlot s: b.getSlots()){ insn_id = genState(ir, b, s, insn_id); } println(ir, 2, ")"); } private int genState(PrintStream ir, SchedulerBoard b, SchedulerSlot slot, int insn_id){ println(ir, 4, "(STATE " + (slot.getStepId()+1)); // step id is 0-origin, but state id is 1-origin if(slot.getNextStep().length == 1 && slot.hasBranchOp() == false){ insn_id += genStateTr(ir, (slot.getNextStep()[0]+1), insn_id); } for(SchedulerItem i: slot.getItems()){ insn_id += genStateInsn(ir, b, i, insn_id); } println(ir, 4, ")"); return insn_id; } private int genStateTr(PrintStream ir, int nextId, int id){ println(ir, 6, String.format("(INSN %d tr 1 () (%d) () ())", id, nextId)); return 1; } private int genStateInsn(PrintStream ir, SchedulerBoard b, SchedulerItem item, int id){ switch(item.getOp()){ case METHOD_EXIT: // busy <= 0 println(ir, 6, String.format("(INSN %d ext_output %d () () (%d) ())", id++, 3, 2)); return 1; case METHOD_ENTRY: // req -> req_wire println(ir, 6, String.format("(INSN %d ext_input %d () () () (%d))", id++, 2, 1)); // tr into 2 when req_wire == '1' println(ir, 6, String.format("(INSN %d tr 1 () (2 3) (1) ())", id++)); // req_wire -> busy println(ir, 6, String.format("(INSN %d ext_output %d () () (%d) ())", id++, 3, 1)); ArrayList<VariableOperand> params = getMethodParams(b); for(VariableOperand v: params){ int s = ext_variables.get(v); int d = registers.get(v); println(ir, 6, String.format("(INSN %d ext_input %d () () () (%d))", id++, s, d)); } return 3 + params.size(); case RETURN: Operand o = item.getSrcOperand()[0]; println(ir, 6, String.format("(INSN %d ext_output %d () () (%d) ())", id++, 4, registers.get(o))); println(ir, 6, String.format("(INSN %d tr 1 () (1) () ())", id++)); return 2; case JP: println(ir, 6, String.format("(INSN %d tr 1 () (1) () ())", id++)); return 1; default: int r = resources.get(item); int s0 = registers.get(item.getSrcOperand()[0]); int s1 = registers.get(item.getSrcOperand()[1]); int d = registers.get(item.getDestOperand()); println(ir, 6, String.format("(INSN %d %s %d () () (%d %d) (%d))", id, convOp(item.getOp()), r, s0, s1, d)); return 1; } } private String convOp(Op o){ switch(o){ case ADD: return "add"; default: return "UNKNOWN"; } } private ArrayList<VariableOperand> getMethodParams(SchedulerBoard b){ ArrayList<VariableOperand> r = new ArrayList<>(); for(Operand v: b.getVarList()){ if(v instanceof VariableOperand){ VariableOperand vo = ((VariableOperand)v); if(!(vo.isMethodParam())) continue; // skip if(!(vo.getType() instanceof PrimitiveTypeKind)) continue; // skip r.add(vo); } } return r; } private Hashtable<Operand, Integer> registers = new Hashtable<>(); private Hashtable<VariableOperand, Integer> ext_variables = new Hashtable<>(); private Hashtable<SchedulerItem, Integer> resources = new Hashtable<>(); private void genResource(PrintStream ir, VariableOperand vo, int id){ ext_variables.put(vo, id); println(ir, 6, "(RESOURCE " + id + " ext_input"); println(ir, 6, " () ()"); println(ir, 6, " (PARAMS (INPUT " + vo.getMethodName() + "_" + vo.getOrigName() + ")"); println(ir, 6, " (WIDTH " + ((PrimitiveTypeKind)vo.getType()).getWidth() + "))"); println(ir, 6, ")"); } private void genResource(PrintStream ir, SchedulerItem item, int id){ if(item.getOp() == Op.METHOD_EXIT) return; if(item.getOp() == Op.METHOD_ENTRY) return; if(item.getOp() == Op.RETURN) return; if(item.getOp() == Op.JP) return; resources.put(item, id); println(ir, 6, "(RESOURCE " + id + " " + convOp(item.getOp())); println(ir, 6, " (UINT 32 UINT 32) (UINT 32)"); println(ir, 6, " (PARAMS)"); println(ir, 6, ")"); } private void genResources(PrintStream ir, SchedulerBoard b){ int resource_id = 1; println(ir, 4, "(RESOURCES"); // basic state transition println(ir, 6, "(RESOURCE " + (resource_id++) + " tr"); println(ir, 6, " () ()"); println(ir, 6, " (PARAMS)"); println(ir, 6, ")"); // method request println(ir, 6, "(RESOURCE " + (resource_id++) + " ext_input"); println(ir, 6, " () ()"); println(ir, 6, " (PARAMS (INPUT " + b.getName() + "_req" + ")"); println(ir, 6, " (WIDTH " + 0 + "))"); println(ir, 6, ")"); // method busy println(ir, 6, "(RESOURCE " + (resource_id++) + " ext_output"); println(ir, 6, " () ()"); println(ir, 6, " (PARAMS (OUTPUT " + b.getName() + "_busy" + ")"); println(ir, 6, " (WIDTH " + 0 + "))"); println(ir, 6, ")"); // method return if(b.getReturnType() instanceof PrimitiveTypeKind){ println(ir, 6, "(RESOURCE " + (resource_id++) + " ext_output"); println(ir, 6, " () ()"); println(ir, 6, " (PARAMS (OUTPUT " + b.getName() + "_return" + ")"); println(ir, 6, " (WIDTH " + ((PrimitiveTypeKind)b.getReturnType()).getWidth() + "))"); println(ir, 6, ")"); } // method parameters ArrayList<VariableOperand> params = getMethodParams(b); for(VariableOperand v: params){ genResource(ir, v, resource_id++); } // required operations for this method for(SchedulerSlot s: b.getSlots()){ for(SchedulerItem i: s.getItems()){ genResource(ir, i, resource_id++); } } println(ir, 4, ")"); } private void genRegisters(PrintStream ir, SchedulerBoard b){ Operand[] vars = b.getVarList().toArray(new Operand[]{}); int register_id = 1; println(ir, 4, "(REGISTERS "); // method request internal wire println(ir, 6, "(REGISTER " + (register_id++) + " " + b.getName() + "_req_wire"); println(ir, 6, " WIRE UINT 0 ()"); println(ir, 6, ")"); // method request internal wire println(ir, 6, "(REGISTER " + (register_id++) + " SJR_CONST_ZERO"); println(ir, 6, " CONST UINT 0 0"); println(ir, 6, ")"); for(Operand v: vars){ if(!(v instanceof VariableOperand)) continue; // skip VariableOperand vo = (VariableOperand)v; genRegister(ir, v, register_id++); } println(ir, 4, ")"); } private void genRegister(PrintStream ir, Operand v, int id){ if(!(v.getType() instanceof PrimitiveTypeKind)) return; registers.put(v, id); println(ir, 6, "(REGISTER " + id + " " + v.getName()); println(ir, 6, " REG INT " + ((PrimitiveTypeKind)v.getType()).getWidth() + " ()"); println(ir, 6, ")"); } }