2014-01-25 Mikael Pettersson * src/itc.c, src/itc.h: new, implement a 2MHz ITC * src/exec_hd.c, src/read.c, src/sim.c, src/state.c, src/write.c: adjust for the new ITC implementation * src/Makefile.am: list itc.c and itc.h diff -rupN ski-1.3.2/src/Makefile.am ski-1.3.2.2MHz-ITC/src/Makefile.am --- ski-1.3.2/src/Makefile.am 2008-02-05 05:11:38.000000000 +0100 +++ ski-1.3.2.2MHz-ITC/src/Makefile.am 2014-01-25 12:49:47.170584453 +0100 @@ -144,6 +144,7 @@ skiinclude_HEADERS= \ simmem.h \ os_support.h \ platform.h \ + itc.h \ sim.h \ ski.h \ state.h \ @@ -232,6 +233,7 @@ libski_la_SOURCES= \ $(IAEXEC_DECODER_DERIVED) \ $(ICNT_DERIVED) \ state.c \ + itc.c \ sim.c \ simmem.c \ float.c \ diff -rupN ski-1.3.2/src/exec_hd.c ski-1.3.2.2MHz-ITC/src/exec_hd.c --- ski-1.3.2/src/exec_hd.c 2008-02-05 05:11:38.000000000 +0100 +++ ski-1.3.2.2MHz-ITC/src/exec_hd.c 2014-01-25 12:49:47.170584453 +0100 @@ -41,6 +41,7 @@ #include "ia_state.h" #include "ia_exec.h" #include "ssc.h" +#include "itc.h" #define HYPERLAZY /* To support non-hyperlazy RSE, Ski must implement a RNAT array instead of a single diff -rupN ski-1.3.2/src/itc.c ski-1.3.2.2MHz-ITC/src/itc.c --- ski-1.3.2/src/itc.c 1970-01-01 01:00:00.000000000 +0100 +++ ski-1.3.2.2MHz-ITC/src/itc.c 2014-01-25 12:49:50.940573588 +0100 @@ -0,0 +1,154 @@ +/* + * Simulates a 2.0 MHz ITC on top of setitimer(ITIMER_REAL) and gettimeofday(). + * + * The 2.0 MHz frequency is chosen because it matches the Linux kernel's default + * for CONFIG_IA64_HP_SIM=y: SAL_FREQ_BASE_PLATFORM=200MHz, itc_ratio=1/100. + */ + +#include +#include +#include +#include +#include +#include +#include "itc.h" + +static unsigned long long itm; +static unsigned long long itc; +static struct timeval tv; +static int itimer_active; +char itc_itimer_fired; + +static void onalrm(int sig) +{ + itc_itimer_fired = 1; +} + +static void itimer_stop(void) +{ + if (itimer_active) { + struct itimerval itv; + + memset(&itv, 0, sizeof itv); + setitimer(ITIMER_REAL, &itv, NULL); + itimer_active = 0; + } +} + +/* + * PRE: + * - !itimer_active + * - tv and itc in sync + */ +static void itimer_start(void) +{ + unsigned long long ticks, usecs, seconds; + struct itimerval itv; + static int catch_sigalrm_done; + + itc_itimer_fired = 0; + + ticks = itm - itc; + + usecs = ticks / 2ULL; + if ((ticks % 2ULL) != 0) + ++usecs; + + itv.it_value.tv_usec = usecs % 1000000ULL; + seconds = usecs / 1000000ULL; + itv.it_value.tv_sec = + (seconds > (unsigned long long)LONG_MAX) + ? LONG_MAX + : (long)seconds; + + if (itv.it_value.tv_sec == 0 && itv.it_value.tv_usec == 0) { + itc_itimer_fired = 1; + return; + } + + itv.it_interval.tv_sec = 0; + itv.it_interval.tv_usec = 0; + + if (!catch_sigalrm_done) { + struct sigaction act; + + catch_sigalrm_done = 1; + + memset(&act, 0, sizeof act); + act.sa_handler = onalrm; + + if (sigaction(SIGALRM, &act, NULL) == -1) { + perror("sigaction"); + exit(1); + } + } + + itimer_active = 1; + if (setitimer(ITIMER_REAL, &itv, NULL) == -1) { + perror("setitimer"); + exit(1); + } +} + +static void tv_update(void) +{ + if (gettimeofday(&tv, NULL) == -1) { + perror("gettimeofday"); + exit(1); + } +} + +static unsigned long long tv_update_ticks(void) +{ + struct timeval prev_tv; + unsigned long long usecs; + + prev_tv = tv; + + tv_update(); + + if (prev_tv.tv_sec == 0 && prev_tv.tv_usec == 0) + return 1; /* the ITC always increments.. */ + + usecs = ((tv.tv_sec - prev_tv.tv_sec) * 1000000LL + + tv.tv_usec + - prev_tv.tv_usec); + + if (usecs == 0) + return 1; /* the ITC always increments.. */ + + return usecs * 2; +} + +static void itc_update(void) +{ + itc += tv_update_ticks(); +} + +unsigned long long itc_read(void) +{ + itc_update(); + return itc; +} + +void itc_write(unsigned long long val) +{ + itimer_stop(); + tv_update(); + itc = val; + itimer_start(); +} + +void itm_write(unsigned long long val) +{ + itimer_stop(); + itc_update(); + itm = val; + itimer_start(); +} + +void itc_untick(int flag) +{ + if (flag) + itc_itimer_fired = 1; +} diff -rupN ski-1.3.2/src/itc.h ski-1.3.2.2MHz-ITC/src/itc.h --- ski-1.3.2/src/itc.h 1970-01-01 01:00:00.000000000 +0100 +++ ski-1.3.2.2MHz-ITC/src/itc.h 2014-01-25 12:49:47.180584420 +0100 @@ -0,0 +1,19 @@ +#ifndef _SKI_ITC_H +#define _SKI_ITC_H + +void itc_write(unsigned long long); +unsigned long long itc_read(void); +void itm_write(unsigned long long); +void itc_untick(int); + +extern char itc_itimer_fired; + +static __inline__ int itc_tick_overflow(void) +{ + if (!itc_itimer_fired) + return 0; + itc_itimer_fired = 0; + return 1; +} + +#endif /* _SKI_ITC_H */ diff -rupN ski-1.3.2/src/read.c ski-1.3.2.2MHz-ITC/src/read.c --- ski-1.3.2/src/read.c 2008-02-05 05:11:38.000000000 +0100 +++ ski-1.3.2.2MHz-ITC/src/read.c 2014-01-25 12:49:47.180584420 +0100 @@ -29,6 +29,7 @@ #include "fields.h" #include "state.h" #include "sim.h" +#include "itc.h" Status illRd(INSTINFO *info) { @@ -1217,7 +1218,10 @@ Status brIARd(INSTINFO *info) Status oneArRd(INSTINFO *info) { - SRC1 = ArRd(ar3); + if (ar3 == ITC_ID) + SRC1 = itc_read(); + else + SRC1 = ArRd(ar3); return PrRd(qp); } diff -rupN ski-1.3.2/src/sim.c ski-1.3.2.2MHz-ITC/src/sim.c --- ski-1.3.2/src/sim.c 2008-02-05 05:11:38.000000000 +0100 +++ ski-1.3.2.2MHz-ITC/src/sim.c 2014-01-25 12:52:42.850149431 +0100 @@ -62,6 +62,7 @@ #include "instinfo.h" #include "icnt_core.h" #include "os_support.h" +#include "itc.h" #define ALARM @@ -273,7 +274,7 @@ rseDB(char *s) static void updateTmrs(void) { - if (++ITC == ITM && !IMASK(ITV)) + if (itc_tick_overflow() && !IMASK(ITV)) pendIrpt(ITV); if (sscPend && --sscPend->irptcnt <= 0) { pendSscIrpt(sscPend->type); @@ -808,7 +809,7 @@ Status iCycleSys(void) } } else /* Fault */ icp = NULL; - if (++ITC == ITM && !IMASK(ITV)) + if (itc_tick_overflow() && !IMASK(ITV)) pendIrpt(ITV); if (sscPend && --sscPend->irptcnt <= 0) pendSscIrpt(sscPend->type); @@ -1679,7 +1680,7 @@ lbl: } total_insts++; - if (++ITC == ITM && !IMASK(ITV)) + if (itc_tick_overflow() && !IMASK(ITV)) pendIrpt(ITV); if (sscPend && --sscPend->irptcnt <= 0) pendSscIrpt(sscPend->type); @@ -1713,6 +1714,7 @@ static Status iCycleSysLoopLite(unsigned unsigned long cycle_count = 0L; BOOL psr_ic = PSR_IC; Status st; + int itc_overflow_flag = 0; do { INSTINFO *info = icp; @@ -1763,7 +1765,8 @@ static Status iCycleSysLoopLite(unsigned --insn_count; /* should we break the loop? */ - if (++ITC == ITM || !icp || st & ST_CHECK || intrsim) { + itc_overflow_flag = itc_tick_overflow(); + if (itc_overflow_flag || !icp || st & ST_CHECK || intrsim) { break; } @@ -1771,7 +1774,7 @@ static Status iCycleSysLoopLite(unsigned /* ITC will get incremented upon return, restore value */ - --ITC; + itc_untick(itc_overflow_flag); /* update the counters */ total_insts += count - insn_count; @@ -1839,7 +1842,7 @@ static void iCycleSysLoop(void) } } - if (++ITC == ITM && !IMASK(ITV)) + if (itc_tick_overflow() && !IMASK(ITV)) pendIrpt(ITV); if (sscPend && --sscPend->irptcnt <= 0) diff -rupN ski-1.3.2/src/state.c ski-1.3.2.2MHz-ITC/src/state.c --- ski-1.3.2/src/state.c 2008-02-05 05:11:38.000000000 +0100 +++ ski-1.3.2.2MHz-ITC/src/state.c 2014-01-25 12:49:47.180584420 +0100 @@ -29,6 +29,7 @@ #include "fields.h" #include "state.h" #include "libcore.h" +#include "itc.h" #include @@ -336,7 +337,10 @@ REG arGet(int proc, int i) #ifdef NEW_MP return mpState[proc].ars_[i]; #else - return ars[i]; + if (i == ITC_ID) + return itc_read(); + else + return ars[i]; #endif } @@ -889,7 +893,10 @@ BOOL arSet(int proc, int i, REG val) #ifdef NEW_MP mpState[proc].ars_[i] = val; #else - ars[i] = val; + if (i == ITC_ID) + itc_write(val); + else + ars[i] = val; #endif return YES; } @@ -1016,6 +1023,8 @@ BOOL crSet(int proc, int i, REG val) #ifdef NEW_MP mpState[proc].crs_[i] = val; #else + if (i == ITM_ID) + itm_write(val); crs[i] = val; #endif return YES; diff -rupN ski-1.3.2/src/write.c ski-1.3.2.2MHz-ITC/src/write.c --- ski-1.3.2/src/write.c 2008-02-05 05:11:38.000000000 +0100 +++ ski-1.3.2.2MHz-ITC/src/write.c 2014-01-25 12:49:47.180584420 +0100 @@ -29,6 +29,7 @@ #include "fields.h" #include "state.h" #include "sim.h" +#include "itc.h" void nullWrt(INSTINFO *info) { @@ -132,7 +133,10 @@ void rotPrWrt(INSTINFO *info) void oneArWrt(INSTINFO *info) { traceArTgt(DST1); - ArWrt(ar3, DST1); + if (ar3 == ITC_ID) + itc_write(DST1); + else + ArWrt(ar3, DST1); } void oneFrWrt(INSTINFO *info) @@ -795,6 +799,8 @@ void rfiWrt(INSTINFO *info) void oneCrWrt(INSTINFO *info) { + if (cr3 == ITM_ID) + itm_write(DST1); CrWrt(cr3, DST1); if (cr3 == TPR_ID && acceptIrpt()) intrsim = extint = YES;