Nios® V Processor: Lockstep Implementation

ID 833274
Date 10/07/2024
Public
Document Table of Contents

B. Appendix

Assumptions:
  • A Lockstep-disabled Nios® V processor (Core 1) acts as the System Supervisor to manage a Lockstep-enabled Nios® V processor (Core 2).
  • Lockstep Configuration Interface of Core 2 is connected to Data Manager of Core 1.
  • The starting address of the Configuration Interface is 0xA0000.

Reading Generated Alarms

#define LOCKSTEP_CONFIG_BASE_ADDR 0x000A0000

int main()
{
//Reading Alarms (ERRCTRL_FNGIALARMS)
unsigned int read_alarm = IORD_32DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD498);

if(!read_alarm) 
{
  printf(“No Alarms”);
} 
else
{
  if(read_alarm&0x1) printf(“Alarm0\n”);
  if(read_alarm&0x2) printf(“Alarm1\n”);
  if(read_alarm&0x4) printf(“Alarm2\n”);
  if(read_alarm&0x8) printf(“Alarm3\n”);
  if(read_alarm&0x10) printf(“Alarm4\n”);
  if(read_alarm&0x10000) printf(“Alarm16\n”);
  if(read_alarm&0x20000) printf(“Alarm17\n”);
  if(read_alarm&0x80000) printf(“Alarm19\n”);
}
}

Reading fRSmartComp State

#define LOCKSTEP_CONFIG_BASE_ADDR 0x000A0000

int main()
{
//Reading fRSmartComp state (ERRCTRL_FNPERIPHGI4)
unsigned int read_state = IORD_32DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD4E4);

switch(read_state)
{
  case 0x1: printf(“DISABLED”); break;
  case 0x2: printf(“OD”); break;
  case 0x4: printf(“FCS”); break;
  default: printf(“This is not expected.”);
}
}

Reading Mismatch Comparator Slices

#define LOCKSTEP_CONFIG_BASE_ADDR 0x000A0000

int main()
{
//Reading Mismatch Comparator Slices (ERRCTRL_FNGICMPCTXT0)
unsigned int read_slice = IORD_32DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD4B0);

if(!read_slice)
{
  printf(“No mismatch”);
}
else
{
  for(int i=0; i<23; i++)
  {
    if(read_slice&0x1) printf(“Mismatch in Slice %d\n”, i);
    read_slice=read_slice/2; 
  }
}
}

Injecting Alarm Faults

#define LOCKSTEP_CONFIG_BASE_ADDR 0x000A0000

int main()
{
/*
 * Before Alarm Fault Injection
 * 1. Read Alarms (Expecting no alarms)
 * 2. Read fRSmartComp state (Expecting OD state)
 */
//Refer to Example 1 Reading Generated Alarms
//Refer to Example 2 Reading fRSmartComp State

/*
 * Start Alarm4 Fault Injection (ERRCTRL_ALARM_INJ)
 */
IOWR_32DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD448, 0x10);

/*
 * After Alarm Fault Injection
 * 1. Read Alarms (Expecting a new Alarm4)
 * 2. Read fRSmartComp state (Expecting OD state)
 */
//Refer to Example 1 Reading Generated Alarms
//Refer to Example 2 Reading fRSmartComp State

/*
 * Stop Alarm4 Fault Injection
 * 1. Read Alarms (Expecting no alarms)
 * 2. Read fRSmartComp state (Expecting OD state)
 */
IOWR_32DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD448, 0x0);
//Refer to Example 1 Reading Generated Alarms
//Refer to Example 2 Reading fRSmartComp State
}

Injecting Root Faults

#define LOCKSTEP_CONFIG_BASE_ADDR 0x000A0000

int main()
{
/*
 * Before Root Fault Injection
 * 1. Read Alarms (Expecting no alarms)
 * 2. Read fRSmartComp state (Expecting OD state)
 * 3. Read mismatch slice (Expecting no mismatch)
 */
//Refer to Example 1 Reading Generated Alarms
//Refer to Example 2 Reading fRSmartComp State
//Refer to Example 3 Reading Mismatch Comparator Slices

/*
 * Configure and Start Root Fault Injection
 * 1. Select BUS_D_CNTRL as target slice (ERRCTRL_PGO0)
 * 2. Inject Comparator Self-detection 
 *     with faulty frSmartComp (ERRCTRL_ROOT_INJ)
 */
IOWR_32DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD460, 0x4);
IOWR_32DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD444, 0x5);

/*
 * After Root Fault Injection
 * 1. Read Alarms (Expecting a new Alarm1, Alarm2, Alarm4)
 * 2. Read fRSmartComp state (Expecting FCS state)
 * 3. Read mismatch slice (Expecting no mismatch, 
 *    and not affected by root fault injection)
 */
//Refer to Example 1 Reading Generated Alarms
//Refer to Example 2 Reading fRSmartComp State
//Refer to Example 3 Reading Mismatch Comparator Slices

/*
 * Stop Root Fault Injection
 * No Effects due to Sticky Faults
 * 1. Read Alarms (Expecting the same Alarm1, Alarm2, Alarm4)
 * 2. Read fRSmartComp state (Expecting the same FCS state)
 * 3. Read mismatch slice (Expecting the same no mismatch)
 */
IOWR_32DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD444, 0x0);
//Refer to Example 1 Reading Generated Alarms
//Refer to Example 2 Reading fRSmartComp State
//Refer to Example 3 Reading Mismatch Comparator Slices

/*
 * Reset Processor to Clear Root Faults
 */
}

Startup Procedure

#define LOCKSTEP_CONFIG_BASE_ADDR 0x000A0000

int main()
{
  /*
   * Enter main() after Nios V processor initialization is successful
   */


  /*
   * Configure fRSmartComp
   * 1. Enable INTREQ generation (ERRCTRL_INTREQ_CONF)
   * 2. Verify no alarm mask (ERRCTRL_MASK*)
   * 3. Check default alarms’ severity (ERRCTRL_ROUT*)
   * 4. Check frSmartComp Enable counter (ERRCTRL_PGO4)
   */
  
  // 1. Enable INTREQ generation for ERROR-type alarm
  IOWR_32DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD420, 0x25);
  
  // 2. Verify no alarm mask
  unsigned int maskA = 
    IORD_32DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD44C)&0xffffff;
  unsigned int maskB = 
    IORD_32DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD450)&0xffffff;
  if((maskA == 0x555555)&&(maskB == 0x555555))
  {
    printf(“All alarms are unmasked.\n”);
  }

  // 3. Check default alarms’ severity 
  unsigned int severityA = 
    IORD_32DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD454)&0xffffff;
  unsigned int severityB = 
    IORD_32DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD458)&0xffffff;
  if((severityA == 0xe8fca8)&&(severityB == 0xaa0000))
  {
    printf(“All alarms are reset to default severity.\n”);
  }

  // 4. Check frSmartComp Enable counter
  unsigned int en_count = 
    IORD_32DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD470)&0xf;
  printf(“System Supervisor can trigger %d fRSmartComp Enable command before
    triggering Alarm17.\n”, en_count+1);


  /*
   * Provide timeout acknowledgment (ERRCTRL_TIMEOUT_ACK)
   * Verify timeout counter stopped (ERRCTRL_TIMEOUT) by 
   * delaying more than timeout period
   * Max timeout period at 100MHz processor clock is 10.44 milliseconds
   */
  IOWR_32DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD428, 0x78A5C3E1);
  IOWR_32DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD428, 0x875A3C1E);
  unsigned char count1 = IORD_8DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD425);
  usleep(10000);
  unsigned char count2 = IORD_8DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD425);
  if(count1 == count2) printf(“Timeout acknowledged.\n”);

/*
   * Disable timeout (ERRCTRL_TIMEOUT)
   * 1. Unlock ERRCTRL_TIMEOUT
   * 2. Verify unlocked status
   * 3. Write new timeout deadline as 0 (Disable)
   * 4. Lock ERRCTRL_TIMEOUT
   */
  IOWR_8DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD427, (0x19<<1));
  unsigned int timeout_csr = 
    IORD_32DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD424);
  printf("Timeout Period = %d\n", timeout_csr&0xff);
  if(timeout_csr&0x01000000) 
  {
    printf(“Unlocked Success.\n”);
  } else
  {
    printf(“Still Locked. Failed to unlock.\n”);
  }
  IOWR_8DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD424, 0);
  IOWR_8DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD427, 0);
  timeout_csr = 
    IORD_32DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD424);
  if(timeout_csr&0x01000000) 
  {
    printf(“Still Unlocked. Failed to lock.\n”);
  } else
  {
    printf(“Locked Success.\n”);
  }
	 timeout_csr = IORD_32DIRECT(LOCKSTEP_CONFIG_BASE_ADDR, 0xD424);
	 printf("Timeout Period = %d\n", timeout_csr&0xff);
	 if((timeout_csr&0xff) == 0) printf("Timeout disabled.\n");

  /*
   * Check no alarms
   * If ALARM0 ~ ALARM4, a mismatch happens during startup.
   * If ALARM16, timeout acknowledgement failed
   * If ALARM19, either wrong key when disabling timeout or internal error
   */
 //Refer to Example 1 Reading Generated Alarms

}