Propose :
在 low power design 上, "Power Management" 佔了很重要的地位. 利用 Power ON/OFF 來開關 Devices, 讓沒有在 work 的 devices 能進入 "Sleep" or "Shutdown" Mode... ,而這些判斷機制主要是透過上層的 software 演算法來決策. 因為過度的 ON/OFF 會消耗 "switch power", 讓電容不斷的 charge and discharge 導致不必要的 Power 消耗, 有時甚至比待機時候還來的耗電. 所以在 Power Management software design 上, 透過 control signal 打給底層的 hardware, 讓 hardware 有 state 上的變化, 再藉由每個不同的 state 來 define devices 的 on/off.
Target :
用 c++ 來模擬 Power Management 的 hardware mode.
底下我們用 Linux 的 Power Management 來當例子.
Ref: state define and detail info
Linux power management
other Refs :
Android Power Management
Power Planning
power_man.h
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <list>
using namespace std;
enum PWSTATE {
PW_RUN =0,
PW_STANDBY =1,
PW_SLEEP =2,
PW_SHUTDOWN =3,
PW_NOP =4,
};
enum PWSWITCH {
ON =0,
OFF =1,
SLEEP =2,
LOW =3,
};
enum PWERROR {
CUR2NXT_OK =0,
CUR2NXT_ERR =1,
CUR2PUT_OK =2,
CUR2PUT_ERR =3,
};
template<class T>
class Power_Man_IN {
public:
T ReBoot;
T Activity;
T InActivity;
T ShutDown;
T CLK;
T Button;
};
template<class T>
class Power_Man_OT {
public:
T CPU;
T LCD;
T Keys;
T Audio;
};
class Power_Man {
public:
Power_Man_IN<int8_t> PW_MN_IN_Pt;
Power_Man_OT<int8_t> PW_MN_OT_Pt;
list<Power_Man_IN<int8_t> > TST_VEC_LIST;
int8_t Cur_ST;
int8_t Nxt_ST;
void SET2PW_MN_IN(int8_t r,int8_t a,int8_t i,int8_t s,int8_t c,int8_t b);
void SET2PW_MN_OT(int8_t c,int8_t l,int8_t k,int8_t a);
int8_t PRO2PW_MN();
int8_t Put2OutREG();
void DisPlaySET2PW_MN_IN();
void DisPlaySET2PW_MN_OT();
//================================
// Test Bench
//================================
void SET_TEST_VECTOR(int8_t r,int8_t a,int8_t i,int8_t s,int8_t c,int8_t b);
void SET_TEST_LIST();
};
power_man.cpp
//#include <systemc.h>
#include "power_man.h"
void Power_Man::SET_TEST_VECTOR(int8_t r,int8_t a,int8_t i,int8_t s,int8_t c,int8_t b){
Power_Man_IN<int8_t> *VECPt = new Power_Man_IN<int8_t>;
VECPt->ReBoot = r;
VECPt->Activity = a;
VECPt->InActivity = i;
VECPt->ShutDown = s;
VECPt->CLK = c;
VECPt->Button = b;
TST_VEC_LIST.push_back(*VECPt);
delete VECPt;
}
//====================================
// Write your Test Bench here
//====================================
void Power_Man::SET_TEST_LIST(){
Cur_ST = PW_NOP;
Nxt_ST = PW_NOP;
SET_TEST_VECTOR(OFF, OFF, OFF, OFF, OFF, OFF);
// Set to Run ST
SET_TEST_VECTOR(ON, OFF, OFF, OFF, OFF, OFF);
SET_TEST_VECTOR(OFF, OFF, OFF, OFF, OFF, OFF);
SET_TEST_VECTOR(OFF, OFF, OFF, OFF, OFF, OFF);
// Set to STANDBY
SET_TEST_VECTOR(OFF, OFF, ON, OFF, OFF, OFF);
SET_TEST_VECTOR(OFF, OFF, OFF, OFF, OFF, OFF);
SET_TEST_VECTOR(OFF, OFF, OFF, OFF, OFF, OFF);
}
void Power_Man::SET2PW_MN_IN(int8_t r,int8_t a,int8_t i,int8_t s,int8_t c,int8_t b){
PW_MN_IN_Pt.ReBoot = r;
PW_MN_IN_Pt.Activity = a;
PW_MN_IN_Pt.InActivity = i;
PW_MN_IN_Pt.ShutDown = s;
PW_MN_IN_Pt.CLK = c;
PW_MN_IN_Pt.Button = b;
}
void Power_Man::SET2PW_MN_OT(int8_t c,int8_t l,int8_t k,int8_t a){
PW_MN_OT_Pt.CPU = c;
PW_MN_OT_Pt.LCD = l;
PW_MN_OT_Pt.Keys = k;
PW_MN_OT_Pt.Audio = a;
}
int8_t Power_Man::PRO2PW_MN(){
switch(Cur_ST){
case PW_RUN : Nxt_ST = (PW_MN_IN_Pt.InActivity == ON )? PW_STANDBY :
(PW_MN_IN_Pt.ShutDown == ON )? PW_SHUTDOWN : PW_RUN; break;
case PW_STANDBY : Nxt_ST = (PW_MN_IN_Pt.InActivity == ON )? PW_SLEEP :
(PW_MN_IN_Pt.Activity == ON )? PW_RUN : PW_STANDBY; break;
case PW_SLEEP : Nxt_ST = (PW_MN_IN_Pt.Activity == ON )? PW_RUN : PW_SLEEP; break;
case PW_SHUTDOWN: Nxt_ST = (PW_MN_IN_Pt.Button == ON )? PW_RUN : PW_SHUTDOWN; break;
case PW_NOP : Nxt_ST = (PW_MN_IN_Pt.ReBoot == ON )? PW_RUN : PW_NOP; break;
default: return CUR2NXT_ERR; break;
}
Cur_ST = Nxt_ST;
return CUR2NXT_OK;
}
int8_t Power_Man::Put2OutREG(){
switch(Cur_ST){
case PW_RUN : SET2PW_MN_OT(ON, ON, ON, ON ); break;
case PW_STANDBY : SET2PW_MN_OT(LOW, OFF, ON, ON ); break;
case PW_SLEEP : SET2PW_MN_OT(SLEEP,OFF, OFF, OFF); break;
case PW_SHUTDOWN: SET2PW_MN_OT(SLEEP,OFF, OFF, OFF); break;
case PW_NOP : SET2PW_MN_OT(OFF, OFF, OFF, OFF); break;
default: return CUR2PUT_ERR; break;
}
return CUR2PUT_OK;
}
void Power_Man::DisPlaySET2PW_MN_IN(){
int8_t r = PW_MN_IN_Pt.ReBoot;
int8_t a = PW_MN_IN_Pt.Activity;
int8_t i = PW_MN_IN_Pt.InActivity;
int8_t s = PW_MN_IN_Pt.ShutDown;
int8_t c = PW_MN_IN_Pt.CLK;
int8_t b = PW_MN_IN_Pt.Button;
cout<<"CTL\t"<<"CLK:\t"<<int(c)<<"\tREBT:\t"<<int(r)<<"\tACT:\t"<<int(a)<<"\tINACT:\t"<<int(i)<<"\tSHTDN:\t"<<int(s)<<"\tBUTTON:\t"<<int(b)<<endl;
}
void Power_Man::DisPlaySET2PW_MN_OT(){
int8_t c = PW_MN_OT_Pt.CPU;
int8_t l = PW_MN_OT_Pt.LCD;
int8_t k = PW_MN_OT_Pt.Keys;
int8_t a = PW_MN_OT_Pt.Audio;
cout<<"PUT\t"<<"CPU:\t"<<int(c)<<"\tLCD:\t"<<int(l)<<"\tKEYS:\t"<<int(k)<<"\tAUDIO:\t"<<int(a)<<endl;
}
int main() {
_List_iterator<Power_Man_IN<int8_t> > it;
Power_Man *PW_MN_Pt = new Power_Man;
PW_MN_Pt->SET_TEST_LIST();
for(it=PW_MN_Pt->TST_VEC_LIST.begin(); it!=PW_MN_Pt->TST_VEC_LIST.end(); it++){
if( PW_MN_Pt->Put2OutREG()!= CUR2PUT_OK ){
cout<<"CUR2PUT Error"<<endl; return -1; }
PW_MN_Pt->DisPlaySET2PW_MN_OT();
int8_t r = it->ReBoot;
int8_t a = it->Activity;
int8_t i = it->InActivity;
int8_t s = it->ShutDown;
int8_t c = it->CLK;
int8_t b = it->Button;
PW_MN_Pt->SET2PW_MN_IN( r, a, i, s, c, b);
PW_MN_Pt->DisPlaySET2PW_MN_IN();
if( PW_MN_Pt->PRO2PW_MN()!= CUR2NXT_OK ){
cout<<"CUR2NXT Error"<<endl; return -1; }
}
delete PW_MN_Pt;
return 0;
}
Results:
PUT CPU: 1 LCD: 1 KEYS: 1 AUDIO: 1
CTL CLK: 1 REBT: 1 ACT: 1 INACT: 1 SHTDN: 1 BUTTON: 1
PUT CPU: 1 LCD: 1 KEYS: 1 AUDIO: 1
CTL CLK: 1 REBT: 0 ACT: 1 INACT: 1 SHTDN: 1 BUTTON: 1
PUT CPU: 0 LCD: 0 KEYS: 0 AUDIO: 0
CTL CLK: 1 REBT: 1 ACT: 1 INACT: 1 SHTDN: 1 BUTTON: 1
PUT CPU: 0 LCD: 0 KEYS: 0 AUDIO: 0
CTL CLK: 1 REBT: 1 ACT: 1 INACT: 1 SHTDN: 1 BUTTON: 1
PUT CPU: 0 LCD: 0 KEYS: 0 AUDIO: 0
CTL CLK: 1 REBT: 1 ACT: 1 INACT: 0 SHTDN: 1 BUTTON: 1
PUT CPU: 3 LCD: 1 KEYS: 0 AUDIO: 0
PS:目前只有考慮 CPU, LCD, KEYS, AUDIO 的 control. 當然你也可以自己 define
所要 control 的 devices
download :
http://sites.google.com/site/funningboy/c/power_man.cpp?attredirects=0&d=1
http://sites.google.com/site/funningboy/c/power_man.h?attredirects=0&d=1
Essential Linux Device Drivers
回覆刪除http://elinuxdd.com/~elinuxdd/elinuxdd.docs/sources.html
ACPI
回覆刪除http://www.acpica.org/download/acpica-reference.pdf