Похоже, я немного поторопился с оправданием текущей V-модели, так как не учёл, что после eval_all_p() и eval_all_n() выполняются ещё и assign_all().
Если поставить отладочную печать после assign_all() :
Код:
/* Выполнение модели по переднему фронту ТЧ */
void vm1_qbus::eval_p(int nClk, VM1_QBUS_INOUT *pINOUT)
{
m_pINOUTPins = pINOUT;
m_nClk = nClk;
InLog('p');
eval_all_p(); //выполняем все always для переднего фронта
assign_all(); //вычисляем все assignы
OutLog('p');
}
/* Выполнение модели по заднему фронту ТЧ */
void vm1_qbus::eval_n(int nClk, VM1_QBUS_INOUT *pINOUT)
{
m_pINOUTPins = pINOUT;
m_nClk = nClk;
InLog(' ');
eval_all_n(); //выполняем все always для заднего фронта
assign_all(); //вычисляем все assignы
OutLog(' ');
}
То проблема с неправильным распределением сигналов по тактам встаёт во весь рост:
Код:
clk ad bsy wtbt sync din dout rply
p> 000019 000000 0 0 0 0 0 0
p< 000019 000000 0 0 0 0 0 0
> 000019 000000 0 0 0 0 0 0
< 000019 177716 1 0 0 0 0 0
p> 000020 177716 1 0 0 0 0 0
p< 000020 177716 1 0 0 0 0 0
> 000020 177716 1 0 0 0 0 0
< 000020 177716 1 0 1 0 0 0
p> 000021 177716 1 0 1 0 0 0
p< 000021 000000 1 0 1 1 0 0
> 000021 000000 1 0 1 1 0 0
< 000021 000000 1 0 1 1 0 1
Если же поменять местами выполнение eval и assign :
Код:
/* Выполнение модели по переднему фронту ТЧ */
void vm1_qbus::eval_p(int nClk, VM1_QBUS_INOUT *pINOUT)
{
m_pINOUTPins = pINOUT;
m_nClk = nClk;
InLog('p');
assign_all(); //вычисляем все assignы
eval_all_p(); //выполняем все always для переднего фронта
OutLog('p');
}
/* Выполнение модели по заднему фронту ТЧ */
void vm1_qbus::eval_n(int nClk, VM1_QBUS_INOUT *pINOUT)
{
m_pINOUTPins = pINOUT;
m_nClk = nClk;
InLog(' ');
assign_all(); //вычисляем все assignы
eval_all_n(); //выполняем все always для заднего фронта
OutLog(' ');
}
То распределение входных и выходных сигналов по фронтам становится идеальным:
Код:
clk ad bsy wtbt sync din dout rply
p> 000019 000000 0 0 0 0 0 0
p< 000019 177716 1 0 0 0 0 0
> 000019 177716 1 0 0 0 0 0
< 000019 177716 1 0 0 0 0 0
p> 000020 177716 1 0 0 0 0 0
p< 000020 177716 1 0 1 0 0 0
> 000020 177716 1 0 1 0 0 0
< 000020 000000 1 0 1 1 0 0
p> 000021 000000 1 0 1 1 0 0
p< 000021 000000 1 0 1 1 0 1
> 000021 000000 1 0 1 1 0 1
< 000021 000000 1 0 1 1 0 1
Но с синхронным адаптером процессор зависает в ходе выполнения первой же команды.
Кстати, при вычислении assign перед eval сигнал SEL1 должен корректно устанавливаться даже в исходной версии V-модели, что дополнительно указывает на верность такого подхода.
Чтобы воспроизвести проблему зависания модифицированной V-модели при работе с синхронным адаптером МПИ - достаточно убрать обработку сигналов шины между eval_p и eval_n :
Код:
void tboard::maincycle()
{
m_pCPU->eval_p(m_nClk, m_pMPI); //отработаем передний фронт ТЧ
// m_pMemory->eval(m_pMPI);
// m_pIRPS->eval(m_pMPI);
#ifdef OUT_VM1PIN_DBG_LOG
OutLog();
#endif
m_pCPU->eval_n(m_nClk, m_pMPI); //отработаем задний фронт ТЧ
m_pMemory->eval(m_pMPI);
m_pIRPS->eval(m_pMPI);
#ifdef OUT_VM1PIN_DBG_LOG
OutLog();
#endif
m_nClk++;
}