From 99f217daf307b3cd963bcbce8eb7b025d58f734e Mon Sep 17 00:00:00 2001 From: Patrick Williams Date: Tue, 31 Jul 2012 10:26:12 -0500 Subject: Support for master winkle. RTC: 44730 Change-Id: Ifaeecc659e1bfd8ded4744dc591fc993471519ba Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/1471 Tested-by: Jenkins Server Reviewed-by: Mark W. Wenning Reviewed-by: A. Patrick Williams III --- src/build/citest/etc/bbuild | 2 +- src/build/citest/etc/patches/p8.chip.patch | 32 - src/build/citest/etc/patches/p8_inst.act | 1275 +++++++++++++++++++++- src/build/citest/etc/patches/p8_master.por.patch | 17 - src/build/citest/etc/patches/patchlist.txt | 5 +- src/build/citest/etc/workarounds.postsimsetup | 11 +- src/include/arch/ppc.H | 14 +- src/include/kernel/cpu.H | 55 +- src/include/kernel/cpumgr.H | 43 +- src/include/kernel/deferred.H | 201 ++++ src/include/kernel/misc.H | 29 + src/include/kernel/ppcconsts.S | 23 +- src/include/kernel/syscalls.H | 6 +- src/include/sys/misc.h | 3 + src/kernel.ld | 5 +- src/kernel/cpumgr.C | 101 +- src/kernel/deferred.C | 268 +++++ src/kernel/exception.C | 30 +- src/kernel/kernel.C | 47 +- src/kernel/makefile | 8 +- src/kernel/misc.C | 82 +- src/kernel/start.S | 181 ++- src/kernel/syscall.C | 53 +- src/lib/syscall_misc.C | 10 +- src/makefile | 3 +- src/sys/prof/idletask.C | 10 +- src/usr/hwpf/hwp/core_activate/core_activate.C | 9 +- 27 files changed, 2222 insertions(+), 301 deletions(-) delete mode 100644 src/build/citest/etc/patches/p8.chip.patch delete mode 100644 src/build/citest/etc/patches/p8_master.por.patch create mode 100644 src/include/kernel/deferred.H create mode 100644 src/kernel/deferred.C diff --git a/src/build/citest/etc/bbuild b/src/build/citest/etc/bbuild index 91bbd50e7..89125a7b5 100644 --- a/src/build/citest/etc/bbuild +++ b/src/build/citest/etc/bbuild @@ -1 +1 @@ -/esw/fips810/Builds/b0719a_1229.810 +/esw/fips810/Builds/b0727a_1231.810 diff --git a/src/build/citest/etc/patches/p8.chip.patch b/src/build/citest/etc/patches/p8.chip.patch deleted file mode 100644 index cd9227b20..000000000 --- a/src/build/citest/etc/patches/p8.chip.patch +++ /dev/null @@ -1,32 +0,0 @@ - - -##### from src/build/etc/patches/p8_master.por.patch - -ACTIONS=p8_inst.act - -#dc01 -########################## Logical Instruction State ################### -REGSPACE THREADSTATE CHIPLET ex - ### Current State ### - # 0: thread is in POR state - # 1: thread is quiesced - # 2: thread is running - # 3: thread is in maint mode - # 4: thread is active (not in SLEEP or NAP or POR) - # 5: thread is in NAP state - # 6: thread is in SLEEP state - # 7: thread is in WINKLE state - - # One register per thread - 0x0, 32 - 0x1, 32 - 0x2, 32 - 0x3, 32 - 0x4, 32 - 0x5, 32 - 0x6, 32 - 0x7, 32 - -END - -##### end patch diff --git a/src/build/citest/etc/patches/p8_inst.act b/src/build/citest/etc/patches/p8_inst.act index 523acd32b..f9b47ae21 100644 --- a/src/build/citest/etc/patches/p8_inst.act +++ b/src/build/citest/etc/patches/p8_inst.act @@ -2,7 +2,8 @@ # Flag PTR/DCR# Userid Date Description # ---- -------- -------- -------- ----------- -# D841334 dcrowell 06/11/11 File Created +# D841334 dcrowell 06/11/11 File Created +# @01 D846452 dcrowell 07/31/12 Add Winkle/IPI support # Actions work like this: @@ -11,10 +12,6 @@ # # See p8.chip for THREADSTATE bit definitions -#NOTE: Hostboot patched version is hardcoded to Core5 -#NOTE: Hostboot patched version does not set NIA for SRESET - - ################### ## Scom Triggers ## @@ -24,8 +21,8 @@ CAUSE_EFFECT CHIPLETS ex { LABEL=[Sreset Instructions - cXt0] WATCH=[REG(MYCHIPLET,0x013000)] # RAS Control Reg CAUSE: TARGET=[REG(MYCHIPLET,0x013000)] OP=[BIT,ON] BIT=[60] # SRESET - #EFFECT: TARGET=[PROCREG(nia, 5, 0)] OP=[EQUALTO,BUF] DATA=[LITERAL(64,00000000 00000100)] - EFFECT: TARGET=[MODULE(startInstructions, 5, 0)] OP=[MODULECALL] + EFFECT: TARGET=[PROCREG(nia, MYCORE, 0)] OP=[EQUALTO,BUF] DATA=[LITERAL(64,00000000 00000100)] + EFFECT: TARGET=[MODULE(startInstructions, MYCORE, 0)] OP=[MODULECALL] # Clear quiesce, por, maint mode, and all idle states # Set running, active EFFECT: TARGET=[THREADSTATE(MYCHIPLET,0x0)] OP=[EQUALTO,BUF] DATA=[LITERAL(32,28000000)] @@ -36,8 +33,8 @@ CAUSE_EFFECT CHIPLETS ex { LABEL=[Sreset Instructions - cXt1] WATCH=[REG(MYCHIPLET,0x013010)] # RAS Control Reg CAUSE: TARGET=[REG(MYCHIPLET,0x013010)] OP=[BIT,ON] BIT=[60] # SRESET - #EFFECT: TARGET=[PROCREG(nia, 5, 1)] OP=[EQUALTO,BUF] DATA=[LITERAL(64,00000000 00000100)] - EFFECT: TARGET=[MODULE(startInstructions, 5, 1)] OP=[MODULECALL] # Start Hostboot + EFFECT: TARGET=[PROCREG(nia, MYCORE, 1)] OP=[EQUALTO,BUF] DATA=[LITERAL(64,00000000 00000100)] + EFFECT: TARGET=[MODULE(startInstructions, MYCORE, 1)] OP=[MODULECALL] # Start Hostboot # Clear quiesce, por, maint mode, and all idle states # Set running, active EFFECT: TARGET=[THREADSTATE(MYCHIPLET,0x1)] OP=[EQUALTO,BUF] DATA=[LITERAL(32,28000000)] @@ -48,8 +45,8 @@ CAUSE_EFFECT CHIPLETS ex { LABEL=[Sreset Instructions - cXt2] WATCH=[REG(MYCHIPLET,0x013020)] # RAS Control Reg CAUSE: TARGET=[REG(MYCHIPLET,0x013020)] OP=[BIT,ON] BIT=[60] # SRESET - #EFFECT: TARGET=[PROCREG(nia, 5, 2)] OP=[EQUALTO,BUF] DATA=[LITERAL(64,00000000 00000100)] - EFFECT: TARGET=[MODULE(startInstructions, 5, 2)] OP=[MODULECALL] # Start Hostboot + EFFECT: TARGET=[PROCREG(nia, MYCORE, 2)] OP=[EQUALTO,BUF] DATA=[LITERAL(64,00000000 00000100)] + EFFECT: TARGET=[MODULE(startInstructions, MYCORE, 2)] OP=[MODULECALL] # Start Hostboot # Clear quiesce, por, maint mode, and all idle states # Set running, active EFFECT: TARGET=[THREADSTATE(MYCHIPLET,0x2)] OP=[EQUALTO,BUF] DATA=[LITERAL(32,28000000)] @@ -60,8 +57,8 @@ CAUSE_EFFECT CHIPLETS ex { LABEL=[Sreset Instructions - cXt3] WATCH=[REG(MYCHIPLET,0x013030)] # RAS Control Reg CAUSE: TARGET=[REG(MYCHIPLET,0x013030)] OP=[BIT,ON] BIT=[60] # SRESET - #EFFECT: TARGET=[PROCREG(nia, 5, 3)] OP=[EQUALTO,BUF] DATA=[LITERAL(64,00000000 00000100)] - EFFECT: TARGET=[MODULE(startInstructions, 5, 3)] OP=[MODULECALL] # Start Hostboot + EFFECT: TARGET=[PROCREG(nia, MYCORE, 3)] OP=[EQUALTO,BUF] DATA=[LITERAL(64,00000000 00000100)] + EFFECT: TARGET=[MODULE(startInstructions, MYCORE, 3)] OP=[MODULECALL] # Start Hostboot # Clear quiesce, por, maint mode, and all idle states # Set running, active EFFECT: TARGET=[THREADSTATE(MYCHIPLET,0x3)] OP=[EQUALTO,BUF] DATA=[LITERAL(32,28000000)] @@ -72,8 +69,8 @@ CAUSE_EFFECT CHIPLETS ex { LABEL=[Sreset Instructions - cXt4] WATCH=[REG(MYCHIPLET,0x013040)] # RAS Control Reg CAUSE: TARGET=[REG(MYCHIPLET,0x013040)] OP=[BIT,ON] BIT=[60] # SRESET - #EFFECT: TARGET=[PROCREG(nia, 5, 4)] OP=[EQUALTO,BUF] DATA=[LITERAL(64,00000000 00000100)] - EFFECT: TARGET=[MODULE(startInstructions, 5, 4)] OP=[MODULECALL] # Start Hostboot + EFFECT: TARGET=[PROCREG(nia, MYCORE, 4)] OP=[EQUALTO,BUF] DATA=[LITERAL(64,00000000 00000100)] + EFFECT: TARGET=[MODULE(startInstructions, MYCORE, 4)] OP=[MODULECALL] # Start Hostboot # Clear quiesce, por, maint mode, and all idle states # Set running, active EFFECT: TARGET=[THREADSTATE(MYCHIPLET,0x4)] OP=[EQUALTO,BUF] DATA=[LITERAL(32,28000000)] @@ -84,8 +81,8 @@ CAUSE_EFFECT CHIPLETS ex { LABEL=[Sreset Instructions - cXt5] WATCH=[REG(MYCHIPLET,0x013050)] # RAS Control Reg CAUSE: TARGET=[REG(MYCHIPLET,0x013050)] OP=[BIT,ON] BIT=[60] # SRESET - #EFFECT: TARGET=[PROCREG(nia, 5, 5)] OP=[EQUALTO,BUF] DATA=[LITERAL(64,00000000 00000100)] - EFFECT: TARGET=[MODULE(startInstructions, 5, 5)] OP=[MODULECALL] # Start Hostboot + EFFECT: TARGET=[PROCREG(nia, MYCORE, 5)] OP=[EQUALTO,BUF] DATA=[LITERAL(64,00000000 00000100)] + EFFECT: TARGET=[MODULE(startInstructions, MYCORE, 5)] OP=[MODULECALL] # Start Hostboot # Clear quiesce, por, maint mode, and all idle states # Set running, active EFFECT: TARGET=[THREADSTATE(MYCHIPLET,0x5)] OP=[EQUALTO,BUF] DATA=[LITERAL(32,28000000)] @@ -96,8 +93,8 @@ CAUSE_EFFECT CHIPLETS ex { LABEL=[Sreset Instructions - cXt6] WATCH=[REG(MYCHIPLET,0x013060)] # RAS Control Reg CAUSE: TARGET=[REG(MYCHIPLET,0x013060)] OP=[BIT,ON] BIT=[60] # SRESET - #EFFECT: TARGET=[PROCREG(nia, 5, 6)] OP=[EQUALTO,BUF] DATA=[LITERAL(64,00000000 00000100)] - EFFECT: TARGET=[MODULE(startInstructions, 5, 6)] OP=[MODULECALL] # Start Hostboot + EFFECT: TARGET=[PROCREG(nia, MYCORE, 6)] OP=[EQUALTO,BUF] DATA=[LITERAL(64,00000000 00000100)] + EFFECT: TARGET=[MODULE(startInstructions, MYCORE, 6)] OP=[MODULECALL] # Start Hostboot # Clear quiesce, por, maint mode, and all idle states # Set running, active EFFECT: TARGET=[THREADSTATE(MYCHIPLET,0x6)] OP=[EQUALTO,BUF] DATA=[LITERAL(32,28000000)] @@ -108,8 +105,8 @@ CAUSE_EFFECT CHIPLETS ex { LABEL=[Sreset Instructions - cXt7] WATCH=[REG(MYCHIPLET,0x013070)] # RAS Control Reg CAUSE: TARGET=[REG(MYCHIPLET,0x013070)] OP=[BIT,ON] BIT=[60] # SRESET - #EFFECT: TARGET=[PROCREG(nia, 5, 7)] OP=[EQUALTO,BUF] DATA=[LITERAL(64,00000000 00000100)] - EFFECT: TARGET=[MODULE(startInstructions, 5, 7)] OP=[MODULECALL] # Start Hostboot + EFFECT: TARGET=[PROCREG(nia, MYCORE, 7)] OP=[EQUALTO,BUF] DATA=[LITERAL(64,00000000 00000100)] + EFFECT: TARGET=[MODULE(startInstructions, MYCORE, 7)] OP=[MODULECALL] # Start Hostboot # Clear quiesce, por, maint mode, and all idle states # Set running, active EFFECT: TARGET=[THREADSTATE(MYCHIPLET,0x7)] OP=[EQUALTO,BUF] DATA=[LITERAL(32,28000000)] @@ -123,7 +120,7 @@ CAUSE_EFFECT CHIPLETS ex { LABEL=[Start Instructions - cXt0] WATCH=[REG(MYCHIPLET,0x013000)] # RAS Control Reg CAUSE: TARGET=[REG(MYCHIPLET,0x013000)] OP=[BIT,ON] BIT=[62] # Start - EFFECT: TARGET=[MODULE(startInstructions, 5, 0)] OP=[MODULECALL] + EFFECT: TARGET=[MODULE(startInstructions, MYCORE, 0)] OP=[MODULECALL] # Clear quiesce, por, maint mode # Set running # Leave other bits alone @@ -135,7 +132,7 @@ CAUSE_EFFECT CHIPLETS ex { LABEL=[Start Instructions - cXt1] WATCH=[REG(MYCHIPLET,0x013010)] # RAS Control Reg CAUSE: TARGET=[REG(MYCHIPLET,0x013010)] OP=[BIT,ON] BIT=[62] # Start - EFFECT: TARGET=[MODULE(startInstructions, 5, 1)] OP=[MODULECALL] # Start Hostboot + EFFECT: TARGET=[MODULE(startInstructions, MYCORE, 1)] OP=[MODULECALL] # Start Hostboot # Clear quiesce, por, maint mode # Set running # Leave other bits alone @@ -147,7 +144,7 @@ CAUSE_EFFECT CHIPLETS ex { LABEL=[Start Instructions - cXt2] WATCH=[REG(MYCHIPLET,0x013020)] # RAS Control Reg CAUSE: TARGET=[REG(MYCHIPLET,0x013020)] OP=[BIT,ON] BIT=[62] # Start - EFFECT: TARGET=[MODULE(startInstructions, 5, 2)] OP=[MODULECALL] # Start Hostboot + EFFECT: TARGET=[MODULE(startInstructions, MYCORE, 2)] OP=[MODULECALL] # Start Hostboot # Clear quiesce, por, maint mode # Set running # Leave other bits alone @@ -159,7 +156,7 @@ CAUSE_EFFECT CHIPLETS ex { LABEL=[Start Instructions - cXt3] WATCH=[REG(MYCHIPLET,0x013030)] # RAS Control Reg CAUSE: TARGET=[REG(MYCHIPLET,0x013030)] OP=[BIT,ON] BIT=[62] # Start - EFFECT: TARGET=[MODULE(startInstructions, 5, 3)] OP=[MODULECALL] # Start Hostboot + EFFECT: TARGET=[MODULE(startInstructions, MYCORE, 3)] OP=[MODULECALL] # Start Hostboot # Clear quiesce, por, maint mode # Set running # Leave other bits alone @@ -171,7 +168,7 @@ CAUSE_EFFECT CHIPLETS ex { LABEL=[Start Instructions - cXt4] WATCH=[REG(MYCHIPLET,0x013040)] # RAS Control Reg CAUSE: TARGET=[REG(MYCHIPLET,0x013040)] OP=[BIT,ON] BIT=[62] # Start - EFFECT: TARGET=[MODULE(startInstructions, 5, 4)] OP=[MODULECALL] # Start Hostboot + EFFECT: TARGET=[MODULE(startInstructions, MYCORE, 4)] OP=[MODULECALL] # Start Hostboot # Clear quiesce, por, maint mode # Set running # Leave other bits alone @@ -183,7 +180,7 @@ CAUSE_EFFECT CHIPLETS ex { LABEL=[Start Instructions - cXt5] WATCH=[REG(MYCHIPLET,0x013050)] # RAS Control Reg CAUSE: TARGET=[REG(MYCHIPLET,0x013050)] OP=[BIT,ON] BIT=[62] # Start - EFFECT: TARGET=[MODULE(startInstructions, 5, 5)] OP=[MODULECALL] # Start Hostboot + EFFECT: TARGET=[MODULE(startInstructions, MYCORE, 5)] OP=[MODULECALL] # Start Hostboot # Clear quiesce, por, maint mode # Set running # Leave other bits alone @@ -195,7 +192,7 @@ CAUSE_EFFECT CHIPLETS ex { LABEL=[Start Instructions - cXt6] WATCH=[REG(MYCHIPLET,0x013062)] # RAS Control Reg CAUSE: TARGET=[REG(MYCHIPLET,0x013062)] OP=[BIT,ON] BIT=[62] # Start - EFFECT: TARGET=[MODULE(startInstructions, 5, 6)] OP=[MODULECALL] # Start Hostboot + EFFECT: TARGET=[MODULE(startInstructions, MYCORE, 6)] OP=[MODULECALL] # Start Hostboot # Clear quiesce, por, maint mode # Set running # Leave other bits alone @@ -207,7 +204,7 @@ CAUSE_EFFECT CHIPLETS ex { LABEL=[Start Instructions - cXt7] WATCH=[REG(MYCHIPLET,0x013070)] # RAS Control Reg CAUSE: TARGET=[REG(MYCHIPLET,0x013070)] OP=[BIT,ON] BIT=[62] # Start - EFFECT: TARGET=[MODULE(startInstructions, 5, 7)] OP=[MODULECALL] # Start Hostboot + EFFECT: TARGET=[MODULE(startInstructions, MYCORE, 7)] OP=[MODULECALL] # Start Hostboot # Clear quiesce, por, maint mode # Set running # Leave other bits alone @@ -583,3 +580,1223 @@ CAUSE_EFFECT CHIPLETS ex { ELSE: TARGET=[REG(MYCHIPLET,0x013072)] OP=[BIT,OFF] BIT=[21] #core_is_in_maintenance_mode } +#@01 begin +##### Winkle ##### +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Winkle - cXt0] + WATCH=[THREADSTATE(MYCHIPLET,0x0)] + WATCH=[REG(MYCHIPLET,0x013004)] + # active=0,nap=0,sleep=0,winkle=1 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x0)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,01000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=11, 23:25=111 + EFFECT: TARGET=[REG(MYCHIPLET,0x013004)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,0C0001C0 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Winkle - cXt1] + WATCH=[THREADSTATE(MYCHIPLET,0x1)] + WATCH=[REG(MYCHIPLET,0x013014)] + # active=0,nap=0,sleep=0,winkle=1 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x1)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,01000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=11, 23:25=111 + EFFECT: TARGET=[REG(MYCHIPLET,0x013014)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,0C0001C0 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Winkle - cXt2] + WATCH=[THREADSTATE(MYCHIPLET,0x2)] + WATCH=[REG(MYCHIPLET,0x013024)] + # active=0,nap=0,sleep=0,winkle=1 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x2)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,01000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=11, 23:25=111 + EFFECT: TARGET=[REG(MYCHIPLET,0x013024)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,0C0001C0 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Winkle - cXt3] + WATCH=[THREADSTATE(MYCHIPLET,0x3)] + WATCH=[REG(MYCHIPLET,0x013034)] + # active=0,nap=0,sleep=0,winkle=1 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x3)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,01000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=11, 23:25=111 + EFFECT: TARGET=[REG(MYCHIPLET,0x013034)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,0C0001C0 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Winkle - cXt4] + WATCH=[THREADSTATE(MYCHIPLET,0x4)] + WATCH=[REG(MYCHIPLET,0x013044)] + # active=0,nap=0,sleep=0,winkle=1 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x4)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,01000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=11, 23:25=111 + EFFECT: TARGET=[REG(MYCHIPLET,0x013044)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,0C0001C0 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Winkle - cXt5] + WATCH=[THREADSTATE(MYCHIPLET,0x5)] + WATCH=[REG(MYCHIPLET,0x013054)] + # active=0,nap=0,sleep=0,winkle=1 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x5)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,01000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=11, 23:25=111 + EFFECT: TARGET=[REG(MYCHIPLET,0x013054)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,0C0001C0 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Winkle - cXt6] + WATCH=[THREADSTATE(MYCHIPLET,0x6)] + WATCH=[REG(MYCHIPLET,0x013064)] + # active=0,nap=0,sleep=0,winkle=1 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x6)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,01000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=11, 23:25=111 + EFFECT: TARGET=[REG(MYCHIPLET,0x013064)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,0C0001C0 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Winkle - cXt7] + WATCH=[THREADSTATE(MYCHIPLET,0x7)] + WATCH=[REG(MYCHIPLET,0x013074)] + # active=0,nap=0,sleep=0,winkle=1 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x7)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,01000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=11, 23:25=111 + EFFECT: TARGET=[REG(MYCHIPLET,0x013074)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,0C0001C0 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} + +##### Sleep ##### +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Sleep - cXt0] + WATCH=[THREADSTATE(MYCHIPLET,0x0)] + WATCH=[REG(MYCHIPLET,0x013004)] + # active=0,nap=0,sleep=1,winkle=0 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x0)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,02000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=11, 23:25=110 + EFFECT: TARGET=[REG(MYCHIPLET,0x013004)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,0C000180 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Sleep - cXt1] + WATCH=[THREADSTATE(MYCHIPLET,0x1)] + WATCH=[REG(MYCHIPLET,0x013014)] + # active=0,nap=0,sleep=1,winkle=0 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x1)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,02000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=11, 23:25=110 + EFFECT: TARGET=[REG(MYCHIPLET,0x013014)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,0C000180 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Sleep - cXt2] + WATCH=[THREADSTATE(MYCHIPLET,0x2)] + WATCH=[REG(MYCHIPLET,0x013024)] + # active=0,nap=0,sleep=1,winkle=0 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x2)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,02000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=11, 23:25=110 + EFFECT: TARGET=[REG(MYCHIPLET,0x013024)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,0C000180 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Sleep - cXt3] + WATCH=[THREADSTATE(MYCHIPLET,0x3)] + WATCH=[REG(MYCHIPLET,0x013034)] + # active=0,nap=0,sleep=1,winkle=0 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x3)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,02000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=11, 23:25=110 + EFFECT: TARGET=[REG(MYCHIPLET,0x013034)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,0C000180 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Sleep - cXt4] + WATCH=[THREADSTATE(MYCHIPLET,0x4)] + WATCH=[REG(MYCHIPLET,0x013044)] + # active=0,nap=0,sleep=1,winkle=0 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x4)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,02000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=11, 23:25=110 + EFFECT: TARGET=[REG(MYCHIPLET,0x013044)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,0C000180 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Sleep - cXt5] + WATCH=[THREADSTATE(MYCHIPLET,0x5)] + WATCH=[REG(MYCHIPLET,0x013054)] + # active=0,nap=0,sleep=1,winkle=0 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x5)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,02000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=11, 23:25=110 + EFFECT: TARGET=[REG(MYCHIPLET,0x013054)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,0C000180 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Sleep - cXt6] + WATCH=[THREADSTATE(MYCHIPLET,0x6)] + WATCH=[REG(MYCHIPLET,0x013064)] + # active=0,nap=0,sleep=1,winkle=0 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x6)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,02000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=11, 23:25=110 + EFFECT: TARGET=[REG(MYCHIPLET,0x013064)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,0C000180 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Sleep - cXt7] + WATCH=[THREADSTATE(MYCHIPLET,0x7)] + WATCH=[REG(MYCHIPLET,0x013074)] + # active=0,nap=0,sleep=1,winkle=0 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x7)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,02000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=11, 23:25=110 + EFFECT: TARGET=[REG(MYCHIPLET,0x013074)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,0C000180 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} + +##### Active ##### + +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Active - cXt0] + WATCH=[THREADSTATE(MYCHIPLET,0x0)] + WATCH=[REG(MYCHIPLET,0x013004)] + # active=1,nap=0,sleep=0,winkle=0 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x0)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,08000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=00, 23:25=000 + EFFECT: TARGET=[REG(MYCHIPLET,0x013004)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,00000000 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Active - cXt1] + WATCH=[THREADSTATE(MYCHIPLET,0x1)] + WATCH=[REG(MYCHIPLET,0x013014)] + # active=1,nap=0,sleep=0,winkle=0 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x1)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,08000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=00, 23:25=000 + EFFECT: TARGET=[REG(MYCHIPLET,0x013014)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,00000000 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Active - cXt2] + WATCH=[THREADSTATE(MYCHIPLET,0x2)] + WATCH=[REG(MYCHIPLET,0x013024)] + # active=1,nap=0,sleep=0,winkle=0 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x2)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,08000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=00, 23:25=000 + EFFECT: TARGET=[REG(MYCHIPLET,0x013024)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,00000000 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Active - cXt3] + WATCH=[THREADSTATE(MYCHIPLET,0x3)] + WATCH=[REG(MYCHIPLET,0x013034)] + # active=1,nap=0,sleep=0,winkle=0 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x3)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,08000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=00, 23:25=000 + EFFECT: TARGET=[REG(MYCHIPLET,0x013034)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,00000000 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Active - cXt4] + WATCH=[THREADSTATE(MYCHIPLET,0x4)] + WATCH=[REG(MYCHIPLET,0x013044)] + # active=1,nap=0,sleep=0,winkle=0 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x4)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,08000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=00, 23:25=000 + EFFECT: TARGET=[REG(MYCHIPLET,0x013044)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,00000000 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Active - cXt5] + WATCH=[THREADSTATE(MYCHIPLET,0x5)] + WATCH=[REG(MYCHIPLET,0x013054)] + # active=1,nap=0,sleep=0,winkle=0 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x5)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,08000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=00, 23:25=000 + EFFECT: TARGET=[REG(MYCHIPLET,0x013054)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,00000000 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Active - cXt6] + WATCH=[THREADSTATE(MYCHIPLET,0x6)] + WATCH=[REG(MYCHIPLET,0x013064)] + # active=1,nap=0,sleep=0,winkle=0 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x6)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,08000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=00, 23:25=000 + EFFECT: TARGET=[REG(MYCHIPLET,0x013064)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,00000000 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Status - Active - cXt7] + WATCH=[THREADSTATE(MYCHIPLET,0x7)] + WATCH=[REG(MYCHIPLET,0x013074)] + # active=1,nap=0,sleep=0,winkle=0 + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x7)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,08000000)] MASK=[LITERAL(32,0F000000)] + # 4:5=00, 23:25=000 + EFFECT: TARGET=[REG(MYCHIPLET,0x013074)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,00000000 00000000)] MASK=[LITERAL(64,0C0001C0 00000000)] +} + + +################### +## HAP Triggers ## + +# HAP Actions work like this: +# Simics sets bits in HAP regs (below) +# Action will set status bit in THREADSTATE +# Changes to THREADSTATE regspace will update status bits in Scom regs + +# Each bit represents the state of a given core/thread, and the bit +# position is computed as: +# +# bit = core * threadsPerCore + thread +# +#0xFF000020, 64 # ADDR_LOGIC_THREAD_BREAKPOINT +#0xFF000030, 64 # ADDR_LOGIC_THREAD_NAP +#0xFF000040, 64 # ADDR_LOGIC_THREAD_SLEEP +#0xFF000050, 64 # ADDR_LOGIC_THREAD_SRESET +#0xFF000060, 64 # ADDR_LOGIC_THREAD_WINKLE + +#### Winkle #### +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c1t0] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[8] + EFFECT: TARGET=[THREADSTATE(0x11000000)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x11000000)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c1t1] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[9] + EFFECT: TARGET=[THREADSTATE(0x11000001)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x11000001)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c1t2] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[10] + EFFECT: TARGET=[THREADSTATE(0x11000002)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x11000002)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c1t3] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[11] + EFFECT: TARGET=[THREADSTATE(0x11000003)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x11000003)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c1t4] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[12] + EFFECT: TARGET=[THREADSTATE(0x11000004)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x11000004)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c1t5] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[13] + EFFECT: TARGET=[THREADSTATE(0x11000005)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x11000005)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c1t6] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[14] + EFFECT: TARGET=[THREADSTATE(0x11000006)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x11000006)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c1t7] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[15] + EFFECT: TARGET=[THREADSTATE(0x11000007)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x11000007)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c2t0] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[16] + EFFECT: TARGET=[THREADSTATE(0x12000000)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x12000000)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c2t1] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[17] + EFFECT: TARGET=[THREADSTATE(0x12000001)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x12000001)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c2t2] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[18] + EFFECT: TARGET=[THREADSTATE(0x12000002)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x12000002)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c2t3] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[19] + EFFECT: TARGET=[THREADSTATE(0x12000003)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x12000003)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c2t4] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[20] + EFFECT: TARGET=[THREADSTATE(0x12000004)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x12000004)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c2t5] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[21] + EFFECT: TARGET=[THREADSTATE(0x12000005)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x12000005)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c2t6] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[22] + EFFECT: TARGET=[THREADSTATE(0x12000006)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x12000006)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c2t7] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[23] + EFFECT: TARGET=[THREADSTATE(0x12000007)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x12000007)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c3t0] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[24] + EFFECT: TARGET=[THREADSTATE(0x13000000)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x13000000)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c3t1] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[25] + EFFECT: TARGET=[THREADSTATE(0x13000001)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x13000001)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c3t2] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[26] + EFFECT: TARGET=[THREADSTATE(0x13000002)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x13000002)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c3t3] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[27] + EFFECT: TARGET=[THREADSTATE(0x13000003)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x13000003)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c3t4] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[28] + EFFECT: TARGET=[THREADSTATE(0x13000004)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x13000004)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c3t5] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[29] + EFFECT: TARGET=[THREADSTATE(0x13000005)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x13000005)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c3t6] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[30] + EFFECT: TARGET=[THREADSTATE(0x13000006)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x13000006)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c3t7] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[31] + EFFECT: TARGET=[THREADSTATE(0x13000007)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x13000007)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c4t0] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[32] + EFFECT: TARGET=[THREADSTATE(0x14000000)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x14000000)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c4t1] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[33] + EFFECT: TARGET=[THREADSTATE(0x14000001)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x14000001)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c4t2] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[34] + EFFECT: TARGET=[THREADSTATE(0x14000002)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x14000002)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c4t3] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[35] + EFFECT: TARGET=[THREADSTATE(0x14000003)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x14000003)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c4t4] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[36] + EFFECT: TARGET=[THREADSTATE(0x14000004)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x14000004)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c4t5] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[37] + EFFECT: TARGET=[THREADSTATE(0x14000005)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x14000005)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c4t6] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[38] + EFFECT: TARGET=[THREADSTATE(0x14000006)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x14000006)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c4t7] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[39] + EFFECT: TARGET=[THREADSTATE(0x14000007)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x14000007)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c5t0] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[40] + EFFECT: TARGET=[THREADSTATE(0x15000000)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x15000000)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c5t1] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[41] + EFFECT: TARGET=[THREADSTATE(0x15000001)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x15000001)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c5t2] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[42] + EFFECT: TARGET=[THREADSTATE(0x15000002)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x15000002)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c5t3] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[43] + EFFECT: TARGET=[THREADSTATE(0x15000003)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x15000003)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c5t4] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[44] + EFFECT: TARGET=[THREADSTATE(0x15000004)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x15000004)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c5t5] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[45] + EFFECT: TARGET=[THREADSTATE(0x15000005)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x15000005)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c5t6] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[46] + EFFECT: TARGET=[THREADSTATE(0x15000006)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x15000006)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c5t7] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[47] + EFFECT: TARGET=[THREADSTATE(0x15000007)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x15000007)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c6t0] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[48] + EFFECT: TARGET=[THREADSTATE(0x16000000)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x16000000)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c6t1] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[49] + EFFECT: TARGET=[THREADSTATE(0x16000001)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x16000001)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c6t2] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[50] + EFFECT: TARGET=[THREADSTATE(0x16000002)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x16000002)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c6t3] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[51] + EFFECT: TARGET=[THREADSTATE(0x16000003)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x16000003)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c6t4] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[52] + EFFECT: TARGET=[THREADSTATE(0x16000004)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x16000004)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c6t5] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[53] + EFFECT: TARGET=[THREADSTATE(0x16000005)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x16000005)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c6t6] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[54] + EFFECT: TARGET=[THREADSTATE(0x16000006)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x16000006)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} +CAUSE_EFFECT { + LABEL=[HAP - Winkle - c6t7] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[55] + EFFECT: TARGET=[THREADSTATE(0x16000007)] OP=[BIT,ON] BIT=[7] #winkle=1 + ELSE: TARGET=[THREADSTATE(0x16000007)] OP=[BIT,OFF] BIT=[7] #winkle=0 +} + + +#### Active #### +CAUSE_EFFECT { + LABEL=[HAP - Active - c1t0] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[8] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[8] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[8] #no sleep + EFFECT: TARGET=[THREADSTATE(0x11000000)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x11000000)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c1t1] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[9] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[9] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[9] #no sleep + EFFECT: TARGET=[THREADSTATE(0x11000001)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x11000001)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c1t2] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[10] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[10] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[10] #no sleep + EFFECT: TARGET=[THREADSTATE(0x11000002)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x11000002)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c1t3] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[11] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[11] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[11] #no sleep + EFFECT: TARGET=[THREADSTATE(0x11000003)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x11000003)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c1t4] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[12] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[12] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[12] #no sleep + EFFECT: TARGET=[THREADSTATE(0x11000004)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x11000004)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c1t5] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[13] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[13] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[13] #no sleep + EFFECT: TARGET=[THREADSTATE(0x11000005)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x11000005)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c1t6] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[14] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[14] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[14] #no sleep + EFFECT: TARGET=[THREADSTATE(0x11000006)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x11000006)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c1t7] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[15] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[15] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[15] #no sleep + EFFECT: TARGET=[THREADSTATE(0x11000007)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x11000007)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c2t0] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[16] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[16] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[16] #no sleep + EFFECT: TARGET=[THREADSTATE(0x12000000)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x12000000)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c2t1] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[17] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[17] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[17] #no sleep + EFFECT: TARGET=[THREADSTATE(0x12000001)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x12000001)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c2t2] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[18] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[18] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[18] #no sleep + EFFECT: TARGET=[THREADSTATE(0x12000002)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x12000002)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c2t3] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[19] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[19] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[19] #no sleep + EFFECT: TARGET=[THREADSTATE(0x12000003)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x12000003)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c2t4] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[20] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[20] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[20] #no sleep + EFFECT: TARGET=[THREADSTATE(0x12000004)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x12000004)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c2t5] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[21] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[21] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[21] #no sleep + EFFECT: TARGET=[THREADSTATE(0x12000005)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x12000005)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c2t6] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[22] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[22] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[22] #no sleep + EFFECT: TARGET=[THREADSTATE(0x12000006)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x12000006)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c2t7] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[23] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[23] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[23] #no sleep + EFFECT: TARGET=[THREADSTATE(0x12000007)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x12000007)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c3t0] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[24] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[24] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[24] #no sleep + EFFECT: TARGET=[THREADSTATE(0x13000000)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x13000000)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c3t1] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[25] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[25] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[25] #no sleep + EFFECT: TARGET=[THREADSTATE(0x13000001)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x13000001)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c3t2] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[26] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[26] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[26] #no sleep + EFFECT: TARGET=[THREADSTATE(0x13000002)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x13000002)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c3t3] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[27] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[27] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[27] #no sleep + EFFECT: TARGET=[THREADSTATE(0x13000003)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x13000003)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c3t4] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[28] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[28] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[28] #no sleep + EFFECT: TARGET=[THREADSTATE(0x13000004)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x13000004)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c3t5] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[29] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[29] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[29] #no sleep + EFFECT: TARGET=[THREADSTATE(0x13000005)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x13000005)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c3t6] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[30] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[30] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[30] #no sleep + EFFECT: TARGET=[THREADSTATE(0x13000006)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x13000006)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c3t7] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[31] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[31] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[31] #no sleep + EFFECT: TARGET=[THREADSTATE(0x13000007)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x13000007)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c4t0] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[32] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[32] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[32] #no sleep + EFFECT: TARGET=[THREADSTATE(0x14000000)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x14000000)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c4t1] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[33] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[33] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[33] #no sleep + EFFECT: TARGET=[THREADSTATE(0x14000001)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x14000001)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c4t2] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[34] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[34] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[34] #no sleep + EFFECT: TARGET=[THREADSTATE(0x14000002)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x14000002)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c4t3] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[35] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[35] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[35] #no sleep + EFFECT: TARGET=[THREADSTATE(0x14000003)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x14000003)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c4t4] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[36] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[36] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[36] #no sleep + EFFECT: TARGET=[THREADSTATE(0x14000004)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x14000004)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c4t5] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[37] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[37] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[37] #no sleep + EFFECT: TARGET=[THREADSTATE(0x14000005)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x14000005)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c4t6] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[38] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[38] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[38] #no sleep + EFFECT: TARGET=[THREADSTATE(0x14000006)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x14000006)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c4t7] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[39] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[39] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[39] #no sleep + EFFECT: TARGET=[THREADSTATE(0x14000007)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x14000007)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c5t0] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[40] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[40] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[40] #no sleep + EFFECT: TARGET=[THREADSTATE(0x15000000)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x15000000)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c5t1] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[41] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[41] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[41] #no sleep + EFFECT: TARGET=[THREADSTATE(0x15000001)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x15000001)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c5t2] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[42] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[42] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[42] #no sleep + EFFECT: TARGET=[THREADSTATE(0x15000002)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x15000002)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c5t3] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[43] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[43] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[43] #no sleep + EFFECT: TARGET=[THREADSTATE(0x15000003)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x15000003)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c5t4] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[44] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[44] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[44] #no sleep + EFFECT: TARGET=[THREADSTATE(0x15000004)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x15000004)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c5t5] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[45] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[45] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[45] #no sleep + EFFECT: TARGET=[THREADSTATE(0x15000005)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x15000005)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c5t6] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[46] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[46] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[46] #no sleep + EFFECT: TARGET=[THREADSTATE(0x15000006)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x15000006)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c5t7] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[47] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[47] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[47] #no sleep + EFFECT: TARGET=[THREADSTATE(0x15000007)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x15000007)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c6t0] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[48] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[48] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[48] #no sleep + EFFECT: TARGET=[THREADSTATE(0x16000000)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x16000000)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c6t1] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[49] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[49] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[49] #no sleep + EFFECT: TARGET=[THREADSTATE(0x16000001)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x16000001)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c6t2] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[50] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[50] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[50] #no sleep + EFFECT: TARGET=[THREADSTATE(0x16000002)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x16000002)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c6t3] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[51] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[51] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[51] #no sleep + EFFECT: TARGET=[THREADSTATE(0x16000003)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x16000003)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c6t4] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[52] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[52] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[52] #no sleep + EFFECT: TARGET=[THREADSTATE(0x16000004)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x16000004)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c6t5] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[53] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[53] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[53] #no sleep + EFFECT: TARGET=[THREADSTATE(0x16000005)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x16000005)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c6t6] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[54] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[54] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[54] #no sleep + EFFECT: TARGET=[THREADSTATE(0x16000006)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x16000006)] OP=[BIT,OFF] BIT=[4] #active=0 +} + +CAUSE_EFFECT { + LABEL=[HAP - Active - c6t7] + WATCH=[LOGIC(0xFF000030)] + WATCH=[LOGIC(0xFF000050)] + WATCH=[LOGIC(0xFF000060)] + CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,OFF] BIT=[55] #no winkle + CAUSE: TARGET=[LOGIC(0xFF000030)] OP=[BIT,OFF] BIT=[55] #no nap + CAUSE: TARGET=[LOGIC(0xFF000050)] OP=[BIT,OFF] BIT=[55] #no sleep + EFFECT: TARGET=[THREADSTATE(0x16000007)] OP=[BIT,ON] BIT=[4] #active=1 + ELSE: TARGET=[THREADSTATE(0x16000007)] OP=[BIT,OFF] BIT=[4] #active=0 +} + + + +#### Sreset #### +#CAUSE_EFFECT { +# LABEL=[HAP - Sreset - c5t0] +# WATCH=[LOGIC(0xFF000050)] +# CAUSE: TARGET=[LOGIC(0xFF000060)] OP=[BIT,ON] BIT=[40] #c5t0 +# EFFECT: TARGET=[THREADSTATE(0x15000000)] OP=[BIT,ON] BIT=[4] #active=1 +# EFFECT: TARGET=[THREADSTATE(0x15000000)] OP=[BIT,OFF] BIT=[5] #nap=0 +# EFFECT: TARGET=[THREADSTATE(0x15000000)] OP=[BIT,OFF] BIT=[6] #sleep=0 +# EFFECT: TARGET=[THREADSTATE(0x15000000)] OP=[BIT,OFF] BIT=[7] #winkle=0 +#} + +########################################## +# SBE Master Winkle Wakeup +CAUSE_EFFECT CHIPLETS ex { + LABEL=[Master Winkle Wakeup] + WATCH=[THREADSTATE(MYCHIPLET,0x0)] + WATCH=[THREADSTATE(MYCHIPLET,0x1)] + WATCH=[THREADSTATE(MYCHIPLET,0x2)] + WATCH=[THREADSTATE(MYCHIPLET,0x3)] + WATCH=[THREADSTATE(MYCHIPLET,0x4)] + WATCH=[THREADSTATE(MYCHIPLET,0x5)] + WATCH=[THREADSTATE(MYCHIPLET,0x6)] + WATCH=[THREADSTATE(MYCHIPLET,0x7)] + # active=0,nap=0,sleep=0,winkle=1 on all 8 threads + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x0)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,01000000)] MASK=[LITERAL(32,0F000000)] + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x1)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,01000000)] MASK=[LITERAL(32,0F000000)] + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x2)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,01000000)] MASK=[LITERAL(32,0F000000)] + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x3)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,01000000)] MASK=[LITERAL(32,0F000000)] + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x4)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,01000000)] MASK=[LITERAL(32,0F000000)] + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x5)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,01000000)] MASK=[LITERAL(32,0F000000)] + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x6)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,01000000)] MASK=[LITERAL(32,0F000000)] + CAUSE: TARGET=[THREADSTATE(MYCHIPLET,0x7)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(32,01000000)] MASK=[LITERAL(32,0F000000)] + # check that substep_deadman_start program is running in SBE @todo: Hostboot RTC:41412 + #CAUSE: TARGET=[FSIMBOX(0x1C)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,0000F012 00000000)] MASK=[LITERAL(64,0000FFFF 00000000)] + # Restore LPCR for wake-up options. + EFFECT: TARGET=[PROCREG(lpcr, MYCORE, 0)] OP=[BIT,ON] BIT=[49] + EFFECT: TARGET=[PROCREG(lpcr, MYCORE, 1)] OP=[BIT,ON] BIT=[49] + EFFECT: TARGET=[PROCREG(lpcr, MYCORE, 2)] OP=[BIT,ON] BIT=[49] + EFFECT: TARGET=[PROCREG(lpcr, MYCORE, 3)] OP=[BIT,ON] BIT=[49] + EFFECT: TARGET=[PROCREG(lpcr, MYCORE, 4)] OP=[BIT,ON] BIT=[49] + EFFECT: TARGET=[PROCREG(lpcr, MYCORE, 5)] OP=[BIT,ON] BIT=[49] + EFFECT: TARGET=[PROCREG(lpcr, MYCORE, 6)] OP=[BIT,ON] BIT=[49] + EFFECT: TARGET=[PROCREG(lpcr, MYCORE, 7)] OP=[BIT,ON] BIT=[49] + # Clear Timebase (to simulate core losing state). + EFFECT: TARGET=[PROCREG(tb, MYCORE, 0)] OP=[EQUALTO,BUF] DATA=[LITERAL(64,00000000 00000000)] + # Send IPI to thread + EFFECT: TARGET=[MODULE(interProcessorInterrupt, MYCORE, 0 )] OP=[MODULECALL] + EFFECT: TARGET=[MODULE(interProcessorInterrupt, MYCORE, 1 )] OP=[MODULECALL] + EFFECT: TARGET=[MODULE(interProcessorInterrupt, MYCORE, 2 )] OP=[MODULECALL] + EFFECT: TARGET=[MODULE(interProcessorInterrupt, MYCORE, 3 )] OP=[MODULECALL] + EFFECT: TARGET=[MODULE(interProcessorInterrupt, MYCORE, 4 )] OP=[MODULECALL] + EFFECT: TARGET=[MODULE(interProcessorInterrupt, MYCORE, 5 )] OP=[MODULECALL] + EFFECT: TARGET=[MODULE(interProcessorInterrupt, MYCORE, 6 )] OP=[MODULECALL] + EFFECT: TARGET=[MODULE(interProcessorInterrupt, MYCORE, 7 )] OP=[MODULECALL] + EFFECT: TARGET=[THREADSTATE(MYCHIPLET,0x0)] OP=[BIT,OFF] BIT=[7] +} + +#@01 end diff --git a/src/build/citest/etc/patches/p8_master.por.patch b/src/build/citest/etc/patches/p8_master.por.patch deleted file mode 100644 index f74f75465..000000000 --- a/src/build/citest/etc/patches/p8_master.por.patch +++ /dev/null @@ -1,17 +0,0 @@ - -##### from src/build/etc/patches/p8_master.por.patch - -#dc01 -#Flush state is : por=0,quiesced=1,running=0,maintmode=1,active=0,nap/sleep/winkle=0 -THREADSTATE(0x15000001)=0x10000000 -THREADSTATE(0x15000002)=0x10000000 -THREADSTATE(0x15000003)=0x10000000 -THREADSTATE(0x15000004)=0x10000000 -THREADSTATE(0x15000005)=0x10000000 -THREADSTATE(0x15000006)=0x10000000 -THREADSTATE(0x15000007)=0x10000000 - -#Master thread is started by SBE : running=1,active=1 -THREADSTATE(0x15000000)=0x28000000 - -##### end patch diff --git a/src/build/citest/etc/patches/patchlist.txt b/src/build/citest/etc/patches/patchlist.txt index c9732b104..4cdb8d248 100644 --- a/src/build/citest/etc/patches/patchlist.txt +++ b/src/build/citest/etc/patches/patchlist.txt @@ -5,9 +5,8 @@ Brief description of the problem or reason for patch -Files: list of files -Coreq: list of associated changes, e.g. workarounds.presimsetup - -New actions for instruction state processing +New actions for master-winkle wakeup -RTC: Task 43959 will remove the patches --CMVC: D841334 is integrating the changes +-CMVC: D846452 is integrating the changes -Files: p8_inst.act -Coreq: there are related changes in workarounds.postsimsetup diff --git a/src/build/citest/etc/workarounds.postsimsetup b/src/build/citest/etc/workarounds.postsimsetup index 51b45d176..2ff683e94 100755 --- a/src/build/citest/etc/workarounds.postsimsetup +++ b/src/build/citest/etc/workarounds.postsimsetup @@ -27,17 +27,8 @@ ## ### Updates to handle instruction states (Remove with RTC:43959) -echo "+++ Update cec-chip files for instruction state processing" +echo "+++ Update cec-chip files for master-winkle wakeup" mkdir -p $sb/simu/data/cec-chip/ -cp --update $bb/src/simu/data/cec-chip/p8.chip $sb/simu/data/cec-chip/ -cat $HOSTBOOTROOT/src/build/citest/etc/patches/p8.chip.patch >> $sb/simu/data/cec-chip/p8.chip -grep -v DONE $sb/simu/data/cec-chip/p8.chip > $sb/simu/data/cec-chip/p8.chip.tmp -echo "DONE" >> $sb/simu/data/cec-chip/p8.chip.tmp -mv $sb/simu/data/cec-chip/p8.chip.tmp $sb/simu/data/cec-chip/p8.chip - -cp --update $bb/src/simu/data/cec-chip/p8_master.por $sb/simu/data/cec-chip/ -cat $HOSTBOOTROOT/src/build/citest/etc/patches/p8_master.por.patch >> $sb/simu/data/cec-chip/p8_master.por - cp $HOSTBOOTROOT/src/build/citest/etc/patches/p8_inst.act $sb/simu/data/cec-chip/ ### diff --git a/src/include/arch/ppc.H b/src/include/arch/ppc.H index 9ba62ff9e..4e6add553 100644 --- a/src/include/arch/ppc.H +++ b/src/include/arch/ppc.H @@ -158,6 +158,16 @@ inline uint64_t getTB() return tb; } +ALWAYS_INLINE +inline void setTB(uint64_t _tb) +{ + // The bottom 24 bits of the timebase can't be written so round it up. + register uint64_t tb = (_tb + 0x1000000); + // Note that SPR 286 is intended (while getTB is 268) here. + // This is the mttbu40 instruction and not the mttb, which doesn't exist. + asm volatile("mtspr 286, %0" :: "r" (tb)); +} + ALWAYS_INLINE inline void setDEC(uint64_t _dec) { @@ -277,9 +287,9 @@ inline void icbi(void* _ptr) } ALWAYS_INLINE -inline void doze() +inline void nap() { - asm volatile("doze"); + asm volatile("nap"); } ALWAYS_INLINE diff --git a/src/include/kernel/cpu.H b/src/include/kernel/cpu.H index e395b2920..2efa89df2 100644 --- a/src/include/kernel/cpu.H +++ b/src/include/kernel/cpu.H @@ -1,25 +1,26 @@ -// IBM_PROLOG_BEGIN_TAG -// This is an automatically generated prolog. -// -// $Source: src/include/kernel/cpu.H $ -// -// IBM CONFIDENTIAL -// -// COPYRIGHT International Business Machines Corp. 2010 - 2011 -// -// p1 -// -// Object Code Only (OCO) source materials -// Licensed Internal Code Source Materials -// IBM HostBoot Licensed Internal Code -// -// The source code for this program is not published or other- -// wise divested of its trade secrets, irrespective of what has -// been deposited with the U.S. Copyright Office. -// -// Origin: 30 -// -// IBM_PROLOG_END +/* IBM_PROLOG_BEGIN_TAG + * This is an automatically generated prolog. + * + * $Source: src/include/kernel/cpu.H $ + * + * IBM CONFIDENTIAL + * + * COPYRIGHT International Business Machines Corp. 2010-2012 + * + * p1 + * + * Object Code Only (OCO) source materials + * Licensed Internal Code Source Materials + * IBM HostBoot Licensed Internal Code + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + * + * Origin: 30 + * + * IBM_PROLOG_END_TAG + */ /** @file cpu.H * @brief Defines kernel information and functions about CPUs. * @@ -42,7 +43,7 @@ class Scheduler; * @brief Stores per-CPU kernel information. * * @note kernel_stack and master need to be at fixed locations in this - * structure due to usages in start.S. + * structure due to usages in start.S (see ppcconsts.S). * * - kernel_stack is a double-word at cpu_t[0 bytes]. * - master is a byte at cpu_t[12 bytes]. @@ -63,8 +64,11 @@ struct cpu_t /** If the CPU is active */ bool active:1; + /** If the CPU is winkled */ + bool winkled:1; + /** Ensure alignment of master attribute for asm code. */ - uint64_t __reserved_master:30; + uint64_t __reserved_master:29; } PACKED; /** Pointer to the scheduler for this CPU (may not be unique) */ @@ -86,6 +90,9 @@ struct cpu_t /** counter for executePeriodics */ size_t periodic_count; + + /** Sequence ID of CPU initialization. */ + uint64_t cpu_start_seqid; }; /** @fn getCpuId diff --git a/src/include/kernel/cpumgr.H b/src/include/kernel/cpumgr.H index 8cf6d0fc3..fc7b68547 100644 --- a/src/include/kernel/cpumgr.H +++ b/src/include/kernel/cpumgr.H @@ -82,10 +82,39 @@ class CpuManager */ static void activateCPU(cpu_t * i_cpu); + /** @fn deactivateCPU + * Deactivate a cpu to show it is not running. + * @param[in] cpu_t the CPU + * @post Active flag is off in cpu_t structure. + */ + static void deactivateCPU(cpu_t * i_cpu); + /** @fn getCpuCount - * Return the number of active CPUs. + * Return the number of active CPUs. + */ + static size_t getCpuCount() { return cv_cpuSeq & 0xFFFFFFFF; } + + /** @fn getCpuSeqId + * Return the current CPU start sequence ID. + */ + static size_t getCpuSeqId() { return cv_cpuSeq >> 32; } + + /** @fn getCpuCountAndSeqId + * Atomically retrieve both the current active CPU count and + * sequence ID. + * */ - static size_t getCpuCount() { return cv_cpuCount; } + static void getCpuCountAndSeqId(uint32_t& o_count, uint32_t& o_seq) + { + uint64_t cpuSeq = cv_cpuSeq; + o_count = cpuSeq & 0xFFFFFFFF; + o_seq = cpuSeq >> 32; + } + + /** @fn getThreadCount + * Return the number of HW threads for this CPU core type. + */ + static size_t getThreadCount(); /** @fn startCore * Create structures to support a core activating and start the core. @@ -127,16 +156,16 @@ class CpuManager void startCPU(ssize_t i = -1); void startSlaveCPU(cpu_t*); - static size_t getThreadCount(); - private: static cpu_t** cv_cpus; // Need to be able to access this // from start.S to get initial stacks // of secondary cpus / threads. - static Barrier cv_barrier; //!< barrier for cpus - static bool cv_defrag; //!< mem heap defrag - static size_t cv_cpuCount; //!< # of active CPUs + /** Number of active CPUs. + * Stored as "(seqID << 32) | cpus" + */ + static uint64_t cv_cpuSeq; + static bool cv_forcedMemPeriodic; //!< force free / coalesce. // If a shutdown of all CPUs is requested diff --git a/src/include/kernel/deferred.H b/src/include/kernel/deferred.H new file mode 100644 index 000000000..6d8950acb --- /dev/null +++ b/src/include/kernel/deferred.H @@ -0,0 +1,201 @@ +/* IBM_PROLOG_BEGIN_TAG + * This is an automatically generated prolog. + * + * $Source: src/include/kernel/deferred.H $ + * + * IBM CONFIDENTIAL + * + * COPYRIGHT International Business Machines Corp. 2012 + * + * p1 + * + * Object Code Only (OCO) source materials + * Licensed Internal Code Source Materials + * IBM HostBoot Licensed Internal Code + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + * + * Origin: 30 + * + * IBM_PROLOG_END_TAG + */ +#ifndef __KERNEL_DEFERRED_H +#define __KERNEL_DEFERRED_H + +/** @file deferred.H + * @brief Definition of kernel's deferred work constructs. + * + * These classes allow the kernel to synchronize all CPUs into kernel-mode + * and execute a task. These work items are queued up to be executed at + * the next time-slice expiration (decrementer exception). + */ + +#include +#include +#include + +/** @class DeferredWork + * @brief The base work-item type for deferred work. + * + * This class implements the synchronization and state transition for a + * general deferred work object. This class has methods for defining + * the behavior at specific points in its execution. A real behavior + * implementation should be defined by inheriting this class and overloading + * the desired virtual methods. + * + * The class is closely associated with the DeferredQueue, which is meant to + * hold pending DeferredWork objects. When a DeferredWork is complete it + * will remove itself from the DeferredQueue and self-delete. + * + * The state transition is as follows: + * + *
+ *        MASTER           Both            NON-MASTER
+ *  1.                   Sync all
+ *  2.  masterPreWork                         block
+ *  3.                activeMainWork
+ *  4.                   Sync all
+ *  5.  masterPostWork                        block
+ *  6.              Last thread out deletes
+ *  
+ * + * With the deferred work there is concern as to what to do with CPUs that + * come online while a deferred work item is being executed. For instance, + * the Heap Coalescing work could cause data integrity issues if a freshly + * activated CPU were to not block with the rest of the CPUs and instead + * started executed user-space code. To deal with this condition a + * CPU which is activated after the DeferredWork object was created will + * block at masterPreWork and masterPostWork stages and call + * nonactiveMainWork. Typically, the non-active CPUs perform no action + * but an implementation could assert for a race-condition that cannot + * be handled properly (though should never occur). + */ +class DeferredWork +{ + public: + /** Default Constructor + * Initializes the work item and determines the CPU-activation + * sequence number at the time of creation. + */ + DeferredWork(); + + /** Default destructor + * Verifies that the work item has completed properly and is + * detached from the DeferredQueue. + */ + virtual ~DeferredWork(); + + /** Entry point for DeferredWork execution. */ + void start(); + + protected: + // Functions to override for desired behavior: + /** Executed by master before "main" but after all active + * CPUs are sync'd. + */ + virtual void masterPreWork() {}; + /** Executed by master after "main" work is complete. */ + virtual void masterPostWork() {}; + /** Executed by all [active] CPUs as the "main" work. */ + virtual void activeMainWork() {}; + /** Executed by all non-active CPUs as the "main" work. */ + virtual void nonactiveMainWork() {}; + + private: + friend class DeferredQueue; + + /** Barrier for synchronization of active CPUs. */ + Barrier iv_barrier; + /** Count of CPUs in object and pointer to next object. + * + * Stored as "(cpu count << 32) | (DeferredWork* next)". This + * is done so that we can atomically check and/or set both + * values. + */ + volatile uint64_t iv_cpus_and_next; + /** Sequence ID at the time of creation. */ + uint32_t iv_activeSeqId; + /** Boolean to indicate masterPreWork is complete. */ + volatile bool iv_releasePre; + /** Boolean to indicate masterPostWork is complete. */ + volatile bool iv_releasePost; + + // Internal state transition functions. + void _waitForCpus(); + void _masterPre(); + void _waitAtPre(); + void _masterPost(); + void _waitAtPost(); + void _cleanup(); + +}; + +/** @class DeferredQueue + * @brief Queue for DeferredWork objects. + * + * This class should have a Singleton instance for the whole kernel. + * Periodically, kernel threads can call the 'execute' function to execute + * pending work, if any is available. Additional work can be 'insert'ed. + */ +class DeferredQueue +{ + public: + /** Default constructor. */ + DeferredQueue(); + /** Default destructor. */ + ~DeferredQueue(); + + /** Insert a work item into the queue. + * + * @param i_work - The item to add. + * + * Ownership of the work item is transfered to the queue, which is + * responsible for delete once the work is complete. + */ + static void insert(DeferredWork* i_work); + /** Execute any pending work items. */ + static void execute(); + + private: + friend class DeferredWork; + + // Instance functions for static pair. + void _insert(DeferredWork* i_work); + void _execute(); + + /** Remove a completed work item from the queue. + * + * This function is to be called by the master CPU executing the + * work item being completed. + * + * The work item is atomically removed from the queue and the + * count of CPUs with a pointer to the work item is compared + * against the count of CPUs in the work item. This function + * returns when all CPUs that have a pointer are actually inside + * the work item (so we can accurately determine when there is + * only a single CPU in the work item for delete). + * + * @param i_work - The item to remove. + */ + void _complete(DeferredWork* i_work); + + /** Spinlock to protect insert / remove operations. + * + * This is effectively a "write" lock on the structure and all + * reads are done atomically. The writers have also use atomic + * update operations to ensure the readers (which are never + * locked) operate in a thread-safe manner. + */ + Spinlock lock; + /** Count of CPUs in first object and pointer to it. + * + * Stored as "(cpu count << 32) | (DeferredWork* ptr)". This + * is done so that we can atomically check and/or set both + * values. + */ + volatile uint64_t iv_cpus_and_next; +}; + +#endif diff --git a/src/include/kernel/misc.H b/src/include/kernel/misc.H index ebec9cc48..c970c337e 100644 --- a/src/include/kernel/misc.H +++ b/src/include/kernel/misc.H @@ -30,6 +30,8 @@ #include #include +#include +#include namespace KernelMisc { @@ -59,5 +61,32 @@ namespace KernelMisc } return true; } + + /** @class WinkleCore + * + * @brief DeferredWork class for implementing cpu_master_winkle. + */ + class WinkleCore : public ::DeferredWork + { + public: + /** ctor + * + * @param i_caller - Task calling cpu_master_winkle to be + * restored after winkle is complete. + */ + WinkleCore(task_t* i_caller) : + iv_caller(i_caller), iv_timebase(0) {}; + + void masterPreWork(); + void activeMainWork(); + void masterPostWork(); + void nonactiveMainWork(); + + private: + /** Caller of cpu_master_winkle() */ + task_t* iv_caller; + /** Current time-base value for restore after winkle. */ + uint64_t iv_timebase; + }; }; #endif diff --git a/src/include/kernel/ppcconsts.S b/src/include/kernel/ppcconsts.S index 1568bb911..8b84e9135 100644 --- a/src/include/kernel/ppcconsts.S +++ b/src/include/kernel/ppcconsts.S @@ -1,24 +1,24 @@ # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. -# +# # $Source: src/include/kernel/ppcconsts.S $ -# +# # IBM CONFIDENTIAL -# +# # COPYRIGHT International Business Machines Corp. 2010-2012 -# +# # p1 -# +# # Object Code Only (OCO) source materials # Licensed Internal Code Source Materials # IBM HostBoot Licensed Internal Code -# +# # The source code for this program is not published or other- # wise divested of its trade secrets, irrespective of what has # been deposited with the U.S. Copyright Office. -# +# # Origin: 30 -# +# # IBM_PROLOG_END_TAG #*--------------------------------------------------------------------*# #* Register Constants *# @@ -243,3 +243,10 @@ .set TASK_FPR_31, TASK_FPR_30+8 .set TASK_FPSCR, TASK_FPR_31+8 +.set CPU_KERNEL_STACK, 0 +.set CPU_CPUID, CPU_KERNEL_STACK+8 +.set CPU_STATUS, CPU_CPUID+4 + +.set CPU_STATUS_MASTER, 0 +.set CPU_STATUS_ACTIVE, CPU_STATUS_MASTER+1 +.set CPU_STATUS_WINKLED, CPU_STATUS_ACTIVE+1 diff --git a/src/include/kernel/syscalls.H b/src/include/kernel/syscalls.H index 5523fc158..b02fd2216 100644 --- a/src/include/kernel/syscalls.H +++ b/src/include/kernel/syscalls.H @@ -92,8 +92,10 @@ namespace Systemcalls MISC_CPUSTARTCORE, /** cpu_spr_value() */ MISC_CPUSPRVALUE, - /** cpu_doze() - Hidden syscall */ - MISC_CPUDOZE, + /** cpu_nap() - Hidden syscall */ + MISC_CPUNAP, + /** cpu_master_winkle() */ + MISC_CPUWINKLE, /** mm_alloc_block() */ MM_ALLOC_BLOCK, diff --git a/src/include/sys/misc.h b/src/include/sys/misc.h index 1ffd8e6a7..f1c62273b 100644 --- a/src/include/sys/misc.h +++ b/src/include/sys/misc.h @@ -142,6 +142,9 @@ uint64_t cpu_spr_value(CpuSprNames spr); * * @retval 0 - Success * @retval -EDEADLK - Cores other than the master are already running. + * + * @note This function will migrate the task to the master thread and in the + * process will unset any task affinity. See task_affinity_unpin(). */ int cpu_master_winkle(); diff --git a/src/kernel.ld b/src/kernel.ld index 368605e9b..3f9060548 100644 --- a/src/kernel.ld +++ b/src/kernel.ld @@ -5,7 +5,7 @@ * * IBM CONFIDENTIAL * - * COPYRIGHT International Business Machines Corp. 2010 - 2011 + * COPYRIGHT International Business Machines Corp. 2010-2012 * * p1 * @@ -19,7 +19,7 @@ * * Origin: 30 * - * IBM_PROLOG_END + * IBM_PROLOG_END_TAG */ base_load_address = 0x00000000; text_load_address = 0x00003000; @@ -31,6 +31,7 @@ SECTIONS .text ALIGN(0x1000): { *(.text.intvects) . = text_load_address; + *(.text.kernelasm) *(.text) *(.text._*) *(.rodata) diff --git a/src/kernel/cpumgr.C b/src/kernel/cpumgr.C index 943ef48fd..909661cca 100644 --- a/src/kernel/cpumgr.C +++ b/src/kernel/cpumgr.C @@ -38,13 +38,13 @@ #include #include #include +#include +#include cpu_t** CpuManager::cv_cpus = NULL; bool CpuManager::cv_shutdown_requested = false; uint64_t CpuManager::cv_shutdown_status = 0; -Barrier CpuManager::cv_barrier; -bool CpuManager::cv_defrag = false; -size_t CpuManager::cv_cpuCount = 0; +size_t CpuManager::cv_cpuSeq = 0; bool CpuManager::cv_forcedMemPeriodic = false; InteractiveDebug CpuManager::cv_interactive_debug; @@ -95,6 +95,35 @@ void CpuManager::requestShutdown(uint64_t i_status) cv_shutdown_status = i_status; __sync_synchronize(); cv_shutdown_requested = true; + + class ExecuteShutdown : public DeferredWork + { + public: + void masterPreWork() + { + // The stats can be retrieved from global variables as needed. + // This can be uncommented for debug if desired + #ifdef __MEMSTATS__ + if(c->master) + HeapManager::stats(); + #endif + } + + void activeMainWork() + { + KernelMisc::shutdown(); + } + + void nonactiveMainWork() + { + // Something wasn't synchronized correctly if we got to here. + // Should not have CPUs coming online while trying to execute + // a shutdown. + kassert(false); + } + }; + + DeferredQueue::insert(new ExecuteShutdown()); } void CpuManager::startCPU(ssize_t i) @@ -163,8 +192,20 @@ void CpuManager::activateCPU(cpu_t * i_cpu) { // Set active. i_cpu->active = true; - __sync_add_and_fetch(&cv_cpuCount, 1); - lwsync(); + + // Update sequence ID. + do + { + uint64_t old_seq = cv_cpuSeq; + i_cpu->cpu_start_seqid = old_seq + 1 + (1ull << 32); + + if (__sync_bool_compare_and_swap(&cv_cpuSeq, old_seq, + i_cpu->cpu_start_seqid)) + { + break; + } + } while (1); + i_cpu->cpu_start_seqid >>= 32; // Verify / set SPRs. uint64_t msr = getMSR(); @@ -172,6 +213,24 @@ void CpuManager::activateCPU(cpu_t * i_cpu) setLPCR(WAKEUP_LPCR_VALUE); } +void CpuManager::deactivateCPU(cpu_t * i_cpu) +{ + // Set inactive. + i_cpu->active = false; + + // Update sequence ID. + do + { + uint64_t old_seq = cv_cpuSeq; + uint64_t new_seq = old_seq - 1 + (1ull << 32); + + if (__sync_bool_compare_and_swap(&cv_cpuSeq, old_seq, new_seq)) + { + break; + } + } while(1); +} + void CpuManager::executePeriodics(cpu_t * i_cpu) { if(i_cpu->master) @@ -211,32 +270,22 @@ void CpuManager::executePeriodics(cpu_t * i_cpu) if((0 == (i_cpu->periodic_count % CPU_PERIODIC_DEFRAG)) || (forceMemoryPeriodic)) { - // set up barrier based on # cpus cv_barrier; - // TODO whatif other cpus become active? - isync(); // Ensure all instructions complete before this point, so - // we don't get a stale shutdown_requested. - if(!cv_shutdown_requested) + class MemoryCoalesce : public DeferredWork { - cv_barrier.init(cv_cpuCount); - lwsync(); // Ensure barrier init is globally visible before - // setting defrag = true. - cv_defrag = true; - } + public: + void masterPreWork() + { + HeapManager::coalesce(); + PageManager::coalesce(); + } + }; + + DeferredQueue::insert(new MemoryCoalesce()); } } - if(cv_defrag) - { - cv_barrier.wait(); - if(i_cpu->master) - { - HeapManager::coalesce(); - PageManager::coalesce(); - cv_defrag = false; - } + DeferredQueue::execute(); - cv_barrier.wait(); - } } int CpuManager::startCore(uint64_t pir) diff --git a/src/kernel/deferred.C b/src/kernel/deferred.C new file mode 100644 index 000000000..dc6494857 --- /dev/null +++ b/src/kernel/deferred.C @@ -0,0 +1,268 @@ +/* IBM_PROLOG_BEGIN_TAG + * This is an automatically generated prolog. + * + * $Source: src/kernel/deferred.C $ + * + * IBM CONFIDENTIAL + * + * COPYRIGHT International Business Machines Corp. 2012 + * + * p1 + * + * Object Code Only (OCO) source materials + * Licensed Internal Code Source Materials + * IBM HostBoot Licensed Internal Code + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + * + * Origin: 30 + * + * IBM_PROLOG_END_TAG + */ +#include +#include +#include +#include +#include + +/** Extract the DeferredWork pointer part of a iv_cpus_and_next instance var. */ +#define DEFERRED_QUEUE_GET_NEXT_PTR(item) \ + reinterpret_cast((item)->iv_cpus_and_next & 0xFFFFFFFF) + +/** Set the DeferredWork pointer part of a iv_cpus_and_next instance var. */ +#define DEFERRED_QUEUE_SET_NEXT_PTR(item) \ + (item)->iv_cpus_and_next = \ + ((item)->iv_cpus_and_next & 0xFFFFFFFF00000000ull) | \ + reinterpret_cast(item) + +/** Extract the CPU count portion of a iv_cpus_and_next instance var. */ +#define DEFERRED_QUEUE_GET_CPU_COUNT(item) (item)->iv_cpus_and_next >> 32 + +// Initialize the work queue. +DeferredQueue::DeferredQueue() : lock(), iv_cpus_and_next(0) {} + +DeferredQueue::~DeferredQueue() +{ + // Ensure that all work is completed. + kassert(0 == iv_cpus_and_next); +} + +void DeferredQueue::insert(DeferredWork* i_work) +{ + // Call singleton insert. + Singleton::instance()._insert(i_work); +} + +void DeferredQueue::execute() +{ + // Call singleton execute. + Singleton::instance()._execute(); +} + +void DeferredQueue::_insert(DeferredWork* i_work) +{ + lock.lock(); + + // NULL pointer implies empty, so just add work item. + if (0 == iv_cpus_and_next) + { + iv_cpus_and_next = reinterpret_cast(i_work); + } + else + { + // Follow linked list to last work item. + DeferredWork* tail = DEFERRED_QUEUE_GET_NEXT_PTR(this); + while (NULL != DEFERRED_QUEUE_GET_NEXT_PTR(tail)) + { + tail = DEFERRED_QUEUE_GET_NEXT_PTR(tail); + } + + // Add work item to the end of the list. + DEFERRED_QUEUE_SET_NEXT_PTR(i_work); + } + + lock.unlock(); +} + +void DeferredQueue::_execute() +{ + uint64_t cpus_and_next = 0; + + // Increment the CPU count for pointer references. + do + { + cpus_and_next = iv_cpus_and_next; + + if (0 == cpus_and_next) // No work to execute. + { + return; + } + + } while(!__sync_bool_compare_and_swap(&iv_cpus_and_next, + cpus_and_next, + cpus_and_next + (1ull << 32))); + + // Extract the item pointer. + DeferredWork* item = + reinterpret_cast(cpus_and_next & 0xFFFFFFFF); + + // Execute the extracted item. + item->start(); +} + +void DeferredQueue::_complete(DeferredWork* i_work) +{ + lock.lock(); + + // Update list-head to pop item off. + uint64_t new_ptr = + reinterpret_cast(DEFERRED_QUEUE_GET_NEXT_PTR(i_work)); + uint64_t old_ptr = 0; + + do + { + old_ptr = iv_cpus_and_next; + } while(!__sync_bool_compare_and_swap(&iv_cpus_and_next, old_ptr, new_ptr)); + + // Get the CPU count from the old object pointer and wait until those + // CPUs get into i_work. + old_ptr >>= 32; + while (DEFERRED_QUEUE_GET_CPU_COUNT(i_work) != old_ptr) + { + setThreadPriorityLow(); + } + setThreadPriorityHigh(); + + lock.unlock(); +} + +DeferredWork::DeferredWork() : iv_barrier(), iv_cpus_and_next(0), + iv_activeSeqId(0), + iv_releasePre(false), iv_releasePost(false) +{ + uint32_t cpuCount; + + // Read the current CPU count and sequence number. + CpuManager::getCpuCountAndSeqId(cpuCount, iv_activeSeqId); + // Initialize the barrier with the number of active CPUs. + iv_barrier.init(cpuCount); +} + +DeferredWork::~DeferredWork() +{ + // Ensure the work item was removed from the queue chain and no + // CPUs are still inside it. + kassert(0 == iv_cpus_and_next); +} + +void DeferredWork::start() +{ + // Increment object reference count. + __sync_add_and_fetch(&iv_cpus_and_next, 1ull << 32); + + // Get our CPU object and determine if we were active when the item + // was created. (Our sequence # being less or equal work item sequence #) + cpu_t* cpu = CpuManager::getCurrentCPU(); + bool active = cpu->cpu_start_seqid <= iv_activeSeqId; + + // Synchronize active CPUs. + if (active) + { + _waitForCpus(); + } + + // Call masterPre step. + if (cpu->master) + { + _masterPre(); + } + else + { + _waitAtPre(); + } + + // Call MainWork step. + if (active) + { + activeMainWork(); + _waitForCpus(); + } + else + { + nonactiveMainWork(); + } + + // Call masterPost step. + if (cpu->master) + { + _masterPost(); + } + else + { + _waitAtPost(); + } + + // Release reference to this object. + _cleanup(); +} + +void DeferredWork::_waitForCpus() +{ + iv_barrier.wait(); +} + +void DeferredWork::_masterPre() +{ + masterPreWork(); + + // Ensure memory ops are globally visible before releasing all CPUs. + lwsync(); + iv_releasePre = true; +} + +void DeferredWork::_waitAtPre() +{ + while(!iv_releasePre) + { + setThreadPriorityLow(); + } + isync(); // Prevent spec. execution past this point until released. + setThreadPriorityHigh(); +} + +void DeferredWork::_masterPost() +{ + masterPostWork(); + + // Remove ourself from the queue chain now. + Singleton::instance()._complete(this); + + // Ensure memory ops are globally visible before releasing all CPUs. + lwsync(); + iv_releasePost = true; +} + +void DeferredWork::_waitAtPost() +{ + while(!iv_releasePost) + { + setThreadPriorityLow(); + } + isync(); // Prevent spec. execution past this point until released. + setThreadPriorityHigh(); +} + +void DeferredWork::_cleanup() +{ + // Decrement reference count. + uint64_t cpu_count = + __sync_sub_and_fetch(&iv_cpus_and_next, 1ull << 32) >> 32; + + // If the last object, delete this work item. + if (0 == cpu_count) + { + delete this; + } +} diff --git a/src/kernel/exception.C b/src/kernel/exception.C index 0d63d0a73..071f10b1e 100644 --- a/src/kernel/exception.C +++ b/src/kernel/exception.C @@ -38,7 +38,7 @@ namespace ExceptionHandles bool PrivInstr(task_t*); } -const uint64_t EXCEPTION_SRR1_MASK = 0x00000000783F0000; +const uint64_t EXCEPTION_SRR1_MASK = 0x00000000783F0000; const uint64_t EXCEPTION_SRR1_PRIVINS = 0x0000000000040000; extern "C" @@ -56,12 +56,12 @@ void kernel_execute_prog_ex() } if (!handled) { - printk("Program exception, killing task %d\n", t->tid); - TaskManager::endTask(t, NULL, TASK_STATUS_CRASHED); + printk("Program exception, killing task %d\n", t->tid); + TaskManager::endTask(t, NULL, TASK_STATUS_CRASHED); } } -const uint64_t EXCEPTION_DSISR_MASK = 0x0000000048000000; +const uint64_t EXCEPTION_DSISR_MASK = 0x0000000048000000; const uint64_t EXCEPTION_DSISR_PTEMISS = 0x0000000040000000; const uint64_t EXCEPTION_DSISR_PERMERR = 0x0000000008000000; const uint64_t EXCEPTION_DSISR_STORE = 0x0000000002000000; @@ -75,7 +75,7 @@ void kernel_execute_data_storage() bool handled = false; switch(exception) { - case EXCEPTION_DSISR_PTEMISS: + case EXCEPTION_DSISR_PTEMISS: { uint64_t is_store = getDSISR() & EXCEPTION_DSISR_STORE; handled = VmmManager::pteMiss(t, getDAR(), 0 != is_store); @@ -87,16 +87,16 @@ void kernel_execute_data_storage() uint64_t is_store = getDSISR() & EXCEPTION_DSISR_STORE; if (is_store) { - handled = VmmManager::pteMiss(t, getDAR(), true); + handled = VmmManager::pteMiss(t, getDAR(), true); } - break; + break; } } if (!handled) { - printk("Data Storage exception on %d: %lx, %lx @ %p\n", - t->tid, getDAR(), getDSISR(), t->context.nip); - TaskManager::endTask(t, NULL, TASK_STATUS_CRASHED); + printk("Data Storage exception on %d: %lx, %lx @ %p\n", + t->tid, getDAR(), getDSISR(), t->context.nip); + TaskManager::endTask(t, NULL, TASK_STATUS_CRASHED); } } @@ -129,7 +129,7 @@ void kernel_execute_inst_storage() { printk("Inst Storage exception on %d: %lx, %lx\n", t->tid, getSRR0(), getSRR1()); - TaskManager::endTask(t, NULL, TASK_STATUS_CRASHED); + TaskManager::endTask(t, NULL, TASK_STATUS_CRASHED); } } @@ -169,19 +169,19 @@ namespace ExceptionHandles { uint32_t* instruction = reinterpret_cast(phys_addr); - // Check for 'doze' and skip over. This avoids a task-crash + // Check for 'nap' and skip over. This avoids a task-crash // if for some reason we entered back into the task without // priviledge raised. - if (*instruction == 0x4c000324) + if (*instruction == 0x4c000364) { - printk("Error: Doze executed with lowered permissions on %d\n", + printk("Error: Nap executed with lowered permissions on %d\n", t->tid); t->context.nip = static_cast(instruction + 1); return true; } } - return false; + return false; } } diff --git a/src/kernel/kernel.C b/src/kernel/kernel.C index cbac9a20f..e29af240e 100644 --- a/src/kernel/kernel.C +++ b/src/kernel/kernel.C @@ -1,25 +1,26 @@ -// IBM_PROLOG_BEGIN_TAG -// This is an automatically generated prolog. -// -// $Source: src/kernel/kernel.C $ -// -// IBM CONFIDENTIAL -// -// COPYRIGHT International Business Machines Corp. 2010 - 2011 -// -// p1 -// -// Object Code Only (OCO) source materials -// Licensed Internal Code Source Materials -// IBM HostBoot Licensed Internal Code -// -// The source code for this program is not published or other- -// wise divested of its trade secrets, irrespective of what has -// been deposited with the U.S. Copyright Office. -// -// Origin: 30 -// -// IBM_PROLOG_END +/* IBM_PROLOG_BEGIN_TAG + * This is an automatically generated prolog. + * + * $Source: src/kernel/kernel.C $ + * + * IBM CONFIDENTIAL + * + * COPYRIGHT International Business Machines Corp. 2010-2012 + * + * p1 + * + * Object Code Only (OCO) source materials + * Licensed Internal Code Source Materials + * IBM HostBoot Licensed Internal Code + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + * + * Origin: 30 + * + * IBM_PROLOG_END_TAG + */ #include #include #include @@ -33,6 +34,7 @@ #include #include #include +#include #include @@ -85,6 +87,7 @@ int smp_slave_main(cpu_t* cpu) CpuManager::init_slave_smp(cpu); VmmManager::init_slb(); cpu->scheduler->setNextRunnable(); + DeferredQueue::execute(); kernel_dispatch_task(); return 0; } diff --git a/src/kernel/makefile b/src/kernel/makefile index 06c7536be..c23cb7fe9 100644 --- a/src/kernel/makefile +++ b/src/kernel/makefile @@ -1,11 +1,11 @@ -# IBM_PROLOG_BEGIN_TAG +# IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # $Source: src/kernel/makefile $ # # IBM CONFIDENTIAL # -# COPYRIGHT International Business Machines Corp. 2010 - 2011 +# COPYRIGHT International Business Machines Corp. 2010-2012 # # p1 # @@ -19,14 +19,14 @@ # # Origin: 30 # -# IBM_PROLOG_END +# IBM_PROLOG_END_TAG ROOTPATH = ../.. OBJS = start.o kernel.o console.o pagemgr.o heapmgr.o taskmgr.o cpumgr.o OBJS += syscall.o scheduler.o spinlock.o exception.o vmmmgr.o timemgr.o OBJS += futexmgr.o ptmgr.o segmentmgr.o devicesegment.o basesegment.o OBJS += block.o cpuid.o misc.o msghandler.o blockmsghdlr.o stacksegment.o -OBJS += softpatch_p7.o barrier.o idebug.o intmsghandler.o +OBJS += softpatch_p7.o barrier.o idebug.o intmsghandler.o deferred.o include ${ROOTPATH}/config.mk diff --git a/src/kernel/misc.C b/src/kernel/misc.C index a29aaea21..d45473259 100644 --- a/src/kernel/misc.C +++ b/src/kernel/misc.C @@ -26,6 +26,8 @@ #include #include #include +#include +#include extern "C" void kernel_shutdown(size_t, uint64_t, uint64_t) NO_RETURN; @@ -82,15 +84,15 @@ namespace KernelMisc if (c->master) { - printk("No payload... doze'ing all threads.\n"); + printk("No payload... nap'ing all threads.\n"); } - // Clear LPCR values that wakes up from doze. LPCR[49, 50, 51] + // Clear LPCR values that wakes up from nap. LPCR[49, 50, 51] setLPCR(getLPCR() & (~0x0000000000007000)); while(1) { - doze(); + nap(); } } else @@ -110,4 +112,78 @@ namespace KernelMisc g_payload_entry); } } + + void WinkleCore::masterPreWork() + { + printk("Winkle threads - "); + + // Save away the current timebase. All threads are in this object + // now so they're not going to be using the time for anything else. + iv_timebase = getTB(); + } + + extern "C" void kernel_execute_winkle(task_t* t); + + void WinkleCore::activeMainWork() + { + cpu_t* cpu = CpuManager::getCurrentCPU(); + printk("%d", static_cast(cpu->cpu & 0x7)); + + // Return current task to run-queue so it isn't lost. + cpu->scheduler->returnRunnable(); + TaskManager::setCurrentTask(cpu->idle_task); + + // Clear LPCR values that wakes up from winkle. LPCR[49, 50, 51] + // Otherwise, there may be an interrupt pending or something that + // prevents us from fully entering winkle. + setLPCR(getLPCR() & (~0x0000000000007000)); + + // Deactivate CPU from kernel. + cpu->winkled = true; + CpuManager::deactivateCPU(cpu); + + // Create kernel save area and store ptr in bottom of kernel stack. + task_t* saveArea = new task_t; + memset(saveArea, '\0', sizeof(task_t)); + saveArea->context.msr_mask = 0xC030; // EE, PR, IR, DR. + *(reinterpret_cast(cpu->kernel_stack)) = saveArea; + + // Execute winkle. + kernel_execute_winkle(saveArea); + + // Re-activate CPU in kernel and re-init VMM SPRs. + delete saveArea; + cpu->winkled = false; + CpuManager::activateCPU(cpu); + VmmManager::init_slb(); + + // Select a new task if not the master CPU. Master CPU will resume + // the code that called cpu_master_winkle(). + if (!cpu->master) + { + cpu->scheduler->setNextRunnable(); + } + + } + + void WinkleCore::masterPostWork() + { + printk(" - Awake!\n"); + + // Restore timebase. + setTB(iv_timebase); + + // Restore caller of cpu_master_winkle(). + TaskManager::setCurrentTask(iv_caller); + + } + + void WinkleCore::nonactiveMainWork() + { + // Race condition that should not occur... + // + // Attempted to winkle the master and another thread came online in + // the process. + kassert(false); + } }; diff --git a/src/kernel/start.S b/src/kernel/start.S index 7d2d77845..f26592245 100644 --- a/src/kernel/start.S +++ b/src/kernel/start.S @@ -145,39 +145,8 @@ finished_relocate: b kernel_dispatch_task; /* Return to task */ .org _start + 0x100 -intvect_system_reset: - /* TODO: Add handling for SRESET from winkle for master. */ - ;// Need to identify reason for SRESET and then perform appropriate - ;// action. - ;// Current support: - ;// - Decrementer wake-up from doze. - ;// - External interrupt (also wake-up from doze). - ;// - IPI wake-up from winkle of slave core. - - ;// Free up two registers temporarily. - mtsprg0 r1 - mtsprg1 r2 - - ;// Save CR. - mfcr r1 - - ;// Find bit 42:44 of SRR1 (reason for SRESET). - mfsrr1 r2 - extrdi r2, r2, 3, 42 - ;// Check for decrementer (bits = 011). - cmpi cr0, r2, 0x3 - beq+ intvect_system_reset_decrementer - ;// Check for external interrupt (bits = 010). - cmpi cr0, r2, 0x4 - beq+ intvect_system_reset_external - ;// Check for HMI (bits = 101). - cmpi cr0, r2, 0x5 - beq+ _start - ;// Check for bits 000, which is probably a Simics bug right now. - cmpi cr0, r2, 0x0 - beq+ _start -1: ;// Unknown reason. - b 1b +intvect_system_reset_stub: + b intvect_system_reset .org _start + 0x180 intvect_inst_start: @@ -272,7 +241,7 @@ softpatch_stub: mfsprg1 r1 ;// Restore R1 and use normal interrupt code. STD_INTERRUPT_NOADDR(softpatch) -.section .text +.section .text.kernelasm ;// _main: ;// Set up stack and TOC and call kernel's main. _main: @@ -302,8 +271,7 @@ _other_thread_spinlock: 1: ld r3, 0(r2) ;// Loop until value is 1... - li r4, 1 - cmp cr0, r3, r4 + cmpi cr0, r3, 1 beq _other_thread_spinlock_complete or 1,1,1 ;// Lower thread priority. b 1b @@ -321,7 +289,7 @@ _other_thread_spinlock_complete: ld r3, 0(r2) ;// Load CPU object. cmpi cr0, r3, 0 ;// Check for NULL CPU object. beq- cr0, 1f ;// Jump to handling if no CPU object found. - ld r1, 0(r3) ;// Load initial stack. + ld r1, CPU_KERNEL_STACK(r3) ;// Load initial stack. lis r2, smp_slave_main@h ;// Load TOC base. ori r2, r2, smp_slave_main@l @@ -329,11 +297,11 @@ _other_thread_spinlock_complete: bl smp_slave_main ;// Call smp_slave_main b _main_loop 1: - ;// No CPU object available, doze this CPU. + ;// No CPU object available, nap this CPU. ;// We should only get to this point on simics. SBE will only wake up ;// a single core / thread at a time and we are responsible for ;// further sequencing. - doze + nap b 1b @@ -399,8 +367,8 @@ kernel_save_task: bne- cr0, 1f ;// Jump to FP-save if != NULL. 2: - ld r1, 0(r1) ;// Get CPU pointer - ld r1, 0(r1) ;// Get kernel stack pointer. + ld r1, TASK_CPUPTR(r1) ;// Get CPU pointer + ld r1, CPU_KERNEL_STACK(r1) ;// Get kernel stack pointer. mfsprg0 r0 ;// Retrieve return address from SPRG0 mtlr r0 ;// Call @@ -461,8 +429,8 @@ kernel_dispatch_task: .global kernel_dispatch_task mfsprg3 r1 ;// Load task structure to r1. - ldarx r0, 0, r1 ;// Clear the reservation by loading / storing - stdcx. r0, 0, r1 ;// the CPU pointer in the task. + ldarx r0, TASK_CPUPTR, r1 ;// Clear the reservation by loading / storing + stdcx. r0, TASK_CPUPTR, r1 ;// the CPU pointer in the task. mfmsr r2 ;// Get current MSR ori r2,r2, 0xC030 ;// Enable MSR[EE,PR,IR,DR]. @@ -574,20 +542,88 @@ kernel_dispatch_task: b 2b +intvect_system_reset: + ;// Need to identify reason for SRESET and then perform appropriate + ;// action. + ;// Current support: + ;// - Initial sreset. + ;// - Decrementer wake-up from nap. + ;// - External interrupt from nap or winkle. + ;// - IPI wake-up from winkle of slave core. + + ;// Raise priority to high. + or 3,3,3 + + ;// Free up two registers temporarily. + mtsprg0 r1 + mtsprg1 r2 + + ;// Check spinlock for 0, which implies we haven't started yet. + lis r2, kernel_other_thread_spinlock@h + ori r2, r2, kernel_other_thread_spinlock@l + ld r2, 0(r2) + cmpi cr0, r2, 0 + beq- _start + + ;// Get CPU object from thread ID, check for NULL which implies not + ;// started yet. + mfspr r1, PIR + lis r2, _ZN10CpuManager7cv_cpusE@h + ori r2, r2, _ZN10CpuManager7cv_cpusE@l + ld r2, 0(r2) ;// Dereference cv_cpus to get array. + muli r1, r1, 8 + ldx r2, r1, r2 ;// Load CPU object. + cmpi cr0, r2, 0 ;// Check for NULL CPU object. + beq- _start + + ;// Check for inactive CPU. + ld r1, CPU_STATUS(r2) + extrdi. r1, r1, 1, CPU_STATUS_ACTIVE + beq- intvect_system_reset_inactive + + ;// Now we were an active processor so this must be a nap-wakeup. + + ;// Find bit 42:44 of SRR1 (reason for SRESET). + mfsrr1 r2 + extrdi r2, r2, 3, 42 + ;// Check for decrementer (bits = 011). + cmpi cr0, r2, 0x3 + beq+ intvect_system_reset_decrementer + ;// Check for external interrupt (bits = 010). + cmpi cr0, r2, 0x4 + beq+ intvect_system_reset_external + ;// Check for HMI (bits = 101). + cmpi cr0, r2, 0x5 + beq+ 1f ;// TODO: need to handle HMIs? +1: ;// Unknown reason. + b 1b + + ;// @fn intvect_system_reset_inactive + ;// Handle SRESET on an inactive processor. + ;// This is due to either instruction start or winkle-wakeup. +intvect_system_reset_inactive: + ;// Check winkle state in CPU. + ld r1, CPU_STATUS(r2) + extrdi. r1, r1, 1, CPU_STATUS_WINKLED + beq+ _start + + ;// Now we are a winkled processor that is awoken. + ld r1, CPU_KERNEL_STACK(r2) + ld r1, 0(r1) + mtsprg3 r1 + b kernel_dispatch_task + ;// @fn intvect_system_reset_decrementer ;// Handle SRESET due to decrementer wake-up. - ;// This is a wake-up from 'doze'. Clear priviledge escalation and + ;// This is a wake-up from 'nap'. Clear priviledge escalation and ;// perform decrementer. intvect_system_reset_decrementer: - ;// Restore CR. - mtcr r1 - - ;// Clear MSR mask, since privilaged instruction was now executed (doze). + ;// Clear MSR mask, since privilaged instruction was now executed (nap). mfsprg3 r1 ;// Load task structure to r1. li r2, 0 ;// Zero r2. std r2, TASK_MSR_MASK(r1) ;// Zero msr_mask. - ;// Advance saved NIA (past doze). + ;// Advance saved NIA (past nap). mfsrr0 r1 addi r1, r1, 4 mtsrr0 r1 @@ -600,13 +636,10 @@ intvect_system_reset_decrementer: ;// @fn intvect_system_reset_external ;// Handle SRESET due to wake-up from external interrupt. - ;// This is a wake-up from 'doze', but not due to the decrementer - ;// itself firing. Therefore, leave 'doze' process state alone + ;// This is a wake-up from 'nap', but not due to the decrementer + ;// itself firing. Therefore, leave 'nap' process state alone ;// including NIA and handle the external interrupt. intvect_system_reset_external: - ;// Restore CR. - mtcr r1 - ;// Restore save registers. mfsprg0 r1 mfsprg1 r2 @@ -638,9 +671,9 @@ system_call_fast_path: bne cr0, 4f ;// Check for being on master processor. mfsprg3 r6 ;// Get task structure. - ld r6, 0(r6) ;// Get CPU structure. - lbz r6, 12(r6) ;// Read master boolean. - cmpi cr0, r6, 0x0 + ld r6, TASK_CPUPTR(r6) ;// Get CPU structure. + ld r6, CPU_STATUS(r6) ;// Read master boolean. + extrdi. r6, r6, 1, CPU_STATUS_MASTER beq cr0, 300f ;// Call TASK_MIGRATE_TO_MASTER if not on master. ;// Read scratch. mtspr 276, r4 @@ -665,9 +698,9 @@ system_call_fast_path: bne cr0, 5f ;// Check for master processor. mfsprg3 r6 ;// Get task structure. - ld r6, 0(r6) ;// Get CPU structure. - lbz r6, 12(r6) ;// Read master boolean. - cmpi cr0, r6, 0x0 + ld r6, TASK_CPUPTR(r6) ;// Get CPU structure. + ld r6, CPU_STATUS(r6) ;// Read master boolean. + extrdi. r6, r6, 1, CPU_STATUS_MASTER beq cr0, 300b ;// Call TASK_MIGRATE_TO_MASTER if not on master. ;// Write scratch. mtspr 276, r4 @@ -785,6 +818,34 @@ kernel_shutdown_ea0_1_mode: STD_INTERRUPT_NOADDR(hype_emu_assist) + ;// @fn kernel_execute_winkle + ;// + ;// Saves kernel state into a specified task structure and then executes + ;// the winkle instruction. + ;// + ;// @param r3 - task_t* to save kernel state into. + ;// +.global kernel_execute_winkle +kernel_execute_winkle: + ;// Move save area to SPRG3 for kernel_save_task. + mtsprg3 r3 + + ;// Copy LR to SRR0 (since that is where kernel_save_task gets it from). + mflr r3 + mtsrr0 r3 + + ;// Load winkle instruction address into the "return to" address (SPRG0). + lis r3, 1f@h + ori r3, r3, 1f@l + mtsprg0 r3 + + ;// Save kernel state. + b kernel_save_task + + ;// Execute winkle. +1: + rvwinkle + .section .data .balign 1024 kernel_stack: diff --git a/src/kernel/syscall.C b/src/kernel/syscall.C index 6dcbe0c25..645691d70 100644 --- a/src/kernel/syscall.C +++ b/src/kernel/syscall.C @@ -52,19 +52,7 @@ void kernel_execute_decrementer() task_t* current_task = TaskManager::getCurrentTask(); - CpuManager::executePeriodics(c);//TODO is there still a potential deadlock? - - if (CpuManager::isShutdownRequested()) - { - // The code below could cause a hang during shutdown - // The stats can be retrieved from global variables as needed. - // This can be uncommented for debug if desired -#ifdef __MEMSTATS__ - if(c->master) - HeapManager::stats(); -#endif - KernelMisc::shutdown(); - } + CpuManager::executePeriodics(c); if (current_task == TaskManager::getCurrentTask()) { @@ -98,7 +86,8 @@ namespace Systemcalls void CpuDDLevel(task_t *t); void CpuStartCore(task_t *t); void CpuSprValue(task_t *t); - void CpuDoze(task_t *t); + void CpuNap(task_t *t); + void CpuWinkle(task_t *t); void MmAllocBlock(task_t *t); void MmRemovePages(task_t *t); void MmSetPermission(task_t *t); @@ -134,7 +123,8 @@ namespace Systemcalls &CpuDDLevel, // MISC_CPUDDLEVEL &CpuStartCore, // MISC_CPUSTARTCORE &CpuSprValue, // MISC_CPUSPRVALUE - &CpuDoze, // MISC_CPUDOZE + &CpuNap, // MISC_CPUNAP + &CpuWinkle, // MISC_CPUWINKLE &MmAllocBlock, // MM_ALLOC_BLOCK &MmRemovePages, // MM_REMOVE_PAGES @@ -670,33 +660,52 @@ namespace Systemcalls }; /** - * Allow a task to request priviledge escalation to execute the 'doze' + * Allow a task to request priviledge escalation to execute the 'nap' * instruction. * - * Verifies the instruction to execute is, in fact, doze and then sets + * Verifies the instruction to execute is, in fact, nap and then sets * an MSR mask in the task structure to allow escalation on next * execution. * - * When 'doze' is executed the processor will eventually issue an + * When 'nap' is executed the processor will eventually issue an * SRESET exception with flags in srr1 to indication that the * decrementer caused the wake-up. The kernel will then need to - * advance the task to the instruction after the doze and remove + * advance the task to the instruction after the nap and remove * priviledge escalation. * */ - void CpuDoze(task_t *t) + void CpuNap(task_t *t) { uint32_t* instruction = static_cast(t->context.nip); - if (0x4c000324 == (*instruction)) // Verify 'doze' instruction, + if (0x4c000364 == (*instruction)) // Verify 'nap' instruction, // otherwise just return. { - // Disable PR, IR, DR so 'doze' can be executed. + // Disable PR, IR, DR so 'nap' can be executed. // (which means to stay in HV state) t->context.msr_mask = 0x4030; } }; + /** Winkle all the threads so that the runtime SLW image can be loaded. */ + void CpuWinkle(task_t *t) + { + cpu_t* cpu = CpuManager::getCurrentCPU(); + + if ((CpuManager::getCpuCount() > CpuManager::getThreadCount()) || + (!cpu->master)) + { + TASK_SETRTN(t, -EDEADLK); + } + else + { + TASK_SETRTN(t, 0); + DeferredQueue::insert(new KernelMisc::WinkleCore(t)); + TaskManager::setCurrentTask(cpu->idle_task); + DeferredQueue::execute(); + } + } + /** * Allocate a block of virtual memory within the base segment * @param[in] t: The task used to allocate a block in the base segment diff --git a/src/lib/syscall_misc.C b/src/lib/syscall_misc.C index 7b23ef22b..c1b47b772 100644 --- a/src/lib/syscall_misc.C +++ b/src/lib/syscall_misc.C @@ -25,6 +25,7 @@ #include #include +#include using namespace Systemcalls; @@ -85,6 +86,13 @@ uint64_t cpu_spr_value(CpuSprNames spr) int cpu_master_winkle() { - return 0; + task_affinity_pin(); + task_affinity_migrate_to_master(); + + int rc = reinterpret_cast(_syscall0(MISC_CPUWINKLE)); + + task_affinity_unpin(); + + return rc; } diff --git a/src/makefile b/src/makefile index 4a59af354..4dcc6006a 100644 --- a/src/makefile +++ b/src/makefile @@ -29,7 +29,8 @@ EXTRA_LIDS = dslid BASE_OBJECTS = console.o spinlock.o string.o string_ext.o stdlib.o ctype.o \ assert.o stdio.o builtins.o vfs_init.o heapmgr.o pagemgr.o \ - math.o barrier.o idebug.o intmsghandler.o idletask.o splaytree.o + math.o barrier.o idebug.o intmsghandler.o deferred.o \ + idletask.o splaytree.o ifdef HOSTBOOT_PROFILE BASE_OBJECTS += gcov.o diff --git a/src/sys/prof/idletask.C b/src/sys/prof/idletask.C index da568f955..1c38835ce 100644 --- a/src/sys/prof/idletask.C +++ b/src/sys/prof/idletask.C @@ -42,11 +42,11 @@ void TaskManager::idleTaskLoop(void* unused) // Lower priority (and yield simics thread). setThreadPriorityLow(); - // Request privilege escalation for doze. - register uint64_t syscall = MISC_CPUDOZE; - asm volatile("or 3, %0, %0; sc" :: "r" (syscall) : "r3"); + // Request privilege escalation for nap. + register uint64_t syscall = MISC_CPUNAP; + asm volatile("or 3, %0, %0; sc" :: "r" (syscall) : "r3", "cc"); - // Execute doze. - doze(); + // Execute nap. + nap(); } } diff --git a/src/usr/hwpf/hwp/core_activate/core_activate.C b/src/usr/hwpf/hwp/core_activate/core_activate.C index 99d02baab..7e50c93e3 100644 --- a/src/usr/hwpf/hwp/core_activate/core_activate.C +++ b/src/usr/hwpf/hwp/core_activate/core_activate.C @@ -134,6 +134,9 @@ using namespace ISTEP; "proc_prep_master_winkle SUCCESS" ); } + if (is_vpo()) // TODO: RTC 46651 - Simics doesn't support winkle. + { + // put the master into winkle. TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "call_host_activate_master: put master into winkle..." ); @@ -163,11 +166,7 @@ using namespace ISTEP; break; } - - // -------------------------------------------------------- - // $$ @todo do something to trigger IPI at this point. - // MAGIC_INSTRUCTION( ???? ); - // -------------------------------------------------------- + } // TODO: Remove with RTC 46651 // -------------------------------------------------------- -- cgit v1.2.1