package synthesijer.scheduler;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Optional;
import synthesijer.CompileState;
import synthesijer.IdentifierGenerator;
import synthesijer.Manager;
import synthesijer.Manager.SynthesijerModuleInfo;
import synthesijer.Options;
import synthesijer.SynthesijerUtils;
import synthesijer.ast.Type;
import synthesijer.ast.type.ArrayRef;
import synthesijer.ast.type.ArrayType;
import synthesijer.ast.type.BitVector;
import synthesijer.ast.type.ChannelType;
import synthesijer.ast.type.ComponentRef;
import synthesijer.ast.type.ComponentType;
import synthesijer.ast.type.MultipleType;
import synthesijer.ast.type.MySelfType;
import synthesijer.ast.type.PrimitiveTypeKind;
import synthesijer.hdl.HDLExpr;
import synthesijer.hdl.HDLInstance;
import synthesijer.hdl.HDLInstanceRef;
import synthesijer.hdl.HDLModule;
import synthesijer.hdl.HDLOp;
import synthesijer.hdl.HDLPort;
import synthesijer.hdl.HDLPrimitiveType;
import synthesijer.hdl.HDLSequencer;
import synthesijer.hdl.HDLSignal;
import synthesijer.hdl.HDLSignalBinding;
import synthesijer.hdl.HDLType;
import synthesijer.hdl.HDLUtils;
import synthesijer.hdl.HDLVariable;
import synthesijer.hdl.expr.HDLPreDefinedConstant;
import synthesijer.hdl.expr.HDLValue;
import synthesijer.hdl.sequencer.SequencerState;
import synthesijer.lib.FCOMP32;
import synthesijer.lib.FCOMP64;
public class SchedulerInfoCompiler {
private SchedulerInfo info;
private HDLModule hm;
public SchedulerInfoCompiler(SchedulerInfo info, HDLModule hm){
this.info = info;
this.hm = hm;
}
public void compile(){
System.out.println("Compile: " + info.getName());
genDeclarations();
genStatemachines();
}
private Hashtable<String, HDLVariable> varTable = new Hashtable<>();
private void genDeclarations(){
//for(ArrayList<VariableOperand> t: info.getVarTableList()){
for(ArrayList<Operand> t: info.getVarTableList()){
//for(VariableOperand v: t){
for(Operand v: t){
if(!(v instanceof VariableOperand)) continue;
Optional<HDLVariable> var = Optional.ofNullable(genHDLVariable((VariableOperand)v));
var.ifPresent(x -> varTable.put(v.getName(), x));
}
}
}
private SynthesijerModuleInfo searchArrayModuleInfo(PrimitiveTypeKind t, boolean publicFlag){
SynthesijerModuleInfo info = null;
if(publicFlag){
switch(t){
case BOOLEAN: info = Manager.INSTANCE.searchHDLModuleInfo("BlockRAM1"); break;
case BYTE: info = Manager.INSTANCE.searchHDLModuleInfo("BlockRAM8"); break;
case SHORT: info = Manager.INSTANCE.searchHDLModuleInfo("BlockRAM16"); break;
case INT: info = Manager.INSTANCE.searchHDLModuleInfo("BlockRAM32"); break;
case LONG: info = Manager.INSTANCE.searchHDLModuleInfo("BlockRAM64"); break;
case FLOAT: info = Manager.INSTANCE.searchHDLModuleInfo("BlockRAM32"); break;
case DOUBLE: info = Manager.INSTANCE.searchHDLModuleInfo("BlockRAM64"); break;
default: throw new RuntimeException("unsupported type: " + t);
}
}else{
switch(t){
case BOOLEAN: info = Manager.INSTANCE.searchHDLModuleInfo("SimpleBlockRAM1"); break;
case BYTE: info = Manager.INSTANCE.searchHDLModuleInfo("SimpleBlockRAM8"); break;
case SHORT: info = Manager.INSTANCE.searchHDLModuleInfo("SimpleBlockRAM16"); break;
case INT: info = Manager.INSTANCE.searchHDLModuleInfo("SimpleBlockRAM32"); break;
case LONG: info = Manager.INSTANCE.searchHDLModuleInfo("SimpleBlockRAM64"); break;
case FLOAT: info = Manager.INSTANCE.searchHDLModuleInfo("SimpleBlockRAM32"); break;
case DOUBLE: info = Manager.INSTANCE.searchHDLModuleInfo("SimpleBlockRAM64"); break;
default: throw new RuntimeException("unsupported type: " + t);
}
}
return info;
}
private SynthesijerModuleInfo searchChannelModuleInfo(PrimitiveTypeKind t, boolean publicFlag){
SynthesijerModuleInfo info = null;
if(publicFlag){
switch(t){
case BOOLEAN: info = Manager.INSTANCE.searchHDLModuleInfo("FIFO1"); break;
case BYTE: info = Manager.INSTANCE.searchHDLModuleInfo("FIFO8"); break;
case SHORT: info = Manager.INSTANCE.searchHDLModuleInfo("FIFO16"); break;
case INT: info = Manager.INSTANCE.searchHDLModuleInfo("FIFO32"); break;
case LONG: info = Manager.INSTANCE.searchHDLModuleInfo("FIFO64"); break;
case FLOAT: info = Manager.INSTANCE.searchHDLModuleInfo("FIFO32"); break;
case DOUBLE: info = Manager.INSTANCE.searchHDLModuleInfo("FIFO64"); break;
default: throw new RuntimeException("unsupported type: " + t);
}
}else{
switch(t){
case BOOLEAN: info = Manager.INSTANCE.searchHDLModuleInfo("FIFO1"); break;
case BYTE: info = Manager.INSTANCE.searchHDLModuleInfo("FIFO8"); break;
case SHORT: info = Manager.INSTANCE.searchHDLModuleInfo("FIFO16"); break;
case INT: info = Manager.INSTANCE.searchHDLModuleInfo("FIFO32"); break;
case LONG: info = Manager.INSTANCE.searchHDLModuleInfo("FIFO64"); break;
case FLOAT: info = Manager.INSTANCE.searchHDLModuleInfo("FIFO32"); break;
case DOUBLE: info = Manager.INSTANCE.searchHDLModuleInfo("FIFO64"); break;
default: throw new RuntimeException("unsupported type: " + t);
}
}
return info;
}
private HDLInstance genArrayInstance(String name, ArrayType t, boolean publicFlag){
SynthesijerModuleInfo info = null;
Type t0 = t.getElemType();
if(t0 instanceof PrimitiveTypeKind == false){
throw new RuntimeException("unsupported type: " + t);
}
info = searchArrayModuleInfo((PrimitiveTypeKind)t0, publicFlag);
HDLInstance inst = hm.newModuleInstance(info.getHDLModule(), name);
inst.getSignalForPort("clk").setAssign(null, hm.getSysClk().getSignal());
inst.getSignalForPort("reset").setAssign(null, hm.getSysReset().getSignal());
return inst;
}
private HDLInstanceRef genArrayInstanceRef(String name, ArrayType t, boolean publicFlag){
SynthesijerModuleInfo info = null;
Type t0 = t.getElemType();
if(t0 instanceof PrimitiveTypeKind == false){
throw new RuntimeException("unsupported type: " + t);
}
info = searchArrayModuleInfo((PrimitiveTypeKind)t0, publicFlag);
HDLInstanceRef ref = new HDLInstanceRef(hm, info.getHDLModule(), name);
return ref;
}
private HDLInstance genChannelInstance(String name, ChannelType t, boolean publicFlag){
//System.out.println("genChannelInstance");
SynthesijerModuleInfo info = null;
Type t0 = t.getElemType();
if(t0 instanceof PrimitiveTypeKind == false){
throw new RuntimeException("unsupported type: " + t);
}
info = searchChannelModuleInfo((PrimitiveTypeKind)t0, publicFlag);
//System.out.println(info.getHDLModule().getName());
HDLInstance inst = hm.newModuleInstance(info.getHDLModule(), name);
inst.getSignalForPort("clk").setAssign(null, hm.getSysClk().getSignal());
inst.getSignalForPort("reset").setAssign(null, hm.getSysReset().getSignal());
return inst;
}
private HDLInstanceRef genChannelInstanceRef(String name, ChannelType t, boolean publicFlag){
SynthesijerModuleInfo info = null;
Type t0 = t.getElemType();
if(t0 instanceof PrimitiveTypeKind == false){
throw new RuntimeException("unsupported type: " + t);
}
info = searchChannelModuleInfo((PrimitiveTypeKind)t0, publicFlag);
HDLInstanceRef ref = new HDLInstanceRef(hm, info.getHDLModule(), name);
return ref;
}
private class Pair{
public final VariableOperand orig; // the VariableOperand in given source
public final HDLSignal reg; // the actual signal for the method.
public final HDLPort port; // port from outside
public final HDLSignal local; // signal for local invocation
public Pair(VariableOperand v, HDLSignal reg, HDLPort port, HDLSignal local){
this.orig = v;
this.reg = reg;
this.port = port;
this.local = local;
}
}
private Hashtable<String, ArrayList<Pair>> paramListMap = new Hashtable<>();
private ArrayList<Pair> getMethodParamPairList(String methodName){
ArrayList<Pair> list;
if(paramListMap.containsKey(methodName) == false){
list = new ArrayList<>();
paramListMap.put(methodName, list);
}else{
list = paramListMap.get(methodName);
}
return list;
}
private HDLExpr convConstantToHDLExpr(ConstantOperand c){
HDLPrimitiveType type = (HDLPrimitiveType)getHDLType(c.getType());
//HDLSignal tmp = hm.newSignal(String.format("constant_%04d", constIdGen.id()), type);
//tmp.setAssign(null, new HDLValue(c.getValue(), type));
return new HDLValue(c.getValue(), type);
}
private HDLVariable genHDLVariable(VariableOperand v, PrimitiveTypeKind type){
String name = v.getName();
if(type == PrimitiveTypeKind.DECLARED){
//SynthesijerUtils.warn("Declaration is skipped: " + name + "::" + type);
return null;
}
if(type == PrimitiveTypeKind.VOID) return null; // Void variable is not synthesized.
HDLSignal sig = hm.newSignal(name, getHDLType(type));
if(v.isDebug()) sig.setDebugFlag(true);
// if(v.getInitExpr() != null && v.getInitExpr().isConstant()){
if(v.getInitSrc() != null){
if(v.getInitSrc() instanceof ConstantOperand){
HDLExpr e = convConstantToHDLExpr((ConstantOperand)(v.getInitSrc()));
if(e == null){
SynthesijerUtils.warn("initial value is not allowed:" + v.getInitSrc());
}else{
sig.setResetValue(e);
}
/*
}else if(v.getInitSrc() instanceof VariableOperand){
VariableOperand o = (VariableOperand)(v.getInitSrc());
if(varTable.containsKey(o.getName())){
HDLExpr e = varTable.get(o.getName());
sig.setResetValue(e);
}else{
if(v.isMember()){
SynthesijerUtils.warn(v.getInitSrc().info() + " is not defiend at previous using by "+ v.getName());
}
}
// if(v.isMember()){
// SynthesijerUtils.warn("only litral for initial value of member is allowed: " + v.getName() + ":" + v.getInitSrc().info());
// }
*/
}
}
if(v.isMethodParam()){
String prefix = v.getMethodName();
String n = prefix + "_" + v.getOrigName();
HDLSignal local = hm.newSignal(n + "_local", getHDLType(type));
if(v.isPrivateMethod()){
getMethodParamPairList(prefix).add(new Pair(v, sig, null, local));
}else{
HDLPort port = hm.newPort(n, HDLPort.DIR.IN, getHDLType(type));
getMethodParamPairList(prefix).add(new Pair(v, sig, port, local));
}
}else if(v.isPublic() && (!v.isGlobalConstant())){
String n = v.getOrigName();
HDLPort din = hm.newPort(n + "_in", HDLPort.DIR.IN, getHDLType(type));
HDLPort we = hm.newPort(n + "_we", HDLPort.DIR.IN, HDLPrimitiveType.genBitType());
HDLPort dout = hm.newPort(n + "_out", HDLPort.DIR.OUT, getHDLType(type));
dout.getSignal().setAssign(null, sig);
// always(clk'posedge) sig <= din when we = '1' else sig
HDLSignal mux = hm.newSignal(name + "_mux", getHDLType(type), HDLSignal.ResourceKind.WIRE);
mux.setAssign(null, hm.newExpr(HDLOp.IF, we.getSignal(), din.getSignal(), sig));
sig.setDefaultValue(mux);
}
return sig;
}
private HDLVariable genHDLVariable(VariableOperand v, ArrayType t){
String name = v.getName();
Operand initSrc = v.getInitSrc();
HDLVariable ret = null;
if(initSrc != null && initSrc instanceof ArrayRefOperand){
HDLInstance array = genArrayInstance(name, t, v.isPublic());
ArrayRefOperand o = (ArrayRefOperand)initSrc;
array.getParameterPair("WORDS").setValue(new HDLValue(o.words));
int depth = o.depth;
array.getParameterPair("DEPTH").setValue(new HDLValue(depth));
if(v.isPublic() && (!v.isGlobalConstant())){
String n = v.getOrigName();
HDLPort addr = hm.newPort(n + "_address", HDLPort.DIR.IN, array.getSignalForPort("address").getType());
HDLPort we = hm.newPort(n + "_we", HDLPort.DIR.IN, array.getSignalForPort("we").getType());
HDLPort oe = hm.newPort(n + "_oe", HDLPort.DIR.IN, array.getSignalForPort("oe").getType());
HDLPort din = hm.newPort(n + "_din", HDLPort.DIR.IN, array.getSignalForPort("din").getType());
HDLPort dout = hm.newPort(n + "_dout", HDLPort.DIR.OUT, array.getSignalForPort("dout").getType());
HDLPort length = hm.newPort(n + "_length", HDLPort.DIR.OUT, array.getSignalForPort("length").getType());
array.getSignalForPort("address").setAssign(null, addr.getSignal());
array.getSignalForPort("we").setAssign(null, we.getSignal());
array.getSignalForPort("oe").setAssign(null, oe.getSignal());
array.getSignalForPort("din").setAssign(null, din.getSignal());
dout.getSignal().setAssign(null, array.getSignalForPort("dout"));
length.getSignal().setAssign(null, array.getSignalForPort("length"));
//System.out.println("len:" + length.getName());
}
ret = array;
}else if(v.isMethodParam()){
String prefix = v.getMethodName();
String n = prefix + "_" + v.getOrigName();
HDLType ht = getHDLType(t.getElemType());
HDLInstanceRef ref = genArrayInstanceRef(n, t, v.isPublic());
ret = ref;
}else{
if(initSrc != null){
//SynthesijerUtils.warn("unsupported to init array with un-immediate number:" + initSrc.info());
}else{
SynthesijerUtils.warn("unsupported to array initializing expression: " + v.toSexp());
}
SynthesijerUtils.warn("the size of memory is set as default parameter(DEPTH=1024)");
}
return ret;
}
private HDLVariable genHDLVariable(VariableOperand v, ChannelType t){
String name = v.getName();
Operand initSrc = v.getInitSrc();
HDLVariable ret = null;
// if(initSrc != null && initSrc instanceof ArrayRefOperand){
if(v.isMethodParam() == false){
HDLInstance array = genChannelInstance(name, t, v.isPublic());
//ArrayRefOperand o = (ArrayRefOperand)initSrc;
//array.getParameterPair("WORDS").setValue(new HDLValue(o.words));
//int depth = o.depth;
//array.getParameterPair("DEPTH").setValue(new HDLValue(depth));
if(v.isPublic() && (!v.isGlobalConstant())){
String n = v.getOrigName();
HDLPort addr = hm.newPort(n + "_address", HDLPort.DIR.IN, array.getSignalForPort("address").getType());
HDLPort we = hm.newPort(n + "_we", HDLPort.DIR.IN, array.getSignalForPort("we").getType());
HDLPort oe = hm.newPort(n + "_oe", HDLPort.DIR.IN, array.getSignalForPort("oe").getType());
HDLPort din = hm.newPort(n + "_din", HDLPort.DIR.IN, array.getSignalForPort("din").getType());
HDLPort dout = hm.newPort(n + "_dout", HDLPort.DIR.OUT, array.getSignalForPort("dout").getType());
HDLPort length = hm.newPort(n + "_length", HDLPort.DIR.OUT, array.getSignalForPort("length").getType());
array.getSignalForPort("address").setAssign(null, addr.getSignal());
array.getSignalForPort("we").setAssign(null, we.getSignal());
array.getSignalForPort("oe").setAssign(null, oe.getSignal());
array.getSignalForPort("din").setAssign(null, din.getSignal());
dout.getSignal().setAssign(null, array.getSignalForPort("dout"));
length.getSignal().setAssign(null, array.getSignalForPort("length"));
//System.out.println("len:" + length.getName());
}
ret = array;
}else if(v.isMethodParam()){
String prefix = v.getMethodName();
String n = prefix + "_" + v.getOrigName();
HDLType ht = getHDLType(t.getElemType());
HDLInstanceRef ref = genChannelInstanceRef(n, t, v.isPublic());
ret = ref;
}else{
if(initSrc != null){
//SynthesijerUtils.warn("unsupported to init array with un-immediate number:" + initSrc.info());
}else{
SynthesijerUtils.warn("unsupported to chann initializing expression: " + v.toSexp());
}
SynthesijerUtils.warn("the size of memory is set as default parameter(DEPTH=1024)");
}
return ret;
}
private HDLVariable genHDLVariable(VariableOperand v, ComponentType t){
String name = v.getName();
//NewClassExpr expr = (NewClassExpr)v.getInitExpr();
Operand initSrc = v.getInitSrc();
//String instName = c.getName();
if(initSrc == null || !(initSrc instanceof InstanceRefOperand)){
SynthesijerUtils.warn("unsupported to init component without InstanceRefOperand:" + initSrc.info());
return null;
}
// String instName = expr.getClassName();
String instName = ((InstanceRefOperand)initSrc).className;
Manager.SynthesijerModuleInfo info = Manager.INSTANCE.searchHDLModuleInfo(instName);
if(info == null){
SynthesijerUtils.error(instName + " is not found.");
Manager.INSTANCE.HDLModuleInfoList();
System.exit(0);
}
if(info.getCompileState().isBefore(CompileState.GENERATE_HDL)){
SynthesijerUtils.info("enters into >>>");
Manager.INSTANCE.compileSchedulerInfo(instName);
SynthesijerUtils.info("<<< return to compiling " + this.info.getName());
}
//System.out.println(v.getName());
//System.out.println(v.getOrigName());
HDLInstance inst = hm.newModuleInstance(info.getHDLModule(), name, v.getOrigName());
if(v.getInitSrc() != null){
Operand src = v.getInitSrc();
if(src instanceof InstanceRefOperand){
InstanceRefOperand o = (InstanceRefOperand)src;
for(InstanceRefOperand.ParamPair p: o.getParameters()){
String key = p.key;
String value = p.value;
if(inst.getParameterPair(key) != null){
inst.getParameterPair(key).setValue(new HDLValue(Integer.parseInt(value))); // ad-hoc, only to treat integer value paramters
}else{
SynthesijerUtils.warn(key + " is not defined in " + inst.getSubModule().getName());
SynthesijerUtils.warn("parameter " + key + " -> " + value + " is not used.");
}
}
}else{
SynthesijerUtils.warn("can use only InstanceRefOperand for source operand of instance variable");
}
}
Hashtable<HDLSignalBinding, HDLSignalBinding> exportBindingMap = new Hashtable<>();
for(HDLPort p: inst.getSubModule().getPorts()){
if(p.isSet(HDLPort.OPTION.EXPORT)){
String n = inst.getSignalForPort(p.getName()).getName();
//String n = p.getName();
if(p.isSet(HDLPort.OPTION.EXPORT_PATH) == false || Options.INSTANCE.legacy_instance_variable_name){
n += "_exp";
}
HDLPort export = hm.newPort(n, p.getDir(), p.getType(), EnumSet.of(HDLPort.OPTION.EXPORT, HDLPort.OPTION.EXPORT_PATH));
hm.rmSignal(inst.getSignalForPort(p.getName()));
inst.rmPortPair(inst.getPortPair(p));
inst.addPortPair(export, p);
/*
if(p.getDir() == HDLPort.DIR.INOUT || p.isSet(HDLPort.OPTION.NO_SIG)){
hm.rmSignal(inst.getSignalForPort(p.getName()));
inst.rmPortPair(inst.getPortPair(p));
inst.addPortPair(export, p);
}else if(p.getDir() == HDLPort.DIR.OUT){
export.getSignal().setAssign(null, inst.getSignalForPort(p.getName()));
}else{
inst.getSignalForPort(p.getName()).setAssign(null, export.getSignal());
}
*/
if(p.isBinded()){
HDLSignalBinding b = p.getSignalBinding();
HDLSignalBinding e = null;
if(exportBindingMap.containsKey(b) == false){
// only first time for this binding
e = b.export(inst.getName());
exportBindingMap.put(b, e);
}else{
e = exportBindingMap.get(b);
}
e.set(export, b.get(p));
}
}
}
inst.getSignalForPort(inst.getSubModule().getSysClkName()).setAssign(null, hm.getSysClk().getSignal());
inst.getSignalForPort(inst.getSubModule().getSysResetName()).setAssign(null, hm.getSysReset().getSignal());
return inst;
}
private HDLVariable genHDLVariable(VariableOperand v){
Type type = v.getType();
if(type instanceof PrimitiveTypeKind){
return genHDLVariable(v, (PrimitiveTypeKind)type);
}else if(type instanceof ArrayType){
return genHDLVariable(v, (ArrayType)type);
}else if(type instanceof ComponentType){
return genHDLVariable(v, (ComponentType)type);
}else if(type instanceof ArrayRef){
String name = v.getName();
Type t = ((ArrayRef) type).getRefType().getElemType();
HDLSignal sig = hm.newSignal(name, getHDLType(t));
return sig;
}else if(type instanceof ComponentRef){
String name = v.getName();
ComponentRef cr = (ComponentRef)type;
HDLSignal sig = null;
if(cr.getRefType() instanceof PrimitiveTypeKind){
sig = hm.newSignal(name, getHDLType(cr.getRefType()));
}else if(cr.getRefType() instanceof ArrayType){
Type t = ((ArrayType) cr.getRefType()).getElemType();
sig = hm.newSignal(name, getHDLType(t));
}else{
System.out.println("unknown ref type: " + name + ":" + cr.getRefType());
}
return sig;
}else if(type instanceof BitVector){
String name = v.getName();
HDLSignal sig = hm.newSignal(name, HDLPrimitiveType.genVectorType(((BitVector) type).getWidth()));
return sig;
}else if(type instanceof ChannelType){
return genHDLVariable(v, (ChannelType)type);
}else{
String name = v.getName();
throw new RuntimeException("unsupported type: " + type + " of " + name);
}
}
private HDLType getHDLType(Type type){
if(type instanceof PrimitiveTypeKind){
return getHDLType((PrimitiveTypeKind)type);
}else if(type instanceof ArrayType){
return getHDLType((ArrayType)type);
}else if(type instanceof ComponentType){
return getHDLType((ComponentType)type);
}else if(type instanceof MySelfType){
return getHDLType((MySelfType)type);
}else if(type instanceof MultipleType){
return getHDLType((MultipleType)type);
}else if(type instanceof ChannelType){
return getHDLType((ChannelType)type);
}else{
return null;
}
}
private HDLPrimitiveType getHDLType(PrimitiveTypeKind t){
switch(t){
case BOOLEAN: return HDLPrimitiveType.genBitType();
case BYTE: return HDLPrimitiveType.genSignedType(8);
case CHAR: return HDLPrimitiveType.genVectorType(16);
case SHORT: return HDLPrimitiveType.genSignedType(16);
case INT: return HDLPrimitiveType.genSignedType(32);
case LONG: return HDLPrimitiveType.genSignedType(64);
case FLOAT: return HDLPrimitiveType.genVectorType(32);
case DOUBLE: return HDLPrimitiveType.genVectorType(64);
default: return null; // return HDLPrimitiveType.genUnknowType();
}
}
private HDLPrimitiveType getHDLType(MySelfType t){
//System.err.println("unsupported type: " + t);
return null;
}
private HDLPrimitiveType getHDLType(ComponentType t){
System.err.println("unsupported type: " + t.getName() + "::ComponentType");
return null;
}
private HDLPrimitiveType getHDLType(ArrayType t){
System.err.println("unsupported type: " + t);
return null;
}
private HDLType getHDLType(MultipleType t){
return getHDLType(t.get(0));
}
private HDLPrimitiveType getHDLType(ChannelType t){
System.err.println("unsupported type: " + t);
return null;
}
private Hashtable<SchedulerItem, HDLExpr> predExprMap;
private void genStatemachines(){
Hashtable<SchedulerBoard, Hashtable<HDLVariable, HDLInstance>> callStackMaps = new Hashtable<>();
for(SchedulerBoard board: info.getBoardsList()){
Hashtable<HDLVariable, HDLInstance> callStackMap = new Hashtable<>();
callStackMaps.put(board, callStackMap);
genMethodCtrlSignals(board, callStackMap);
}
for(SchedulerBoard board: info.getBoardsList()){
predExprMap = new Hashtable<>();
HardwareResource resource = new HardwareResource();
Hashtable<Integer, SequencerState> returnTable = new Hashtable<>();
Hashtable<HDLVariable, HDLInstance> callStackMap = callStackMaps.get(board);
Hashtable<Integer, SequencerState> states = genStatemachine(board, resource, returnTable, callStackMap);
genExprs(board, states, resource, returnTable);
}
}
class HardwareResource{
private HDLInstance mul32 = null;
private HDLInstance mul64 = null;
private HDLInstance div32 = null;
private HDLInstance div64 = null;
private HDLInstance fadd32 = null;
private HDLInstance fsub32 = null;
private HDLInstance fmul32 = null;
private HDLInstance fdiv32 = null;
private HDLInstance fadd64 = null;
private HDLInstance fsub64 = null;
private HDLInstance fmul64 = null;
private HDLInstance fdiv64 = null;
private HDLInstance f2i = null;
private HDLInstance i2f = null;
private HDLInstance d2l = null;
private HDLInstance l2d = null;
private HDLInstance f2d = null;
private HDLInstance d2f = null;
private HDLInstance lshift32 = null;
private HDLInstance logic_rshift32 = null;
private HDLInstance arith_rshift32 = null;
private HDLInstance lshift64 = null;
private HDLInstance logic_rshift64 = null;
private HDLInstance arith_rshift64 = null;
private HDLInstance fcomp32 = null;
private HDLInstance fcomp64 = null;
}
private IdentifierGenerator constIdGen = new IdentifierGenerator();
private HDLExpr convOperandToHDLExpr(SchedulerItem item, Operand o){
HDLExpr ret;
if(o instanceof VariableOperand){
if(o.isChaining(item)){
SchedulerItem pred = ((VariableOperand)o).getPredItem(item);
if(predExprMap.containsKey(pred)){
//ret = predExprMap.get(pred);
ret = predExprMap.get(pred).getResultExpr();
}else{
SynthesijerUtils.warn("detected chaining, but chained expression is not found.");
ret = varTable.get(((VariableOperand)o).getName());
}
}else{
ret = varTable.get(((VariableOperand)o).getName());
}
}else{ // instanceof ConstantOperand
ConstantOperand c = (ConstantOperand)o;
HDLPrimitiveType type = (HDLPrimitiveType)getHDLType(c.getType());
//HDLSignal tmp = hm.newSignal(String.format("constant_%04d", constIdGen.id()), type);
//tmp.setAssign(null, new HDLValue(c.getValue(), type));
ret = new HDLValue(c.getValue(), type);
}
return ret;
}
private void genExprs(SchedulerBoard board, Hashtable<Integer, SequencerState> states, HardwareResource resource, Hashtable<Integer, SequencerState> returnTable){
HDLSignal return_sig = null;
return_sig = returnSigTable.get(board);
Hashtable<String, FieldAccessItem> fieldAccessChainMap = new Hashtable<>();
for(SchedulerSlot slot: board.getSlots()){
int id = slot.getStepId();
for(SchedulerItem item: slot.getItems()){
genExpr(board, resource, item, states.get(id), return_sig, paramListMap.get(board.getName()), fieldAccessChainMap, predExprMap, returnTable);
}
}
}
private HDLOp convOp2HDLOp(Op op){
HDLOp ret = HDLOp.UNDEFINED;
switch(op){
case METHOD_ENTRY : break;
case METHOD_EXIT : break;
case ASSIGN : break;
case NOP : break;
case ADD : ret = HDLOp.ADD;break;
case SUB : ret = HDLOp.SUB;break;
case MUL32 : break; //ret = HDLOp.MUL;break;
case MUL64 : break; // ret = HDLOp.MUL;break;
case DIV32 : break;
case DIV64 : break;
case MOD32 : break;
case MOD64 : break;
case LT : ret = HDLOp.LT;break;
case LEQ : ret = HDLOp.LEQ;break;
case GT : ret = HDLOp.GT;break;
case GEQ : ret = HDLOp.GEQ;break;
case COMPEQ : ret = HDLOp.EQ;break;
case NEQ : ret = HDLOp.NEQ;break;
case SIMPLE_LSHIFT32 : ret = HDLOp.LSHIFT32;break;
case SIMPLE_LOGIC_RSHIFT32 : ret = HDLOp.LOGIC_RSHIFT32;break;
case SIMPLE_ARITH_RSHIFT32 : ret = HDLOp.ARITH_RSHIFT32;break;
case SIMPLE_LSHIFT64 : ret = HDLOp.LSHIFT64;break;
case SIMPLE_LOGIC_RSHIFT64 : ret = HDLOp.LOGIC_RSHIFT64;break;
case SIMPLE_ARITH_RSHIFT64 : ret = HDLOp.ARITH_RSHIFT64;break;
case LSHIFT32 : break;
case LOGIC_RSHIFT32 : break;
case ARITH_RSHIFT32 : break;
case LSHIFT64 : break;
case LOGIC_RSHIFT64 : break;
case ARITH_RSHIFT64 : break;
case JP : break;
case JT : break;
case RETURN : break;
case SELECT : break;
case AND : ret = HDLOp.AND;break;
case NOT : ret = HDLOp.NOT;break;
case MSB_FLAP : ret = HDLOp.MSB_FLAP;break;
case LAND : ret = HDLOp.AND;break;
case LOR : ret = HDLOp.OR;break;
case OR : ret = HDLOp.OR;break;
case XOR : ret = HDLOp.XOR;break;
case LNOT : ret = HDLOp.NOT;break;
case ARRAY_ACCESS : break;
case ARRAY_ACCESS_WAIT : break;
case ARRAY_ACCESS0 : break;
case ARRAY_INDEX : break;
case FIFO_WRITE : break;
case CALL : break;
case EXT_CALL : break;
case FIELD_ACCESS : break;
case BREAK : break;
case CONTINUE : break;
case CAST : break;
case UNDEFINED : break;
default:
}
return ret;
}
private int getBitWidth(Type t){
if(t instanceof PrimitiveTypeKind){
return ((PrimitiveTypeKind) t).getWidth();
}else if(t instanceof BitVector){
return ((BitVector) t).getWidth();
}else if(t instanceof ArrayRef){
return getBitWidth(((ArrayRef) t).getRefType());
}else if(t instanceof ArrayType){
return getBitWidth(((ArrayType) t).getElemType());
}else{
System.out.println(t);
return -1;
}
}
private void genExpr(SchedulerBoard board, HardwareResource resource, SchedulerItem item, SequencerState state, HDLSignal return_sig, ArrayList<Pair> paramList, Hashtable<String, FieldAccessItem> fieldAccessChainMap, Hashtable<SchedulerItem, HDLExpr> predExprMap, Hashtable<Integer, SequencerState> returnTable){
switch(item.getOp()){
case METHOD_ENTRY:{
if(paramList != null){
for(Pair pair: paramList){
// MUX to select valid siganl from inside/outside arguments
HDLExpr arg;
if(board.isPrivate() == false){
arg = hm.newExpr(HDLOp.IF, varTable.get(board.getName()+"_req"), pair.port.getSignal(), pair.local);
}else{
arg = pair.local;
}
pair.reg.setAssign(state, arg);
}
}
break;
}
case METHOD_EXIT:{
break;
}
case ASSIGN : {
Operand[] src = item.getSrcOperand();
VariableOperand dest = item.getDestOperand();
if(dest.getType() instanceof PrimitiveTypeKind || dest.getType() instanceof BitVector){
HDLVariable d;
FieldAccessItem fa = fieldAccessChainMap.get(dest.getName());
if(fa != null){
// should write into field variable pointed by FIELD_ACCESS
HDLInstance obj = (HDLInstance)(varTable.get(fa.obj.getName()));
d = obj.getSignalForPort(fa.name);
if(d != null){
// for unsynthesized HDLModule
}else{
d = obj.getSignalForPort(fa.name + "_in");
HDLSignal we = obj.getSignalForPort(fa.name + "_we");
if(we != null){
we.setAssign(state, HDLPreDefinedConstant.HIGH); // in this state
we.setDefaultValue(HDLPreDefinedConstant.LOW); // otherwise
}
}
}else{
d = (HDLVariable)(convOperandToHDLExpr(item, dest));
}
if(d != null){
HDLExpr expr = convOperandToHDLExpr(item, src[0]);
d.setAssign(state, expr);
predExprMap.put(item, expr);
}
}else if(dest.getType() instanceof ArrayRef){
VariableRefOperand d = (VariableRefOperand)dest;
VariableOperand ref = d.getRef();
HDLSignal we = null, din = null, addr = null;
HDLVariable var = varTable.get(ref.getName());
if(var instanceof HDLInstance){
// local memory
HDLInstance array = (HDLInstance)var;
//we = array.getSignalForPort("we_b");
//din = array.getSignalForPort("din_b");
we = hm.getSignal(array.getName() + "_we_b");
din = hm.getSignal(array.getName() + "_din_b");
addr = hm.getSignal(array.getName() + "_address_b");
}else if(var instanceof HDLInstanceRef){
HDLInstanceRef array = (HDLInstanceRef)var;
we = array.getPortByPostfix("_we_b").get().getSignal();
din = array.getPortByPostfix("_din_b").get().getSignal();
addr = array.getPortByPostfix("_address_b").get().getSignal();
}else{
// external memory (through Field Access)
FieldAccessItem fa = fieldAccessChainMap.get(ref.getName());
HDLInstance obj = (HDLInstance)(varTable.get(fa.obj.getName()));
we = obj.getSignalForPort(fa.name + "_we");
din = obj.getSignalForPort(fa.name + "_din");
addr = obj.getSignalForPort(fa.name + "_address_b");
}
we.setAssign(state, HDLPreDefinedConstant.HIGH);
we.setDefaultValue(HDLPreDefinedConstant.LOW);
HDLExpr expr = convOperandToHDLExpr(item, src[0]);
din.setAssign(state, expr);
if(addr == null){
// indirect memory access. in this case, destination address is already asserted...
}else{
addr.setAssign(state, convOperandToHDLExpr(item, d.getPtr()));
}
predExprMap.put(item, expr);
}else if(dest.getType() instanceof ChannelType){
HDLInstanceRef chan = (HDLInstanceRef)convOperandToHDLExpr(item, dest);
HDLSignal we = hm.getPort(chan.getName() + "_" + "we").getSignal();
HDLSignal din = hm.getPort(chan.getName() + "_" + "din").getSignal();
HDLExpr srcExpr = (HDLExpr)convOperandToHDLExpr(item, src[0]);
we.setAssign(state, HDLPreDefinedConstant.HIGH);
we.setDefaultValue(HDLPreDefinedConstant.LOW);
din.setAssign(state, srcExpr);
//System.out.println("dout,we <= " + srcExpr.getVHDL() + ",HIGH");
}else{
SynthesijerUtils.warn("Unsupported ASSIGN: " + item.info());
}
}
case NOP :{
break;
}
case JP :{
break;
}
case JT :{
break;
}
case RETURN : {
if(return_sig == null) break;
Operand[] src = item.getSrcOperand();
return_sig.setAssign(state, convOperandToHDLExpr(item, src[0]));
break;
}
case MULTI_RETURN : {
// TODO
Operand[] src = item.getSrcOperand();
HDLSignal s = returnMultiSigTable.get(board)[Integer.parseInt(src[0].getName())];
//return_sig.setAssign(state, convOperandToHDLExpr(item, src[1]));
s.setAssign(state, convOperandToHDLExpr(item, src[1]));
break;
}
case SELECT :{
break;
}
case ARRAY_ACCESS_WAIT :{
break;
}
case ARRAY_ACCESS0:
case ARRAY_ACCESS :{
if(item.getOp() == Op.ARRAY_ACCESS){
state.setMaxConstantDelay(2);
}
HDLSignal dest = (HDLSignal)convOperandToHDLExpr(item, item.getDestOperand());
Operand src[] = item.getSrcOperand();
HDLSignal addr = null, oe = null, dout = null;
HDLVariable var = varTable.get(((VariableOperand)src[0]).getName());
if(var instanceof HDLInstance){
// local memory
HDLInstance array = (HDLInstance)var;
//addr = array.getSignalForPort("address_b");
//oe = array.getSignalForPort("oe_b");
//dout = array.getSignalForPort("dout_b");
addr = hm.getSignal(array.getName() + "_address_b");
oe = hm.getSignal(array.getName() + "_oe_b");
dout = hm.getSignal(array.getName() + "_dout_b");
}else if(var instanceof HDLInstanceRef){
HDLInstanceRef array = (HDLInstanceRef)var;
addr = array.getPortByPostfix("_address_b").get().getSignal();
oe = array.getPortByPostfix("_oe_b").get().getSignal();
dout = array.getPortByPostfix("_dout_b").get().getSignal();
}else{
// external memory (through Field Access)
FieldAccessItem fa = fieldAccessChainMap.get(((VariableOperand)src[0]).getName());
HDLInstance obj = (HDLInstance)(varTable.get(fa.obj.getName()));
addr = obj.getSignalForPort(fa.name + "_address");
oe = obj.getSignalForPort(fa.name + "_oe");
dout = obj.getSignalForPort(fa.name + "_dout");
}
HDLExpr index = convOperandToHDLExpr(item, src[1]);
if((addr != null) && (item.getOp() == Op.ARRAY_ACCESS)){
addr.setAssign(state, 0, index);
}
if(oe != null){
oe.setAssign(state, 0, HDLPreDefinedConstant.HIGH);
oe.setDefaultValue(HDLPreDefinedConstant.LOW);
}
if(dout != null){
if(item.getOp() == Op.ARRAY_ACCESS){
dest.setAssign(state, 2, dout);
}else{
dest.setAssign(state, dout);
}
predExprMap.put(item, dout);
}
break;
}
case ARRAY_INDEX :{
Operand src[] = item.getSrcOperand();
HDLSignal addr = null;
HDLVariable var = varTable.get(((VariableOperand)src[0]).getName());
if(var instanceof HDLInstance){
// local memory
HDLInstance array = (HDLInstance)var;
//addr = array.getSignalForPort("address_b");
addr = hm.getSignal(array.getName() + "_address_b");
}else if(var instanceof HDLInstanceRef){
HDLInstanceRef array = (HDLInstanceRef)var;
addr = array.getPortByPostfix("_address_b").get().getSignal();
}else{
// external memory (through Field Access)
FieldAccessItem fa = fieldAccessChainMap.get(((VariableOperand)src[0]).getName());
HDLInstance obj = (HDLInstance)(varTable.get(fa.obj.getName()));
addr = obj.getSignalForPort(fa.name + "_address");
}
HDLExpr index = convOperandToHDLExpr(item, src[1]);
addr.setAssign(state, index);
break;
}
case FIFO_WRITE :{
break;
}
case CALL :{
MethodInvokeItem item0 = (MethodInvokeItem)item;
Operand[] params = item0.getSrcOperand();
//System.out.println(item0.getSrcOperand().length);
//for(Operand param: params) System.out.println("Parameter : " + param.toString());
ArrayList<Pair> list = getMethodParamPairList(item0.name);
for(int i = 0; i < params.length; i++){
HDLSignal t = list.get(i).local;
HDLExpr s = convOperandToHDLExpr(item, params[i]);
t.setAssign(state.getTransitions().get(0).getDestState(), 0, s); // should set in ***_body
//t.setAssign(state, 0, s);
}
if(item0.getDestOperand().getType() != PrimitiveTypeKind.VOID){
HDLSignal dest = (HDLSignal)convOperandToHDLExpr(item, item0.getDestOperand());
HDLSignal ret = hm.getSignal(item0.name + "_return");
if(ret == null) ret = hm.getPort(item0.name + "_return").getSignal();
dest.setAssign(state.getTransitions().get(0).getDestState().getTransitions().get(0).getDestState(), ret); // should read in ***_wait
predExprMap.put(item, ret);
SequencerState retState = returnTable.get(item0.getStepId());
if(retState != null){
dest.setAssign(retState, ret); // should read in ***_wait
}
}
break;
}
case EXT_CALL :{
MethodInvokeItem item0 = (MethodInvokeItem)item;
HDLInstance obj = (HDLInstance)(varTable.get(item0.obj.getName()));
Operand[] params = item0.getSrcOperand();
for(int i = 0; i < item0.args.length; i++){
Type t = params[i].getType();
if(t instanceof ArrayType){
// connect array type parameter
HDLInstance target = (HDLInstance)(varTable.get((params[i]).getName()));
HDLSignal flag = hm.newTmpSignal(HDLPrimitiveType.genBitType(), HDLSignal.ResourceKind.REGISTER);
flag.setDefaultValue(HDLPreDefinedConstant.LOW);
flag.setAssign(state, HDLPreDefinedConstant.HIGH);
flag.setAssign(state.getTransitions().get(0).getDestState(), HDLPreDefinedConstant.HIGH); // ext_call body
flag.setAssign(state.getTransitions().get(0).getDestState().getTransitions().get(0).getDestState(), HDLPreDefinedConstant.HIGH); // ext_call wait
connectArrayTypeParammeter(flag, target, obj, item0.name + "_" + item0.args[i]); // connect obj into target
}else{
// for primitive parameters
HDLSignal d = obj.getSignalForPort(item0.name + "_" + item0.args[i]);
// should set in ***_body
d.setAssign(state.getTransitions().get(0).getDestState(), 0, convOperandToHDLExpr(item, params[i]));
//t.setAssign(state, 0, convOperandToHDLExpr(params[i]));
}
}
if(item0.getDestOperand().getType() != PrimitiveTypeKind.VOID){ // non-void function
HDLSignal dest = (HDLSignal)convOperandToHDLExpr(item, item0.getDestOperand());
HDLSignal ret = obj.getSignalForPort(item0.name + "_return");
dest.setAssign(state.getTransitions().get(0).getDestState().getTransitions().get(0).getDestState(), ret); // should read in ***_wait
//dest.setAssign(state, ret);
predExprMap.put(item, ret);
SequencerState retState = returnTable.get(item0.getStepId());
if(retState != null){
dest.setAssign(retState, ret); // should read in ***_wait
}
}
break;
}
case FIELD_ACCESS :{
FieldAccessItem item0 = (FieldAccessItem)item;
HDLVariable var = varTable.get(item0.obj.getName());
HDLSignal src = null;
if(var != null && var instanceof HDLInstance){
HDLInstance obj = (HDLInstance)var;
src = obj.getSignalForPort(item0.name);
if(src == null){
src = obj.getSignalForPort(item0.name + "_out"); // normal
}
}else if(var != null && var instanceof HDLInstanceRef){
src = hm.getPort(var.getName() + "_" + item0.name).getSignal();
}
HDLExpr dest = convOperandToHDLExpr(item, item0.getDestOperand());
if(dest instanceof HDLSignal && src != null){
HDLSignal d = (HDLSignal)dest;
d.setAssign(state, src);
predExprMap.put(item, src);
}else{
// just ref
}
// stored this item into map to use in following items
fieldAccessChainMap.put(item0.getDestOperand().getName(), item0);
break;
}
case BREAK :{
break;
}
case CONTINUE :{
break;
}
case CAST:{
TypeCastItem item0 = (TypeCastItem)item;
HDLSignal dest = (HDLSignal)(convOperandToHDLExpr(item, item.getDestOperand()));
HDLExpr src = convOperandToHDLExpr(item, item.getSrcOperand()[0]);
if(src instanceof HDLValue){
HDLSignal tmp = hm.newSignal(String.format("const_%04d", constIdGen.id()), (HDLPrimitiveType)src.getType());
tmp.setAssign(null, src);
src = tmp;
}
int w0 = getBitWidth(item0.orig);
int w1 = getBitWidth(item0.target);
if(w0 < 0 || w1 < 0){
SynthesijerUtils.error("Unsupported CAST: " + item.info());
}
HDLExpr expr;
if(w0 > w1){
expr = hm.newExpr(HDLOp.DROPHEAD, src, HDLUtils.newValue(w0-w1, 32));
}else if(w0 < w1){
expr = hm.newExpr(HDLOp.PADDINGHEAD, src, HDLUtils.newValue(w1-w0, 32));
}else{
expr = src;
}
dest.setAssign(state, expr);
predExprMap.put(item, expr);
break;
}
case COND:{
HDLVariable dest = (HDLVariable)(convOperandToHDLExpr(item, item.getDestOperand()));
Operand[] src = item.getSrcOperand();
HDLExpr expr = hm.newExpr(HDLOp.IF,
convOperandToHDLExpr(item, src[0]),
convOperandToHDLExpr(item, src[1]),
convOperandToHDLExpr(item, src[2]));
dest.setAssign(state, expr);
predExprMap.put(item, expr);
break;
}
case UNDEFINED :{
System.out.println("UNDEFINED : " + item.info());
break;
}
case LSHIFT32:
case LOGIC_RSHIFT32:
case ARITH_RSHIFT32:
case LSHIFT64:
case LOGIC_RSHIFT64:
case ARITH_RSHIFT64:
case MUL32:
case MUL64:
{
Operand[] arg = item.getSrcOperand();
HDLInstance inst = getOperationUnit(item.getOp(), resource, board.getName());
inst.getSignalForPort("a").setAssign(state, 0, convOperandToHDLExpr(item, arg[0]));
inst.getSignalForPort("b").setAssign(state, 0, convOperandToHDLExpr(item, arg[1]));
HDLSignal dest = (HDLSignal)convOperandToHDLExpr(item, item.getDestOperand());
dest.setAssign(state, inst.getSignalForPort("result"));
predExprMap.put(item, inst.getSignalForPort("result"));
break;
}
case DIV32 :
case DIV64 :
{
Operand[] arg = item.getSrcOperand();
HDLInstance inst = getOperationUnit(item.getOp(), resource, board.getName());
inst.getSignalForPort("a").setAssign(state, 0, convOperandToHDLExpr(item, arg[0]));
inst.getSignalForPort("b").setAssign(state, 0, convOperandToHDLExpr(item, arg[1]));
inst.getSignalForPort("nd").setAssign(state, 0, HDLPreDefinedConstant.HIGH);
inst.getSignalForPort("nd").setDefaultValue(HDLPreDefinedConstant.LOW);
inst.getSignalForPort("nd").setResetValue(HDLPreDefinedConstant.LOW);
HDLSignal dest = (HDLSignal)convOperandToHDLExpr(item, item.getDestOperand());
dest.setAssign(state, inst.getSignalForPort("quantient"));
predExprMap.put(item, inst.getSignalForPort("quantient"));
break;
}
case MOD32 :
case MOD64 :
{
Operand[] arg = item.getSrcOperand();
HDLInstance inst = getOperationUnit(item.getOp(), resource, board.getName());
inst.getSignalForPort("a").setAssign(state, 0, convOperandToHDLExpr(item, arg[0]));
inst.getSignalForPort("b").setAssign(state, 0, convOperandToHDLExpr(item, arg[1]));
inst.getSignalForPort("nd").setAssign(state, 0, HDLPreDefinedConstant.HIGH);
inst.getSignalForPort("nd").setDefaultValue(HDLPreDefinedConstant.LOW);
HDLSignal dest = (HDLSignal)convOperandToHDLExpr(item, item.getDestOperand());
dest.setAssign(state, inst.getSignalForPort("remainder"));
predExprMap.put(item, inst.getSignalForPort("remainder"));
break;
}
case FADD32 :
case FSUB32 :
case FMUL32 :
case FDIV32 :
case FADD64 :
case FSUB64 :
case FMUL64 :
case FDIV64 :
{
Operand[] arg = item.getSrcOperand();
HDLInstance inst = getOperationUnit(item.getOp(), resource, board.getName());
inst.getSignalForPort("a").setAssign(state, 0, convOperandToHDLExpr(item, arg[0]));
inst.getSignalForPort("b").setAssign(state, 0, convOperandToHDLExpr(item, arg[1]));
inst.getSignalForPort("nd").setAssign(state, 0, HDLPreDefinedConstant.HIGH);
inst.getSignalForPort("nd").setDefaultValue(HDLPreDefinedConstant.LOW);
HDLSignal dest = (HDLSignal)convOperandToHDLExpr(item, item.getDestOperand());
dest.setAssign(state, inst.getSignalForPort("result"));
predExprMap.put(item, inst.getSignalForPort("result"));
break;
}
case CONV_F2I:
case CONV_I2F:
case CONV_D2L:
case CONV_L2D:
case CONV_F2D:
case CONV_D2F:
{
Operand[] arg = item.getSrcOperand();
HDLInstance inst = getOperationUnit(item.getOp(), resource, board.getName());
inst.getSignalForPort("a").setAssign(state, 0, convOperandToHDLExpr(item, arg[0]));
inst.getSignalForPort("nd").setAssign(state, 0, HDLPreDefinedConstant.HIGH);
inst.getSignalForPort("nd").setDefaultValue(HDLPreDefinedConstant.LOW);
HDLSignal dest = (HDLSignal)convOperandToHDLExpr(item, item.getDestOperand());
dest.setAssign(state, inst.getSignalForPort("result"));
predExprMap.put(item, inst.getSignalForPort("result"));
break;
}
case FLT32: genCompUnitExpr(item, FCOMP32.LT, state, resource, board); break;
case FLEQ32: genCompUnitExpr(item, FCOMP32.LEQ, state, resource, board); break;
case FGT32: genCompUnitExpr(item, FCOMP32.GT, state, resource, board); break;
case FGEQ32: genCompUnitExpr(item, FCOMP32.GEQ, state, resource, board); break;
case FCOMPEQ32: genCompUnitExpr(item, FCOMP32.EQ, state, resource, board); break;
case FNEQ32: genCompUnitExpr(item, FCOMP32.NEQ, state, resource, board); break;
case FLT64: genCompUnitExpr(item, FCOMP64.LT, state, resource, board); break;
case FLEQ64: genCompUnitExpr(item, FCOMP64.LEQ, state, resource, board); break;
case FGT64: genCompUnitExpr(item, FCOMP64.GT, state, resource, board); break;
case FGEQ64: genCompUnitExpr(item, FCOMP64.GEQ, state, resource, board); break;
case FCOMPEQ64: genCompUnitExpr(item, FCOMP64.EQ, state, resource, board); break;
case FNEQ64: genCompUnitExpr(item, FCOMP64.NEQ, state, resource, board); break;
case MSB_FLAP:{
HDLOp op = convOp2HDLOp(item.getOp());
HDLVariable dest = (HDLVariable)(convOperandToHDLExpr(item, item.getDestOperand()));
HDLExpr src = convOperandToHDLExpr(item, item.getSrcOperand()[0]);
if(src instanceof HDLValue){
HDLSignal tmp = hm.newSignal(String.format("const_%04d", constIdGen.id()), (HDLPrimitiveType)src.getType());
tmp.setAssign(null, src);
src = tmp;
}
HDLExpr expr = hm.newExpr(op, src);
dest.setAssign(state, expr);
predExprMap.put(item, expr);
break;
}
default: {
// System.out.println(item.info());
HDLOp op = convOp2HDLOp(item.getOp());
// if(op == HDLOp.UNDEFINED) return;
HDLVariable dest = (HDLVariable)(convOperandToHDLExpr(item, item.getDestOperand()));
Operand[] src = item.getSrcOperand();
int nums = op.getArgNums();
HDLExpr expr = (nums == 1) ?
hm.newExpr(op, convOperandToHDLExpr(item, src[0])) :
hm.newExpr(op, convOperandToHDLExpr(item, src[0]), convOperandToHDLExpr(item, src[1]));
dest.setAssign(state, expr);
predExprMap.put(item, expr);
}
}
}
private void connectArrayTypeParammeter(HDLExpr flag, HDLInstance src, HDLInstance dest, String key){
HDLExpr mux_key = hm.newExpr(HDLOp.OR, dest.getSignalForPort(key + "_we_b"), dest.getSignalForPort(key + "_oe_b"));
// length (dest.length <- src.length)
HDLSignal dest_length = dest.getSignalForPort(key + "_length");
if(dest_length.isAssignAlways() == false){
dest_length.setAssign(null, src.getSignalForPort("length"));
}else{
HDLExpr expr = dest_length.getAssignAlwaysExpr();
dest_length.setAssign(null, hm.newExpr(HDLOp.IF, flag, src.getSignalForPort("length"), expr));
}
// dout_b (dest.dout_b <- src.dout_b)
HDLSignal dest_dout = dest.getSignalForPort(key + "_dout_b");
if(dest_dout.isAssignAlways() == false){
dest_dout.setAssign(null, src.getSignalForPort("dout_b"));
}else{
HDLExpr expr = dest_dout.getAssignAlwaysExpr();
dest_dout.setAssign(null, hm.newExpr(HDLOp.IF, flag, src.getSignalForPort("dout_b"), expr));
}
// address (src.address_b <- dest.address_b when mux_key else src.address_b)
HDLSignal dest_address_b = dest.getSignalForPort(key + "_address_b");
HDLSignal src_address_b = src.getSignalForPort("address_b");
HDLSignal address_b_mux = hm.newTmpSignal(src_address_b.getType(), HDLSignal.ResourceKind.WIRE);
//address_b_mux.setAssign(null, hm.newExpr(HDLOp.IF, hm.newExpr(HDLOp.AND, mux_key, flag), dest_address_b, src_address_b));
address_b_mux.setAssign(null, hm.newExpr(HDLOp.IF, flag, dest_address_b, src_address_b));
src.replacePortPair(src_address_b, address_b_mux);
// din (src.din_b <- dest.din_b when mux_key else src.din_b)
HDLSignal dest_din_b = dest.getSignalForPort(key + "_din_b");
HDLSignal src_din_b = src.getSignalForPort("din_b");
HDLSignal din_b_mux = hm.newTmpSignal(src_din_b.getType(), HDLSignal.ResourceKind.WIRE);
din_b_mux.setAssign(null, hm.newExpr(HDLOp.IF, mux_key, dest_din_b, src_din_b));
src.replacePortPair(src_din_b, din_b_mux);
// we (src.we_b <- dest.we_b or src.we_b)
HDLSignal dest_we_b = dest.getSignalForPort(key + "_we_b");
HDLSignal src_we_b = src.getSignalForPort("we_b");
HDLSignal we_b_or = hm.newTmpSignal(src_we_b.getType(), HDLSignal.ResourceKind.WIRE);
we_b_or.setAssign(null, hm.newExpr(HDLOp.OR, hm.newExpr(HDLOp.AND, flag, dest_we_b), src_we_b));
src.replacePortPair(src_we_b, we_b_or);
// oe (src.)oe_b <- dest.oe_b or else src.oe_b)
HDLSignal dest_oe_b = dest.getSignalForPort(key + "_oe_b");
HDLSignal src_oe_b = src.getSignalForPort("oe_b");
HDLSignal oe_b_or = hm.newTmpSignal(src_oe_b.getType(), HDLSignal.ResourceKind.WIRE);
oe_b_or.setAssign(null, hm.newExpr(HDLOp.OR, dest_oe_b, src_oe_b));
src.replacePortPair(src_oe_b, oe_b_or);
}
private void genCompUnitExpr(SchedulerItem item, int opcode, SequencerState state, HardwareResource resource, SchedulerBoard board){
Operand[] arg = item.getSrcOperand();
HDLInstance inst = getOperationUnit(item.getOp(), resource, board.getName());
inst.getSignalForPort("a").setAssign(state, 0, convOperandToHDLExpr(item, arg[0]));
inst.getSignalForPort("b").setAssign(state, 0, convOperandToHDLExpr(item, arg[1]));
inst.getSignalForPort("opcode").setAssign(state, 0, HDLUtils.newValue(opcode, 8));
inst.getSignalForPort("nd").setAssign(state, 0, HDLPreDefinedConstant.HIGH);
inst.getSignalForPort("nd").setDefaultValue(HDLPreDefinedConstant.LOW);
HDLSignal dest = (HDLSignal)convOperandToHDLExpr(item, item.getDestOperand());
dest.setAssign(state, inst.getSignalForPort("result"));
predExprMap.put(item, inst.getSignalForPort("result"));
}
private Hashtable<SchedulerBoard, HDLSignal> returnSigTable = new Hashtable<>();
private Hashtable<SchedulerBoard, HDLSignal[]> returnMultiSigTable = new Hashtable<>();
private void genMethodCtrlSignals(SchedulerBoard board, Hashtable<HDLVariable, HDLInstance> callStackMap){
if(board.getReturnType() != PrimitiveTypeKind.VOID &&
!(board.getReturnType() instanceof synthesijer.ast.type.MySelfType) &&
!(board.getReturnType() instanceof synthesijer.ast.type.MultipleType)
){
if(board.isPrivate() == false){
HDLPort return_port = hm.newPort(board.getName() + "_return", HDLPort.DIR.OUT, getHDLType(board.getReturnType()));
returnSigTable.put(board, return_port.getSignal());
}else{
HDLSignal return_sig = hm.newSignal(board.getName() + "_return", getHDLType(board.getReturnType()));
returnSigTable.put(board, return_sig);
}
}
if(board.getReturnType() instanceof synthesijer.ast.type.MultipleType){
MultipleType t = (MultipleType)(board.getReturnType());
ArrayList<HDLSignal> list = new ArrayList<HDLSignal>();
for(int i = 0; i < t.size(); i++){
if(board.isPrivate() == false){
HDLPort return_port = hm.newPort(board.getName() + "_return_" + i, HDLPort.DIR.OUT, getHDLType(board.getReturnType()));
list.add(return_port.getSignal());
}else{
HDLSignal return_sig = hm.newSignal(board.getName() + "_return_" + i, getHDLType(board.getReturnType()));
list.add(return_sig);
}
}
returnMultiSigTable.put(board, list.toArray(new HDLSignal[]{}));
}
if(board.isAuto()){
return;
}
// generating a busy port signal
if(board.isPrivate() == false){ // public
HDLPort busy_port = hm.newPort(board.getName() + "_busy", HDLPort.DIR.OUT, HDLPrimitiveType.genBitType());
busy_port.getSignal().setResetValue(HDLPreDefinedConstant.HIGH);
varTable.put(busy_port.getName(), busy_port.getSignal());
}else{ // private
HDLSignal busy_sig = hm.newSignal(board.getName() + "_busy", HDLPrimitiveType.genBitType());
varTable.put(busy_sig.getName(), busy_sig);
}
HDLSignal req_flag = hm.newSignal(board.getName() + "_req_flag", HDLPrimitiveType.genBitType());
HDLSignal req_local = hm.newSignal(board.getName() + "_req_local", HDLPrimitiveType.genBitType());
if(board.isPrivate() == false){ // public
HDLPort req_port = hm.newPort(board.getName() + "_req", HDLPort.DIR.IN, HDLPrimitiveType.genBitType());
varTable.put(req_port.getName(), req_port.getSignal());
req_flag.setAssign(null, hm.newExpr(HDLOp.OR, req_local, req_port.getSignal()));
}else{ // private
req_flag.setAssign(null, req_local);
}
varTable.put(req_flag.getName(), req_flag);
varTable.put(req_local.getName(), req_local);
if(board.hasCallStack()){
HDLInstance call_stack = genStackForRecursiveCall(board.getName() + "_call_stack_memory", board.getCallStackSize(), 16);
//for(VariableOperand v: board.getVarList()){
for(Operand v: board.getVarList()){
if(!(v instanceof VariableOperand)) continue;
if(((VariableOperand)v).getMethodName() == null){
continue; // skip non-user defined variable
}
HDLVariable hv = varTable.get(v.getName());
if(hv.getType() instanceof HDLPrimitiveType){
HDLInstance inst = genStackForRecursiveCall(hv.getName() + "_call_stack_memory", board.getCallStackSize(), ((HDLPrimitiveType)hv.getType()).getWidth());
callStackMap.put(hv, inst);
}else{
SynthesijerUtils.warn("cannot preserve non-primitive type variable for recursive call:" + v);
}
}
}
}
private HDLInstance genStackForRecursiveCall(String name, int size, int width){
HDLInstance stack;
switch(width){
case 1:
stack = newInstModule("SimpleBlockRAM1", name);
break;
case 8:
stack = newInstModule("SimpleBlockRAM8", name);
break;
case 16:
stack = newInstModule("SimpleBlockRAM16", name);
break;
case 32:
stack = newInstModule("SimpleBlockRAM32", name);
break;
case 64:
stack = newInstModule("SimpleBlockRAM64", name);
break;
default:
SynthesijerUtils.warn("SchedulerInfoCompiler: might be generated unexpected stack:" + name);
stack = newInstModule("SimpleBlockRAM32", name);
}
stack.getSignalForPort("clk").setAssign(null, hm.getSysClk().getSignal());
stack.getSignalForPort("reset").setAssign(null, hm.getSysReset().getSignal());
stack.getParameterPair("WORDS").setValue(new HDLValue(size));
int depth = (int)Math.ceil(Math.log(size) / Math.log(2.0));
stack.getParameterPair("DEPTH").setValue(new HDLValue(depth));
stack.getSignalForPort("address_b").setResetValue(HDLPreDefinedConstant.VECTOR_ZERO);
stack.getSignalForPort("we_b").setResetValue(HDLPreDefinedConstant.LOW);
return stack;
}
private Hashtable<Integer, SequencerState> genStatemachine(SchedulerBoard board, HardwareResource resource, Hashtable<Integer, SequencerState> returnTable, Hashtable<HDLVariable, HDLInstance> callStackMap){
HDLSequencer seq = hm.newSequencer(board.getName() + "_method");
IdGen id = new IdGen("S");
Hashtable<Integer, SequencerState> states = new Hashtable<>();
HDLVariable busy_port_sig = null, req_flag = null, req_flag_d = null, req_flag_edge = null;
HDLInstance call_stack = hm.getModuleInstance(board.getName() + "_call_stack_memory");
if(board.isAuto() == false){
req_flag = varTable.get(board.getName() + "_req_flag");
busy_port_sig = varTable.get(board.getName() + "_busy");
req_flag_d = hm.newSignal(req_flag.getName() + "_d", req_flag.getType());
req_flag_d.setAssignForSequencer(seq, req_flag);
req_flag_edge = hm.newSignal(req_flag.getName() + "_edge", req_flag.getType());
req_flag_edge.setAssign(null, hm.newExpr(HDLOp.AND, req_flag, hm.newExpr(HDLOp.NOT, req_flag_d)));
}
SequencerState methodEntryState = null;
SequencerState methodIdleState = null;
for(SchedulerSlot slot: board.getSlots()){
states.put(slot.getStepId(), seq.addSequencerState(id.get(slot.getStepId())));
}
for(SchedulerSlot slot: board.getSlots()){
if(slot.hasBranchOp() || slot.getNextStep().length > 1 || slot.getLatency() > 0) continue;
if(slot.getStepId() == 0) continue;
states.get(slot.getStepId()).addStateTransit(states.get(slot.getNextStep()[0]));
}
for(SchedulerSlot slot: board.getSlots()){
for(SchedulerItem item: slot.getItems()){
SequencerState s = states.get(item.getStepId());
switch(item.getOp()){
case METHOD_EXIT: {
HDLExpr unlock = null;
HDLExpr wait_with_unlock = null;
if(board.hasWaitDependsBoard()){ // must wait for other method, such as join
HDLVariable flag = varTable.get(board.getWaitDependsBoardName() + "_busy");
wait_with_unlock = hm.newExpr(HDLOp.EQ, flag, HDLPreDefinedConstant.LOW); // the waiting method has been done.
unlock = wait_with_unlock;
}
if(board.hasCallStack()){
HDLExpr stack_bottom = hm.newExpr(HDLOp.EQ, call_stack.getSignalForPort("address_b"), HDLPreDefinedConstant.INTEGER_ZERO);
// unlock is updated with this stack bottom condition
unlock = (unlock == null) ? stack_bottom : hm.newExpr(HDLOp.AND, stack_bottom, unlock);
}
if(unlock != null){
s.addStateTransit(unlock, states.get(item.getSlot().getNextStep()[0]));
}else{
s.addStateTransit(states.get(item.getSlot().getNextStep()[0]));
}
if(board.isAuto() == false){
if(unlock != null){
busy_port_sig.setAssign(s, hm.newExpr(HDLOp.IF, unlock, HDLPreDefinedConstant.LOW, HDLPreDefinedConstant.HIGH));
}else{
busy_port_sig.setAssign(s, HDLPreDefinedConstant.LOW);
}
}
methodIdleState = s;
break;
}
case METHOD_ENTRY:{
if(board.isAuto()){
s.addStateTransit(states.get(item.getSlot().getNextStep()[0]));
}else{
s.addStateTransit(hm.newExpr(HDLOp.OR, req_flag, req_flag_d), states.get(item.getSlot().getNextStep()[0]));
//s.addStateTransit(req_flag, states.get(item.getSlot().getNextStep()[0]));
busy_port_sig.setAssign(s, hm.newExpr(HDLOp.OR, req_flag, req_flag_d));
}
methodEntryState = s;
break;
}
case SELECT:{
SelectItem item0 = (SelectItem)item;
for(int i = 0; i < item0.pat.length; i++){
HDLExpr cond = convOperandToHDLExpr(item, item0.target);
HDLExpr pat = convOperandToHDLExpr(item, item0.pat[i]);
s.addStateTransit(hm.newExpr(HDLOp.EQ, cond, pat), states.get(item.getSlot().getNextStep()[i]));
}
s.addStateTransit(states.get(item0.getSlot().getNextStep()[item0.pat.length]));
break;
}
case JT:{
HDLExpr flag = convOperandToHDLExpr(item, item.getSrcOperand()[0]);
s.addStateTransit(hm.newExpr(HDLOp.EQ, flag, HDLPreDefinedConstant.HIGH), states.get(item.getSlot().getNextStep()[0]));
s.addStateTransit(hm.newExpr(HDLOp.EQ, flag, HDLPreDefinedConstant.LOW), states.get(item.getSlot().getNextStep()[1]));
break;
}
case JP:
s.addStateTransit(states.get(item.getSlot().getNextStep()[0]));
break;
case CALL:
case EXT_CALL:
{
SequencerState call_body = seq.addSequencerState(s.getStateId().getValue()+"_body", false);
SequencerState call_wait = seq.addSequencerState(s.getStateId().getValue()+"_wait", false);
MethodInvokeItem item0 = (MethodInvokeItem)item;
HDLVariable call_req, call_busy;
String flag_name;
if(item0.getOp() == Op.EXT_CALL){
HDLInstance obj = (HDLInstance)(varTable.get(item0.obj.getName()));
call_req = obj.getSignalForPort(item0.name + "_req");
call_busy = obj.getSignalForPort(item0.name + "_busy");
//flag_name = String.format("%s_ext_call_flag_%04d", obj.getName(), item.getStepId());
flag_name = String.format("%s_%s_ext_call_flag_%04d", obj.getName(), item0.name, item.getStepId());
}else{
call_req = varTable.get(item0.name + "_req_local");
call_busy = varTable.get(item0.name + "_busy");
flag_name = String.format("%s_call_flag_%04d", item0.name, item.getStepId());
}
HDLSignal flag = (HDLSignal)varTable.get(flag_name);
if(flag == null){
flag = hm.newSignal(flag_name, HDLPrimitiveType.genBitType(), HDLSignal.ResourceKind.WIRE);
flag.setAssign(null, hm.newExpr(HDLOp.EQ,
hm.newExpr(HDLOp.AND,
hm.newExpr(HDLOp.EQ, call_busy, HDLPreDefinedConstant.LOW),
hm.newExpr(HDLOp.EQ, call_req, HDLPreDefinedConstant.LOW)),
HDLPreDefinedConstant.HIGH));
varTable.put(flag_name, flag);
}
// when busy = '0', s -> call_body
// recur
// s.addStateTransit(hm.newExpr(HDLOp.EQ, call_busy, HDLPreDefinedConstant.LOW), call_body);
s.addStateTransit(call_body);
// call_body
// call_req.setAssign(call_body, 0, HDLPreDefinedConstant.HIGH);
call_req.setAssign(call_body, HDLPreDefinedConstant.HIGH);
call_req.setDefaultValue(HDLPreDefinedConstant.LOW); // otherwise '0'
// call_body.setMaxConstantDelay(1);
if(item0.isNoWait() == true){
System.out.println("no wait:" + call_req);
call_body.addStateTransit(states.get(item.getSlot().getNextStep()[0]));
}else{
//System.out.println("block:" + call_req);
// call_body.setStateExitFlag(flag);
call_body.addStateTransit(call_wait);
call_wait.addStateTransit(flag, states.get(item.getSlot().getNextStep()[0]));
// call_wait.setStateExitFlag(flag);
}
// call_body.addStateTransit(states.get(item.getSlot().getNextStep()[0]));
if(call_stack != null && board.getName().equals(item0.name)){
//System.out.println("treating recursive call.");
HDLSignal addr = call_stack.getSignalForPort("address_b");
HDLSignal we = call_stack.getSignalForPort("we_b");
HDLSignal wdata = call_stack.getSignalForPort("din_b");
we.setAssign(s, HDLPreDefinedConstant.HIGH);
we.setDefaultValue(HDLPreDefinedConstant.LOW); // others
int retPoint = item.getStepId();
HDLValue retPointValue = new HDLValue(String.valueOf(retPoint), HDLPrimitiveType.genSignedType(16));
wdata.setAssign(s, retPointValue);
HDLExpr addr_expr = hm.newExpr(HDLOp.ADD, addr, HDLPreDefinedConstant.INTEGER_ONE);
addr.setAssign(s, addr_expr);
Enumeration<HDLVariable> preserve = callStackMap.keys();
while(preserve.hasMoreElements()){
HDLVariable src = preserve.nextElement();
HDLInstance inst = callStackMap.get(src);
HDLSignal a = inst.getSignalForPort("address_b");
HDLSignal w = inst.getSignalForPort("we_b");
HDLSignal d = inst.getSignalForPort("din_b");
w.setAssign(s, HDLPreDefinedConstant.HIGH);
w.setDefaultValue(HDLPreDefinedConstant.LOW); // others
d.setAssign(s, src);
a.setAssign(s, addr_expr);
}
SequencerState call_ret = seq.addSequencerState(s.getStateId().getValue()+"_ret", false);
call_ret.addStateTransit(states.get(item.getSlot().getNextStep()[0]));
returnTable.put(retPoint, call_ret);
}
break;
}
case LSHIFT32 :
case LOGIC_RSHIFT32 :
case ARITH_RSHIFT32 :
case LSHIFT64 :
case LOGIC_RSHIFT64 :
case ARITH_RSHIFT64 :
case MUL32 :
case MUL64 :
case DIV32 :
case DIV64 :
case MOD32 :
case MOD64 :
case FADD32 :
case FSUB32 :
case FMUL32 :
case FDIV32 :
case FADD64 :
case FSUB64 :
case FMUL64 :
case FDIV64 :
case CONV_F2I :
case CONV_I2F :
case CONV_D2L :
case CONV_L2D :
case CONV_F2D :
case CONV_D2F :
case FLT32:
case FLEQ32:
case FGT32:
case FGEQ32:
case FCOMPEQ32:
case FNEQ32:
case FLT64:
case FLEQ64:
case FGT64:
case FGEQ64:
case FCOMPEQ64:
case FNEQ64:
{
s.setMaxConstantDelay(item.getOp().latency);
s.addStateTransit(states.get(item.getSlot().getNextStep()[0]));
HDLInstance inst = getOperationUnit(item.getOp(), resource, board.getName());
s.setStateExitFlag(inst.getSignalForPort("valid"));
break;
}
case ARRAY_ACCESS:{
states.get(slot.getStepId()).addStateTransit(states.get(slot.getNextStep()[0]));
break;
}
case RETURN:{
states.get(slot.getStepId()).addStateTransit(states.get(slot.getNextStep()[0]));
break;
}
case MULTI_RETURN:{
// TODO
states.get(slot.getStepId()).addStateTransit(states.get(slot.getNextStep()[0]));
break;
}
default:
/*
if(slot.hasBranchOp() || slot.getNextStep().length > 1 || slot.getLatency() > 0){
SynthesijerUtils.warn("Undefined state transition: " + item.getOp());
}
*/
states.get(slot.getStepId()).addStateTransit(states.get(slot.getNextStep()[0]));
/*
if(item.isBranchOp()){
}else{
s.addStateTransit(states[item.getStepId()+1]);
}
*/
//s.addStateTransit(states[item.getBranchId()[0]]);
//s.addStateTransit(states.get(item.getSlot().getNextStep()[0]));
}
}
}
seq.getIdleState().addStateTransit(states.get(0));
if(board.isAuto() == false){
if(methodEntryState != null && methodIdleState != null){
HDLSignal sig = methodEntryState.getKey();
sig.setAssignForSequencer(seq,
hm.newExpr(HDLOp.AND, hm.newExpr(HDLOp.NEQ, sig, methodIdleState.getStateId()),
hm.newExpr(HDLOp.AND, hm.newExpr(HDLOp.NEQ, sig, methodEntryState.getStateId()),
req_flag_edge)),
methodEntryState.getStateId());
}
}
if(board.hasCallStack()){
HDLExpr unlock = null;
if(board.hasWaitDependsBoard()){ // must wait for other method, such as join
HDLVariable flag = varTable.get(board.getWaitDependsBoardName() + "_busy");
unlock = hm.newExpr(HDLOp.EQ, flag, HDLPreDefinedConstant.LOW); // the waiting method has been done.
}
Enumeration<Integer> i = returnTable.keys();
HDLSignal top = call_stack.getSignalForPort("dout_b");
HDLExpr stack_bottom = hm.newExpr(HDLOp.EQ, call_stack.getSignalForPort("address_b"), HDLPreDefinedConstant.INTEGER_ZERO);
HDLExpr not_stack_bottom = hm.newExpr(HDLOp.NOT, stack_bottom);
while(i.hasMoreElements()){
int nk = i.nextElement();
SequencerState ns = returnTable.get(nk);
HDLExpr cond = hm.newExpr(HDLOp.AND, not_stack_bottom, hm.newExpr(HDLOp.EQ, top, new HDLValue(String.valueOf(nk), HDLPrimitiveType.genSignedType(16))));
cond = (unlock == null) ? cond : hm.newExpr(HDLOp.AND, unlock, cond);
methodIdleState.addStateTransit(cond, ns);
}
HDLSignal addr = call_stack.getSignalForPort("address_b");
HDLExpr dec = hm.newExpr(HDLOp.SUB, addr, HDLPreDefinedConstant.INTEGER_ONE);
if(unlock != null){
addr.setAssign(methodIdleState, hm.newExpr(HDLOp.AND, not_stack_bottom, unlock), dec);
}else{
addr.setAssign(methodIdleState, not_stack_bottom, dec);
}
Enumeration<HDLVariable> preserve = callStackMap.keys();
while(preserve.hasMoreElements()){
HDLVariable src = preserve.nextElement();
HDLInstance inst = callStackMap.get(src);
HDLSignal a = inst.getSignalForPort("address_b");
HDLSignal d = inst.getSignalForPort("dout_b");
if(unlock != null){
src.setAssign(methodIdleState, hm.newExpr(HDLOp.AND, not_stack_bottom, unlock), d);
a.setAssign(methodIdleState, hm.newExpr(HDLOp.AND, not_stack_bottom, unlock), dec);
}else{
src.setAssign(methodIdleState, not_stack_bottom, d);
a.setAssign(methodIdleState, not_stack_bottom, dec);
}
}
}
return states;
}
private HDLInstance newInstModule(String mName, String uName){
SynthesijerModuleInfo info = Manager.INSTANCE.searchHDLModuleInfo(mName);
HDLInstance inst = hm.newModuleInstance(info.getHDLModule(), uName);
inst.getSignalForPort("clk").setAssign(null, hm.getSysClk().getSignal());
inst.getSignalForPort("reset").setAssign(null, hm.getSysReset().getSignal());
return inst;
}
private HDLInstance getOperationUnit(Op op, HardwareResource resource, String name){
switch(op){
case MUL32:{
if(resource.mul32 == null) resource.mul32 = newInstModule("MUL32", "u_synthesijer_mul32" + "_" + name);
return resource.mul32;
}
case MUL64:{
if(resource.mul64 == null) resource.mul64 = newInstModule("MUL64", "u_synthesijer_mul64" + "_" + name);
return resource.mul64;
}
case DIV32:
case MOD32:{
if(resource.div32 == null){
resource.div32 = newInstModule("DIV32", "u_synthesijer_div32" + "_" + name);
resource.div32.getSignalForPort("b").setResetValue(HDLUtils.newValue(1, 32));
}
return resource.div32;
}
case DIV64:
case MOD64:{
if(resource.div64 == null){
resource.div64 = newInstModule("DIV64", "u_synthesijer_div64" + "_" + name);
resource.div64.getSignalForPort("b").setResetValue(HDLUtils.newValue(1, 64));
}
return resource.div64;
}
case FADD32:{
if(resource.fadd32 == null) resource.fadd32 = newInstModule("FADD32", "u_synthesijer_fadd32" + "_" + name);
return resource.fadd32;
}
case FSUB32:{
if(resource.fsub32 == null) resource.fsub32 = newInstModule("FSUB32", "u_synthesijer_fsub32" + "_" + name);
return resource.fsub32;
}
case FMUL32:{
if(resource.fmul32 == null) resource.fmul32 = newInstModule("FMUL32", "u_synthesijer_fmul32" + "_" + name);
return resource.fmul32;
}
case FDIV32:{
if(resource.fdiv32 == null) resource.fdiv32 = newInstModule("FDIV32", "u_synthesijer_fdiv32" + "_" + name);
return resource.fdiv32;
}
case FADD64:{
if(resource.fadd64 == null) resource.fadd64 = newInstModule("FADD64", "u_synthesijer_fadd64" + "_" + name);
return resource.fadd64;
}
case FSUB64:{
if(resource.fsub64 == null) resource.fsub64 = newInstModule("FSUB64", "u_synthesijer_fsub64" + "_" + name);
return resource.fsub64;
}
case FMUL64:{
if(resource.fmul64 == null) resource.fmul64 = newInstModule("FMUL64", "u_synthesijer_fmul64" + "_" + name);
return resource.fmul64;
}
case FDIV64:{
if(resource.fdiv64 == null) resource.fdiv64 = newInstModule("FDIV64", "u_synthesijer_fdiv64" + "_" + name);
return resource.fdiv64;
}
case CONV_F2I:{
if(resource.f2i == null) resource.f2i = newInstModule("FCONV_F2I", "u_synthesijer_fconv_f2i" + "_" + name);
return resource.f2i;
}
case CONV_I2F:{
if(resource.i2f == null) resource.i2f = newInstModule("FCONV_I2F", "u_synthesijer_fconv_i2f" + "_" + name);
return resource.i2f;
}
case CONV_L2D:{
if(resource.l2d == null) resource.l2d = newInstModule("FCONV_L2D", "u_synthesijer_fconv_l2d" + "_" + name);
return resource.l2d;
}
case CONV_D2L:{
if(resource.d2l == null) resource.d2l = newInstModule("FCONV_D2L", "u_synthesijer_fconv_d2l" + "_" + name);
return resource.d2l;
}
case CONV_F2D:{
if(resource.f2d == null) resource.f2d = newInstModule("FCONV_F2D", "u_synthesijer_fconv_f2d" + "_" + name);
return resource.f2d;
}
case CONV_D2F:{
if(resource.d2f == null) resource.d2f = newInstModule("FCONV_D2F", "u_synthesijer_fconv_d2f" + "_" + name);
return resource.d2f;
}
case LSHIFT32:{
if(resource.lshift32 == null) resource.lshift32 = newInstModule("LSHIFT32", "u_synthesijer_lshift32" + "_" + name);
return resource.lshift32;
}
case LOGIC_RSHIFT32:{
if(resource.logic_rshift32 == null) resource.logic_rshift32 = newInstModule("LOGIC_RSHIFT32", "u_synthesijer_logic_rshift32" + "_" + name);
return resource.logic_rshift32;
}
case ARITH_RSHIFT32:{
if(resource.arith_rshift32 == null) resource.arith_rshift32 = newInstModule("ARITH_RSHIFT32", "u_synthesijer_arith_rshift32" + "_" + name);
return resource.arith_rshift32;
}
case LSHIFT64:{
if(resource.lshift64 == null) resource.lshift64 = newInstModule("LSHIFT64", "u_synthesijer_lshift64" + "_" + name);
return resource.lshift64;
}
case LOGIC_RSHIFT64:{
if(resource.logic_rshift64 == null) resource.logic_rshift64 = newInstModule("LOGIC_RSHIFT64", "u_synthesijer_logic_rshift64" + "_" + name);
return resource.logic_rshift64;
}
case ARITH_RSHIFT64:{
if(resource.arith_rshift64 == null) resource.arith_rshift64 = newInstModule("ARITH_RSHIFT64", "u_synthesijer_arith_rshift64" + "_" + name);
return resource.arith_rshift64;
}
case FLT32:
case FLEQ32:
case FGT32:
case FGEQ32:
case FCOMPEQ32:
case FNEQ32:{
if(resource.fcomp32 == null) resource.fcomp32 = newInstModule("FCOMP32", "u_synthesijer_fcomp32" + "_" + name);
return resource.fcomp32;
}
case FLT64:
case FLEQ64:
case FGT64:
case FGEQ64:
case FCOMPEQ64:
case FNEQ64:{
if(resource.fcomp64 == null) resource.fcomp64 = newInstModule("FCOMP64", "u_synthesijer_fcomp64" + "_" + name);
return resource.fcomp64;
}
default: return null;
}
}
private class IdGen{
String prefix;
public IdGen(String prefix){
this.prefix = prefix;
}
public String get(int id){
String v = String.format("%s_%04d", prefix, id);
return v;
}
}
}