📄 simulate.cpp
字号:
case ELEM_TON:
if(which == ELEM_RTO)
flag = VAR_FLAG_RTO;
else if(which == ELEM_TOF)
flag = VAR_FLAG_TOF;
else if(which == ELEM_TON)
flag = VAR_FLAG_TON;
else oops();
MarkWithCheck(l->d.timer.name, flag);
break;
case ELEM_CTU:
case ELEM_CTD:
case ELEM_CTC:
if(which == ELEM_CTU)
flag = VAR_FLAG_CTU;
else if(which == ELEM_CTD)
flag = VAR_FLAG_CTD;
else if(which == ELEM_CTC)
flag = VAR_FLAG_CTC;
else oops();
MarkWithCheck(l->d.counter.name, flag);
break;
case ELEM_RES:
MarkWithCheck(l->d.reset.name, VAR_FLAG_RES);
break;
case ELEM_MOVE:
MarkWithCheck(l->d.move.dest, VAR_FLAG_ANY);
break;
case ELEM_LOOK_UP_TABLE:
MarkWithCheck(l->d.lookUpTable.dest, VAR_FLAG_ANY);
break;
case ELEM_PIECEWISE_LINEAR:
MarkWithCheck(l->d.piecewiseLinear.dest, VAR_FLAG_ANY);
break;
case ELEM_READ_ADC:
MarkWithCheck(l->d.readAdc.name, VAR_FLAG_ANY);
break;
case ELEM_ADD:
case ELEM_SUB:
case ELEM_MUL:
case ELEM_DIV:
MarkWithCheck(l->d.math.dest, VAR_FLAG_ANY);
break;
case ELEM_UART_RECV:
MarkWithCheck(l->d.uart.name, VAR_FLAG_ANY);
break;
case ELEM_SHIFT_REGISTER: {
int i;
for(i = 1; i < l->d.shiftRegister.stages; i++) {
char str[MAX_NAME_LEN+10];
sprintf(str, "%s%d", l->d.shiftRegister.name, i);
MarkWithCheck(str, VAR_FLAG_ANY);
}
break;
}
case ELEM_PERSIST:
case ELEM_FORMATTED_STRING:
case ELEM_SET_PWM:
case ELEM_MASTER_RELAY:
case ELEM_UART_SEND:
case ELEM_PLACEHOLDER:
case ELEM_COMMENT:
case ELEM_OPEN:
case ELEM_SHORT:
case ELEM_COIL:
case ELEM_CONTACTS:
case ELEM_ONE_SHOT_RISING:
case ELEM_ONE_SHOT_FALLING:
case ELEM_EQU:
case ELEM_NEQ:
case ELEM_GRT:
case ELEM_GEQ:
case ELEM_LES:
case ELEM_LEQ:
break;
default:
oops();
}
}
static void CheckVariableNames(void)
{
int i;
for(i = 0; i < Prog.numRungs; i++) {
CheckVariableNamesCircuit(ELEM_SERIES_SUBCKT, Prog.rungs[i]);
}
}
//-----------------------------------------------------------------------------
// The IF condition is true. Execute the body, up until the ELSE or the
// END IF, and then skip the ELSE if it is present. Called with PC on the
// IF, returns with PC on the END IF.
//-----------------------------------------------------------------------------
static void IfConditionTrue(void)
{
IntPc++;
// now PC is on the first statement of the IF body
SimulateIntCode();
// now PC is on the ELSE or the END IF
if(IntCode[IntPc].op == INT_ELSE) {
int nesting = 1;
for(; ; IntPc++) {
if(IntPc >= IntCodeLen) oops();
if(IntCode[IntPc].op == INT_END_IF) {
nesting--;
} else if(INT_IF_GROUP(IntCode[IntPc].op)) {
nesting++;
}
if(nesting == 0) break;
}
} else if(IntCode[IntPc].op == INT_END_IF) {
return;
} else {
oops();
}
}
//-----------------------------------------------------------------------------
// The IF condition is false. Skip the body, up until the ELSE or the END
// IF, and then execute the ELSE if it is present. Called with PC on the IF,
// returns with PC on the END IF.
//-----------------------------------------------------------------------------
static void IfConditionFalse(void)
{
int nesting = 0;
for(; ; IntPc++) {
if(IntPc >= IntCodeLen) oops();
if(IntCode[IntPc].op == INT_END_IF) {
nesting--;
} else if(INT_IF_GROUP(IntCode[IntPc].op)) {
nesting++;
} else if(IntCode[IntPc].op == INT_ELSE && nesting == 1) {
break;
}
if(nesting == 0) break;
}
// now PC is on the ELSE or the END IF
if(IntCode[IntPc].op == INT_ELSE) {
IntPc++;
SimulateIntCode();
} else if(IntCode[IntPc].op == INT_END_IF) {
return;
} else {
oops();
}
}
//-----------------------------------------------------------------------------
// Evaluate a circuit, calling ourselves recursively to evaluate if/else
// constructs. Updates the on/off state of all the leaf elements in our
// internal tables. Returns when it reaches an end if or an else construct,
// or at the end of the program.
//-----------------------------------------------------------------------------
static void SimulateIntCode(void)
{
for(; IntPc < IntCodeLen; IntPc++) {
IntOp *a = &IntCode[IntPc];
switch(a->op) {
case INT_SIMULATE_NODE_STATE:
if(*(a->poweredAfter) != SingleBitOn(a->name1))
NeedRedraw = TRUE;
*(a->poweredAfter) = SingleBitOn(a->name1);
break;
case INT_SET_BIT:
SetSingleBit(a->name1, TRUE);
break;
case INT_CLEAR_BIT:
SetSingleBit(a->name1, FALSE);
break;
case INT_COPY_BIT_TO_BIT:
SetSingleBit(a->name1, SingleBitOn(a->name2));
break;
case INT_SET_VARIABLE_TO_LITERAL:
if(GetSimulationVariable(a->name1) !=
a->literal && a->name1[0] != '$')
{
NeedRedraw = TRUE;
}
SetSimulationVariable(a->name1, a->literal);
break;
case INT_SET_VARIABLE_TO_VARIABLE:
if(GetSimulationVariable(a->name1) !=
GetSimulationVariable(a->name2))
{
NeedRedraw = TRUE;
}
SetSimulationVariable(a->name1,
GetSimulationVariable(a->name2));
break;
case INT_INCREMENT_VARIABLE:
IncrementVariable(a->name1);
break;
{
SWORD v;
case INT_SET_VARIABLE_ADD:
v = GetSimulationVariable(a->name2) +
GetSimulationVariable(a->name3);
goto math;
case INT_SET_VARIABLE_SUBTRACT:
v = GetSimulationVariable(a->name2) -
GetSimulationVariable(a->name3);
goto math;
case INT_SET_VARIABLE_MULTIPLY:
v = GetSimulationVariable(a->name2) *
GetSimulationVariable(a->name3);
goto math;
case INT_SET_VARIABLE_DIVIDE:
if(GetSimulationVariable(a->name3) != 0) {
v = GetSimulationVariable(a->name2) /
GetSimulationVariable(a->name3);
} else {
v = 0;
Error(_("Division by zero; halting simulation"));
StopSimulation();
}
goto math;
math:
if(GetSimulationVariable(a->name1) != v) {
NeedRedraw = TRUE;
SetSimulationVariable(a->name1, v);
}
break;
}
#define IF_BODY \
{ \
IfConditionTrue(); \
} else { \
IfConditionFalse(); \
}
case INT_IF_BIT_SET:
if(SingleBitOn(a->name1))
IF_BODY
break;
case INT_IF_BIT_CLEAR:
if(!SingleBitOn(a->name1))
IF_BODY
break;
case INT_IF_VARIABLE_LES_LITERAL:
if(GetSimulationVariable(a->name1) < a->literal)
IF_BODY
break;
case INT_IF_VARIABLE_EQUALS_VARIABLE:
if(GetSimulationVariable(a->name1) ==
GetSimulationVariable(a->name2))
IF_BODY
break;
case INT_IF_VARIABLE_GRT_VARIABLE:
if(GetSimulationVariable(a->name1) >
GetSimulationVariable(a->name2))
IF_BODY
break;
case INT_SET_PWM:
// Dummy call will cause a warning if no one ever assigned
// to that variable.
(void)GetSimulationVariable(a->name1);
break;
// Don't try to simulate the EEPROM stuff: just hold the EEPROM
// busy all the time, so that the program never does anything
// with it.
case INT_EEPROM_BUSY_CHECK:
SetSingleBit(a->name1, TRUE);
break;
case INT_EEPROM_READ:
case INT_EEPROM_WRITE:
oops();
break;
case INT_READ_ADC:
// Keep the shadow copies of the ADC variables because in
// the real device they will not be updated until an actual
// read is performed, which occurs only for a true rung-in
// condition there.
SetSimulationVariable(a->name1, GetAdcShadow(a->name1));
break;
case INT_UART_SEND:
if(SingleBitOn(a->name2) && (SimulateUartTxCountdown == 0)) {
SimulateUartTxCountdown = 2;
AppendToUartSimulationTextControl(
(BYTE)GetSimulationVariable(a->name1));
}
if(SimulateUartTxCountdown == 0) {
SetSingleBit(a->name2, FALSE);
} else {
SetSingleBit(a->name2, TRUE);
}
break;
case INT_UART_RECV:
if(QueuedUartCharacter >= 0) {
SetSingleBit(a->name2, TRUE);
SetSimulationVariable(a->name1, (SWORD)QueuedUartCharacter);
QueuedUartCharacter = -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -