}
BitWidth dataWidth = state.getAttributeValue(StdAttr.WIDTH);
Object triggerType = state.getAttributeValue(StdAttr.EDGE_TRIGGER);
int max = state.getAttributeValue(ATTR_MAX).intValue();
Value clock = state.getPort(CK);
boolean triggered = data.updateClock(clock, triggerType);
Value newValue;
boolean carry;
if (state.getPort(CLR) == Value.TRUE) {
newValue = Value.createKnown(dataWidth, 0);
carry = false;
} else {
boolean ld = state.getPort(LD) == Value.TRUE;
boolean ct = state.getPort(CT) != Value.FALSE;
int oldVal = data.value;
int newVal;
if (!triggered) {
newVal = oldVal;
// trigger, enable = 1: should increment or decrement
} else if (ct) {
int goal = ld ? 0 : max;
if (oldVal == goal) {
Object onGoal = state.getAttributeValue(ATTR_ON_GOAL);
if (onGoal == ON_GOAL_WRAP) {
newVal = ld ? max : 0;
} else if (onGoal == ON_GOAL_STAY) {
newVal = oldVal;
} else if (onGoal == ON_GOAL_LOAD) {
Value in = state.getPort(IN);
newVal = in.isFullyDefined() ? in.toIntValue() : 0;
if (newVal > max) {
newVal &= max;
}
} else if (onGoal == ON_GOAL_CONT) {
newVal = ld ? oldVal - 1 : oldVal + 1;
} else {
//OK
System.err.println("Invalid goal attribute " + onGoal);
newVal = ld ? max : 0;
}
} else {
newVal = ld ? oldVal - 1 : oldVal + 1;
}
// trigger, enable = 0, load = 1: should load
} else if (ld) {
Value in = state.getPort(IN);
newVal = in.isFullyDefined() ? in.toIntValue() : 0;
if (newVal > max) {
newVal &= max;
}
// trigger, enable = 0, load = 0: no change