Merge zizzer.eecs.umich.edu:/bk/newmem
into zeep.pool:/y/binkertn/research/m5/rtc --HG-- extra : convert_revision : 65ddda89f38c5fa874722c20e5d82ed1bb4e12d9
This commit is contained in:
commit
1c2949a2ff
|
@ -57,25 +57,77 @@ using namespace std;
|
||||||
//Should this be AlphaISA?
|
//Should this be AlphaISA?
|
||||||
using namespace TheISA;
|
using namespace TheISA;
|
||||||
|
|
||||||
TsunamiIO::RTC::RTC(const string &n, Tsunami* tsunami, time_t t, Tick i)
|
TsunamiIO::RTC::RTC(const string &n, Tsunami* tsunami, const vector<int> &t,
|
||||||
: _name(n), event(tsunami, i), addr(0)
|
bool bcd, Tick i)
|
||||||
|
: _name(n), event(tsunami, i), addr(0), year_is_bcd(bcd)
|
||||||
{
|
{
|
||||||
memset(clock_data, 0, sizeof(clock_data));
|
memset(clock_data, 0, sizeof(clock_data));
|
||||||
stat_regA = RTCA_32768HZ | RTCA_1024HZ;
|
stat_regA = RTCA_32768HZ | RTCA_1024HZ;
|
||||||
stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR;
|
stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR;
|
||||||
|
|
||||||
|
if (year_is_bcd) {
|
||||||
|
// The RTC uses BCD for the last two digits in the year.
|
||||||
|
// They python year is a full year.
|
||||||
|
int _year = t[0] % 100;
|
||||||
|
int tens = _year / 10;
|
||||||
|
int ones = _year % 10;
|
||||||
|
|
||||||
|
year = (tens << 4) + ones;
|
||||||
|
} else {
|
||||||
|
// Even though the datasheet says that the year field should be
|
||||||
|
// interpreted as BCD, we just enter the number of years since
|
||||||
|
// 1900 since linux seems to be happy with that (and I believe
|
||||||
|
// that Tru64 was as well)
|
||||||
|
year = t[0] - 1900;
|
||||||
|
}
|
||||||
|
|
||||||
|
mon = t[1];
|
||||||
|
mday = t[2];
|
||||||
|
hour = t[3];
|
||||||
|
min = t[4];
|
||||||
|
sec = t[5];
|
||||||
|
|
||||||
|
// wday is defined to be in the range from 1 - 7 with 1 being Sunday.
|
||||||
|
// the value coming from python is in the range from 0 - 6 with 0 being
|
||||||
|
// Monday. Fix that here.
|
||||||
|
wday = t[6] + 2;
|
||||||
|
if (wday > 7)
|
||||||
|
wday -= 7;
|
||||||
|
|
||||||
|
DPRINTFN("Real-time clock set to %s", getDateString());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
TsunamiIO::RTC::getDateString()
|
||||||
|
{
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
gmtime_r(&t, &tm);
|
|
||||||
|
|
||||||
sec = tm.tm_sec;
|
memset(&tm, 0, sizeof(tm));
|
||||||
min = tm.tm_min;
|
|
||||||
hour = tm.tm_hour;
|
|
||||||
wday = tm.tm_wday + 1;
|
|
||||||
mday = tm.tm_mday;
|
|
||||||
mon = tm.tm_mon + 1;
|
|
||||||
year = tm.tm_year;
|
|
||||||
|
|
||||||
DPRINTFN("Real-time clock set to %s", asctime(&tm));
|
if (year_is_bcd) {
|
||||||
|
// undo the BCD and conver to years since 1900 guessing that
|
||||||
|
// anything before 1970 is actually after 2000
|
||||||
|
int _year = (year >> 4) * 10 + (year & 0xf);
|
||||||
|
if (_year < 70)
|
||||||
|
_year += 100;
|
||||||
|
|
||||||
|
tm.tm_year = _year;
|
||||||
|
} else {
|
||||||
|
// number of years since 1900
|
||||||
|
tm.tm_year = year;
|
||||||
|
}
|
||||||
|
|
||||||
|
// unix is 0-11 for month
|
||||||
|
tm.tm_mon = mon - 1;
|
||||||
|
tm.tm_mday = mday;
|
||||||
|
tm.tm_hour = hour;
|
||||||
|
tm.tm_min = min;
|
||||||
|
tm.tm_sec = sec;
|
||||||
|
|
||||||
|
// to add more annoyance unix is 0 - 6 with 0 as sunday
|
||||||
|
tm.tm_wday = wday - 1;
|
||||||
|
|
||||||
|
return asctime(&tm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -424,7 +476,8 @@ TsunamiIO::PITimer::Counter::CounterEvent::description()
|
||||||
|
|
||||||
TsunamiIO::TsunamiIO(Params *p)
|
TsunamiIO::TsunamiIO(Params *p)
|
||||||
: BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"),
|
: BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"),
|
||||||
rtc(p->name + ".rtc", p->tsunami, p->init_time, p->frequency)
|
rtc(p->name + ".rtc", p->tsunami, p->init_time, p->year_is_bcd,
|
||||||
|
p->frequency)
|
||||||
{
|
{
|
||||||
pioSize = 0x100;
|
pioSize = 0x100;
|
||||||
|
|
||||||
|
@ -649,7 +702,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO)
|
||||||
Param<Tick> frequency;
|
Param<Tick> frequency;
|
||||||
SimObjectParam<Platform *> platform;
|
SimObjectParam<Platform *> platform;
|
||||||
SimObjectParam<System *> system;
|
SimObjectParam<System *> system;
|
||||||
Param<time_t> time;
|
VectorParam<int> time;
|
||||||
|
Param<bool> year_is_bcd;
|
||||||
SimObjectParam<Tsunami *> tsunami;
|
SimObjectParam<Tsunami *> tsunami;
|
||||||
|
|
||||||
END_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO)
|
END_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO)
|
||||||
|
@ -662,6 +716,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiIO)
|
||||||
INIT_PARAM(platform, "platform"),
|
INIT_PARAM(platform, "platform"),
|
||||||
INIT_PARAM(system, "system object"),
|
INIT_PARAM(system, "system object"),
|
||||||
INIT_PARAM(time, "System time to use (0 for actual time"),
|
INIT_PARAM(time, "System time to use (0 for actual time"),
|
||||||
|
INIT_PARAM(year_is_bcd, ""),
|
||||||
INIT_PARAM(tsunami, "Tsunami")
|
INIT_PARAM(tsunami, "Tsunami")
|
||||||
|
|
||||||
END_INIT_SIM_OBJECT_PARAMS(TsunamiIO)
|
END_INIT_SIM_OBJECT_PARAMS(TsunamiIO)
|
||||||
|
@ -676,6 +731,7 @@ CREATE_SIM_OBJECT(TsunamiIO)
|
||||||
p->platform = platform;
|
p->platform = platform;
|
||||||
p->system = system;
|
p->system = system;
|
||||||
p->init_time = time;
|
p->init_time = time;
|
||||||
|
p->year_is_bcd = year_is_bcd;
|
||||||
p->tsunami = tsunami;
|
p->tsunami = tsunami;
|
||||||
return new TsunamiIO(p);
|
return new TsunamiIO(p);
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,9 @@ class TsunamiIO : public BasicPioDevice
|
||||||
/** Current RTC register address/index */
|
/** Current RTC register address/index */
|
||||||
int addr;
|
int addr;
|
||||||
|
|
||||||
|
/** should the year be interpreted as BCD? */
|
||||||
|
bool year_is_bcd;
|
||||||
|
|
||||||
/** Data for real-time clock function */
|
/** Data for real-time clock function */
|
||||||
union {
|
union {
|
||||||
uint8_t clock_data[10];
|
uint8_t clock_data[10];
|
||||||
|
@ -110,7 +113,8 @@ class TsunamiIO : public BasicPioDevice
|
||||||
uint8_t stat_regB;
|
uint8_t stat_regB;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RTC(const std::string &name, Tsunami* tsunami, time_t t, Tick i);
|
RTC(const std::string &name, Tsunami* tsunami,
|
||||||
|
const std::vector<int> &t, bool bcd, Tick i);
|
||||||
|
|
||||||
/** RTC address port: write address of RTC RAM data to access */
|
/** RTC address port: write address of RTC RAM data to access */
|
||||||
void writeAddr(const uint8_t data);
|
void writeAddr(const uint8_t data);
|
||||||
|
@ -121,6 +125,9 @@ class TsunamiIO : public BasicPioDevice
|
||||||
/** RTC read data */
|
/** RTC read data */
|
||||||
uint8_t readData();
|
uint8_t readData();
|
||||||
|
|
||||||
|
/** RTC get the date */
|
||||||
|
std::string getDateString();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize this object to the given output stream.
|
* Serialize this object to the given output stream.
|
||||||
* @param base The base name of the counter object.
|
* @param base The base name of the counter object.
|
||||||
|
@ -313,8 +320,10 @@ class TsunamiIO : public BasicPioDevice
|
||||||
{
|
{
|
||||||
Tick frequency;
|
Tick frequency;
|
||||||
Tsunami *tsunami;
|
Tsunami *tsunami;
|
||||||
time_t init_time;
|
std::vector<int> init_time;
|
||||||
|
bool year_is_bcd;
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const Params *params() const { return (const Params*)_params; }
|
const Params *params() const { return (const Params*)_params; }
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,10 @@ class TsunamiCChip(BasicPioDevice):
|
||||||
|
|
||||||
class TsunamiIO(BasicPioDevice):
|
class TsunamiIO(BasicPioDevice):
|
||||||
type = 'TsunamiIO'
|
type = 'TsunamiIO'
|
||||||
time = Param.Time('01/01/2009',
|
time = Param.Time('01/01/2006',
|
||||||
"System time to use ('Now' for actual time)")
|
"System time to use ('Now' for actual time)")
|
||||||
|
year_is_bcd = Param.Bool(False,
|
||||||
|
"The RTC should interpret the year as a BCD value")
|
||||||
tsunami = Param.Tsunami(Parent.any, "Tsunami")
|
tsunami = Param.Tsunami(Parent.any, "Tsunami")
|
||||||
frequency = Param.Frequency('1024Hz', "frequency of interrupts")
|
frequency = Param.Frequency('1024Hz', "frequency of interrupts")
|
||||||
|
|
||||||
|
|
|
@ -518,49 +518,55 @@ class EthernetAddr(ParamValue):
|
||||||
else:
|
else:
|
||||||
return self.value
|
return self.value
|
||||||
|
|
||||||
def parse_time(value):
|
time_formats = [ "%a %b %d %H:%M:%S %Z %Y",
|
||||||
strings = [ "%a %b %d %H:%M:%S %Z %Y",
|
"%a %b %d %H:%M:%S %Z %Y",
|
||||||
"%a %b %d %H:%M:%S %Z %Y",
|
"%Y/%m/%d %H:%M:%S",
|
||||||
"%Y/%m/%d %H:%M:%S",
|
"%Y/%m/%d %H:%M",
|
||||||
"%Y/%m/%d %H:%M",
|
"%Y/%m/%d",
|
||||||
"%Y/%m/%d",
|
"%m/%d/%Y %H:%M:%S",
|
||||||
"%m/%d/%Y %H:%M:%S",
|
"%m/%d/%Y %H:%M",
|
||||||
"%m/%d/%Y %H:%M",
|
"%m/%d/%Y",
|
||||||
"%m/%d/%Y",
|
"%m/%d/%y %H:%M:%S",
|
||||||
"%m/%d/%y %H:%M:%S",
|
"%m/%d/%y %H:%M",
|
||||||
"%m/%d/%y %H:%M",
|
"%m/%d/%y"]
|
||||||
"%m/%d/%y"]
|
|
||||||
|
|
||||||
for string in strings:
|
|
||||||
try:
|
def parse_time(value):
|
||||||
return time.strptime(value, string)
|
from time import gmtime, strptime, struct_time, time
|
||||||
except ValueError:
|
from datetime import datetime, date
|
||||||
pass
|
|
||||||
|
if isinstance(value, struct_time):
|
||||||
|
return value
|
||||||
|
|
||||||
|
if isinstance(value, (int, long)):
|
||||||
|
return gmtime(value)
|
||||||
|
|
||||||
|
if isinstance(value, (datetime, date)):
|
||||||
|
return value.timetuple()
|
||||||
|
|
||||||
|
if isinstance(value, str):
|
||||||
|
if value in ('Now', 'Today'):
|
||||||
|
return time.gmtime(time.time())
|
||||||
|
|
||||||
|
for format in time_formats:
|
||||||
|
try:
|
||||||
|
return strptime(value, format)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
raise ValueError, "Could not parse '%s' as a time" % value
|
raise ValueError, "Could not parse '%s' as a time" % value
|
||||||
|
|
||||||
class Time(ParamValue):
|
class Time(ParamValue):
|
||||||
cxx_type = 'time_t'
|
cxx_type = 'time_t'
|
||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
if isinstance(value, time.struct_time):
|
self.value = parse_time(value)
|
||||||
self.value = time.mktime(value)
|
|
||||||
elif isinstance(value, int):
|
|
||||||
self.value = value
|
|
||||||
elif isinstance(value, str):
|
|
||||||
if value in ('Now', 'Today'):
|
|
||||||
self.value = time.time()
|
|
||||||
else:
|
|
||||||
self.value = time.mktime(parse_time(value))
|
|
||||||
elif isinstance(value, (datetime.datetime, datetime.date)):
|
|
||||||
self.value = time.mktime(value.timetuple())
|
|
||||||
else:
|
|
||||||
raise ValueError, "Could not parse '%s' as a time" % value
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(int(self.value))
|
tm = self.value
|
||||||
|
return ' '.join([ str(tm[i]) for i in xrange(8)])
|
||||||
|
|
||||||
def ini_str(self):
|
def ini_str(self):
|
||||||
return str(int(self.value))
|
return str(self)
|
||||||
|
|
||||||
# Enumerated types are a little more complex. The user specifies the
|
# Enumerated types are a little more complex. The user specifies the
|
||||||
# type as Enum(foo) where foo is either a list or dictionary of
|
# type as Enum(foo) where foo is either a list or dictionary of
|
||||||
|
|
Loading…
Reference in a new issue