summaryrefslogtreecommitdiff
path: root/src/base
diff options
context:
space:
mode:
authorSteve Reinhardt <stever@eecs.umich.edu>2006-05-22 14:29:33 -0400
committerSteve Reinhardt <stever@eecs.umich.edu>2006-05-22 14:29:33 -0400
commitba2eae5d528487900d1510fc0a160e660f2c394c (patch)
treea2c6dd5948f6ff353763cb3f83ddd734077e646e /src/base
parent86777c9db174c74be49667bce3dda99f8ba23696 (diff)
downloadgem5-ba2eae5d528487900d1510fc0a160e660f2c394c.tar.xz
New directory structure:
- simulator source now in 'src' subdirectory - imported files from 'ext' repository - support building in arbitrary places, including outside of the source tree. See comment at top of SConstruct file for more details. Regression tests are temporarily disabled; that syetem needs more extensive revisions. SConstruct: Update for new directory structure. Modify to support build trees that are not subdirectories of the source tree. See comment at top of file for more details. Regression tests are temporarily disabled. src/arch/SConscript: src/arch/isa_parser.py: src/python/SConscript: Update for new directory structure. --HG-- rename : build/SConstruct => SConstruct rename : build/default_options/ALPHA_FS => build_opts/ALPHA_FS rename : build/default_options/ALPHA_FS_TL => build_opts/ALPHA_FS_TL rename : build/default_options/ALPHA_SE => build_opts/ALPHA_SE rename : build/default_options/MIPS_SE => build_opts/MIPS_SE rename : build/default_options/SPARC_SE => build_opts/SPARC_SE rename : Doxyfile => src/Doxyfile rename : SConscript => src/SConscript rename : arch/SConscript => src/arch/SConscript rename : arch/alpha/SConscript => src/arch/alpha/SConscript rename : arch/alpha/aout_machdep.h => src/arch/alpha/aout_machdep.h rename : arch/alpha/arguments.cc => src/arch/alpha/arguments.cc rename : arch/alpha/arguments.hh => src/arch/alpha/arguments.hh rename : arch/alpha/ecoff_machdep.h => src/arch/alpha/ecoff_machdep.h rename : arch/alpha/ev5.cc => src/arch/alpha/ev5.cc rename : arch/alpha/ev5.hh => src/arch/alpha/ev5.hh rename : arch/alpha/faults.cc => src/arch/alpha/faults.cc rename : arch/alpha/faults.hh => src/arch/alpha/faults.hh rename : arch/alpha/freebsd/system.cc => src/arch/alpha/freebsd/system.cc rename : arch/alpha/freebsd/system.hh => src/arch/alpha/freebsd/system.hh rename : arch/alpha/isa/branch.isa => src/arch/alpha/isa/branch.isa rename : arch/alpha/isa/decoder.isa => src/arch/alpha/isa/decoder.isa rename : arch/alpha/isa/fp.isa => src/arch/alpha/isa/fp.isa rename : arch/alpha/isa/int.isa => src/arch/alpha/isa/int.isa rename : arch/alpha/isa/main.isa => src/arch/alpha/isa/main.isa rename : arch/alpha/isa/mem.isa => src/arch/alpha/isa/mem.isa rename : arch/alpha/isa/opcdec.isa => src/arch/alpha/isa/opcdec.isa rename : arch/alpha/isa/pal.isa => src/arch/alpha/isa/pal.isa rename : arch/alpha/isa/unimp.isa => src/arch/alpha/isa/unimp.isa rename : arch/alpha/isa/unknown.isa => src/arch/alpha/isa/unknown.isa rename : arch/alpha/isa/util.isa => src/arch/alpha/isa/util.isa rename : arch/alpha/isa_traits.hh => src/arch/alpha/isa_traits.hh rename : arch/alpha/linux/aligned.hh => src/arch/alpha/linux/aligned.hh rename : arch/alpha/linux/hwrpb.hh => src/arch/alpha/linux/hwrpb.hh rename : arch/alpha/linux/linux.cc => src/arch/alpha/linux/linux.cc rename : arch/alpha/linux/linux.hh => src/arch/alpha/linux/linux.hh rename : arch/alpha/linux/process.cc => src/arch/alpha/linux/process.cc rename : arch/alpha/linux/process.hh => src/arch/alpha/linux/process.hh rename : arch/alpha/linux/system.cc => src/arch/alpha/linux/system.cc rename : arch/alpha/linux/system.hh => src/arch/alpha/linux/system.hh rename : arch/alpha/linux/thread_info.hh => src/arch/alpha/linux/thread_info.hh rename : arch/alpha/linux/threadinfo.hh => src/arch/alpha/linux/threadinfo.hh rename : arch/alpha/osfpal.cc => src/arch/alpha/osfpal.cc rename : arch/alpha/osfpal.hh => src/arch/alpha/osfpal.hh rename : arch/alpha/process.cc => src/arch/alpha/process.cc rename : arch/alpha/process.hh => src/arch/alpha/process.hh rename : arch/alpha/regfile.hh => src/arch/alpha/regfile.hh rename : arch/alpha/stacktrace.cc => src/arch/alpha/stacktrace.cc rename : arch/alpha/stacktrace.hh => src/arch/alpha/stacktrace.hh rename : arch/alpha/system.cc => src/arch/alpha/system.cc rename : arch/alpha/system.hh => src/arch/alpha/system.hh rename : arch/alpha/tlb.cc => src/arch/alpha/tlb.cc rename : arch/alpha/tlb.hh => src/arch/alpha/tlb.hh rename : arch/alpha/tru64/process.cc => src/arch/alpha/tru64/process.cc rename : arch/alpha/tru64/process.hh => src/arch/alpha/tru64/process.hh rename : arch/alpha/tru64/system.cc => src/arch/alpha/tru64/system.cc rename : arch/alpha/tru64/system.hh => src/arch/alpha/tru64/system.hh rename : arch/alpha/tru64/tru64.cc => src/arch/alpha/tru64/tru64.cc rename : arch/alpha/tru64/tru64.hh => src/arch/alpha/tru64/tru64.hh rename : arch/alpha/types.hh => src/arch/alpha/types.hh rename : arch/alpha/utility.hh => src/arch/alpha/utility.hh rename : arch/alpha/vtophys.cc => src/arch/alpha/vtophys.cc rename : arch/alpha/vtophys.hh => src/arch/alpha/vtophys.hh rename : arch/isa_parser.py => src/arch/isa_parser.py rename : arch/isa_specific.hh => src/arch/isa_specific.hh rename : arch/mips/SConscript => src/arch/mips/SConscript rename : arch/mips/faults.cc => src/arch/mips/faults.cc rename : arch/mips/faults.hh => src/arch/mips/faults.hh rename : arch/mips/isa/base.isa => src/arch/mips/isa/base.isa rename : arch/mips/isa/bitfields.isa => src/arch/mips/isa/bitfields.isa rename : arch/mips/isa/decoder.isa => src/arch/mips/isa/decoder.isa rename : arch/mips/isa/formats/basic.isa => src/arch/mips/isa/formats/basic.isa rename : arch/mips/isa/formats/branch.isa => src/arch/mips/isa/formats/branch.isa rename : arch/mips/isa/formats/formats.isa => src/arch/mips/isa/formats/formats.isa rename : arch/mips/isa/formats/fp.isa => src/arch/mips/isa/formats/fp.isa rename : arch/mips/isa/formats/int.isa => src/arch/mips/isa/formats/int.isa rename : arch/mips/isa/formats/mem.isa => src/arch/mips/isa/formats/mem.isa rename : arch/mips/isa/formats/noop.isa => src/arch/mips/isa/formats/noop.isa rename : arch/mips/isa/formats/tlbop.isa => src/arch/mips/isa/formats/tlbop.isa rename : arch/mips/isa/formats/trap.isa => src/arch/mips/isa/formats/trap.isa rename : arch/mips/isa/formats/unimp.isa => src/arch/mips/isa/formats/unimp.isa rename : arch/mips/isa/formats/unknown.isa => src/arch/mips/isa/formats/unknown.isa rename : arch/mips/isa/formats/util.isa => src/arch/mips/isa/formats/util.isa rename : arch/mips/isa/includes.isa => src/arch/mips/isa/includes.isa rename : arch/mips/isa/main.isa => src/arch/mips/isa/main.isa rename : arch/mips/isa/operands.isa => src/arch/mips/isa/operands.isa rename : arch/mips/isa_traits.cc => src/arch/mips/isa_traits.cc rename : arch/mips/isa_traits.hh => src/arch/mips/isa_traits.hh rename : arch/mips/linux/linux.cc => src/arch/mips/linux/linux.cc rename : arch/mips/linux/linux.hh => src/arch/mips/linux/linux.hh rename : arch/mips/linux/process.cc => src/arch/mips/linux/process.cc rename : arch/mips/linux/process.hh => src/arch/mips/linux/process.hh rename : arch/mips/process.cc => src/arch/mips/process.cc rename : arch/mips/process.hh => src/arch/mips/process.hh rename : arch/mips/regfile/float_regfile.hh => src/arch/mips/regfile/float_regfile.hh rename : arch/mips/regfile/int_regfile.hh => src/arch/mips/regfile/int_regfile.hh rename : arch/mips/regfile/misc_regfile.hh => src/arch/mips/regfile/misc_regfile.hh rename : arch/mips/regfile/regfile.hh => src/arch/mips/regfile/regfile.hh rename : arch/mips/stacktrace.hh => src/arch/mips/stacktrace.hh rename : arch/mips/types.hh => src/arch/mips/types.hh rename : arch/mips/utility.hh => src/arch/mips/utility.hh rename : arch/sparc/SConscript => src/arch/sparc/SConscript rename : arch/sparc/faults.cc => src/arch/sparc/faults.cc rename : arch/sparc/faults.hh => src/arch/sparc/faults.hh rename : arch/sparc/isa/base.isa => src/arch/sparc/isa/base.isa rename : arch/sparc/isa/bitfields.isa => src/arch/sparc/isa/bitfields.isa rename : arch/sparc/isa/decoder.isa => src/arch/sparc/isa/decoder.isa rename : arch/sparc/isa/formats.isa => src/arch/sparc/isa/formats.isa rename : arch/sparc/isa/formats/basic.isa => src/arch/sparc/isa/formats/basic.isa rename : arch/sparc/isa/formats/branch.isa => src/arch/sparc/isa/formats/branch.isa rename : arch/sparc/isa/formats/integerop.isa => src/arch/sparc/isa/formats/integerop.isa rename : arch/sparc/isa/formats/mem.isa => src/arch/sparc/isa/formats/mem.isa rename : arch/sparc/isa/formats/nop.isa => src/arch/sparc/isa/formats/nop.isa rename : arch/sparc/isa/formats/priv.isa => src/arch/sparc/isa/formats/priv.isa rename : arch/sparc/isa/formats/trap.isa => src/arch/sparc/isa/formats/trap.isa rename : arch/sparc/isa/formats/unknown.isa => src/arch/sparc/isa/formats/unknown.isa rename : arch/sparc/isa/includes.isa => src/arch/sparc/isa/includes.isa rename : arch/sparc/isa/main.isa => src/arch/sparc/isa/main.isa rename : arch/sparc/isa/operands.isa => src/arch/sparc/isa/operands.isa rename : arch/sparc/isa_traits.hh => src/arch/sparc/isa_traits.hh rename : arch/sparc/linux/linux.cc => src/arch/sparc/linux/linux.cc rename : arch/sparc/linux/linux.hh => src/arch/sparc/linux/linux.hh rename : arch/sparc/linux/process.cc => src/arch/sparc/linux/process.cc rename : arch/sparc/linux/process.hh => src/arch/sparc/linux/process.hh rename : arch/sparc/process.cc => src/arch/sparc/process.cc rename : arch/sparc/process.hh => src/arch/sparc/process.hh rename : arch/sparc/regfile.hh => src/arch/sparc/regfile.hh rename : arch/sparc/solaris/process.cc => src/arch/sparc/solaris/process.cc rename : arch/sparc/solaris/process.hh => src/arch/sparc/solaris/process.hh rename : arch/sparc/solaris/solaris.cc => src/arch/sparc/solaris/solaris.cc rename : arch/sparc/solaris/solaris.hh => src/arch/sparc/solaris/solaris.hh rename : arch/sparc/stacktrace.hh => src/arch/sparc/stacktrace.hh rename : arch/sparc/system.cc => src/arch/sparc/system.cc rename : arch/sparc/system.hh => src/arch/sparc/system.hh rename : arch/sparc/utility.hh => src/arch/sparc/utility.hh rename : base/bitfield.hh => src/base/bitfield.hh rename : base/callback.hh => src/base/callback.hh rename : base/chunk_generator.hh => src/base/chunk_generator.hh rename : base/circlebuf.cc => src/base/circlebuf.cc rename : base/circlebuf.hh => src/base/circlebuf.hh rename : base/compression/lzss_compression.cc => src/base/compression/lzss_compression.cc rename : base/compression/lzss_compression.hh => src/base/compression/lzss_compression.hh rename : base/compression/null_compression.hh => src/base/compression/null_compression.hh rename : base/cprintf.cc => src/base/cprintf.cc rename : base/cprintf.hh => src/base/cprintf.hh rename : base/cprintf_formats.hh => src/base/cprintf_formats.hh rename : base/crc.cc => src/base/crc.cc rename : base/crc.hh => src/base/crc.hh rename : base/date.cc => src/base/date.cc rename : base/dbl_list.hh => src/base/dbl_list.hh rename : base/endian.hh => src/base/endian.hh rename : base/fast_alloc.cc => src/base/fast_alloc.cc rename : base/fast_alloc.hh => src/base/fast_alloc.hh rename : base/fenv.hh => src/base/fenv.hh rename : base/fifo_buffer.cc => src/base/fifo_buffer.cc rename : base/fifo_buffer.hh => src/base/fifo_buffer.hh rename : base/hashmap.hh => src/base/hashmap.hh rename : base/hostinfo.cc => src/base/hostinfo.cc rename : base/hostinfo.hh => src/base/hostinfo.hh rename : base/hybrid_pred.cc => src/base/hybrid_pred.cc rename : base/hybrid_pred.hh => src/base/hybrid_pred.hh rename : base/inet.cc => src/base/inet.cc rename : base/inet.hh => src/base/inet.hh rename : base/inifile.cc => src/base/inifile.cc rename : base/inifile.hh => src/base/inifile.hh rename : base/intmath.cc => src/base/intmath.cc rename : base/intmath.hh => src/base/intmath.hh rename : base/kgdb.h => src/base/kgdb.h rename : base/loader/aout_object.cc => src/base/loader/aout_object.cc rename : base/loader/aout_object.hh => src/base/loader/aout_object.hh rename : base/loader/coff_sym.h => src/base/loader/coff_sym.h rename : base/loader/coff_symconst.h => src/base/loader/coff_symconst.h rename : base/loader/ecoff_object.cc => src/base/loader/ecoff_object.cc rename : base/loader/ecoff_object.hh => src/base/loader/ecoff_object.hh rename : base/loader/elf_object.cc => src/base/loader/elf_object.cc rename : base/loader/elf_object.hh => src/base/loader/elf_object.hh rename : base/loader/exec_aout.h => src/base/loader/exec_aout.h rename : base/loader/exec_ecoff.h => src/base/loader/exec_ecoff.h rename : base/loader/object_file.cc => src/base/loader/object_file.cc rename : base/loader/object_file.hh => src/base/loader/object_file.hh rename : base/loader/symtab.cc => src/base/loader/symtab.cc rename : base/loader/symtab.hh => src/base/loader/symtab.hh rename : base/match.cc => src/base/match.cc rename : base/match.hh => src/base/match.hh rename : base/misc.cc => src/base/misc.cc rename : base/misc.hh => src/base/misc.hh rename : base/mod_num.hh => src/base/mod_num.hh rename : base/mysql.cc => src/base/mysql.cc rename : base/mysql.hh => src/base/mysql.hh rename : base/output.cc => src/base/output.cc rename : base/output.hh => src/base/output.hh rename : base/pollevent.cc => src/base/pollevent.cc rename : base/pollevent.hh => src/base/pollevent.hh rename : base/predictor.hh => src/base/predictor.hh rename : base/random.cc => src/base/random.cc rename : base/random.hh => src/base/random.hh rename : base/range.cc => src/base/range.cc rename : base/range.hh => src/base/range.hh rename : base/refcnt.hh => src/base/refcnt.hh rename : base/remote_gdb.cc => src/base/remote_gdb.cc rename : base/remote_gdb.hh => src/base/remote_gdb.hh rename : base/res_list.hh => src/base/res_list.hh rename : base/sat_counter.cc => src/base/sat_counter.cc rename : base/sat_counter.hh => src/base/sat_counter.hh rename : base/sched_list.hh => src/base/sched_list.hh rename : base/socket.cc => src/base/socket.cc rename : base/socket.hh => src/base/socket.hh rename : base/statistics.cc => src/base/statistics.cc rename : base/statistics.hh => src/base/statistics.hh rename : base/stats/events.cc => src/base/stats/events.cc rename : base/stats/events.hh => src/base/stats/events.hh rename : base/stats/flags.hh => src/base/stats/flags.hh rename : base/stats/mysql.cc => src/base/stats/mysql.cc rename : base/stats/mysql.hh => src/base/stats/mysql.hh rename : base/stats/mysql_run.hh => src/base/stats/mysql_run.hh rename : base/stats/output.hh => src/base/stats/output.hh rename : base/stats/statdb.cc => src/base/stats/statdb.cc rename : base/stats/statdb.hh => src/base/stats/statdb.hh rename : base/stats/text.cc => src/base/stats/text.cc rename : base/stats/text.hh => src/base/stats/text.hh rename : base/stats/types.hh => src/base/stats/types.hh rename : base/stats/visit.cc => src/base/stats/visit.cc rename : base/stats/visit.hh => src/base/stats/visit.hh rename : base/str.cc => src/base/str.cc rename : base/str.hh => src/base/str.hh rename : base/time.cc => src/base/time.cc rename : base/time.hh => src/base/time.hh rename : base/timebuf.hh => src/base/timebuf.hh rename : base/trace.cc => src/base/trace.cc rename : base/trace.hh => src/base/trace.hh rename : base/traceflags.py => src/base/traceflags.py rename : base/userinfo.cc => src/base/userinfo.cc rename : base/userinfo.hh => src/base/userinfo.hh rename : cpu/SConscript => src/cpu/SConscript rename : cpu/base.cc => src/cpu/base.cc rename : cpu/base.hh => src/cpu/base.hh rename : cpu/base_dyn_inst.cc => src/cpu/base_dyn_inst.cc rename : cpu/base_dyn_inst.hh => src/cpu/base_dyn_inst.hh rename : cpu/cpu_exec_context.cc => src/cpu/cpu_exec_context.cc rename : cpu/cpu_exec_context.hh => src/cpu/cpu_exec_context.hh rename : cpu/cpu_models.py => src/cpu/cpu_models.py rename : cpu/exec_context.hh => src/cpu/exec_context.hh rename : cpu/exetrace.cc => src/cpu/exetrace.cc rename : cpu/exetrace.hh => src/cpu/exetrace.hh rename : cpu/inst_seq.hh => src/cpu/inst_seq.hh rename : cpu/intr_control.cc => src/cpu/intr_control.cc rename : cpu/intr_control.hh => src/cpu/intr_control.hh rename : cpu/memtest/memtest.cc => src/cpu/memtest/memtest.cc rename : cpu/memtest/memtest.hh => src/cpu/memtest/memtest.hh rename : cpu/o3/2bit_local_pred.cc => src/cpu/o3/2bit_local_pred.cc rename : cpu/o3/2bit_local_pred.hh => src/cpu/o3/2bit_local_pred.hh rename : cpu/o3/alpha_cpu.cc => src/cpu/o3/alpha_cpu.cc rename : cpu/o3/alpha_cpu.hh => src/cpu/o3/alpha_cpu.hh rename : cpu/o3/alpha_cpu_builder.cc => src/cpu/o3/alpha_cpu_builder.cc rename : cpu/o3/alpha_cpu_impl.hh => src/cpu/o3/alpha_cpu_impl.hh rename : cpu/o3/alpha_dyn_inst.cc => src/cpu/o3/alpha_dyn_inst.cc rename : cpu/o3/alpha_dyn_inst.hh => src/cpu/o3/alpha_dyn_inst.hh rename : cpu/o3/alpha_dyn_inst_impl.hh => src/cpu/o3/alpha_dyn_inst_impl.hh rename : cpu/o3/alpha_impl.hh => src/cpu/o3/alpha_impl.hh rename : cpu/o3/alpha_params.hh => src/cpu/o3/alpha_params.hh rename : cpu/o3/bpred_unit.cc => src/cpu/o3/bpred_unit.cc rename : cpu/o3/bpred_unit.hh => src/cpu/o3/bpred_unit.hh rename : cpu/o3/bpred_unit_impl.hh => src/cpu/o3/bpred_unit_impl.hh rename : cpu/o3/btb.cc => src/cpu/o3/btb.cc rename : cpu/o3/btb.hh => src/cpu/o3/btb.hh rename : cpu/o3/comm.hh => src/cpu/o3/comm.hh rename : cpu/o3/commit.cc => src/cpu/o3/commit.cc rename : cpu/o3/commit.hh => src/cpu/o3/commit.hh rename : cpu/o3/commit_impl.hh => src/cpu/o3/commit_impl.hh rename : cpu/o3/cpu.cc => src/cpu/o3/cpu.cc rename : cpu/o3/cpu.hh => src/cpu/o3/cpu.hh rename : cpu/o3/cpu_policy.hh => src/cpu/o3/cpu_policy.hh rename : cpu/o3/decode.cc => src/cpu/o3/decode.cc rename : cpu/o3/decode.hh => src/cpu/o3/decode.hh rename : cpu/o3/decode_impl.hh => src/cpu/o3/decode_impl.hh rename : cpu/o3/fetch.cc => src/cpu/o3/fetch.cc rename : cpu/o3/fetch.hh => src/cpu/o3/fetch.hh rename : cpu/o3/fetch_impl.hh => src/cpu/o3/fetch_impl.hh rename : cpu/o3/free_list.cc => src/cpu/o3/free_list.cc rename : cpu/o3/free_list.hh => src/cpu/o3/free_list.hh rename : cpu/o3/iew.cc => src/cpu/o3/iew.cc rename : cpu/o3/iew.hh => src/cpu/o3/iew.hh rename : cpu/o3/iew_impl.hh => src/cpu/o3/iew_impl.hh rename : cpu/o3/inst_queue.cc => src/cpu/o3/inst_queue.cc rename : cpu/o3/inst_queue.hh => src/cpu/o3/inst_queue.hh rename : cpu/o3/inst_queue_impl.hh => src/cpu/o3/inst_queue_impl.hh rename : cpu/o3/mem_dep_unit.cc => src/cpu/o3/mem_dep_unit.cc rename : cpu/o3/mem_dep_unit.hh => src/cpu/o3/mem_dep_unit.hh rename : cpu/o3/mem_dep_unit_impl.hh => src/cpu/o3/mem_dep_unit_impl.hh rename : cpu/o3/ras.cc => src/cpu/o3/ras.cc rename : cpu/o3/ras.hh => src/cpu/o3/ras.hh rename : cpu/o3/regfile.hh => src/cpu/o3/regfile.hh rename : cpu/o3/rename.cc => src/cpu/o3/rename.cc rename : cpu/o3/rename.hh => src/cpu/o3/rename.hh rename : cpu/o3/rename_impl.hh => src/cpu/o3/rename_impl.hh rename : cpu/o3/rename_map.cc => src/cpu/o3/rename_map.cc rename : cpu/o3/rename_map.hh => src/cpu/o3/rename_map.hh rename : cpu/o3/rob.cc => src/cpu/o3/rob.cc rename : cpu/o3/rob.hh => src/cpu/o3/rob.hh rename : cpu/o3/rob_impl.hh => src/cpu/o3/rob_impl.hh rename : cpu/o3/sat_counter.cc => src/cpu/o3/sat_counter.cc rename : cpu/o3/sat_counter.hh => src/cpu/o3/sat_counter.hh rename : cpu/o3/store_set.cc => src/cpu/o3/store_set.cc rename : cpu/o3/store_set.hh => src/cpu/o3/store_set.hh rename : cpu/o3/tournament_pred.cc => src/cpu/o3/tournament_pred.cc rename : cpu/o3/tournament_pred.hh => src/cpu/o3/tournament_pred.hh rename : cpu/op_class.cc => src/cpu/op_class.cc rename : cpu/op_class.hh => src/cpu/op_class.hh rename : cpu/ozone/cpu.cc => src/cpu/ozone/cpu.cc rename : cpu/ozone/cpu.hh => src/cpu/ozone/cpu.hh rename : cpu/ozone/cpu_impl.hh => src/cpu/ozone/cpu_impl.hh rename : cpu/ozone/ea_list.cc => src/cpu/ozone/ea_list.cc rename : cpu/ozone/ea_list.hh => src/cpu/ozone/ea_list.hh rename : cpu/pc_event.cc => src/cpu/pc_event.cc rename : cpu/pc_event.hh => src/cpu/pc_event.hh rename : cpu/profile.cc => src/cpu/profile.cc rename : cpu/profile.hh => src/cpu/profile.hh rename : cpu/simple/atomic.cc => src/cpu/simple/atomic.cc rename : cpu/simple/atomic.hh => src/cpu/simple/atomic.hh rename : cpu/simple/base.cc => src/cpu/simple/base.cc rename : cpu/simple/base.hh => src/cpu/simple/base.hh rename : cpu/simple/timing.cc => src/cpu/simple/timing.cc rename : cpu/simple/timing.hh => src/cpu/simple/timing.hh rename : cpu/smt.hh => src/cpu/smt.hh rename : cpu/static_inst.cc => src/cpu/static_inst.cc rename : cpu/static_inst.hh => src/cpu/static_inst.hh rename : cpu/trace/opt_cpu.cc => src/cpu/trace/opt_cpu.cc rename : cpu/trace/opt_cpu.hh => src/cpu/trace/opt_cpu.hh rename : cpu/trace/reader/ibm_reader.cc => src/cpu/trace/reader/ibm_reader.cc rename : cpu/trace/reader/ibm_reader.hh => src/cpu/trace/reader/ibm_reader.hh rename : cpu/trace/reader/itx_reader.cc => src/cpu/trace/reader/itx_reader.cc rename : cpu/trace/reader/itx_reader.hh => src/cpu/trace/reader/itx_reader.hh rename : cpu/trace/reader/m5_reader.cc => src/cpu/trace/reader/m5_reader.cc rename : cpu/trace/reader/m5_reader.hh => src/cpu/trace/reader/m5_reader.hh rename : cpu/trace/reader/mem_trace_reader.cc => src/cpu/trace/reader/mem_trace_reader.cc rename : cpu/trace/reader/mem_trace_reader.hh => src/cpu/trace/reader/mem_trace_reader.hh rename : cpu/trace/trace_cpu.cc => src/cpu/trace/trace_cpu.cc rename : cpu/trace/trace_cpu.hh => src/cpu/trace/trace_cpu.hh rename : dev/alpha_access.h => src/dev/alpha_access.h rename : dev/alpha_console.cc => src/dev/alpha_console.cc rename : dev/alpha_console.hh => src/dev/alpha_console.hh rename : dev/baddev.cc => src/dev/baddev.cc rename : dev/baddev.hh => src/dev/baddev.hh rename : dev/disk_image.cc => src/dev/disk_image.cc rename : dev/disk_image.hh => src/dev/disk_image.hh rename : dev/etherbus.cc => src/dev/etherbus.cc rename : dev/etherbus.hh => src/dev/etherbus.hh rename : dev/etherdump.cc => src/dev/etherdump.cc rename : dev/etherdump.hh => src/dev/etherdump.hh rename : dev/etherint.cc => src/dev/etherint.cc rename : dev/etherint.hh => src/dev/etherint.hh rename : dev/etherlink.cc => src/dev/etherlink.cc rename : dev/etherlink.hh => src/dev/etherlink.hh rename : dev/etherpkt.cc => src/dev/etherpkt.cc rename : dev/etherpkt.hh => src/dev/etherpkt.hh rename : dev/ethertap.cc => src/dev/ethertap.cc rename : dev/ethertap.hh => src/dev/ethertap.hh rename : dev/ide_atareg.h => src/dev/ide_atareg.h rename : dev/ide_ctrl.cc => src/dev/ide_ctrl.cc rename : dev/ide_ctrl.hh => src/dev/ide_ctrl.hh rename : dev/ide_disk.cc => src/dev/ide_disk.cc rename : dev/ide_disk.hh => src/dev/ide_disk.hh rename : dev/ide_wdcreg.h => src/dev/ide_wdcreg.h rename : dev/io_device.cc => src/dev/io_device.cc rename : dev/io_device.hh => src/dev/io_device.hh rename : dev/isa_fake.cc => src/dev/isa_fake.cc rename : dev/isa_fake.hh => src/dev/isa_fake.hh rename : dev/ns_gige.cc => src/dev/ns_gige.cc rename : dev/ns_gige.hh => src/dev/ns_gige.hh rename : dev/ns_gige_reg.h => src/dev/ns_gige_reg.h rename : dev/pciconfigall.cc => src/dev/pciconfigall.cc rename : dev/pciconfigall.hh => src/dev/pciconfigall.hh rename : dev/pcidev.cc => src/dev/pcidev.cc rename : dev/pcidev.hh => src/dev/pcidev.hh rename : dev/pcireg.h => src/dev/pcireg.h rename : dev/pitreg.h => src/dev/pitreg.h rename : dev/pktfifo.cc => src/dev/pktfifo.cc rename : dev/pktfifo.hh => src/dev/pktfifo.hh rename : dev/platform.cc => src/dev/platform.cc rename : dev/platform.hh => src/dev/platform.hh rename : dev/rtcreg.h => src/dev/rtcreg.h rename : dev/simconsole.cc => src/dev/simconsole.cc rename : dev/simconsole.hh => src/dev/simconsole.hh rename : dev/simple_disk.cc => src/dev/simple_disk.cc rename : dev/simple_disk.hh => src/dev/simple_disk.hh rename : dev/sinic.cc => src/dev/sinic.cc rename : dev/sinic.hh => src/dev/sinic.hh rename : dev/sinicreg.hh => src/dev/sinicreg.hh rename : dev/tsunami.cc => src/dev/tsunami.cc rename : dev/tsunami.hh => src/dev/tsunami.hh rename : dev/tsunami_cchip.cc => src/dev/tsunami_cchip.cc rename : dev/tsunami_cchip.hh => src/dev/tsunami_cchip.hh rename : dev/tsunami_io.cc => src/dev/tsunami_io.cc rename : dev/tsunami_io.hh => src/dev/tsunami_io.hh rename : dev/tsunami_pchip.cc => src/dev/tsunami_pchip.cc rename : dev/tsunami_pchip.hh => src/dev/tsunami_pchip.hh rename : dev/tsunamireg.h => src/dev/tsunamireg.h rename : dev/uart.cc => src/dev/uart.cc rename : dev/uart.hh => src/dev/uart.hh rename : dev/uart8250.cc => src/dev/uart8250.cc rename : dev/uart8250.hh => src/dev/uart8250.hh rename : kern/kernel_stats.cc => src/kern/kernel_stats.cc rename : kern/kernel_stats.hh => src/kern/kernel_stats.hh rename : kern/linux/events.cc => src/kern/linux/events.cc rename : kern/linux/events.hh => src/kern/linux/events.hh rename : kern/linux/linux.hh => src/kern/linux/linux.hh rename : kern/linux/linux_syscalls.cc => src/kern/linux/linux_syscalls.cc rename : kern/linux/linux_syscalls.hh => src/kern/linux/linux_syscalls.hh rename : kern/linux/printk.cc => src/kern/linux/printk.cc rename : kern/linux/printk.hh => src/kern/linux/printk.hh rename : kern/linux/sched.hh => src/kern/linux/sched.hh rename : kern/solaris/solaris.hh => src/kern/solaris/solaris.hh rename : kern/system_events.cc => src/kern/system_events.cc rename : kern/system_events.hh => src/kern/system_events.hh rename : kern/tru64/dump_mbuf.cc => src/kern/tru64/dump_mbuf.cc rename : kern/tru64/dump_mbuf.hh => src/kern/tru64/dump_mbuf.hh rename : kern/tru64/mbuf.hh => src/kern/tru64/mbuf.hh rename : kern/tru64/printf.cc => src/kern/tru64/printf.cc rename : kern/tru64/printf.hh => src/kern/tru64/printf.hh rename : kern/tru64/tru64.hh => src/kern/tru64/tru64.hh rename : kern/tru64/tru64_events.cc => src/kern/tru64/tru64_events.cc rename : kern/tru64/tru64_events.hh => src/kern/tru64/tru64_events.hh rename : kern/tru64/tru64_syscalls.cc => src/kern/tru64/tru64_syscalls.cc rename : kern/tru64/tru64_syscalls.hh => src/kern/tru64/tru64_syscalls.hh rename : mem/bridge.cc => src/mem/bridge.cc rename : mem/bridge.hh => src/mem/bridge.hh rename : mem/bus.cc => src/mem/bus.cc rename : mem/bus.hh => src/mem/bus.hh rename : mem/cache/prefetch/tagged_prefetcher_impl.hh => src/mem/cache/prefetch/tagged_prefetcher_impl.hh rename : mem/config/prefetch.hh => src/mem/config/prefetch.hh rename : mem/mem_object.cc => src/mem/mem_object.cc rename : mem/mem_object.hh => src/mem/mem_object.hh rename : mem/packet.cc => src/mem/packet.cc rename : mem/packet.hh => src/mem/packet.hh rename : mem/page_table.cc => src/mem/page_table.cc rename : mem/page_table.hh => src/mem/page_table.hh rename : mem/physical.cc => src/mem/physical.cc rename : mem/physical.hh => src/mem/physical.hh rename : mem/port.cc => src/mem/port.cc rename : mem/port.hh => src/mem/port.hh rename : mem/request.hh => src/mem/request.hh rename : mem/translating_port.cc => src/mem/translating_port.cc rename : mem/translating_port.hh => src/mem/translating_port.hh rename : mem/vport.cc => src/mem/vport.cc rename : mem/vport.hh => src/mem/vport.hh rename : python/SConscript => src/python/SConscript rename : python/m5/__init__.py => src/python/m5/__init__.py rename : python/m5/config.py => src/python/m5/config.py rename : python/m5/convert.py => src/python/m5/convert.py rename : python/m5/multidict.py => src/python/m5/multidict.py rename : python/m5/objects/AlphaConsole.py => src/python/m5/objects/AlphaConsole.py rename : python/m5/objects/AlphaFullCPU.py => src/python/m5/objects/AlphaFullCPU.py rename : python/m5/objects/AlphaTLB.py => src/python/m5/objects/AlphaTLB.py rename : python/m5/objects/BadDevice.py => src/python/m5/objects/BadDevice.py rename : python/m5/objects/BaseCPU.py => src/python/m5/objects/BaseCPU.py rename : python/m5/objects/BaseCache.py => src/python/m5/objects/BaseCache.py rename : python/m5/objects/Bridge.py => src/python/m5/objects/Bridge.py rename : python/m5/objects/Bus.py => src/python/m5/objects/Bus.py rename : python/m5/objects/CoherenceProtocol.py => src/python/m5/objects/CoherenceProtocol.py rename : python/m5/objects/Device.py => src/python/m5/objects/Device.py rename : python/m5/objects/DiskImage.py => src/python/m5/objects/DiskImage.py rename : python/m5/objects/Ethernet.py => src/python/m5/objects/Ethernet.py rename : python/m5/objects/Ide.py => src/python/m5/objects/Ide.py rename : python/m5/objects/IntrControl.py => src/python/m5/objects/IntrControl.py rename : python/m5/objects/MemObject.py => src/python/m5/objects/MemObject.py rename : python/m5/objects/MemTest.py => src/python/m5/objects/MemTest.py rename : python/m5/objects/Pci.py => src/python/m5/objects/Pci.py rename : python/m5/objects/PhysicalMemory.py => src/python/m5/objects/PhysicalMemory.py rename : python/m5/objects/Platform.py => src/python/m5/objects/Platform.py rename : python/m5/objects/Process.py => src/python/m5/objects/Process.py rename : python/m5/objects/Repl.py => src/python/m5/objects/Repl.py rename : python/m5/objects/Root.py => src/python/m5/objects/Root.py rename : python/m5/objects/SimConsole.py => src/python/m5/objects/SimConsole.py rename : python/m5/objects/SimpleDisk.py => src/python/m5/objects/SimpleDisk.py rename : python/m5/objects/System.py => src/python/m5/objects/System.py rename : python/m5/objects/Tsunami.py => src/python/m5/objects/Tsunami.py rename : python/m5/objects/Uart.py => src/python/m5/objects/Uart.py rename : python/m5/smartdict.py => src/python/m5/smartdict.py rename : sim/async.hh => src/sim/async.hh rename : sim/builder.cc => src/sim/builder.cc rename : sim/builder.hh => src/sim/builder.hh rename : sim/byteswap.hh => src/sim/byteswap.hh rename : sim/debug.cc => src/sim/debug.cc rename : sim/debug.hh => src/sim/debug.hh rename : sim/eventq.cc => src/sim/eventq.cc rename : sim/eventq.hh => src/sim/eventq.hh rename : sim/faults.cc => src/sim/faults.cc rename : sim/faults.hh => src/sim/faults.hh rename : sim/host.hh => src/sim/host.hh rename : sim/main.cc => src/sim/main.cc rename : sim/param.cc => src/sim/param.cc rename : sim/param.hh => src/sim/param.hh rename : sim/process.cc => src/sim/process.cc rename : sim/process.hh => src/sim/process.hh rename : sim/pseudo_inst.cc => src/sim/pseudo_inst.cc rename : sim/pseudo_inst.hh => src/sim/pseudo_inst.hh rename : sim/root.cc => src/sim/root.cc rename : sim/serialize.cc => src/sim/serialize.cc rename : sim/serialize.hh => src/sim/serialize.hh rename : sim/sim_events.cc => src/sim/sim_events.cc rename : sim/sim_events.hh => src/sim/sim_events.hh rename : sim/sim_exit.hh => src/sim/sim_exit.hh rename : sim/sim_object.cc => src/sim/sim_object.cc rename : sim/sim_object.hh => src/sim/sim_object.hh rename : sim/startup.cc => src/sim/startup.cc rename : sim/startup.hh => src/sim/startup.hh rename : sim/stat_control.cc => src/sim/stat_control.cc rename : sim/stat_control.hh => src/sim/stat_control.hh rename : sim/stats.hh => src/sim/stats.hh rename : sim/syscall_emul.cc => src/sim/syscall_emul.cc rename : sim/syscall_emul.hh => src/sim/syscall_emul.hh rename : sim/system.cc => src/sim/system.cc rename : sim/system.hh => src/sim/system.hh rename : sim/vptr.hh => src/sim/vptr.hh rename : test/Makefile => src/unittest/Makefile rename : test/bitvectest.cc => src/unittest/bitvectest.cc rename : test/circletest.cc => src/unittest/circletest.cc rename : test/cprintftest.cc => src/unittest/cprintftest.cc rename : test/foo.ini => src/unittest/foo.ini rename : test/genini.py => src/unittest/genini.py rename : test/initest.cc => src/unittest/initest.cc rename : test/initest.ini => src/unittest/initest.ini rename : test/lru_test.cc => src/unittest/lru_test.cc rename : test/nmtest.cc => src/unittest/nmtest.cc rename : test/offtest.cc => src/unittest/offtest.cc rename : test/paramtest.cc => src/unittest/paramtest.cc rename : test/rangetest.cc => src/unittest/rangetest.cc rename : test/sized_test.cc => src/unittest/sized_test.cc rename : test/stattest.cc => src/unittest/stattest.cc rename : test/strnumtest.cc => src/unittest/strnumtest.cc rename : test/symtest.cc => src/unittest/symtest.cc rename : test/tokentest.cc => src/unittest/tokentest.cc rename : test/tracetest.cc => src/unittest/tracetest.cc extra : convert_revision : cab6a5271ca1b368193cd948e5d3dcc47ab1bd48
Diffstat (limited to 'src/base')
-rw-r--r--src/base/bitfield.hh69
-rw-r--r--src/base/callback.hh122
-rw-r--r--src/base/chunk_generator.hh141
-rw-r--r--src/base/circlebuf.cc213
-rw-r--r--src/base/circlebuf.hh62
-rw-r--r--src/base/compression/lzss_compression.cc171
-rw-r--r--src/base/compression/lzss_compression.hh101
-rw-r--r--src/base/compression/null_compression.hh76
-rw-r--r--src/base/cprintf.cc268
-rw-r--r--src/base/cprintf.hh197
-rw-r--r--src/base/cprintf_formats.hh353
-rw-r--r--src/base/crc.cc114
-rw-r--r--src/base/crc.hh37
-rw-r--r--src/base/date.cc29
-rw-r--r--src/base/dbl_list.hh165
-rw-r--r--src/base/endian.hh41
-rw-r--r--src/base/fast_alloc.cc195
-rw-r--r--src/base/fast_alloc.hh214
-rw-r--r--src/base/fenv.hh52
-rw-r--r--src/base/fifo_buffer.cc40
-rw-r--r--src/base/fifo_buffer.hh86
-rw-r--r--src/base/hashmap.hh85
-rw-r--r--src/base/hostinfo.cc85
-rw-r--r--src/base/hostinfo.hh43
-rw-r--r--src/base/hybrid_pred.cc273
-rw-r--r--src/base/hybrid_pred.hh201
-rw-r--r--src/base/inet.cc207
-rw-r--r--src/base/inet.hh407
-rw-r--r--src/base/inifile.cc433
-rw-r--r--src/base/inifile.hh208
-rw-r--r--src/base/intmath.cc58
-rw-r--r--src/base/intmath.hh230
-rw-r--r--src/base/kgdb.h174
-rw-r--r--src/base/loader/aout_object.cc94
-rw-r--r--src/base/loader/aout_object.hh56
-rw-r--r--src/base/loader/coff_sym.h519
-rw-r--r--src/base/loader/coff_symconst.h200
-rw-r--r--src/base/loader/ecoff_object.cc153
-rw-r--r--src/base/loader/ecoff_object.hh60
-rw-r--r--src/base/loader/elf_object.cc315
-rw-r--r--src/base/loader/elf_object.hh55
-rw-r--r--src/base/loader/exec_aout.h61
-rw-r--r--src/base/loader/exec_ecoff.h110
-rw-r--r--src/base/loader/object_file.cc145
-rw-r--r--src/base/loader/object_file.hh119
-rw-r--r--src/base/loader/symtab.cc137
-rw-r--r--src/base/loader/symtab.hh173
-rw-r--r--src/base/match.cc96
-rw-r--r--src/base/match.hh57
-rw-r--r--src/base/misc.cc124
-rw-r--r--src/base/misc.hh85
-rw-r--r--src/base/mod_num.hh201
-rw-r--r--src/base/mysql.cc110
-rw-r--r--src/base/mysql.hh423
-rw-r--r--src/base/output.cc129
-rw-r--r--src/base/output.hh61
-rw-r--r--src/base/pollevent.cc273
-rw-r--r--src/base/pollevent.hh97
-rw-r--r--src/base/predictor.hh60
-rw-r--r--src/base/random.cc97
-rw-r--r--src/base/random.hh126
-rw-r--r--src/base/range.cc83
-rw-r--r--src/base/range.hh355
-rw-r--r--src/base/refcnt.hh123
-rw-r--r--src/base/remote_gdb.cc1175
-rw-r--r--src/base/remote_gdb.hh209
-rw-r--r--src/base/res_list.hh755
-rw-r--r--src/base/sat_counter.cc268
-rw-r--r--src/base/sat_counter.hh190
-rw-r--r--src/base/sched_list.hh178
-rw-r--r--src/base/socket.cc111
-rw-r--r--src/base/socket.hh49
-rw-r--r--src/base/statistics.cc356
-rw-r--r--src/base/statistics.hh2896
-rw-r--r--src/base/stats/events.cc169
-rw-r--r--src/base/stats/events.hh66
-rw-r--r--src/base/stats/flags.hh73
-rw-r--r--src/base/stats/mysql.cc900
-rw-r--r--src/base/stats/mysql.hh155
-rw-r--r--src/base/stats/mysql_run.hh65
-rw-r--r--src/base/stats/output.hh47
-rw-r--r--src/base/stats/statdb.cc93
-rw-r--r--src/base/stats/statdb.hh74
-rw-r--r--src/base/stats/text.cc736
-rw-r--r--src/base/stats/text.hh77
-rw-r--r--src/base/stats/types.hh49
-rw-r--r--src/base/stats/visit.cc41
-rw-r--r--src/base/stats/visit.hh63
-rw-r--r--src/base/str.cc373
-rw-r--r--src/base/str.hh141
-rw-r--r--src/base/time.cc131
-rw-r--r--src/base/time.hh65
-rw-r--r--src/base/timebuf.hh218
-rw-r--r--src/base/trace.cc350
-rw-r--r--src/base/trace.hh231
-rw-r--r--src/base/traceflags.py316
-rw-r--r--src/base/userinfo.cc41
-rw-r--r--src/base/userinfo.hh36
98 files changed, 20544 insertions, 0 deletions
diff --git a/src/base/bitfield.hh b/src/base/bitfield.hh
new file mode 100644
index 000000000..c59354c7d
--- /dev/null
+++ b/src/base/bitfield.hh
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_BITFIELD_HH__
+#define __BASE_BITFIELD_HH__
+
+#include "sim/host.hh"
+
+/**
+ * Generate a 64-bit mask of 'nbits' 1s, right justified.
+ */
+inline uint64_t
+mask(int nbits)
+{
+ return (nbits == 64) ? (uint64_t)-1LL : (1ULL << nbits) - 1;
+}
+
+
+/**
+ * Extract the bitfield from position 'first' to 'last' (inclusive)
+ * from 'val' and right justify it. MSB is numbered 63, LSB is 0.
+ */
+template <class T>
+inline
+T
+bits(T val, int first, int last)
+{
+ int nbits = first - last + 1;
+ return (val >> last) & mask(nbits);
+}
+
+/**
+ * Sign-extend an N-bit value to 64 bits.
+ */
+template <int N>
+inline
+int64_t
+sext(uint64_t val)
+{
+ int sign_bit = bits(val, N-1, N-1);
+ return sign_bit ? (val | ~mask(N)) : val;
+}
+
+#endif // __BASE_BITFIELD_HH__
diff --git a/src/base/callback.hh b/src/base/callback.hh
new file mode 100644
index 000000000..7b3023505
--- /dev/null
+++ b/src/base/callback.hh
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CALLBACK_HH__
+#define __CALLBACK_HH__
+
+#include <list>
+
+/**
+ * Generic callback class. This base class provides a virtual process
+ * function that gets called when the callback queue is processed.
+ */
+class Callback
+{
+ public:
+ /**
+ * virtualize the destructor to make sure that the correct one
+ * gets called.
+ */
+ virtual ~Callback() {}
+
+ /**
+ * virtual process function that is invoked when the callback
+ * queue is executed.
+ */
+ virtual void process() = 0;
+};
+
+class CallbackQueue
+{
+ protected:
+ /**
+ * Simple typedef for the data structure that stores all of the
+ * callbacks.
+ */
+ typedef std::list<Callback *> queue;
+
+ /**
+ * List of all callbacks. To be called in fifo order.
+ */
+ queue callbacks;
+
+ public:
+ /**
+ * Add a callback to the end of the queue
+ * @param callback the callback to be added to the queue
+ */
+ void add(Callback *callback)
+ {
+ callbacks.push_back(callback);
+ }
+
+ /**
+ * Find out if there are any callbacks in the queue
+ */
+ bool empty() const { return callbacks.empty(); }
+
+ /**
+ * process all callbacks
+ */
+ void process()
+ {
+ queue::iterator i = callbacks.begin();
+ queue::iterator end = callbacks.end();
+
+ while (i != end) {
+ (*i)->process();
+ ++i;
+ }
+ }
+
+ /**
+ * clear the callback queue
+ */
+ void clear()
+ {
+ callbacks.clear();
+ }
+};
+
+/// Helper template class to turn a simple class member function into
+/// a callback.
+template <class T, void (T::* F)()>
+class MakeCallback : public Callback
+{
+ private:
+ T *object;
+
+ public:
+ MakeCallback(T *o)
+ : object(o)
+ { }
+
+ void process() { (object->*F)(); }
+};
+
+#endif // __CALLBACK_HH__
diff --git a/src/base/chunk_generator.hh b/src/base/chunk_generator.hh
new file mode 100644
index 000000000..4f708bd4b
--- /dev/null
+++ b/src/base/chunk_generator.hh
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE__CHUNK_GENERATOR_HH__
+#define __BASE__CHUNK_GENERATOR_HH__
+
+/**
+ * @file
+ * Declaration and inline definition of ChunkGenerator object.
+ */
+
+#include <algorithm>
+#include "base/intmath.hh"
+#include "arch/isa_traits.hh" // for Addr
+
+/**
+ * This class takes an arbitrary memory region (address/length pair)
+ * and generates a series of appropriately (e.g. block- or page-)
+ * aligned chunks covering the same region.
+ *
+ * Example usage:
+
+\code
+ for (ChunkGenerator gen(addr, size, chunkSize); !gen.done(); gen.next()) {
+ doSomethingChunky(gen.addr(), gen.size());
+ }
+\endcode
+ */
+class ChunkGenerator
+{
+ private:
+ /** The starting address of the current chunk. */
+ Addr curAddr;
+ /** The starting address of the next chunk (after the current one). */
+ Addr nextAddr;
+ /** The size of the current chunk (in bytes). */
+ int curSize;
+ /** The number of bytes remaining in the region after the current chunk. */
+ int sizeLeft;
+ /** The start address so we can calculate offset in writing block. */
+ const Addr startAddr;
+ /** The maximum chunk size, e.g., the cache block size or page size. */
+ const int chunkSize;
+
+ public:
+ /**
+ * Constructor.
+ * @param startAddr The starting address of the region.
+ * @param totalSize The total size of the region.
+ * @param _chunkSize The size/alignment of chunks into which
+ * the region should be decomposed.
+ */
+ ChunkGenerator(Addr _startAddr, int totalSize, int _chunkSize)
+ : startAddr(_startAddr), chunkSize(_chunkSize)
+ {
+ // chunkSize must be a power of two
+ assert(chunkSize == 0 || isPowerOf2(chunkSize));
+
+ // set up initial chunk.
+ curAddr = startAddr;
+
+ if (chunkSize == 0) //Special Case, if we see 0, assume no chuncking
+ {
+ nextAddr = startAddr + totalSize;
+ }
+ else
+ {
+ // nextAddr should be *next* chunk start
+ nextAddr = roundUp(startAddr, chunkSize);
+ if (curAddr == nextAddr) {
+ // ... even if startAddr is already chunk-aligned
+ nextAddr += chunkSize;
+ }
+ }
+
+ // how many bytes are left between curAddr and the end of this chunk?
+ int left_in_chunk = nextAddr - curAddr;
+ curSize = std::min(totalSize, left_in_chunk);
+ sizeLeft = totalSize - curSize;
+ }
+
+ /** Return starting address of current chunk. */
+ Addr addr() { return curAddr; }
+ /** Return size in bytes of current chunk. */
+ int size() { return curSize; }
+
+ /** Number of bytes we have already chunked up. */
+ int complete() { return curAddr - startAddr; }
+ /**
+ * Are we done? That is, did the last call to next() advance
+ * past the end of the region?
+ * @return True if yes, false if more to go.
+ */
+ bool done() { return (curSize == 0); }
+
+ /**
+ * Advance generator to next chunk.
+ * @return True if successful, false if unsuccessful
+ * (because we were at the last chunk).
+ */
+ bool next()
+ {
+ if (sizeLeft == 0) {
+ curSize = 0;
+ return false;
+ }
+
+ curAddr = nextAddr;
+ curSize = std::min(sizeLeft, chunkSize);
+ sizeLeft -= curSize;
+ nextAddr += curSize;
+ return true;
+ }
+};
+
+#endif // __BASE__CHUNK_GENERATOR_HH__
diff --git a/src/base/circlebuf.cc b/src/base/circlebuf.cc
new file mode 100644
index 000000000..89bbfd822
--- /dev/null
+++ b/src/base/circlebuf.cc
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <algorithm>
+#include <string>
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "base/circlebuf.hh"
+#include "base/cprintf.hh"
+#include "base/intmath.hh"
+
+using namespace std;
+
+CircleBuf::CircleBuf(int l)
+ : _rollover(false), _buflen(l), _size(0), _start(0), _stop(0)
+{
+ _buf = new char[_buflen];
+}
+
+CircleBuf::~CircleBuf()
+{
+ if (_buf)
+ delete [] _buf;
+}
+
+void
+CircleBuf::dump()
+{
+ cprintf("start = %10d, stop = %10d, buflen = %10d\n",
+ _start, _stop, _buflen);
+ fflush(stdout);
+ ::write(STDOUT_FILENO, _buf, _buflen);
+ ::write(STDOUT_FILENO, "<\n", 2);
+}
+
+void
+CircleBuf::flush()
+{
+ _start = 0;
+ _stop = 0;
+ _rollover = false;
+}
+
+void
+CircleBuf::read(char *b, int len)
+{
+ _size -= len;
+ if (_size < 0)
+ _size = 0;
+
+ if (_stop > _start) {
+ len = min(len, _stop - _start);
+ memcpy(b, _buf + _start, len);
+ _start += len;
+ }
+ else {
+ int endlen = _buflen - _start;
+ if (endlen > len) {
+ memcpy(b, _buf + _start, len);
+ _start += len;
+ }
+ else {
+ memcpy(b, _buf + _start, endlen);
+ _start = min(len - endlen, _stop);
+ memcpy(b + endlen, _buf, _start);
+ }
+ }
+}
+
+void
+CircleBuf::read(int fd, int len)
+{
+ _size -= len;
+ if (_size < 0)
+ _size = 0;
+
+ if (_stop > _start) {
+ len = min(len, _stop - _start);
+ ::write(fd, _buf + _start, len);
+ _start += len;
+ }
+ else {
+ int endlen = _buflen - _start;
+ if (endlen > len) {
+ ::write(fd, _buf + _start, len);
+ _start += len;
+ }
+ else {
+ ::write(fd, _buf + _start, endlen);
+ _start = min(len - endlen, _stop);
+ ::write(fd, _buf, _start);
+ }
+ }
+}
+
+void
+CircleBuf::read(int fd)
+{
+ _size = 0;
+
+ if (_stop > _start) {
+ ::write(fd, _buf + _start, _stop - _start);
+ }
+ else {
+ ::write(fd, _buf + _start, _buflen - _start);
+ ::write(fd, _buf, _stop);
+ }
+
+ _start = _stop;
+}
+
+void
+CircleBuf::read(ostream &out)
+{
+ _size = 0;
+
+ if (_stop > _start) {
+ out.write(_buf + _start, _stop - _start);
+ }
+ else {
+ out.write(_buf + _start, _buflen - _start);
+ out.write(_buf, _stop);
+ }
+
+ _start = _stop;
+}
+
+void
+CircleBuf::readall(int fd)
+{
+ if (_rollover)
+ ::write(fd, _buf + _stop, _buflen - _stop);
+
+ ::write(fd, _buf, _stop);
+ _start = _stop;
+}
+
+void
+CircleBuf::write(char b)
+{
+ write(&b, 1);
+}
+
+void
+CircleBuf::write(const char *b)
+{
+ write(b, strlen(b));
+}
+
+void
+CircleBuf::write(const char *b, int len)
+{
+ if (len <= 0)
+ return;
+
+ _size += len;
+ if (_size > _buflen)
+ _size = _buflen;
+
+ int old_start = _start;
+ int old_stop = _stop;
+
+ if (len >= _buflen) {
+ _start = 0;
+ _stop = _buflen;
+ _rollover = true;
+ memcpy(_buf, b + (len - _buflen), _buflen);
+ return;
+ }
+
+ if (_stop + len <= _buflen) {
+ memcpy(_buf + _stop, b, len);
+ _stop += len;
+ } else {
+ int end_len = _buflen - old_stop;
+ _stop = len - end_len;
+ memcpy(_buf + old_stop, b, end_len);
+ memcpy(_buf, b + end_len, _stop);
+ _rollover = true;
+ }
+
+ if (old_start > old_stop && old_start < _stop ||
+ old_start < old_stop && _stop < old_stop)
+ _start = _stop + 1;
+}
diff --git a/src/base/circlebuf.hh b/src/base/circlebuf.hh
new file mode 100644
index 000000000..8a64cb5f5
--- /dev/null
+++ b/src/base/circlebuf.hh
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CIRCLEBUF_HH__
+#define __CIRCLEBUF_HH__
+
+#include <iosfwd>
+
+class CircleBuf
+{
+ protected:
+ char *_buf;
+ bool _rollover;
+ int _buflen;
+ int _size;
+ int _start;
+ int _stop;
+
+ public:
+ explicit CircleBuf(int l);
+ ~CircleBuf();
+
+ bool empty() const { return _size == 0; }
+ int size() const { return _size; }
+ void dump();
+ void flush();
+ void read(char *b, int len);
+ void read(int fd, int len);
+ void read(int fd);
+ void read(std::ostream &out);
+ void readall(int fd);
+ void write(char b);
+ void write(const char *b);
+ void write(const char *b, int len);
+};
+
+#endif // __CIRCLEBUF_HH__
diff --git a/src/base/compression/lzss_compression.cc b/src/base/compression/lzss_compression.cc
new file mode 100644
index 000000000..3ffdf7e95
--- /dev/null
+++ b/src/base/compression/lzss_compression.cc
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * LZSSCompression definitions.
+ */
+
+#include <assert.h>
+
+#include "base/compression/lzss_compression.hh"
+
+#include "base/misc.hh" //for fatal
+
+void
+LZSSCompression::findSubString(uint8_t *src, int back, int size, uint16_t &L,
+ uint16_t &P)
+{
+ int front = 0;
+ int max_length = size - back;
+ L = 0;
+ P = back - 1;
+ while (front < back) {
+ while (src[front] != src[back] && front < back) ++front;
+ if (front >= back) {
+ return;
+ }
+ int i = 1;
+ while (src[front+i] == src[back+i] && i < max_length) ++i;
+ if (i >= L) {
+ L = i;
+ P = front;
+ }
+ if (src[front+i] != src[back+i-1]) {
+ // can't find a longer substring until past this point.
+ front += i;
+ } else {
+ ++front;
+ }
+ }
+}
+
+int
+LZSSCompression::emitByte(uint8_t *dest, uint8_t byte)
+{
+ if ((byte >> 5 & 0x7) == 0 || (byte >> 5 & 0x7) == 7) {
+ // If the top 3 bits are the same, emit 00<6bits>
+ dest[0] = byte & 0x3f;
+ return 1;
+ } else {
+ // emit 01XXXXXX <8 bits>
+ dest[0] = 0x40;
+ dest[1] = byte;
+ return 2;
+ }
+}
+
+void
+LZSSCompression::emitString(uint8_t *dest, uint16_t P, uint16_t L)
+{
+ // Emit 1<7P> <5P><3L> <8L>
+ dest[0] = 1<<7 | (P >> 5 & 0x7f);
+ dest[1] = ((P & 0x1f) << 3) | (L>>8 & 0x3);
+ dest[2] = L & 0xFF;
+}
+
+int
+LZSSCompression::compress(uint8_t *dest, uint8_t *src, int size)
+{
+ if (size > 4096) {
+ fatal("Compression can only handle block sizes of 4096 bytes or less");
+ }
+
+ // Encode the first byte.
+ int dest_index = emitByte(dest, src[0]);
+ int i = 1;
+ // A 11 bit field
+ uint16_t L;
+ // A 12 bit field
+ uint16_t P = 0;
+
+ while (i < size && dest_index < size) {
+ L = 0;
+
+ if (dest_index+3 >= size) {
+ dest_index = size;
+ continue;
+ }
+
+ if (i == size - 1) {
+ // Output the character
+ dest_index += emitByte(&dest[dest_index], src[i]);
+ ++i;
+ continue;
+ }
+ findSubString(src, i, size, L, P);
+ if (L > 1) {
+ // Output the string reference
+ emitString(&dest[dest_index], P, L);
+ dest_index += 3;
+ i = i+L;
+ } else {
+ // Output the character
+ dest_index += emitByte(&dest[dest_index], src[i]);
+ ++i;
+ }
+ }
+
+ if (dest_index >= size) {
+ // Have expansion instead of compression, just copy.
+ memcpy(dest,src,size);
+ return size;
+ }
+ return dest_index;
+}
+
+int
+LZSSCompression::uncompress(uint8_t *dest, uint8_t *src, int size)
+{
+ int index = 0;
+ int i = 0;
+ while (i < size) {
+ if (src[i] & 1<<7 ) {
+ // We have a string
+ // Extract P
+ int start = (src[i] & 0x3f)<<5 | ((src[i+1] >> 3) & 0x1f);
+ // Extract L
+ int len = (src[i+1] & 0x07)<<8 | src[i+2];
+ i += 3;
+ for (int j = start; j < start+len; ++j) {
+ dest[index++] = dest[j];
+ }
+ } else {
+ // We have a character
+ if (src[i] & 1<<6) {
+ // Value is in the next byte
+ dest[index++] = src[i+1];
+ i += 2;
+ } else {
+ // just extend the lower 6 bits
+ dest[index++] = (src[i] & 0x3f) | ((src[i] & 1<<5) ? 0xC0 : 0);
+ ++i;
+ }
+ }
+ }
+ return index;
+}
diff --git a/src/base/compression/lzss_compression.hh b/src/base/compression/lzss_compression.hh
new file mode 100644
index 000000000..c136c6d60
--- /dev/null
+++ b/src/base/compression/lzss_compression.hh
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __LZSS_COMPRESSION_HH__
+#define __LZSS_COMPRESSION_HH__
+
+/** @file
+ * LZSSCompression declarations.
+ */
+
+#include "sim/host.hh" // for uint8_t
+
+/**
+ * Simple LZSS compression scheme.
+ */
+class LZSSCompression
+{
+ /**
+ * Finds the longest substring for the given offset.
+ * @param src The source block that we search for substrings.
+ * @param back The larger offset.
+ * @param size The size of the source block.
+ * @param L The length of the largest substring.
+ * @param P The starting offset of the largest substring.
+ */
+ void findSubString(uint8_t *src, int back, int size, uint16_t &L,
+ uint16_t &P);
+
+ /**
+ * Emit an encoded byte to the compressed data array. If the 2 high
+ * order bits can be signed extended, use 1 byte encoding, if not use 2
+ * bytes.
+ * @param dest The compressed data.
+ * @param byte The byte to emit.
+ * @return The number of bytes used to encode.
+ */
+ int emitByte(uint8_t *dest, uint8_t byte);
+
+ /**
+ * Emit a string reference to the compressed data array. A string reference
+ * always uses 3 bytes. 1 flag bit, 12 bits for the starting position, and
+ * 11 bits for the length of the string. This allows compression of 4096
+ * byte blocks with string lengths of up to 2048 bytes.
+ * @param dest The compressed data.
+ * @param P The starting position in the uncompressed data.
+ * @param L The length in bytes of the string.
+ */
+ void emitString(uint8_t *dest, uint16_t P, uint16_t L);
+
+ public:
+ /**
+ * Compresses the source block and stores it in the destination block. If
+ * the compressed block grows to larger than the source block, it aborts
+ * and just performs a copy.
+ * @param dest The destination block.
+ * @param src The block to be compressed.
+ * @param size The size of the source block.
+ * @return The size of the compressed block.
+ *
+ * @pre Destination has enough storage to hold the compressed block.
+ */
+ int compress(uint8_t *dest, uint8_t *src, int size);
+
+ /**
+ * Unompresses the source block and stores it in the destination block.
+ * @param dest The destination block.
+ * @param src The block to be uncompressed.
+ * @param size The size of the source block.
+ * @return The size of the uncompressed block.
+ *
+ * @pre Destination has enough storage to hold the uncompressed block.
+ */
+ int uncompress(uint8_t *dest, uint8_t *src, int size);
+};
+
+#endif //__LZSS_COMPRESSION_HH__
diff --git a/src/base/compression/null_compression.hh b/src/base/compression/null_compression.hh
new file mode 100644
index 000000000..5fbcf562b
--- /dev/null
+++ b/src/base/compression/null_compression.hh
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_COMPRESSION_NULL_COMPRESSION_HH__
+#define __BASE_COMPRESSION_NULL_COMPRESSION_HH__
+
+/**
+ * @file
+ * This file defines a doNothing compression algorithm.
+ */
+
+#include "base/misc.hh" // for fatal()
+#include "sim/host.hh"
+
+
+/**
+ * A dummy compression class to use when no data compression is desired.
+ */
+class NullCompression
+{
+ public:
+ /**
+ * Uncompress the data, causes a fatal since no data should be compressed.
+ * @param dest The output buffer.
+ * @param src The compressed data.
+ * @param size The number of bytes in src.
+ *
+ * @retval The size of the uncompressed data.
+ */
+ static int uncompress(uint8_t * dest, uint8_t *src, int size)
+ {
+ fatal("Can't uncompress data");
+ }
+
+ /**
+ * Compress the data, just returns the source data.
+ * @param dest The output buffer.
+ * @param src The data to be compressed.
+ * @param size The number of bytes in src.
+ *
+ * @retval The size of the compressed data.
+ */
+
+ static int compress(uint8_t *dest, uint8_t *src, int size)
+ {
+ memcpy(dest,src,size);
+ return size;
+ }
+};
+
+#endif //__BASE_COMPRESSION_NULL_COMPRESSION_HH__
diff --git a/src/base/cprintf.cc b/src/base/cprintf.cc
new file mode 100644
index 000000000..cf332ebf2
--- /dev/null
+++ b/src/base/cprintf.cc
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <cassert>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+
+#include "base/cprintf.hh"
+
+using namespace std;
+
+namespace cp {
+
+ArgList::~ArgList()
+{
+ while (!objects.empty()) {
+ delete objects.front();
+ objects.pop_front();
+ }
+}
+
+void
+ArgList::dump(const string &format)
+{
+ list_t::iterator iter = objects.begin();
+ list_t::iterator end = objects.end();
+
+ const char *p = format.c_str();
+
+ stream->fill(' ');
+ stream->flags((ios::fmtflags)0);
+
+ while (*p) {
+ switch (*p) {
+ case '%': {
+ if (p[1] == '%') {
+ *stream << '%';
+ p += 2;
+ continue;
+ }
+
+ Format fmt;
+ bool done = false;
+ bool end_number = false;
+ bool have_precision = false;
+ int number = 0;
+
+ while (!done) {
+ ++p;
+ if (*p >= '0' && *p <= '9') {
+ if (end_number)
+ continue;
+ } else if (number > 0)
+ end_number = true;
+
+ switch (*p) {
+ case 's':
+ fmt.format = Format::string;
+ done = true;
+ break;
+
+ case 'c':
+ fmt.format = Format::character;
+ done = true;
+ break;
+
+ case 'l':
+ continue;
+
+ case 'p':
+ fmt.format = Format::integer;
+ fmt.base = Format::hex;
+ fmt.alternate_form = true;
+ done = true;
+ break;
+
+ case 'X':
+ fmt.uppercase = true;
+ case 'x':
+ fmt.base = Format::hex;
+ fmt.format = Format::integer;
+ done = true;
+ break;
+
+ case 'o':
+ fmt.base = Format::oct;
+ fmt.format = Format::integer;
+ done = true;
+ break;
+
+ case 'd':
+ case 'i':
+ case 'u':
+ fmt.format = Format::integer;
+ done = true;
+ break;
+
+ case 'G':
+ fmt.uppercase = true;
+ case 'g':
+ fmt.format = Format::floating;
+ fmt.float_format = Format::best;
+ done = true;
+ break;
+
+ case 'E':
+ fmt.uppercase = true;
+ case 'e':
+ fmt.format = Format::floating;
+ fmt.float_format = Format::scientific;
+ done = true;
+ break;
+
+ case 'f':
+ fmt.format = Format::floating;
+ fmt.float_format = Format::fixed;
+ done = true;
+ break;
+
+ case 'n':
+ *stream << "we don't do %n!!!\n";
+ done = true;
+ break;
+
+ case '#':
+ fmt.alternate_form = true;
+ break;
+
+ case '-':
+ fmt.flush_left = true;
+ break;
+
+ case '+':
+ fmt.print_sign = true;
+ break;
+
+ case ' ':
+ fmt.blank_space = true;
+ break;
+
+ case '.':
+ fmt.width = number;
+ fmt.precision = 0;
+ have_precision = true;
+ number = 0;
+ end_number = false;
+ break;
+
+ case '0':
+ if (number == 0) {
+ fmt.fill_zero = true;
+ break;
+ }
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ number = number * 10 + (*p - '0');
+ break;
+
+ case '%':
+ assert("we shouldn't get here");
+ break;
+
+ default:
+ done = true;
+ break;
+ }
+
+ if (end_number) {
+ if (have_precision)
+ fmt.precision = number;
+ else
+ fmt.width = number;
+
+ end_number = false;
+ number = 0;
+ }
+ }
+
+ if (iter != end)
+ {
+ ios::fmtflags saved_flags = stream->flags();
+ char old_fill = stream->fill();
+ int old_precision = stream->precision();
+
+ (*iter)->process(*stream, fmt);
+
+ stream->flags(saved_flags);
+ stream->fill(old_fill);
+ stream->precision(old_precision);
+
+ ++iter;
+ } else {
+ *stream << "<missing arg for format>";
+ }
+
+ ++p;
+ }
+ break;
+
+ case '\n':
+ *stream << endl;
+ ++p;
+ break;
+ case '\r':
+ ++p;
+ if (*p != '\n')
+ *stream << endl;
+ break;
+
+ default: {
+ size_t len = strcspn(p, "%\n\r\0");
+ stream->write(p, len);
+ p += len;
+ }
+ break;
+ }
+ }
+
+ while (iter != end) {
+ *stream << "<extra arg>";
+ ++iter;
+ }
+}
+
+string
+ArgList::dumpToString(const string &format)
+{
+ stringstream ss;
+
+ dump(ss, format);
+
+ return ss.str();
+}
+
+}
diff --git a/src/base/cprintf.hh b/src/base/cprintf.hh
new file mode 100644
index 000000000..c468c375f
--- /dev/null
+++ b/src/base/cprintf.hh
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CPRINTF_HH__
+#define __CPRINTF_HH__
+
+#include <iostream>
+#include <list>
+#include <string>
+
+#include "base/cprintf_formats.hh"
+
+namespace cp {
+
+class ArgList
+{
+ private:
+ class Base
+ {
+ public:
+ virtual ~Base() {}
+ virtual void process(std::ostream &out, Format &fmt) = 0;
+ };
+
+ template <typename T>
+ class Node : public Base
+ {
+ public:
+ const T &data;
+
+ public:
+ Node(const T &d) : data(d) {}
+ virtual void process(std::ostream &out, Format &fmt) {
+ switch (fmt.format) {
+ case Format::character:
+ format_char(out, data, fmt);
+ break;
+
+ case Format::integer:
+ format_integer(out, data, fmt);
+ break;
+
+ case Format::floating:
+ format_float(out, data, fmt);
+ break;
+
+ case Format::string:
+ format_string(out, data, fmt);
+ break;
+
+ default:
+ out << "<bad format>";
+ break;
+ }
+ }
+ };
+
+ typedef std::list<Base *> list_t;
+
+ protected:
+ list_t objects;
+ std::ostream *stream;
+
+ public:
+ ArgList() : stream(&std::cout) {}
+ ~ArgList();
+
+ template<class T>
+ void append(const T &data) {
+ Base *obj = new ArgList::Node<T>(data);
+ objects.push_back(obj);
+ }
+
+ template<class T>
+ void prepend(const T &data) {
+ Base *obj = new ArgList::Node<T>(data);
+ objects.push_front(obj);
+ }
+
+ void dump(const std::string &format);
+ void dump(std::ostream &strm, const std::string &fmt)
+ { stream = &strm; dump(fmt); }
+
+ std::string dumpToString(const std::string &format);
+
+ friend ArgList &operator<<(std::ostream &str, ArgList &list);
+};
+
+template<class T>
+inline ArgList &
+operator,(ArgList &alist, const T &data)
+{
+ alist.append(data);
+ return alist;
+}
+
+class ArgListNull {
+};
+
+inline ArgList &
+operator,(ArgList &alist, ArgListNull)
+{ return alist; }
+
+//
+// cprintf(format, args, ...) prints to cout
+// (analogous to printf())
+//
+inline void
+__cprintf(const std::string &format, ArgList &args)
+{ args.dump(format); delete &args; }
+#define __cprintf__(format, args...) \
+ cp::__cprintf(format, (*(new cp::ArgList), args))
+#define cprintf(args...) \
+ __cprintf__(args, cp::ArgListNull())
+
+//
+// ccprintf(stream, format, args, ...) prints to the specified stream
+// (analogous to fprintf())
+//
+inline void
+__ccprintf(std::ostream &stream, const std::string &format, ArgList &args)
+{ args.dump(stream, format); delete &args; }
+#define __ccprintf__(stream, format, args...) \
+ cp::__ccprintf(stream, format, (*(new cp::ArgList), args))
+#define ccprintf(stream, args...) \
+ __ccprintf__(stream, args, cp::ArgListNull())
+
+//
+// csprintf(format, args, ...) returns a string
+// (roughly analogous to sprintf())
+//
+inline std::string
+__csprintf(const std::string &format, ArgList &args)
+{ std::string s = args.dumpToString(format); delete &args; return s; }
+#define __csprintf__(format, args...) \
+ cp::__csprintf(format, (*(new cp::ArgList), args))
+#define csprintf(args...) \
+ __csprintf__(args, cp::ArgListNull())
+
+template<class T>
+inline ArgList &
+operator<<(ArgList &list, const T &data)
+{
+ list.append(data);
+ return list;
+}
+
+inline ArgList &
+operator<<(std::ostream &str, ArgList &list)
+{
+ list.stream = &str;
+ return list;
+}
+
+class ArgListTemp
+{
+ private:
+ std::string format;
+ ArgList *args;
+
+ public:
+ ArgListTemp(const std::string &f) : format(f) { args = new ArgList; }
+ ~ArgListTemp() { args->dump(format); delete args; }
+
+ operator ArgList *() { return args; }
+};
+
+#define cformat(format) \
+ (*((cp::ArgList *)cp::ArgListTemp(format)))
+}
+
+#endif // __CPRINTF_HH__
diff --git a/src/base/cprintf_formats.hh b/src/base/cprintf_formats.hh
new file mode 100644
index 000000000..05a8723a4
--- /dev/null
+++ b/src/base/cprintf_formats.hh
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CPRINTF_FORMATS_HH__
+#define __CPRINTF_FORMATS_HH__
+
+#include <sstream>
+#include <ostream>
+
+namespace cp {
+
+struct Format
+{
+ bool alternate_form;
+ bool flush_left;
+ bool print_sign;
+ bool blank_space;
+ bool fill_zero;
+ bool uppercase;
+ enum { dec, hex, oct } base;
+ enum { none, string, integer, character, floating } format;
+ enum { best, fixed, scientific } float_format;
+ int precision;
+ int width;
+
+ Format() { clear(); }
+
+ void clear()
+ {
+ alternate_form = false;
+ flush_left = false;
+ print_sign = false;
+ blank_space = false;
+ fill_zero = false;
+ uppercase = false;
+ base = dec;
+ format = none;
+ precision = -1;
+ width = 0;
+ }
+};
+
+template <typename T>
+inline void
+_format_char(std::ostream &out, const T &data, Format &fmt)
+{
+ using namespace std;
+
+ out << data;
+}
+
+template <typename T>
+inline void
+_format_integer(std::ostream &out, const T &data, Format &fmt)
+{
+ using namespace std;
+
+ switch (fmt.base) {
+ case Format::hex:
+ out.setf(ios::hex, ios::basefield);
+ break;
+
+ case Format::oct:
+ out.setf(ios::oct, ios::basefield);
+ break;
+
+ case Format::dec:
+ out.setf(ios::dec, ios::basefield);
+ break;
+ }
+
+ if (fmt.alternate_form) {
+ if (!fmt.fill_zero)
+ out.setf(ios::showbase);
+ else {
+ switch (fmt.base) {
+ case Format::hex:
+ out << "0x";
+ fmt.width -= 2;
+ break;
+ case Format::oct:
+ out << "0";
+ fmt.width -= 1;
+ break;
+ case Format::dec:
+ break;
+ }
+ }
+ }
+
+ if (fmt.fill_zero)
+ out.fill('0');
+
+ if (fmt.width > 0)
+ out.width(fmt.width);
+
+ if (fmt.flush_left && !fmt.fill_zero)
+ out.setf(ios::left);
+
+ if (fmt.print_sign)
+ out.setf(ios::showpos);
+
+ if (fmt.uppercase)
+ out.setf(ios::uppercase);
+
+ out << data;
+}
+
+template <typename T>
+inline void
+_format_float(std::ostream &out, const T &data, Format &fmt)
+{
+ using namespace std;
+
+ switch (fmt.float_format) {
+ case Format::scientific:
+ if (fmt.precision != -1) {
+ if (fmt.width > 0)
+ out.width(fmt.width);
+
+ if (fmt.precision == 0)
+ fmt.precision = 1;
+ else
+ out.setf(ios::scientific);
+
+ out.precision(fmt.precision);
+ } else
+ if (fmt.width > 0)
+ out.width(fmt.width);
+
+ if (fmt.uppercase)
+ out.setf(ios::uppercase);
+ break;
+
+ case Format::fixed:
+ if (fmt.precision != -1) {
+ if (fmt.width > 0)
+ out.width(fmt.width);
+
+ out.setf(ios::fixed);
+ out.precision(fmt.precision);
+ } else
+ if (fmt.width > 0)
+ out.width(fmt.width);
+
+ break;
+
+ default:
+ if (fmt.precision != -1)
+ out.precision(fmt.precision);
+
+ if (fmt.width > 0)
+ out.width(fmt.width);
+
+ break;
+ }
+
+ out << data;
+}
+
+template <typename T>
+inline void
+_format_string(std::ostream &out, const T &data, Format &fmt)
+{
+ using namespace std;
+
+#if defined(__GNUC__) && (__GNUC__ < 3) || 1
+ if (fmt.width > 0) {
+ std::stringstream foo;
+ foo << data;
+ int flen = foo.str().size();
+
+ if (fmt.width > flen) {
+ char *spaces = new char[fmt.width - flen + 1];
+ memset(spaces, ' ', fmt.width - flen);
+ spaces[fmt.width - flen] = 0;
+
+ if (fmt.flush_left)
+ out << foo.str() << spaces;
+ else
+ out << spaces << foo.str();
+
+ delete [] spaces;
+ } else
+ out << data;
+ } else
+ out << data;
+#else
+ if (fmt.width > 0)
+ out.width(fmt.width);
+ if (fmt.flush_left)
+ out.setf(ios::left);
+
+ out << data;
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// The code below controls the actual usage of formats for various types
+//
+
+//
+// character formats
+//
+template <typename T>
+inline void
+format_char(std::ostream &out, const T &data, Format &fmt)
+{ out << "<bad arg type for char format>"; }
+
+inline void
+format_char(std::ostream &out, char data, Format &fmt)
+{ _format_char(out, data, fmt); }
+
+inline void
+format_char(std::ostream &out, unsigned char data, Format &fmt)
+{ _format_char(out, data, fmt); }
+
+inline void
+format_char(std::ostream &out, signed char data, Format &fmt)
+{ _format_char(out, data, fmt); }
+
+inline void
+format_char(std::ostream &out, short data, Format &fmt)
+{ _format_char(out, (char)data, fmt); }
+
+inline void
+format_char(std::ostream &out, unsigned short data, Format &fmt)
+{ _format_char(out, (char)data, fmt); }
+
+inline void
+format_char(std::ostream &out, int data, Format &fmt)
+{ _format_char(out, (char)data, fmt); }
+
+inline void
+format_char(std::ostream &out, unsigned int data, Format &fmt)
+{ _format_char(out, (char)data, fmt); }
+
+inline void
+format_char(std::ostream &out, long data, Format &fmt)
+{ _format_char(out, (char)data, fmt); }
+
+inline void
+format_char(std::ostream &out, unsigned long data, Format &fmt)
+{ _format_char(out, (char)data, fmt); }
+
+inline void
+format_char(std::ostream &out, long long data, Format &fmt)
+{ _format_char(out, (char)data, fmt); }
+
+inline void
+format_char(std::ostream &out, unsigned long long data, Format &fmt)
+{ _format_char(out, (char)data, fmt); }
+
+//
+// integer formats
+//
+template <typename T>
+inline void
+format_integer(std::ostream &out, const T &data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+inline void
+format_integer(std::ostream &out, char data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+inline void
+format_integer(std::ostream &out, unsigned char data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+inline void
+format_integer(std::ostream &out, signed char data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+#if 0
+inline void
+format_integer(std::ostream &out, short data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+inline void
+format_integer(std::ostream &out, unsigned short data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+inline void
+format_integer(std::ostream &out, int data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+inline void
+format_integer(std::ostream &out, unsigned int data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+inline void
+format_integer(std::ostream &out, long data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+inline void
+format_integer(std::ostream &out, unsigned long data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+inline void
+format_integer(std::ostream &out, long long data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+inline void
+format_integer(std::ostream &out, unsigned long long data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+#endif
+
+//
+// floating point formats
+//
+template <typename T>
+inline void
+format_float(std::ostream &out, const T &data, Format &fmt)
+{ out << "<bad arg type for float format>"; }
+
+inline void
+format_float(std::ostream &out, float data, Format &fmt)
+{ _format_float(out, data, fmt); }
+
+inline void
+format_float(std::ostream &out, double data, Format &fmt)
+{ _format_float(out, data, fmt); }
+
+//
+// string formats
+//
+template <typename T>
+inline void
+format_string(std::ostream &out, const T &data, Format &fmt)
+{ _format_string(out, data, fmt); }
+
+inline void
+format_string(std::ostream &out, const std::stringstream &data, Format &fmt)
+{ _format_string(out, data.str(), fmt); }
+
+} // namespace cp
+
+#endif // __CPRINTF_FORMATS_HH__
diff --git a/src/base/crc.cc b/src/base/crc.cc
new file mode 100644
index 000000000..08f039577
--- /dev/null
+++ b/src/base/crc.cc
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 1988, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <string>
+
+#include "sim/host.hh"
+#include "base/crc.hh"
+
+#define ETHER_CRC_POLY_LE 0xedb88320
+#define ETHER_CRC_POLY_BE 0x04c11db6
+
+#if 0
+/*
+ * This is for reference. We have a table-driven version
+ * of the little-endian crc32 generator, which is faster
+ * than the double-loop.
+ */
+uint32_t
+crc32le(const uint8_t *buf, size_t len)
+{
+ uint32_t c, crc, carry;
+ size_t i, j;
+
+ crc = 0xffffffffU; /* initial value */
+
+ for (i = 0; i < len; i++) {
+ c = buf[i];
+ for (j = 0; j < 8; j++) {
+ carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01);
+ crc >>= 1;
+ c >>= 1;
+ if (carry)
+ crc = (crc ^ ETHER_CRC_POLY_LE);
+ }
+ }
+
+ return (crc);
+}
+#else
+uint32_t
+crc32le(const uint8_t *buf, size_t len)
+{
+ static const uint32_t crctab[] = {
+ 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
+ 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
+ 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
+ 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
+ };
+ uint32_t crc;
+ int i;
+
+ crc = 0xffffffffU; /* initial value */
+
+ for (i = 0; i < len; i++) {
+ crc ^= buf[i];
+ crc = (crc >> 4) ^ crctab[crc & 0xf];
+ crc = (crc >> 4) ^ crctab[crc & 0xf];
+ }
+
+ return (crc);
+}
+#endif
+
+uint32_t
+crc32be(const uint8_t *buf, size_t len)
+{
+ uint32_t c, crc, carry;
+ size_t i, j;
+
+ crc = 0xffffffffU; /* initial value */
+
+ for (i = 0; i < len; i++) {
+ c = buf[i];
+ for (j = 0; j < 8; j++) {
+ carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01);
+ crc <<= 1;
+ c >>= 1;
+ if (carry)
+ crc = (crc ^ ETHER_CRC_POLY_BE) | carry;
+ }
+ }
+
+ return (crc);
+}
diff --git a/src/base/crc.hh b/src/base/crc.hh
new file mode 100644
index 000000000..6ede07748
--- /dev/null
+++ b/src/base/crc.hh
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_CRC_HH__
+#define __BASE_CRC_HH__
+
+#include "sim/host.hh"
+
+uint32_t crc32be(const uint8_t *buf, size_t len);
+uint32_t crc32le(const uint8_t *buf, size_t len);
+
+#endif // __BASE_CRC_HH__
diff --git a/src/base/date.cc b/src/base/date.cc
new file mode 100644
index 000000000..ba7698c29
--- /dev/null
+++ b/src/base/date.cc
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+const char *compileDate = __DATE__ " " __TIME__;
diff --git a/src/base/dbl_list.hh b/src/base/dbl_list.hh
new file mode 100644
index 000000000..1d06ff576
--- /dev/null
+++ b/src/base/dbl_list.hh
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2000-2001, 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DBL_LIST_HH__
+#define __DBL_LIST_HH__
+
+class DblListEl {
+ DblListEl *next;
+ DblListEl *prev;
+
+ // remove this from list
+ void remove() {
+ prev->next = next;
+ next->prev = prev;
+ }
+
+ // insert this before old_el
+ void insertBefore(DblListEl *old_el) {
+ prev = old_el->prev;
+ next = old_el;
+ prev->next = this;
+ next->prev = this;
+ }
+
+ // insert this after old_el
+ void insertAfter(DblListEl *old_el) {
+ next = old_el->next;
+ prev = old_el;
+ next->prev = this;
+ prev->next = this;
+ }
+
+ friend class DblListBase;
+};
+
+
+//
+// doubly-linked list of DblListEl objects
+//
+class DblListBase {
+ // dummy list head element: dummy.next is head, dummy.prev is tail
+ DblListEl dummy;
+
+ // length counter
+ unsigned length;
+
+ DblListEl *valid_or_null(DblListEl *el) {
+ // make sure users never see the dummy element
+ return (el == &dummy) ? NULL : el;
+ }
+
+ public:
+
+ DblListEl *head() {
+ return valid_or_null(dummy.next);
+ }
+
+ DblListEl *tail() {
+ return valid_or_null(dummy.prev);
+ }
+
+ DblListEl *next(DblListEl *el) {
+ return valid_or_null(el->next);
+ }
+
+ DblListEl *prev(DblListEl *el) {
+ return valid_or_null(el->prev);
+ }
+
+ bool is_empty() {
+ return (dummy.next == &dummy);
+ }
+
+ void remove(DblListEl *el) {
+ el->remove();
+ --length;
+ }
+
+ void insertBefore(DblListEl *new_el, DblListEl *old_el) {
+ new_el->insertBefore(old_el);
+ ++length;
+ }
+
+ void insertAfter(DblListEl *new_el, DblListEl *old_el) {
+ new_el->insertAfter(old_el);
+ ++length;
+ }
+
+ // append to end of list, i.e. as dummy.prev
+ void append(DblListEl *el) {
+ insertBefore(el, &dummy);
+ }
+
+ // prepend to front of list (push), i.e. as dummy.next
+ void prepend(DblListEl *el) {
+ insertAfter(el, &dummy);
+ }
+
+ DblListEl *pop() {
+ DblListEl *hd = head();
+ if (hd != NULL)
+ remove(hd);
+ return hd;
+ }
+
+ // constructor
+ DblListBase() {
+ dummy.next = dummy.prev = &dummy;
+ length = 0;
+ }
+};
+
+
+//
+// Template class serves solely to cast args & return values
+// to appropriate type (T *)
+//
+template<class T> class DblList : private DblListBase {
+
+ public:
+
+ T *head() { return (T *)DblListBase::head(); }
+ T *tail() { return (T *)DblListBase::tail(); }
+
+ T *next(T *el) { return (T *)DblListBase::next(el); }
+ T *prev(T *el) { return (T *)DblListBase::prev(el); }
+
+ bool is_empty() { return DblListBase::is_empty(); }
+
+ void remove(T *el) { DblListBase::remove(el); }
+
+ void append(T *el) { DblListBase::append(el); }
+ void prepend(T *el) { DblListBase::prepend(el); }
+
+ T *pop() { return (T *)DblListBase::pop(); }
+
+ DblList<T>() { }
+};
+
+#endif // __DBL_LIST_HH__
diff --git a/src/base/endian.hh b/src/base/endian.hh
new file mode 100644
index 000000000..499eb50c5
--- /dev/null
+++ b/src/base/endian.hh
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ENDIAN_HH__
+#define __ENDIAN_HH__
+
+#include <arpa/inet.h>
+
+inline bool
+HostBigEndian()
+{
+ int x = 0x11223344;
+ return x == htonl(x);
+}
+
+#endif // __ENDIAN_HH__
diff --git a/src/base/fast_alloc.cc b/src/base/fast_alloc.cc
new file mode 100644
index 000000000..6504e07c2
--- /dev/null
+++ b/src/base/fast_alloc.cc
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2000-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This code was originally written by Steve Reinhardt as part of
+ * the Wisconsin Wind Tunnel simulator. Relicensed as part of M5
+ * by permission.
+ */
+
+#ifndef NO_FAST_ALLOC
+
+#ifdef __GNUC__
+#pragma implementation
+#endif
+
+#include <assert.h>
+#include "base/fast_alloc.hh"
+
+void *FastAlloc::freeLists[Num_Buckets];
+
+#ifdef FAST_ALLOC_STATS
+unsigned FastAlloc::newCount[Num_Buckets];
+unsigned FastAlloc::deleteCount[Num_Buckets];
+unsigned FastAlloc::allocCount[Num_Buckets];
+#endif
+
+void *FastAlloc::moreStructs(int bucket)
+{
+ assert(bucket > 0 && bucket < Num_Buckets);
+
+ int sz = bucket * Alloc_Quantum;
+ const int nstructs = Num_Structs_Per_New; // how many to allocate?
+ char *p = ::new char[nstructs * sz];
+
+#ifdef FAST_ALLOC_STATS
+ ++allocCount[bucket];
+#endif
+
+ freeLists[bucket] = p;
+ for (int i = 0; i < (nstructs-2); ++i, p += sz)
+ *(void **)p = p + sz;
+ *(void **)p = 0;
+
+ return (p + sz);
+}
+
+
+#ifdef FAST_ALLOC_DEBUG
+
+#include <typeinfo>
+#include <iostream>
+#include <iomanip>
+#include <map>
+#include <string>
+
+using namespace std;
+
+// count of in-use FastAlloc objects
+int FastAlloc::numInUse;
+
+// dummy head & tail object for doubly linked list of in-use FastAlloc
+// objects
+FastAlloc FastAlloc::inUseHead(&FastAlloc::inUseHead, &FastAlloc::inUseHead);
+
+// special constructor for dummy head: make inUsePrev & inUseNext
+// point to self
+FastAlloc::FastAlloc(FastAlloc *prev, FastAlloc *next)
+{
+ inUsePrev = prev;
+ inUseNext = next;
+}
+
+
+// constructor: marks as in use, add to in-use list
+FastAlloc::FastAlloc()
+{
+ // mark this object in use
+ inUse = true;
+
+ // update count
+ ++numInUse;
+
+ // add to tail of list of in-use objects ("before" dummy head)
+ FastAlloc *myNext = &inUseHead;
+ FastAlloc *myPrev = inUseHead.inUsePrev;
+
+ inUsePrev = myPrev;
+ inUseNext = myNext;
+ myPrev->inUseNext = this;
+ myNext->inUsePrev = this;
+}
+
+// destructor: mark not in use, remove from in-use list
+FastAlloc::~FastAlloc()
+{
+ assert(inUse);
+ inUse = false;
+
+ --numInUse;
+ assert(numInUse >= 0);
+
+ // remove me from in-use list
+ inUsePrev->inUseNext = inUseNext;
+ inUseNext->inUsePrev = inUsePrev;
+}
+
+
+// summarize in-use list
+void
+FastAlloc::dump_summary()
+{
+ map<string, int> typemap;
+
+ for (FastAlloc *p = inUseHead.inUseNext; p != &inUseHead; p = p->inUseNext)
+ {
+ ++typemap[typeid(*p).name()];
+ }
+
+ map<string, int>::const_iterator mapiter;
+
+ cout << " count type\n"
+ << " ----- ----\n";
+ for (mapiter = typemap.begin(); mapiter != typemap.end(); ++mapiter)
+ {
+ cout << setw(6) << mapiter->second << " " << mapiter->first << endl;
+ }
+}
+
+
+// show oldest n items on in-use list
+void
+FastAlloc::dump_oldest(int n)
+{
+ // sanity check: don't want to crash the debugger if you forget to
+ // pass in a parameter
+ if (n < 0 || n > numInUse)
+ {
+ cout << "FastAlloc::dump_oldest: bad arg " << n
+ << " (" << numInUse << " objects in use" << endl;
+ return;
+ }
+
+ for (FastAlloc *p = inUseHead.inUsePrev;
+ p != &inUseHead && n > 0;
+ p = p->inUsePrev, --n)
+ {
+ cout << p << " " << typeid(*p).name() << endl;
+ }
+}
+
+
+//
+// C interfaces to FastAlloc::dump_summary() and FastAlloc::dump_oldest().
+// gdb seems to have trouble with calling C++ functions directly.
+//
+extern "C" void
+fast_alloc_summary()
+{
+ FastAlloc::dump_summary();
+}
+
+extern "C" void
+fast_alloc_oldest(int n)
+{
+ FastAlloc::dump_oldest(n);
+}
+
+#endif
+
+#endif // NO_FAST_ALLOC
diff --git a/src/base/fast_alloc.hh b/src/base/fast_alloc.hh
new file mode 100644
index 000000000..54e35f8e0
--- /dev/null
+++ b/src/base/fast_alloc.hh
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2000-2001, 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This code was originally written by Steve Reinhardt as part of
+ * the Wisconsin Wind Tunnel simulator. Relicensed as part of M5
+ * by permission.
+ */
+
+#ifndef __FAST_ALLOC_H__
+#define __FAST_ALLOC_H__
+
+#include <stddef.h>
+
+// Fast structure allocator. Designed for small objects that are
+// frequently allocated and deallocated. This code is derived from the
+// 'alloc_struct' package used in WWT and Blizzard. C++ provides a
+// much nicer framework for the same optimization. The package is
+// implemented as a class, FastAlloc. Allocation and deletion are
+// performed using FastAlloc's new and delete operators. Any object
+// that derives from the FastAlloc class will transparently use this
+// allocation package.
+
+// The static allocate() and deallocate() methods can also be called
+// directly if desired.
+
+// In order for derived classes to call delete with the correct
+// structure size even when they are deallocated via a base-type
+// pointer, they must have a virtual destructor. It is sufficient for
+// FastAlloc to declare a virtual destructor (as it does); it is not
+// required for derived classes to declare their own destructor. The
+// compiler will automatically generate a virtual destructor for each
+// derived class. However, it is more efficient if each derived class
+// defines an inline destructor, so that the compiler can statically
+// collapse the destructor call chain back up the inheritance
+// hierarchy.
+
+// Uncomment this #define to track in-use objects
+// (for debugging memory leaks).
+//#define FAST_ALLOC_DEBUG
+
+// Uncomment this #define to count news, deletes, and chunk allocations
+// (by bucket).
+// #define FAST_ALLOC_STATS
+
+#include "config/no_fast_alloc.hh"
+
+#if NO_FAST_ALLOC
+
+class FastAlloc {
+};
+
+#else
+
+class FastAlloc {
+ public:
+
+ static void *allocate(size_t);
+ static void deallocate(void *, size_t);
+
+ void *operator new(size_t);
+ void operator delete(void *, size_t);
+
+#ifdef FAST_ALLOC_DEBUG
+ FastAlloc();
+ FastAlloc(FastAlloc*,FastAlloc*); // for inUseHead, see below
+ virtual ~FastAlloc();
+#else
+ virtual ~FastAlloc() {}
+#endif
+
+ private:
+
+ // Max_Alloc_Size is the largest object that can be allocated with
+ // this class. There's no fundamental limit, but this limits the
+ // size of the freeLists array. Let's not make this really huge
+ // like in Blizzard.
+ static const int Max_Alloc_Size = 512;
+
+ // Alloc_Quantum is the difference in size between adjacent
+ // buckets in the free list array.
+ static const int Log2_Alloc_Quantum = 3;
+ static const int Alloc_Quantum = (1 << Log2_Alloc_Quantum);
+
+ // Num_Buckets = bucketFor(Max_Alloc_Size) + 1
+ static const int Num_Buckets =
+ ((Max_Alloc_Size + Alloc_Quantum - 1) >> Log2_Alloc_Quantum) + 1;
+
+ // when we call new() for more structures, how many should we get?
+ static const int Num_Structs_Per_New = 20;
+
+ static int bucketFor(size_t);
+ static void *moreStructs(int bucket);
+
+ static void *freeLists[Num_Buckets];
+
+#ifdef FAST_ALLOC_STATS
+ static unsigned newCount[Num_Buckets];
+ static unsigned deleteCount[Num_Buckets];
+ static unsigned allocCount[Num_Buckets];
+#endif
+
+#ifdef FAST_ALLOC_DEBUG
+ // per-object debugging fields
+ bool inUse; // in-use flag
+ FastAlloc *inUsePrev; // ptrs to build list of in-use objects
+ FastAlloc *inUseNext;
+
+ // static (global) debugging vars
+ static int numInUse; // count in-use objects
+ static FastAlloc inUseHead; // dummy head for list of in-use objects
+
+ public:
+ // functions to dump debugging info (see fast_alloc.cc for C
+ // versions that might be more agreeable to call from gdb)
+ static void dump_summary();
+ static void dump_oldest(int n);
+#endif
+};
+
+
+inline
+int FastAlloc::bucketFor(size_t sz)
+{
+ return (sz + Alloc_Quantum - 1) >> Log2_Alloc_Quantum;
+}
+
+
+inline
+void *FastAlloc::allocate(size_t sz)
+{
+ int b;
+ void *p;
+
+ if (sz > Max_Alloc_Size)
+ return (void *)::new char[sz];
+
+ b = bucketFor(sz);
+ p = freeLists[b];
+
+ if (p)
+ freeLists[b] = *(void **)p;
+ else
+ p = moreStructs(b);
+
+#ifdef FAST_ALLOC_STATS
+ ++newCount[b];
+#endif
+
+ return p;
+}
+
+
+inline
+void FastAlloc::deallocate(void *p, size_t sz)
+{
+ int b;
+
+ if (sz > Max_Alloc_Size)
+ {
+ ::delete [] (char *)p;
+ return;
+ }
+
+ b = bucketFor(sz);
+ *(void **)p = freeLists[b];
+ freeLists[b] = p;
+#ifdef FAST_ALLOC_STATS
+ ++deleteCount[b];
+#endif
+}
+
+
+inline
+void *FastAlloc::operator new(size_t sz)
+{
+ return allocate(sz);
+}
+
+
+inline
+void FastAlloc::operator delete(void *p, size_t sz)
+{
+ deallocate(p, sz);
+}
+
+#endif // NO_FAST_ALLOC
+
+#endif // __FAST_ALLOC_H__
diff --git a/src/base/fenv.hh b/src/base/fenv.hh
new file mode 100644
index 000000000..3234f5dd3
--- /dev/null
+++ b/src/base/fenv.hh
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_FENV_HH__
+#define __BASE_FENV_HH__
+
+#include "config/use_fenv.hh"
+
+#if USE_FENV
+
+#include <fenv.h>
+
+#else
+
+// Dummy definitions to allow code to compile w/o a real <fenv.h>.
+
+#define FE_TONEAREST 0
+#define FE_DOWNWARD 0
+#define FE_UPWARD 0
+#define FE_TOWARDZERO 0
+
+inline int fesetround(int rounding_mode) { return 0; }
+
+#endif // USE_FENV
+
+
+#endif // __BASE_FENV_HH__
diff --git a/src/base/fifo_buffer.cc b/src/base/fifo_buffer.cc
new file mode 100644
index 000000000..85b306c25
--- /dev/null
+++ b/src/base/fifo_buffer.cc
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "base/fifo_buffer.hh"
+
+template<class T>
+void
+FifoBuffer<T>::dump()
+{
+ if (buffer->count() > 0)
+ for (iterator i=buffer->tail(); i.notnull(); i=i.prev())
+ i->dump();
+}
+
+
diff --git a/src/base/fifo_buffer.hh b/src/base/fifo_buffer.hh
new file mode 100644
index 000000000..03ce057c7
--- /dev/null
+++ b/src/base/fifo_buffer.hh
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FIFO_BUFFER_HH__
+#define __FIFO_BUFFER_HH__
+
+#include "base/res_list.hh"
+
+
+//
+// The FifoBuffer requires only that the objects to be used have a default
+// constructor and a dump() method
+//
+template<class T>
+class FifoBuffer
+{
+ public:
+ typedef typename res_list<T>::iterator iterator;
+
+ private:
+ res_list<T> *buffer;
+
+ unsigned size;
+
+ public:
+ FifoBuffer(unsigned sz)
+ {
+ buffer = new res_list<T>(sz, true, 0);
+ size = sz;
+ }
+
+ void add(T &item)
+ {
+ assert(buffer->num_free() > 0);
+ buffer->add_head(item);
+ }
+
+ iterator head() { return buffer->head(); }
+ iterator tail() { return buffer->tail(); }
+
+ unsigned count() {return buffer->count();}
+ unsigned free_slots() {return buffer->num_free();}
+
+ T *peek() { return (count() > 0) ? tail().data_ptr() : 0; }
+
+ T remove()
+ {
+ assert(buffer->count() > 0);
+ T rval = *buffer->tail();
+ buffer->remove_tail();
+ return rval;
+ }
+
+ void dump();
+
+ ~FifoBuffer() { delete buffer; }
+};
+
+
+#endif
+
diff --git a/src/base/hashmap.hh b/src/base/hashmap.hh
new file mode 100644
index 000000000..712366829
--- /dev/null
+++ b/src/base/hashmap.hh
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HASHMAP_HH__
+#define __HASHMAP_HH__
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+#include <ext/hash_map>
+#else
+#include <hash_map>
+#endif
+
+#include <string>
+
+#include "sim/host.hh"
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+ #define __hash_namespace __gnu_cxx
+#else
+ #define __hash_namespace std
+#endif
+
+namespace m5 {
+ using ::__hash_namespace::hash_multimap;
+ using ::__hash_namespace::hash_map;
+ using ::__hash_namespace::hash;
+}
+
+
+///////////////////////////////////
+// Some default Hashing Functions
+//
+
+namespace __hash_namespace {
+#if !defined(__LP64__) && !defined(__alpha__)
+ template<>
+ struct hash<uint64_t> {
+ size_t operator()(uint64_t r) const {
+ return r;
+ }
+ };
+
+ template<>
+ struct hash<int64_t> {
+ size_t operator()(int64_t r) const {
+ return r;
+ };
+ };
+#endif
+
+ template<>
+ struct hash<std::string> {
+ size_t operator()(const std::string &s) const {
+ return(__stl_hash_string(s.c_str()));
+ }
+ };
+}
+
+
+#endif // __HASHMAP_HH__
diff --git a/src/base/hostinfo.cc b/src/base/hostinfo.cc
new file mode 100644
index 000000000..d42c96732
--- /dev/null
+++ b/src/base/hostinfo.cc
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <math.h>
+#include <unistd.h>
+
+#include <cstdlib>
+#include <cstring>
+#include <string>
+
+#include "base/misc.hh"
+#include "sim/host.hh"
+
+using namespace std;
+
+string
+__get_hostname()
+{
+ char host[256];
+ if (gethostname(host, sizeof host) == -1)
+ warn("could not get host name!");
+ return host;
+}
+
+string &
+hostname()
+{
+ static string hostname = __get_hostname();
+ return hostname;
+}
+
+uint64_t
+procInfo(char *filename, char *target)
+{
+ int done = 0;
+ char line[80];
+ char format[80];
+ long usage;
+
+ FILE *fp = fopen(filename, "r");
+
+ while (fp && !feof(fp) && !done) {
+ if (fgets(line, 80, fp)) {
+ if (strncmp(line, target, strlen(target)) == 0) {
+ snprintf(format, sizeof(format), "%s %%ld", target);
+ sscanf(line, format, &usage);
+
+ fclose(fp);
+ return usage ;
+ }
+ }
+ }
+
+ if (fp)
+ fclose(fp);
+
+ return 0;
+}
diff --git a/src/base/hostinfo.hh b/src/base/hostinfo.hh
new file mode 100644
index 000000000..21a6e5475
--- /dev/null
+++ b/src/base/hostinfo.hh
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HOSTINFO_HH__
+#define __HOSTINFO_HH__
+
+#include <string>
+
+#include "sim/host.hh"
+
+std::string &hostname();
+
+uint64_t procInfo(char *filename, char *target);
+
+inline uint64_t memUsage()
+{ return procInfo("/proc/self/status", "VmSize:"); }
+
+#endif // __HOSTINFO_HH__
diff --git a/src/base/hybrid_pred.cc b/src/base/hybrid_pred.cc
new file mode 100644
index 000000000..21cbdb0fd
--- /dev/null
+++ b/src/base/hybrid_pred.cc
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string>
+#include <sstream>
+
+#include "base/hybrid_pred.hh"
+#include "base/statistics.hh"
+#include "sim/stats.hh"
+
+using namespace std;
+
+HybridPredictor::HybridPredictor(const char *_p_name, const char *_z_name,
+ const char *_o_name,
+ unsigned _index_bits, unsigned _counter_bits,
+ unsigned _zero_change, unsigned _one_change,
+ unsigned _thresh,
+ unsigned _global_bits,
+ unsigned _global_thresh,
+ bool _reg_individual_stats)
+{
+ stringstream local_name, global_name;
+
+ pred_name = _p_name;
+ one_name = _o_name;
+ zero_name = _z_name;
+ reg_individual_stats = _reg_individual_stats;
+
+ local_name << pred_name.c_str() << ":L";
+ local = new SaturatingCounterPred(local_name.str(), zero_name, one_name,
+ _index_bits, _counter_bits,
+ _zero_change, _one_change, _thresh);
+
+ global_name << pred_name.c_str() << ":G";
+ global = new SaturatingCounterPred(global_name.str(), zero_name, one_name,
+ 0, _global_bits, 1, 1, _global_thresh);
+}
+
+void HybridPredictor::regStats()
+{
+ using namespace Stats;
+
+ string p_name;
+ stringstream description;
+
+ if (reg_individual_stats)
+ p_name = pred_name + ":A";
+ else
+ p_name = pred_name;
+
+
+ //
+ // Number of predictions
+ //
+ stringstream num_zero_preds;
+ num_zero_preds << p_name << ":" << zero_name << ":preds";
+ description << "number of predictions of " << zero_name;
+ pred_zero
+ .name(num_zero_preds.str())
+ .desc(description.str());
+ description.str("");
+
+ stringstream num_one_preds;
+ num_one_preds << p_name << ":" << one_name << ":preds";
+ description << "number of predictions of " << one_name;
+ pred_one
+ .name(num_one_preds.str())
+ .desc(description.str())
+ ;
+ description.str("");
+
+ //
+ // Count the number of correct predictions
+ //
+ stringstream num_zero_correct;
+ num_zero_correct << p_name << ":" << zero_name << ":corr_preds";
+ description << "number of correct " << zero_name << " preds" ;
+ correct_pred_zero
+ .name(num_zero_correct.str())
+ .desc(description.str())
+ ;
+ description.str("");
+
+ stringstream num_one_correct;
+ num_one_correct << p_name << ":" << one_name << ":corr_preds";
+ description << "number of correct " << one_name << " preds" ;
+ correct_pred_one
+ .name(num_one_correct.str())
+ .desc(description.str())
+ ;
+ description.str("");
+
+
+ //
+ // Number of predictor updates
+ //
+ stringstream num_zero_updates;
+ num_zero_updates << p_name << ":" << zero_name << ":updates" ;
+ description << "number of actual " << zero_name << "s" ;
+ record_zero
+ .name(num_zero_updates.str())
+ .desc(description.str())
+ ;
+ description.str("");
+
+ stringstream num_one_updates;
+ num_one_updates << p_name << ":" << one_name << ":updates" ;
+ description << "number of actual " << one_name << "s" ;
+ record_one
+ .name(num_one_updates.str())
+ .desc(description.str())
+ ;
+ description.str("");
+
+ //
+ // Local & Global predictor stats
+ //
+ if (reg_individual_stats) {
+ local->regStats();
+ global->regStats();
+ }
+}
+
+void HybridPredictor::regFormulas()
+{
+ using namespace Stats;
+
+ string p_name;
+ stringstream description;
+ stringstream name;
+
+ if (reg_individual_stats)
+ p_name = pred_name + ":A";
+ else
+ p_name = pred_name;
+
+ //
+ // Number of predictions
+ //
+ name << p_name << ":predictions" ;
+ total_preds
+ .name(name.str())
+ .desc("total number of predictions made")
+ ;
+ total_preds = pred_one + pred_zero;
+ name.str("");
+
+ //
+ // Fraction of all predictions that are one or zero
+ //
+ name << p_name << ":" << zero_name << ":pred_frac";
+ description << "fraction of all preds that were " << zero_name ;
+ frac_preds_zero
+ .name(name.str())
+ .desc(description.str())
+ ;
+ frac_preds_zero = 100 * record_zero / total_preds;
+ description.str("");
+ name.str("");
+
+ name << p_name << ":" << one_name << ":pred_frac";
+ description << "fraction of all preds that were " << one_name ;
+ frac_preds_one
+ .name(name.str())
+ .desc(description.str())
+ ;
+ frac_preds_one = 100 * record_one / total_preds;
+ description.str("");
+ name.str("");
+
+ //
+ // Count the number of correct predictions
+ //
+ name << p_name << ":correct_preds" ;
+ total_correct
+ .name(name.str())
+ .desc("total number of correct predictions made")
+ ;
+ total_correct = correct_pred_one + correct_pred_zero;
+ name.str("");
+
+
+ //
+ // Prediction accuracy rates
+ //
+ name << p_name << ":pred_rate";
+ total_accuracy
+ .name(name.str())
+ .desc("fraction of all preds that were correct")
+ ;
+ total_accuracy = 100 * total_correct / total_preds;
+ name.str("");
+
+ name << p_name << ":" << zero_name << ":pred_rate" ;
+ description << "fraction of "<< zero_name <<" preds that were correct";
+ zero_accuracy
+ .name(name.str())
+ .desc(description.str())
+ ;
+ zero_accuracy = 100 * correct_pred_zero / pred_zero;
+ description.str("");
+ name.str("");
+
+ name << p_name << ":" << one_name << ":pred_rate" ;
+ description << "fraction of "<< one_name <<" preds that were correct";
+ one_accuracy
+ .name(name.str())
+ .desc(description.str())
+ ;
+ one_accuracy = 100 * correct_pred_one / pred_one;
+ description.str("");
+ name.str("");
+
+ //
+ // Coverage
+ //
+ name << p_name << ":" << zero_name << ":coverage";
+ description << "fraction of " << zero_name
+ << "s that were predicted correctly";
+ zero_coverage
+ .name(name.str())
+ .desc(description.str())
+ ;
+ zero_coverage = 100 * correct_pred_zero / record_zero;
+ description.str("");
+ name.str("");
+
+ name << p_name << ":" << one_name << ":coverage";
+ description << "fraction of " << one_name
+ << "s that were predicted correctly";
+ one_coverage
+ .name(name.str())
+ .desc(description.str())
+ ;
+ one_coverage = 100 * correct_pred_one / record_one;
+ description.str("");
+ name.str("");
+
+ //
+ // Local & Global predictor stats
+ //
+ if (reg_individual_stats) {
+ local->regFormulas();
+ global->regFormulas();
+ }
+
+}
+
diff --git a/src/base/hybrid_pred.hh b/src/base/hybrid_pred.hh
new file mode 100644
index 000000000..ea4a9d04c
--- /dev/null
+++ b/src/base/hybrid_pred.hh
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//==========================================================================
+//
+// This predictor takes the AND of a "local" and a "global" predictor
+// in order to determine its prediction.
+//
+//
+//
+//
+
+#ifndef __HYBRID_PRED_HH__
+#define __HYBRID_PRED_HH__
+
+#include <string>
+
+#include "base/sat_counter.hh"
+#include "base/statistics.hh"
+
+class HybridPredictor : public GenericPredictor
+{
+ private:
+ std::string pred_name;
+ std::string one_name;
+ std::string zero_name;
+ bool reg_individual_stats;
+
+ SaturatingCounterPred *local;
+ SaturatingCounterPred *global;
+
+ unsigned long max_index;
+
+ //
+ // Stats
+ //
+ Stats::Scalar<> pred_one; //num_one_preds
+ Stats::Scalar<> pred_zero; //num_zero_preds
+ Stats::Scalar<> correct_pred_one; //num_one_correct
+ Stats::Scalar<> correct_pred_zero; //num_zero_correct
+ Stats::Scalar<> record_one; //num_one_updates
+ Stats::Scalar<> record_zero; //num_zero_updates
+
+ Stats::Formula total_preds;
+ Stats::Formula frac_preds_zero;
+ Stats::Formula frac_preds_one;
+ Stats::Formula total_correct;
+ Stats::Formula total_accuracy;
+ Stats::Formula zero_accuracy;
+ Stats::Formula one_accuracy;
+ Stats::Formula zero_coverage;
+ Stats::Formula one_coverage;
+
+ public:
+ HybridPredictor(const char *_p_name, const char *_z_name,
+ const char *_o_name,
+ unsigned _index_bits, unsigned _counter_bits,
+ unsigned _zero_change, unsigned _one_change,
+ unsigned _thresh,
+ unsigned _global_bits, unsigned _global_thresh,
+ bool _reg_individual_stats = false);
+
+ void clear() {
+ global->clear();
+ local->clear();
+ }
+
+ unsigned peek(unsigned long _index) {
+ unsigned l = local->peek(_index);
+ unsigned g = global->peek(_index);
+
+ if (l && g)
+ return 1;
+
+ return 0;
+ }
+
+ unsigned value(unsigned long _index) {
+ unsigned l = local->peek(_index);
+ unsigned g = global->peek(_index);
+
+ l = l & 0xFFFF;
+ g = g & 0xFFFF;
+
+ return (l << 16) | g;
+
+ }
+
+ unsigned predict(unsigned long _index) {
+ unsigned l = local->predict(_index);
+ unsigned g = global->predict(_index);
+
+ if (l && g) {
+ ++pred_one;
+ return 1;
+ }
+
+ ++pred_zero;
+ return 0;
+ }
+
+
+ //
+ // This version need only be used if local/global statistics
+ // will be maintained
+ //
+ unsigned predict(unsigned long _index, unsigned &_pdata) {
+ unsigned l = local->predict(_index);
+ unsigned g = global->predict(_index);
+
+ //
+ // bit 0 => local predictor result
+ // bit 1 => global predictor result
+ //
+ _pdata = 0;
+ if (l)
+ _pdata |= 1;
+ if (g)
+ _pdata |= 2;
+ if (l && g) {
+ ++pred_one;
+ return 1;
+ }
+
+ ++pred_zero;
+ return 0;
+ }
+
+ void record(unsigned long _index, unsigned _val, unsigned _predicted) {
+
+ if (_val) {
+ local->record(_index, _val, 0);
+ global->record(_index, _val, 0);
+ ++record_one;
+
+ if (_val == _predicted) {
+ ++correct_pred_one;
+ }
+ } else {
+ local->record(_index, _val, 0);
+ global->record(_index, _val, 0);
+ ++record_zero;
+
+ if (_val == _predicted)
+ ++correct_pred_zero;
+ }
+ }
+
+ void record(unsigned long _index, unsigned _val, unsigned _predicted,
+ unsigned _pdata)
+ {
+
+ local->record(_index, _val, (_pdata & 1));
+ global->record(_index, _val, ((_pdata & 2) ? 1 : 0));
+
+
+ if (_val) {
+ ++record_one;
+
+ if (_val == _predicted)
+ ++correct_pred_one;
+ } else {
+ ++record_zero;
+
+ if (_val == _predicted)
+ ++correct_pred_zero;
+ }
+ }
+
+ void regStats();
+ void regFormulas();
+};
+
+
+#endif // _HYBRID_PRED_HH__
+
diff --git a/src/base/inet.cc b/src/base/inet.cc
new file mode 100644
index 000000000..f2665bd2b
--- /dev/null
+++ b/src/base/inet.cc
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sstream>
+#include <string>
+
+#include "base/cprintf.hh"
+#include "sim/host.hh"
+#include "base/inet.hh"
+
+using namespace std;
+namespace Net {
+
+EthAddr::EthAddr()
+{
+ memset(data, 0, ETH_ADDR_LEN);
+}
+
+EthAddr::EthAddr(const uint8_t ea[ETH_ADDR_LEN])
+{
+ *data = *ea;
+}
+
+EthAddr::EthAddr(const eth_addr &ea)
+{
+ *data = *ea.data;
+}
+
+EthAddr::EthAddr(const std::string &addr)
+{
+ parse(addr);
+}
+
+const EthAddr &
+EthAddr::operator=(const eth_addr &ea)
+{
+ *data = *ea.data;
+ return *this;
+}
+
+const EthAddr &
+EthAddr::operator=(const std::string &addr)
+{
+ parse(addr);
+ return *this;
+}
+
+void
+EthAddr::parse(const std::string &addr)
+{
+ // the hack below is to make sure that ETH_ADDR_LEN is 6 otherwise
+ // the sscanf function won't work.
+ int bytes[ETH_ADDR_LEN == 6 ? ETH_ADDR_LEN : -1];
+ if (sscanf(addr.c_str(), "%x:%x:%x:%x:%x:%x", &bytes[0], &bytes[1],
+ &bytes[2], &bytes[3], &bytes[4], &bytes[5]) != ETH_ADDR_LEN) {
+ memset(data, 0xff, ETH_ADDR_LEN);
+ return;
+ }
+
+ for (int i = 0; i < ETH_ADDR_LEN; ++i) {
+ if (bytes[i] & ~0xff) {
+ memset(data, 0xff, ETH_ADDR_LEN);
+ return;
+ }
+
+ data[i] = bytes[i];
+ }
+}
+
+string
+EthAddr::string() const
+{
+ stringstream stream;
+ stream << *this;
+ return stream.str();
+}
+
+bool
+operator==(const EthAddr &left, const EthAddr &right)
+{
+ return memcmp(left.bytes(), right.bytes(), ETH_ADDR_LEN);
+}
+
+ostream &
+operator<<(ostream &stream, const EthAddr &ea)
+{
+ const uint8_t *a = ea.addr();
+ ccprintf(stream, "%x:%x:%x:%x:%x:%x", a[0], a[1], a[2], a[3], a[4], a[5]);
+ return stream;
+}
+
+uint16_t
+cksum(const IpPtr &ptr)
+{
+ int sum = ip_cksum_add(ptr->bytes(), ptr->hlen(), 0);
+ return ip_cksum_carry(sum);
+}
+
+uint16_t
+__tu_cksum(const IpPtr &ip)
+{
+ int tcplen = ip->len() - ip->hlen();
+ int sum = ip_cksum_add(ip->payload(), tcplen, 0);
+ sum = ip_cksum_add(&ip->ip_src, 8, sum); // source and destination
+ sum += htons(ip->ip_p + tcplen);
+ return ip_cksum_carry(sum);
+}
+
+uint16_t
+cksum(const TcpPtr &tcp)
+{ return __tu_cksum(IpPtr(tcp.packet())); }
+
+uint16_t
+cksum(const UdpPtr &udp)
+{ return __tu_cksum(IpPtr(udp.packet())); }
+
+bool
+IpHdr::options(vector<const IpOpt *> &vec) const
+{
+ vec.clear();
+
+ const uint8_t *data = bytes() + sizeof(struct ip_hdr);
+ int all = hlen() - sizeof(struct ip_hdr);
+ while (all > 0) {
+ const IpOpt *opt = (const IpOpt *)data;
+ int len = opt->len();
+ if (all < len)
+ return false;
+
+ vec.push_back(opt);
+ all -= len;
+ data += len;
+ }
+
+ return true;
+}
+
+bool
+TcpHdr::options(vector<const TcpOpt *> &vec) const
+{
+ vec.clear();
+
+ const uint8_t *data = bytes() + sizeof(struct tcp_hdr);
+ int all = off() - sizeof(struct tcp_hdr);
+ while (all > 0) {
+ const TcpOpt *opt = (const TcpOpt *)data;
+ int len = opt->len();
+ if (all < len)
+ return false;
+
+ vec.push_back(opt);
+ all -= len;
+ data += len;
+ }
+
+ return true;
+}
+
+bool
+TcpOpt::sack(vector<SackRange> &vec) const
+{
+ vec.clear();
+
+ const uint8_t *data = bytes() + sizeof(struct tcp_hdr);
+ int all = len() - offsetof(tcp_opt, opt_data.sack);
+ while (all > 0) {
+ const uint16_t *sack = (const uint16_t *)data;
+ int len = sizeof(uint16_t) * 2;
+ if (all < len) {
+ vec.clear();
+ return false;
+ }
+
+ vec.push_back(RangeIn(ntohs(sack[0]), ntohs(sack[1])));
+ all -= len;
+ data += len;
+ }
+
+ return false;
+}
+
+/* namespace Net */ }
diff --git a/src/base/inet.hh b/src/base/inet.hh
new file mode 100644
index 000000000..e5d0473f9
--- /dev/null
+++ b/src/base/inet.hh
@@ -0,0 +1,407 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_INET_HH__
+#define __BASE_INET_HH__
+
+#include <iosfwd>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/range.hh"
+#include "dev/etherpkt.hh"
+#include "sim/host.hh"
+
+#include "dnet/os.h"
+#include "dnet/eth.h"
+#include "dnet/ip.h"
+#include "dnet/ip6.h"
+#include "dnet/addr.h"
+#include "dnet/arp.h"
+#include "dnet/icmp.h"
+#include "dnet/tcp.h"
+#include "dnet/udp.h"
+#include "dnet/intf.h"
+#include "dnet/route.h"
+#include "dnet/fw.h"
+#include "dnet/blob.h"
+#include "dnet/rand.h"
+
+namespace Net {
+
+/*
+ * Ethernet Stuff
+ */
+struct EthAddr : protected eth_addr
+{
+ protected:
+ void parse(const std::string &addr);
+
+ public:
+ EthAddr();
+ EthAddr(const uint8_t ea[ETH_ADDR_LEN]);
+ EthAddr(const eth_addr &ea);
+ EthAddr(const std::string &addr);
+ const EthAddr &operator=(const eth_addr &ea);
+ const EthAddr &operator=(const std::string &addr);
+
+ int size() const { return sizeof(eth_addr); }
+
+ const uint8_t *bytes() const { return &data[0]; }
+ uint8_t *bytes() { return &data[0]; }
+
+ const uint8_t *addr() const { return &data[0]; }
+ bool unicast() const { return data[0] == 0x00; }
+ bool multicast() const { return data[0] == 0x01; }
+ bool broadcast() const { return data[0] == 0xff; }
+ std::string string() const;
+
+ operator uint64_t() const
+ {
+ uint64_t reg = 0;
+ reg |= ((uint64_t)data[0]) << 40;
+ reg |= ((uint64_t)data[1]) << 32;
+ reg |= ((uint64_t)data[2]) << 24;
+ reg |= ((uint64_t)data[3]) << 16;
+ reg |= ((uint64_t)data[4]) << 8;
+ reg |= ((uint64_t)data[5]) << 0;
+ return reg;
+ }
+
+};
+
+std::ostream &operator<<(std::ostream &stream, const EthAddr &ea);
+bool operator==(const EthAddr &left, const EthAddr &right);
+
+struct EthHdr : public eth_hdr
+{
+ uint16_t type() const { return ntohs(eth_type); }
+ const EthAddr &src() const { return *(EthAddr *)&eth_src; }
+ const EthAddr &dst() const { return *(EthAddr *)&eth_dst; }
+
+ int size() const { return sizeof(eth_hdr); }
+
+ const uint8_t *bytes() const { return (const uint8_t *)this; }
+ const uint8_t *payload() const { return bytes() + size(); }
+ uint8_t *bytes() { return (uint8_t *)this; }
+ uint8_t *payload() { return bytes() + size(); }
+};
+
+class EthPtr
+{
+ protected:
+ friend class IpPtr;
+ EthPacketPtr p;
+
+ public:
+ EthPtr() {}
+ EthPtr(const EthPacketPtr &ptr) : p(ptr) { }
+
+ EthHdr *operator->() { return (EthHdr *)p->data; }
+ EthHdr &operator*() { return *(EthHdr *)p->data; }
+ operator EthHdr *() { return (EthHdr *)p->data; }
+
+ const EthHdr *operator->() const { return (const EthHdr *)p->data; }
+ const EthHdr &operator*() const { return *(const EthHdr *)p->data; }
+ operator const EthHdr *() const { return (const EthHdr *)p->data; }
+
+ const EthPtr &operator=(const EthPacketPtr &ptr) { p = ptr; return *this; }
+
+ const EthPacketPtr packet() const { return p; }
+ EthPacketPtr packet() { return p; }
+ bool operator!() const { return !p; }
+ operator bool() const { return p; }
+};
+
+/*
+ * IP Stuff
+ */
+struct IpOpt;
+struct IpHdr : public ip_hdr
+{
+ uint8_t version() const { return ip_v; }
+ uint8_t hlen() const { return ip_hl * 4; }
+ uint8_t tos() const { return ip_tos; }
+ uint16_t len() const { return ntohs(ip_len); }
+ uint16_t id() const { return ntohs(ip_id); }
+ uint16_t frag_flags() const { return ntohs(ip_off) >> 13; }
+ uint16_t frag_off() const { return ntohs(ip_off) & 0x1fff; }
+ uint8_t ttl() const { return ip_ttl; }
+ uint8_t proto() const { return ip_p; }
+ uint16_t sum() const { return ip_sum; }
+ uint32_t src() const { return ntohl(ip_src); }
+ uint32_t dst() const { return ntohl(ip_dst); }
+
+ void sum(uint16_t sum) { ip_sum = sum; }
+
+ bool options(std::vector<const IpOpt *> &vec) const;
+
+ int size() const { return hlen(); }
+ const uint8_t *bytes() const { return (const uint8_t *)this; }
+ const uint8_t *payload() const { return bytes() + size(); }
+ uint8_t *bytes() { return (uint8_t *)this; }
+ uint8_t *payload() { return bytes() + size(); }
+};
+
+class IpPtr
+{
+ protected:
+ friend class TcpPtr;
+ friend class UdpPtr;
+ EthPacketPtr p;
+
+ const IpHdr *h() const
+ { return (const IpHdr *)(p->data + sizeof(eth_hdr)); }
+ IpHdr *h() { return (IpHdr *)(p->data + sizeof(eth_hdr)); }
+
+ void set(const EthPacketPtr &ptr)
+ {
+ EthHdr *eth = (EthHdr *)ptr->data;
+ if (eth->type() == ETH_TYPE_IP)
+ p = ptr;
+ else
+ p = 0;
+ }
+
+ public:
+ IpPtr() {}
+ IpPtr(const EthPacketPtr &ptr) { set(ptr); }
+ IpPtr(const EthPtr &ptr) { set(ptr.p); }
+ IpPtr(const IpPtr &ptr) : p(ptr.p) { }
+
+ IpHdr *operator->() { return h(); }
+ IpHdr &operator*() { return *h(); }
+ operator IpHdr *() { return h(); }
+
+ const IpHdr *operator->() const { return h(); }
+ const IpHdr &operator*() const { return *h(); }
+ operator const IpHdr *() const { return h(); }
+
+ const IpPtr &operator=(const EthPacketPtr &ptr) { set(ptr); return *this; }
+ const IpPtr &operator=(const EthPtr &ptr) { set(ptr.p); return *this; }
+ const IpPtr &operator=(const IpPtr &ptr) { p = ptr.p; return *this; }
+
+ const EthPacketPtr packet() const { return p; }
+ EthPacketPtr packet() { return p; }
+ bool operator!() const { return !p; }
+ operator bool() const { return p; }
+ operator bool() { return p; }
+};
+
+uint16_t cksum(const IpPtr &ptr);
+
+struct IpOpt : public ip_opt
+{
+ uint8_t type() const { return opt_type; }
+ uint8_t typeNumber() const { return IP_OPT_NUMBER(opt_type); }
+ uint8_t typeClass() const { return IP_OPT_CLASS(opt_type); }
+ uint8_t typeCopied() const { return IP_OPT_COPIED(opt_type); }
+ uint8_t len() const { return IP_OPT_TYPEONLY(type()) ? 1 : opt_len; }
+
+ bool isNumber(int num) const { return typeNumber() == IP_OPT_NUMBER(num); }
+ bool isClass(int cls) const { return typeClass() == IP_OPT_CLASS(cls); }
+ bool isCopied(int cpy) const { return typeCopied() == IP_OPT_COPIED(cpy); }
+
+ const uint8_t *data() const { return opt_data.data8; }
+ void sec(ip_opt_data_sec &sec) const;
+ void lsrr(ip_opt_data_rr &rr) const;
+ void ssrr(ip_opt_data_rr &rr) const;
+ void ts(ip_opt_data_ts &ts) const;
+ uint16_t satid() const { return ntohs(opt_data.satid); }
+ uint16_t mtup() const { return ntohs(opt_data.mtu); }
+ uint16_t mtur() const { return ntohs(opt_data.mtu); }
+ void tr(ip_opt_data_tr &tr) const;
+ const uint32_t *addext() const { return &opt_data.addext[0]; }
+ uint16_t rtralt() const { return ntohs(opt_data.rtralt); }
+ void sdb(std::vector<uint32_t> &vec) const;
+};
+
+/*
+ * TCP Stuff
+ */
+struct TcpOpt;
+struct TcpHdr : public tcp_hdr
+{
+ uint16_t sport() const { return ntohs(th_sport); }
+ uint16_t dport() const { return ntohs(th_dport); }
+ uint32_t seq() const { return ntohl(th_seq); }
+ uint32_t ack() const { return ntohl(th_ack); }
+ uint8_t off() const { return th_off; }
+ uint8_t flags() const { return th_flags & 0x3f; }
+ uint16_t win() const { return ntohs(th_win); }
+ uint16_t sum() const { return th_sum; }
+ uint16_t urp() const { return ntohs(th_urp); }
+
+ void sum(uint16_t sum) { th_sum = sum; }
+
+ bool options(std::vector<const TcpOpt *> &vec) const;
+
+ int size() const { return off(); }
+ const uint8_t *bytes() const { return (const uint8_t *)this; }
+ const uint8_t *payload() const { return bytes() + size(); }
+ uint8_t *bytes() { return (uint8_t *)this; }
+ uint8_t *payload() { return bytes() + size(); }
+};
+
+class TcpPtr
+{
+ protected:
+ EthPacketPtr p;
+ int off;
+
+ const TcpHdr *h() const { return (const TcpHdr *)(p->data + off); }
+ TcpHdr *h() { return (TcpHdr *)(p->data + off); }
+
+ void set(const EthPacketPtr &ptr, int offset) { p = ptr; off = offset; }
+ void set(const IpPtr &ptr)
+ {
+ if (ptr->proto() == IP_PROTO_TCP)
+ set(ptr.p, sizeof(eth_hdr) + ptr->hlen());
+ else
+ set(0, 0);
+ }
+
+ public:
+ TcpPtr() {}
+ TcpPtr(const IpPtr &ptr) { set(ptr); }
+ TcpPtr(const TcpPtr &ptr) : p(ptr.p), off(ptr.off) {}
+
+ TcpHdr *operator->() { return h(); }
+ TcpHdr &operator*() { return *h(); }
+ operator TcpHdr *() { return h(); }
+
+ const TcpHdr *operator->() const { return h(); }
+ const TcpHdr &operator*() const { return *h(); }
+ operator const TcpHdr *() const { return h(); }
+
+ const TcpPtr &operator=(const IpPtr &i) { set(i); return *this; }
+ const TcpPtr &operator=(const TcpPtr &t) { set(t.p, t.off); return *this; }
+
+ const EthPacketPtr packet() const { return p; }
+ EthPacketPtr packet() { return p; }
+ bool operator!() const { return !p; }
+ operator bool() const { return p; }
+ operator bool() { return p; }
+};
+
+uint16_t cksum(const TcpPtr &ptr);
+
+typedef Range<uint16_t> SackRange;
+
+struct TcpOpt : public tcp_opt
+{
+ uint8_t type() const { return opt_type; }
+ uint8_t len() const { return TCP_OPT_TYPEONLY(type()) ? 1 : opt_len; }
+
+ bool isopt(int opt) const { return type() == opt; }
+
+ const uint8_t *data() const { return opt_data.data8; }
+
+ uint16_t mss() const { return ntohs(opt_data.mss); }
+ uint8_t wscale() const { return opt_data.wscale; }
+ bool sack(std::vector<SackRange> &vec) const;
+ uint32_t echo() const { return ntohl(opt_data.echo); }
+ uint32_t tsval() const { return ntohl(opt_data.timestamp[0]); }
+ uint32_t tsecr() const { return ntohl(opt_data.timestamp[1]); }
+ uint32_t cc() const { return ntohl(opt_data.cc); }
+ uint8_t cksum() const{ return opt_data.cksum; }
+ const uint8_t *md5() const { return opt_data.md5; }
+
+ int size() const { return len(); }
+ const uint8_t *bytes() const { return (const uint8_t *)this; }
+ const uint8_t *payload() const { return bytes() + size(); }
+ uint8_t *bytes() { return (uint8_t *)this; }
+ uint8_t *payload() { return bytes() + size(); }
+};
+
+/*
+ * UDP Stuff
+ */
+struct UdpHdr : public udp_hdr
+{
+ uint16_t sport() const { return ntohs(uh_sport); }
+ uint16_t dport() const { return ntohs(uh_dport); }
+ uint16_t len() const { return ntohs(uh_ulen); }
+ uint16_t sum() const { return uh_sum; }
+
+ void sum(uint16_t sum) { uh_sum = sum; }
+
+ int size() const { return sizeof(udp_hdr); }
+ const uint8_t *bytes() const { return (const uint8_t *)this; }
+ const uint8_t *payload() const { return bytes() + size(); }
+ uint8_t *bytes() { return (uint8_t *)this; }
+ uint8_t *payload() { return bytes() + size(); }
+};
+
+class UdpPtr
+{
+ protected:
+ EthPacketPtr p;
+ int off;
+
+ const UdpHdr *h() const { return (const UdpHdr *)(p->data + off); }
+ UdpHdr *h() { return (UdpHdr *)(p->data + off); }
+
+ void set(const EthPacketPtr &ptr, int offset) { p = ptr; off = offset; }
+ void set(const IpPtr &ptr)
+ {
+ if (ptr->proto() == IP_PROTO_UDP)
+ set(ptr.p, sizeof(eth_hdr) + ptr->hlen());
+ else
+ set(0, 0);
+ }
+
+ public:
+ UdpPtr() {}
+ UdpPtr(const IpPtr &ptr) { set(ptr); }
+ UdpPtr(const UdpPtr &ptr) : p(ptr.p), off(ptr.off) {}
+
+ UdpHdr *operator->() { return h(); }
+ UdpHdr &operator*() { return *h(); }
+ operator UdpHdr *() { return h(); }
+
+ const UdpHdr *operator->() const { return h(); }
+ const UdpHdr &operator*() const { return *h(); }
+ operator const UdpHdr *() const { return h(); }
+
+ const UdpPtr &operator=(const IpPtr &i) { set(i); return *this; }
+ const UdpPtr &operator=(const UdpPtr &t) { set(t.p, t.off); return *this; }
+
+ const EthPacketPtr packet() const { return p; }
+ EthPacketPtr packet() { return p; }
+ bool operator!() const { return !p; }
+ operator bool() const { return p; }
+ operator bool() { return p; }
+};
+
+uint16_t cksum(const UdpPtr &ptr);
+
+/* namespace Net */ }
+
+#endif // __BASE_INET_HH__
diff --git a/src/base/inifile.cc b/src/base/inifile.cc
new file mode 100644
index 000000000..eb5a1335f
--- /dev/null
+++ b/src/base/inifile.cc
@@ -0,0 +1,433 @@
+/*
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define USE_CPP
+
+#ifdef USE_CPP
+#include <sys/signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#endif
+
+#include <fstream>
+#include <iostream>
+
+#include <vector>
+#include <string>
+
+#include "base/inifile.hh"
+#include "base/str.hh"
+
+using namespace std;
+
+IniFile::IniFile()
+{}
+
+IniFile::~IniFile()
+{
+ SectionTable::iterator i = table.begin();
+ SectionTable::iterator end = table.end();
+
+ while (i != end) {
+ delete (*i).second;
+ ++i;
+ }
+}
+
+
+#ifdef USE_CPP
+bool
+IniFile::loadCPP(const string &file, vector<char *> &cppArgs)
+{
+ // Open the file just to verify that we can. Otherwise if the
+ // file doesn't exist or has bad permissions the user will get
+ // confusing errors from cpp/g++.
+ ifstream tmpf(file.c_str());
+
+ if (!tmpf.is_open())
+ return false;
+
+ tmpf.close();
+
+ char *cfile = strncpy(new char[file.size() + 1], file.c_str(),
+ file.size());
+ char *dir = dirname(cfile);
+ char *dir_arg = NULL;
+ if (*dir != '.') {
+ string arg = "-I";
+ arg += dir;
+
+ dir_arg = new char[arg.size() + 1];
+ strncpy(dir_arg, arg.c_str(), arg.size());
+ }
+
+ delete [] cfile;
+
+ char tempfile[] = "/tmp/configXXXXXX";
+ int tmp_fd = mkstemp(tempfile);
+
+ int pid = fork();
+
+ if (pid == -1)
+ return false;
+
+ if (pid == 0) {
+ char filename[FILENAME_MAX];
+ string::size_type i = file.copy(filename, sizeof(filename) - 1);
+ filename[i] = '\0';
+
+ int arg_count = cppArgs.size();
+
+ char **args = new char *[arg_count + 20];
+
+ int nextArg = 0;
+ args[nextArg++] = "g++";
+ args[nextArg++] = "-E";
+ args[nextArg++] = "-P";
+ args[nextArg++] = "-nostdinc";
+ args[nextArg++] = "-nostdinc++";
+ args[nextArg++] = "-x";
+ args[nextArg++] = "c++";
+ args[nextArg++] = "-undef";
+
+ for (int i = 0; i < arg_count; i++)
+ args[nextArg++] = cppArgs[i];
+
+ if (dir_arg)
+ args[nextArg++] = dir_arg;
+
+ args[nextArg++] = filename;
+ args[nextArg++] = NULL;
+
+ close(STDOUT_FILENO);
+ if (dup2(tmp_fd, STDOUT_FILENO) == -1)
+ exit(1);
+
+ execvp("g++", args);
+
+ exit(0);
+ }
+
+ int retval;
+ waitpid(pid, &retval, 0);
+
+ delete [] dir_arg;
+
+ // check for normal completion of CPP
+ if (!WIFEXITED(retval) || WEXITSTATUS(retval) != 0)
+ return false;
+
+ close(tmp_fd);
+
+ bool status = false;
+
+ status = load(tempfile);
+
+ unlink(tempfile);
+
+ return status;
+}
+#endif
+
+bool
+IniFile::load(const string &file)
+{
+ ifstream f(file.c_str());
+
+ if (!f.is_open())
+ return false;
+
+ return load(f);
+}
+
+
+const string &
+IniFile::Entry::getValue() const
+{
+ referenced = true;
+ return value;
+}
+
+
+void
+IniFile::Section::addEntry(const std::string &entryName,
+ const std::string &value,
+ bool append)
+{
+ EntryTable::iterator ei = table.find(entryName);
+
+ if (ei == table.end()) {
+ // new entry
+ table[entryName] = new Entry(value);
+ }
+ else if (append) {
+ // append new reult to old entry
+ ei->second->appendValue(value);
+ }
+ else {
+ // override old entry
+ ei->second->setValue(value);
+ }
+}
+
+
+bool
+IniFile::Section::add(const std::string &assignment)
+{
+ string::size_type offset = assignment.find('=');
+ if (offset == string::npos) {
+ // no '=' found
+ cerr << "Can't parse .ini line " << assignment << endl;
+ return false;
+ }
+
+ // if "+=" rather than just "=" then append value
+ bool append = (assignment[offset-1] == '+');
+
+ string entryName = assignment.substr(0, append ? offset-1 : offset);
+ string value = assignment.substr(offset + 1);
+
+ eat_white(entryName);
+ eat_white(value);
+
+ addEntry(entryName, value, append);
+ return true;
+}
+
+
+IniFile::Entry *
+IniFile::Section::findEntry(const std::string &entryName) const
+{
+ referenced = true;
+
+ EntryTable::const_iterator ei = table.find(entryName);
+
+ return (ei == table.end()) ? NULL : ei->second;
+}
+
+
+IniFile::Section *
+IniFile::addSection(const string &sectionName)
+{
+ SectionTable::iterator i = table.find(sectionName);
+
+ if (i != table.end()) {
+ return i->second;
+ }
+ else {
+ // new entry
+ Section *sec = new Section();
+ table[sectionName] = sec;
+ return sec;
+ }
+}
+
+
+IniFile::Section *
+IniFile::findSection(const string &sectionName) const
+{
+ SectionTable::const_iterator i = table.find(sectionName);
+
+ return (i == table.end()) ? NULL : i->second;
+}
+
+
+// Take string of the form "<section>:<parameter>=<value>" and add to
+// database. Return true if successful, false if parse error.
+bool
+IniFile::add(const string &str)
+{
+ // find ':'
+ string::size_type offset = str.find(':');
+ if (offset == string::npos) // no ':' found
+ return false;
+
+ string sectionName = str.substr(0, offset);
+ string rest = str.substr(offset + 1);
+
+ eat_white(sectionName);
+ Section *s = addSection(sectionName);
+
+ return s->add(rest);
+}
+
+bool
+IniFile::load(istream &f)
+{
+ Section *section = NULL;
+
+ while (!f.eof()) {
+ f >> ws; // Eat whitespace
+ if (f.eof()) {
+ break;
+ }
+
+ string line;
+ getline(f, line);
+ if (line.size() == 0)
+ continue;
+
+ eat_end_white(line);
+ int last = line.size() - 1;
+
+ if (line[0] == '[' && line[last] == ']') {
+ string sectionName = line.substr(1, last - 1);
+ eat_white(sectionName);
+ section = addSection(sectionName);
+ continue;
+ }
+
+ if (section == NULL)
+ continue;
+
+ if (!section->add(line))
+ return false;
+ }
+
+ return true;
+}
+
+bool
+IniFile::find(const string &sectionName, const string &entryName,
+ string &value) const
+{
+ Section *section = findSection(sectionName);
+ if (section == NULL)
+ return false;
+
+ Entry *entry = section->findEntry(entryName);
+ if (entry == NULL)
+ return false;
+
+ value = entry->getValue();
+
+ return true;
+}
+
+bool
+IniFile::sectionExists(const string &sectionName) const
+{
+ return findSection(sectionName) != NULL;
+}
+
+
+bool
+IniFile::Section::printUnreferenced(const string &sectionName)
+{
+ bool unref = false;
+ bool search_unref_entries = false;
+ vector<string> unref_ok_entries;
+
+ Entry *entry = findEntry("unref_entries_ok");
+ if (entry != NULL) {
+ tokenize(unref_ok_entries, entry->getValue(), ' ');
+ if (unref_ok_entries.size()) {
+ search_unref_entries = true;
+ }
+ }
+
+ for (EntryTable::iterator ei = table.begin();
+ ei != table.end(); ++ei) {
+ const string &entryName = ei->first;
+ Entry *entry = ei->second;
+
+ if (entryName == "unref_section_ok" ||
+ entryName == "unref_entries_ok")
+ {
+ continue;
+ }
+
+ if (!entry->isReferenced()) {
+ if (search_unref_entries &&
+ (std::find(unref_ok_entries.begin(), unref_ok_entries.end(),
+ entryName) != unref_ok_entries.end()))
+ {
+ continue;
+ }
+
+ cerr << "Parameter " << sectionName << ":" << entryName
+ << " not referenced." << endl;
+ unref = true;
+ }
+ }
+
+ return unref;
+}
+
+
+bool
+IniFile::printUnreferenced()
+{
+ bool unref = false;
+
+ for (SectionTable::iterator i = table.begin();
+ i != table.end(); ++i) {
+ const string &sectionName = i->first;
+ Section *section = i->second;
+
+ if (!section->isReferenced()) {
+ if (section->findEntry("unref_section_ok") == NULL) {
+ cerr << "Section " << sectionName << " not referenced."
+ << endl;
+ unref = true;
+ }
+ }
+ else {
+ if (section->printUnreferenced(sectionName)) {
+ unref = true;
+ }
+ }
+ }
+
+ return unref;
+}
+
+
+void
+IniFile::Section::dump(const string &sectionName)
+{
+ for (EntryTable::iterator ei = table.begin();
+ ei != table.end(); ++ei) {
+ cout << sectionName << ": " << (*ei).first << " => "
+ << (*ei).second->getValue() << "\n";
+ }
+}
+
+void
+IniFile::dump()
+{
+ for (SectionTable::iterator i = table.begin();
+ i != table.end(); ++i) {
+ i->second->dump(i->first);
+ }
+}
diff --git a/src/base/inifile.hh b/src/base/inifile.hh
new file mode 100644
index 000000000..3c6894978
--- /dev/null
+++ b/src/base/inifile.hh
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __INIFILE_HH__
+#define __INIFILE_HH__
+
+#include <fstream>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "base/hashmap.hh"
+
+/**
+ * @file
+ * Declaration of IniFile object.
+ * @todo Change comments to match documentation style.
+ */
+
+///
+/// This class represents the contents of a ".ini" file.
+///
+/// It's basically a two level lookup table: a set of named sections,
+/// where each section is a set of key/value pairs. Section names,
+/// keys, and values are all uninterpreted strings.
+///
+class IniFile
+{
+ protected:
+
+ ///
+ /// A single key/value pair.
+ ///
+ class Entry
+ {
+ std::string value; ///< The entry value.
+ mutable bool referenced; ///< Has this entry been used?
+
+ public:
+ /// Constructor.
+ Entry(const std::string &v)
+ : value(v), referenced(false)
+ {
+ }
+
+ /// Has this entry been used?
+ bool isReferenced() { return referenced; }
+
+ /// Fetch the value.
+ const std::string &getValue() const;
+
+ /// Set the value.
+ void setValue(const std::string &v) { value = v; }
+
+ /// Append the given string to the value. A space is inserted
+ /// between the existing value and the new value. Since this
+ /// operation is typically used with values that are
+ /// space-separated lists of tokens, this keeps the tokens
+ /// separate.
+ void appendValue(const std::string &v) { value += " "; value += v; }
+ };
+
+ ///
+ /// A section.
+ ///
+ class Section
+ {
+ /// EntryTable type. Map of strings to Entry object pointers.
+ typedef m5::hash_map<std::string, Entry *> EntryTable;
+
+ EntryTable table; ///< Table of entries.
+ mutable bool referenced; ///< Has this section been used?
+
+ public:
+ /// Constructor.
+ Section()
+ : table(), referenced(false)
+ {
+ }
+
+ /// Has this section been used?
+ bool isReferenced() { return referenced; }
+
+ /// Add an entry to the table. If an entry with the same name
+ /// already exists, the 'append' parameter is checked If true,
+ /// the new value will be appended to the existing entry. If
+ /// false, the new value will replace the existing entry.
+ void addEntry(const std::string &entryName, const std::string &value,
+ bool append);
+
+ /// Add an entry to the table given a string assigment.
+ /// Assignment should be of the form "param=value" or
+ /// "param+=value" (for append). This funciton parses the
+ /// assignment statment and calls addEntry().
+ /// @retval True for success, false if parse error.
+ bool add(const std::string &assignment);
+
+ /// Find the entry with the given name.
+ /// @retval Pointer to the entry object, or NULL if none.
+ Entry *findEntry(const std::string &entryName) const;
+
+ /// Print the unreferenced entries in this section to cerr.
+ /// Messages can be suppressed using "unref_section_ok" and
+ /// "unref_entries_ok".
+ /// @param sectionName Name of this section, for use in output message.
+ /// @retval True if any entries were printed.
+ bool printUnreferenced(const std::string &sectionName);
+
+ /// Print the contents of this section to cout (for debugging).
+ void dump(const std::string &sectionName);
+ };
+
+ /// SectionTable type. Map of strings to Section object pointers.
+ typedef m5::hash_map<std::string, Section *> SectionTable;
+
+ protected:
+ /// Hash of section names to Section object pointers.
+ SectionTable table;
+
+ /// Look up section with the given name, creating a new section if
+ /// not found.
+ /// @retval Pointer to section object.
+ Section *addSection(const std::string &sectionName);
+
+ /// Look up section with the given name.
+ /// @retval Pointer to section object, or NULL if not found.
+ Section *findSection(const std::string &sectionName) const;
+
+ public:
+ /// Constructor.
+ IniFile();
+
+ /// Destructor.
+ ~IniFile();
+
+ /// Load parameter settings from given istream. This is a helper
+ /// function for load(string) and loadCPP(), which open a file
+ /// and then pass it here.
+ /// @retval True if successful, false if errors were encountered.
+ bool load(std::istream &f);
+
+ /// Load the specified file, passing it through the C preprocessor.
+ /// Parameter settings found in the file will be merged with any
+ /// already defined in this object.
+ /// @param file The path of the file to load.
+ /// @param cppFlags Vector of extra flags to pass to cpp.
+ /// @retval True if successful, false if errors were encountered.
+ bool loadCPP(const std::string &file, std::vector<char *> &cppFlags);
+
+ /// Load the specified file.
+ /// Parameter settings found in the file will be merged with any
+ /// already defined in this object.
+ /// @param file The path of the file to load.
+ /// @retval True if successful, false if errors were encountered.
+ bool load(const std::string &file);
+
+ /// Take string of the form "<section>:<parameter>=<value>" or
+ /// "<section>:<parameter>+=<value>" and add to database.
+ /// @retval True if successful, false if parse error.
+ bool add(const std::string &s);
+
+ /// Find value corresponding to given section and entry names.
+ /// Value is returned by reference in 'value' param.
+ /// @retval True if found, false if not.
+ bool find(const std::string &section, const std::string &entry,
+ std::string &value) const;
+
+ /// Determine whether the named section exists in the .ini file.
+ /// Note that the 'Section' class is (intentionally) not public,
+ /// so all clients can do is get a bool that says whether there
+ /// are any values in that section or not.
+ /// @return True if the section exists.
+ bool sectionExists(const std::string &section) const;
+
+ /// Print unreferenced entries in object. Iteratively calls
+ /// printUnreferend() on all the constituent sections.
+ bool printUnreferenced();
+
+ /// Dump contents to cout. For debugging.
+ void dump();
+};
+
+#endif // __INIFILE_HH__
diff --git a/src/base/intmath.cc b/src/base/intmath.cc
new file mode 100644
index 000000000..f1c1651ba
--- /dev/null
+++ b/src/base/intmath.cc
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2001, 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "base/intmath.hh"
+
+int
+prevPrime(int n)
+{
+ int decr;
+
+ // If the number is even, let's start with the previous odd number.
+ if (!(n & 1))
+ --n;
+
+ // Lets test for divisibility by 3. Then we will be able to easily
+ // avoid numbers that are divisible by 3 in the future.
+ decr = n % 3;
+ if (decr == 0) {
+ n -= 2;
+ decr = 2;
+ }
+ else if (decr == 1)
+ decr = 4;
+
+ for (;;) {
+ if (isPrime(n))
+ return n;
+ n -= decr;
+ // Toggle between 2 and 4 to prevent trying numbers that are known
+ // to be divisible by 3.
+ decr = 6 - decr;
+ }
+}
diff --git a/src/base/intmath.hh b/src/base/intmath.hh
new file mode 100644
index 000000000..51baddb91
--- /dev/null
+++ b/src/base/intmath.hh
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2001, 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __INTMATH_HH__
+#define __INTMATH_HH__
+
+#include <assert.h>
+
+#include "sim/host.hh"
+
+// Returns the prime number one less than n.
+int prevPrime(int n);
+
+// Determine if a number is prime
+template <class T>
+inline bool
+isPrime(T n)
+{
+ T i;
+
+ if (n == 2 || n == 3)
+ return true;
+
+ // Don't try every odd number to prove if it is a prime.
+ // Toggle between every 2nd and 4th number.
+ // (This is because every 6th odd number is divisible by 3.)
+ for (i = 5; i*i <= n; i += 6) {
+ if (((n % i) == 0 ) || ((n % (i + 2)) == 0) ) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+template <class T>
+inline T
+leastSigBit(T n)
+{
+ return n & ~(n - 1);
+}
+
+template <class T>
+inline bool
+isPowerOf2(T n)
+{
+ return n != 0 && leastSigBit(n) == n;
+}
+
+inline int
+floorLog2(unsigned x)
+{
+ assert(x > 0);
+
+ int y = 0;
+
+ if (x & 0xffff0000) { y += 16; x >>= 16; }
+ if (x & 0x0000ff00) { y += 8; x >>= 8; }
+ if (x & 0x000000f0) { y += 4; x >>= 4; }
+ if (x & 0x0000000c) { y += 2; x >>= 2; }
+ if (x & 0x00000002) { y += 1; }
+
+ return y;
+}
+
+inline int
+floorLog2(unsigned long x)
+{
+ assert(x > 0);
+
+ int y = 0;
+
+#if defined(__LP64__)
+ if (x & ULL(0xffffffff00000000)) { y += 32; x >>= 32; }
+#endif
+ if (x & 0xffff0000) { y += 16; x >>= 16; }
+ if (x & 0x0000ff00) { y += 8; x >>= 8; }
+ if (x & 0x000000f0) { y += 4; x >>= 4; }
+ if (x & 0x0000000c) { y += 2; x >>= 2; }
+ if (x & 0x00000002) { y += 1; }
+
+ return y;
+}
+
+inline int
+floorLog2(unsigned long long x)
+{
+ assert(x > 0);
+
+ int y = 0;
+
+ if (x & ULL(0xffffffff00000000)) { y += 32; x >>= 32; }
+ if (x & ULL(0x00000000ffff0000)) { y += 16; x >>= 16; }
+ if (x & ULL(0x000000000000ff00)) { y += 8; x >>= 8; }
+ if (x & ULL(0x00000000000000f0)) { y += 4; x >>= 4; }
+ if (x & ULL(0x000000000000000c)) { y += 2; x >>= 2; }
+ if (x & ULL(0x0000000000000002)) { y += 1; }
+
+ return y;
+}
+
+inline int
+floorLog2(int x)
+{
+ assert(x > 0);
+ return floorLog2((unsigned)x);
+}
+
+inline int
+floorLog2(long x)
+{
+ assert(x > 0);
+ return floorLog2((unsigned long)x);
+}
+
+inline int
+floorLog2(long long x)
+{
+ assert(x > 0);
+ return floorLog2((unsigned long long)x);
+}
+
+template <class T>
+inline int
+ceilLog2(T n)
+{
+ if (n == 1)
+ return 0;
+
+ return floorLog2(n - (T)1) + 1;
+}
+
+template <class T>
+inline T
+floorPow2(T n)
+{
+ return (T)1 << floorLog2(n);
+}
+
+template <class T>
+inline T
+ceilPow2(T n)
+{
+ return (T)1 << ceilLog2(n);
+}
+
+template <class T>
+inline T
+divCeil(T a, T b)
+{
+ return (a + b - 1) / b;
+}
+
+template <class T>
+inline T
+roundUp(T val, int align)
+{
+ T mask = (T)align - 1;
+ return (val + mask) & ~mask;
+}
+
+template <class T>
+inline T
+roundDown(T val, int align)
+{
+ T mask = (T)align - 1;
+ return val & ~mask;
+}
+
+inline bool
+isHex(char c)
+{
+ return c >= '0' && c <= '9' ||
+ c >= 'A' && c <= 'F' ||
+ c >= 'a' && c <= 'f';
+}
+
+inline bool
+isOct(char c)
+{
+ return c >= '0' && c <= '7';
+}
+
+inline bool
+isDec(char c)
+{
+ return c >= '0' && c <= '9';
+}
+
+inline int
+hex2Int(char c)
+{
+ if (c >= '0' && c <= '9')
+ return (c - '0');
+
+ if (c >= 'A' && c <= 'F')
+ return (c - 'A') + 10;
+
+ if (c >= 'a' && c <= 'f')
+ return (c - 'a') + 10;
+
+ return 0;
+}
+
+#endif // __INTMATH_HH__
diff --git a/src/base/kgdb.h b/src/base/kgdb.h
new file mode 100644
index 000000000..104244d0b
--- /dev/null
+++ b/src/base/kgdb.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratories.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)remote-sl.h 8.1 (Berkeley) 6/11/93
+ */
+
+/* $NetBSD: kgdb.h,v 1.4 1998/08/13 02:10:59 eeh Exp $ */
+
+#ifndef __KGDB_H__
+#define __KGDB_H__
+
+/*
+ * Message types.
+ */
+#define KGDB_SIGNAL '?' // last sigal
+#define KGDB_SET_BAUD 'b' // set baud (deprecated)
+#define KGDB_SET_BREAK 'B' // set breakpoint (deprecated)
+#define KGDB_CONT 'c' // resume
+#define KGDB_ASYNC_CONT 'C' // continue with signal
+#define KGDB_DEBUG 'd' // toggle debug flags (deprecated)
+#define KGDB_DETACH 'D' // detach remote gdb
+#define KGDB_REG_R 'g' // read general registers
+#define KGDB_REG_W 'G' // write general registers
+#define KGDB_SET_THREAD 'H' // set thread
+#define KGDB_CYCLE_STEP 'i' // step a single cycle
+#define KGDB_SIG_CYCLE_STEP 'I' // signal then single cycle step
+#define KGDB_KILL 'k' // kill program
+#define KGDB_MEM_R 'm' // read memory
+#define KGDB_MEM_W 'M' // write memory
+#define KGDB_READ_REG 'p' // read register
+#define KGDB_SET_REG 'P' // write register
+#define KGDB_QUERY_VAR 'q' // query variable
+#define KGDB_SET_VAR 'Q' // set variable
+#define KGDB_RESET 'r' // reset system. (Deprecated)
+#define KGDB_STEP 's' // step
+#define KGDB_ASYNC_STEP 'S' // signal and step
+#define KGDB_THREAD_ALIVE 'T' // find out if the thread is alive.
+#define KGDB_TARGET_EXIT 'W' // target exited
+#define KGDB_BINARY_DLOAD 'X' // write memory
+#define KGDB_CLR_HW_BKPT 'z' // remove breakpoint or watchpoint
+#define KGDB_SET_HW_BKPT 'Z' // insert breakpoint or watchpoint
+
+/*
+ * start of frame/end of frame
+ */
+#define KGDB_START '$'
+#define KGDB_END '#'
+#define KGDB_GOODP '+'
+#define KGDB_BADP '-'
+
+/*
+ * Stuff for KGDB.
+ */
+#define KGDB_NUMREGS 66 /* from tm-alpha.h, NUM_REGS */
+#define KGDB_REG_V0 0
+#define KGDB_REG_T0 1
+#define KGDB_REG_T1 2
+#define KGDB_REG_T2 3
+#define KGDB_REG_T3 4
+#define KGDB_REG_T4 5
+#define KGDB_REG_T5 6
+#define KGDB_REG_T6 7
+#define KGDB_REG_T7 8
+#define KGDB_REG_S0 9
+#define KGDB_REG_S1 10
+#define KGDB_REG_S2 11
+#define KGDB_REG_S3 12
+#define KGDB_REG_S4 13
+#define KGDB_REG_S5 14
+#define KGDB_REG_S6 15 /* FP */
+#define KGDB_REG_A0 16
+#define KGDB_REG_A1 17
+#define KGDB_REG_A2 18
+#define KGDB_REG_A3 19
+#define KGDB_REG_A4 20
+#define KGDB_REG_A5 21
+#define KGDB_REG_T8 22
+#define KGDB_REG_T9 23
+#define KGDB_REG_T10 24
+#define KGDB_REG_T11 25
+#define KGDB_REG_RA 26
+#define KGDB_REG_T12 27
+#define KGDB_REG_AT 28
+#define KGDB_REG_GP 29
+#define KGDB_REG_SP 30
+#define KGDB_REG_ZERO 31
+#define KGDB_REG_F0 32
+#define KGDB_REG_F1 33
+#define KGDB_REG_F2 34
+#define KGDB_REG_F3 35
+#define KGDB_REG_F4 36
+#define KGDB_REG_F5 37
+#define KGDB_REG_F6 38
+#define KGDB_REG_F7 39
+#define KGDB_REG_F8 40
+#define KGDB_REG_F9 41
+#define KGDB_REG_F10 42
+#define KGDB_REG_F11 43
+#define KGDB_REG_F12 44
+#define KGDB_REG_F13 45
+#define KGDB_REG_F14 46
+#define KGDB_REG_F15 47
+#define KGDB_REG_F16 48
+#define KGDB_REG_F17 49
+#define KGDB_REG_F18 50
+#define KGDB_REG_F19 51
+#define KGDB_REG_F20 52
+#define KGDB_REG_F21 53
+#define KGDB_REG_F22 54
+#define KGDB_REG_F23 55
+#define KGDB_REG_F24 56
+#define KGDB_REG_F25 57
+#define KGDB_REG_F26 58
+#define KGDB_REG_F27 59
+#define KGDB_REG_F28 60
+#define KGDB_REG_F29 61
+#define KGDB_REG_F30 62
+#define KGDB_REG_F31 63
+#define KGDB_REG_PC 64
+#define KGDB_REG_VFP 65
+
+/* Too much? Must be large enough for register transfer. */
+#define KGDB_BUFLEN 1024
+
+/*
+ * Kernel Entry Vectors. [OSF/1 PALcode Specific]
+ */
+
+#define ALPHA_KENTRY_INT 0
+#define ALPHA_KENTRY_ARITH 1
+#define ALPHA_KENTRY_MM 2
+#define ALPHA_KENTRY_IF 3
+#define ALPHA_KENTRY_UNA 4
+#define ALPHA_KENTRY_SYS 5
+
+#endif /* __KGDB_H__ */
diff --git a/src/base/loader/aout_object.cc b/src/base/loader/aout_object.cc
new file mode 100644
index 000000000..564898ca3
--- /dev/null
+++ b/src/base/loader/aout_object.cc
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string>
+
+#include "base/loader/aout_object.hh"
+
+#include "base/loader/symtab.hh"
+
+#include "base/trace.hh" // for DPRINTF
+
+#include "base/loader/exec_aout.h"
+
+using namespace std;
+
+ObjectFile *
+AoutObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
+{
+ if (!N_BADMAG(*(aout_exechdr *)data)) {
+ // right now this is only used for Alpha PAL code
+ return new AoutObject(fname, fd, len, data,
+ ObjectFile::Alpha, ObjectFile::UnknownOpSys);
+ }
+ else {
+ return NULL;
+ }
+}
+
+
+AoutObject::AoutObject(const string &_filename, int _fd,
+ size_t _len, uint8_t *_data,
+ Arch _arch, OpSys _opSys)
+ : ObjectFile(_filename, _fd, _len, _data, _arch, _opSys)
+{
+ execHdr = (aout_exechdr *)fileData;
+
+ entry = execHdr->entry;
+
+ text.baseAddr = N_TXTADDR(*execHdr);
+ text.size = execHdr->tsize;
+ text.fileImage = fileData + N_TXTOFF(*execHdr);
+
+ data.baseAddr = N_DATADDR(*execHdr);
+ data.size = execHdr->dsize;
+ data.fileImage = fileData + N_DATOFF(*execHdr);
+
+ bss.baseAddr = N_BSSADDR(*execHdr);
+ bss.size = execHdr->bsize;
+ bss.fileImage = NULL;
+
+ DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n",
+ text.baseAddr, text.size, data.baseAddr, data.size,
+ bss.baseAddr, bss.size);
+}
+
+
+bool
+AoutObject::loadGlobalSymbols(SymbolTable *symtab)
+{
+ // a.out symbols not supported yet
+ return false;
+}
+
+bool
+AoutObject::loadLocalSymbols(SymbolTable *symtab)
+{
+ // a.out symbols not supported yet
+ return false;
+}
diff --git a/src/base/loader/aout_object.hh b/src/base/loader/aout_object.hh
new file mode 100644
index 000000000..aeb710427
--- /dev/null
+++ b/src/base/loader/aout_object.hh
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __AOUT_OBJECT_HH__
+#define __AOUT_OBJECT_HH__
+
+#include "base/loader/object_file.hh"
+
+// forward decls: avoid including exec_aout.h here
+struct aout_exechdr;
+
+class AoutObject : public ObjectFile
+{
+ protected:
+ aout_exechdr *execHdr;
+
+ AoutObject(const std::string &_filename, int _fd,
+ size_t _len, uint8_t *_data,
+ Arch _arch, OpSys _opSys);
+
+ public:
+ virtual ~AoutObject() {}
+
+ virtual bool loadGlobalSymbols(SymbolTable *symtab);
+ virtual bool loadLocalSymbols(SymbolTable *symtab);
+
+ static ObjectFile *tryFile(const std::string &fname, int fd,
+ size_t len, uint8_t *data);
+};
+
+#endif // __AOUT_OBJECT_HH__
diff --git a/src/base/loader/coff_sym.h b/src/base/loader/coff_sym.h
new file mode 100644
index 000000000..4c6540395
--- /dev/null
+++ b/src/base/loader/coff_sym.h
@@ -0,0 +1,519 @@
+/*
+ * Copyright (c) 2003, 2005-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Steve Reinhardt
+ */
+
+/*
+ * Taken from binutils-2.14.90.0.5 include/coff/sym.h
+ */
+
+/* Declarations of internal format of MIPS ECOFF symbols.
+ Originally contributed by MIPS Computer Systems and Third Eye Software.
+ Changes contributed by Cygnus Support are in the public domain.
+
+ This file is just aggregated with the files that make up the GNU
+ release; it is not considered part of GAS, GDB, or other GNU
+ programs. */
+
+/*
+ * |-----------------------------------------------------------|
+ * | Copyright (c) 1992, 1991, 1990 MIPS Computer Systems, Inc.|
+ * | MIPS Computer Systems, Inc. grants reproduction and use |
+ * | rights to all parties, PROVIDED that this comment is |
+ * | maintained in the copy. |
+ * |-----------------------------------------------------------|
+ */
+#ifndef _SYM_H
+#define _SYM_H
+
+/* (C) Copyright 1984 by Third Eye Software, Inc.
+ *
+ * Third Eye Software, Inc. grants reproduction and use rights to
+ * all parties, PROVIDED that this comment is maintained in the copy.
+ *
+ * Third Eye makes no claims about the applicability of this
+ * symbol table to a particular use.
+ */
+
+/*
+ * This file contains the definition of the Third Eye Symbol Table.
+ *
+ * Symbols are assumed to be in 'encounter order' - i.e. the order that
+ * the things they represent were encountered by the compiler/assembler/loader.
+ * EXCEPT for globals! These are assumed to be bunched together,
+ * probably right after the last 'normal' symbol. Globals ARE sorted
+ * in ascending order.
+ *
+ * -----------------------------------------------------------------------
+ * A brief word about Third Eye naming/use conventions:
+ *
+ * All arrays and index's are 0 based.
+ * All "ifooMax" values are the highest legal value PLUS ONE. This makes
+ * them good for allocating arrays, etc. All checks are "ifoo < ifooMax".
+ *
+ * "isym" Index into the SYMbol table.
+ * "ipd" Index into the Procedure Descriptor array.
+ * "ifd" Index into the File Descriptor array.
+ * "iss" Index into String Space.
+ * "cb" Count of Bytes.
+ * "rgPd" array whose domain is "0..ipdMax-1" and RanGe is PDR.
+ * "rgFd" array whose domain is "0..ifdMax-1" and RanGe is FDR.
+ */
+
+
+/*
+ * Symbolic Header (HDR) structure.
+ * As long as all the pointers are set correctly,
+ * we don't care WHAT order the various sections come out in!
+ *
+ * A file produced solely for the use of CDB will probably NOT have
+ * any instructions or data areas in it, as these are available
+ * in the original.
+ */
+
+typedef struct ecoff_symhdr {
+ coff_short magic; /* to verify validity of the table */
+ coff_short vstamp; /* version stamp */
+ coff_int ilineMax; /* number of line number entries */
+ coff_int idnMax; /* max index into dense number table */
+ coff_int ipdMax; /* number of procedures */
+ coff_int isymMax; /* number of local symbols */
+ coff_int ioptMax; /* max index into optimization symbol entries */
+ coff_int iauxMax; /* number of auxillary symbol entries */
+ coff_int issMax; /* max index into local strings */
+ coff_int issExtMax; /* max index into external strings */
+ coff_int ifdMax; /* number of file descriptor entries */
+ coff_int crfd; /* number of relative file descriptor entries */
+ coff_int iextMax; /* max index into external symbols */
+ coff_addr cbLine; /* number of bytes for line number entries */
+ coff_addr cbLineOffset; /* offset to start of line number entries*/
+ coff_addr cbDnOffset; /* offset to start dense number table */
+ coff_addr cbPdOffset; /* offset to procedure descriptor table */
+ coff_addr cbSymOffset; /* offset to start of local symbols*/
+ coff_addr cbOptOffset; /* offset to optimization symbol entries */
+ coff_addr cbAuxOffset; /* offset to start of auxillary symbol entries*/
+ coff_addr cbSsOffset; /* offset to start of local strings */
+ coff_addr cbSsExtOffset; /* offset to start of external strings */
+ coff_addr cbFdOffset; /* offset to file descriptor table */
+ coff_addr cbRfdOffset; /* offset to relative file descriptor table */
+ coff_addr cbExtOffset; /* offset to start of external symbol entries*/
+ /* If you add machine dependent fields, add them here */
+} HDRR, *pHDRR;
+#define cbHDRR sizeof(HDRR)
+#define hdrNil ((pHDRR)0)
+
+/*
+ * The FDR and PDR structures speed mapping of address <-> name.
+ * They are sorted in ascending memory order and are kept in
+ * memory by CDB at runtime.
+ */
+
+/*
+ * File Descriptor
+ *
+ * There is one of these for EVERY FILE, whether compiled with
+ * full debugging symbols or not. The name of a file should be
+ * the path name given to the compiler. This allows the user
+ * to simply specify the names of the directories where the COMPILES
+ * were done, and we will be able to find their files.
+ * A field whose comment starts with "R - " indicates that it will be
+ * setup at runtime.
+ */
+typedef struct ecoff_fdr {
+ coff_addr adr; /* memory address of beginning of file */
+ coff_addr cbLineOffset; /* byte offset from header for this file ln's */
+ coff_addr cbLine; /* size of lines for this file */
+ coff_addr cbSs; /* number of bytes in the ss */
+ coff_int rss; /* file name (of source, if known) */
+ coff_int issBase; /* file's string space */
+ coff_int isymBase; /* beginning of symbols */
+ coff_int csym; /* count file's of symbols */
+ coff_int ilineBase; /* file's line symbols */
+ coff_int cline; /* count of file's line symbols */
+ coff_int ioptBase; /* file's optimization entries */
+ coff_int copt; /* count of file's optimization entries */
+ coff_int ipdFirst; /* start of procedures for this file */
+ coff_int cpd; /* count of procedures for this file */
+ coff_int iauxBase; /* file's auxiliary entries */
+ coff_int caux; /* count of file's auxiliary entries */
+ coff_int rfdBase; /* index into the file indirect table */
+ coff_int crfd; /* count file indirect entries */
+ unsigned lang: 5; /* language for this file */
+ unsigned fMerge : 1; /* whether this file can be merged */
+ unsigned fReadin : 1; /* true if it was read in (not just created) */
+ unsigned fBigendian : 1;/* if set, was compiled on big endian machine */
+ /* aux's will be in compile host's sex */
+ unsigned glevel : 2; /* level this file was compiled with */
+ unsigned reserved : 22; /* reserved for future use */
+ coff_uint reserved2;
+} FDR, *pFDR;
+#define cbFDR sizeof(FDR)
+#define fdNil ((pFDR)0)
+#define ifdNil -1
+#define ifdTemp 0
+#define ilnNil -1
+
+
+/*
+ * Procedure Descriptor
+ *
+ * There is one of these for EVERY TEXT LABEL.
+ * If a procedure is in a file with full symbols, then isym
+ * will point to the PROC symbols, else it will point to the
+ * global symbol for the label.
+ */
+
+typedef struct pdr {
+ coff_addr adr; /* memory address of start of procedure */
+ coff_addr cbLineOffset; /* byte offset for this procedure from the fd base */
+ coff_int isym; /* start of local symbol entries */
+ coff_int iline; /* start of line number entries*/
+ coff_uint regmask; /* save register mask */
+ coff_int regoffset; /* save register offset */
+ coff_int iopt; /* start of optimization symbol entries*/
+ coff_uint fregmask; /* save floating point register mask */
+ coff_int fregoffset; /* save floating point register offset */
+ coff_int frameoffset; /* frame size */
+ coff_int lnLow; /* lowest line in the procedure */
+ coff_int lnHigh; /* highest line in the procedure */
+ /* These fields are new for 64 bit ECOFF. */
+ unsigned gp_prologue : 8; /* byte size of GP prologue */
+ unsigned gp_used : 1; /* true if the procedure uses GP */
+ unsigned reg_frame : 1; /* true if register frame procedure */
+ unsigned prof : 1; /* true if compiled with -pg */
+ unsigned reserved : 13; /* reserved: must be zero */
+ unsigned localoff : 8; /* offset of local variables from vfp */
+ coff_short framereg; /* frame pointer register */
+ coff_short pcreg; /* offset or reg of return pc */
+} PDR, *pPDR;
+#define cbPDR sizeof(PDR)
+#define pdNil ((pPDR) 0)
+#define ipdNil -1
+
+/*
+ * The structure of the runtime procedure descriptor created by the loader
+ * for use by the static exception system.
+ */
+/*
+ * If 0'd out because exception_info chokes Visual C++ and because there
+ * don't seem to be any references to this structure elsewhere in gdb.
+ */
+#if 0
+typedef struct runtime_pdr {
+ coff_addr adr; /* memory address of start of procedure */
+ coff_uint regmask; /* save register mask */
+ coff_int regoffset; /* save register offset */
+ coff_uint fregmask; /* save floating point register mask */
+ coff_int fregoffset; /* save floating point register offset */
+ coff_int frameoffset; /* frame size */
+ coff_ushort framereg; /* frame pointer register */
+ coff_ushort pcreg; /* offset or reg of return pc */
+ coff_int irpss; /* index into the runtime string table */
+ coff_uint reserved;
+ struct exception_info *exception_info;/* pointer to exception array */
+} RPDR, *pRPDR;
+#define cbRPDR sizeof(RPDR)
+#define rpdNil ((pRPDR) 0)
+#endif
+
+/*
+ * Line Numbers
+ *
+ * Line Numbers are segregated from the normal symbols because they
+ * are [1] smaller , [2] are of no interest to your
+ * average loader, and [3] are never needed in the middle of normal
+ * scanning and therefore slow things down.
+ *
+ * By definition, the first LINER for any given procedure will have
+ * the first line of a procedure and represent the first address.
+ */
+
+typedef coff_int LINER, *pLINER;
+#define lineNil ((pLINER)0)
+#define cbLINER sizeof(LINER)
+#define ilineNil -1
+
+
+
+/*
+ * The Symbol Structure (GFW, to those who Know!)
+ */
+
+typedef struct ecoff_sym {
+ coff_long value; /* value of symbol */
+ coff_int iss; /* index into String Space of name */
+ unsigned st : 6; /* symbol type */
+ unsigned sc : 5; /* storage class - text, data, etc */
+ unsigned reserved : 1; /* reserved */
+ unsigned index : 20; /* index into sym/aux table */
+} SYMR, *pSYMR;
+#define symNil ((pSYMR)0)
+#define cbSYMR sizeof(SYMR)
+#define isymNil -1
+#define indexNil 0xfffff
+#define issNil -1
+#define issNull 0
+
+
+/* The following converts a memory resident string to an iss.
+ * This hack is recognized in SbFIss, in sym.c of the debugger.
+ */
+#define IssFSb(sb) (0x80000000 | ((coff_ulong)(sb)))
+
+/* E X T E R N A L S Y M B O L R E C O R D
+ *
+ * Same as the SYMR except it contains file context to determine where
+ * the index is.
+ */
+typedef struct ecoff_extsym {
+ SYMR asym; /* symbol for the external */
+ unsigned jmptbl:1; /* symbol is a jump table entry for shlibs */
+ unsigned cobol_main:1; /* symbol is a cobol main procedure */
+ unsigned weakext:1; /* symbol is weak external */
+ unsigned reserved:29; /* reserved for future use */
+ coff_int ifd; /* where the iss and index fields point into */
+} EXTR, *pEXTR;
+#define extNil ((pEXTR)0)
+#define cbEXTR sizeof(EXTR)
+
+
+/* A U X I L L A R Y T Y P E I N F O R M A T I O N */
+
+/*
+ * Type Information Record
+ */
+typedef struct {
+ unsigned fBitfield : 1; /* set if bit width is specified */
+ unsigned continued : 1; /* indicates additional TQ info in next AUX */
+ unsigned bt : 6; /* basic type */
+ unsigned tq4 : 4;
+ unsigned tq5 : 4;
+ /* ---- 16 bit boundary ---- */
+ unsigned tq0 : 4;
+ unsigned tq1 : 4; /* 6 type qualifiers - tqPtr, etc. */
+ unsigned tq2 : 4;
+ unsigned tq3 : 4;
+} TIR, *pTIR;
+#define cbTIR sizeof(TIR)
+#define tiNil ((pTIR)0)
+#define itqMax 6
+
+/*
+ * Relative symbol record
+ *
+ * If the rfd field is 4095, the index field indexes into the global symbol
+ * table.
+ */
+
+typedef struct {
+ unsigned rfd : 12; /* index into the file indirect table */
+ unsigned index : 20; /* index int sym/aux/iss tables */
+} RNDXR, *pRNDXR;
+#define cbRNDXR sizeof(RNDXR)
+#define rndxNil ((pRNDXR)0)
+
+/* dense numbers or sometimes called block numbers are stored in this type,
+ * a rfd of 0xffffffff is an index into the global table.
+ */
+typedef struct {
+ coff_uint rfd; /* index into the file table */
+ coff_uint index; /* index int sym/aux/iss tables */
+} DNR, *pDNR;
+#define cbDNR sizeof(DNR)
+#define dnNil ((pDNR)0)
+
+
+
+/*
+ * Auxillary information occurs only if needed.
+ * It ALWAYS occurs in this order when present.
+
+ isymMac used by stProc only
+ TIR type info
+ TIR additional TQ info (if first TIR was not enough)
+ rndx if (bt == btStruct,btUnion,btEnum,btSet,btRange,
+ btTypedef):
+ rsym.index == iaux for btSet or btRange
+ else rsym.index == isym
+ dimLow btRange, btSet
+ dimMac btRange, btSet
+ rndx0 As many as there are tq arrays
+ dimLow0
+ dimHigh0
+ ...
+ rndxMax-1
+ dimLowMax-1
+ dimHighMax-1
+ width in bits if (bit field), width in bits.
+ */
+#define cAuxMax (6 + (idimMax*3))
+
+/* a union of all possible info in the AUX universe */
+typedef union {
+ TIR ti; /* type information record */
+ RNDXR rndx; /* relative index into symbol table */
+ coff_int dnLow; /* low dimension */
+ coff_int dnHigh; /* high dimension */
+ coff_int isym; /* symbol table index (end of proc) */
+ coff_int iss; /* index into string space (not used) */
+ coff_int width; /* width for non-default sized struc fields */
+ coff_int count; /* count of ranges for variant arm */
+} AUXU, *pAUXU;
+#define cbAUXU sizeof(AUXU)
+#define auxNil ((pAUXU)0)
+#define iauxNil -1
+
+
+/*
+ * Optimization symbols
+ *
+ * Optimization symbols contain some overlap information with the normal
+ * symbol table. In particular, the proc information
+ * is somewhat redundant but necessary to easily find the other information
+ * present.
+ *
+ * All of the offsets are relative to the beginning of the last otProc
+ */
+
+typedef struct {
+ unsigned ot: 8; /* optimization type */
+ unsigned value: 24; /* address where we are moving it to */
+ RNDXR rndx; /* points to a symbol or opt entry */
+ coff_ulong offset; /* relative offset this occured */
+} OPTR, *pOPTR;
+#define optNil ((pOPTR) 0)
+#define cbOPTR sizeof(OPTR)
+#define ioptNil -1
+
+/*
+ * File Indirect
+ *
+ * When a symbol is referenced across files the following procedure is used:
+ * 1) use the file index to get the File indirect entry.
+ * 2) use the file indirect entry to get the File descriptor.
+ * 3) add the sym index to the base of that file's sym table
+ *
+ */
+
+typedef coff_long RFDT, *pRFDT;
+#define cbRFDT sizeof(RFDT)
+#define rfdNil -1
+
+/*
+ * The file indirect table in the mips loader is known as an array of FITs.
+ * This is done to keep the code in the loader readable in the area where
+ * these tables are merged. Note this is only a name change.
+ */
+typedef coff_int FIT, *pFIT;
+#define cbFIT sizeof(FIT)
+#define ifiNil -1
+#define fiNil ((pFIT) 0)
+
+#ifdef _LANGUAGE_PASCAL
+#define ifdNil -1
+#define ilnNil -1
+#define ipdNil -1
+#define ilineNil -1
+#define isymNil -1
+#define indexNil 16#fffff
+#define issNil -1
+#define issNull 0
+#define itqMax 6
+#define iauxNil -1
+#define ioptNil -1
+#define rfdNil -1
+#define ifiNil -1
+#endif /* _LANGUAGE_PASCAL */
+
+
+/* Dense numbers
+ *
+ * Rather than use file index, symbol index pairs to represent symbols
+ * and globals, we use dense number so that they can be easily embeded
+ * in intermediate code and the programs that process them can
+ * use direct access tabls instead of hash table (which would be
+ * necesary otherwise because of the sparse name space caused by
+ * file index, symbol index pairs. Dense number are represented
+ * by RNDXRs.
+ */
+
+/*
+ * The following table defines the meaning of each SYM field as
+ * a function of the "st". (scD/B == scData OR scBss)
+ *
+ * Note: the value "isymMac" is used by symbols that have the concept
+ * of enclosing a block of related information. This value is the
+ * isym of the first symbol AFTER the end associated with the primary
+ * symbol. For example if a procedure was at isym==90 and had an
+ * isymMac==155, the associated end would be at isym==154, and the
+ * symbol at 155 would probably (although not necessarily) be the
+ * symbol for the next procedure. This allows rapid skipping over
+ * internal information of various sorts. "stEnd"s ALWAYS have the
+ * isym of the primary symbol that started the block.
+ *
+
+ST SC VALUE INDEX
+-------- ------ -------- ------
+stFile scText address isymMac
+stLabel scText address ---
+stGlobal scD/B address iaux
+stStatic scD/B address iaux
+stParam scAbs offset iaux
+stLocal scAbs offset iaux
+stProc scText address iaux (isymMac is first AUX)
+stStaticProc scText address iaux (isymMac is first AUX)
+
+stMember scNil ordinal --- (if member of enum)
+ (mipsread thinks the case below has a bit, not byte, offset.)
+stMember scNil byte offset iaux (if member of struct/union)
+stMember scBits bit offset iaux (bit field spec)
+
+stBlock scText address isymMac (text block)
+ (the code seems to think that rather than scNil, we see scInfo for
+ the two cases below.)
+stBlock scNil cb isymMac (struct/union member define)
+stBlock scNil cMembers isymMac (enum member define)
+
+ (New types added by SGI to simplify things:)
+stStruct scInfo cb isymMac (struct type define)
+stUnion scInfo cb isymMac (union type define)
+stEnum scInfo cMembers isymMac (enum type define)
+
+stEnd scText address isymStart
+stEnd scNil ------- isymStart (struct/union/enum)
+
+stTypedef scNil ------- iaux
+stRegReloc sc??? value old register number
+stForward sc??? new address isym to original symbol
+
+stConstant scInfo value --- (scalar)
+stConstant scInfo iss --- (complex, e.g. string)
+
+ *
+ */
+#endif
diff --git a/src/base/loader/coff_symconst.h b/src/base/loader/coff_symconst.h
new file mode 100644
index 000000000..f383c19e6
--- /dev/null
+++ b/src/base/loader/coff_symconst.h
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2003, 2005-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Steve Reinhardt
+ */
+
+/*
+ * Taken from binutils-2.14.90.0.5 include/coff/symconst.h
+ */
+
+/* Declarations of constants for internal format of MIPS ECOFF symbols.
+ Originally contributed by MIPS Computer Systems and Third Eye Software.
+ Changes contributed by Cygnus Support are in the public domain.
+
+ This file is just aggregated with the files that make up the GNU
+ release; it is not considered part of GAS, GDB, or other GNU
+ programs. */
+
+/*
+ * |-----------------------------------------------------------|
+ * | Copyright (c) 1992, 1991, 1990 MIPS Computer Systems, Inc.|
+ * | MIPS Computer Systems, Inc. grants reproduction and use |
+ * | rights to all parties, PROVIDED that this comment is |
+ * | maintained in the copy. |
+ * |-----------------------------------------------------------|
+ */
+
+/* (C) Copyright 1984 by Third Eye Software, Inc.
+ *
+ * Third Eye Software, Inc. grants reproduction and use rights to
+ * all parties, PROVIDED that this comment is maintained in the copy.
+ *
+ * Third Eye makes no claims about the applicability of this
+ * symbol table to a particular use.
+ */
+
+/* glevels for field in FDR */
+#define GLEVEL_0 2
+#define GLEVEL_1 1
+#define GLEVEL_2 0 /* for upward compat reasons. */
+#define GLEVEL_3 3
+
+/* magic number fo symheader */
+#define magicSym 0x7009
+/* The Alpha uses this value instead, for some reason. */
+#define magicSym2 0x1992
+
+/* Language codes */
+#define langC 0
+#define langPascal 1
+#define langFortran 2
+#define langAssembler 3 /* one Assembley inst might map to many mach */
+#define langMachine 4
+#define langNil 5
+#define langAda 6
+#define langPl1 7
+#define langCobol 8
+#define langStdc 9 /* FIXME: Collides with SGI langCplusplus */
+#define langCplusplus 9 /* FIXME: Collides with langStdc */
+#define langCplusplusV2 10 /* SGI addition */
+#define langMax 11 /* maximun allowed 32 -- 5 bits */
+
+/* The following are value definitions for the fields in the SYMR */
+
+/*
+ * Storage Classes
+ */
+
+#define scNil 0
+#define scText 1 /* text symbol */
+#define scData 2 /* initialized data symbol */
+#define scBss 3 /* un-initialized data symbol */
+#define scRegister 4 /* value of symbol is register number */
+#define scAbs 5 /* value of symbol is absolute */
+#define scUndefined 6 /* who knows? */
+#define scCdbLocal 7 /* variable's value is IN se->va.?? */
+#define scBits 8 /* this is a bit field */
+#define scCdbSystem 9 /* variable's value is IN CDB's address space */
+#define scDbx 9 /* overlap dbx internal use */
+#define scRegImage 10 /* register value saved on stack */
+#define scInfo 11 /* symbol contains debugger information */
+#define scUserStruct 12 /* address in struct user for current process */
+#define scSData 13 /* load time only small data */
+#define scSBss 14 /* load time only small common */
+#define scRData 15 /* load time only read only data */
+#define scVar 16 /* Var parameter (fortran,pascal) */
+#define scCommon 17 /* common variable */
+#define scSCommon 18 /* small common */
+#define scVarRegister 19 /* Var parameter in a register */
+#define scVariant 20 /* Variant record */
+#define scSUndefined 21 /* small undefined(external) data */
+#define scInit 22 /* .init section symbol */
+#define scBasedVar 23 /* Fortran or PL/1 ptr based var */
+#define scXData 24 /* exception handling data */
+#define scPData 25 /* Procedure section */
+#define scFini 26 /* .fini section */
+#define scRConst 27 /* .rconst section */
+#define scMax 32
+
+
+/*
+ * Symbol Types
+ */
+
+#define stNil 0 /* Nuthin' special */
+#define stGlobal 1 /* external symbol */
+#define stStatic 2 /* static */
+#define stParam 3 /* procedure argument */
+#define stLocal 4 /* local variable */
+#define stLabel 5 /* label */
+#define stProc 6 /* " " Procedure */
+#define stBlock 7 /* beginnning of block */
+#define stEnd 8 /* end (of anything) */
+#define stMember 9 /* member (of anything - struct/union/enum */
+#define stTypedef 10 /* type definition */
+#define stFile 11 /* file name */
+#define stRegReloc 12 /* register relocation */
+#define stForward 13 /* forwarding address */
+#define stStaticProc 14 /* load time only static procs */
+#define stConstant 15 /* const */
+#define stStaParam 16 /* Fortran static parameters */
+ /* These new symbol types have been recently added to SGI machines. */
+#define stStruct 26 /* Beginning of block defining a struct type */
+#define stUnion 27 /* Beginning of block defining a union type */
+#define stEnum 28 /* Beginning of block defining an enum type */
+#define stIndirect 34 /* Indirect type specification */
+ /* Pseudo-symbols - internal to debugger */
+#define stStr 60 /* string */
+#define stNumber 61 /* pure number (ie. 4 NOR 2+2) */
+#define stExpr 62 /* 2+2 vs. 4 */
+#define stType 63 /* post-coersion SER */
+#define stMax 64
+
+/* definitions for fields in TIR */
+
+/* type qualifiers for ti.tq0 -> ti.(itqMax-1) */
+#define tqNil 0 /* bt is what you see */
+#define tqPtr 1 /* pointer */
+#define tqProc 2 /* procedure */
+#define tqArray 3 /* duh */
+#define tqFar 4 /* longer addressing - 8086/8 land */
+#define tqVol 5 /* volatile */
+#define tqConst 6 /* const */
+#define tqMax 8
+
+/* basic types as seen in ti.bt */
+#define btNil 0 /* undefined (also, enum members) */
+#define btAdr 1 /* address - integer same size as pointer */
+#define btChar 2 /* character */
+#define btUChar 3 /* unsigned character */
+#define btShort 4 /* short */
+#define btUShort 5 /* unsigned short */
+#define btInt 6 /* int */
+#define btUInt 7 /* unsigned int */
+#define btLong 8 /* long */
+#define btULong 9 /* unsigned long */
+#define btFloat 10 /* float (real) */
+#define btDouble 11 /* Double (real) */
+#define btStruct 12 /* Structure (Record) */
+#define btUnion 13 /* Union (variant) */
+#define btEnum 14 /* Enumerated */
+#define btTypedef 15 /* defined via a typedef, isymRef points */
+#define btRange 16 /* subrange of int */
+#define btSet 17 /* pascal sets */
+#define btComplex 18 /* fortran complex */
+#define btDComplex 19 /* fortran double complex */
+#define btIndirect 20 /* forward or unnamed typedef */
+#define btFixedDec 21 /* Fixed Decimal */
+#define btFloatDec 22 /* Float Decimal */
+#define btString 23 /* Varying Length Character String */
+#define btBit 24 /* Aligned Bit String */
+#define btPicture 25 /* Picture */
+#define btVoid 26 /* void */
+#define btLongLong 27 /* long long */
+#define btULongLong 28 /* unsigned long long */
+#define btMax 64
diff --git a/src/base/loader/ecoff_object.cc b/src/base/loader/ecoff_object.cc
new file mode 100644
index 000000000..80917ee9c
--- /dev/null
+++ b/src/base/loader/ecoff_object.cc
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string>
+
+#include "base/loader/ecoff_object.hh"
+#include "base/misc.hh"
+#include "base/loader/symtab.hh"
+
+#include "base/trace.hh" // for DPRINTF
+
+#include "base/loader/exec_ecoff.h"
+#include "base/loader/coff_sym.h"
+#include "base/loader/coff_symconst.h"
+
+using namespace std;
+
+ObjectFile *
+EcoffObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
+{
+ if (((ecoff_filehdr *)data)->f_magic == ECOFF_MAGIC_ALPHA) {
+ // it's Alpha ECOFF
+ return new EcoffObject(fname, fd, len, data,
+ ObjectFile::Alpha, ObjectFile::Tru64);
+ }
+ else {
+ return NULL;
+ }
+}
+
+
+EcoffObject::EcoffObject(const string &_filename, int _fd,
+ size_t _len, uint8_t *_data,
+ Arch _arch, OpSys _opSys)
+ : ObjectFile(_filename, _fd, _len, _data, _arch, _opSys)
+{
+ execHdr = (ecoff_exechdr *)fileData;
+ fileHdr = &(execHdr->f);
+ aoutHdr = &(execHdr->a);
+
+ entry = aoutHdr->entry;
+
+ text.baseAddr = aoutHdr->text_start;
+ text.size = aoutHdr->tsize;
+ text.fileImage = fileData + ECOFF_TXTOFF(execHdr);
+
+ data.baseAddr = aoutHdr->data_start;
+ data.size = aoutHdr->dsize;
+ data.fileImage = fileData + ECOFF_DATOFF(execHdr);
+
+ bss.baseAddr = aoutHdr->bss_start;
+ bss.size = aoutHdr->bsize;
+ bss.fileImage = NULL;
+
+ DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n",
+ text.baseAddr, text.size, data.baseAddr, data.size,
+ bss.baseAddr, bss.size);
+}
+
+
+bool
+EcoffObject::loadGlobalSymbols(SymbolTable *symtab)
+{
+ if (!symtab)
+ return false;
+
+ if (fileHdr->f_magic != ECOFF_MAGIC_ALPHA) {
+ warn("loadGlobalSymbols: wrong magic on %s\n", filename);
+ return false;
+ }
+
+ ecoff_symhdr *syms = (ecoff_symhdr *)(fileData + fileHdr->f_symptr);
+ if (syms->magic != magicSym2) {
+ warn("loadGlobalSymbols: bad symbol header magic on %s\n", filename);
+ return false;
+ }
+
+ ecoff_extsym *ext_syms = (ecoff_extsym *)(fileData + syms->cbExtOffset);
+
+ char *ext_strings = (char *)(fileData + syms->cbSsExtOffset);
+ for (int i = 0; i < syms->iextMax; i++) {
+ ecoff_sym *entry = &(ext_syms[i].asym);
+ if (entry->iss != -1)
+ symtab->insert(entry->value, ext_strings + entry->iss);
+ }
+
+ return true;
+}
+
+bool
+EcoffObject::loadLocalSymbols(SymbolTable *symtab)
+{
+ if (!symtab)
+ return false;
+
+ if (fileHdr->f_magic != ECOFF_MAGIC_ALPHA) {
+ warn("loadGlobalSymbols: wrong magic on %s\n", filename);
+ return false;
+ }
+
+ ecoff_symhdr *syms = (ecoff_symhdr *)(fileData + fileHdr->f_symptr);
+ if (syms->magic != magicSym2) {
+ warn("loadGlobalSymbols: bad symbol header magic on %s\n", filename);
+ return false;
+ }
+
+ ecoff_sym *local_syms = (ecoff_sym *)(fileData + syms->cbSymOffset);
+ char *local_strings = (char *)(fileData + syms->cbSsOffset);
+ ecoff_fdr *fdesc = (ecoff_fdr *)(fileData + syms->cbFdOffset);
+
+ for (int i = 0; i < syms->ifdMax; i++) {
+ ecoff_sym *entry = (ecoff_sym *)(local_syms + fdesc[i].isymBase);
+ char *strings = (char *)(local_strings + fdesc[i].issBase);
+ for (int j = 0; j < fdesc[i].csym; j++) {
+ if (entry[j].st == stGlobal || entry[j].st == stProc)
+ if (entry[j].iss != -1)
+ symtab->insert(entry[j].value, strings + entry[j].iss);
+ }
+ }
+
+ for (int i = 0; i < syms->isymMax; i++) {
+ ecoff_sym *entry = &(local_syms[i]);
+ if (entry->st == stProc)
+ symtab->insert(entry->value, local_strings + entry->iss);
+ }
+
+ return true;
+}
diff --git a/src/base/loader/ecoff_object.hh b/src/base/loader/ecoff_object.hh
new file mode 100644
index 000000000..603c70bec
--- /dev/null
+++ b/src/base/loader/ecoff_object.hh
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ECOFF_OBJECT_HH__
+#define __ECOFF_OBJECT_HH__
+
+#include "base/loader/object_file.hh"
+
+// forward decls: avoid including exec_ecoff.h here
+struct ecoff_exechdr;
+struct ecoff_filehdr;
+struct ecoff_aouthdr;
+
+class EcoffObject : public ObjectFile
+{
+ protected:
+ ecoff_exechdr *execHdr;
+ ecoff_filehdr *fileHdr;
+ ecoff_aouthdr *aoutHdr;
+
+ EcoffObject(const std::string &_filename, int _fd,
+ size_t _len, uint8_t *_data,
+ Arch _arch, OpSys _opSys);
+
+ public:
+ virtual ~EcoffObject() {}
+
+ virtual bool loadGlobalSymbols(SymbolTable *symtab);
+ virtual bool loadLocalSymbols(SymbolTable *symtab);
+
+ static ObjectFile *tryFile(const std::string &fname, int fd,
+ size_t len, uint8_t *data);
+};
+
+#endif // __ECOFF_OBJECT_HH__
diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc
new file mode 100644
index 000000000..165501e1c
--- /dev/null
+++ b/src/base/loader/elf_object.cc
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string>
+
+// Because of the -Wundef flag we have to do this
+#define __LIBELF_INTERNAL__ 0
+// counterintuitive, but the flag below causes libelf to define
+// 64-bit elf types that apparently didn't exist in some older
+// versions of Linux. They seem to be there in 2.4.x, so don't
+// set this now (it causes things to break on 64-bit platforms).
+#define __LIBELF64_LINUX 0
+#define __LIBELF_NEED_LINK_H 0
+#define __LIBELF_SYMBOL_VERSIONS 0
+
+#include "libelf/libelf.h"
+#include "libelf/gelf.h"
+
+#include "base/loader/elf_object.hh"
+#include "base/misc.hh"
+
+#include "base/loader/symtab.hh"
+
+#include "base/trace.hh" // for DPRINTF
+
+#include "sim/byteswap.hh"
+
+
+using namespace std;
+
+ObjectFile *
+ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
+{
+ Elf *elf;
+ GElf_Ehdr ehdr;
+ Arch arch = UnknownArch;
+ OpSys opSys = UnknownOpSys;
+
+ // check that header matches library version
+ if (elf_version(EV_CURRENT) == EV_NONE)
+ panic("wrong elf version number!");
+
+ // get a pointer to elf structure
+ elf = elf_memory((char*)data,len);
+ // will only fail if fd is invalid
+ assert(elf != NULL);
+
+ // Check that we actually have a elf file
+ if (gelf_getehdr(elf, &ehdr) ==0) {
+ DPRINTFR(Loader, "Not ELF\n");
+ elf_end(elf);
+ return NULL;
+ } else {
+ //Detect the architecture
+ //Since we don't know how to check for alpha right now, we'll
+ //just assume if it wasn't something else and it's 64 bit, that's
+ //what it must be.
+ if (ehdr.e_machine == EM_SPARC64 ||
+ ehdr.e_machine == EM_SPARC ||
+ ehdr.e_machine == EM_SPARCV9) {
+ arch = ObjectFile::SPARC;
+ } else if (ehdr.e_machine == EM_MIPS
+ && ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
+ arch = ObjectFile::Mips;
+ } else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
+ arch = ObjectFile::Alpha;
+ } else {
+ warn("Unknown architecture: %d\n", ehdr.e_machine);
+ arch = ObjectFile::UnknownArch;
+ }
+
+ //Detect the operating system
+ switch (ehdr.e_ident[EI_OSABI])
+ {
+
+ case ELFOSABI_LINUX:
+ opSys = ObjectFile::Linux;
+ break;
+ case ELFOSABI_SOLARIS:
+ opSys = ObjectFile::Solaris;
+ break;
+ case ELFOSABI_TRU64:
+ opSys = ObjectFile::Tru64;
+ break;
+ default:
+ opSys = ObjectFile::UnknownOpSys;
+ }
+
+ //take a look at the .note.ABI section
+ //It can let us know what's what.
+ if (opSys == ObjectFile::UnknownOpSys) {
+ Elf_Scn *section;
+ GElf_Shdr shdr;
+ Elf_Data *data;
+ uint32_t osAbi;;
+ int secIdx = 1;
+
+ // Get the first section
+ section = elf_getscn(elf, secIdx);
+
+ // While there are no more sections
+ while (section != NULL && opSys == ObjectFile::UnknownOpSys) {
+ gelf_getshdr(section, &shdr);
+ if (shdr.sh_type == SHT_NOTE && !strcmp(".note.ABI-tag",
+ elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) {
+ // we have found a ABI note section
+ // Check the 5th 32bit word for OS 0 == linux, 1 == hurd,
+ // 2 == solaris, 3 == freebsd
+ data = elf_rawdata(section, NULL);
+ assert(data->d_buf);
+ if(ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
+ osAbi = htole(((uint32_t*)data->d_buf)[4]);
+ else
+ osAbi = htobe(((uint32_t*)data->d_buf)[4]);
+
+ switch(osAbi) {
+ case 0:
+ opSys = ObjectFile::Linux;
+ break;
+ case 2:
+ opSys = ObjectFile::Solaris;
+ break;
+ }
+ } // if section found
+ if (!strcmp(".SUNW_version", elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name)))
+ opSys = ObjectFile::Solaris;
+ if (!strcmp(".stab.index", elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name)))
+ opSys = ObjectFile::Solaris;
+
+ section = elf_getscn(elf, ++secIdx);
+ } // while sections
+ }
+
+ elf_end(elf);
+ return new ElfObject(fname, fd, len, data, arch, opSys);
+ }
+}
+
+
+ElfObject::ElfObject(const string &_filename, int _fd,
+ size_t _len, uint8_t *_data,
+ Arch _arch, OpSys _opSys)
+ : ObjectFile(_filename, _fd, _len, _data, _arch, _opSys)
+
+{
+ Elf *elf;
+ GElf_Ehdr ehdr;
+
+ // check that header matches library version
+ if (elf_version(EV_CURRENT) == EV_NONE)
+ panic("wrong elf version number!");
+
+ // get a pointer to elf structure
+ elf = elf_memory((char*)fileData,len);
+ // will only fail if fd is invalid
+ assert(elf != NULL);
+
+ // Check that we actually have a elf file
+ if (gelf_getehdr(elf, &ehdr) ==0) {
+ panic("Not ELF, shouldn't be here");
+ }
+
+ entry = ehdr.e_entry;
+
+
+ // initialize segment sizes to 0 in case they're not present
+ text.size = data.size = bss.size = 0;
+
+ for (int i = 0; i < ehdr.e_phnum; ++i) {
+ GElf_Phdr phdr;
+ if (gelf_getphdr(elf, i, &phdr) == 0) {
+ panic("gelf_getphdr failed for section %d", i);
+ }
+
+ // for now we don't care about non-loadable segments
+ if (!(phdr.p_type & PT_LOAD))
+ continue;
+
+ // the headers don't explicitly distinguish text from data,
+ // but empirically the text segment comes first.
+ if (text.size == 0) { // haven't seen text segment yet
+ text.baseAddr = phdr.p_vaddr;
+ text.size = phdr.p_filesz;
+ text.fileImage = fileData + phdr.p_offset;
+ // if there's any padding at the end that's not in the
+ // file, call it the bss. This happens in the "text"
+ // segment if there's only one loadable segment (as for
+ // kernel images).
+ bss.size = phdr.p_memsz - phdr.p_filesz;
+ bss.baseAddr = phdr.p_vaddr + phdr.p_filesz;
+ bss.fileImage = NULL;
+ } else if (data.size == 0) { // have text, this must be data
+ data.baseAddr = phdr.p_vaddr;
+ data.size = phdr.p_filesz;
+ data.fileImage = fileData + phdr.p_offset;
+ // if there's any padding at the end that's not in the
+ // file, call it the bss. Warn if this happens for both
+ // the text & data segments (should only have one bss).
+ if (phdr.p_memsz - phdr.p_filesz > 0 && bss.size != 0) {
+ warn("Two implied bss segments in file!\n");
+ }
+ bss.size = phdr.p_memsz - phdr.p_filesz;
+ bss.baseAddr = phdr.p_vaddr + phdr.p_filesz;
+ bss.fileImage = NULL;
+ } else {
+ warn("More than two loadable segments in ELF object.");
+ warn("Ignoring segment @ 0x%x length 0x%x.",
+ phdr.p_vaddr, phdr.p_filesz);
+ }
+ }
+
+ // should have found at least one loadable segment
+ assert(text.size != 0);
+
+ DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n",
+ text.baseAddr, text.size, data.baseAddr, data.size,
+ bss.baseAddr, bss.size);
+
+ elf_end(elf);
+
+ // We will actually read the sections when we need to load them
+}
+
+
+bool
+ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding)
+{
+ Elf *elf;
+ int sec_idx = 1; // there is a 0 but it is nothing, go figure
+ Elf_Scn *section;
+ GElf_Shdr shdr;
+ Elf_Data *data;
+ int count, ii;
+ bool found = false;
+ GElf_Sym sym;
+
+ if (!symtab)
+ return false;
+
+ // check that header matches library version
+ if (elf_version(EV_CURRENT) == EV_NONE)
+ panic("wrong elf version number!");
+
+ // get a pointer to elf structure
+ elf = elf_memory((char*)fileData,len);
+
+ assert(elf != NULL);
+
+ // Get the first section
+ section = elf_getscn(elf, sec_idx);
+
+ // While there are no more sections
+ while (section != NULL) {
+ gelf_getshdr(section, &shdr);
+
+ if (shdr.sh_type == SHT_SYMTAB) {
+ found = true;
+ data = elf_getdata(section, NULL);
+ count = shdr.sh_size / shdr.sh_entsize;
+ DPRINTF(Loader, "Found Symbol Table, %d symbols present\n", count);
+
+ // loop through all the symbols, only loading global ones
+ for (ii = 0; ii < count; ++ii) {
+ gelf_getsym(data, ii, &sym);
+ if (GELF_ST_BIND(sym.st_info) == binding) {
+ symtab->insert(sym.st_value,
+ elf_strptr(elf, shdr.sh_link, sym.st_name));
+ }
+ }
+ }
+ ++sec_idx;
+ section = elf_getscn(elf, sec_idx);
+ }
+
+ elf_end(elf);
+
+ return found;
+}
+
+bool
+ElfObject::loadGlobalSymbols(SymbolTable *symtab)
+{
+ return loadSomeSymbols(symtab, STB_GLOBAL);
+}
+
+bool
+ElfObject::loadLocalSymbols(SymbolTable *symtab)
+{
+ return loadSomeSymbols(symtab, STB_LOCAL);
+}
diff --git a/src/base/loader/elf_object.hh b/src/base/loader/elf_object.hh
new file mode 100644
index 000000000..72c265edd
--- /dev/null
+++ b/src/base/loader/elf_object.hh
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ELF_OBJECT_HH__
+#define __ELF_OBJECT_HH__
+
+#include "base/loader/object_file.hh"
+
+class ElfObject : public ObjectFile
+{
+ protected:
+
+ /// Helper functions for loadGlobalSymbols() and loadLocalSymbols().
+ bool loadSomeSymbols(SymbolTable *symtab, int binding);
+
+ ElfObject(const std::string &_filename, int _fd,
+ size_t _len, uint8_t *_data,
+ Arch _arch, OpSys _opSys);
+
+ public:
+ virtual ~ElfObject() {}
+
+ virtual bool loadGlobalSymbols(SymbolTable *symtab);
+ virtual bool loadLocalSymbols(SymbolTable *symtab);
+
+ static ObjectFile *tryFile(const std::string &fname, int fd,
+ size_t len, uint8_t *data);
+};
+
+#endif // __ELF_OBJECT_HH__
diff --git a/src/base/loader/exec_aout.h b/src/base/loader/exec_aout.h
new file mode 100644
index 000000000..eed44baee
--- /dev/null
+++ b/src/base/loader/exec_aout.h
@@ -0,0 +1,61 @@
+/*
+ * Taken from NetBSD sys/exec_aout.h
+ */
+
+/* $NetBSD: exec_aout.h,v 1.29 2002/12/10 17:14:31 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1993, 1994 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SYS_EXEC_AOUT_H_
+#define _SYS_EXEC_AOUT_H_
+
+#ifndef N_PAGSIZ
+#define N_PAGSIZ(ex) (AOUT_LDPGSZ)
+#endif
+
+/* a_magic */
+#define OMAGIC 0407 /* old impure format */
+#define NMAGIC 0410 /* read-only text */
+#define ZMAGIC 0413 /* demand load format */
+
+#define N_ALIGN(ex,x) \
+ (N_GETMAGIC(ex) == ZMAGIC ? \
+ ((x) + AOUT_LDPGSZ - 1) & ~(AOUT_LDPGSZ - 1) : (x))
+
+/* Valid magic number check. */
+#define N_BADMAG(ex) \
+ (N_GETMAGIC(ex) != NMAGIC && N_GETMAGIC(ex) != OMAGIC && \
+ N_GETMAGIC(ex) != ZMAGIC)
+
+//Only alpha will be able to load aout for now
+#include "arch/alpha/aout_machdep.h"
+
+#endif /* !_SYS_EXEC_AOUT_H_ */
diff --git a/src/base/loader/exec_ecoff.h b/src/base/loader/exec_ecoff.h
new file mode 100644
index 000000000..555589806
--- /dev/null
+++ b/src/base/loader/exec_ecoff.h
@@ -0,0 +1,110 @@
+/*
+ * Taken from NetBSD sys/exec_ecoff.h
+ */
+
+/* $NetBSD: exec_ecoff.h,v 1.13 2003/01/18 09:53:18 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1994 Adam Glass
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Adam Glass.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SYS_EXEC_ECOFF_H_
+#define _SYS_EXEC_ECOFF_H_
+
+//Only alpha will be able to load ecoff files for now
+#include "arch/alpha/ecoff_machdep.h"
+
+struct ecoff_filehdr {
+ coff_ushort f_magic; /* magic number */
+ coff_ushort f_nscns; /* # of sections */
+ coff_uint f_timdat; /* time and date stamp */
+ coff_ulong f_symptr; /* file offset of symbol table */
+ coff_uint f_nsyms; /* # of symbol table entries */
+ coff_ushort f_opthdr; /* sizeof the optional header */
+ coff_ushort f_flags; /* flags??? */
+};
+
+struct ecoff_aouthdr {
+ coff_ushort magic;
+ coff_ushort vstamp;
+ ECOFF_PAD
+ coff_ulong tsize;
+ coff_ulong dsize;
+ coff_ulong bsize;
+ coff_ulong entry;
+ coff_ulong text_start;
+ coff_ulong data_start;
+ coff_ulong bss_start;
+ ECOFF_MACHDEP;
+};
+
+struct ecoff_scnhdr { /* needed for size info */
+ char s_name[8]; /* name */
+ coff_ulong s_paddr; /* physical addr? for ROMing?*/
+ coff_ulong s_vaddr; /* virtual addr? */
+ coff_ulong s_size; /* size */
+ coff_ulong s_scnptr; /* file offset of raw data */
+ coff_ulong s_relptr; /* file offset of reloc data */
+ coff_ulong s_lnnoptr; /* file offset of line data */
+ coff_ushort s_nreloc; /* # of relocation entries */
+ coff_ushort s_nlnno; /* # of line entries */
+ coff_uint s_flags; /* flags */
+};
+
+struct ecoff_exechdr {
+ struct ecoff_filehdr f;
+ struct ecoff_aouthdr a;
+};
+
+#define ECOFF_HDR_SIZE (sizeof(struct ecoff_exechdr))
+
+#define ECOFF_OMAGIC 0407
+#define ECOFF_NMAGIC 0410
+#define ECOFF_ZMAGIC 0413
+
+#define ECOFF_ROUND(value, by) \
+ (((value) + (by) - 1) & ~((by) - 1))
+
+#define ECOFF_BLOCK_ALIGN(ep, value) \
+ ((ep)->a.magic == ECOFF_ZMAGIC ? ECOFF_ROUND((value), ECOFF_LDPGSZ) : \
+ (value))
+
+#define ECOFF_TXTOFF(ep) \
+ ((ep)->a.magic == ECOFF_ZMAGIC ? 0 : \
+ ECOFF_ROUND(ECOFF_HDR_SIZE + (ep)->f.f_nscns * \
+ sizeof(struct ecoff_scnhdr), ECOFF_SEGMENT_ALIGNMENT(ep)))
+
+#define ECOFF_DATOFF(ep) \
+ (ECOFF_BLOCK_ALIGN((ep), ECOFF_TXTOFF(ep) + (ep)->a.tsize))
+
+#define ECOFF_SEGMENT_ALIGN(ep, value) \
+ (ECOFF_ROUND((value), ((ep)->a.magic == ECOFF_ZMAGIC ? ECOFF_LDPGSZ : \
+ ECOFF_SEGMENT_ALIGNMENT(ep))))
+
+#endif /* !_SYS_EXEC_ECOFF_H_ */
diff --git a/src/base/loader/object_file.cc b/src/base/loader/object_file.cc
new file mode 100644
index 000000000..c6dfced1d
--- /dev/null
+++ b/src/base/loader/object_file.cc
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2002-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <list>
+#include <string>
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "base/cprintf.hh"
+#include "base/loader/object_file.hh"
+#include "base/loader/symtab.hh"
+
+#include "base/loader/ecoff_object.hh"
+#include "base/loader/aout_object.hh"
+#include "base/loader/elf_object.hh"
+
+#include "mem/translating_port.hh"
+
+using namespace std;
+
+ObjectFile::ObjectFile(const string &_filename, int _fd,
+ size_t _len, uint8_t *_data,
+ Arch _arch, OpSys _opSys)
+ : filename(_filename), descriptor(_fd), fileData(_data), len(_len),
+ arch(_arch), opSys(_opSys)
+{
+}
+
+
+ObjectFile::~ObjectFile()
+{
+ close();
+}
+
+
+bool
+ObjectFile::loadSection(Section *sec, Port *memPort, Addr addrMask)
+{
+ if (sec->size != 0) {
+ Addr addr = sec->baseAddr & addrMask;
+ if (sec->fileImage) {
+ memPort->writeBlob(addr, sec->fileImage, sec->size);
+ }
+ else {
+ // no image: must be bss
+ memPort->memsetBlob(addr, 0, sec->size);
+ }
+ }
+ return true;
+}
+
+
+bool
+ObjectFile::loadSections(Port *memPort, Addr addrMask)
+{
+ return (loadSection(&text, memPort, addrMask)
+ && loadSection(&data, memPort, addrMask)
+ && loadSection(&bss, memPort, addrMask));
+}
+
+
+void
+ObjectFile::close()
+{
+ if (descriptor >= 0) {
+ ::close(descriptor);
+ descriptor = -1;
+ }
+
+ if (fileData) {
+ ::munmap(fileData, len);
+ fileData = NULL;
+ }
+}
+
+
+ObjectFile *
+createObjectFile(const string &fname)
+{
+ // open the file
+ int fd = open(fname.c_str(), O_RDONLY);
+ if (fd < 0) {
+ return NULL;
+ }
+
+ // find the length of the file by seeking to the end
+ size_t len = (size_t)lseek(fd, 0, SEEK_END);
+
+ // mmap the whole shebang
+ uint8_t *fileData =
+ (uint8_t *)mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
+ if (fileData == MAP_FAILED) {
+ close(fd);
+ return NULL;
+ }
+
+ ObjectFile *fileObj = NULL;
+
+ // figure out what we have here
+ if ((fileObj = EcoffObject::tryFile(fname, fd, len, fileData)) != NULL) {
+ return fileObj;
+ }
+
+ if ((fileObj = AoutObject::tryFile(fname, fd, len, fileData)) != NULL) {
+ return fileObj;
+ }
+
+ if ((fileObj = ElfObject::tryFile(fname, fd, len, fileData)) != NULL) {
+ return fileObj;
+ }
+
+ // don't know what it is
+ close(fd);
+ munmap(fileData, len);
+ return NULL;
+}
diff --git a/src/base/loader/object_file.hh b/src/base/loader/object_file.hh
new file mode 100644
index 000000000..b43989cb5
--- /dev/null
+++ b/src/base/loader/object_file.hh
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2002-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __OBJECT_FILE_HH__
+#define __OBJECT_FILE_HH__
+
+#include <limits>
+#include <string>
+
+#include "sim/host.hh" // for Addr
+
+class Port;
+class SymbolTable;
+
+class ObjectFile
+{
+ public:
+
+ enum Arch {
+ UnknownArch,
+ Alpha,
+ SPARC,
+ Mips
+ };
+
+ enum OpSys {
+ UnknownOpSys,
+ Tru64,
+ Linux,
+ Solaris
+ };
+
+ protected:
+ const std::string filename;
+ int descriptor;
+ uint8_t *fileData;
+ size_t len;
+
+ Arch arch;
+ OpSys opSys;
+
+ ObjectFile(const std::string &_filename, int _fd,
+ size_t _len, uint8_t *_data,
+ Arch _arch, OpSys _opSys);
+
+ public:
+ virtual ~ObjectFile();
+
+ void close();
+
+ virtual bool loadSections(Port *memPort, Addr addrMask =
+ std::numeric_limits<Addr>::max());
+ virtual bool loadGlobalSymbols(SymbolTable *symtab) = 0;
+ virtual bool loadLocalSymbols(SymbolTable *symtab) = 0;
+
+ Arch getArch() const { return arch; }
+ OpSys getOpSys() const { return opSys; }
+
+ protected:
+
+ struct Section {
+ Addr baseAddr;
+ uint8_t *fileImage;
+ size_t size;
+ };
+
+ Addr entry;
+ Addr globalPtr;
+
+ Section text;
+ Section data;
+ Section bss;
+
+ bool loadSection(Section *sec, Port *memPort, Addr addrMask);
+ void setGlobalPointer(Addr global_ptr) { globalPtr = global_ptr; }
+
+ public:
+ Addr entryPoint() const { return entry; }
+
+ Addr globalPointer() const { return globalPtr; }
+
+ Addr textBase() const { return text.baseAddr; }
+ Addr dataBase() const { return data.baseAddr; }
+ Addr bssBase() const { return bss.baseAddr; }
+
+ size_t textSize() const { return text.size; }
+ size_t dataSize() const { return data.size; }
+ size_t bssSize() const { return bss.size; }
+};
+
+ObjectFile *createObjectFile(const std::string &fname);
+
+
+#endif // __OBJECT_FILE_HH__
diff --git a/src/base/loader/symtab.cc b/src/base/loader/symtab.cc
new file mode 100644
index 000000000..25f54f9bf
--- /dev/null
+++ b/src/base/loader/symtab.cc
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+
+#include "base/loader/symtab.hh"
+#include "base/misc.hh"
+#include "base/str.hh"
+#include "sim/host.hh"
+#include "sim/serialize.hh"
+
+using namespace std;
+
+SymbolTable *debugSymbolTable = NULL;
+
+void
+SymbolTable::clear()
+{
+ addrTable.clear();
+ symbolTable.clear();
+}
+
+bool
+SymbolTable::insert(Addr address, string symbol)
+{
+ if (symbol.empty())
+ return false;
+
+ if (!addrTable.insert(make_pair(address, symbol)).second)
+ return false;
+
+ if (!symbolTable.insert(make_pair(symbol, address)).second)
+ return false;
+
+ return true;
+}
+
+
+bool
+SymbolTable::load(const string &filename)
+{
+ string buffer;
+ ifstream file(filename.c_str());
+
+ if (!file)
+ fatal("file error: Can't open symbol table file %s\n", filename);
+
+ while (!file.eof()) {
+ getline(file, buffer);
+ if (buffer.empty())
+ continue;
+
+ int idx = buffer.find(',');
+ if (idx == string::npos)
+ return false;
+
+ string address = buffer.substr(0, idx);
+ eat_white(address);
+ if (address.empty())
+ return false;
+
+ string symbol = buffer.substr(idx + 1);
+ eat_white(symbol);
+ if (symbol.empty())
+ return false;
+
+ Addr addr;
+ if (!to_number(address, addr))
+ return false;
+
+ if (!insert(addr, symbol))
+ return false;
+ }
+
+ file.close();
+
+ return true;
+}
+
+void
+SymbolTable::serialize(const string &base, ostream &os)
+{
+ paramOut(os, base + ".size", addrTable.size());
+
+ int i = 0;
+ ATable::const_iterator p, end = addrTable.end();
+ for (p = addrTable.begin(); p != end; ++p) {
+ paramOut(os, csprintf("%s.addr_%d", base, i), p->first);
+ paramOut(os, csprintf("%s.symbol_%d", base, i), p->second);
+ ++i;
+ }
+}
+
+void
+SymbolTable::unserialize(const string &base, Checkpoint *cp,
+ const string &section)
+{
+ clear();
+ int size;
+ paramIn(cp, section, base + ".size", size);
+ for (int i = 0; i < size; ++i) {
+ Addr addr;
+ std::string symbol;
+
+ paramIn(cp, section, csprintf("%s.addr_%d", base, i), addr);
+ paramIn(cp, section, csprintf("%s.symbol_%d", base, i), symbol);
+ insert(addr, symbol);
+ }
+}
diff --git a/src/base/loader/symtab.hh b/src/base/loader/symtab.hh
new file mode 100644
index 000000000..ebcda1345
--- /dev/null
+++ b/src/base/loader/symtab.hh
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SYMTAB_HH__
+#define __SYMTAB_HH__
+
+#include <iosfwd>
+#include <map>
+
+#include "arch/isa_traits.hh" // for Addr
+
+class Checkpoint;
+class SymbolTable
+{
+ public:
+ typedef std::map<Addr, std::string> ATable;
+ typedef std::map<std::string, Addr> STable;
+
+ private:
+ ATable addrTable;
+ STable symbolTable;
+
+ private:
+ bool
+ upperBound(Addr addr, ATable::const_iterator &iter) const
+ {
+ // find first key *larger* than desired address
+ iter = addrTable.upper_bound(addr);
+
+ // if very first key is larger, we're out of luck
+ if (iter == addrTable.begin())
+ return false;
+
+ return true;
+ }
+
+ public:
+ SymbolTable() {}
+ SymbolTable(const std::string &file) { load(file); }
+ ~SymbolTable() {}
+
+ void clear();
+ bool insert(Addr address, std::string symbol);
+ bool load(const std::string &file);
+
+ const ATable &getAddrTable() const { return addrTable; }
+ const STable &getSymbolTable() const { return symbolTable; }
+
+ public:
+ void serialize(const std::string &base, std::ostream &os);
+ void unserialize(const std::string &base, Checkpoint *cp,
+ const std::string &section);
+
+ public:
+ bool
+ findSymbol(Addr address, std::string &symbol) const
+ {
+ ATable::const_iterator i = addrTable.find(address);
+ if (i == addrTable.end())
+ return false;
+
+ symbol = (*i).second;
+ return true;
+ }
+
+ bool
+ findAddress(const std::string &symbol, Addr &address) const
+ {
+ STable::const_iterator i = symbolTable.find(symbol);
+ if (i == symbolTable.end())
+ return false;
+
+ address = (*i).second;
+ return true;
+ }
+
+ /// Find the nearest symbol equal to or less than the supplied
+ /// address (e.g., the label for the enclosing function).
+ /// @param address The address to look up.
+ /// @param symbol Return reference for symbol string.
+ /// @param sym_address Return reference for symbol address.
+ /// @param next_sym_address Address of following symbol (for
+ /// determining valid range of symbol).
+ /// @retval True if a symbol was found.
+ bool
+ findNearestSymbol(Addr addr, std::string &symbol, Addr &symaddr,
+ Addr &nextaddr) const
+ {
+ ATable::const_iterator i;
+ if (!upperBound(addr, i))
+ return false;
+
+ nextaddr = i->first;
+ --i;
+ symaddr = i->first;
+ symbol = i->second;
+ return true;
+ }
+
+ /// Overload for findNearestSymbol() for callers who don't care
+ /// about next_sym_address.
+ bool
+ findNearestSymbol(Addr addr, std::string &symbol, Addr &symaddr) const
+ {
+ ATable::const_iterator i;
+ if (!upperBound(addr, i))
+ return false;
+
+ --i;
+ symaddr = i->first;
+ symbol = i->second;
+ return true;
+ }
+
+
+ bool
+ findNearestAddr(Addr addr, Addr &symaddr, Addr &nextaddr) const
+ {
+ ATable::const_iterator i;
+ if (!upperBound(addr, i))
+ return false;
+
+ nextaddr = i->first;
+ --i;
+ symaddr = i->first;
+ return true;
+ }
+
+ bool
+ findNearestAddr(Addr addr, Addr &symaddr) const
+ {
+ ATable::const_iterator i;
+ if (!upperBound(addr, i))
+ return false;
+
+ --i;
+ symaddr = i->first;
+ return true;
+ }
+};
+
+/// Global unified debugging symbol table (for target). Conceptually
+/// there should be one of these per System object for full system,
+/// and per Process object for non-full-system, but so far one big
+/// global one has worked well enough.
+extern SymbolTable *debugSymbolTable;
+
+#endif // __SYMTAB_HH__
diff --git a/src/base/match.cc b/src/base/match.cc
new file mode 100644
index 000000000..4f1f49b57
--- /dev/null
+++ b/src/base/match.cc
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "base/match.hh"
+#include "base/str.hh"
+
+using namespace std;
+
+ObjectMatch::ObjectMatch()
+{
+}
+
+ObjectMatch::ObjectMatch(const string &expr)
+{
+ setExpression(expr);
+}
+
+void
+ObjectMatch::setExpression(const string &expr)
+{
+ tokens.resize(1);
+ tokenize(tokens[0], expr, '.');
+}
+
+void
+ObjectMatch::setExpression(const vector<string> &expr)
+{
+ if (expr.empty()) {
+ tokens.resize(0);
+ } else {
+ tokens.resize(expr.size());
+ for (int i = 0; i < expr.size(); ++i)
+ tokenize(tokens[i], expr[i], '.');
+ }
+}
+
+/**
+ * @todo this should probably be changed to just use regular
+ * expression code
+ */
+bool
+ObjectMatch::domatch(const string &name) const
+{
+ vector<string> name_tokens;
+ tokenize(name_tokens, name, '.');
+ int ntsize = name_tokens.size();
+
+ int num_expr = tokens.size();
+ for (int i = 0; i < num_expr; ++i) {
+ const vector<string> &token = tokens[i];
+ int jstop = token.size();
+
+ bool match = true;
+ for (int j = 0; j < jstop; ++j) {
+ if (j >= ntsize)
+ break;
+
+ const string &var = token[j];
+ if (var != "*" && var != name_tokens[j]) {
+ match = false;
+ break;
+ }
+ }
+
+ if (match == true)
+ return true;
+ }
+
+ return false;
+}
+
diff --git a/src/base/match.hh b/src/base/match.hh
new file mode 100644
index 000000000..1b0a083a7
--- /dev/null
+++ b/src/base/match.hh
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* @file
+ * User Console Definitions
+ */
+
+#ifndef __BASE_MATCH_HH__
+#define __BASE_MATCH_HH__
+
+#include <string>
+#include <vector>
+
+class ObjectMatch
+{
+ protected:
+ std::vector<std::vector<std::string> > tokens;
+ bool domatch(const std::string &name) const;
+
+ public:
+ ObjectMatch();
+ ObjectMatch(const std::string &expression);
+ void setExpression(const std::string &expression);
+ void setExpression(const std::vector<std::string> &expression);
+ bool match(const std::string &name) const
+ {
+ return tokens.empty() ? false : domatch(name);
+ }
+};
+
+#endif // __BASE_MATCH_HH__
+
diff --git a/src/base/misc.cc b/src/base/misc.cc
new file mode 100644
index 000000000..f3c86827b
--- /dev/null
+++ b/src/base/misc.cc
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <iostream>
+#include <string>
+
+#include "base/cprintf.hh"
+#include "base/hostinfo.hh"
+#include "base/misc.hh"
+#include "base/output.hh"
+#include "base/trace.hh"
+#include "sim/host.hh"
+#include "sim/root.hh"
+
+using namespace std;
+
+void
+__panic(const string &format, cp::ArgList &args, const char *func,
+ const char *file, int line)
+{
+ string fmt = "panic: " + format;
+ switch (fmt[fmt.size() - 1]) {
+ case '\n':
+ case '\r':
+ break;
+ default:
+ fmt += "\n";
+ }
+
+ fmt += " @ cycle %d\n[%s:%s, line %d]\n";
+
+ args.append(curTick);
+ args.append(func);
+ args.append(file);
+ args.append(line);
+ args.dump(cerr, fmt);
+
+ delete &args;
+
+ abort();
+}
+
+void
+__fatal(const string &format, cp::ArgList &args, const char *func,
+ const char *file, int line)
+{
+ string fmt = "fatal: " + format;
+
+ switch (fmt[fmt.size() - 1]) {
+ case '\n':
+ case '\r':
+ break;
+ default:
+ fmt += "\n";
+ }
+
+ fmt += " @ cycle %d\n[%s:%s, line %d]\n";
+ fmt += "Memory Usage: %ld KBytes\n";
+
+ args.append(curTick);
+ args.append(func);
+ args.append(file);
+ args.append(line);
+ args.append(memUsage());
+ args.dump(cerr, fmt);
+
+ delete &args;
+
+ exit(1);
+}
+
+void
+__warn(const string &format, cp::ArgList &args, const char *func,
+ const char *file, int line)
+{
+ string fmt = "warn: " + format;
+
+ switch (fmt[fmt.size() - 1]) {
+ case '\n':
+ case '\r':
+ break;
+ default:
+ fmt += "\n";
+ }
+
+#ifdef VERBOSE_WARN
+ fmt += " @ cycle %d\n[%s:%s, line %d]\n";
+ args.append(curTick);
+ args.append(func);
+ args.append(file);
+ args.append(line);
+#endif
+
+ args.dump(cerr, fmt);
+ if (simout.isFile(*outputStream))
+ args.dump(*outputStream, fmt);
+
+ delete &args;
+}
diff --git a/src/base/misc.hh b/src/base/misc.hh
new file mode 100644
index 000000000..9255c69c6
--- /dev/null
+++ b/src/base/misc.hh
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MISC_HH__
+#define __MISC_HH__
+
+#include <assert.h>
+#include "base/cprintf.hh"
+
+//
+// This implements a cprintf based panic() function. panic() should
+// be called when something happens that should never ever happen
+// regardless of what the user does (i.e., an acutal m5 bug). panic()
+// calls abort which can dump core or enter the debugger.
+//
+//
+void __panic(const std::string&, cp::ArgList &, const char*, const char*, int)
+ __attribute__((noreturn));
+#define __panic__(format, args...) \
+ __panic(format, (*(new cp::ArgList), args), \
+ __FUNCTION__, __FILE__, __LINE__)
+#define panic(args...) \
+ __panic__(args, cp::ArgListNull())
+
+//
+// This implements a cprintf based fatal() function. fatal() should
+// be called when the simulation cannot continue due to some condition
+// that is the user's fault (bad configuration, invalid arguments,
+// etc.) and not a simulator bug. fatal() calls exit(1), i.e., a
+// "normal" exit with an error code, as opposed to abort() like
+// panic() does.
+//
+void __fatal(const std::string&, cp::ArgList &, const char*, const char*, int)
+ __attribute__((noreturn));
+#define __fatal__(format, args...) \
+ __fatal(format, (*(new cp::ArgList), args), \
+ __FUNCTION__, __FILE__, __LINE__)
+#define fatal(args...) \
+ __fatal__(args, cp::ArgListNull())
+
+//
+// This implements a cprintf based warn
+//
+void __warn(const std::string&, cp::ArgList &, const char*, const char*, int);
+#define __warn__(format, args...) \
+ __warn(format, (*(new cp::ArgList), args), \
+ __FUNCTION__, __FILE__, __LINE__)
+#define warn(args...) \
+ __warn__(args, cp::ArgListNull())
+
+//
+// assert() that prints out the current cycle
+//
+#define m5_assert(TEST) \
+ if (!(TEST)) { \
+ std::cerr << "Assertion failure, curTick = " << curTick << std::endl; \
+ } \
+ assert(TEST);
+
+#endif // __MISC_HH__
diff --git a/src/base/mod_num.hh b/src/base/mod_num.hh
new file mode 100644
index 000000000..fabbb56a9
--- /dev/null
+++ b/src/base/mod_num.hh
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+template<class T, T MV>
+class ModNum {
+ private:
+ T value;
+
+ // Compiler should optimize this
+ void setValue(T n) { value = n % MV; }
+
+ public:
+ ModNum() {}
+ ModNum(T n) { setValue(n); }
+ ModNum(const ModNum<T, MV> &n) : value(n.value) {}
+
+ ModNum operator=(T n) {
+ setValue(n);
+ return *this;
+ }
+
+ const ModNum operator=(ModNum n) {
+ value = n.value;
+ return *this;
+ }
+
+ // Return the value if object used as RHS
+ operator T() const { return value; }
+
+ //
+ // Operator "+="
+ //
+ const ModNum<T, MV> operator+=(ModNum<T, MV> r) {
+ setValue(value + r.value);
+ return *this;
+ }
+
+ const ModNum<T, MV> operator+=(T r) {
+ setValue(value + r);
+ return *this;
+ }
+
+ //
+ // Operator "-="
+ //
+ const ModNum<T, MV> operator-=(ModNum<T, MV> r) {
+ setValue(value - r.value);
+ return *this;
+ }
+
+ const ModNum<T, MV> operator-=(T r) {
+ setValue(value - r);
+ return *this;
+ }
+
+ //
+ // Operator "++"
+ //
+ // PREFIX (like ++a)
+ const ModNum<T, MV> operator++() {
+ *this += 1;
+ return *this;
+ }
+
+ // POSTFIX (like a++)
+ const ModNum<T, MV> operator++(int) {
+ ModNum<T, MV> rv = *this;
+
+ *this += 1;
+
+ return rv;
+ }
+
+ //
+ // Operator "--"
+ //
+ // PREFIX (like --a)
+ const ModNum<T, MV> operator--() {
+ *this -= 1;
+ return *this;
+ }
+
+ // POSTFIX (like a--)
+ const ModNum<T, MV> operator--(int) {
+ ModNum<T, MV> rv = *this;
+ *this -= 1;
+ return rv;
+ }
+};
+
+
+//
+// Define operator "+" like this to avoid creating a temporary
+//
+template<class T, T MV>
+inline ModNum<T, MV>
+operator+(ModNum<T, MV> l, ModNum<T, MV> r) {
+ l += r;
+ return l;
+}
+
+template<class T, T MV>
+inline ModNum<T, MV>
+operator+(ModNum<T, MV> l, T r) {
+ l += r;
+ return l;
+}
+
+template<class T, T MV>
+inline ModNum<T, MV>
+operator+(T l, ModNum<T, MV> r) {
+ r += l;
+ return r;
+}
+
+
+//
+// Define operator "-" like this to avoid creating a temporary
+//
+template<class T, T MV>
+inline ModNum<T, MV>
+operator-(ModNum<T, MV> l, ModNum<T, MV> r) {
+ l -= r;
+ return l;
+}
+
+template<class T, T MV>
+inline ModNum<T, MV>
+operator-(ModNum<T, MV> l, T r) {
+ l -= r;
+ return l;
+}
+
+template<class T, T MV>
+inline ModNum<T, MV>
+operator-(T l, ModNum<T, MV> r) {
+ r -= l;
+ return r;
+}
+
+
+//
+// Comparison operators
+// (all other cases are handled with conversons)
+//
+template<class T, T MV>
+inline bool
+operator<(ModNum<T, MV> l, ModNum<T, MV> r) {
+ return l.value < r.value;
+}
+
+template<class T, T MV>
+inline bool
+operator>(ModNum<T, MV> l, ModNum<T, MV> r) {
+ return l.value > r.value;
+}
+
+template<class T, T MV>
+inline bool
+operator==(ModNum<T, MV> l, ModNum<T, MV> r) {
+ return l.value == r.value;
+}
+
+template<class T, T MV>
+inline bool
+operator<=(ModNum<T, MV> l, ModNum<T, MV> r) {
+ return l.value <= r.value;
+}
+
+template<class T, T MV>
+inline bool
+operator>=(ModNum<T, MV> l, ModNum<T, MV> r) {
+ return l.value >= r.value;
+}
+
+
diff --git a/src/base/mysql.cc b/src/base/mysql.cc
new file mode 100644
index 000000000..c8d6e933a
--- /dev/null
+++ b/src/base/mysql.cc
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <iostream>
+
+#include "base/mysql.hh"
+#include "base/trace.hh"
+
+using namespace std;
+
+namespace MySQL {
+
+inline const char *
+charstar(const string &string)
+{
+ return string.empty() ? NULL : string.c_str();
+}
+
+ostream &
+operator<<(ostream &stream, const Error &error)
+{
+ stream << error.string();
+ return stream;
+}
+
+/*
+ * The connection class
+ */
+Connection::Connection()
+ : valid(false)
+{
+}
+
+Connection::~Connection()
+{
+ if (valid)
+ close();
+}
+
+
+bool
+Connection::connect(const string &xhost, const string &xuser,
+ const string &xpasswd, const string &xdatabase)
+{
+ if (connected())
+ return error.set("Already Connected");
+
+ _host = xhost;
+ _user = xuser;
+ _passwd = xpasswd;
+ _database = xdatabase;
+
+ error.clear();
+
+ mysql_init(&mysql);
+ mysql_options(&mysql, MYSQL_OPT_COMPRESS, 0); // might want to be 1
+ mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, "odbc");
+ if (!mysql_real_connect(&mysql, charstar(_host), charstar(_user),
+ charstar(_passwd), charstar(_database),
+ 0, NULL, 0))
+ return error.set(mysql_error(&mysql));
+
+ valid = true;
+ return false;
+}
+
+void
+Connection::close()
+{
+ mysql_close(&mysql);
+}
+
+bool
+Connection::query(const string &sql)
+{
+ DPRINTF(SQL, "Sending SQL query to server:\n%s", sql);
+ error.clear();
+ if (mysql_real_query(&mysql, sql.c_str(), sql.size()))
+ error.set(mysql_error(&mysql));
+
+ return error;
+}
+
+
+/* namespace MySQL */ }
diff --git a/src/base/mysql.hh b/src/base/mysql.hh
new file mode 100644
index 000000000..ae28a9dfb
--- /dev/null
+++ b/src/base/mysql.hh
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_MYSQL_HH__
+#define __BASE_MYSQL_HH__
+
+#define TO_BE_INCLUDED_LATER 0
+
+#include <cassert>
+#include <iosfwd>
+#include <mysql_version.h>
+#include <mysql.h>
+#include <string>
+#include <sstream>
+
+namespace MySQL {
+
+class Error
+{
+ protected:
+ const char *error;
+
+ public:
+ Error() : error(NULL) {}
+
+ Error &clear() { error = NULL; return *this; }
+ Error &set(const char *err) { error = err; return *this; }
+
+ const char *string() const { return error; }
+
+ operator bool() const { return error != NULL; }
+ bool operator!() const { return error == NULL; }
+};
+
+std::ostream &operator<<(std::ostream &stream, const Error &error);
+
+class Result
+{
+ private:
+ MYSQL_RES *result;
+ int *refcount;
+
+ void
+ decref()
+ {
+ if (!refcount)
+ return;
+
+ *refcount -= 1;
+ if (*refcount == 0) {
+ mysql_free_result(result);
+ delete refcount;
+ }
+
+ refcount = NULL;
+ }
+
+ public:
+ Result()
+ : result(0), refcount(NULL)
+ { }
+
+ Result(MYSQL_RES *res)
+ : result(res)
+ {
+ if (result)
+ refcount = new int(1);
+ else
+ refcount = NULL;
+ }
+
+ Result(const Result &result)
+ : result(result.result), refcount(result.refcount)
+ {
+ if (result)
+ *refcount += 1;
+ }
+
+ ~Result()
+ {
+ decref();
+ }
+
+ const Result &
+ operator=(MYSQL_RES *res)
+ {
+ decref();
+ result = res;
+ if (result)
+ refcount = new int(1);
+
+ return *this;
+ }
+
+ const Result &
+ operator=(const Result &res)
+ {
+ decref();
+ result = res.result;
+ refcount = res.refcount;
+ if (result)
+ *refcount += 1;
+
+ return *this;
+ }
+
+ operator bool() const { return result != NULL; }
+ bool operator!() const { return result == NULL; }
+
+ unsigned
+ num_fields()
+ {
+ assert(result);
+ return mysql_num_fields(result);
+ }
+
+ MYSQL_ROW
+ fetch_row()
+ {
+ return mysql_fetch_row(result);
+ }
+
+ unsigned long *
+ fetch_lengths()
+ {
+ return mysql_fetch_lengths(result);
+ }
+};
+
+typedef MYSQL_ROW Row;
+
+class Connection
+{
+ protected:
+ MYSQL mysql;
+ bool valid;
+
+ protected:
+ std::string _host;
+ std::string _user;
+ std::string _passwd;
+ std::string _database;
+
+ public:
+ Connection();
+ virtual ~Connection();
+
+ bool connected() const { return valid; }
+ bool connect(const std::string &host, const std::string &user,
+ const std::string &passwd, const std::string &database);
+ void close();
+
+ public:
+ Error error;
+ operator MYSQL *() { return &mysql; }
+
+ public:
+ bool query(const std::string &sql);
+
+ bool
+ query(const std::stringstream &sql)
+ {
+ return query(sql.str());
+ }
+
+ bool
+ autocommit(bool mode)
+ {
+ return mysql_autocommit(&mysql, mode);
+ }
+
+ bool
+ commit()
+ {
+ return mysql_commit(&mysql);
+ }
+
+ bool
+ rollback()
+ {
+ return mysql_rollback(&mysql);
+ }
+
+ unsigned
+ field_count()
+ {
+ return mysql_field_count(&mysql);
+ }
+
+ unsigned
+ affected_rows()
+ {
+ return mysql_affected_rows(&mysql);
+ }
+
+ unsigned
+ insert_id()
+ {
+ return mysql_insert_id(&mysql);
+ }
+
+
+ Result
+ store_result()
+ {
+ error.clear();
+ Result result = mysql_store_result(&mysql);
+ if (!result)
+ error.set(mysql_error(&mysql));
+
+ return result;
+ }
+};
+
+#if 0
+class BindProxy
+{
+ MYSQL_BIND *bind;
+ BindProxy(MYSQL_BIND *b) : bind(b) {}
+
+ void operator=(bool &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_TINY;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(int8_t &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_TINY;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(int16_t &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_SHORT;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(int32_t &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_LONG;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(int64_t &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_LONGLONG;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(uint8_t &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_TINY;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(uint16_t &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_SHORT;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(uint32_t &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_LONG;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(uint64_t &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_LONGLONG;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(float &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_FLOAT;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(double &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_DOUBLE;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(Time &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_DATE;
+ bind->buffer = (char *)&buffer;
+ }
+
+ void operator=(const char *buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_VAR_STRING;
+ bind->buffer = buffer;
+ }
+
+ void operator=(const std::string &buffer)
+ {
+ bind->buffer_type = MYSQL_TYPE_VAR_STRING;
+ bind->buffer = (char *)&buffer;
+ bind->length = buffer.length;
+ }
+
+ bool
+ set_null(bool null)
+ {
+ bind->is_null = null;
+ }
+};
+
+class Statement
+{
+ protected:
+ Error &error;
+ MYSQL_STMT *stmt;
+ MYSQL_BIND *bind;
+ int size;
+
+ public:
+ Statement(Connection &mysql)
+ : error(mysql.error), bind(NULL), size(0)
+ {
+ stmt = mysql_stmt_init(mysql);
+ assert(valid() && "mysql_stmt_init(), out of memory\n");
+ }
+
+ ~Statement()
+ {
+ assert(valid());
+ error.clear();
+ if (mysql_stmt_close(stmt))
+ error.set(mysql_stmt_error(stmt));
+
+ if (bind)
+ delete [] bind;
+ }
+
+ bool valid()
+ {
+ return stmt != NULL;
+ }
+
+ void prepare(const std::string &query)
+ {
+ assert(valid());
+ mysql.error.clear();
+ if (mysql_stmt_prepare(mysql, query, strlen(query)))
+ mysql.error.set(mysql_stmt_error(stmt));
+
+ int size = count();
+ bind = new MYSQL_BIND[size];
+ }
+
+ unsigned count()
+ {
+ assert(valid());
+ return mysql_stmt_param_count(stmt);
+ }
+
+ unsigned affected()
+ {
+ assert(valid());
+ return mysql_stmt_affected_rows(stmt);
+ }
+
+ void bind(MYSQL_BIND *bind)
+ {
+ mysql.error.clear();
+ if (mysql_stmt_bind_param(stmt, bind))
+ mysql.error.set(mysql_stmt_error(stmt));
+ }
+
+ BindProxy operator[](int index)
+ {
+ assert(index > 0 && index < N);
+ return &bind[N];
+ }
+
+ operator MYSQL_BIND *()
+ {
+ return bind;
+ }
+
+ void operator()()
+ {
+ assert(valid());
+ error.clear();
+ if (mysql_stmt_execute(stmt))
+ error.set(mysql_stmt_error(stmt));
+ }
+}
+#endif
+
+/* namespace MySQL */ }
+
+#endif // __BASE_MYSQL_HH__
diff --git a/src/base/output.cc b/src/base/output.cc
new file mode 100644
index 000000000..2b1733f21
--- /dev/null
+++ b/src/base/output.cc
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <fstream>
+
+#include "base/misc.hh"
+#include "base/output.hh"
+
+using namespace std;
+
+OutputDirectory simout;
+
+/**
+ *
+ */
+OutputDirectory::OutputDirectory()
+{}
+
+OutputDirectory::~OutputDirectory()
+{}
+
+void
+OutputDirectory::setDirectory(const string &d)
+{
+ if (!dir.empty())
+ panic("Output directory already set!\n");
+
+ dir = d;
+
+ if (dir != ".") {
+ if (mkdir(dir.c_str(), 0777) < 0 && errno != EEXIST)
+ panic("couldn't make output dir %s: %s\n",
+ dir, strerror(errno));
+ }
+
+ // guarantee that directory ends with a '/'
+ if (dir[dir.size() - 1] != '/')
+ dir += "/";
+}
+
+const string &
+OutputDirectory::directory()
+{
+ if (dir.empty())
+ panic("Output directory not set!");
+
+ return dir;
+}
+
+string
+OutputDirectory::resolve(const string &name)
+{
+ return (name[0] != '/') ? dir + name : name;
+}
+
+ostream *
+OutputDirectory::create(const string &name)
+{
+ if (name == "cerr" || name == "stderr")
+ return &cerr;
+
+ if (name == "cout" || name == "stdout")
+ return &cout;
+
+ ofstream *file = new ofstream(resolve(name).c_str(), ios::trunc);
+ if (!file->is_open())
+ panic("Cannot open file %s", name);
+
+ return file;
+}
+
+ostream *
+OutputDirectory::find(const string &name)
+{
+ if (name == "cerr" || name == "stderr")
+ return &cerr;
+
+ if (name == "cout" || name == "stdout")
+ return &cout;
+
+ string filename = resolve(name);
+ map_t::iterator i = files.find(filename);
+ if (i != files.end())
+ return (*i).second;
+
+ ofstream *file = new ofstream(filename.c_str(), ios::trunc);
+ if (!file->is_open())
+ panic("Cannot open file %s", filename);
+
+ files[filename] = file;
+ return file;
+}
+
+bool
+OutputDirectory::isFile(const std::ostream *os)
+{
+ return os && os != &cerr && os != &cout;
+}
diff --git a/src/base/output.hh b/src/base/output.hh
new file mode 100644
index 000000000..3bbe73e3b
--- /dev/null
+++ b/src/base/output.hh
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_OUTPUT_HH__
+#define __BASE_OUTPUT_HH__
+
+#include <iosfwd>
+#include <map>
+#include <string>
+
+class OutputDirectory
+{
+ private:
+ typedef std::map<std::string, std::ostream *> map_t;
+
+ map_t files;
+ std::string dir;
+
+ public:
+ OutputDirectory();
+ ~OutputDirectory();
+
+ void setDirectory(const std::string &dir);
+ const std::string &directory();
+
+ std::string resolve(const std::string &name);
+ std::ostream *create(const std::string &name);
+ std::ostream *find(const std::string &name);
+
+ static bool isFile(const std::ostream *os);
+ static inline bool isFile(const std::ostream &os) { return isFile(&os); }
+};
+
+extern OutputDirectory simout;
+
+#endif // __BASE_OUTPUT_HH__
diff --git a/src/base/pollevent.cc b/src/base/pollevent.cc
new file mode 100644
index 000000000..99044fc09
--- /dev/null
+++ b/src/base/pollevent.cc
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include "sim/async.hh"
+#include "sim/host.hh"
+#include "base/misc.hh"
+#include "base/pollevent.hh"
+#include "sim/root.hh"
+#include "sim/serialize.hh"
+
+using namespace std;
+
+PollQueue pollQueue;
+
+/////////////////////////////////////////////////////
+//
+PollEvent::PollEvent(int _fd, int _events)
+ : queue(NULL), enabled(true)
+{
+ pfd.fd = _fd;
+ pfd.events = _events;
+}
+
+PollEvent::~PollEvent()
+{
+ if (queue)
+ queue->remove(this);
+}
+
+void
+PollEvent::disable()
+{
+ if (!enabled) return;
+ enabled = false;
+
+ if (queue)
+ queue->copy();
+}
+
+void
+PollEvent::enable()
+{
+ if (enabled) return;
+ enabled = true;
+
+ if (queue)
+ queue->copy();
+}
+
+void
+PollEvent::serialize(ostream &os)
+{
+ SERIALIZE_SCALAR(pfd.fd);
+ SERIALIZE_SCALAR(pfd.events);
+ SERIALIZE_SCALAR(enabled);
+}
+
+void
+PollEvent::unserialize(Checkpoint *cp, const std::string &section)
+{
+ UNSERIALIZE_SCALAR(pfd.fd);
+ UNSERIALIZE_SCALAR(pfd.events);
+ UNSERIALIZE_SCALAR(enabled);
+}
+
+/////////////////////////////////////////////////////
+//
+PollQueue::PollQueue()
+ : poll_fds(NULL), max_size(0), num_fds(0)
+{ }
+
+PollQueue::~PollQueue()
+{
+ removeHandler();
+ for (int i = 0; i < num_fds; i++)
+ setupAsyncIO(poll_fds[0].fd, false);
+
+ delete [] poll_fds;
+}
+
+void
+PollQueue::copy()
+{
+ eventvec_t::iterator i = events.begin();
+ eventvec_t::iterator end = events.end();
+
+ num_fds = 0;
+
+ while (i < end) {
+ if ((*i)->enabled)
+ poll_fds[num_fds++] = (*i)->pfd;
+ ++i;
+ }
+}
+
+void
+PollQueue::remove(PollEvent *event)
+{
+ eventvec_t::iterator i = events.begin();
+ eventvec_t::iterator end = events.end();
+
+ while (i < end) {
+ if (*i == event) {
+ events.erase(i);
+ copy();
+ event->queue = NULL;
+ return;
+ }
+
+ ++i;
+ }
+
+ panic("Event does not exist. Cannot remove.");
+}
+
+void
+PollQueue::schedule(PollEvent *event)
+{
+ if (event->queue)
+ panic("Event already scheduled!");
+
+ event->queue = this;
+ events.push_back(event);
+ setupAsyncIO(event->pfd.fd, true);
+
+ // if we ran out of space in the fd array, double the capacity
+ // if this is the first time that we've scheduled an event, create
+ // the array with an initial size of 16
+ if (++num_fds > max_size) {
+ if (max_size > 0) {
+ delete [] poll_fds;
+ max_size *= 2;
+ } else {
+ max_size = 16;
+ setupHandler();
+ }
+
+ poll_fds = new pollfd[max_size];
+ }
+
+ copy();
+}
+
+void
+PollQueue::service()
+{
+ int ret = poll(poll_fds, num_fds, 0);
+
+ if (ret <= 0)
+ return;
+
+ for (int i = 0; i < num_fds; i++) {
+ int revents = poll_fds[i].revents;
+ if (revents) {
+ events[i]->process(revents);
+ if (--ret <= 0)
+ break;
+ }
+ }
+}
+
+struct sigaction PollQueue::oldio;
+struct sigaction PollQueue::oldalrm;
+bool PollQueue::handler = false;
+
+void
+PollQueue::setupAsyncIO(int fd, bool set)
+{
+ int flags = fcntl(fd, F_GETFL);
+ if (flags == -1)
+ panic("Could not set up async IO");
+
+ if (set)
+ flags |= FASYNC;
+ else
+ flags &= ~(FASYNC);
+
+ if (fcntl(fd, F_SETFL, flags) == -1)
+ panic("Could not set up async IO");
+
+ if (set) {
+ if (fcntl(fd, F_SETOWN, getpid()) == -1)
+ panic("Could not set up async IO");
+ }
+}
+
+void
+PollQueue::setupHandler()
+{
+ struct sigaction act;
+
+ act.sa_handler = handleIO;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_RESTART;
+
+ if (sigaction(SIGIO, &act, &oldio) == -1)
+ panic("could not do sigaction");
+
+ act.sa_handler = handleALRM;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_RESTART;
+
+ if (sigaction(SIGALRM, &act, &oldalrm) == -1)
+ panic("could not do sigaction");
+
+ alarm(1);
+
+ handler = true;
+}
+
+void
+PollQueue::removeHandler()
+{
+ if (sigaction(SIGIO, &oldio, NULL) == -1)
+ panic("could not remove handler");
+
+ if (sigaction(SIGIO, &oldalrm, NULL) == -1)
+ panic("could not remove handler");
+}
+
+void
+PollQueue::handleIO(int sig)
+{
+ if (sig != SIGIO)
+ panic("Wrong Handler");
+
+ async_event = true;
+ async_io = true;
+}
+
+void
+PollQueue::handleALRM(int sig)
+{
+ if (sig != SIGALRM)
+ panic("Wrong Handler");
+
+ async_event = true;
+ async_alarm = true;
+ alarm(1);
+}
+
diff --git a/src/base/pollevent.hh b/src/base/pollevent.hh
new file mode 100644
index 000000000..d39931797
--- /dev/null
+++ b/src/base/pollevent.hh
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __POLLEVENT_H__
+#define __POLLEVENT_H__
+
+#include <vector>
+#include <poll.h>
+#include "sim/root.hh"
+
+class Checkpoint;
+class PollQueue;
+
+class PollEvent
+{
+ private:
+ friend class PollQueue;
+
+ protected:
+ pollfd pfd;
+ PollQueue *queue;
+ bool enabled;
+
+ public:
+ PollEvent(int fd, int event);
+ virtual ~PollEvent();
+
+ void disable();
+ void enable();
+ virtual void process(int revent) = 0;
+
+ bool queued() { return queue != 0; }
+
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+};
+
+class PollQueue
+{
+ private:
+ typedef std::vector<PollEvent *> eventvec_t;
+ eventvec_t events;
+
+ pollfd *poll_fds;
+ int max_size;
+ int num_fds;
+
+ public:
+ PollQueue();
+ ~PollQueue();
+
+ void copy();
+ void remove(PollEvent *event);
+ void schedule(PollEvent *event);
+ void service();
+
+ protected:
+ static bool handler;
+ static struct sigaction oldio;
+ static struct sigaction oldalrm;
+
+ public:
+ static void setupAsyncIO(int fd, bool set);
+ static void handleIO(int);
+ static void handleALRM(int);
+ static void removeHandler();
+ static void setupHandler();
+};
+
+extern PollQueue pollQueue;
+
+#endif // __POLLEVENT_H__
diff --git a/src/base/predictor.hh b/src/base/predictor.hh
new file mode 100644
index 000000000..37aa29989
--- /dev/null
+++ b/src/base/predictor.hh
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//
+// Abstract base class for a generic predictor
+//
+//
+
+#ifndef __PREDICTOR_HH__
+#define __PREDICTOR_HH__
+
+class GenericPredictor {
+
+ public:
+ virtual void clear() = 0;
+
+ virtual unsigned predict(unsigned long _index) = 0;
+ virtual unsigned predict(unsigned long _index, unsigned &pdata) = 0;
+
+ virtual unsigned peek(unsigned long _index) = 0;
+
+ virtual void record(unsigned long _index, unsigned _actual_value,
+ unsigned _pred_value) = 0;
+ virtual void record(unsigned long _index, unsigned _actual_value,
+ unsigned _pred_value, unsigned _pdata) = 0;
+
+ virtual unsigned value(unsigned long _index) = 0;
+
+ virtual void regStats() = 0;
+ virtual void regFormulas() = 0;
+
+ virtual ~GenericPredictor() {};
+};
+
+#endif // __PREDICTOR_HH__
diff --git a/src/base/random.cc b/src/base/random.cc
new file mode 100644
index 000000000..4aac14101
--- /dev/null
+++ b/src/base/random.cc
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <cstdlib>
+#include <cmath>
+
+#include "sim/param.hh"
+#include "base/random.hh"
+#include "base/trace.hh"
+
+using namespace std;
+
+class RandomContext : public ParamContext
+{
+ public:
+ RandomContext(const string &_iniSection)
+ : ::ParamContext(_iniSection) {}
+ ~RandomContext() {}
+
+ void checkParams();
+};
+
+RandomContext paramContext("random");
+
+Param<unsigned>
+seed(&paramContext, "seed", "seed to random number generator", 1);
+
+void
+RandomContext::checkParams()
+{
+ ::srand48(seed);
+}
+
+long
+getLong()
+{
+ return mrand48();
+}
+
+int64_t
+getUniform(int64_t min, int64_t max)
+{
+ double r;
+ r = drand48() * (max-min) + min;
+ return (int64_t)round(r);
+}
+
+uint64_t
+getUniformPos(uint64_t min, uint64_t max)
+{
+ double r;
+ r = drand48() * (max-min) + min;
+ return (uint64_t)round(r);
+}
+
+
+// idea for generating a double from erand48
+double
+getDouble()
+{
+ union {
+ uint32_t _long[2];
+ uint16_t _short[4];
+ };
+
+ _long[0] = mrand48();
+ _long[1] = mrand48();
+
+ return ldexp((double) _short[0], -48) +
+ ldexp((double) _short[1], -32) +
+ ldexp((double) _short[2], -16);
+}
diff --git a/src/base/random.hh b/src/base/random.hh
new file mode 100644
index 000000000..def7a4bce
--- /dev/null
+++ b/src/base/random.hh
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_RANDOM_HH__
+#define __BASE_RANDOM_HH__
+
+#include "sim/host.hh"
+
+long getLong();
+double getDouble();
+uint64_t getUniformPos(uint64_t min, uint64_t max);
+int64_t getUniform(int64_t min, int64_t max);
+
+template <typename T>
+struct Random;
+
+template<> struct Random<int8_t>
+{
+ static int8_t get()
+ { return getLong() & (int8_t)-1; }
+
+ static int8_t uniform(int8_t min, int8_t max)
+ { return getUniform(min, max); }
+};
+
+template<> struct Random<uint8_t>
+{
+ static uint8_t get()
+ { return getLong() & (uint8_t)-1; }
+
+ static uint8_t uniform(uint8_t min, uint8_t max)
+ { return getUniformPos(min, max); }
+};
+
+template<> struct Random<int16_t>
+{
+ static int16_t get()
+ { return getLong() & (int16_t)-1; }
+
+ static int16_t uniform(int16_t min, int16_t max)
+ { return getUniform(min, max); }
+};
+
+template<> struct Random<uint16_t>
+{
+ static uint16_t get()
+ { return getLong() & (uint16_t)-1; }
+
+ static uint16_t uniform(uint16_t min, uint16_t max)
+ { return getUniformPos(min, max); }
+};
+
+template<> struct Random<int32_t>
+{
+ static int32_t get()
+ { return (int32_t)getLong(); }
+
+ static int32_t uniform(int32_t min, int32_t max)
+ { return getUniform(min, max); }
+};
+
+template<> struct Random<uint32_t>
+{
+ static uint32_t get()
+ { return (uint32_t)getLong(); }
+
+ static uint32_t uniform(uint32_t min, uint32_t max)
+ { return getUniformPos(min, max); }
+};
+
+template<> struct Random<int64_t>
+{
+ static int64_t get()
+ { return (int64_t)getLong() << 32 || (uint64_t)getLong(); }
+
+ static int64_t uniform(int64_t min, int64_t max)
+ { return getUniform(min, max); }
+};
+
+template<> struct Random<uint64_t>
+{
+ static uint64_t get()
+ { return (uint64_t)getLong() << 32 || (uint64_t)getLong(); }
+
+ static uint64_t uniform(uint64_t min, uint64_t max)
+ { return getUniformPos(min, max); }
+};
+
+template<> struct Random<float>
+{
+ static float get()
+ { return getDouble(); }
+};
+
+template<> struct Random<double>
+{
+ static double get()
+ { return getDouble(); }
+};
+
+#endif // __BASE_RANDOM_HH__
diff --git a/src/base/range.cc b/src/base/range.cc
new file mode 100644
index 000000000..a4e50fc4f
--- /dev/null
+++ b/src/base/range.cc
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "base/intmath.hh"
+#include "base/range.hh"
+#include "base/str.hh"
+
+using namespace std;
+
+template <class T>
+bool
+__x_parse_range(const std::string &str, T &first, T &last)
+{
+ std::vector<std::string> values;
+ tokenize(values, str, ':');
+
+ T thefirst, thelast;
+
+ if (values.size() != 2)
+ return false;
+
+ std::string s = values[0];
+ std::string e = values[1];
+
+ if (!to_number(s, thefirst))
+ return false;
+
+ bool increment = (e[0] == '+');
+ if (increment)
+ e = e.substr(1);
+
+ if (!to_number(e, thelast))
+ return false;
+
+ if (increment)
+ thelast += thefirst - 1;
+
+ first = thefirst;
+ last = thelast;
+
+ return true;
+}
+
+#define RANGE_PARSE(type) \
+template<> bool \
+__parse_range(const std::string &s, type &first, type &last) \
+{ return __x_parse_range(s, first, last); }
+
+RANGE_PARSE(unsigned long long);
+RANGE_PARSE(signed long long);
+RANGE_PARSE(unsigned long);
+RANGE_PARSE(signed long);
+RANGE_PARSE(unsigned int);
+RANGE_PARSE(signed int);
+RANGE_PARSE(unsigned short);
+RANGE_PARSE(signed short);
+RANGE_PARSE(unsigned char);
+RANGE_PARSE(signed char);
diff --git a/src/base/range.hh b/src/base/range.hh
new file mode 100644
index 000000000..4e3e0fd6e
--- /dev/null
+++ b/src/base/range.hh
@@ -0,0 +1,355 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_RANGE_HH__
+#define __BASE_RANGE_HH__
+
+#include <cassert>
+#include <iostream>
+#include <string>
+
+/**
+ * @param s range string
+ * EndExclusive Ranges are in the following format:
+ * @verbatim
+ * <range> := {<start_val>}:{<end>}
+ * <start> := <end_val> | +<delta>
+ * @endverbatim
+ */
+template <class T>
+bool __parse_range(const std::string &s, T &start, T &end);
+
+template <class T>
+struct Range
+{
+ T start;
+ T end;
+
+ Range() { invalidate(); }
+
+ template <class U>
+ Range(const std::pair<U, U> &r)
+ : start(r.first), end(r.second)
+ {}
+
+ template <class U>
+ Range(const Range<U> &r)
+ : start(r.start), end(r.end)
+ {}
+
+ Range(const std::string &s)
+ {
+ if (!__parse_range(s, start, end))
+ invalidate();
+ }
+
+ template <class U>
+ const Range<T> &operator=(const Range<U> &r)
+ {
+ start = r.start;
+ end = r.end;
+ return *this;
+ }
+
+ template <class U>
+ const Range<T> &operator=(const std::pair<U, U> &r)
+ {
+ start = r.first;
+ end = r.second;
+ return *this;
+ }
+
+ const Range &operator=(const std::string &s)
+ {
+ if (!__parse_range(s, start, end))
+ invalidate();
+ return *this;
+ }
+
+ void invalidate() { start = 1; end = 0; }
+ T size() const { return end - start + 1; }
+ bool valid() const { return start < end; }
+};
+
+template <class T>
+inline std::ostream &
+operator<<(std::ostream &o, const Range<T> &r)
+{
+ o << '[' << r.start << "," << r.end << ']';
+ return o;
+}
+
+template <class T>
+inline Range<T>
+RangeEx(T start, T end)
+{ return std::make_pair(start, end - 1); }
+
+template <class T>
+inline Range<T>
+RangeIn(T start, T end)
+{ return std::make_pair(start, end); }
+
+template <class T, class U>
+inline Range<T>
+RangeSize(T start, U size)
+{ return std::make_pair(start, start + size - 1); }
+
+////////////////////////////////////////////////////////////////////////
+//
+// Range to Range Comparisons
+//
+
+/**
+ * @param range1 is a range.
+ * @param range2 is a range.
+ * @return if range1 and range2 are identical.
+ */
+template <class T, class U>
+inline bool
+operator==(const Range<T> &range1, const Range<U> &range2)
+{
+ return range1.start == range2.start && range1.end == range2.end;
+}
+
+/**
+ * @param range1 is a range.
+ * @param range2 is a range.
+ * @return if range1 and range2 are not identical.
+ */
+template <class T, class U>
+inline bool
+operator!=(const Range<T> &range1, const Range<U> &range2)
+{
+ return range1.start != range2.start || range1.end != range2.end;
+}
+
+/**
+ * @param range1 is a range.
+ * @param range2 is a range.
+ * @return if range1 is less than range2 and does not overlap range1.
+ */
+template <class T, class U>
+inline bool
+operator<(const Range<T> &range1, const Range<U> &range2)
+{
+ return range1.start < range2.start;
+}
+
+/**
+ * @param range1 is a range.
+ * @param range2 is a range.
+ * @return if range1 is less than range2. range1 may overlap range2,
+ * but not extend beyond the end of range2.
+ */
+template <class T, class U>
+inline bool
+operator<=(const Range<T> &range1, const Range<U> &range2)
+{
+ return range1.start <= range2.start;
+}
+
+/**
+ * @param range1 is a range.
+ * @param range2 is a range.
+ * @return if range1 is greater than range2 and does not overlap range2.
+ */
+template <class T, class U>
+inline bool
+operator>(const Range<T> &range1, const Range<U> &range2)
+{
+ return range1.start > range2.start;
+}
+
+/**
+ * @param range1 is a range.
+ * @param range2 is a range.
+ * @return if range1 is greater than range2. range1 may overlap range2,
+ * but not extend beyond the beginning of range2.
+ */
+template <class T, class U>
+inline bool
+operator>=(const Range<T> &range1, const Range<U> &range2)
+{
+ return range1.start >= range2.start;
+}
+
+////////////////////////////////////////////////////////////////////////
+//
+// Position to Range Comparisons
+//
+
+/**
+ * @param pos position compared to the range.
+ * @param range range compared against.
+ * @return indicates that position pos is within the range.
+ */
+template <class T, class U>
+inline bool
+operator==(const T &pos, const Range<U> &range)
+{
+ return pos >= range.start && pos <= range.end;
+}
+
+/**
+ * @param pos position compared to the range.
+ * @param range range compared against.
+ * @return indicates that position pos is not within the range.
+ */
+template <class T, class U>
+inline bool
+operator!=(const T &pos, const Range<U> &range)
+{
+ return pos < range.start || pos > range.end;
+}
+
+/**
+ * @param pos position compared to the range.
+ * @param range range compared against.
+ * @return indicates that position pos is below the range.
+ */
+template <class T, class U>
+inline bool
+operator<(const T &pos, const Range<U> &range)
+{
+ return pos < range.start;
+}
+
+/**
+ * @param pos position compared to the range.
+ * @param range range compared against.
+ * @return indicates that position pos is below or in the range.
+ */
+template <class T, class U>
+inline bool
+operator<=(const T &pos, const Range<U> &range)
+{
+ return pos <= range.end;
+}
+
+/**
+ * @param pos position compared to the range.
+ * @param range range compared against.
+ * @return indicates that position pos is above the range.
+ */
+template <class T, class U>
+inline bool
+operator>(const T &pos, const Range<U> &range)
+{
+ return pos > range.end;
+}
+
+/**
+ * @param pos position compared to the range.
+ * @param range range compared against.
+ * @return indicates that position pos is above or in the range.
+ */
+template <class T, class U>
+inline bool
+operator>=(const T &pos, const Range<U> &range)
+{
+ return pos >= range.start;
+}
+
+////////////////////////////////////////////////////////////////////////
+//
+// Range to Position Comparisons (for symmetry)
+//
+
+/**
+ * @param range range compared against.
+ * @param pos position compared to the range.
+ * @return indicates that position pos is within the range.
+ */
+template <class T, class U>
+inline bool
+operator==(const Range<T> &range, const U &pos)
+{
+ return pos >= range.start && pos <= range.end;
+}
+
+/**
+ * @param range range compared against.
+ * @param pos position compared to the range.
+ * @return indicates that position pos is not within the range.
+ */
+template <class T, class U>
+inline bool
+operator!=(const Range<T> &range, const U &pos)
+{
+ return pos < range.start || pos > range.end;
+}
+
+/**
+ * @param range range compared against.
+ * @param pos position compared to the range.
+ * @return indicates that position pos is above the range.
+ */
+template <class T, class U>
+inline bool
+operator<(const Range<T> &range, const U &pos)
+{
+ return range.end < pos;
+}
+
+/**
+ * @param range range compared against.
+ * @param pos position compared to the range.
+ * @return indicates that position pos is above or in the range.
+ */
+template <class T, class U>
+inline bool
+operator<=(const Range<T> &range, const U &pos)
+{
+ return range.start <= pos;
+}
+
+/**
+ * @param range range compared against.
+ * @param pos position compared to the range.
+ * 'range > pos' indicates that position pos is below the range.
+ */
+template <class T, class U>
+inline bool
+operator>(const Range<T> &range, const U &pos)
+{
+ return range.start > pos;
+}
+
+/**
+ * @param range range compared against.
+ * @param pos position compared to the range.
+ * 'range >= pos' indicates that position pos is below or in the range.
+ */
+template <class T, class U>
+inline bool
+operator>=(const Range<T> &range, const U &pos)
+{
+ return range.end >= pos;
+}
+
+#endif // __BASE_RANGE_HH__
diff --git a/src/base/refcnt.hh b/src/base/refcnt.hh
new file mode 100644
index 000000000..de589f7c5
--- /dev/null
+++ b/src/base/refcnt.hh
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __REFCNT_HH__
+#define __REFCNT_HH__
+
+#include <stddef.h> //For the NULL macro definition
+
+class RefCounted
+{
+ private:
+ int count;
+
+ private:
+ RefCounted(const RefCounted &);
+
+ public:
+ RefCounted() : count(0) {}
+ virtual ~RefCounted() {}
+
+ void incref() { ++count; }
+ void decref() { if (--count <= 0) delete this; }
+};
+
+template <class T>
+class RefCountingPtr
+{
+ protected:
+ T *data;
+
+ void copy(T *d)
+ {
+ data = d;
+ if (data)
+ data->incref();
+ }
+ void del()
+ {
+ if (data)
+ data->decref();
+ }
+ void set(T *d)
+ {
+ if (data == d)
+ return;
+
+ del();
+ copy(d);
+ }
+
+
+ public:
+ RefCountingPtr() : data(NULL) {}
+ RefCountingPtr(T *data) { copy(data); }
+ RefCountingPtr(const RefCountingPtr &r) { copy(r.data); }
+ ~RefCountingPtr() { del(); }
+
+ T *operator->() { return data; }
+ T &operator*() { return *data; }
+ T *get() { return data; }
+
+ const T *operator->() const { return data; }
+ const T &operator*() const { return *data; }
+ const T *get() const { return data; }
+
+ RefCountingPtr &operator=(T *p) { set(p); return *this; }
+ RefCountingPtr &operator=(const RefCountingPtr &r)
+ { return operator=(r.data); }
+
+ bool operator!() const { return data == 0; }
+ operator bool() const { return data != 0; }
+};
+
+template<class T>
+bool operator==(const RefCountingPtr<T> &l, const RefCountingPtr<T> &r)
+{ return l.get() == r.get(); }
+
+template<class T>
+bool operator==(const RefCountingPtr<T> &l, const T *r)
+{ return l.get() == r; }
+
+template<class T>
+bool operator==(const T &l, const RefCountingPtr<T> &r)
+{ return l == r.get(); }
+
+template<class T>
+bool operator!=(const RefCountingPtr<T> &l, const RefCountingPtr<T> &r)
+{ return l.get() != r.get(); }
+
+template<class T>
+bool operator!=(const RefCountingPtr<T> &l, const T *r)
+{ return l.get() != r; }
+
+template<class T>
+bool operator!=(const T &l, const RefCountingPtr<T> &r)
+{ return l != r.get(); }
+
+#endif // __REFCNT_HH__
diff --git a/src/base/remote_gdb.cc b/src/base/remote_gdb.cc
new file mode 100644
index 000000000..41d0c1471
--- /dev/null
+++ b/src/base/remote_gdb.cc
@@ -0,0 +1,1175 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratories.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94
+ */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * $NetBSD: kgdb_stub.c,v 1.8 2001/07/07 22:58:00 wdk Exp $
+ *
+ * Taken from NetBSD
+ *
+ * "Stub" to allow remote cpu to debug over a serial line using gdb.
+ */
+
+#include <sys/signal.h>
+
+#include <string>
+#include <unistd.h>
+
+#include "arch/vtophys.hh"
+#include "base/intmath.hh"
+#include "base/kgdb.h"
+#include "base/remote_gdb.hh"
+#include "base/socket.hh"
+#include "base/trace.hh"
+#include "config/full_system.hh"
+#include "cpu/exec_context.hh"
+#include "cpu/static_inst.hh"
+#include "mem/physical.hh"
+#include "mem/port.hh"
+#include "sim/system.hh"
+
+using namespace std;
+using namespace TheISA;
+
+#ifndef NDEBUG
+vector<RemoteGDB *> debuggers;
+int current_debugger = -1;
+
+void
+debugger()
+{
+ if (current_debugger >= 0 && current_debugger < debuggers.size()) {
+ RemoteGDB *gdb = debuggers[current_debugger];
+ if (!gdb->isattached())
+ gdb->listener->accept();
+ if (gdb->isattached())
+ gdb->trap(ALPHA_KENTRY_IF);
+ }
+}
+#endif
+
+///////////////////////////////////////////////////////////
+//
+//
+//
+
+GDBListener::Event::Event(GDBListener *l, int fd, int e)
+ : PollEvent(fd, e), listener(l)
+{}
+
+void
+GDBListener::Event::process(int revent)
+{
+ listener->accept();
+}
+
+GDBListener::GDBListener(RemoteGDB *g, int p)
+ : event(NULL), gdb(g), port(p)
+{
+ assert(!gdb->listener);
+ gdb->listener = this;
+}
+
+GDBListener::~GDBListener()
+{
+ if (event)
+ delete event;
+}
+
+string
+GDBListener::name()
+{
+ return gdb->name() + ".listener";
+}
+
+void
+GDBListener::listen()
+{
+ while (!listener.listen(port, true)) {
+ DPRINTF(GDBMisc, "Can't bind port %d\n", port);
+ port++;
+ }
+
+ event = new Event(this, listener.getfd(), POLLIN);
+ pollQueue.schedule(event);
+
+#ifndef NDEBUG
+ gdb->number = debuggers.size();
+ debuggers.push_back(gdb);
+#endif
+
+#ifndef NDEBUG
+ ccprintf(cerr, "%d: %s: listening for remote gdb #%d on port %d\n",
+ curTick, name(), gdb->number, port);
+#else
+ ccprintf(cerr, "%d: %s: listening for remote gdb on port %d\n",
+ curTick, name(), port);
+#endif
+}
+
+void
+GDBListener::accept()
+{
+ if (!listener.islistening())
+ panic("GDBListener::accept(): cannot accept if we're not listening!");
+
+ int sfd = listener.accept(true);
+
+ if (sfd != -1) {
+ if (gdb->isattached())
+ close(sfd);
+ else
+ gdb->attach(sfd);
+ }
+}
+
+///////////////////////////////////////////////////////////
+//
+//
+//
+int digit2i(char);
+char i2digit(int);
+void mem2hex(void *, const void *, int);
+const char *hex2mem(void *, const char *, int);
+Addr hex2i(const char **);
+
+RemoteGDB::Event::Event(RemoteGDB *g, int fd, int e)
+ : PollEvent(fd, e), gdb(g)
+{}
+
+void
+RemoteGDB::Event::process(int revent)
+{
+ if (revent & POLLIN)
+ gdb->trap(ALPHA_KENTRY_IF);
+ else if (revent & POLLNVAL)
+ gdb->detach();
+}
+
+RemoteGDB::RemoteGDB(System *_system, ExecContext *c)
+ : event(NULL), listener(NULL), number(-1), fd(-1),
+ active(false), attached(false),
+ system(_system), pmem(_system->physmem), context(c)
+{
+ memset(gdbregs, 0, sizeof(gdbregs));
+}
+
+RemoteGDB::~RemoteGDB()
+{
+ if (event)
+ delete event;
+}
+
+string
+RemoteGDB::name()
+{
+ return system->name() + ".remote_gdb";
+}
+
+bool
+RemoteGDB::isattached()
+{ return attached; }
+
+void
+RemoteGDB::attach(int f)
+{
+ fd = f;
+
+ event = new Event(this, fd, POLLIN);
+ pollQueue.schedule(event);
+
+ attached = true;
+ DPRINTFN("remote gdb attached\n");
+}
+
+void
+RemoteGDB::detach()
+{
+ attached = false;
+ close(fd);
+ fd = -1;
+
+ pollQueue.remove(event);
+ DPRINTFN("remote gdb detached\n");
+}
+
+const char *
+gdb_command(char cmd)
+{
+ switch (cmd) {
+ case KGDB_SIGNAL: return "KGDB_SIGNAL";
+ case KGDB_SET_BAUD: return "KGDB_SET_BAUD";
+ case KGDB_SET_BREAK: return "KGDB_SET_BREAK";
+ case KGDB_CONT: return "KGDB_CONT";
+ case KGDB_ASYNC_CONT: return "KGDB_ASYNC_CONT";
+ case KGDB_DEBUG: return "KGDB_DEBUG";
+ case KGDB_DETACH: return "KGDB_DETACH";
+ case KGDB_REG_R: return "KGDB_REG_R";
+ case KGDB_REG_W: return "KGDB_REG_W";
+ case KGDB_SET_THREAD: return "KGDB_SET_THREAD";
+ case KGDB_CYCLE_STEP: return "KGDB_CYCLE_STEP";
+ case KGDB_SIG_CYCLE_STEP: return "KGDB_SIG_CYCLE_STEP";
+ case KGDB_KILL: return "KGDB_KILL";
+ case KGDB_MEM_W: return "KGDB_MEM_W";
+ case KGDB_MEM_R: return "KGDB_MEM_R";
+ case KGDB_SET_REG: return "KGDB_SET_REG";
+ case KGDB_READ_REG: return "KGDB_READ_REG";
+ case KGDB_QUERY_VAR: return "KGDB_QUERY_VAR";
+ case KGDB_SET_VAR: return "KGDB_SET_VAR";
+ case KGDB_RESET: return "KGDB_RESET";
+ case KGDB_STEP: return "KGDB_STEP";
+ case KGDB_ASYNC_STEP: return "KGDB_ASYNC_STEP";
+ case KGDB_THREAD_ALIVE: return "KGDB_THREAD_ALIVE";
+ case KGDB_TARGET_EXIT: return "KGDB_TARGET_EXIT";
+ case KGDB_BINARY_DLOAD: return "KGDB_BINARY_DLOAD";
+ case KGDB_CLR_HW_BKPT: return "KGDB_CLR_HW_BKPT";
+ case KGDB_SET_HW_BKPT: return "KGDB_SET_HW_BKPT";
+ case KGDB_START: return "KGDB_START";
+ case KGDB_END: return "KGDB_END";
+ case KGDB_GOODP: return "KGDB_GOODP";
+ case KGDB_BADP: return "KGDB_BADP";
+ default: return "KGDB_UNKNOWN";
+ }
+}
+
+///////////////////////////////////////////////////////////
+// RemoteGDB::acc
+//
+// Determine if the mapping at va..(va+len) is valid.
+//
+bool
+RemoteGDB::acc(Addr va, size_t len)
+{
+ Addr last_va;
+
+ va = TheISA::TruncPage(va);
+ last_va = TheISA::RoundPage(va + len);
+
+ do {
+ if (TheISA::IsK0Seg(va)) {
+ if (va < (TheISA::K0SegBase + pmem->size())) {
+ DPRINTF(GDBAcc, "acc: Mapping is valid K0SEG <= "
+ "%#x < K0SEG + size\n", va);
+ return true;
+ } else {
+ DPRINTF(GDBAcc, "acc: Mapping invalid %#x > K0SEG + size\n",
+ va);
+ return false;
+ }
+ }
+
+ /**
+ * This code says that all accesses to palcode (instruction and data)
+ * are valid since there isn't a va->pa mapping because palcode is
+ * accessed physically. At some point this should probably be cleaned up
+ * but there is no easy way to do it.
+ */
+
+ if (AlphaISA::PcPAL(va) || va < 0x10000)
+ return true;
+
+ Addr ptbr = context->readMiscReg(AlphaISA::IPR_PALtemp20);
+ TheISA::PageTableEntry pte = TheISA::kernel_pte_lookup(context->getPhysPort(), ptbr, va);
+ if (!pte.valid()) {
+ DPRINTF(GDBAcc, "acc: %#x pte is invalid\n", va);
+ return false;
+ }
+ va += TheISA::PageBytes;
+ } while (va < last_va);
+
+ DPRINTF(GDBAcc, "acc: %#x mapping is valid\n", va);
+ return true;
+}
+
+///////////////////////////////////////////////////////////
+// RemoteGDB::signal
+//
+// Translate a trap number into a Unix-compatible signal number.
+// (GDB only understands Unix signal numbers.)
+//
+int
+RemoteGDB::signal(int type)
+{
+ switch (type) {
+ case ALPHA_KENTRY_INT:
+ return (SIGTRAP);
+
+ case ALPHA_KENTRY_UNA:
+ return (SIGBUS);
+
+ case ALPHA_KENTRY_ARITH:
+ return (SIGFPE);
+
+ case ALPHA_KENTRY_IF:
+ return (SIGILL);
+
+ case ALPHA_KENTRY_MM:
+ return (SIGSEGV);
+
+ default:
+ panic("unknown signal type");
+ return 0;
+ }
+}
+
+///////////////////////////////////////////////////////////
+// RemoteGDB::getregs
+//
+// Translate the kernel debugger register format into
+// the GDB register format.
+void
+RemoteGDB::getregs()
+{
+ memset(gdbregs, 0, sizeof(gdbregs));
+
+ gdbregs[KGDB_REG_PC] = context->readPC();
+
+ // @todo: Currently this is very Alpha specific.
+ if (AlphaISA::PcPAL(gdbregs[KGDB_REG_PC])) {
+ for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
+ gdbregs[i] = context->readIntReg(AlphaISA::reg_redir[i]);
+ }
+ } else {
+ for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
+ gdbregs[i] = context->readIntReg(i);
+ }
+ }
+
+#ifdef KGDB_FP_REGS
+ for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) {
+ gdbregs[i + KGDB_REG_F0] = context->readFloatRegBits(i);
+ }
+#endif
+}
+
+///////////////////////////////////////////////////////////
+// RemoteGDB::setregs
+//
+// Translate the GDB register format into the kernel
+// debugger register format.
+//
+void
+RemoteGDB::setregs()
+{
+ // @todo: Currently this is very Alpha specific.
+ if (AlphaISA::PcPAL(gdbregs[KGDB_REG_PC])) {
+ for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
+ context->setIntReg(AlphaISA::reg_redir[i], gdbregs[i]);
+ }
+ } else {
+ for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
+ context->setIntReg(i, gdbregs[i]);
+ }
+ }
+
+#ifdef KGDB_FP_REGS
+ for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) {
+ context->setFloatRegBits(i, gdbregs[i + KGDB_REG_F0]);
+ }
+#endif
+ context->setPC(gdbregs[KGDB_REG_PC]);
+}
+
+void
+RemoteGDB::setTempBreakpoint(TempBreakpoint &bkpt, Addr addr)
+{
+ DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", addr);
+
+ bkpt.address = addr;
+ insertHardBreak(addr, 4);
+}
+
+void
+RemoteGDB::clearTempBreakpoint(TempBreakpoint &bkpt)
+{
+ DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n",
+ bkpt.address);
+
+
+ removeHardBreak(bkpt.address, 4);
+ bkpt.address = 0;
+}
+
+void
+RemoteGDB::clearSingleStep()
+{
+ DPRINTF(GDBMisc, "clearSingleStep bt_addr=%#x nt_addr=%#x\n",
+ takenBkpt.address, notTakenBkpt.address);
+
+ if (takenBkpt.address != 0)
+ clearTempBreakpoint(takenBkpt);
+
+ if (notTakenBkpt.address != 0)
+ clearTempBreakpoint(notTakenBkpt);
+}
+
+void
+RemoteGDB::setSingleStep()
+{
+ Addr pc = context->readPC();
+ Addr npc, bpc;
+ bool set_bt = false;
+
+ npc = pc + sizeof(MachInst);
+
+ // User was stopped at pc, e.g. the instruction at pc was not
+ // executed.
+ MachInst inst = read<MachInst>(pc);
+ StaticInstPtr si(inst);
+ if (si->hasBranchTarget(pc, context, bpc)) {
+ // Don't bother setting a breakpoint on the taken branch if it
+ // is the same as the next pc
+ if (bpc != npc)
+ set_bt = true;
+ }
+
+ DPRINTF(GDBMisc, "setSingleStep bt_addr=%#x nt_addr=%#x\n",
+ takenBkpt.address, notTakenBkpt.address);
+
+ setTempBreakpoint(notTakenBkpt, npc);
+
+ if (set_bt)
+ setTempBreakpoint(takenBkpt, bpc);
+}
+
+/////////////////////////
+//
+//
+
+uint8_t
+RemoteGDB::getbyte()
+{
+ uint8_t b;
+ ::read(fd, &b, 1);
+ return b;
+}
+
+void
+RemoteGDB::putbyte(uint8_t b)
+{
+ ::write(fd, &b, 1);
+}
+
+// Send a packet to gdb
+void
+RemoteGDB::send(const char *bp)
+{
+ const char *p;
+ uint8_t csum, c;
+
+ DPRINTF(GDBSend, "send: %s\n", bp);
+
+ do {
+ p = bp;
+ putbyte(KGDB_START);
+ for (csum = 0; (c = *p); p++) {
+ putbyte(c);
+ csum += c;
+ }
+ putbyte(KGDB_END);
+ putbyte(i2digit(csum >> 4));
+ putbyte(i2digit(csum));
+ } while ((c = getbyte() & 0x7f) == KGDB_BADP);
+}
+
+// Receive a packet from gdb
+int
+RemoteGDB::recv(char *bp, int maxlen)
+{
+ char *p;
+ int c, csum;
+ int len;
+
+ do {
+ p = bp;
+ csum = len = 0;
+ while ((c = getbyte()) != KGDB_START)
+ ;
+
+ while ((c = getbyte()) != KGDB_END && len < maxlen) {
+ c &= 0x7f;
+ csum += c;
+ *p++ = c;
+ len++;
+ }
+ csum &= 0xff;
+ *p = '\0';
+
+ if (len >= maxlen) {
+ putbyte(KGDB_BADP);
+ continue;
+ }
+
+ csum -= digit2i(getbyte()) * 16;
+ csum -= digit2i(getbyte());
+
+ if (csum == 0) {
+ putbyte(KGDB_GOODP);
+ // Sequence present?
+ if (bp[2] == ':') {
+ putbyte(bp[0]);
+ putbyte(bp[1]);
+ len -= 3;
+ bcopy(bp + 3, bp, len);
+ }
+ break;
+ }
+ putbyte(KGDB_BADP);
+ } while (1);
+
+ DPRINTF(GDBRecv, "recv: %s: %s\n", gdb_command(*bp), bp);
+
+ return (len);
+}
+
+// Read bytes from kernel address space for debugger.
+bool
+RemoteGDB::read(Addr vaddr, size_t size, char *data)
+{
+ static Addr lastaddr = 0;
+ static size_t lastsize = 0;
+
+ if (vaddr < 10) {
+ DPRINTF(GDBRead, "read: reading memory location zero!\n");
+ vaddr = lastaddr + lastsize;
+ }
+
+ DPRINTF(GDBRead, "read: addr=%#x, size=%d", vaddr, size);
+
+ context->getVirtPort(context)->readBlob(vaddr, (uint8_t*)data, size);
+
+#if TRACING_ON
+ if (DTRACE(GDBRead)) {
+ if (DTRACE(GDBExtra)) {
+ char buf[1024];
+ mem2hex(buf, data, size);
+ DPRINTFNR(": %s\n", buf);
+ } else
+ DPRINTFNR("\n");
+ }
+#endif
+
+ return true;
+}
+
+// Write bytes to kernel address space for debugger.
+bool
+RemoteGDB::write(Addr vaddr, size_t size, const char *data)
+{
+ static Addr lastaddr = 0;
+ static size_t lastsize = 0;
+
+ if (vaddr < 10) {
+ DPRINTF(GDBWrite, "write: writing memory location zero!\n");
+ vaddr = lastaddr + lastsize;
+ }
+
+ if (DTRACE(GDBWrite)) {
+ DPRINTFN("write: addr=%#x, size=%d", vaddr, size);
+ if (DTRACE(GDBExtra)) {
+ char buf[1024];
+ mem2hex(buf, data, size);
+ DPRINTFNR(": %s\n", buf);
+ } else
+ DPRINTFNR("\n");
+ }
+
+ context->getVirtPort(context)->writeBlob(vaddr, (uint8_t*)data, size);
+
+#ifdef IMB
+ alpha_pal_imb();
+#endif
+
+ return true;
+}
+
+
+PCEventQueue *RemoteGDB::getPcEventQueue()
+{
+ return &system->pcEventQueue;
+}
+
+
+RemoteGDB::HardBreakpoint::HardBreakpoint(RemoteGDB *_gdb, Addr pc)
+ : PCEvent(_gdb->getPcEventQueue(), "HardBreakpoint Event", pc),
+ gdb(_gdb), refcount(0)
+{
+ DPRINTF(GDBMisc, "creating hardware breakpoint at %#x\n", evpc);
+}
+
+void
+RemoteGDB::HardBreakpoint::process(ExecContext *xc)
+{
+ DPRINTF(GDBMisc, "handling hardware breakpoint at %#x\n", pc());
+
+ if (xc == gdb->context)
+ gdb->trap(ALPHA_KENTRY_INT);
+}
+
+bool
+RemoteGDB::insertSoftBreak(Addr addr, size_t len)
+{
+ if (len != sizeof(MachInst))
+ panic("invalid length\n");
+
+ return insertHardBreak(addr, len);
+}
+
+bool
+RemoteGDB::removeSoftBreak(Addr addr, size_t len)
+{
+ if (len != sizeof(MachInst))
+ panic("invalid length\n");
+
+ return removeHardBreak(addr, len);
+}
+
+bool
+RemoteGDB::insertHardBreak(Addr addr, size_t len)
+{
+ if (len != sizeof(MachInst))
+ panic("invalid length\n");
+
+ DPRINTF(GDBMisc, "inserting hardware breakpoint at %#x\n", addr);
+
+ HardBreakpoint *&bkpt = hardBreakMap[addr];
+ if (bkpt == 0)
+ bkpt = new HardBreakpoint(this, addr);
+
+ bkpt->refcount++;
+
+ return true;
+}
+
+bool
+RemoteGDB::removeHardBreak(Addr addr, size_t len)
+{
+ if (len != sizeof(MachInst))
+ panic("invalid length\n");
+
+ DPRINTF(GDBMisc, "removing hardware breakpoint at %#x\n", addr);
+
+ break_iter_t i = hardBreakMap.find(addr);
+ if (i == hardBreakMap.end())
+ return false;
+
+ HardBreakpoint *hbp = (*i).second;
+ if (--hbp->refcount == 0) {
+ delete hbp;
+ hardBreakMap.erase(i);
+ }
+
+ return true;
+}
+
+const char *
+break_type(char c)
+{
+ switch(c) {
+ case '0': return "software breakpoint";
+ case '1': return "hardware breakpoint";
+ case '2': return "write watchpoint";
+ case '3': return "read watchpoint";
+ case '4': return "access watchpoint";
+ default: return "unknown breakpoint/watchpoint";
+ }
+}
+
+// This function does all command processing for interfacing to a
+// remote gdb. Note that the error codes are ignored by gdb at
+// present, but might eventually become meaningful. (XXX) It might
+// makes sense to use POSIX errno values, because that is what the
+// gdb/remote.c functions want to return.
+bool
+RemoteGDB::trap(int type)
+{
+ uint64_t val;
+ size_t datalen, len;
+ char data[KGDB_BUFLEN + 1];
+ char buffer[sizeof(gdbregs) * 2 + 256];
+ char temp[KGDB_BUFLEN];
+ const char *p;
+ char command, subcmd;
+ string var;
+ bool ret;
+
+ if (!attached)
+ return false;
+
+ DPRINTF(GDBMisc, "trap: PC=%#x NPC=%#x\n",
+ context->readPC(), context->readNextPC());
+
+ clearSingleStep();
+
+ /*
+ * The first entry to this function is normally through
+ * a breakpoint trap in kgdb_connect(), in which case we
+ * must advance past the breakpoint because gdb will not.
+ *
+ * On the first entry here, we expect that gdb is not yet
+ * listening to us, so just enter the interaction loop.
+ * After the debugger is "active" (connected) it will be
+ * waiting for a "signaled" message from us.
+ */
+ if (!active)
+ active = true;
+ else
+ // Tell remote host that an exception has occurred.
+ snprintf((char *)buffer, sizeof(buffer), "S%02x", signal(type));
+ send(buffer);
+
+ // Stick frame regs into our reg cache.
+ getregs();
+
+ for (;;) {
+ datalen = recv(data, sizeof(data));
+ data[sizeof(data) - 1] = 0; // Sentinel
+ command = data[0];
+ subcmd = 0;
+ p = data + 1;
+ switch (command) {
+
+ case KGDB_SIGNAL:
+ // if this command came from a running gdb, answer it --
+ // the other guy has no way of knowing if we're in or out
+ // of this loop when he issues a "remote-signal".
+ snprintf((char *)buffer, sizeof(buffer), "S%02x", signal(type));
+ send(buffer);
+ continue;
+
+ case KGDB_REG_R:
+ if (2 * sizeof(gdbregs) > sizeof(buffer))
+ panic("buffer too small");
+
+ mem2hex(buffer, gdbregs, sizeof(gdbregs));
+ send(buffer);
+ continue;
+
+ case KGDB_REG_W:
+ p = hex2mem(gdbregs, p, sizeof(gdbregs));
+ if (p == NULL || *p != '\0')
+ send("E01");
+ else {
+ setregs();
+ send("OK");
+ }
+ continue;
+
+#if 0
+ case KGDB_SET_REG:
+ val = hex2i(&p);
+ if (*p++ != '=') {
+ send("E01");
+ continue;
+ }
+ if (val < 0 && val >= KGDB_NUMREGS) {
+ send("E01");
+ continue;
+ }
+
+ gdbregs[val] = hex2i(&p);
+ setregs();
+ send("OK");
+
+ continue;
+#endif
+
+ case KGDB_MEM_R:
+ val = hex2i(&p);
+ if (*p++ != ',') {
+ send("E02");
+ continue;
+ }
+ len = hex2i(&p);
+ if (*p != '\0') {
+ send("E03");
+ continue;
+ }
+ if (len > sizeof(buffer)) {
+ send("E04");
+ continue;
+ }
+ if (!acc(val, len)) {
+ send("E05");
+ continue;
+ }
+
+ if (read(val, (size_t)len, (char *)buffer)) {
+ mem2hex(temp, buffer, len);
+ send(temp);
+ } else {
+ send("E05");
+ }
+ continue;
+
+ case KGDB_MEM_W:
+ val = hex2i(&p);
+ if (*p++ != ',') {
+ send("E06");
+ continue;
+ }
+ len = hex2i(&p);
+ if (*p++ != ':') {
+ send("E07");
+ continue;
+ }
+ if (len > datalen - (p - data)) {
+ send("E08");
+ continue;
+ }
+ p = hex2mem(buffer, p, sizeof(buffer));
+ if (p == NULL) {
+ send("E09");
+ continue;
+ }
+ if (!acc(val, len)) {
+ send("E0A");
+ continue;
+ }
+ if (write(val, (size_t)len, (char *)buffer))
+ send("OK");
+ else
+ send("E0B");
+ continue;
+
+ case KGDB_SET_THREAD:
+ subcmd = *p++;
+ val = hex2i(&p);
+ if (val == 0)
+ send("OK");
+ else
+ send("E01");
+ continue;
+
+ case KGDB_DETACH:
+ case KGDB_KILL:
+ active = false;
+ clearSingleStep();
+ detach();
+ goto out;
+
+ case KGDB_ASYNC_CONT:
+ subcmd = hex2i(&p);
+ if (*p++ == ';') {
+ val = hex2i(&p);
+ context->setPC(val);
+ context->setNextPC(val + sizeof(MachInst));
+ }
+ clearSingleStep();
+ goto out;
+
+ case KGDB_CONT:
+ if (p - data < datalen) {
+ val = hex2i(&p);
+ context->setPC(val);
+ context->setNextPC(val + sizeof(MachInst));
+ }
+ clearSingleStep();
+ goto out;
+
+ case KGDB_ASYNC_STEP:
+ subcmd = hex2i(&p);
+ if (*p++ == ';') {
+ val = hex2i(&p);
+ context->setPC(val);
+ context->setNextPC(val + sizeof(MachInst));
+ }
+ setSingleStep();
+ goto out;
+
+ case KGDB_STEP:
+ if (p - data < datalen) {
+ val = hex2i(&p);
+ context->setPC(val);
+ context->setNextPC(val + sizeof(MachInst));
+ }
+ setSingleStep();
+ goto out;
+
+ case KGDB_CLR_HW_BKPT:
+ subcmd = *p++;
+ if (*p++ != ',') send("E0D");
+ val = hex2i(&p);
+ if (*p++ != ',') send("E0D");
+ len = hex2i(&p);
+
+ DPRINTF(GDBMisc, "clear %s, addr=%#x, len=%d\n",
+ break_type(subcmd), val, len);
+
+ ret = false;
+
+ switch (subcmd) {
+ case '0': // software breakpoint
+ ret = removeSoftBreak(val, len);
+ break;
+
+ case '1': // hardware breakpoint
+ ret = removeHardBreak(val, len);
+ break;
+
+ case '2': // write watchpoint
+ case '3': // read watchpoint
+ case '4': // access watchpoint
+ default: // unknown
+ send("");
+ break;
+ }
+
+ send(ret ? "OK" : "E0C");
+ continue;
+
+ case KGDB_SET_HW_BKPT:
+ subcmd = *p++;
+ if (*p++ != ',') send("E0D");
+ val = hex2i(&p);
+ if (*p++ != ',') send("E0D");
+ len = hex2i(&p);
+
+ DPRINTF(GDBMisc, "set %s, addr=%#x, len=%d\n",
+ break_type(subcmd), val, len);
+
+ ret = false;
+
+ switch (subcmd) {
+ case '0': // software breakpoint
+ ret = insertSoftBreak(val, len);
+ break;
+
+ case '1': // hardware breakpoint
+ ret = insertHardBreak(val, len);
+ break;
+
+ case '2': // write watchpoint
+ case '3': // read watchpoint
+ case '4': // access watchpoint
+ default: // unknown
+ send("");
+ break;
+ }
+
+ send(ret ? "OK" : "E0C");
+ continue;
+
+ case KGDB_QUERY_VAR:
+ var = string(p, datalen - 1);
+ if (var == "C")
+ send("QC0");
+ else
+ send("");
+ continue;
+
+ case KGDB_SET_BAUD:
+ case KGDB_SET_BREAK:
+ case KGDB_DEBUG:
+ case KGDB_CYCLE_STEP:
+ case KGDB_SIG_CYCLE_STEP:
+ case KGDB_READ_REG:
+ case KGDB_SET_VAR:
+ case KGDB_RESET:
+ case KGDB_THREAD_ALIVE:
+ case KGDB_TARGET_EXIT:
+ case KGDB_BINARY_DLOAD:
+ // Unsupported command
+ DPRINTF(GDBMisc, "Unsupported command: %s\n",
+ gdb_command(command));
+ DDUMP(GDBMisc, (uint8_t *)data, datalen);
+ send("");
+ continue;
+
+ default:
+ // Unknown command.
+ DPRINTF(GDBMisc, "Unknown command: %c(%#x)\n",
+ command, command);
+ send("");
+ continue;
+
+
+ }
+ }
+
+ out:
+ return true;
+}
+
+// Convert a hex digit into an integer.
+// This returns -1 if the argument passed is no valid hex digit.
+int
+digit2i(char c)
+{
+ if (c >= '0' && c <= '9')
+ return (c - '0');
+ else if (c >= 'a' && c <= 'f')
+ return (c - 'a' + 10);
+ else if (c >= 'A' && c <= 'F')
+
+ return (c - 'A' + 10);
+ else
+ return (-1);
+}
+
+// Convert the low 4 bits of an integer into an hex digit.
+char
+i2digit(int n)
+{
+ return ("0123456789abcdef"[n & 0x0f]);
+}
+
+// Convert a byte array into an hex string.
+void
+mem2hex(void *vdst, const void *vsrc, int len)
+{
+ char *dst = (char *)vdst;
+ const char *src = (const char *)vsrc;
+
+ while (len--) {
+ *dst++ = i2digit(*src >> 4);
+ *dst++ = i2digit(*src++);
+ }
+ *dst = '\0';
+}
+
+// Convert an hex string into a byte array.
+// This returns a pointer to the character following the last valid
+// hex digit. If the string ends in the middle of a byte, NULL is
+// returned.
+const char *
+hex2mem(void *vdst, const char *src, int maxlen)
+{
+ char *dst = (char *)vdst;
+ int msb, lsb;
+
+ while (*src && maxlen--) {
+ msb = digit2i(*src++);
+ if (msb < 0)
+ return (src - 1);
+ lsb = digit2i(*src++);
+ if (lsb < 0)
+ return (NULL);
+ *dst++ = (msb << 4) | lsb;
+ }
+ return (src);
+}
+
+// Convert an hex string into an integer.
+// This returns a pointer to the character following the last valid
+// hex digit.
+Addr
+hex2i(const char **srcp)
+{
+ const char *src = *srcp;
+ Addr r = 0;
+ int nibble;
+
+ while ((nibble = digit2i(*src)) >= 0) {
+ r *= 16;
+ r += nibble;
+ src++;
+ }
+ *srcp = src;
+ return (r);
+}
+
diff --git a/src/base/remote_gdb.hh b/src/base/remote_gdb.hh
new file mode 100644
index 000000000..b7abf5116
--- /dev/null
+++ b/src/base/remote_gdb.hh
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __REMOTE_GDB_HH__
+#define __REMOTE_GDB_HH__
+
+#include <map>
+
+#include "base/kgdb.h"
+#include "cpu/pc_event.hh"
+#include "base/pollevent.hh"
+#include "base/socket.hh"
+
+class System;
+class ExecContext;
+class PhysicalMemory;
+
+class GDBListener;
+class RemoteGDB
+{
+ protected:
+ typedef TheISA::MachInst MachInst;
+ private:
+ friend void debugger();
+ friend class GDBListener;
+
+ protected:
+ class Event : public PollEvent
+ {
+ protected:
+ RemoteGDB *gdb;
+
+ public:
+ Event(RemoteGDB *g, int fd, int e);
+ void process(int revent);
+ };
+
+ friend class Event;
+ Event *event;
+ GDBListener *listener;
+ int number;
+
+ protected:
+ int fd;
+ uint64_t gdbregs[KGDB_NUMREGS];
+
+ protected:
+#ifdef notyet
+ label_t recover;
+#endif
+ bool active;
+ bool attached;
+
+ System *system;
+ PhysicalMemory *pmem;
+ ExecContext *context;
+
+ protected:
+ uint8_t getbyte();
+ void putbyte(uint8_t b);
+
+ int recv(char *data, int len);
+ void send(const char *data);
+
+ protected:
+ // Machine memory
+ bool read(Addr addr, size_t size, char *data);
+ bool write(Addr addr, size_t size, const char *data);
+
+ template <class T> T read(Addr addr);
+ template <class T> void write(Addr addr, T data);
+
+ public:
+ RemoteGDB(System *system, ExecContext *context);
+ ~RemoteGDB();
+
+ void replaceExecContext(ExecContext *xc) { context = xc; }
+
+ void attach(int fd);
+ void detach();
+ bool isattached();
+
+ bool acc(Addr addr, size_t len);
+ static int signal(int type);
+ bool trap(int type);
+
+ protected:
+ void getregs();
+ void setregs();
+
+ void clearSingleStep();
+ void setSingleStep();
+
+ PCEventQueue *getPcEventQueue();
+
+ protected:
+ class HardBreakpoint : public PCEvent
+ {
+ private:
+ RemoteGDB *gdb;
+
+ public:
+ int refcount;
+
+ public:
+ HardBreakpoint(RemoteGDB *_gdb, Addr addr);
+ std::string name() { return gdb->name() + ".hwbkpt"; }
+
+ virtual void process(ExecContext *xc);
+ };
+ friend class HardBreakpoint;
+
+ typedef std::map<Addr, HardBreakpoint *> break_map_t;
+ typedef break_map_t::iterator break_iter_t;
+ break_map_t hardBreakMap;
+
+ bool insertSoftBreak(Addr addr, size_t len);
+ bool removeSoftBreak(Addr addr, size_t len);
+ bool insertHardBreak(Addr addr, size_t len);
+ bool removeHardBreak(Addr addr, size_t len);
+
+ protected:
+ struct TempBreakpoint {
+ Addr address; // set here
+ MachInst bkpt_inst; // saved instruction at bkpt
+ int init_count; // number of times to skip bkpt
+ int count; // current count
+ };
+
+ TempBreakpoint notTakenBkpt;
+ TempBreakpoint takenBkpt;
+
+ void clearTempBreakpoint(TempBreakpoint &bkpt);
+ void setTempBreakpoint(TempBreakpoint &bkpt, Addr addr);
+
+ public:
+ std::string name();
+};
+
+template <class T>
+inline T
+RemoteGDB::read(Addr addr)
+{
+ T temp;
+ read(addr, sizeof(T), (char *)&temp);
+ return temp;
+}
+
+template <class T>
+inline void
+RemoteGDB::write(Addr addr, T data)
+{ write(addr, sizeof(T), (const char *)&data); }
+
+class GDBListener
+{
+ protected:
+ class Event : public PollEvent
+ {
+ protected:
+ GDBListener *listener;
+
+ public:
+ Event(GDBListener *l, int fd, int e);
+ void process(int revent);
+ };
+
+ friend class Event;
+ Event *event;
+
+ protected:
+ ListenSocket listener;
+ RemoteGDB *gdb;
+ int port;
+
+ public:
+ GDBListener(RemoteGDB *g, int p);
+ ~GDBListener();
+
+ void accept();
+ void listen();
+ std::string name();
+};
+
+#endif /* __REMOTE_GDB_H__ */
diff --git a/src/base/res_list.hh b/src/base/res_list.hh
new file mode 100644
index 000000000..960ed108e
--- /dev/null
+++ b/src/base/res_list.hh
@@ -0,0 +1,755 @@
+/*
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __RES_LIST_HH__
+#define __RES_LIST_HH__
+
+#include "base/cprintf.hh"
+#include <assert.h>
+
+#define DEBUG_REMOVE 0
+
+#define DEBUG_MEMORY 0
+//#define DEBUG_MEMORY DEBUG
+
+class res_list_base
+{
+#if DEBUG_MEMORY
+ protected:
+ static long long allocated_elements;
+ static long long allocated_lists;
+
+ public:
+ long long get_elements(void) {
+ return allocated_elements;
+ }
+ long long get_lists(void) {
+ return allocated_lists;
+ }
+
+#endif
+};
+
+#if DEBUG_MEMORY
+extern void what_the(void);
+#endif
+
+template<class T>
+class res_list : public res_list_base
+{
+ public:
+ class iterator;
+
+ class res_element
+ {
+ res_element *next;
+ res_element *prev;
+ T *data;
+ bool allocate_data;
+
+ public:
+ // always adds to the END of the list
+ res_element(res_element *_prev, bool allocate);
+ ~res_element();
+ void dump(void);
+
+ friend class res_list<T>;
+ friend class res_list<T>::iterator;
+ };
+
+ class iterator
+ {
+ private:
+ res_element *p;
+
+ friend class res_list<T>;
+
+ public:
+ // Constructors
+ iterator(res_element *q) : p(q) {}
+ iterator(void) { p=0; };
+
+ void dump(void);
+ T* data_ptr(void);
+ res_element *res_el_ptr(void) { return p;}
+ void point_to(T &d) { p->data = &d; }
+
+ iterator next(void) { return iterator(p->next); }
+ iterator prev(void) { return iterator(p->prev); }
+ bool operator== (iterator x) { return (x.p == this->p); }
+ bool operator != (iterator x) { return (x.p != this->p); }
+ T &operator * (void) { return *(p->data); }
+ T* operator -> (void) { return p->data; }
+ bool isnull(void) { return (p==0); }
+ bool notnull(void) { return (p!=0); }
+ };
+
+ private:
+ iterator unused_elements;
+ iterator head_ptr;
+ iterator tail_ptr;
+
+ unsigned base_elements;
+ unsigned extra_elements;
+ unsigned active_elements;
+ bool allocate_storage;
+ unsigned build_size;
+
+ int remove_count;
+
+ //
+ // Allocate new elements, and assign them to the unused_elements
+ // list.
+ //
+ unsigned allocate_elements(unsigned num, bool allocate_storage);
+
+ public:
+ //
+ // List Constructor
+ //
+ res_list(unsigned size, bool alloc_storage = false,
+ unsigned build_sz = 5);
+
+ //
+ // List Destructor
+ //
+ ~res_list();
+
+ iterator head(void) {return head_ptr;};
+ iterator tail(void) {return tail_ptr;};
+
+ unsigned num_free(void) { return size() - count(); }
+ unsigned size(void) { return base_elements + extra_elements; }
+ unsigned count(void) { return active_elements; }
+ bool empty(void) { return count() == 0; }
+ bool full(void);
+
+ //
+ // Insert with data copy
+ //
+ iterator insert_after(iterator prev, T *d);
+ iterator insert_after(iterator prev, T &d);
+ iterator insert_before(iterator prev, T *d);
+ iterator insert_before(iterator prev, T &d);
+
+ //
+ // Insert new list element (no data copy)
+ //
+ iterator insert_after(iterator prev);
+ iterator insert_before(iterator prev);
+
+ iterator add_tail(T *d) { return insert_after(tail_ptr, d); }
+ iterator add_tail(T &d) { return insert_after(tail_ptr, d); }
+ iterator add_tail(void) { return insert_after(tail_ptr); }
+ iterator add_head(T *d) { return insert_before(head_ptr, d); }
+ iterator add_head(T &d) { return insert_before(head_ptr, d); }
+ iterator add_head(void) { return insert_before(head_ptr); }
+
+ iterator remove(iterator q);
+ iterator remove_head(void) {return remove(head_ptr);}
+ iterator remove_tail(void) {return remove(tail_ptr);}
+
+ bool in_list(iterator j);
+ void free_extras(void);
+ void clear(void);
+ void dump(void);
+ void raw_dump(void);
+};
+
+template <class T>
+inline
+res_list<T>::res_element::res_element(res_element *_prev, bool allocate)
+{
+ allocate_data = allocate;
+ prev = _prev;
+ next = 0;
+
+ if (prev)
+ prev->next = this;
+
+ if (allocate)
+ data = new T;
+ else
+ data = 0;
+
+#if DEBUG_MEMORY
+ ++allocated_elements;
+#endif
+}
+
+template <class T>
+inline
+res_list<T>::res_element::~res_element(void)
+{
+ if (prev)
+ prev->next = next;
+
+ if (next)
+ next->prev = prev;
+
+ if (allocate_data)
+ delete data;
+
+#if DEBUG_MEMORY
+ --allocated_elements;
+#endif
+}
+
+template <class T>
+inline void
+res_list<T>::res_element::dump(void)
+{
+ cprintf(" prev = %#x\n", prev);
+ cprintf(" next = %#x\n", next);
+ cprintf(" data = %#x\n", data);
+}
+
+template <class T>
+inline void
+res_list<T>::iterator::dump(void)
+{
+ if (p && p->data)
+ p->data->dump();
+ else {
+ if (!p)
+ cprintf(" Null Pointer\n");
+ else
+ cprintf(" Null 'data' Pointer\n");
+ }
+}
+
+template <class T>
+inline T *
+res_list<T>::iterator::data_ptr(void)
+{
+ if (p)
+ return p->data;
+ else
+ return 0;
+}
+
+
+//
+// Allocate new elements, and assign them to the unused_elements
+// list.
+//
+template <class T>
+inline unsigned
+res_list<T>::allocate_elements(unsigned num, bool allocate_storage)
+{
+ res_element *pnew, *plast = 0, *pfirst=0;
+
+ for (int i=0; i<num; ++i) {
+ pnew = new res_element(plast, allocate_storage);
+ if (i==0)
+ pfirst = pnew;
+ plast = pnew;
+ }
+
+ if (unused_elements.notnull()) {
+ // Add these new elements to the front of the list
+ plast->next = unused_elements.res_el_ptr();
+ unused_elements.res_el_ptr()->prev = plast;
+ }
+
+ unused_elements = iterator(pfirst);
+
+ return num;
+}
+
+template <class T>
+inline
+res_list<T>::res_list(unsigned size, bool alloc_storage, unsigned build_sz)
+{
+#if DEBUG_MEMORY
+ ++allocated_lists;
+#endif
+ extra_elements = 0;
+ active_elements = 0;
+ build_size = build_sz;
+ allocate_storage = alloc_storage;
+ remove_count = 0;
+
+ // Create the new elements
+ base_elements = allocate_elements(size, alloc_storage);
+
+ // The list of active elements
+ head_ptr = iterator(0);
+ tail_ptr = iterator(0);
+}
+
+//
+// List Destructor
+//
+template <class T>
+inline
+res_list<T>::~res_list(void)
+{
+ iterator n;
+
+#if DEBUG_MEMORY
+ --allocated_lists;
+#endif
+
+ // put everything into the unused list
+ clear();
+
+ // rudely delete all the res_elements
+ for (iterator p = unused_elements;
+ p.notnull();
+ p = n) {
+
+ n = p.next();
+
+ // delete the res_element
+ // (it will take care of deleting the data)
+ delete p.res_el_ptr();
+ }
+}
+
+template <class T>
+inline bool
+res_list<T>::full(void)
+{
+ if (build_size)
+ return false;
+ else
+ return unused_elements.isnull();
+}
+
+//
+// Insert with data copy
+//
+template <class T>
+inline typename res_list<T>::iterator
+res_list<T>::insert_after(iterator prev, T *d)
+{
+ iterator p;
+
+ if (!allocate_storage)
+ this->panic("Can't copy data... not allocating storage");
+
+ p = insert_after(prev);
+ if (p.notnull())
+ *p = *d;
+
+ return p;
+}
+
+
+template <class T>
+inline typename res_list<T>::iterator
+res_list<T>::insert_after(iterator prev, T &d)
+{
+ iterator p;
+
+ p = insert_after(prev);
+ if (p.notnull()) {
+
+ if (allocate_storage) {
+ // if we allocate storage, then copy the contents of the
+ // specified object to our object
+ *p = d;
+ }
+ else {
+ // if we don't allocate storage, then we just want to
+ // point to the specified object
+ p.point_to(d);
+ }
+ }
+
+ return p;
+}
+
+
+template <class T>
+inline typename res_list<T>::iterator
+res_list<T>::insert_after(iterator prev)
+{
+
+#if DEBUG_MEMORY
+ if (active_elements > 2*base_elements) {
+ what_the();
+ }
+#endif
+
+ // If we have no unused elements, make some more
+ if (unused_elements.isnull()) {
+
+ if (build_size == 0) {
+ return 0; // No space left, and can't allocate more....
+ }
+
+ extra_elements += allocate_elements(build_size, allocate_storage);
+ }
+
+ // grab the first unused element
+ res_element *p = unused_elements.res_el_ptr();
+
+ unused_elements = unused_elements.next();
+
+ ++active_elements;
+
+ // Insert the new element
+ if (head_ptr.isnull()) {
+ //
+ // Special case #1: Empty List
+ //
+ head_ptr = p;
+ tail_ptr = p;
+ p->prev = 0;
+ p->next = 0;
+ }
+ else if (prev.isnull()) {
+ //
+ // Special case #2: Insert at head
+ //
+
+ // our next ptr points to old head element
+ p->next = head_ptr.res_el_ptr();
+
+ // our element becomes the new head element
+ head_ptr = p;
+
+ // no previous element for the head
+ p->prev = 0;
+
+ // old head element points back to this element
+ p->next->prev = p;
+ }
+ else if (prev.next().isnull()) {
+ //
+ // Special case #3 Insert at tail
+ //
+
+ // our prev pointer points to old tail element
+ p->prev = tail_ptr.res_el_ptr();
+
+ // our element becomes the new tail
+ tail_ptr = p;
+
+ // no next element for the tail
+ p->next = 0;
+
+ // old tail element point to this element
+ p->prev->next = p;
+ }
+ else {
+ //
+ // Normal insertion (after prev)
+ //
+ p->prev = prev.res_el_ptr();
+ p->next = prev.next().res_el_ptr();
+
+ prev.res_el_ptr()->next = p;
+ p->next->prev = p;
+ }
+
+ return iterator(p);
+}
+
+template <class T>
+inline typename res_list<T>::iterator
+res_list<T>::insert_before(iterator next, T &d)
+{
+ iterator p;
+
+ p = insert_before(next);
+ if (p.notnull()) {
+
+ if (allocate_storage) {
+ // if we allocate storage, then copy the contents of the
+ // specified object to our object
+ *p = d;
+ }
+ else {
+ // if we don't allocate storage, then we just want to
+ // point to the specified object
+ p.point_to(d);
+ }
+ }
+
+ return p;
+}
+
+
+template <class T>
+inline typename res_list<T>::iterator
+res_list<T>::insert_before(iterator next)
+{
+
+#if DEBUG_MEMORY
+ if (active_elements > 2*base_elements) {
+ what_the();
+ }
+#endif
+
+ // If we have no unused elements, make some more
+ if (unused_elements.isnull()) {
+
+ if (build_size == 0) {
+ return 0; // No space left, and can't allocate more....
+ }
+
+ extra_elements += allocate_elements(build_size, allocate_storage);
+ }
+
+ // grab the first unused element
+ res_element *p = unused_elements.res_el_ptr();
+
+ unused_elements = unused_elements.next();
+
+ ++active_elements;
+
+ // Insert the new element
+ if (head_ptr.isnull()) {
+ //
+ // Special case #1: Empty List
+ //
+ head_ptr = p;
+ tail_ptr = p;
+ p->prev = 0;
+ p->next = 0;
+ }
+ else if (next.isnull()) {
+ //
+ // Special case #2 Insert at tail
+ //
+
+ // our prev pointer points to old tail element
+ p->prev = tail_ptr.res_el_ptr();
+
+ // our element becomes the new tail
+ tail_ptr = p;
+
+ // no next element for the tail
+ p->next = 0;
+
+ // old tail element point to this element
+ p->prev->next = p;
+ }
+ else if (next.prev().isnull()) {
+ //
+ // Special case #3: Insert at head
+ //
+
+ // our next ptr points to old head element
+ p->next = head_ptr.res_el_ptr();
+
+ // our element becomes the new head element
+ head_ptr = p;
+
+ // no previous element for the head
+ p->prev = 0;
+
+ // old head element points back to this element
+ p->next->prev = p;
+ }
+ else {
+ //
+ // Normal insertion (before next)
+ //
+ p->next = next.res_el_ptr();
+ p->prev = next.prev().res_el_ptr();
+
+ next.res_el_ptr()->prev = p;
+ p->prev->next = p;
+ }
+
+ return iterator(p);
+}
+
+
+template <class T>
+inline typename res_list<T>::iterator
+res_list<T>::remove(iterator q)
+{
+ res_element *p = q.res_el_ptr();
+ iterator n = 0;
+
+ // Handle the special cases
+ if (active_elements == 1) { // This is the only element
+ head_ptr = 0;
+ tail_ptr = 0;
+ }
+ else if (q == head_ptr) { // This is the head element
+ head_ptr = q.next();
+ head_ptr.res_el_ptr()->prev = 0;
+
+ n = head_ptr;
+ }
+ else if (q == tail_ptr) { // This is the tail element
+ tail_ptr = q.prev();
+ tail_ptr.res_el_ptr()->next = 0;
+ }
+ else { // This is between two elements
+ p->prev->next = p->next;
+ p->next->prev = p->prev;
+
+ // Get the "next" element for return
+ n = p->next;
+ }
+
+ --active_elements;
+
+ // Put this element back onto the unused list
+ p->next = unused_elements.res_el_ptr();
+ p->prev = 0;
+ if (p->next) { // NULL if unused list is empty
+ p->next->prev = p;
+ }
+
+ if (!allocate_storage) {
+ p->data = 0;
+ }
+
+ unused_elements = q;
+
+ // A little "garbage collection"
+ if (++remove_count > 10) {
+ // free_extras();
+ remove_count = 0;
+ }
+
+#if DEBUG_REMOVE
+ unsigned unused_count = 0;
+ for (iterator i=unused_elements;
+ i.notnull();
+ i = i.next()) {
+
+ ++unused_count;
+ }
+
+ assert((active_elements+unused_count) == (base_elements+extra_elements));
+#endif
+
+ return iterator(n);
+}
+
+
+template <class T>
+inline bool
+res_list<T>::in_list(iterator j)
+{
+ iterator i;
+
+ for (i=head(); i.notnull(); i=i.next()) {
+ if (j.res_el_ptr() == i.res_el_ptr()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+template <class T>
+inline void
+res_list<T>::free_extras(void)
+{
+ unsigned num_unused = base_elements + extra_elements - active_elements;
+ unsigned to_free = extra_elements;
+ res_element *p;
+
+
+ if (extra_elements != 0) {
+ //
+ // Free min(extra_elements, # unused elements)
+ //
+ if (extra_elements > num_unused) {
+ to_free = num_unused;
+ }
+
+ p = unused_elements.res_el_ptr();
+ for (int i=0; i<to_free; ++i) {
+ res_element *q = p->next;
+
+ delete p;
+
+ p = q;
+ }
+
+ // update the unused element pointer to point to the first
+ // element that wasn't deleted.
+ unused_elements = iterator(p);
+
+ // Update the number of extra elements
+ extra_elements -= to_free;
+ }
+
+ return;
+}
+
+
+template <class T>
+inline void
+res_list<T>::clear(void)
+{
+ iterator i,n;
+
+ for (i=head_ptr; i.notnull(); i=n) {
+ n = i.next();
+ remove(i);
+ }
+
+ free_extras();
+}
+
+template <class T>
+inline void
+res_list<T>::dump(void)
+{
+ for (iterator i=head(); !i.isnull(); i=i.next())
+ i->dump();
+}
+
+template <class T>
+inline void
+res_list<T>::raw_dump(void)
+{
+ int j = 0;
+ res_element *p;
+ for (iterator i=head(); !i.isnull(); i=i.next()) {
+ cprintf("Element %d:\n", j);
+
+ if (i.notnull()) {
+ p = i.res_el_ptr();
+ cprintf(" points to res_element @ %#x\n", p);
+ p->dump();
+ cprintf(" Data Element:\n");
+ i->dump();
+ }
+ else {
+ cprintf(" NULL iterator!\n");
+ }
+
+ ++j;
+ }
+
+}
+
+#endif // __RES_LIST_HH__
diff --git a/src/base/sat_counter.cc b/src/base/sat_counter.cc
new file mode 100644
index 000000000..7920f6c81
--- /dev/null
+++ b/src/base/sat_counter.cc
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sstream>
+
+#include "base/sat_counter.hh"
+#include "base/statistics.hh"
+#include "sim/stats.hh"
+
+
+using namespace std;
+
+
+SaturatingCounterPred::SaturatingCounterPred(string p_name,
+ string z_name,
+ string o_name,
+ unsigned _index_bits,
+ unsigned _counter_bits,
+ unsigned _zero_change,
+ unsigned _one_change,
+ unsigned _thresh,
+ unsigned _init_value)
+{
+ pred_name = p_name;
+ zero_name = z_name;
+ one_name = o_name;
+
+ index_bits = _index_bits;
+ counter_bits = _counter_bits;
+ zero_change = _zero_change;
+ one_change = _one_change;
+ thresh = _thresh;
+ init_value = _init_value;
+
+ max_index = (1 << index_bits) - 1;
+ max_value = (1 << counter_bits) - 1;
+
+ table = new unsigned[max_index + 1];
+
+ // Initialize with the right parameters & clear the counter
+ for (int i = 0; i <= max_index; ++i)
+ table[i] = init_value;
+}
+
+void SaturatingCounterPred::regStats()
+{
+ using namespace Stats;
+ stringstream name, description;
+
+ //
+ // Number of predictions
+ //
+ name << pred_name << ":" << zero_name << ":preds";
+ description << "number of predictions of " << zero_name;
+ predicted_zero
+ .name(name.str())
+ .desc(description.str())
+ ;
+ description.str("");
+ name.str("");
+
+ name << pred_name << ":" << one_name << ":preds";
+ description << "number of predictions of " << one_name;
+ predicted_one
+ .name(name.str())
+ .desc(description.str())
+ ;
+ description.str("");
+ name.str("");
+
+ //
+ // Count the number of correct predictions
+ //
+ name << pred_name << ":" << zero_name << ":corr_preds";
+ description << "number of correct " << zero_name << " preds";
+ correct_pred_zero
+ .name(name.str())
+ .desc(description.str())
+ ;
+ description.str("");
+ name.str("");
+
+ name << pred_name << ":" << one_name << ":corr_preds";
+ description << "number of correct " << one_name << " preds";
+ correct_pred_one
+ .name(name.str())
+ .desc(description.str())
+ ;
+ description.str("");
+ name.str("");
+
+ //
+ // Number of predictor updates
+ //
+ name << pred_name << ":" << zero_name << ":updates";
+ description << "number of actual " << zero_name << "s";
+ record_zero
+ .name(name.str())
+ .desc(description.str())
+ ;
+ description.str("");
+ name.str("");
+
+ name << pred_name << ":" << one_name << ":updates";
+ description << "number of actual " << one_name << "s";
+ record_one
+ .name(name.str())
+ .desc(description.str())
+ ;
+ description.str("");
+ name.str("");
+}
+
+void SaturatingCounterPred::regFormulas()
+{
+ using namespace Stats;
+ stringstream name, description;
+
+ //
+ // Number of predictions
+ //
+ name << pred_name << ":predictions";
+ preds_total
+ .name(name.str())
+ .desc("total number of predictions made")
+ ;
+ preds_total = predicted_zero + predicted_one;
+ name.str("");
+
+ //
+ // Fraction of all predictions that are one or zero
+ //
+ name << pred_name << ":" << zero_name << ":pred_frac";
+ description << "fraction of all preds that were " << zero_name;
+ pred_frac_zero
+ .name(name.str())
+ .desc(description.str())
+ ;
+ pred_frac_zero = 100 * predicted_zero / preds_total;
+ description.str("");
+ name.str("");
+
+ name << pred_name << ":" << one_name << ":pred_frac";
+ description << "fraction of all preds that were " << one_name;
+ pred_frac_one
+ .name(name.str())
+ .desc(description.str())
+ ;
+ pred_frac_one = 100 * predicted_one / preds_total;
+ description.str("");
+ name.str("");
+
+
+ //
+ // Count the number of correct predictions
+ //
+ name << pred_name << ":correct_preds";
+ correct_total
+ .name(name.str())
+ .desc("total correct predictions made")
+ ;
+ correct_total = correct_pred_one + correct_pred_zero;
+ name.str("");
+
+ //
+ // Number of predictor updates
+ //
+ name << pred_name << ":updates";
+ updates_total
+ .name(name.str())
+ .desc("total number of updates")
+ ;
+ updates_total = record_zero + record_one;
+ name.str("");
+
+ //
+ // Prediction accuracy rates
+ //
+ name << pred_name << ":pred_rate";
+ pred_rate
+ .name(name.str())
+ .desc("correct fraction of all preds")
+ ;
+ pred_rate = correct_total / updates_total;
+ name.str("");
+
+ name << pred_name << ":" << zero_name << ":pred_rate";
+ description << "fraction of " << zero_name << " preds that were correct";
+ frac_correct_zero
+ .name(name.str())
+ .desc(description.str())
+ ;
+ frac_correct_zero = 100 * correct_pred_zero /
+ (correct_pred_zero + record_one - correct_pred_one);
+ description.str("");
+ name.str("");
+
+ name << pred_name << ":" << one_name << ":pred_rate";
+ description << "fraction of " << one_name << " preds that were correct";
+ frac_correct_one
+ .name(name.str())
+ .desc(description.str())
+ ;
+ frac_correct_one = 100 * correct_pred_one /
+ (correct_pred_one + record_zero - correct_pred_zero);
+ description.str("");
+ name.str("");
+
+ //
+ // Coverage
+ //
+ name << pred_name << ":" << zero_name << ":coverage";
+ description << "fraction of " << zero_name
+ << "s that were predicted correctly";
+ coverage_zero
+ .name(name.str())
+ .desc(description.str())
+ ;
+ coverage_zero = 100 * correct_pred_zero / record_zero;
+ description.str("");
+ name.str("");
+
+ name << pred_name << ":" << one_name << ":coverage";
+ description << "fraction of " << one_name
+ << "s that were predicted correctly";
+ coverage_one
+ .name(name.str())
+ .desc(description.str())
+ ;
+ coverage_one = 100 * correct_pred_one / record_one;
+ description.str("");
+ name.str("");
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/base/sat_counter.hh b/src/base/sat_counter.hh
new file mode 100644
index 000000000..d7be17b6f
--- /dev/null
+++ b/src/base/sat_counter.hh
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SAT_COUNTER_HH__
+#define __SAT_COUNTER_HH__
+
+#include <string>
+
+#include "base/predictor.hh"
+
+#include "base/statistics.hh"
+#include "sim/stats.hh"
+
+//
+//
+// A simple saturating counter predictor
+//
+//
+class SaturatingCounterPred : public GenericPredictor
+{
+ private:
+ std::string pred_name;
+ std::string zero_name;
+ std::string one_name;
+
+ unsigned index_bits;
+ unsigned counter_bits;
+ unsigned zero_change;
+ unsigned one_change;
+ unsigned thresh;
+ unsigned init_value;
+
+ unsigned max_value; // maximum counter value
+
+ unsigned long max_index; // also the index mask value
+ unsigned *table;
+
+ // Statistics
+ Stats::Scalar<> predicted_one; // Total predictions of one, preds_one
+ Stats::Scalar<> predicted_zero; // Total predictions of zero, preds_zero
+ Stats::Scalar<> correct_pred_one; // Total correct predictions of one, correct_one
+ Stats::Scalar<> correct_pred_zero; // Total correct predictions of zero, correct_zero
+
+ Stats::Scalar<> record_zero; //updates_zero
+ Stats::Scalar<> record_one; //updates_one
+
+ Stats::Formula preds_total;
+ Stats::Formula pred_frac_zero;
+ Stats::Formula pred_frac_one;
+ Stats::Formula correct_total;
+ Stats::Formula updates_total;
+ Stats::Formula pred_rate;
+ Stats::Formula frac_correct_zero;
+ Stats::Formula frac_correct_one;
+ Stats::Formula coverage_zero;
+ Stats::Formula coverage_one;
+
+ private:
+ bool pred_one(unsigned &counter) { return counter > thresh; }
+ bool pred_zero(unsigned &counter) { return counter <= thresh; }
+
+ void update_one(unsigned &counter) {
+
+ if (one_change)
+ counter += one_change;
+ else
+ counter = 0;
+
+ // check for wrap
+ if (counter > max_value)
+ counter = max_value;
+ }
+
+ void update_zero(unsigned &counter) {
+ if (zero_change) {
+ // check for wrap
+ if (counter < zero_change)
+ counter = 0;
+ else
+ counter -= zero_change;
+ } else
+ counter = 0;
+ }
+
+
+ public:
+
+ SaturatingCounterPred(std::string p_name,
+ std::string z_name, std::string o_name,
+ unsigned _index_bits, unsigned _counter_bits = 2,
+ unsigned _zero_change = 1, unsigned _one_change = 1,
+ unsigned _thresh = 1, unsigned _init_value = 0);
+
+ void clear() {
+ for (int i = 0; i <= max_index; ++i)
+ table[i] = init_value;
+ }
+
+ // Record the ACTUAL result... and indicate whether the prediction
+ // corresponding to this event was correct
+ void record(unsigned long _index, unsigned _val, unsigned _predicted,
+ unsigned _pdata)
+ {
+ record(_index, _val, _predicted);
+ }
+
+ void record(unsigned long _index, unsigned _val, unsigned _predicted) {
+ unsigned long index = _index & max_index;
+
+ if (_val) {
+ update_one(table[index]);
+ ++record_one;
+
+ if (_predicted)
+ ++correct_pred_one;
+ } else {
+ update_zero(table[index]);
+ ++record_zero;
+
+ if (!_predicted)
+ ++correct_pred_zero;
+ }
+ }
+
+ unsigned value(unsigned long _index) {
+ unsigned long index = _index & max_index;
+
+ return table[index];
+ }
+
+
+ unsigned predict(unsigned long _index, unsigned &pdata) {
+ return predict(_index);
+ }
+
+ unsigned predict(unsigned long _index) {
+ unsigned long index = _index & max_index;
+
+ if (pred_one(table[index])) {
+ ++predicted_one;
+ return 1;
+ }
+
+ ++predicted_zero;
+ return 0;
+ }
+
+ // No internal state is changed here
+ unsigned peek(unsigned long _index) {
+ unsigned long index = _index & max_index;
+
+ if (pred_one(table[index]))
+ return 1;
+
+ return 0;
+ }
+
+
+ //=======================================================
+ void regStats();
+ void regFormulas();
+};
+
+
+#endif // __SAT_COUNTER_HH__
diff --git a/src/base/sched_list.hh b/src/base/sched_list.hh
new file mode 100644
index 000000000..f794e3514
--- /dev/null
+++ b/src/base/sched_list.hh
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SCHED_LIST_HH
+#define SCHED_LIST_HH
+
+#include <list>
+#include "base/intmath.hh"
+#include "base/misc.hh"
+
+
+// Any types you use this class for must be covered here...
+namespace {
+ void ClearEntry(int &i) { i = 0; };
+ void ClearEntry(unsigned &i) { i = 0; };
+ void ClearEntry(double &i) { i = 0; };
+ template <class T> void ClearEntry(std::list<T> &l) { l.clear(); };
+};
+
+
+//
+// this is a special list type that allows the user to insert elements at a
+// specified positive offset from the "current" element, but only allow them
+// be extracted from the "current" element
+//
+
+
+template <class T>
+class SchedList
+{
+ T *data_array;
+ unsigned position;
+ unsigned size;
+ unsigned mask;
+
+ public:
+ SchedList(unsigned size);
+ SchedList(void);
+
+ void init(unsigned size);
+
+ T &operator[](unsigned offset);
+
+ void advance(void);
+
+ void clear(void);
+};
+
+
+
+//
+// Constructor
+//
+template<class T>
+SchedList<T>::SchedList(unsigned _size)
+{
+ size = _size;
+
+ // size must be a power of two
+ if (!isPowerOf2(size)) {
+ panic("SchedList: size must be a power of two");
+ }
+
+ if (size < 2) {
+ panic("SchedList: you don't want a list that small");
+ }
+
+ // calculate the bit mask for the modulo operation
+ mask = size - 1;
+
+ data_array = new T[size];
+
+ if (!data_array) {
+ panic("SchedList: could not allocate memory");
+ }
+
+ clear();
+}
+
+template<class T>
+SchedList<T>::SchedList(void)
+{
+ data_array = 0;
+ size = 0;
+}
+
+
+template<class T> void
+SchedList<T>::init(unsigned _size)
+{
+ size = _size;
+
+ if (!data_array) {
+ // size must be a power of two
+ if (size & (size-1)) {
+ panic("SchedList: size must be a power of two");
+ }
+
+ if (size < 2) {
+ panic("SchedList: you don't want a list that small");
+ }
+
+ // calculate the bit mask for the modulo operation
+ mask = size - 1;
+
+ data_array = new T[size];
+
+ if (!data_array) {
+ panic("SchedList: could not allocate memory");
+ }
+
+ clear();
+ }
+}
+
+
+template<class T> void
+SchedList<T>::advance(void)
+{
+ ClearEntry(data_array[position]);
+
+ // position = (++position % size);
+ position = ++position & mask;
+}
+
+
+template<class T> void
+SchedList<T>::clear(void)
+{
+ for (unsigned i=0; i<size; ++i) {
+ ClearEntry(data_array[i]);
+ }
+
+ position = 0;
+}
+
+
+template<class T> T&
+SchedList<T>::operator[](unsigned offset)
+{
+ if (offset >= size) {
+ panic("SchedList: can't access element beyond current pointer");
+ }
+
+ // unsigned p = (position + offset) % size;
+ unsigned p = (position + offset) & mask;
+
+ return data_array[p];
+}
+
+
+
+#endif
diff --git a/src/base/socket.cc b/src/base/socket.cc
new file mode 100644
index 000000000..45a60e7e3
--- /dev/null
+++ b/src/base/socket.cc
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#include "sim/host.hh"
+#include "base/misc.hh"
+#include "base/socket.hh"
+
+using namespace std;
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+
+ListenSocket::ListenSocket()
+ : listening(false), fd(-1)
+{}
+
+ListenSocket::~ListenSocket()
+{
+ if (fd != -1)
+ close(fd);
+}
+
+// Create a socket and configure it for listening
+bool
+ListenSocket::listen(int port, bool reuse)
+{
+ if (listening)
+ panic("Socket already listening!");
+
+ fd = ::socket(PF_INET, SOCK_STREAM, 0);
+ if (fd < 0)
+ panic("Can't create socket:%s !", strerror(errno));
+
+ if (reuse) {
+ int i = 1;
+ if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&i,
+ sizeof(i)) < 0)
+ panic("ListenSocket(listen): setsockopt() SO_REUSEADDR failed!");
+ }
+
+ struct sockaddr_in sockaddr;
+ sockaddr.sin_family = PF_INET;
+ sockaddr.sin_addr.s_addr = INADDR_ANY;
+
+ sockaddr.sin_port = htons(port);
+ int ret = ::bind(fd, (struct sockaddr *)&sockaddr, sizeof (sockaddr));
+ if (ret != 0) {
+ if (ret == -1 && errno != EADDRINUSE)
+ panic("ListenSocket(listen): bind() failed!");
+ return false;
+ }
+
+ if (::listen(fd, 1) == -1)
+ panic("ListenSocket(listen): listen() failed!");
+
+ listening = true;
+
+ return true;
+}
+
+
+// Open a connection. Accept will block, so if you don't want it to,
+// make sure a connection is ready before you call accept.
+int
+ListenSocket::accept(bool nodelay)
+{
+ struct sockaddr_in sockaddr;
+ socklen_t slen = sizeof (sockaddr);
+ int sfd = ::accept(fd, (struct sockaddr *)&sockaddr, &slen);
+ if (sfd != -1 && nodelay) {
+ int i = 1;
+ ::setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (char *)&i, sizeof(i));
+ }
+
+ return sfd;
+}
diff --git a/src/base/socket.hh b/src/base/socket.hh
new file mode 100644
index 000000000..848405c09
--- /dev/null
+++ b/src/base/socket.hh
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SOCKET_HH__
+#define __SOCKET_HH__
+
+class ListenSocket
+{
+ protected:
+ bool listening;
+ int fd;
+
+ public:
+ ListenSocket();
+ virtual ~ListenSocket();
+
+ virtual int accept(bool nodelay = false);
+ virtual bool listen(int port, bool reuse = true);
+
+ int getfd() const { return fd; }
+ bool islistening() const { return listening; }
+};
+
+#endif //__SOCKET_HH__
diff --git a/src/base/statistics.cc b/src/base/statistics.cc
new file mode 100644
index 000000000..20de46347
--- /dev/null
+++ b/src/base/statistics.cc
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <iomanip>
+#include <fstream>
+#include <list>
+#include <map>
+#include <string>
+
+#include "base/callback.hh"
+#include "base/cprintf.hh"
+#include "base/hostinfo.hh"
+#include "base/misc.hh"
+#include "base/statistics.hh"
+#include "base/str.hh"
+#include "base/time.hh"
+#include "base/trace.hh"
+#include "base/stats/statdb.hh"
+#include "config/stats_binning.hh"
+
+using namespace std;
+
+namespace Stats {
+
+StatData *
+DataAccess::find() const
+{
+ return Database::find(const_cast<void *>((const void *)this));
+}
+
+const StatData *
+getStatData(const void *stat)
+{
+ return Database::find(const_cast<void *>(stat));
+}
+
+void
+DataAccess::map(StatData *data)
+{
+ Database::regStat(this, data);
+}
+
+StatData *
+DataAccess::statData()
+{
+ StatData *ptr = find();
+ assert(ptr);
+ return ptr;
+}
+
+const StatData *
+DataAccess::statData() const
+{
+ const StatData *ptr = find();
+ assert(ptr);
+ return ptr;
+}
+
+void
+DataAccess::setInit()
+{
+ statData()->flags |= init;
+}
+
+void
+DataAccess::setPrint()
+{
+ Database::regPrint(this);
+}
+
+StatData::StatData()
+ : flags(none), precision(-1), prereq(0)
+{
+ static int count = 0;
+ id = count++;
+}
+
+StatData::~StatData()
+{
+}
+
+bool
+StatData::less(StatData *stat1, StatData *stat2)
+{
+ const string &name1 = stat1->name;
+ const string &name2 = stat2->name;
+
+ vector<string> v1;
+ vector<string> v2;
+
+ tokenize(v1, name1, '.');
+ tokenize(v2, name2, '.');
+
+ int last = min(v1.size(), v2.size()) - 1;
+ for (int i = 0; i < last; ++i)
+ if (v1[i] != v2[i])
+ return v1[i] < v2[i];
+
+ // Special compare for last element.
+ if (v1[last] == v2[last])
+ return v1.size() < v2.size();
+ else
+ return v1[last] < v2[last];
+
+ return false;
+}
+
+bool
+StatData::baseCheck() const
+{
+ if (!(flags & init)) {
+#ifdef DEBUG
+ cprintf("this is stat number %d\n", id);
+#endif
+ panic("Not all stats have been initialized");
+ return false;
+ }
+
+ if ((flags & print) && name.empty()) {
+ panic("all printable stats must be named");
+ return false;
+ }
+
+ return true;
+}
+
+
+void
+FormulaBase::result(VResult &vec) const
+{
+ if (root)
+ vec = root->result();
+}
+
+Result
+FormulaBase::total() const
+{
+ return root ? root->total() : 0.0;
+}
+
+size_t
+FormulaBase::size() const
+{
+ if (!root)
+ return 0;
+ else
+ return root->size();
+}
+
+bool
+FormulaBase::binned() const
+{
+ return root && root->binned();
+}
+
+void
+FormulaBase::reset()
+{
+}
+
+bool
+FormulaBase::zero() const
+{
+ VResult vec;
+ result(vec);
+ for (int i = 0; i < vec.size(); ++i)
+ if (vec[i] != 0.0)
+ return false;
+ return true;
+}
+
+void
+FormulaBase::update(StatData *)
+{
+}
+
+string
+FormulaBase::str() const
+{
+ return root ? root->str() : "";
+}
+
+Formula::Formula()
+{
+ setInit();
+}
+
+Formula::Formula(Temp r)
+{
+ root = r;
+ assert(size());
+}
+
+const Formula &
+Formula::operator=(Temp r)
+{
+ assert(!root && "Can't change formulas");
+ root = r;
+ assert(size());
+ return *this;
+}
+
+const Formula &
+Formula::operator+=(Temp r)
+{
+ if (root)
+ root = NodePtr(new BinaryNode<std::plus<Result> >(root, r));
+ else
+ root = r;
+ assert(size());
+ return *this;
+}
+
+MainBin::MainBin(const string &name)
+ : _name(name), mem(NULL), memsize(-1)
+{
+ Database::regBin(this, name);
+}
+
+MainBin::~MainBin()
+{
+ if (mem)
+ delete [] mem;
+}
+
+char *
+MainBin::memory(off_t off)
+{
+ if (memsize == -1)
+ memsize = ceilPow2((size_t) offset());
+
+ if (!mem) {
+ mem = new char[memsize];
+ memset(mem, 0, memsize);
+ }
+
+ assert(offset() <= size());
+ return mem + off;
+}
+
+void
+check()
+{
+ typedef Database::stat_list_t::iterator iter_t;
+
+ iter_t i, end = Database::stats().end();
+ for (i = Database::stats().begin(); i != end; ++i) {
+ StatData *data = *i;
+ assert(data);
+ if (!data->check() || !data->baseCheck())
+ panic("stat check failed for %s\n", data->name);
+ }
+
+ int j = 0;
+ for (i = Database::stats().begin(); i != end; ++i) {
+ StatData *data = *i;
+ if (!(data->flags & print))
+ data->name = "__Stat" + to_string(j++);
+ }
+
+ Database::stats().sort(StatData::less);
+
+#if STATS_BINNING
+ if (MainBin::curBin() == NULL) {
+ static MainBin mainBin("main bin");
+ mainBin.activate();
+ }
+#endif
+
+ if (i == end)
+ return;
+
+ iter_t last = i;
+ ++i;
+
+ for (i = Database::stats().begin(); i != end; ++i) {
+ if ((*i)->name == (*last)->name)
+ panic("same name used twice! name=%s\n", (*i)->name);
+
+ last = i;
+ }
+}
+
+CallbackQueue resetQueue;
+
+void
+reset()
+{
+ // reset non-binned stats
+ Database::stat_list_t::iterator i = Database::stats().begin();
+ Database::stat_list_t::iterator end = Database::stats().end();
+ while (i != end) {
+ StatData *data = *i;
+ if (!data->binned())
+ data->reset();
+ ++i;
+ }
+
+ // save the bin so we can go back to where we were
+ MainBin *orig = MainBin::curBin();
+
+ // reset binned stats
+ Database::bin_list_t::iterator bi = Database::bins().begin();
+ Database::bin_list_t::iterator be = Database::bins().end();
+ while (bi != be) {
+ MainBin *bin = *bi;
+ bin->activate();
+
+ i = Database::stats().begin();
+ while (i != end) {
+ StatData *data = *i;
+ if (data->binned())
+ data->reset();
+ ++i;
+ }
+ ++bi;
+ }
+
+ // restore bin
+ MainBin::curBin() = orig;
+
+ resetQueue.process();
+}
+
+void
+registerResetCallback(Callback *cb)
+{
+ resetQueue.add(cb);
+}
+
+/* namespace Stats */ }
diff --git a/src/base/statistics.hh b/src/base/statistics.hh
new file mode 100644
index 000000000..dd507c091
--- /dev/null
+++ b/src/base/statistics.hh
@@ -0,0 +1,2896 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Declaration of Statistics objects.
+ */
+
+/**
+* @todo
+*
+* Generalized N-dimensinal vector
+* documentation
+* key stats
+* interval stats
+* -- these both can use the same function that prints out a
+* specific set of stats
+* VectorStandardDeviation totals
+* Document Namespaces
+*/
+#ifndef __BASE_STATISTICS_HH__
+#define __BASE_STATISTICS_HH__
+
+#include <algorithm>
+#include <cassert>
+#include <cmath>
+#include <functional>
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+#include "base/cprintf.hh"
+#include "base/intmath.hh"
+#include "base/refcnt.hh"
+#include "base/str.hh"
+#include "base/stats/bin.hh"
+#include "base/stats/flags.hh"
+#include "base/stats/visit.hh"
+#include "base/stats/types.hh"
+#include "config/stats_binning.hh"
+#include "sim/host.hh"
+
+class Callback;
+
+/** The current simulated cycle. */
+extern Tick curTick;
+
+/* A namespace for all of the Statistics */
+namespace Stats {
+
+/* Contains the statistic implementation details */
+//////////////////////////////////////////////////////////////////////
+//
+// Statistics Framework Base classes
+//
+//////////////////////////////////////////////////////////////////////
+struct StatData
+{
+ /** The name of the stat. */
+ std::string name;
+ /** The description of the stat. */
+ std::string desc;
+ /** The formatting flags. */
+ StatFlags flags;
+ /** The display precision. */
+ int precision;
+ /** A pointer to a prerequisite Stat. */
+ const StatData *prereq;
+ /**
+ * A unique stat ID for each stat in the simulator.
+ * Can be used externally for lookups as well as for debugging.
+ */
+ int id;
+
+ StatData();
+ virtual ~StatData();
+
+ /**
+ * @return true if the stat is binned.
+ */
+ virtual bool binned() const = 0;
+
+ /**
+ * Reset the corresponding stat to the default state.
+ */
+ virtual void reset() = 0;
+
+ /**
+ * @return true if this stat has a value and satisfies its
+ * requirement as a prereq
+ */
+ virtual bool zero() const = 0;
+
+ /**
+ * Check that this stat has been set up properly and is ready for
+ * use
+ * @return true for success
+ */
+ virtual bool check() const = 0;
+ bool baseCheck() const;
+
+ /**
+ * Visitor entry for outputing statistics data
+ */
+ virtual void visit(Visit &visitor) = 0;
+
+ /**
+ * Checks if the first stat's name is alphabetically less than the second.
+ * This function breaks names up at periods and considers each subname
+ * separately.
+ * @param stat1 The first stat.
+ * @param stat2 The second stat.
+ * @return stat1's name is alphabetically before stat2's
+ */
+ static bool less(StatData *stat1, StatData *stat2);
+};
+
+class ScalarData : public StatData
+{
+ public:
+ virtual Counter value() const = 0;
+ virtual Result result() const = 0;
+ virtual Result total() const = 0;
+ virtual void visit(Visit &visitor) { visitor.visit(*this); }
+};
+
+template <class Stat>
+class ScalarStatData : public ScalarData
+{
+ protected:
+ Stat &s;
+
+ public:
+ ScalarStatData(Stat &stat) : s(stat) {}
+
+ virtual bool binned() const { return s.binned(); }
+ virtual bool check() const { return s.check(); }
+ virtual Counter value() const { return s.value(); }
+ virtual Result result() const { return s.result(); }
+ virtual Result total() const { return s.total(); }
+ virtual void reset() { s.reset(); }
+ virtual bool zero() const { return s.zero(); }
+};
+
+struct VectorData : public StatData
+{
+ /** Names and descriptions of subfields. */
+ mutable std::vector<std::string> subnames;
+ mutable std::vector<std::string> subdescs;
+
+ virtual size_t size() const = 0;
+ virtual const VCounter &value() const = 0;
+ virtual const VResult &result() const = 0;
+ virtual Result total() const = 0;
+ void update()
+ {
+ if (!subnames.empty()) {
+ int s = size();
+ if (subnames.size() < s)
+ subnames.resize(s);
+
+ if (subdescs.size() < s)
+ subdescs.resize(s);
+ }
+ }
+};
+
+template <class Stat>
+class VectorStatData : public VectorData
+{
+ protected:
+ Stat &s;
+ mutable VCounter cvec;
+ mutable VResult rvec;
+
+ public:
+ VectorStatData(Stat &stat) : s(stat) {}
+
+ virtual bool binned() const { return s.binned(); }
+ virtual bool check() const { return s.check(); }
+ virtual bool zero() const { return s.zero(); }
+ virtual void reset() { s.reset(); }
+
+ virtual size_t size() const { return s.size(); }
+ virtual VCounter &value() const
+ {
+ s.value(cvec);
+ return cvec;
+ }
+ virtual const VResult &result() const
+ {
+ s.result(rvec);
+ return rvec;
+ }
+ virtual Result total() const { return s.total(); }
+ virtual void visit(Visit &visitor)
+ {
+ update();
+ s.update(this);
+ visitor.visit(*this);
+ }
+};
+
+struct DistDataData
+{
+ Counter min_val;
+ Counter max_val;
+ Counter underflow;
+ Counter overflow;
+ VCounter cvec;
+ Counter sum;
+ Counter squares;
+ Counter samples;
+
+ Counter min;
+ Counter max;
+ Counter bucket_size;
+ int size;
+ bool fancy;
+};
+
+struct DistData : public StatData
+{
+ /** Local storage for the entry values, used for printing. */
+ DistDataData data;
+};
+
+template <class Stat>
+class DistStatData : public DistData
+{
+ protected:
+ Stat &s;
+
+ public:
+ DistStatData(Stat &stat) : s(stat) {}
+
+ virtual bool binned() const { return s.binned(); }
+ virtual bool check() const { return s.check(); }
+ virtual void reset() { s.reset(); }
+ virtual bool zero() const { return s.zero(); }
+ virtual void visit(Visit &visitor)
+ {
+ s.update(this);
+ visitor.visit(*this);
+ }
+};
+
+struct VectorDistData : public StatData
+{
+ std::vector<DistDataData> data;
+
+ /** Names and descriptions of subfields. */
+ mutable std::vector<std::string> subnames;
+ mutable std::vector<std::string> subdescs;
+
+ /** Local storage for the entry values, used for printing. */
+ mutable VResult rvec;
+
+ virtual size_t size() const = 0;
+ void update()
+ {
+ int s = size();
+ if (subnames.size() < s)
+ subnames.resize(s);
+
+ if (subdescs.size() < s)
+ subdescs.resize(s);
+ }
+};
+
+template <class Stat>
+class VectorDistStatData : public VectorDistData
+{
+ protected:
+ Stat &s;
+ typedef typename Stat::bin_t bin_t;
+
+ public:
+ VectorDistStatData(Stat &stat) : s(stat) {}
+
+ virtual bool binned() const { return bin_t::binned; }
+ virtual bool check() const { return s.check(); }
+ virtual void reset() { s.reset(); }
+ virtual size_t size() const { return s.size(); }
+ virtual bool zero() const { return s.zero(); }
+ virtual void visit(Visit &visitor)
+ {
+ update();
+ s.update(this);
+ visitor.visit(*this);
+ }
+};
+
+struct Vector2dData : public StatData
+{
+ /** Names and descriptions of subfields. */
+ std::vector<std::string> subnames;
+ std::vector<std::string> subdescs;
+ std::vector<std::string> y_subnames;
+
+ /** Local storage for the entry values, used for printing. */
+ mutable VCounter cvec;
+ mutable int x;
+ mutable int y;
+
+ void update()
+ {
+ if (subnames.size() < x)
+ subnames.resize(x);
+ }
+};
+
+template <class Stat>
+class Vector2dStatData : public Vector2dData
+{
+ protected:
+ Stat &s;
+ typedef typename Stat::bin_t bin_t;
+
+ public:
+ Vector2dStatData(Stat &stat) : s(stat) {}
+
+ virtual bool binned() const { return bin_t::binned; }
+ virtual bool check() const { return s.check(); }
+ virtual void reset() { s.reset(); }
+ virtual bool zero() const { return s.zero(); }
+ virtual void visit(Visit &visitor)
+ {
+ update();
+ s.update(this);
+ visitor.visit(*this);
+ }
+};
+
+
+class DataAccess
+{
+ protected:
+ StatData *find() const;
+ void map(StatData *data);
+
+ StatData *statData();
+ const StatData *statData() const;
+
+ void setInit();
+ void setPrint();
+};
+
+template <class Parent, class Child, template <class> class Data>
+class Wrap : public Child
+{
+ protected:
+ Parent &self() { return *reinterpret_cast<Parent *>(this); }
+
+ protected:
+ Data<Child> *statData()
+ {
+ StatData *__data = DataAccess::statData();
+ Data<Child> *ptr = dynamic_cast<Data<Child> *>(__data);
+ assert(ptr);
+ return ptr;
+ }
+
+ public:
+ const Data<Child> *statData() const
+ {
+ const StatData *__data = DataAccess::statData();
+ const Data<Child> *ptr = dynamic_cast<const Data<Child> *>(__data);
+ assert(ptr);
+ return ptr;
+ }
+
+ protected:
+ /**
+ * Copy constructor, copies are not allowed.
+ */
+ Wrap(const Wrap &stat);
+ /**
+ * Can't copy stats.
+ */
+ void operator=(const Wrap &);
+
+ public:
+ Wrap()
+ {
+ map(new Data<Child>(*this));
+ }
+
+ /**
+ * Set the name and marks this stat to print at the end of simulation.
+ * @param name The new name.
+ * @return A reference to this stat.
+ */
+ Parent &name(const std::string &_name)
+ {
+ Data<Child> *data = this->statData();
+ data->name = _name;
+ this->setPrint();
+ return this->self();
+ }
+
+ /**
+ * Set the description and marks this stat to print at the end of
+ * simulation.
+ * @param desc The new description.
+ * @return A reference to this stat.
+ */
+ Parent &desc(const std::string &_desc)
+ {
+ this->statData()->desc = _desc;
+ return this->self();
+ }
+
+ /**
+ * Set the precision and marks this stat to print at the end of simulation.
+ * @param p The new precision
+ * @return A reference to this stat.
+ */
+ Parent &precision(int _precision)
+ {
+ this->statData()->precision = _precision;
+ return this->self();
+ }
+
+ /**
+ * Set the flags and marks this stat to print at the end of simulation.
+ * @param f The new flags.
+ * @return A reference to this stat.
+ */
+ Parent &flags(StatFlags _flags)
+ {
+ this->statData()->flags |= _flags;
+ return this->self();
+ }
+
+ /**
+ * Set the prerequisite stat and marks this stat to print at the end of
+ * simulation.
+ * @param prereq The prerequisite stat.
+ * @return A reference to this stat.
+ */
+ template <class Stat>
+ Parent &prereq(const Stat &prereq)
+ {
+ this->statData()->prereq = prereq.statData();
+ return this->self();
+ }
+};
+
+template <class Parent, class Child, template <class Child> class Data>
+class WrapVec : public Wrap<Parent, Child, Data>
+{
+ public:
+ // The following functions are specific to vectors. If you use them
+ // in a non vector context, you will get a nice compiler error!
+
+ /**
+ * Set the subfield name for the given index, and marks this stat to print
+ * at the end of simulation.
+ * @param index The subfield index.
+ * @param name The new name of the subfield.
+ * @return A reference to this stat.
+ */
+ Parent &subname(int index, const std::string &name)
+ {
+ std::vector<std::string> &subn = this->statData()->subnames;
+ if (subn.size() <= index)
+ subn.resize(index + 1);
+ subn[index] = name;
+ return this->self();
+ }
+
+ /**
+ * Set the subfield description for the given index and marks this stat to
+ * print at the end of simulation.
+ * @param index The subfield index.
+ * @param desc The new description of the subfield
+ * @return A reference to this stat.
+ */
+ Parent &subdesc(int index, const std::string &desc)
+ {
+ std::vector<std::string> &subd = this->statData()->subdescs;
+ if (subd.size() <= index)
+ subd.resize(index + 1);
+ subd[index] = desc;
+
+ return this->self();
+ }
+
+};
+
+template <class Parent, class Child, template <class Child> class Data>
+class WrapVec2d : public WrapVec<Parent, Child, Data>
+{
+ public:
+ /**
+ * @warning This makes the assumption that if you're gonna subnames a 2d
+ * vector, you're subnaming across all y
+ */
+ Parent &ysubnames(const char **names)
+ {
+ Data<Child> *data = this->statData();
+ data->y_subnames.resize(this->y);
+ for (int i = 0; i < this->y; ++i)
+ data->y_subnames[i] = names[i];
+ return this->self();
+ }
+ Parent &ysubname(int index, const std::string subname)
+ {
+ Data<Child> *data = this->statData();
+ assert(index < this->y);
+ data->y_subnames.resize(this->y);
+ data->y_subnames[index] = subname.c_str();
+ return this->self();
+ }
+};
+
+//////////////////////////////////////////////////////////////////////
+//
+// Simple Statistics
+//
+//////////////////////////////////////////////////////////////////////
+
+/**
+ * Templatized storage and interface for a simple scalar stat.
+ */
+struct StatStor
+{
+ public:
+ /** The paramaters for this storage type, none for a scalar. */
+ struct Params { };
+
+ private:
+ /** The statistic value. */
+ Counter data;
+
+ public:
+ /**
+ * Builds this storage element and calls the base constructor of the
+ * datatype.
+ */
+ StatStor(const Params &) : data(Counter()) {}
+
+ /**
+ * The the stat to the given value.
+ * @param val The new value.
+ * @param p The paramters of this storage type.
+ */
+ void set(Counter val, const Params &p) { data = val; }
+ /**
+ * Increment the stat by the given value.
+ * @param val The new value.
+ * @param p The paramters of this storage type.
+ */
+ void inc(Counter val, const Params &p) { data += val; }
+ /**
+ * Decrement the stat by the given value.
+ * @param val The new value.
+ * @param p The paramters of this storage type.
+ */
+ void dec(Counter val, const Params &p) { data -= val; }
+ /**
+ * Return the value of this stat as its base type.
+ * @param p The params of this storage type.
+ * @return The value of this stat.
+ */
+ Counter value(const Params &p) const { return data; }
+ /**
+ * Return the value of this stat as a result type.
+ * @param p The parameters of this storage type.
+ * @return The value of this stat.
+ */
+ Result result(const Params &p) const { return (Result)data; }
+ /**
+ * Reset stat value to default
+ */
+ void reset() { data = Counter(); }
+
+ /**
+ * @return true if zero value
+ */
+ bool zero() const { return data == Counter(); }
+};
+
+/**
+ * Templatized storage and interface to a per-cycle average stat. This keeps
+ * a current count and updates a total (count * cycles) when this count
+ * changes. This allows the quick calculation of a per cycle count of the item
+ * being watched. This is good for keeping track of residencies in structures
+ * among other things.
+ * @todo add lateny to the stat and fix binning.
+ */
+struct AvgStor
+{
+ public:
+ /** The paramaters for this storage type */
+ struct Params
+ {
+ /**
+ * The current count. We stash this here because the current
+ * value is not a binned value.
+ */
+ Counter current;
+ };
+
+ private:
+ /** The total count for all cycles. */
+ mutable Result total;
+ /** The cycle that current last changed. */
+ mutable Tick last;
+
+ public:
+ /**
+ * Build and initializes this stat storage.
+ */
+ AvgStor(Params &p) : total(0), last(0) { p.current = Counter(); }
+
+ /**
+ * Set the current count to the one provided, update the total and last
+ * set values.
+ * @param val The new count.
+ * @param p The parameters for this storage.
+ */
+ void set(Counter val, Params &p) {
+ total += p.current * (curTick - last);
+ last = curTick;
+ p.current = val;
+ }
+
+ /**
+ * Increment the current count by the provided value, calls set.
+ * @param val The amount to increment.
+ * @param p The parameters for this storage.
+ */
+ void inc(Counter val, Params &p) { set(p.current + val, p); }
+
+ /**
+ * Deccrement the current count by the provided value, calls set.
+ * @param val The amount to decrement.
+ * @param p The parameters for this storage.
+ */
+ void dec(Counter val, Params &p) { set(p.current - val, p); }
+
+ /**
+ * Return the current count.
+ * @param p The parameters for this storage.
+ * @return The current count.
+ */
+ Counter value(const Params &p) const { return p.current; }
+
+ /**
+ * Return the current average.
+ * @param p The parameters for this storage.
+ * @return The current average.
+ */
+ Result result(const Params &p) const
+ {
+ total += p.current * (curTick - last);
+ last = curTick;
+ return (Result)(total + p.current) / (Result)(curTick + 1);
+ }
+
+ /**
+ * Reset stat value to default
+ */
+ void reset()
+ {
+ total = 0;
+ last = curTick;
+ }
+
+ /**
+ * @return true if zero value
+ */
+ bool zero() const { return total == 0.0; }
+};
+
+/**
+ * Implementation of a scalar stat. The type of stat is determined by the
+ * Storage template. The storage for this stat is held within the Bin class.
+ * This allows for breaking down statistics across multiple bins easily.
+ */
+template <class Storage, class Bin>
+class ScalarBase : public DataAccess
+{
+ public:
+ /** Define the params of the storage class. */
+ typedef typename Storage::Params params_t;
+ /** Define the bin type. */
+ typedef typename Bin::template Bin<Storage> bin_t;
+
+ protected:
+ /** The bin of this stat. */
+ bin_t bin;
+ /** The parameters for this stat. */
+ params_t params;
+
+ protected:
+ /**
+ * Retrieve the storage from the bin.
+ * @return The storage object for this stat.
+ */
+ Storage *data() { return bin.data(params); }
+ /**
+ * Retrieve a const pointer to the storage from the bin.
+ * @return A const pointer to the storage object for this stat.
+ */
+ const Storage *data() const
+ {
+ bin_t *_bin = const_cast<bin_t *>(&bin);
+ params_t *_params = const_cast<params_t *>(&params);
+ return _bin->data(*_params);
+ }
+
+ public:
+ /**
+ * Return the current value of this stat as its base type.
+ * @return The current value.
+ */
+ Counter value() const { return data()->value(params); }
+
+ public:
+ /**
+ * Create and initialize this stat, register it with the database.
+ */
+ ScalarBase()
+ {
+ bin.init(params);
+ }
+
+ public:
+ // Common operators for stats
+ /**
+ * Increment the stat by 1. This calls the associated storage object inc
+ * function.
+ */
+ void operator++() { data()->inc(1, params); }
+ /**
+ * Decrement the stat by 1. This calls the associated storage object dec
+ * function.
+ */
+ void operator--() { data()->dec(1, params); }
+
+ /** Increment the stat by 1. */
+ void operator++(int) { ++*this; }
+ /** Decrement the stat by 1. */
+ void operator--(int) { --*this; }
+
+ /**
+ * Set the data value to the given value. This calls the associated storage
+ * object set function.
+ * @param v The new value.
+ */
+ template <typename U>
+ void operator=(const U &v) { data()->set(v, params); }
+
+ /**
+ * Increment the stat by the given value. This calls the associated
+ * storage object inc function.
+ * @param v The value to add.
+ */
+ template <typename U>
+ void operator+=(const U &v) { data()->inc(v, params); }
+
+ /**
+ * Decrement the stat by the given value. This calls the associated
+ * storage object dec function.
+ * @param v The value to substract.
+ */
+ template <typename U>
+ void operator-=(const U &v) { data()->dec(v, params); }
+
+ /**
+ * Return the number of elements, always 1 for a scalar.
+ * @return 1.
+ */
+ size_t size() const { return 1; }
+ /**
+ * Return true if stat is binned.
+ *@return True is stat is binned.
+ */
+ bool binned() const { return bin_t::binned; }
+
+ bool check() const { return bin.initialized(); }
+
+ /**
+ * Reset stat value to default
+ */
+ void reset() { bin.reset(); }
+
+ Counter value() { return data()->value(params); }
+
+ Result result() { return data()->result(params); }
+
+ Result total() { return result(); }
+
+ bool zero() { return result() == 0.0; }
+
+};
+
+class ProxyData : public ScalarData
+{
+ public:
+ virtual void visit(Visit &visitor) { visitor.visit(*this); }
+ virtual bool binned() const { return false; }
+ virtual std::string str() const { return to_string(value()); }
+ virtual size_t size() const { return 1; }
+ virtual bool zero() const { return value() == 0; }
+ virtual bool check() const { return true; }
+ virtual void reset() { }
+};
+
+template <class T>
+class ValueProxy : public ProxyData
+{
+ private:
+ T *scalar;
+
+ public:
+ ValueProxy(T &val) : scalar(&val) {}
+ virtual Counter value() const { return *scalar; }
+ virtual Result result() const { return *scalar; }
+ virtual Result total() const { return *scalar; }
+};
+
+template <class T>
+class FunctorProxy : public ProxyData
+{
+ private:
+ T *functor;
+
+ public:
+ FunctorProxy(T &func) : functor(&func) {}
+ virtual Counter value() const { return (*functor)(); }
+ virtual Result result() const { return (*functor)(); }
+ virtual Result total() const { return (*functor)(); }
+};
+
+class ValueBase : public DataAccess
+{
+ private:
+ ProxyData *proxy;
+
+ public:
+ ValueBase() : proxy(NULL) { }
+ ~ValueBase() { if (proxy) delete proxy; }
+
+ template <class T>
+ void scalar(T &value)
+ {
+ proxy = new ValueProxy<T>(value);
+ setInit();
+ }
+
+ template <class T>
+ void functor(T &func)
+ {
+ proxy = new FunctorProxy<T>(func);
+ setInit();
+ }
+
+ Counter value() { return proxy->value(); }
+ Result result() const { return proxy->result(); }
+ Result total() const { return proxy->total(); };
+ size_t size() const { return proxy->size(); }
+
+ bool binned() const { return proxy->binned(); }
+ std::string str() const { return proxy->str(); }
+ bool zero() const { return proxy->zero(); }
+ bool check() const { return proxy != NULL; }
+ void reset() { }
+};
+
+//////////////////////////////////////////////////////////////////////
+//
+// Vector Statistics
+//
+//////////////////////////////////////////////////////////////////////
+template <class Storage, class Bin>
+class ScalarProxy;
+
+/**
+ * Implementation of a vector of stats. The type of stat is determined by the
+ * Storage class. @sa ScalarBase
+ */
+template <class Storage, class Bin>
+class VectorBase : public DataAccess
+{
+ public:
+ /** Define the params of the storage class. */
+ typedef typename Storage::Params params_t;
+ /** Define the bin type. */
+ typedef typename Bin::template VectorBin<Storage> bin_t;
+
+ protected:
+ /** The bin of this stat. */
+ bin_t bin;
+ /** The parameters for this stat. */
+ params_t params;
+
+ protected:
+ /**
+ * Retrieve the storage from the bin for the given index.
+ * @param index The vector index to access.
+ * @return The storage object at the given index.
+ */
+ Storage *data(int index) { return bin.data(index, params); }
+ /**
+ * Retrieve a const pointer to the storage from the bin
+ * for the given index.
+ * @param index The vector index to access.
+ * @return A const pointer to the storage object at the given index.
+ */
+ const Storage *data(int index) const
+ {
+ bin_t *_bin = const_cast<bin_t *>(&bin);
+ params_t *_params = const_cast<params_t *>(&params);
+ return _bin->data(index, *_params);
+ }
+
+ public:
+ void value(VCounter &vec) const
+ {
+ vec.resize(size());
+ for (int i = 0; i < size(); ++i)
+ vec[i] = data(i)->value(params);
+ }
+
+ /**
+ * Copy the values to a local vector and return a reference to it.
+ * @return A reference to a vector of the stat values.
+ */
+ void result(VResult &vec) const
+ {
+ vec.resize(size());
+ for (int i = 0; i < size(); ++i)
+ vec[i] = data(i)->result(params);
+ }
+
+ /**
+ * @return True is stat is binned.
+ */
+ bool binned() const { return bin_t::binned; }
+
+ /**
+ * Return a total of all entries in this vector.
+ * @return The total of all vector entries.
+ */
+ Result total() const {
+ Result total = 0.0;
+ for (int i = 0; i < size(); ++i)
+ total += data(i)->result(params);
+ return total;
+ }
+
+ /**
+ * @return the number of elements in this vector.
+ */
+ size_t size() const { return bin.size(); }
+
+ bool zero() const
+ {
+ for (int i = 0; i < size(); ++i)
+ if (data(i)->zero())
+ return true;
+ return false;
+ }
+
+ bool check() const { return bin.initialized(); }
+ void reset() { bin.reset(); }
+
+ public:
+ VectorBase() {}
+
+ /** Friend this class with the associated scalar proxy. */
+ friend class ScalarProxy<Storage, Bin>;
+
+ /**
+ * Return a reference (ScalarProxy) to the stat at the given index.
+ * @param index The vector index to access.
+ * @return A reference of the stat.
+ */
+ ScalarProxy<Storage, Bin> operator[](int index);
+
+ void update(StatData *data) {}
+};
+
+const StatData * getStatData(const void *stat);
+
+/**
+ * A proxy class to access the stat at a given index in a VectorBase stat.
+ * Behaves like a ScalarBase.
+ */
+template <class Storage, class Bin>
+class ScalarProxy
+{
+ public:
+ /** Define the params of the storage class. */
+ typedef typename Storage::Params params_t;
+ /** Define the bin type. */
+ typedef typename Bin::template VectorBin<Storage> bin_t;
+
+ private:
+ /** Pointer to the bin in the parent VectorBase. */
+ bin_t *bin;
+ /** Pointer to the params in the parent VectorBase. */
+ params_t *params;
+ /** The index to access in the parent VectorBase. */
+ int index;
+ /** Keep a pointer to the original stat so was can get data */
+ void *stat;
+
+ protected:
+ /**
+ * Retrieve the storage from the bin.
+ * @return The storage from the bin for this stat.
+ */
+ Storage *data() { return bin->data(index, *params); }
+ /**
+ * Retrieve a const pointer to the storage from the bin.
+ * @return A const pointer to the storage for this stat.
+ */
+ const Storage *data() const
+ {
+ bin_t *_bin = const_cast<bin_t *>(bin);
+ params_t *_params = const_cast<params_t *>(params);
+ return _bin->data(index, *_params);
+ }
+
+ public:
+ /**
+ * Return the current value of this stat as its base type.
+ * @return The current value.
+ */
+ Counter value() const { return data()->value(*params); }
+
+ /**
+ * Return the current value of this statas a result type.
+ * @return The current value.
+ */
+ Result result() const { return data()->result(*params); }
+
+ public:
+ /**
+ * Create and initialize this proxy, do not register it with the database.
+ * @param b The bin to use.
+ * @param p The params to use.
+ * @param i The index to access.
+ */
+ ScalarProxy(bin_t &b, params_t &p, int i, void *s)
+ : bin(&b), params(&p), index(i), stat(s) {}
+ /**
+ * Create a copy of the provided ScalarProxy.
+ * @param sp The proxy to copy.
+ */
+ ScalarProxy(const ScalarProxy &sp)
+ : bin(sp.bin), params(sp.params), index(sp.index), stat(sp.stat) {}
+ /**
+ * Set this proxy equal to the provided one.
+ * @param sp The proxy to copy.
+ * @return A reference to this proxy.
+ */
+ const ScalarProxy &operator=(const ScalarProxy &sp) {
+ bin = sp.bin;
+ params = sp.params;
+ index = sp.index;
+ stat = sp.stat;
+ return *this;
+ }
+
+ public:
+ // Common operators for stats
+ /**
+ * Increment the stat by 1. This calls the associated storage object inc
+ * function.
+ */
+ void operator++() { data()->inc(1, *params); }
+ /**
+ * Decrement the stat by 1. This calls the associated storage object dec
+ * function.
+ */
+ void operator--() { data()->dec(1, *params); }
+
+ /** Increment the stat by 1. */
+ void operator++(int) { ++*this; }
+ /** Decrement the stat by 1. */
+ void operator--(int) { --*this; }
+
+ /**
+ * Set the data value to the given value. This calls the associated storage
+ * object set function.
+ * @param v The new value.
+ */
+ template <typename U>
+ void operator=(const U &v) { data()->set(v, *params); }
+
+ /**
+ * Increment the stat by the given value. This calls the associated
+ * storage object inc function.
+ * @param v The value to add.
+ */
+ template <typename U>
+ void operator+=(const U &v) { data()->inc(v, *params); }
+
+ /**
+ * Decrement the stat by the given value. This calls the associated
+ * storage object dec function.
+ * @param v The value to substract.
+ */
+ template <typename U>
+ void operator-=(const U &v) { data()->dec(v, *params); }
+
+ /**
+ * Return the number of elements, always 1 for a scalar.
+ * @return 1.
+ */
+ size_t size() const { return 1; }
+
+ /**
+ * Return true if stat is binned.
+ *@return false since Proxies aren't printed/binned
+ */
+ bool binned() const { return false; }
+
+ /**
+ * This stat has no state. Nothing to reset
+ */
+ void reset() { }
+
+ public:
+ const StatData *statData() const { return getStatData(stat); }
+ std::string str() const
+ {
+ return csprintf("%s[%d]", this->statData()->name, index);
+
+ }
+};
+
+template <class Storage, class Bin>
+inline ScalarProxy<Storage, Bin>
+VectorBase<Storage, Bin>::operator[](int index)
+{
+ assert (index >= 0 && index < size());
+ return ScalarProxy<Storage, Bin>(bin, params, index, this);
+}
+
+template <class Storage, class Bin>
+class VectorProxy;
+
+template <class Storage, class Bin>
+class Vector2dBase : public DataAccess
+{
+ public:
+ typedef typename Storage::Params params_t;
+ typedef typename Bin::template VectorBin<Storage> bin_t;
+
+ protected:
+ size_t x;
+ size_t y;
+ bin_t bin;
+ params_t params;
+
+ protected:
+ Storage *data(int index) { return bin.data(index, params); }
+ const Storage *data(int index) const
+ {
+ bin_t *_bin = const_cast<bin_t *>(&bin);
+ params_t *_params = const_cast<params_t *>(&params);
+ return _bin->data(index, *_params);
+ }
+
+ public:
+ Vector2dBase() {}
+
+ void update(Vector2dData *data)
+ {
+ int size = this->size();
+ data->cvec.resize(size);
+ for (int i = 0; i < size; ++i)
+ data->cvec[i] = this->data(i)->value(params);
+ }
+
+ std::string ysubname(int i) const { return (*this->y_subnames)[i]; }
+
+ friend class VectorProxy<Storage, Bin>;
+ VectorProxy<Storage, Bin> operator[](int index);
+
+ size_t size() const { return bin.size(); }
+ bool zero() const { return data(0)->value(params) == 0.0; }
+
+ /**
+ * Reset stat value to default
+ */
+ void reset() { bin.reset(); }
+
+ bool check() { return bin.initialized(); }
+};
+
+template <class Storage, class Bin>
+class VectorProxy
+{
+ public:
+ typedef typename Storage::Params params_t;
+ typedef typename Bin::template VectorBin<Storage> bin_t;
+
+ private:
+ bin_t *bin;
+ params_t *params;
+ int offset;
+ int len;
+ void *stat;
+
+ private:
+ mutable VResult *vec;
+
+ Storage *data(int index) {
+ assert(index < len);
+ return bin->data(offset + index, *params);
+ }
+
+ const Storage *data(int index) const {
+ bin_t *_bin = const_cast<bin_t *>(bin);
+ params_t *_params = const_cast<params_t *>(params);
+ return _bin->data(offset + index, *_params);
+ }
+
+ public:
+ const VResult &result() const {
+ if (vec)
+ vec->resize(size());
+ else
+ vec = new VResult(size());
+
+ for (int i = 0; i < size(); ++i)
+ (*vec)[i] = data(i)->result(*params);
+
+ return *vec;
+ }
+
+ Result total() const {
+ Result total = 0.0;
+ for (int i = 0; i < size(); ++i)
+ total += data(i)->result(*params);
+ return total;
+ }
+
+ public:
+ VectorProxy(bin_t &b, params_t &p, int o, int l, void *s)
+ : bin(&b), params(&p), offset(o), len(l), stat(s), vec(NULL)
+ {
+ }
+
+ VectorProxy(const VectorProxy &sp)
+ : bin(sp.bin), params(sp.params), offset(sp.offset), len(sp.len),
+ stat(sp.stat), vec(NULL)
+ {
+ }
+
+ ~VectorProxy()
+ {
+ if (vec)
+ delete vec;
+ }
+
+ const VectorProxy &operator=(const VectorProxy &sp)
+ {
+ bin = sp.bin;
+ params = sp.params;
+ offset = sp.offset;
+ len = sp.len;
+ stat = sp.stat;
+ if (vec)
+ delete vec;
+ vec = NULL;
+ return *this;
+ }
+
+ ScalarProxy<Storage, Bin> operator[](int index)
+ {
+ assert (index >= 0 && index < size());
+ return ScalarProxy<Storage, Bin>(*bin, *params, offset + index, stat);
+ }
+
+ size_t size() const { return len; }
+
+ /**
+ * Return true if stat is binned.
+ *@return false since Proxies aren't printed/binned
+ */
+ bool binned() const { return false; }
+
+ /**
+ * This stat has no state. Nothing to reset.
+ */
+ void reset() { }
+};
+
+template <class Storage, class Bin>
+inline VectorProxy<Storage, Bin>
+Vector2dBase<Storage, Bin>::operator[](int index)
+{
+ int offset = index * y;
+ assert (index >= 0 && offset < size());
+ return VectorProxy<Storage, Bin>(bin, params, offset, y, this);
+}
+
+//////////////////////////////////////////////////////////////////////
+//
+// Non formula statistics
+//
+//////////////////////////////////////////////////////////////////////
+
+/**
+ * Templatized storage and interface for a distrbution stat.
+ */
+struct DistStor
+{
+ public:
+ /** The parameters for a distribution stat. */
+ struct Params
+ {
+ /** The minimum value to track. */
+ Counter min;
+ /** The maximum value to track. */
+ Counter max;
+ /** The number of entries in each bucket. */
+ Counter bucket_size;
+ /** The number of buckets. Equal to (max-min)/bucket_size. */
+ int size;
+ };
+ enum { fancy = false };
+
+ private:
+ /** The smallest value sampled. */
+ Counter min_val;
+ /** The largest value sampled. */
+ Counter max_val;
+ /** The number of values sampled less than min. */
+ Counter underflow;
+ /** The number of values sampled more than max. */
+ Counter overflow;
+ /** The current sum. */
+ Counter sum;
+ /** The sum of squares. */
+ Counter squares;
+ /** The number of samples. */
+ Counter samples;
+ /** Counter for each bucket. */
+ VCounter cvec;
+
+ public:
+ /**
+ * Construct this storage with the supplied params.
+ * @param params The parameters.
+ */
+ DistStor(const Params &params)
+ : min_val(INT_MAX), max_val(INT_MIN), underflow(Counter()),
+ overflow(Counter()), sum(Counter()), squares(Counter()),
+ samples(Counter()), cvec(params.size)
+ {
+ reset();
+ }
+
+ /**
+ * Add a value to the distribution for the given number of times.
+ * @param val The value to add.
+ * @param number The number of times to add the value.
+ * @param params The paramters of the distribution.
+ */
+ void sample(Counter val, int number, const Params &params)
+ {
+ if (val < params.min)
+ underflow += number;
+ else if (val > params.max)
+ overflow += number;
+ else {
+ int index = (int)floor((val - params.min) / params.bucket_size);
+ assert(index < size(params));
+ cvec[index] += number;
+ }
+
+ if (val < min_val)
+ min_val = val;
+
+ if (val > max_val)
+ max_val = val;
+
+ Counter sample = val * number;
+ sum += sample;
+ squares += sample * sample;
+ samples += number;
+ }
+
+ /**
+ * Return the number of buckets in this distribution.
+ * @return the number of buckets.
+ * @todo Is it faster to return the size from the parameters?
+ */
+ size_t size(const Params &) const { return cvec.size(); }
+
+ /**
+ * Returns true if any calls to sample have been made.
+ * @param params The paramters of the distribution.
+ * @return True if any values have been sampled.
+ */
+ bool zero(const Params &params) const
+ {
+ return samples == Counter();
+ }
+
+ void update(DistDataData *data, const Params &params)
+ {
+ data->min = params.min;
+ data->max = params.max;
+ data->bucket_size = params.bucket_size;
+ data->size = params.size;
+
+ data->min_val = (min_val == INT_MAX) ? 0 : min_val;
+ data->max_val = (max_val == INT_MIN) ? 0 : max_val;
+ data->underflow = underflow;
+ data->overflow = overflow;
+ data->cvec.resize(params.size);
+ for (int i = 0; i < params.size; ++i)
+ data->cvec[i] = cvec[i];
+
+ data->sum = sum;
+ data->squares = squares;
+ data->samples = samples;
+ }
+
+ /**
+ * Reset stat value to default
+ */
+ void reset()
+ {
+ min_val = INT_MAX;
+ max_val = INT_MIN;
+ underflow = 0;
+ overflow = 0;
+
+ int size = cvec.size();
+ for (int i = 0; i < size; ++i)
+ cvec[i] = Counter();
+
+ sum = Counter();
+ squares = Counter();
+ samples = Counter();
+ }
+};
+
+/**
+ * Templatized storage and interface for a distribution that calculates mean
+ * and variance.
+ */
+struct FancyStor
+{
+ public:
+ /**
+ * No paramters for this storage.
+ */
+ struct Params {};
+ enum { fancy = true };
+
+ private:
+ /** The current sum. */
+ Counter sum;
+ /** The sum of squares. */
+ Counter squares;
+ /** The number of samples. */
+ Counter samples;
+
+ public:
+ /**
+ * Create and initialize this storage.
+ */
+ FancyStor(const Params &)
+ : sum(Counter()), squares(Counter()), samples(Counter())
+ { }
+
+ /**
+ * Add a value the given number of times to this running average.
+ * Update the running sum and sum of squares, increment the number of
+ * values seen by the given number.
+ * @param val The value to add.
+ * @param number The number of times to add the value.
+ * @param p The parameters of this stat.
+ */
+ void sample(Counter val, int number, const Params &p)
+ {
+ Counter value = val * number;
+ sum += value;
+ squares += value * value;
+ samples += number;
+ }
+
+ void update(DistDataData *data, const Params &params)
+ {
+ data->sum = sum;
+ data->squares = squares;
+ data->samples = samples;
+ }
+
+ /**
+ * Return the number of entries in this stat, 1
+ * @return 1.
+ */
+ size_t size(const Params &) const { return 1; }
+
+ /**
+ * Return true if no samples have been added.
+ * @return True if no samples have been added.
+ */
+ bool zero(const Params &) const { return samples == Counter(); }
+
+ /**
+ * Reset stat value to default
+ */
+ void reset()
+ {
+ sum = Counter();
+ squares = Counter();
+ samples = Counter();
+ }
+};
+
+/**
+ * Templatized storage for distribution that calculates per cycle mean and
+ * variance.
+ */
+struct AvgFancy
+{
+ public:
+ /** No parameters for this storage. */
+ struct Params {};
+ enum { fancy = true };
+
+ private:
+ /** Current total. */
+ Counter sum;
+ /** Current sum of squares. */
+ Counter squares;
+
+ public:
+ /**
+ * Create and initialize this storage.
+ */
+ AvgFancy(const Params &) : sum(Counter()), squares(Counter()) {}
+
+ /**
+ * Add a value to the distribution for the given number of times.
+ * Update the running sum and sum of squares.
+ * @param val The value to add.
+ * @param number The number of times to add the value.
+ * @param p The paramters of the distribution.
+ */
+ void sample(Counter val, int number, const Params &p)
+ {
+ Counter value = val * number;
+ sum += value;
+ squares += value * value;
+ }
+
+ void update(DistDataData *data, const Params &params)
+ {
+ data->sum = sum;
+ data->squares = squares;
+ data->samples = curTick;
+ }
+
+ /**
+ * Return the number of entries, in this case 1.
+ * @return 1.
+ */
+ size_t size(const Params &params) const { return 1; }
+ /**
+ * Return true if no samples have been added.
+ * @return True if the sum is zero.
+ */
+ bool zero(const Params &params) const { return sum == Counter(); }
+ /**
+ * Reset stat value to default
+ */
+ void reset()
+ {
+ sum = Counter();
+ squares = Counter();
+ }
+};
+
+/**
+ * Implementation of a distribution stat. The type of distribution is
+ * determined by the Storage template. @sa ScalarBase
+ */
+template <class Storage, class Bin>
+class DistBase : public DataAccess
+{
+ public:
+ /** Define the params of the storage class. */
+ typedef typename Storage::Params params_t;
+ /** Define the bin type. */
+ typedef typename Bin::template Bin<Storage> bin_t;
+
+ protected:
+ /** The bin of this stat. */
+ bin_t bin;
+ /** The parameters for this stat. */
+ params_t params;
+
+ protected:
+ /**
+ * Retrieve the storage from the bin.
+ * @return The storage object for this stat.
+ */
+ Storage *data() { return bin.data(params); }
+ /**
+ * Retrieve a const pointer to the storage from the bin.
+ * @return A const pointer to the storage object for this stat.
+ */
+ const Storage *data() const
+ {
+ bin_t *_bin = const_cast<bin_t *>(&bin);
+ params_t *_params = const_cast<params_t *>(&params);
+ return _bin->data(*_params);
+ }
+
+ public:
+ DistBase() { }
+
+ /**
+ * Add a value to the distribtion n times. Calls sample on the storage
+ * class.
+ * @param v The value to add.
+ * @param n The number of times to add it, defaults to 1.
+ */
+ template <typename U>
+ void sample(const U &v, int n = 1) { data()->sample(v, n, params); }
+
+ /**
+ * Return the number of entries in this stat.
+ * @return The number of entries.
+ */
+ size_t size() const { return data()->size(params); }
+ /**
+ * Return true if no samples have been added.
+ * @return True if there haven't been any samples.
+ */
+ bool zero() const { return data()->zero(params); }
+
+ void update(DistData *base)
+ {
+ base->data.fancy = Storage::fancy;
+ data()->update(&(base->data), params);
+ }
+ /**
+ * @return True is stat is binned.
+ */
+ bool binned() const { return bin_t::binned; }
+ /**
+ * Reset stat value to default
+ */
+ void reset()
+ {
+ bin.reset();
+ }
+
+ bool check() { return bin.initialized(); }
+};
+
+template <class Storage, class Bin>
+class DistProxy;
+
+template <class Storage, class Bin>
+class VectorDistBase : public DataAccess
+{
+ public:
+ typedef typename Storage::Params params_t;
+ typedef typename Bin::template VectorBin<Storage> bin_t;
+
+ protected:
+ bin_t bin;
+ params_t params;
+
+ protected:
+ Storage *data(int index) { return bin.data(index, params); }
+ const Storage *data(int index) const
+ {
+ bin_t *_bin = const_cast<bin_t *>(&bin);
+ params_t *_params = const_cast<params_t *>(&params);
+ return _bin->data(index, *_params);
+ }
+
+ public:
+ VectorDistBase() {}
+
+ friend class DistProxy<Storage, Bin>;
+ DistProxy<Storage, Bin> operator[](int index);
+ const DistProxy<Storage, Bin> operator[](int index) const;
+
+ size_t size() const { return bin.size(); }
+ bool zero() const { return false; }
+ /**
+ * Return true if stat is binned.
+ *@return True is stat is binned.
+ */
+ bool binned() const { return bin_t::binned; }
+ /**
+ * Reset stat value to default
+ */
+ void reset() { bin.reset(); }
+
+ bool check() { return bin.initialized(); }
+ void update(VectorDistData *base)
+ {
+ int size = this->size();
+ base->data.resize(size);
+ for (int i = 0; i < size; ++i) {
+ base->data[i].fancy = Storage::fancy;
+ data(i)->update(&(base->data[i]), params);
+ }
+ }
+};
+
+template <class Storage, class Bin>
+class DistProxy
+{
+ public:
+ typedef typename Storage::Params params_t;
+ typedef typename Bin::template Bin<Storage> bin_t;
+ typedef VectorDistBase<Storage, Bin> base_t;
+
+ private:
+ union {
+ base_t *stat;
+ const base_t *cstat;
+ };
+ int index;
+
+ protected:
+ Storage *data() { return stat->data(index); }
+ const Storage *data() const { return cstat->data(index); }
+
+ public:
+ DistProxy(const VectorDistBase<Storage, Bin> &s, int i)
+ : cstat(&s), index(i) {}
+ DistProxy(const DistProxy &sp)
+ : cstat(sp.cstat), index(sp.index) {}
+ const DistProxy &operator=(const DistProxy &sp) {
+ cstat = sp.cstat; index = sp.index; return *this;
+ }
+
+ public:
+ template <typename U>
+ void sample(const U &v, int n = 1) { data()->sample(v, n, cstat->params); }
+
+ size_t size() const { return 1; }
+ bool zero() const { return data()->zero(cstat->params); }
+ /**
+ * Return true if stat is binned.
+ *@return false since Proxies are not binned/printed.
+ */
+ bool binned() const { return false; }
+ /**
+ * Proxy has no state. Nothing to reset.
+ */
+ void reset() { }
+};
+
+template <class Storage, class Bin>
+inline DistProxy<Storage, Bin>
+VectorDistBase<Storage, Bin>::operator[](int index)
+{
+ assert (index >= 0 && index < size());
+ return DistProxy<Storage, Bin>(*this, index);
+}
+
+template <class Storage, class Bin>
+inline const DistProxy<Storage, Bin>
+VectorDistBase<Storage, Bin>::operator[](int index) const
+{
+ assert (index >= 0 && index < size());
+ return DistProxy<Storage, Bin>(*this, index);
+}
+
+#if 0
+template <class Storage, class Bin>
+Result
+VectorDistBase<Storage, Bin>::total(int index) const
+{
+ int total = 0;
+ for (int i=0; i < x_size(); ++i) {
+ total += data(i)->result(*params);
+ }
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////
+//
+// Formula Details
+//
+//////////////////////////////////////////////////////////////////////
+
+/**
+ * Base class for formula statistic node. These nodes are used to build a tree
+ * that represents the formula.
+ */
+class Node : public RefCounted
+{
+ public:
+ /**
+ * Return the number of nodes in the subtree starting at this node.
+ * @return the number of nodes in this subtree.
+ */
+ virtual size_t size() const = 0;
+ /**
+ * Return the result vector of this subtree.
+ * @return The result vector of this subtree.
+ */
+ virtual const VResult &result() const = 0;
+ /**
+ * Return the total of the result vector.
+ * @return The total of the result vector.
+ */
+ virtual Result total() const = 0;
+ /**
+ * Return true if stat is binned.
+ *@return True is stat is binned.
+ */
+ virtual bool binned() const = 0;
+
+ /**
+ *
+ */
+ virtual std::string str() const = 0;
+};
+
+/** Reference counting pointer to a function Node. */
+typedef RefCountingPtr<Node> NodePtr;
+
+class ScalarStatNode : public Node
+{
+ private:
+ const ScalarData *data;
+ mutable VResult vresult;
+
+ public:
+ ScalarStatNode(const ScalarData *d) : data(d), vresult(1) {}
+ virtual const VResult &result() const
+ {
+ vresult[0] = data->result();
+ return vresult;
+ }
+ virtual Result total() const { return data->result(); };
+
+ virtual size_t size() const { return 1; }
+ /**
+ * Return true if stat is binned.
+ *@return True is stat is binned.
+ */
+ virtual bool binned() const { return data->binned(); }
+
+ /**
+ *
+ */
+ virtual std::string str() const { return data->name; }
+};
+
+template <class Storage, class Bin>
+class ScalarProxyNode : public Node
+{
+ private:
+ const ScalarProxy<Storage, Bin> proxy;
+ mutable VResult vresult;
+
+ public:
+ ScalarProxyNode(const ScalarProxy<Storage, Bin> &p)
+ : proxy(p), vresult(1) { }
+ virtual const VResult &result() const
+ {
+ vresult[0] = proxy.result();
+ return vresult;
+ }
+ virtual Result total() const { return proxy.result(); };
+
+ virtual size_t size() const { return 1; }
+ /**
+ * Return true if stat is binned.
+ *@return True is stat is binned.
+ */
+ virtual bool binned() const { return proxy.binned(); }
+
+ /**
+ *
+ */
+ virtual std::string str() const { return proxy.str(); }
+};
+
+class VectorStatNode : public Node
+{
+ private:
+ const VectorData *data;
+
+ public:
+ VectorStatNode(const VectorData *d) : data(d) { }
+ virtual const VResult &result() const { return data->result(); }
+ virtual Result total() const { return data->total(); };
+
+ virtual size_t size() const { return data->size(); }
+ /**
+ * Return true if stat is binned.
+ *@return True is stat is binned.
+ */
+ virtual bool binned() const { return data->binned(); }
+
+ virtual std::string str() const { return data->name; }
+};
+
+template <class T>
+class ConstNode : public Node
+{
+ private:
+ VResult vresult;
+
+ public:
+ ConstNode(T s) : vresult(1, (Result)s) {}
+ const VResult &result() const { return vresult; }
+ virtual Result total() const { return vresult[0]; };
+ virtual size_t size() const { return 1; }
+
+ /**
+ * Return true if stat is binned.
+ *@return False since constants aren't binned.
+ */
+ virtual bool binned() const { return false; }
+
+ virtual std::string str() const { return to_string(vresult[0]); }
+};
+
+template <class Op>
+struct OpString;
+
+template<>
+struct OpString<std::plus<Result> >
+{
+ static std::string str() { return "+"; }
+};
+
+template<>
+struct OpString<std::minus<Result> >
+{
+ static std::string str() { return "-"; }
+};
+
+template<>
+struct OpString<std::multiplies<Result> >
+{
+ static std::string str() { return "*"; }
+};
+
+template<>
+struct OpString<std::divides<Result> >
+{
+ static std::string str() { return "/"; }
+};
+
+template<>
+struct OpString<std::modulus<Result> >
+{
+ static std::string str() { return "%"; }
+};
+
+template<>
+struct OpString<std::negate<Result> >
+{
+ static std::string str() { return "-"; }
+};
+
+template <class Op>
+class UnaryNode : public Node
+{
+ public:
+ NodePtr l;
+ mutable VResult vresult;
+
+ public:
+ UnaryNode(NodePtr &p) : l(p) {}
+
+ const VResult &result() const
+ {
+ const VResult &lvec = l->result();
+ int size = lvec.size();
+
+ assert(size > 0);
+
+ vresult.resize(size);
+ Op op;
+ for (int i = 0; i < size; ++i)
+ vresult[i] = op(lvec[i]);
+
+ return vresult;
+ }
+
+ Result total() const {
+ Op op;
+ return op(l->total());
+ }
+
+ virtual size_t size() const { return l->size(); }
+ /**
+ * Return true if child of node is binned.
+ *@return True if child of node is binned.
+ */
+ virtual bool binned() const { return l->binned(); }
+
+ virtual std::string str() const
+ {
+ return OpString<Op>::str() + l->str();
+ }
+};
+
+template <class Op>
+class BinaryNode : public Node
+{
+ public:
+ NodePtr l;
+ NodePtr r;
+ mutable VResult vresult;
+
+ public:
+ BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {}
+
+ const VResult &result() const
+ {
+ Op op;
+ const VResult &lvec = l->result();
+ const VResult &rvec = r->result();
+
+ assert(lvec.size() > 0 && rvec.size() > 0);
+
+ if (lvec.size() == 1 && rvec.size() == 1) {
+ vresult.resize(1);
+ vresult[0] = op(lvec[0], rvec[0]);
+ } else if (lvec.size() == 1) {
+ int size = rvec.size();
+ vresult.resize(size);
+ for (int i = 0; i < size; ++i)
+ vresult[i] = op(lvec[0], rvec[i]);
+ } else if (rvec.size() == 1) {
+ int size = lvec.size();
+ vresult.resize(size);
+ for (int i = 0; i < size; ++i)
+ vresult[i] = op(lvec[i], rvec[0]);
+ } else if (rvec.size() == lvec.size()) {
+ int size = rvec.size();
+ vresult.resize(size);
+ for (int i = 0; i < size; ++i)
+ vresult[i] = op(lvec[i], rvec[i]);
+ }
+
+ return vresult;
+ }
+
+ Result total() const {
+ Op op;
+ return op(l->total(), r->total());
+ }
+
+ virtual size_t size() const {
+ int ls = l->size();
+ int rs = r->size();
+ if (ls == 1)
+ return rs;
+ else if (rs == 1)
+ return ls;
+ else {
+ assert(ls == rs && "Node vector sizes are not equal");
+ return ls;
+ }
+ }
+ /**
+ * Return true if any children of node are binned
+ *@return True if either child of node is binned.
+ */
+ virtual bool binned() const { return (l->binned() || r->binned()); }
+
+ virtual std::string str() const
+ {
+ return csprintf("(%s %s %s)", l->str(), OpString<Op>::str(), r->str());
+ }
+};
+
+template <class Op>
+class SumNode : public Node
+{
+ public:
+ NodePtr l;
+ mutable VResult vresult;
+
+ public:
+ SumNode(NodePtr &p) : l(p), vresult(1) {}
+
+ const VResult &result() const
+ {
+ const VResult &lvec = l->result();
+ int size = lvec.size();
+ assert(size > 0);
+
+ vresult[0] = 0.0;
+
+ Op op;
+ for (int i = 0; i < size; ++i)
+ vresult[0] = op(vresult[0], lvec[i]);
+
+ return vresult;
+ }
+
+ Result total() const
+ {
+ const VResult &lvec = l->result();
+ int size = lvec.size();
+ assert(size > 0);
+
+ Result vresult = 0.0;
+
+ Op op;
+ for (int i = 0; i < size; ++i)
+ vresult = op(vresult, lvec[i]);
+
+ return vresult;
+ }
+
+ virtual size_t size() const { return 1; }
+ /**
+ * Return true if child of node is binned.
+ *@return True if child of node is binned.
+ */
+ virtual bool binned() const { return l->binned(); }
+
+ virtual std::string str() const
+ {
+ return csprintf("total(%s)", l->str());
+ }
+};
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// Visible Statistics Types
+//
+//////////////////////////////////////////////////////////////////////
+/**
+ * @defgroup VisibleStats "Statistic Types"
+ * These are the statistics that are used in the simulator. By default these
+ * store counters and don't use binning, but are templatized to accept any type
+ * and any Bin class.
+ * @{
+ */
+
+/**
+ * This is an easy way to assign all your stats to be binned or not
+ * binned. If the typedef is NoBin, nothing is binned. If it is
+ * MainBin, then all stats are binned under that Bin.
+ */
+#if STATS_BINNING
+typedef MainBin DefaultBin;
+#else
+typedef NoBin DefaultBin;
+#endif
+
+/**
+ * This is a simple scalar statistic, like a counter.
+ * @sa Stat, ScalarBase, StatStor
+ */
+template <class Bin = DefaultBin>
+class Scalar
+ : public Wrap<Scalar<Bin>,
+ ScalarBase<StatStor, Bin>,
+ ScalarStatData>
+{
+ public:
+ /** The base implementation. */
+ typedef ScalarBase<StatStor, Bin> Base;
+
+ Scalar()
+ {
+ this->setInit();
+ }
+
+ /**
+ * Sets the stat equal to the given value. Calls the base implementation
+ * of operator=
+ * @param v The new value.
+ */
+ template <typename U>
+ void operator=(const U &v) { Base::operator=(v); }
+};
+
+class Value
+ : public Wrap<Value,
+ ValueBase,
+ ScalarStatData>
+{
+ public:
+ /** The base implementation. */
+ typedef ValueBase Base;
+
+ template <class T>
+ Value &scalar(T &value)
+ {
+ Base::scalar(value);
+ return *this;
+ }
+
+ template <class T>
+ Value &functor(T &func)
+ {
+ Base::functor(func);
+ return *this;
+ }
+};
+
+/**
+ * A stat that calculates the per cycle average of a value.
+ * @sa Stat, ScalarBase, AvgStor
+ */
+template <class Bin = DefaultBin>
+class Average
+ : public Wrap<Average<Bin>,
+ ScalarBase<AvgStor, Bin>,
+ ScalarStatData>
+{
+ public:
+ /** The base implementation. */
+ typedef ScalarBase<AvgStor, Bin> Base;
+
+ Average()
+ {
+ this->setInit();
+ }
+
+ /**
+ * Sets the stat equal to the given value. Calls the base implementation
+ * of operator=
+ * @param v The new value.
+ */
+ template <typename U>
+ void operator=(const U &v) { Base::operator=(v); }
+};
+
+/**
+ * A vector of scalar stats.
+ * @sa Stat, VectorBase, StatStor
+ */
+template <class Bin = DefaultBin>
+class Vector
+ : public WrapVec<Vector<Bin>,
+ VectorBase<StatStor, Bin>,
+ VectorStatData>
+{
+ public:
+ /** The base implementation. */
+ typedef ScalarBase<StatStor, Bin> Base;
+
+ /**
+ * Set this vector to have the given size.
+ * @param size The new size.
+ * @return A reference to this stat.
+ */
+ Vector &init(size_t size) {
+ this->bin.init(size, this->params);
+ this->setInit();
+
+ return *this;
+ }
+};
+
+/**
+ * A vector of Average stats.
+ * @sa Stat, VectorBase, AvgStor
+ */
+template <class Bin = DefaultBin>
+class AverageVector
+ : public WrapVec<AverageVector<Bin>,
+ VectorBase<AvgStor, Bin>,
+ VectorStatData>
+{
+ public:
+ /**
+ * Set this vector to have the given size.
+ * @param size The new size.
+ * @return A reference to this stat.
+ */
+ AverageVector &init(size_t size) {
+ this->bin.init(size, this->params);
+ this->setInit();
+
+ return *this;
+ }
+};
+
+/**
+ * A 2-Dimensional vecto of scalar stats.
+ * @sa Stat, Vector2dBase, StatStor
+ */
+template <class Bin = DefaultBin>
+class Vector2d
+ : public WrapVec2d<Vector2d<Bin>,
+ Vector2dBase<StatStor, Bin>,
+ Vector2dStatData>
+{
+ public:
+ Vector2d &init(size_t _x, size_t _y) {
+ this->statData()->x = this->x = _x;
+ this->statData()->y = this->y = _y;
+ this->bin.init(this->x * this->y, this->params);
+ this->setInit();
+
+ return *this;
+ }
+};
+
+/**
+ * A simple distribution stat.
+ * @sa Stat, DistBase, DistStor
+ */
+template <class Bin = DefaultBin>
+class Distribution
+ : public Wrap<Distribution<Bin>,
+ DistBase<DistStor, Bin>,
+ DistStatData>
+{
+ public:
+ /** Base implementation. */
+ typedef DistBase<DistStor, Bin> Base;
+ /** The Parameter type. */
+ typedef typename DistStor::Params Params;
+
+ public:
+ /**
+ * Set the parameters of this distribution. @sa DistStor::Params
+ * @param min The minimum value of the distribution.
+ * @param max The maximum value of the distribution.
+ * @param bkt The number of values in each bucket.
+ * @return A reference to this distribution.
+ */
+ Distribution &init(Counter min, Counter max, Counter bkt) {
+ this->params.min = min;
+ this->params.max = max;
+ this->params.bucket_size = bkt;
+ this->params.size = (int)rint((max - min) / bkt + 1.0);
+ this->bin.init(this->params);
+ this->setInit();
+
+ return *this;
+ }
+};
+
+/**
+ * Calculates the mean and variance of all the samples.
+ * @sa Stat, DistBase, FancyStor
+ */
+template <class Bin = DefaultBin>
+class StandardDeviation
+ : public Wrap<StandardDeviation<Bin>,
+ DistBase<FancyStor, Bin>,
+ DistStatData>
+{
+ public:
+ /** The base implementation */
+ typedef DistBase<DistStor, Bin> Base;
+ /** The parameter type. */
+ typedef typename DistStor::Params Params;
+
+ public:
+ /**
+ * Construct and initialize this distribution.
+ */
+ StandardDeviation() {
+ this->bin.init(this->params);
+ this->setInit();
+ }
+};
+
+/**
+ * Calculates the per cycle mean and variance of the samples.
+ * @sa Stat, DistBase, AvgFancy
+ */
+template <class Bin = DefaultBin>
+class AverageDeviation
+ : public Wrap<AverageDeviation<Bin>,
+ DistBase<AvgFancy, Bin>,
+ DistStatData>
+{
+ public:
+ /** The base implementation */
+ typedef DistBase<DistStor, Bin> Base;
+ /** The parameter type. */
+ typedef typename DistStor::Params Params;
+
+ public:
+ /**
+ * Construct and initialize this distribution.
+ */
+ AverageDeviation()
+ {
+ this->bin.init(this->params);
+ this->setInit();
+ }
+};
+
+/**
+ * A vector of distributions.
+ * @sa Stat, VectorDistBase, DistStor
+ */
+template <class Bin = DefaultBin>
+class VectorDistribution
+ : public WrapVec<VectorDistribution<Bin>,
+ VectorDistBase<DistStor, Bin>,
+ VectorDistStatData>
+{
+ public:
+ /** The base implementation */
+ typedef VectorDistBase<DistStor, Bin> Base;
+ /** The parameter type. */
+ typedef typename DistStor::Params Params;
+
+ public:
+ /**
+ * Initialize storage and parameters for this distribution.
+ * @param size The size of the vector (the number of distributions).
+ * @param min The minimum value of the distribution.
+ * @param max The maximum value of the distribution.
+ * @param bkt The number of values in each bucket.
+ * @return A reference to this distribution.
+ */
+ VectorDistribution &init(int size, Counter min, Counter max, Counter bkt) {
+ this->params.min = min;
+ this->params.max = max;
+ this->params.bucket_size = bkt;
+ this->params.size = (int)rint((max - min) / bkt + 1.0);
+ this->bin.init(size, this->params);
+ this->setInit();
+
+ return *this;
+ }
+};
+
+/**
+ * This is a vector of StandardDeviation stats.
+ * @sa Stat, VectorDistBase, FancyStor
+ */
+template <class Bin = DefaultBin>
+class VectorStandardDeviation
+ : public WrapVec<VectorStandardDeviation<Bin>,
+ VectorDistBase<FancyStor, Bin>,
+ VectorDistStatData>
+{
+ public:
+ /** The base implementation */
+ typedef VectorDistBase<FancyStor, Bin> Base;
+ /** The parameter type. */
+ typedef typename DistStor::Params Params;
+
+ public:
+ /**
+ * Initialize storage for this distribution.
+ * @param size The size of the vector.
+ * @return A reference to this distribution.
+ */
+ VectorStandardDeviation &init(int size) {
+ this->bin.init(size, this->params);
+ this->setInit();
+
+ return *this;
+ }
+};
+
+/**
+ * This is a vector of AverageDeviation stats.
+ * @sa Stat, VectorDistBase, AvgFancy
+ */
+template <class Bin = DefaultBin>
+class VectorAverageDeviation
+ : public WrapVec<VectorAverageDeviation<Bin>,
+ VectorDistBase<AvgFancy, Bin>,
+ VectorDistStatData>
+{
+ public:
+ /** The base implementation */
+ typedef VectorDistBase<AvgFancy, Bin> Base;
+ /** The parameter type. */
+ typedef typename DistStor::Params Params;
+
+ public:
+ /**
+ * Initialize storage for this distribution.
+ * @param size The size of the vector.
+ * @return A reference to this distribution.
+ */
+ VectorAverageDeviation &init(int size) {
+ this->bin.init(size, this->params);
+ this->setInit();
+
+ return *this;
+ }
+};
+
+/**
+ * A formula for statistics that is calculated when printed. A formula is
+ * stored as a tree of Nodes that represent the equation to calculate.
+ * @sa Stat, ScalarStat, VectorStat, Node, Temp
+ */
+class FormulaBase : public DataAccess
+{
+ protected:
+ /** The root of the tree which represents the Formula */
+ NodePtr root;
+ friend class Temp;
+
+ public:
+ /**
+ * Return the result of the Fomula in a vector. If there were no Vector
+ * components to the Formula, then the vector is size 1. If there were,
+ * like x/y with x being a vector of size 3, then the result returned will
+ * be x[0]/y, x[1]/y, x[2]/y, respectively.
+ * @return The result vector.
+ */
+ void result(VResult &vec) const;
+
+ /**
+ * Return the total Formula result. If there is a Vector
+ * component to this Formula, then this is the result of the
+ * Formula if the formula is applied after summing all the
+ * components of the Vector. For example, if Formula is x/y where
+ * x is size 3, then total() will return (x[1]+x[2]+x[3])/y. If
+ * there is no Vector component, total() returns the same value as
+ * the first entry in the VResult val() returns.
+ * @return The total of the result vector.
+ */
+ Result total() const;
+
+ /**
+ * Return the number of elements in the tree.
+ */
+ size_t size() const;
+
+ /**
+ * Return true if Formula is binned. i.e. any of its children
+ * nodes are binned
+ * @return True if Formula is binned.
+ */
+ bool binned() const;
+
+ bool check() const { return true; }
+
+ /**
+ * Formulas don't need to be reset
+ */
+ void reset();
+
+ /**
+ *
+ */
+ bool zero() const;
+
+ /**
+ *
+ */
+ void update(StatData *);
+
+ std::string str() const;
+};
+
+class FormulaData : public VectorData
+{
+ public:
+ virtual std::string str() const = 0;
+ virtual bool check() const { return true; }
+};
+
+template <class Stat>
+class FormulaStatData : public FormulaData
+{
+ protected:
+ Stat &s;
+ mutable VResult vec;
+ mutable VCounter cvec;
+
+ public:
+ FormulaStatData(Stat &stat) : s(stat) {}
+
+ virtual bool binned() const { return s.binned(); }
+ virtual bool zero() const { return s.zero(); }
+ virtual void reset() { s.reset(); }
+
+ virtual size_t size() const { return s.size(); }
+ virtual const VResult &result() const
+ {
+ s.result(vec);
+ return vec;
+ }
+ virtual Result total() const { return s.total(); }
+ virtual VCounter &value() const { return cvec; }
+ virtual void visit(Visit &visitor)
+ {
+ update();
+ s.update(this);
+ visitor.visit(*this);
+ }
+ virtual std::string str() const { return s.str(); }
+};
+
+class Temp;
+class Formula
+ : public WrapVec<Formula,
+ FormulaBase,
+ FormulaStatData>
+{
+ public:
+ /**
+ * Create and initialize thie formula, and register it with the database.
+ */
+ Formula();
+
+ /**
+ * Create a formula with the given root node, register it with the
+ * database.
+ * @param r The root of the expression tree.
+ */
+ Formula(Temp r);
+
+ /**
+ * Set an unitialized Formula to the given root.
+ * @param r The root of the expression tree.
+ * @return a reference to this formula.
+ */
+ const Formula &operator=(Temp r);
+
+ /**
+ * Add the given tree to the existing one.
+ * @param r The root of the expression tree.
+ * @return a reference to this formula.
+ */
+ const Formula &operator+=(Temp r);
+};
+
+class FormulaNode : public Node
+{
+ private:
+ const Formula &formula;
+ mutable VResult vec;
+
+ public:
+ FormulaNode(const Formula &f) : formula(f) {}
+
+ virtual size_t size() const { return formula.size(); }
+ virtual const VResult &result() const { formula.result(vec); return vec; }
+ virtual Result total() const { return formula.total(); }
+ virtual bool binned() const { return formula.binned(); }
+
+ virtual std::string str() const { return formula.str(); }
+};
+
+/**
+ * Helper class to construct formula node trees.
+ */
+class Temp
+{
+ protected:
+ /**
+ * Pointer to a Node object.
+ */
+ NodePtr node;
+
+ public:
+ /**
+ * Copy the given pointer to this class.
+ * @param n A pointer to a Node object to copy.
+ */
+ Temp(NodePtr n) : node(n) { }
+
+ /**
+ * Return the node pointer.
+ * @return the node pointer.
+ */
+ operator NodePtr&() { return node;}
+
+ public:
+ /**
+ * Create a new ScalarStatNode.
+ * @param s The ScalarStat to place in a node.
+ */
+ template <class Bin>
+ Temp(const Scalar<Bin> &s)
+ : node(new ScalarStatNode(s.statData())) { }
+
+ /**
+ * Create a new ScalarStatNode.
+ * @param s The ScalarStat to place in a node.
+ */
+ Temp(const Value &s)
+ : node(new ScalarStatNode(s.statData())) { }
+
+ /**
+ * Create a new ScalarStatNode.
+ * @param s The ScalarStat to place in a node.
+ */
+ template <class Bin>
+ Temp(const Average<Bin> &s)
+ : node(new ScalarStatNode(s.statData())) { }
+
+ /**
+ * Create a new VectorStatNode.
+ * @param s The VectorStat to place in a node.
+ */
+ template <class Bin>
+ Temp(const Vector<Bin> &s)
+ : node(new VectorStatNode(s.statData())) { }
+
+ /**
+ *
+ */
+ Temp(const Formula &f)
+ : node(new FormulaNode(f)) { }
+
+ /**
+ * Create a new ScalarProxyNode.
+ * @param p The ScalarProxy to place in a node.
+ */
+ template <class Storage, class Bin>
+ Temp(const ScalarProxy<Storage, Bin> &p)
+ : node(new ScalarProxyNode<Storage, Bin>(p)) { }
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(signed char value)
+ : node(new ConstNode<signed char>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(unsigned char value)
+ : node(new ConstNode<unsigned char>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(signed short value)
+ : node(new ConstNode<signed short>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(unsigned short value)
+ : node(new ConstNode<unsigned short>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(signed int value)
+ : node(new ConstNode<signed int>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(unsigned int value)
+ : node(new ConstNode<unsigned int>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(signed long value)
+ : node(new ConstNode<signed long>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(unsigned long value)
+ : node(new ConstNode<unsigned long>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(signed long long value)
+ : node(new ConstNode<signed long long>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(unsigned long long value)
+ : node(new ConstNode<unsigned long long>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(float value)
+ : node(new ConstNode<float>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(double value)
+ : node(new ConstNode<double>(value)) {}
+};
+
+
+/**
+ * @}
+ */
+
+void check();
+void reset();
+void registerResetCallback(Callback *cb);
+
+inline Temp
+operator+(Temp l, Temp r)
+{
+ return NodePtr(new BinaryNode<std::plus<Result> >(l, r));
+}
+
+inline Temp
+operator-(Temp l, Temp r)
+{
+ return NodePtr(new BinaryNode<std::minus<Result> >(l, r));
+}
+
+inline Temp
+operator*(Temp l, Temp r)
+{
+ return NodePtr(new BinaryNode<std::multiplies<Result> >(l, r));
+}
+
+inline Temp
+operator/(Temp l, Temp r)
+{
+ return NodePtr(new BinaryNode<std::divides<Result> >(l, r));
+}
+
+inline Temp
+operator-(Temp l)
+{
+ return NodePtr(new UnaryNode<std::negate<Result> >(l));
+}
+
+template <typename T>
+inline Temp
+constant(T val)
+{
+ return NodePtr(new ConstNode<T>(val));
+}
+
+inline Temp
+sum(Temp val)
+{
+ return NodePtr(new SumNode<std::plus<Result> >(val));
+}
+
+/* namespace Stats */ }
+
+#endif // __BASE_STATISTICS_HH__
diff --git a/src/base/stats/events.cc b/src/base/stats/events.cc
new file mode 100644
index 000000000..3191aec13
--- /dev/null
+++ b/src/base/stats/events.cc
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <vector>
+
+#include "base/stats/events.hh"
+
+#if USE_MYSQL
+#include "base/cprintf.hh"
+#include "base/misc.hh"
+#include "base/mysql.hh"
+#include "base/stats/mysql.hh"
+#include "base/stats/mysql_run.hh"
+#include "base/str.hh"
+#endif
+
+#include "base/match.hh"
+#include "sim/host.hh"
+#include "sim/sim_object.hh"
+#include "sim/root.hh"
+
+using namespace std;
+
+namespace Stats {
+
+Tick EventStart = ULL(0x7fffffffffffffff);
+
+ObjectMatch event_ignore;
+
+#if USE_MYSQL
+class InsertEvent
+{
+ private:
+ char *query;
+ int size;
+ bool first;
+ static const int maxsize = 1024*1024;
+
+ typedef map<string, uint32_t> event_map_t;
+ event_map_t events;
+
+ MySQL::Connection &mysql;
+ uint16_t run;
+
+ public:
+ InsertEvent()
+ : mysql(MySqlDB.conn()), run(MySqlDB.run())
+ {
+ query = new char[maxsize + 1];
+ size = 0;
+ first = true;
+ flush();
+ }
+ ~InsertEvent()
+ {
+ flush();
+ }
+
+ void flush();
+ void insert(const string &stat);
+};
+
+void
+InsertEvent::insert(const string &stat)
+{
+ assert(mysql.connected());
+
+ event_map_t::iterator i = events.find(stat);
+ uint32_t event;
+ if (i == events.end()) {
+ mysql.query(
+ csprintf("SELECT en_id "
+ "from event_names "
+ "where en_name=\"%s\"",
+ stat));
+
+ MySQL::Result result = mysql.store_result();
+ if (!result)
+ panic("could not get a run\n%s\n", mysql.error);
+
+ assert(result.num_fields() == 1);
+ MySQL::Row row = result.fetch_row();
+ if (row) {
+ if (!to_number(row[0], event))
+ panic("invalid event id: %s\n", row[0]);
+ } else {
+ mysql.query(
+ csprintf("INSERT INTO "
+ "event_names(en_name)"
+ "values(\"%s\")",
+ stat));
+
+ if (mysql.error)
+ panic("could not get a run\n%s\n", mysql.error);
+
+ event = mysql.insert_id();
+ }
+ } else {
+ event = (*i).second;
+ }
+
+ if (size + 1024 > maxsize)
+ flush();
+
+ if (!first) {
+ query[size++] = ',';
+ query[size] = '\0';
+ }
+
+ first = false;
+
+ size += sprintf(query + size, "(%u,%u,%llu)",
+ event, run, (unsigned long long)curTick);
+}
+
+void
+InsertEvent::flush()
+{
+ static const char query_header[] = "INSERT INTO "
+ "events(ev_event, ev_run, ev_tick)"
+ "values";
+
+ if (size) {
+ MySQL::Connection &mysql = MySqlDB.conn();
+ assert(mysql.connected());
+ mysql.query(query);
+ }
+
+ query[0] = '\0';
+ size = sizeof(query_header);
+ first = true;
+ memcpy(query, query_header, size);
+}
+
+void
+__event(const string &stat)
+{
+ static InsertEvent event;
+ event.insert(stat);
+}
+
+#endif
+
+/* namespace Stats */ }
diff --git a/src/base/stats/events.hh b/src/base/stats/events.hh
new file mode 100644
index 000000000..2a23240b4
--- /dev/null
+++ b/src/base/stats/events.hh
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_STATS_EVENTS_HH__
+#define __BASE_STATS_EVENTS_HH__
+
+#include <string>
+
+#include "base/trace.hh"
+#include "config/use_mysql.hh"
+
+namespace Stats {
+
+extern Tick EventStart;
+
+#if USE_MYSQL
+void __event(const std::string &stat);
+bool MySqlConnected();
+#endif
+
+bool ignoreEvent(const std::string &name);
+
+inline void
+recordEvent(const std::string &stat)
+{
+ if (EventStart > curTick)
+ return;
+
+ DPRINTF(StatEvents, "Statistics Event: %s\n", stat);
+
+#if USE_MYSQL
+ if (!MySqlConnected())
+ return;
+
+ __event(stat);
+#endif
+}
+
+/* namespace Stats */ }
+
+#endif // __BASE_STATS_EVENTS_HH__
diff --git a/src/base/stats/flags.hh b/src/base/stats/flags.hh
new file mode 100644
index 000000000..00db95bc1
--- /dev/null
+++ b/src/base/stats/flags.hh
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_STATS_FLAGS_HH__
+#define __BASE_STATS_FLAGS_HH__
+namespace Stats {
+
+/**
+ * Define the storage for format flags.
+ * @todo Can probably shrink this.
+ */
+typedef u_int32_t StatFlags;
+
+/** Nothing extra to print. */
+const StatFlags none = 0x00000000;
+/** This Stat is Initialized */
+const StatFlags init = 0x00000001;
+/** Print this stat. */
+const StatFlags print = 0x00000002;
+/** Print the total. */
+const StatFlags total = 0x00000010;
+/** Print the percent of the total that this entry represents. */
+const StatFlags pdf = 0x00000020;
+/** Print the cumulative percentage of total upto this entry. */
+const StatFlags cdf = 0x00000040;
+/** Print the distribution. */
+const StatFlags dist = 0x00000080;
+/** Don't print if this is zero. */
+const StatFlags nozero = 0x00000100;
+/** Don't print if this is NAN */
+const StatFlags nonan = 0x00000200;
+/** Used for SS compatability. */
+const StatFlags __substat = 0x80000000;
+
+/** Mask of flags that can't be set directly */
+const StatFlags __reserved = init | print | __substat;
+
+enum DisplayMode
+{
+ mode_m5,
+ mode_simplescalar
+};
+
+extern DisplayMode DefaultMode;
+
+/* namespace Stats */ }
+
+#endif // __BASE_STATS_FLAGS_HH__
diff --git a/src/base/stats/mysql.cc b/src/base/stats/mysql.cc
new file mode 100644
index 000000000..6d12b4fc1
--- /dev/null
+++ b/src/base/stats/mysql.cc
@@ -0,0 +1,900 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <cassert>
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "base/misc.hh"
+#include "base/mysql.hh"
+#include "base/statistics.hh"
+#include "base/stats/flags.hh"
+#include "base/stats/mysql.hh"
+#include "base/stats/mysql_run.hh"
+#include "base/stats/statdb.hh"
+#include "base/stats/types.hh"
+#include "base/str.hh"
+#include "sim/host.hh"
+
+using namespace std;
+
+namespace Stats {
+
+MySqlRun MySqlDB;
+
+bool
+MySqlConnected()
+{
+ return MySqlDB.connected();
+}
+
+void
+MySqlRun::connect(const string &host, const string &user, const string &passwd,
+ const string &db, const string &name, const string &sample,
+ const string &project)
+{
+ if (connected())
+ panic("can only get one database connection at this time!");
+
+ mysql.connect(host, user, passwd, db);
+ if (mysql.error)
+ panic("could not connect to database server\n%s\n", mysql.error);
+
+ if (mysql.autocommit(false))
+ panic("could not set autocommit\n%s\n", mysql.error);
+
+ remove(name);
+ //cleanup();
+ setup(name, sample, user, project);
+}
+
+void
+MySqlRun::setup(const string &name, const string &sample, const string &user,
+ const string &project)
+{
+ assert(mysql.connected());
+
+ stringstream insert;
+ ccprintf(insert,
+ "INSERT INTO "
+ "runs(rn_name,rn_sample,rn_user,rn_project,rn_date,rn_expire)"
+ "values(\"%s\", \"%s\", \"%s\", \"%s\", NOW(),"
+ "DATE_ADD(CURDATE(), INTERVAL 31 DAY))",
+ name, sample, user, project);
+
+ mysql.query(insert);
+ if (mysql.error)
+ panic("could not get a run\n%s\n", mysql.error);
+
+ run_id = mysql.insert_id();
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+}
+
+void
+MySqlRun::remove(const string &name)
+{
+ assert(mysql.connected());
+ stringstream sql;
+ ccprintf(sql, "DELETE FROM runs WHERE rn_name=\"%s\"", name);
+ mysql.query(sql);
+ if (mysql.error)
+ panic("could not delete run\n%s\n", mysql.error);
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+}
+
+void
+MySqlRun::cleanup()
+{
+ assert(mysql.connected());
+
+ mysql.query("DELETE data "
+ "FROM data "
+ "LEFT JOIN runs ON dt_run=rn_id "
+ "WHERE rn_id IS NULL");
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+
+ mysql.query("DELETE formula_ref "
+ "FROM formula_ref "
+ "LEFT JOIN runs ON fr_run=rn_id "
+ "WHERE rn_id IS NULL");
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+
+ mysql.query("DELETE formulas "
+ "FROM formulas "
+ "LEFT JOIN formula_ref ON fm_stat=fr_stat "
+ "WHERE fr_stat IS NULL");
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+
+ mysql.query("DELETE stats "
+ "FROM stats "
+ "LEFT JOIN data ON st_id=dt_stat "
+ "WHERE dt_stat IS NULL");
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+
+ mysql.query("DELETE subdata "
+ "FROM subdata "
+ "LEFT JOIN data ON sd_stat=dt_stat "
+ "WHERE dt_stat IS NULL");
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+
+ mysql.query("DELETE bins "
+ "FROM bins "
+ "LEFT JOIN data ON bn_id=dt_bin "
+ "WHERE dt_bin IS NULL");
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+
+ mysql.query("DELETE events"
+ "FROM events"
+ "LEFT JOIN runs ON ev_run=rn_id"
+ "WHERE rn_id IS NULL");
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+
+ mysql.query("DELETE event_names"
+ "FROM event_names"
+ "LEFT JOIN events ON en_id=ev_event"
+ "WHERE ev_event IS NULL");
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+}
+
+void
+SetupStat::init()
+{
+ name = "";
+ descr = "";
+ type = "";
+ print = false;
+ prereq = 0;
+ prec = -1;
+ nozero = false;
+ nonan = false;
+ total = false;
+ pdf = false;
+ cdf = false;
+ min = 0;
+ max = 0;
+ bktsize = 0;
+ size = 0;
+}
+
+unsigned
+SetupStat::setup()
+{
+ MySQL::Connection &mysql = MySqlDB.conn();
+
+ stringstream insert;
+ ccprintf(insert,
+ "INSERT INTO "
+ "stats(st_name, st_descr, st_type, st_print, st_prereq, "
+ "st_prec, st_nozero, st_nonan, st_total, st_pdf, st_cdf, "
+ "st_min, st_max, st_bktsize, st_size)"
+ "values(\"%s\",\"%s\",\"%s\","
+ " %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)",
+ name, descr, type, print, prereq, (int)prec, nozero, nonan,
+ total, pdf, cdf,
+ min, max, bktsize, size);
+
+ mysql.query(insert);
+ if (!mysql.error) {
+ int id = mysql.insert_id();
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+ return id;
+ }
+
+ stringstream select;
+ ccprintf(select, "SELECT * FROM stats WHERE st_name=\"%s\"", name);
+
+ mysql.query(select);
+ MySQL::Result result = mysql.store_result();
+ if (!result)
+ panic("could not find stat\n%s\n", mysql.error);
+
+ assert(result.num_fields() == 16);
+ MySQL::Row row = result.fetch_row();
+ if (!row)
+ panic("could not get stat row\n%s\n", mysql.error);
+
+ bool tb;
+ int8_t ti8;
+ uint16_t tu16;
+ int64_t ti64;
+ uint64_t tu64;
+
+ if (name != (char *)row[1])
+ panic("failed stat check on %s:name. %s != %s\n",
+ name, name, row[1]);
+
+ if (descr != (char *)row[2])
+ panic("failed stat check on %s:descr. %s != %s\n",
+ name, descr, row[2]);
+
+ if (type != (char *)row[3])
+ panic("failed stat check on %s:type. %s != %s\n",
+ name, type, row[3]);
+
+ if (!to_number(row[4], tb) || print != tb)
+ panic("failed stat check on %s:print. %d != %d\n",
+ name, print, tb);
+
+ if (!to_number(row[6], ti8) || prec != ti8)
+ panic("failed stat check on %s:prec. %d != %d\n",
+ name, prec, ti8);
+
+ if (!to_number(row[7], tb) || nozero != tb)
+ panic("failed stat check on %s:nozero. %d != %d\n",
+ name, nozero, tb);
+
+ if (!to_number(row[8], tb) || nonan != tb)
+ panic("failed stat check on %s:nonan. %d != %d\n",
+ name, nonan, tb);
+
+ if (!to_number(row[9], tb) || total != tb)
+ panic("failed stat check on %s:total. %d != %d\n",
+ name, total, tb);
+
+ if (!to_number(row[10], tb) || pdf != tb)
+ panic("failed stat check on %s:pdf. %d != %d\n",
+ name, pdf, tb);
+
+ if (!to_number(row[11], tb) || cdf != tb)
+ panic("failed stat check on %s:cdf. %d != %d\n",
+ name, cdf, tb);
+
+ if (!to_number(row[12], ti64) || min != ti64)
+ panic("failed stat check on %s:min. %d != %d\n",
+ name, min, ti64);
+
+ if (!to_number(row[13], ti64) || max != ti64)
+ panic("failed stat check on %s:max. %d != %d\n",
+ name, max, ti64);
+
+ if (!to_number(row[14], tu64) || bktsize != tu64)
+ panic("failed stat check on %s:bktsize. %d != %d\n",
+ name, bktsize, tu64);
+
+ if (!to_number(row[15], tu16) || size != tu16)
+ panic("failed stat check on %s:size. %d != %d\n",
+ name, size, tu16);
+
+ to_number(row[5], prereq);
+ uint16_t statid;
+ to_number(row[0], statid);
+ return statid;
+}
+
+unsigned
+SetupBin(const string &bin)
+{
+ static map<string, int> binmap;
+
+ using namespace MySQL;
+ map<string,int>::const_iterator i = binmap.find(bin);
+ if (i != binmap.end())
+ return (*i).second;
+
+ Connection &mysql = MySqlDB.conn();
+ assert(mysql.connected());
+
+ uint16_t bin_id;
+
+ stringstream select;
+ stringstream insert;
+ ccprintf(select, "SELECT bn_id FROM bins WHERE bn_name=\"%s\"", bin);
+
+ mysql.query(select);
+ MySQL::Result result = mysql.store_result();
+ if (result) {
+ assert(result.num_fields() == 1);
+ MySQL::Row row = result.fetch_row();
+ if (row) {
+ to_number(row[0], bin_id);
+ goto exit;
+ }
+ }
+
+ ccprintf(insert, "INSERT INTO bins(bn_name) values(\"%s\")", bin);
+
+ mysql.query(insert);
+ if (mysql.error)
+ panic("could not get a bin\n%s\n", mysql.error);
+
+ bin_id = mysql.insert_id();
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+
+ binmap.insert(make_pair(bin, bin_id));
+
+ exit:
+ return bin_id;
+}
+
+InsertData::InsertData()
+{
+ query = new char[maxsize + 1];
+ size = 0;
+ flush();
+}
+
+InsertData::~InsertData()
+{
+ delete [] query;
+}
+
+void
+InsertData::flush()
+{
+ if (size) {
+ MySQL::Connection &mysql = MySqlDB.conn();
+ assert(mysql.connected());
+ mysql.query(query);
+ if (mysql.error)
+ panic("could not insert data\n%s\n", mysql.error);
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+ }
+
+ query[0] = '\0';
+ size = 0;
+ first = true;
+ strcpy(query, "INSERT INTO "
+ "data(dt_stat,dt_x,dt_y,dt_run,dt_tick,dt_bin,dt_data) "
+ "values");
+ size = strlen(query);
+}
+
+void
+InsertData::insert()
+{
+ if (size + 1024 > maxsize)
+ flush();
+
+ if (!first) {
+ query[size++] = ',';
+ query[size] = '\0';
+ }
+
+ first = false;
+
+ size += sprintf(query + size, "(%u,%d,%d,%u,%llu,%u,\"%f\")",
+ stat, x, y, MySqlDB.run(), (unsigned long long)tick,
+ bin, data);
+}
+
+struct InsertSubData
+{
+ uint16_t stat;
+ int16_t x;
+ int16_t y;
+ string name;
+ string descr;
+
+ void setup();
+};
+
+void
+InsertSubData::setup()
+{
+ MySQL::Connection &mysql = MySqlDB.conn();
+ assert(mysql.connected());
+ stringstream insert;
+ ccprintf(insert,
+ "INSERT INTO subdata(sd_stat,sd_x,sd_y,sd_name,sd_descr) "
+ "values(%d,%d,%d,\"%s\",\"%s\")",
+ stat, x, y, name, descr);
+
+ mysql.query(insert);
+// if (mysql.error)
+// panic("could not insert subdata\n%s\n", mysql.error);
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+}
+
+void
+InsertFormula(uint16_t stat, const string &formula)
+{
+ MySQL::Connection &mysql = MySqlDB.conn();
+ assert(mysql.connected());
+ stringstream insert_formula;
+ ccprintf(insert_formula,
+ "INSERT INTO formulas(fm_stat,fm_formula) values(%d, \"%s\")",
+ stat, formula);
+
+ mysql.query(insert_formula);
+// if (mysql.error)
+// panic("could not insert formula\n%s\n", mysql.error);
+
+ stringstream insert_ref;
+ ccprintf(insert_ref,
+ "INSERT INTO formula_ref(fr_stat,fr_run) values(%d, %d)",
+ stat, MySqlDB.run());
+
+ mysql.query(insert_ref);
+// if (mysql.error)
+// panic("could not insert formula reference\n%s\n", mysql.error);
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+}
+
+void
+UpdatePrereq(uint16_t stat, uint16_t prereq)
+{
+ MySQL::Connection &mysql = MySqlDB.conn();
+ assert(mysql.connected());
+ stringstream update;
+ ccprintf(update, "UPDATE stats SET st_prereq=%d WHERE st_id=%d",
+ prereq, stat);
+ mysql.query(update);
+ if (mysql.error)
+ panic("could not update prereq\n%s\n", mysql.error);
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+}
+
+void
+MySql::configure()
+{
+ /*
+ * set up all stats!
+ */
+ using namespace Database;
+
+ MySQL::Connection &mysql = MySqlDB.conn();
+
+ stat_list_t::const_iterator i, end = stats().end();
+ for (i = stats().begin(); i != end; ++i) {
+ (*i)->visit(*this);
+ }
+
+ for (i = stats().begin(); i != end; ++i) {
+ StatData *data = *i;
+ if (data->prereq) {
+ uint16_t stat_id = find(data->id);
+ uint16_t prereq_id = find(data->prereq->id);
+ assert(stat_id && prereq_id);
+
+ UpdatePrereq(stat_id, prereq_id);
+ }
+ }
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+
+ configured = true;
+}
+
+
+bool
+MySql::configure(const StatData &data, string type)
+{
+ stat.init();
+ stat.name = data.name;
+ stat.descr = data.desc;
+ stat.type = type;
+ stat.print = data.flags & print;
+ stat.prec = data.precision;
+ stat.nozero = data.flags & nozero;
+ stat.nonan = data.flags & nonan;
+ stat.total = data.flags & total;
+ stat.pdf = data.flags & pdf;
+ stat.cdf = data.flags & cdf;
+
+ return stat.print;
+}
+
+void
+MySql::configure(const ScalarData &data)
+{
+ if (!configure(data, "SCALAR"))
+ return;
+
+ insert(data.id, stat.setup());
+}
+
+void
+MySql::configure(const VectorData &data)
+{
+ if (!configure(data, "VECTOR"))
+ return;
+
+ uint16_t statid = stat.setup();
+
+ if (!data.subnames.empty()) {
+ InsertSubData subdata;
+ subdata.stat = statid;
+ subdata.y = 0;
+ for (int i = 0; i < data.subnames.size(); ++i) {
+ subdata.x = i;
+ subdata.name = data.subnames[i];
+ subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i];
+
+ if (!subdata.name.empty() || !subdata.descr.empty())
+ subdata.setup();
+ }
+ }
+
+ insert(data.id, statid);
+}
+
+void
+MySql::configure(const DistData &data)
+{
+ if (!configure(data, "DIST"))
+ return;
+
+ if (!data.data.fancy) {
+ stat.size = data.data.size;
+ stat.min = data.data.min;
+ stat.max = data.data.max;
+ stat.bktsize = data.data.bucket_size;
+ }
+ insert(data.id, stat.setup());
+}
+
+void
+MySql::configure(const VectorDistData &data)
+{
+ if (!configure(data, "VECTORDIST"))
+ return;
+
+ if (!data.data[0].fancy) {
+ stat.size = data.data[0].size;
+ stat.min = data.data[0].min;
+ stat.max = data.data[0].max;
+ stat.bktsize = data.data[0].bucket_size;
+ }
+
+ uint16_t statid = stat.setup();
+
+ if (!data.subnames.empty()) {
+ InsertSubData subdata;
+ subdata.stat = statid;
+ subdata.y = 0;
+ for (int i = 0; i < data.subnames.size(); ++i) {
+ subdata.x = i;
+ subdata.name = data.subnames[i];
+ subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i];
+ if (!subdata.name.empty() || !subdata.descr.empty())
+ subdata.setup();
+ }
+ }
+
+ insert(data.id, statid);
+}
+
+void
+MySql::configure(const Vector2dData &data)
+{
+ if (!configure(data, "VECTOR2D"))
+ return;
+
+ uint16_t statid = stat.setup();
+
+ if (!data.subnames.empty()) {
+ InsertSubData subdata;
+ subdata.stat = statid;
+ subdata.y = -1;
+ for (int i = 0; i < data.subnames.size(); ++i) {
+ subdata.x = i;
+ subdata.name = data.subnames[i];
+ subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i];
+ if (!subdata.name.empty() || !subdata.descr.empty())
+ subdata.setup();
+ }
+ }
+
+ if (!data.y_subnames.empty()) {
+ InsertSubData subdata;
+ subdata.stat = statid;
+ subdata.x = -1;
+ subdata.descr = "";
+ for (int i = 0; i < data.y_subnames.size(); ++i) {
+ subdata.y = i;
+ subdata.name = data.y_subnames[i];
+ if (!subdata.name.empty())
+ subdata.setup();
+ }
+ }
+
+ insert(data.id, statid);
+}
+
+void
+MySql::configure(const FormulaData &data)
+{
+ configure(data, "FORMULA");
+ insert(data.id, stat.setup());
+ InsertFormula(find(data.id), data.str());
+}
+
+void
+MySql::output(MainBin *bin)
+{
+ MySQL::Connection &mysql = MySqlDB.conn();
+
+ if (bin) {
+ bin->activate();
+ newdata.bin = SetupBin(bin->name());
+ } else {
+ newdata.bin = 0;
+ }
+
+ Database::stat_list_t::const_iterator i, end = Database::stats().end();
+ for (i = Database::stats().begin(); i != end; ++i) {
+ StatData *stat = *i;
+ if (bin && stat->binned() || !bin && !stat->binned()) {
+ stat->visit(*this);
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
+ }
+ }
+}
+
+bool
+MySql::valid() const
+{
+ return MySqlDB.connected();
+}
+
+void
+MySql::output()
+{
+ using namespace Database;
+ assert(valid());
+
+ if (!configured)
+ configure();
+
+ // store sample #
+ newdata.tick = curTick;
+
+ output(NULL);
+ if (!bins().empty()) {
+ bin_list_t::iterator i, end = bins().end();
+ for (i = bins().begin(); i != end; ++i)
+ output(*i);
+ }
+
+ newdata.flush();
+}
+
+void
+MySql::output(const ScalarData &data)
+{
+ if (!(data.flags & print))
+ return;
+
+ newdata.stat = find(data.id);
+ newdata.x = 0;
+ newdata.y = 0;
+ newdata.data = data.value();
+
+ newdata.insert();
+}
+
+void
+MySql::output(const VectorData &data)
+{
+ if (!(data.flags & print))
+ return;
+
+ newdata.stat = find(data.id);
+ newdata.y = 0;
+
+ const VCounter &cvec = data.value();
+ int size = data.size();
+ for (int x = 0; x < size; x++) {
+ newdata.x = x;
+ newdata.data = cvec[x];
+ newdata.insert();
+ }
+}
+
+void
+MySql::output(const DistDataData &data)
+{
+ const int db_sum = -1;
+ const int db_squares = -2;
+ const int db_samples = -3;
+ const int db_min_val = -4;
+ const int db_max_val = -5;
+ const int db_underflow = -6;
+ const int db_overflow = -7;
+
+ newdata.x = db_sum;
+ newdata.data = data.sum;
+ newdata.insert();
+
+ newdata.x = db_squares;
+ newdata.data = data.squares;
+ newdata.insert();
+
+ newdata.x = db_samples;
+ newdata.data = data.samples;
+ newdata.insert();
+
+ if (data.samples && !data.fancy) {
+ newdata.x = db_min_val;
+ newdata.data = data.min_val;
+ newdata.insert();
+
+ newdata.x = db_max_val;
+ newdata.data = data.max_val;
+ newdata.insert();
+
+ newdata.x = db_underflow;
+ newdata.data = data.underflow;
+ newdata.insert();
+
+ newdata.x = db_overflow;
+ newdata.data = data.overflow;
+ newdata.insert();
+
+ int size = data.cvec.size();
+ for (int x = 0; x < size; x++) {
+ newdata.x = x;
+ newdata.data = data.cvec[x];
+ newdata.insert();
+ }
+ }
+}
+
+
+void
+MySql::output(const DistData &data)
+{
+ if (!(data.flags & print))
+ return;
+
+ newdata.stat = find(data.id);
+ newdata.y = 0;
+ output(data.data);
+}
+
+void
+MySql::output(const VectorDistData &data)
+{
+ if (!(data.flags & print))
+ return;
+
+ newdata.stat = find(data.id);
+
+ int size = data.data.size();
+ for (int y = 0; y < size; ++y) {
+ newdata.y = y;
+ output(data.data[y]);
+ }
+}
+
+void
+MySql::output(const Vector2dData &data)
+{
+ if (!(data.flags & print))
+ return;
+
+ newdata.stat = find(data.id);
+
+ int index = 0;
+ for (int x = 0; x < data.x; x++) {
+ newdata.x = x;
+ for (int y = 0; y < data.y; y++) {
+ newdata.y = y;
+ newdata.data = data.cvec[index++];
+ newdata.insert();
+ }
+ }
+}
+
+void
+MySql::output(const FormulaData &data)
+{
+}
+
+/*
+ * Implement the visitor
+ */
+void
+MySql::visit(const ScalarData &data)
+{
+ if (!configured)
+ configure(data);
+ else
+ output(data);
+}
+
+void
+MySql::visit(const VectorData &data)
+{
+ if (!configured)
+ configure(data);
+ else
+ output(data);
+}
+
+void
+MySql::visit(const DistData &data)
+{
+ return;
+ if (!configured)
+ configure(data);
+ else
+ output(data);
+}
+
+void
+MySql::visit(const VectorDistData &data)
+{
+ return;
+ if (!configured)
+ configure(data);
+ else
+ output(data);
+}
+
+void
+MySql::visit(const Vector2dData &data)
+{
+ return;
+ if (!configured)
+ configure(data);
+ else
+ output(data);
+}
+
+void
+MySql::visit(const FormulaData &data)
+{
+ if (!configured)
+ configure(data);
+ else
+ output(data);
+}
+
+/* namespace Stats */ }
diff --git a/src/base/stats/mysql.hh b/src/base/stats/mysql.hh
new file mode 100644
index 000000000..25ea22b97
--- /dev/null
+++ b/src/base/stats/mysql.hh
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_STATS_MYSQL_HH__
+#define __BASE_STATS_MYSQL_HH__
+
+#include <map>
+#include <string>
+
+#include "base/stats/output.hh"
+
+namespace MySQL { class Connection; }
+namespace Stats {
+
+class MainBin;
+class DistDataData;
+class MySqlRun;
+bool MySqlConnected();
+extern MySqlRun MySqlDB;
+
+struct SetupStat
+{
+ std::string name;
+ std::string descr;
+ std::string type;
+ bool print;
+ uint16_t prereq;
+ int8_t prec;
+ bool nozero;
+ bool nonan;
+ bool total;
+ bool pdf;
+ bool cdf;
+ double min;
+ double max;
+ double bktsize;
+ uint16_t size;
+
+ void init();
+ unsigned setup();
+};
+
+class InsertData
+{
+ private:
+ char *query;
+ int size;
+ bool first;
+ static const int maxsize = 1024*1024;
+
+ public:
+ MySqlRun *run;
+
+ public:
+ uint64_t tick;
+ double data;
+ uint16_t stat;
+ uint16_t bin;
+ int16_t x;
+ int16_t y;
+
+ public:
+ InsertData();
+ ~InsertData();
+
+ void flush();
+ void insert();
+};
+
+class MySql : public Output
+{
+ protected:
+ SetupStat stat;
+ InsertData newdata;
+ std::list<FormulaData *> formulas;
+ bool configured;
+
+ protected:
+ std::map<int, int> idmap;
+
+ void insert(int sim_id, int db_id)
+ {
+ using namespace std;
+ idmap.insert(make_pair(sim_id, db_id));
+ }
+
+ int find(int sim_id)
+ {
+ using namespace std;
+ map<int,int>::const_iterator i = idmap.find(sim_id);
+ assert(i != idmap.end());
+ return (*i).second;
+ }
+ public:
+ // Implement Visit
+ virtual void visit(const ScalarData &data);
+ virtual void visit(const VectorData &data);
+ virtual void visit(const DistData &data);
+ virtual void visit(const VectorDistData &data);
+ virtual void visit(const Vector2dData &data);
+ virtual void visit(const FormulaData &data);
+
+ // Implement Output
+ virtual bool valid() const;
+ virtual void output();
+
+ protected:
+ // Output helper
+ void output(MainBin *bin);
+ void output(const DistDataData &data);
+ void output(const ScalarData &data);
+ void output(const VectorData &data);
+ void output(const DistData &data);
+ void output(const VectorDistData &data);
+ void output(const Vector2dData &data);
+ void output(const FormulaData &data);
+
+ void configure();
+ bool configure(const StatData &data, std::string type);
+ void configure(const ScalarData &data);
+ void configure(const VectorData &data);
+ void configure(const DistData &data);
+ void configure(const VectorDistData &data);
+ void configure(const Vector2dData &data);
+ void configure(const FormulaData &data);
+};
+
+/* namespace Stats */ }
+
+#endif // __BASE_STATS_MYSQL_HH__
diff --git a/src/base/stats/mysql_run.hh b/src/base/stats/mysql_run.hh
new file mode 100644
index 000000000..d8dcb7594
--- /dev/null
+++ b/src/base/stats/mysql_run.hh
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_STATS_MYSQL_RUN_HH__
+#define __BASE_STATS_MYSQL_RUN_HH__
+
+#include <string>
+
+#include "base/mysql.hh"
+#include "sim/host.hh"
+
+namespace Stats {
+
+struct MySqlRun
+{
+ private:
+ MySQL::Connection mysql;
+ uint16_t run_id;
+
+ protected:
+ void setup(const std::string &name, const std::string &sample,
+ const std::string &user, const std::string &project);
+
+ void remove(const std::string &name);
+ void cleanup();
+
+ public:
+ bool connected() const { return mysql.connected(); }
+ void connect(const std::string &host, const std::string &user,
+ const std::string &passwd, const std::string &db,
+ const std::string &name, const std::string &sample,
+ const std::string &project);
+
+ MySQL::Connection &conn() { return mysql; }
+ uint16_t run() const { return run_id; }
+};
+
+/* namespace Stats */ }
+
+#endif // __BASE_STATS_MYSQL_RUN_HH__
diff --git a/src/base/stats/output.hh b/src/base/stats/output.hh
new file mode 100644
index 000000000..ee6b38d63
--- /dev/null
+++ b/src/base/stats/output.hh
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_STATS_OUTPUT_HH__
+#define __BASE_STATS_OUTPUT_HH__
+
+#include <string>
+
+#include "base/stats/visit.hh"
+
+namespace Stats {
+
+struct Output : public Visit
+{
+ inline void operator()() { output(); }
+ virtual void output() = 0;
+ virtual bool valid() const = 0;
+};
+
+/* namespace Stats */ }
+
+#endif // __BASE_STATS_OUTPUT_HH__
diff --git a/src/base/stats/statdb.cc b/src/base/stats/statdb.cc
new file mode 100644
index 000000000..a6b00ab8a
--- /dev/null
+++ b/src/base/stats/statdb.cc
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "base/misc.hh"
+#include "base/trace.hh"
+#include "base/statistics.hh"
+#include "base/stats/bin.hh"
+#include "base/stats/statdb.hh"
+
+using namespace std;
+
+namespace Stats {
+namespace Database {
+
+StatData *
+find(void *stat)
+{
+ stat_map_t::const_iterator i = map().find(stat);
+
+ if (i == map().end())
+ return NULL;
+
+ return (*i).second;
+}
+
+void
+regBin(MainBin *bin, const std::string &_name)
+{
+ bin_list_t::iterator i, end = bins().end();
+ for (i = bins().begin(); i != end; ++i)
+ if ((*i)->name() == _name)
+ panic("re-registering bin %s", _name);
+ bins().push_back(bin);
+ DPRINTF(Stats, "registering %s\n", _name);
+}
+
+void
+regStat(void *stat, StatData *data)
+{
+ if (map().find(stat) != map().end())
+ panic("shouldn't register stat twice!");
+
+ stats().push_back(data);
+
+#ifndef NDEBUG
+ pair<stat_map_t::iterator, bool> result =
+#endif
+ map().insert(make_pair(stat, data));
+ assert(result.second && "this should never fail");
+ assert(map().find(stat) != map().end());
+}
+
+void
+regPrint(void *stat)
+{
+ StatData *data = find(stat);
+ assert(data);
+ data->flags |= print;
+}
+
+TheDatabase &db()
+{
+ static TheDatabase db;
+ return db;
+}
+
+/* namespace Database */ }
+/* namespace Stats */ }
diff --git a/src/base/stats/statdb.hh b/src/base/stats/statdb.hh
new file mode 100644
index 000000000..eb56d8fac
--- /dev/null
+++ b/src/base/stats/statdb.hh
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_STATS_STATDB_HH__
+#define __BASE_STATS_STATDB_HH__
+
+#include <iosfwd>
+#include <list>
+#include <map>
+#include <string>
+
+class Python;
+
+namespace Stats {
+
+class MainBin;
+class StatData;
+
+namespace Database {
+
+typedef std::map<void *, StatData *> stat_map_t;
+typedef std::list<StatData *> stat_list_t;
+typedef std::list<MainBin *> bin_list_t;
+
+// We wrap the database in a struct to make sure it is built in time.
+struct TheDatabase
+{
+ stat_map_t map;
+ stat_list_t stats;
+ bin_list_t bins;
+
+};
+
+TheDatabase &db();
+inline stat_map_t &map() { return db().map; }
+inline stat_list_t &stats() { return db().stats; }
+inline bin_list_t &bins() { return db().bins; }
+
+StatData *find(void *stat);
+void regBin(MainBin *bin, const std::string &name);
+void regStat(void *stat, StatData *data);
+void regPrint(void *stat);
+
+inline std::string name() { return "Statistics Database"; }
+
+/* namespace Database */ }
+/* namespace Stats */ }
+
+#endif // __BASE_STATS_STATDB_HH__
diff --git a/src/base/stats/text.cc b/src/base/stats/text.cc
new file mode 100644
index 000000000..300737c60
--- /dev/null
+++ b/src/base/stats/text.cc
@@ -0,0 +1,736 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(__APPLE__)
+#define _GLIBCPP_USE_C99 1
+#endif
+
+#include <iostream>
+#include <sstream>
+#include <fstream>
+#include <string>
+
+#include "base/misc.hh"
+#include "base/statistics.hh"
+#include "base/stats/statdb.hh"
+#include "base/stats/text.hh"
+#include "base/stats/visit.hh"
+
+using namespace std;
+
+#ifndef NAN
+float __nan();
+/** Define Not a number. */
+#define NAN (__nan())
+/** Need to define __nan() */
+#define __M5_NAN
+#endif
+
+#ifdef __M5_NAN
+float
+__nan()
+{
+ union {
+ uint32_t ui;
+ float f;
+ } nan;
+
+ nan.ui = 0x7fc00000;
+ return nan.f;
+}
+#endif
+
+namespace Stats {
+
+Text::Text()
+ : mystream(false), stream(NULL), compat(false), descriptions(false)
+{
+}
+
+Text::Text(std::ostream &stream)
+ : mystream(false), stream(NULL), compat(false), descriptions(false)
+{
+ open(stream);
+}
+
+Text::Text(const std::string &file)
+ : mystream(false), stream(NULL), compat(false), descriptions(false)
+{
+ open(file);
+}
+
+
+Text::~Text()
+{
+ if (mystream) {
+ assert(stream);
+ delete stream;
+ }
+}
+
+void
+Text::open(std::ostream &_stream)
+{
+ if (stream)
+ panic("stream already set!");
+
+ mystream = false;
+ stream = &_stream;
+ assert(valid());
+}
+
+void
+Text::open(const std::string &file)
+{
+ if (stream)
+ panic("stream already set!");
+
+ mystream = true;
+ stream = new ofstream(file.c_str(), ios::trunc);
+ assert(valid());
+}
+
+bool
+Text::valid() const
+{
+ return stream != NULL;
+}
+
+void
+Text::output()
+{
+ using namespace Database;
+
+ ccprintf(*stream, "\n---------- Begin Simulation Statistics ----------\n");
+ if (bins().empty() || bins().size() == 1) {
+ stat_list_t::const_iterator i, end = stats().end();
+ for (i = stats().begin(); i != end; ++i)
+ (*i)->visit(*this);
+ } else {
+ ccprintf(*stream, "PRINTING BINNED STATS\n");
+ bin_list_t::iterator i, end = bins().end();
+ for (i = bins().begin(); i != end; ++i) {
+ MainBin *bin = *i;
+ bin->activate();
+ ccprintf(*stream,"---%s Bin------------\n", bin->name());
+ stat_list_t::const_iterator i, end = stats().end();
+ for (i = stats().begin(); i != end; ++i)
+ (*i)->visit(*this);
+ ccprintf(*stream, "---------------------------------\n");
+ }
+ }
+ ccprintf(*stream, "\n---------- End Simulation Statistics ----------\n");
+ stream->flush();
+}
+
+bool
+Text::noOutput(const StatData &data)
+{
+ if (!(data.flags & print))
+ return true;
+
+ if (data.prereq && data.prereq->zero())
+ return true;
+
+ return false;
+}
+
+string
+ValueToString(Result value, int precision, bool compat)
+{
+ stringstream val;
+
+ if (!isnan(value)) {
+ if (precision != -1)
+ val.precision(precision);
+ else if (value == rint(value))
+ val.precision(0);
+
+ val.unsetf(ios::showpoint);
+ val.setf(ios::fixed);
+ val << value;
+ } else {
+ val << (compat ? "<err: div-0>" : "no value");
+ }
+
+ return val.str();
+}
+
+struct ScalarPrint
+{
+ Result value;
+ string name;
+ string desc;
+ StatFlags flags;
+ bool compat;
+ bool descriptions;
+ int precision;
+ Result pdf;
+ Result cdf;
+
+ void operator()(ostream &stream) const;
+};
+
+void
+ScalarPrint::operator()(ostream &stream) const
+{
+ if (flags & nozero && value == 0.0 ||
+ flags & nonan && isnan(value))
+ return;
+
+ stringstream pdfstr, cdfstr;
+
+ if (!isnan(pdf))
+ ccprintf(pdfstr, "%.2f%%", pdf * 100.0);
+
+ if (!isnan(cdf))
+ ccprintf(cdfstr, "%.2f%%", cdf * 100.0);
+
+ if (compat && flags & __substat) {
+ ccprintf(stream, "%32s %12s %10s %10s", name,
+ ValueToString(value, precision, compat), pdfstr, cdfstr);
+ } else {
+ ccprintf(stream, "%-40s %12s %10s %10s", name,
+ ValueToString(value, precision, compat), pdfstr, cdfstr);
+ }
+
+ if (descriptions) {
+ if (!desc.empty())
+ ccprintf(stream, " # %s", desc);
+ }
+ stream << endl;
+}
+
+struct VectorPrint
+{
+ string name;
+ string desc;
+ vector<string> subnames;
+ vector<string> subdescs;
+ StatFlags flags;
+ bool compat;
+ bool descriptions;
+ int precision;
+ VResult vec;
+ Result total;
+
+ void operator()(ostream &stream) const;
+};
+
+void
+VectorPrint::operator()(std::ostream &stream) const
+{
+ int _size = vec.size();
+ Result _total = 0.0;
+
+ if (flags & (pdf | cdf)) {
+ for (int i = 0; i < _size; ++i) {
+ _total += vec[i];
+ }
+ }
+
+ string base = name + (compat ? "_" : "::");
+
+ ScalarPrint print;
+ print.name = name;
+ print.desc = desc;
+ print.precision = precision;
+ print.descriptions = descriptions;
+ print.flags = flags;
+ print.pdf = NAN;
+ print.cdf = NAN;
+
+ bool havesub = !subnames.empty();
+
+ if (_size == 1) {
+ print.value = vec[0];
+ print(stream);
+ } else if (!compat) {
+ for (int i = 0; i < _size; ++i) {
+ if (havesub && (i >= subnames.size() || subnames[i].empty()))
+ continue;
+
+ print.name = base + (havesub ? subnames[i] : to_string(i));
+ print.desc = subdescs.empty() ? desc : subdescs[i];
+ print.value = vec[i];
+
+ if (_total && (flags & pdf)) {
+ print.pdf = vec[i] / _total;
+ print.cdf += print.pdf;
+ }
+
+ print(stream);
+ }
+
+ if (flags & ::Stats::total) {
+ print.name = base + "total";
+ print.desc = desc;
+ print.value = total;
+ print(stream);
+ }
+ } else {
+ if (flags & ::Stats::total) {
+ print.value = total;
+ print(stream);
+ }
+
+ Result _pdf = 0.0;
+ Result _cdf = 0.0;
+ if (flags & dist) {
+ ccprintf(stream, "%s.start_dist\n", name);
+ for (int i = 0; i < _size; ++i) {
+ print.name = havesub ? subnames[i] : to_string(i);
+ print.desc = subdescs.empty() ? desc : subdescs[i];
+ print.flags |= __substat;
+ print.value = vec[i];
+
+ if (_total) {
+ _pdf = vec[i] / _total;
+ _cdf += _pdf;
+ }
+
+ if (flags & pdf)
+ print.pdf = _pdf;
+ if (flags & cdf)
+ print.cdf = _cdf;
+
+ print(stream);
+ }
+ ccprintf(stream, "%s.end_dist\n", name);
+ } else {
+ for (int i = 0; i < _size; ++i) {
+ if (havesub && subnames[i].empty())
+ continue;
+
+ print.name = base;
+ print.name += havesub ? subnames[i] : to_string(i);
+ print.desc = subdescs.empty() ? desc : subdescs[i];
+ print.value = vec[i];
+
+ if (_total) {
+ _pdf = vec[i] / _total;
+ _cdf += _pdf;
+ } else {
+ _pdf = _cdf = NAN;
+ }
+
+ if (flags & pdf) {
+ print.pdf = _pdf;
+ print.cdf = _cdf;
+ }
+
+ print(stream);
+ }
+ }
+ }
+}
+
+struct DistPrint
+{
+ string name;
+ string desc;
+ StatFlags flags;
+ bool compat;
+ bool descriptions;
+ int precision;
+
+ Result min_val;
+ Result max_val;
+ Result underflow;
+ Result overflow;
+ VResult vec;
+ Result sum;
+ Result squares;
+ Result samples;
+
+ Counter min;
+ Counter max;
+ Counter bucket_size;
+ int size;
+ bool fancy;
+
+ void operator()(ostream &stream) const;
+};
+
+void
+DistPrint::operator()(ostream &stream) const
+{
+ if (fancy) {
+ ScalarPrint print;
+ string base = name + (compat ? "_" : "::");
+
+ print.precision = precision;
+ print.flags = flags;
+ print.compat = compat;
+ print.descriptions = descriptions;
+ print.desc = desc;
+ print.pdf = NAN;
+ print.cdf = NAN;
+
+ print.name = base + "mean";
+ print.value = samples ? sum / samples : NAN;
+ print(stream);
+
+ print.name = base + "stdev";
+ print.value = samples ? sqrt((samples * squares - sum * sum) /
+ (samples * (samples - 1.0))) : NAN;
+ print(stream);
+
+ print.name = "**Ignore: " + base + "TOT";
+ print.value = samples;
+ print(stream);
+ return;
+ }
+
+ assert(size == vec.size());
+
+ Result total = 0.0;
+
+ total += underflow;
+ for (int i = 0; i < size; ++i)
+ total += vec[i];
+ total += overflow;
+
+ string base = name + (compat ? "." : "::");
+
+ ScalarPrint print;
+ print.desc = compat ? "" : desc;
+ print.flags = flags;
+ print.compat = compat;
+ print.descriptions = descriptions;
+ print.precision = precision;
+ print.pdf = NAN;
+ print.cdf = NAN;
+
+ if (compat) {
+ ccprintf(stream, "%-42s", base + "start_dist");
+ if (descriptions && !desc.empty())
+ ccprintf(stream, " # %s", desc);
+ stream << endl;
+ }
+
+ print.name = base + "samples";
+ print.value = samples;
+ print(stream);
+
+ print.name = base + "min_value";
+ print.value = min_val;
+ print(stream);
+
+ if (!compat || underflow > 0.0) {
+ print.name = base + "underflows";
+ print.value = underflow;
+ if (!compat && total) {
+ print.pdf = underflow / total;
+ print.cdf += print.pdf;
+ }
+ print(stream);
+ }
+
+
+ if (!compat) {
+ for (int i = 0; i < size; ++i) {
+ stringstream namestr;
+ namestr << name;
+
+ Counter low = i * bucket_size + min;
+ Counter high = ::min(low + bucket_size, max);
+ namestr << low;
+ if (low < high)
+ namestr << "-" << high;
+
+ print.name = namestr.str();
+ print.value = vec[i];
+ if (total) {
+ print.pdf = vec[i] / total;
+ print.cdf += print.pdf;
+ }
+ print(stream);
+ }
+
+ } else {
+ Counter _min;
+ Result _pdf;
+ Result _cdf = 0.0;
+
+ print.flags = flags | __substat;
+
+ for (int i = 0; i < size; ++i) {
+ if (flags & nozero && vec[i] == 0.0 ||
+ flags & nonan && isnan(vec[i]))
+ continue;
+
+ _min = i * bucket_size + min;
+ _pdf = vec[i] / total * 100.0;
+ _cdf += _pdf;
+
+
+ print.name = ValueToString(_min, 0, compat);
+ print.value = vec[i];
+ print.pdf = (flags & pdf) ? _pdf : NAN;
+ print.cdf = (flags & cdf) ? _cdf : NAN;
+ print(stream);
+ }
+
+ print.flags = flags;
+ }
+
+ if (!compat || overflow > 0.0) {
+ print.name = base + "overflows";
+ print.value = overflow;
+ if (!compat && total) {
+ print.pdf = overflow / total;
+ print.cdf += print.pdf;
+ } else {
+ print.pdf = NAN;
+ print.cdf = NAN;
+ }
+ print(stream);
+ }
+
+ print.pdf = NAN;
+ print.cdf = NAN;
+
+ if (!compat) {
+ print.name = base + "total";
+ print.value = total;
+ print(stream);
+ }
+
+ print.name = base + "max_value";
+ print.value = max_val;
+ print(stream);
+
+ if (!compat && samples != 0) {
+ print.name = base + "mean";
+ print.value = sum / samples;
+ print(stream);
+
+ print.name = base + "stdev";
+ print.value = sqrt((samples * squares - sum * sum) /
+ (samples * (samples - 1.0)));
+ print(stream);
+ }
+
+ if (compat)
+ ccprintf(stream, "%send_dist\n\n", base);
+}
+
+void
+Text::visit(const ScalarData &data)
+{
+ if (noOutput(data))
+ return;
+
+ ScalarPrint print;
+ print.value = data.result();
+ print.name = data.name;
+ print.desc = data.desc;
+ print.flags = data.flags;
+ print.compat = compat;
+ print.descriptions = descriptions;
+ print.precision = data.precision;
+ print.pdf = NAN;
+ print.cdf = NAN;
+
+ print(*stream);
+}
+
+void
+Text::visit(const VectorData &data)
+{
+ if (noOutput(data))
+ return;
+
+ int size = data.size();
+ VectorPrint print;
+
+ print.name = data.name;
+ print.desc = data.desc;
+ print.flags = data.flags;
+ print.compat = compat;
+ print.descriptions = descriptions;
+ print.precision = data.precision;
+ print.vec = data.result();
+ print.total = data.total();
+
+ if (!data.subnames.empty()) {
+ for (int i = 0; i < size; ++i) {
+ if (!data.subnames[i].empty()) {
+ print.subnames = data.subnames;
+ print.subnames.resize(size);
+ for (int i = 0; i < size; ++i) {
+ if (!data.subnames[i].empty() &&
+ !data.subdescs[i].empty()) {
+ print.subdescs = data.subdescs;
+ print.subdescs.resize(size);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ print(*stream);
+}
+
+void
+Text::visit(const Vector2dData &data)
+{
+ if (noOutput(data))
+ return;
+
+ bool havesub = false;
+ VectorPrint print;
+
+ print.subnames = data.y_subnames;
+ print.flags = data.flags;
+ print.compat = compat;
+ print.descriptions = descriptions;
+ print.precision = data.precision;
+
+ if (!data.subnames.empty()) {
+ for (int i = 0; i < data.x; ++i)
+ if (!data.subnames[i].empty())
+ havesub = true;
+ }
+
+ VResult tot_vec(data.y);
+ Result super_total = 0.0;
+ for (int i = 0; i < data.x; ++i) {
+ if (havesub && (i >= data.subnames.size() || data.subnames[i].empty()))
+ continue;
+
+ int iy = i * data.y;
+ VResult yvec(data.y);
+
+ Result total = 0.0;
+ for (int j = 0; j < data.y; ++j) {
+ yvec[j] = data.cvec[iy + j];
+ tot_vec[j] += yvec[j];
+ total += yvec[j];
+ super_total += yvec[j];
+ }
+
+ print.name = data.name + "_" + (havesub ? data.subnames[i] : to_string(i));
+ print.desc = data.desc;
+ print.vec = yvec;
+ print.total = total;
+ print(*stream);
+ }
+
+ if ((data.flags & ::Stats::total) && (data.x > 1)) {
+ print.name = data.name;
+ print.desc = data.desc;
+ print.vec = tot_vec;
+ print.total = super_total;
+ print(*stream);
+ }
+}
+
+void
+Text::visit(const DistData &data)
+{
+ if (noOutput(data))
+ return;
+
+ DistPrint print;
+
+ print.name = data.name;
+ print.desc = data.desc;
+ print.flags = data.flags;
+ print.compat = compat;
+ print.descriptions = descriptions;
+ print.precision = data.precision;
+
+ print.min_val = data.data.min_val;
+ print.max_val = data.data.max_val;
+ print.underflow = data.data.underflow;
+ print.overflow = data.data.overflow;
+ print.vec.resize(data.data.cvec.size());
+ for (int i = 0; i < print.vec.size(); ++i)
+ print.vec[i] = (Result)data.data.cvec[i];
+ print.sum = data.data.sum;
+ print.squares = data.data.squares;
+ print.samples = data.data.samples;
+
+ print.min = data.data.min;
+ print.max = data.data.max;
+ print.bucket_size = data.data.bucket_size;
+ print.size = data.data.size;
+ print.fancy = data.data.fancy;
+
+ print(*stream);
+}
+
+void
+Text::visit(const VectorDistData &data)
+{
+ if (noOutput(data))
+ return;
+
+ for (int i = 0; i < data.size(); ++i) {
+ DistPrint print;
+
+ print.name = data.name +
+ (data.subnames[i].empty() ? ("_" + to_string(i)) : data.subnames[i]);
+ print.desc = data.subdescs[i].empty() ? data.desc : data.subdescs[i];
+ print.flags = data.flags;
+ print.compat = compat;
+ print.descriptions = descriptions;
+ print.precision = data.precision;
+
+ print.min_val = data.data[i].min_val;
+ print.max_val = data.data[i].max_val;
+ print.underflow = data.data[i].underflow;
+ print.overflow = data.data[i].overflow;
+ print.vec.resize(data.data[i].cvec.size());
+ for (int j = 0; j < print.vec.size(); ++j)
+ print.vec[j] = (Result)data.data[i].cvec[j];
+ print.sum = data.data[i].sum;
+ print.squares = data.data[i].squares;
+ print.samples = data.data[i].samples;
+
+ print.min = data.data[i].min;
+ print.max = data.data[i].max;
+ print.bucket_size = data.data[i].bucket_size;
+ print.size = data.data[i].size;
+ print.fancy = data.data[i].fancy;
+
+ print(*stream);
+ }
+}
+
+void
+Text::visit(const FormulaData &data)
+{
+ visit((const VectorData &)data);
+}
+
+/* namespace Stats */ }
diff --git a/src/base/stats/text.hh b/src/base/stats/text.hh
new file mode 100644
index 000000000..125cb79fa
--- /dev/null
+++ b/src/base/stats/text.hh
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_STATS_TEXT_HH__
+#define __BASE_STATS_TEXT_HH__
+
+#include <iosfwd>
+#include <string>
+
+#include "base/stats/output.hh"
+
+namespace Stats {
+
+class Text : public Output
+{
+ protected:
+ bool mystream;
+ std::ostream *stream;
+
+ protected:
+ bool noOutput(const StatData &data);
+ void binout();
+
+ public:
+ bool compat;
+ bool descriptions;
+
+ public:
+ Text();
+ Text(std::ostream &stream);
+ Text(const std::string &file);
+ ~Text();
+
+ void open(std::ostream &stream);
+ void open(const std::string &file);
+
+ // Implement Visit
+ virtual void visit(const ScalarData &data);
+ virtual void visit(const VectorData &data);
+ virtual void visit(const DistData &data);
+ virtual void visit(const VectorDistData &data);
+ virtual void visit(const Vector2dData &data);
+ virtual void visit(const FormulaData &data);
+
+ // Implement Output
+ virtual bool valid() const;
+ virtual void output();
+};
+
+/* namespace Stats */ }
+
+#endif // __BASE_STATS_TEXT_HH__
diff --git a/src/base/stats/types.hh b/src/base/stats/types.hh
new file mode 100644
index 000000000..57f1564a5
--- /dev/null
+++ b/src/base/stats/types.hh
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_STATS_TYPES_HH__
+#define __BASE_STATS_TYPES_HH__
+
+#include <vector>
+#include "sim/host.hh"
+
+namespace Stats {
+
+/** All counters are of 64-bit values. */
+typedef double Counter;
+/** vector of counters. */
+typedef std::vector<Counter> VCounter;
+
+/** All results are doubles. */
+typedef double Result;
+/** vector of results. */
+typedef std::vector<Result> VResult;
+
+/* namespace Stats */ }
+
+#endif // __BASE_STATS_TYPES_HH__
diff --git a/src/base/stats/visit.cc b/src/base/stats/visit.cc
new file mode 100644
index 000000000..dd4d49502
--- /dev/null
+++ b/src/base/stats/visit.cc
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "base/stats/visit.hh"
+
+namespace Stats {
+namespace Detail {
+
+Visit::Visit()
+{}
+
+Visit::~Visit()
+{}
+
+/* namespace Detail */ }
+/* namespace Stats */ }
diff --git a/src/base/stats/visit.hh b/src/base/stats/visit.hh
new file mode 100644
index 000000000..c0593c670
--- /dev/null
+++ b/src/base/stats/visit.hh
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_STATS_VISIT_HH__
+#define __BASE_STATS_VISIT_HH__
+
+#include <string>
+
+#include "base/time.hh"
+#include "sim/host.hh"
+
+namespace Stats {
+
+class StatData;
+class ScalarData;
+class VectorData;
+class DistDataData;
+class DistData;
+class VectorDistData;
+class Vector2dData;
+class FormulaData;
+
+struct Visit
+{
+ Visit();
+ virtual ~Visit();
+
+ virtual void visit(const ScalarData &data) = 0;
+ virtual void visit(const VectorData &data) = 0;
+ virtual void visit(const DistData &data) = 0;
+ virtual void visit(const VectorDistData &data) = 0;
+ virtual void visit(const Vector2dData &data) = 0;
+ virtual void visit(const FormulaData &data) = 0;
+};
+
+/* namespace Stats */ }
+
+#endif // __BASE_STATS_VISIT_HH__
diff --git a/src/base/str.cc b/src/base/str.cc
new file mode 100644
index 000000000..5f7f50286
--- /dev/null
+++ b/src/base/str.cc
@@ -0,0 +1,373 @@
+/*
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <ctype.h>
+
+#include <cstring>
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "base/intmath.hh"
+#include "base/str.hh"
+
+using namespace std;
+
+bool
+split_first(const string &s, string &lhs, string &rhs, char c)
+{
+ string::size_type offset = s.find(c);
+ if (offset == string::npos) {
+ lhs = s;
+ rhs = "";
+ return false;
+ }
+
+ lhs = s.substr(0, offset);
+ rhs = s.substr(offset + 1);
+ return true;
+}
+
+bool
+split_last(const string &s, string &lhs, string &rhs, char c)
+{
+ string::size_type offset = s.rfind(c);
+ if (offset == string::npos) {
+ lhs = s;
+ rhs = "";
+ return false;
+ }
+
+ lhs = s.substr(0, offset);
+ rhs = s.substr(offset + 1);
+ return true;
+}
+
+void
+tokenize(vector<string>& v, const string &s, char token, bool ignore)
+{
+ string::size_type first = 0;
+ string::size_type last = s.find_first_of(token);
+
+ if (s.empty())
+ return;
+
+ if (ignore && last == first) {
+ while (last == first)
+ last = s.find_first_of(token, ++first);
+
+ if (last == string::npos) {
+ if (first != s.size())
+ v.push_back(s.substr(first));
+ return;
+ }
+ }
+
+ while (last != string::npos) {
+ v.push_back(s.substr(first, last - first));
+
+ if (ignore) {
+ first = s.find_first_not_of(token, last + 1);
+
+ if (first == string::npos)
+ return;
+ } else
+ first = last + 1;
+
+ last = s.find_first_of(token, first);
+ }
+
+ v.push_back(s.substr(first));
+}
+
+/**
+ * @todo This function will not handle the smallest negative decimal
+ * value for a signed type
+ */
+
+template <class T>
+inline bool
+__to_number(string value, T &retval)
+{
+ static const T maxnum = ((T)-1);
+ static const bool sign = maxnum < 0;
+ static const int bits = sizeof(T) * 8;
+ static const T hexmax = maxnum & (((T)1 << (bits - 4 - sign)) - 1);
+ static const T octmax = maxnum & (((T)1 << (bits - 3 - sign)) - 1);
+ static const T signmax =
+ (sign) ? maxnum & (((T)1 << (bits - 1)) - 1) : maxnum;
+ static const T decmax = signmax / 10;
+
+#if 0
+ cout << "maxnum = 0x" << hex << (unsigned long long)maxnum << "\n"
+ << "sign = 0x" << hex << (unsigned long long)sign << "\n"
+ << "hexmax = 0x" << hex << (unsigned long long)hexmax << "\n"
+ << "octmax = 0x" << hex << (unsigned long long)octmax << "\n"
+ << "signmax = 0x" << hex << (unsigned long long)signmax << "\n"
+ << "decmax = 0x" << hex << (unsigned long long)decmax << "\n";
+#endif
+
+ eat_white(value);
+
+ bool negative = false;
+ bool hex = false;
+ bool oct = false;
+ int last = value.size() - 1;
+ retval = 0;
+ int i = 0;
+
+ char c = value[i];
+ if (!isDec(c)) {
+ if (c == '-' && sign)
+ negative = true;
+ else
+ return false;
+ }
+ else {
+ retval += c - '0';
+ if (last == 0) return true;
+ }
+
+ if (c == '0')
+ oct = true;
+
+ c = value[++i];
+ if (oct) {
+ if (sign && negative)
+ return false;
+
+ if (!isOct(c)) {
+ if (c == 'X' || c == 'x') {
+ hex = true;
+ oct = false;
+ } else
+ return false;
+ }
+ else
+ retval += c - '0';
+ } else if (!isDec(c))
+ goto multiply;
+ else {
+ if (sign && negative && c == '0')
+ return false;
+
+ retval *= 10;
+ retval += c - '0';
+ if (last == 1) {
+ if (sign && negative) retval = -retval;
+ return true;
+ }
+ }
+
+ if (hex) {
+ if (last == 1)
+ return false;
+
+ for (i = 2; i <= last ; i++) {
+ c = value[i];
+ if (!isHex(c))
+ return false;
+
+ if (retval > hexmax) return false;
+ retval *= 16;
+ retval += hex2Int(c);
+ }
+ return true;
+ } else if (oct) {
+ for (i = 2; i <= last ; i++) {
+ c = value[i];
+ if (!isOct(c))
+ return false;
+
+ if (retval > octmax) return false;
+ retval *= 8;
+ retval += (c - '0');
+ }
+ return true;
+ }
+
+ for (i = 2; i < last ; i++) {
+ c = value[i];
+ if (!isDec(c))
+ goto multiply;
+
+ if (retval > decmax) return false;
+ bool atmax = retval == decmax;
+ retval *= 10;
+ retval += c - '0';
+ if (atmax && retval < decmax) return false;
+ if (sign && (retval & ((T)1 << (sizeof(T) * 8 - 1))))
+ return false;
+ }
+
+ c = value[last];
+ if (isDec(c)) {
+
+ if (retval > decmax) return false;
+ bool atmax = retval == decmax;
+ retval *= 10;
+ retval += c - '0';
+ if (atmax && retval < decmax) return false;
+ if (sign && negative) {
+ if ((retval & ((T)1 << (sizeof(T) * 8 - 1))) &&
+ retval >= (T)-signmax)
+ return false;
+ retval = -retval;
+ }
+ else
+ if (sign && (retval & ((T)1 << ((sizeof(T) * 8) - 1))))
+ return false;
+ return true;
+ }
+
+ multiply:
+ signed long long mult = 1;
+ T val;
+ switch (c) {
+ case 'k':
+ case 'K':
+ if (i != last) return false;
+ mult = 1024;
+ val = signmax / mult;
+ break;
+ case 'm':
+ case 'M':
+ if (i != last) return false;
+ mult = 1024 * 1024;
+ val = signmax / mult;
+ break;
+ case 'g':
+ case 'G':
+ if (i != last) return false;
+ mult = 1024 * 1024 * 1024;
+ val = signmax / mult;
+ break;
+ case 'e':
+ case 'E':
+ if (i >= last) return false;
+
+ mult = 0;
+ for (i++; i <= last; i++) {
+ c = value[i];
+ if (!isDec(c))
+ return false;
+
+ mult *= 10;
+ mult += c - '0';
+ }
+
+ for (i = 0; i < mult; i++) {
+ if (retval > signmax / 10)
+ return false;
+ retval *= 10;
+ if (sign && (retval & ((T)1 << (sizeof(T) * 8 - 1))))
+ return false;
+ }
+ if (sign && negative) {
+ if ((retval & ((T)1 << (sizeof(T) * 8 - 1))) &&
+ retval >= (T)-signmax)
+ return false;
+ retval = -retval;
+ }
+ else
+ if (sign && (retval & ((T)1 << ((sizeof(T) * 8) - 1))))
+ return false;
+
+ return true;
+
+ default:
+ return false;
+ }
+
+ if (sign && negative)
+ return false;
+
+ if (mult > (unsigned long long)signmax)
+ return false;
+
+ if (retval > val)
+ return false;
+
+ retval *= mult;
+
+ return true;
+}
+
+#define STN(type) \
+template<> \
+bool to_number<type>(const string &value, type &retval) \
+{ return __to_number(value, retval); }
+
+STN(unsigned long long);
+STN(signed long long);
+STN(unsigned long);
+STN(signed long);
+STN(unsigned int);
+STN(signed int);
+STN(unsigned short);
+STN(signed short);
+STN(unsigned char);
+STN(signed char);
+
+template<>
+bool to_number<bool>(const string &value, bool &retval)
+{
+ string lowered = to_lower(value);
+
+ if (value == "0") {
+ retval = false;
+ return true;
+ }
+
+ if (value == "1"){
+ retval = true;
+ return true;
+ }
+
+ if (lowered == "false") {
+ retval = false;
+ return true;
+ }
+
+ if (lowered == "true"){
+ retval = true;
+ return true;
+ }
+
+ if (lowered == "no") {
+ retval = false;
+ return true;
+ }
+
+ if (lowered == "yes"){
+ retval = true;
+ return true;
+ }
+
+ return false;
+}
diff --git a/src/base/str.hh b/src/base/str.hh
new file mode 100644
index 000000000..79e33a1be
--- /dev/null
+++ b/src/base/str.hh
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __STR_HH__
+#define __STR_HH__
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <ctype.h>
+
+template<class> class Hash;
+template<>
+class Hash<std::string> {
+public:
+ unsigned operator()(const std::string &s) {
+ std::string::const_iterator i = s.begin();
+ std::string::const_iterator end = s.end();
+ unsigned hash = 5381;
+
+ while (i < end)
+ hash = ((hash << 5) + hash) + *i++;
+
+ return hash;
+ }
+};
+
+inline void
+eat_lead_white(std::string &s)
+{
+ std::string::size_type off = s.find_first_not_of(' ');
+ if (off != std::string::npos) {
+ std::string::iterator begin = s.begin();
+ s.erase(begin, begin + off);
+ }
+}
+
+inline void
+eat_end_white(std::string &s)
+{
+ std::string::size_type off = s.find_last_not_of(' ');
+ if (off != std::string::npos)
+ s.erase(s.begin() + off + 1, s.end());
+}
+
+inline void
+eat_white(std::string &s)
+{
+ eat_lead_white(s);
+ eat_end_white(s);
+}
+
+inline std::string
+to_lower(const std::string &s)
+{
+ std::string lower;
+ int len = s.size();
+
+ lower.reserve(len);
+
+ for (int i = 0; i < len; ++i)
+ lower.push_back(tolower(s[i]));
+
+ return lower;
+}
+
+// Split the string s into lhs and rhs on the first occurence of the
+// character c.
+bool
+split_first(const std::string &s, std::string &lhs, std::string &rhs, char c);
+
+// Split the string s into lhs and rhs on the last occurence of the
+// character c.
+bool
+split_last(const std::string &s, std::string &lhs, std::string &rhs, char c);
+
+// Tokenize the string <s> splitting on the character <token>, and
+// place the result in the string vector <vector>. If <ign> is true,
+// then empty result strings (due to trailing tokens, or consecutive
+// tokens) are skipped.
+void
+tokenize(std::vector<std::string> &vector, const std::string &s,
+ char token, bool ign = true);
+
+template <class T> bool
+to_number(const std::string &value, T &retval);
+
+template <class T>
+inline std::string
+to_string(const T &value)
+{
+ std::stringstream str;
+ str << value;
+ return str.str();
+}
+
+// Put quotes around string arg if it contains spaces.
+inline std::string
+quote(const std::string &s)
+{
+ std::string ret;
+ bool quote = s.find(' ') != std::string::npos;
+
+ if (quote)
+ ret = '"';
+
+ ret += s;
+
+ if (quote)
+ ret += '"';
+
+ return ret;
+}
+
+#endif //__STR_HH__
diff --git a/src/base/time.cc b/src/base/time.cc
new file mode 100644
index 000000000..5827c9a85
--- /dev/null
+++ b/src/base/time.cc
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+#include <iostream>
+#include <string>
+
+#include "base/time.hh"
+
+using namespace std;
+
+struct _timeval
+{
+ timeval tv;
+};
+
+double
+convert(const timeval &tv)
+{
+ return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
+}
+
+Time::Time(bool set_now)
+{
+ time = new _timeval;
+ if (set_now)
+ set();
+}
+
+Time::Time(const timeval &val)
+{
+ time = new _timeval;
+ set(val);
+}
+
+Time::Time(const Time &val)
+{
+ time = new _timeval;
+ set(val.get());
+}
+
+Time::~Time()
+{
+ delete time;
+}
+
+const timeval &
+Time::get() const
+{
+ return time->tv;
+}
+
+void
+Time::set()
+{
+ ::gettimeofday(&time->tv, NULL);
+}
+
+void
+Time::set(const timeval &tv)
+{
+ memcpy(&time->tv, &tv, sizeof(timeval));
+}
+
+double
+Time::operator()() const
+{
+ return convert(get());
+}
+
+string
+Time::date(string format) const
+{
+ const timeval &tv = get();
+ time_t sec = tv.tv_sec;
+ char buf[256];
+
+ if (format.empty()) {
+ ctime_r(&sec, buf);
+ buf[24] = '\0';
+ return buf;
+ }
+
+ struct tm *tm = localtime(&sec);
+ strftime(buf, sizeof(buf), format.c_str(), tm);
+ return buf;
+}
+
+ostream &
+operator<<(ostream &out, const Time &start)
+{
+ out << start.date();
+ return out;
+}
+
+Time
+operator-(const Time &l, const Time &r)
+{
+ timeval tv;
+ timersub(&l.get(), &r.get(), &tv);
+ return tv;
+}
+
+const Time Time::start(true);
diff --git a/src/base/time.hh b/src/base/time.hh
new file mode 100644
index 000000000..5731e3029
--- /dev/null
+++ b/src/base/time.hh
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SIM_TIME_HH__
+#define __SIM_TIME_HH__
+
+#include <sys/time.h>
+
+#include <iosfwd>
+#include <string>
+
+struct _timeval;
+
+class Time
+{
+ protected:
+ mutable _timeval *time;
+
+ public:
+ explicit Time(bool set_now = false);
+ Time(const timeval &val);
+ Time(const Time &val);
+ ~Time();
+
+ void set();
+ const timeval &get() const;
+ void set(const timeval &val);
+
+ double operator()() const;
+ std::string date(std::string format = "") const;
+
+ public:
+ static const Time start;
+};
+
+Time operator-(const Time &l, const Time &r);
+
+std::ostream &operator<<(std::ostream &out, const Time &time);
+
+#endif // __SIM_TIME_HH__
diff --git a/src/base/timebuf.hh b/src/base/timebuf.hh
new file mode 100644
index 000000000..f6b5b2781
--- /dev/null
+++ b/src/base/timebuf.hh
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_TIMEBUF_HH__
+#define __BASE_TIMEBUF_HH__
+
+#include <vector>
+
+template <class T>
+class TimeBuffer
+{
+ protected:
+ int past;
+ int future;
+ int size;
+
+ char *data;
+ std::vector<char *> index;
+ int base;
+
+ void valid(int idx)
+ {
+ assert (idx >= -past && idx <= future);
+ }
+
+ public:
+ friend class wire;
+ class wire
+ {
+ friend class TimeBuffer;
+ protected:
+ TimeBuffer<T> *buffer;
+ int index;
+
+ void set(int idx)
+ {
+ buffer->valid(idx);
+ index = idx;
+ }
+
+ wire(TimeBuffer<T> *buf, int i)
+ : buffer(buf), index(i)
+ { }
+
+ public:
+ wire()
+ { }
+
+ wire(const wire &i)
+ : buffer(i.buffer), index(i.index)
+ { }
+
+ const wire &operator=(const wire &i)
+ {
+ buffer = i.buffer;
+ set(i.index);
+ return *this;
+ }
+
+ const wire &operator=(int idx)
+ {
+ set(idx);
+ return *this;
+ }
+
+ const wire &operator+=(int offset)
+ {
+ set(index + offset);
+ return *this;
+ }
+
+ const wire &operator-=(int offset)
+ {
+ set(index - offset);
+ return *this;
+ }
+
+ wire &operator++()
+ {
+ set(index + 1);
+ return *this;
+ }
+
+ wire &operator++(int)
+ {
+ int i = index;
+ set(index + 1);
+ return wire(this, i);
+ }
+
+ wire &operator--()
+ {
+ set(index - 1);
+ return *this;
+ }
+
+ wire &operator--(int)
+ {
+ int i = index;
+ set(index - 1);
+ return wire(this, i);
+ }
+ T &operator*() const { return *buffer->access(index); }
+ T *operator->() const { return buffer->access(index); }
+ };
+
+
+ public:
+ TimeBuffer(int p, int f)
+ : past(p), future(f), size(past + future + 1),
+ data(new char[size * sizeof(T)]), index(size), base(0)
+ {
+ assert(past >= 0 && future >= 0);
+ char *ptr = data;
+ for (int i = 0; i < size; i++) {
+ index[i] = ptr;
+ memset(ptr, 0, sizeof(T));
+ new (ptr) T;
+ ptr += sizeof(T);
+ }
+ }
+
+ TimeBuffer()
+ : data(NULL)
+ {
+ }
+
+ ~TimeBuffer()
+ {
+ for (int i = 0; i < size; ++i)
+ (reinterpret_cast<T *>(index[i]))->~T();
+ delete [] data;
+ }
+
+ void
+ advance()
+ {
+ if (++base >= size)
+ base = 0;
+
+ int ptr = base + future;
+ if (ptr >= size)
+ ptr -= size;
+ (reinterpret_cast<T *>(index[ptr]))->~T();
+ memset(index[ptr], 0, sizeof(T));
+ new (index[ptr]) T;
+ }
+
+ T *access(int idx)
+ {
+ //Need more complex math here to calculate index.
+ valid(idx);
+
+ int vector_index = idx + base;
+ if (vector_index >= size) {
+ vector_index -= size;
+ } else if (vector_index < 0) {
+ vector_index += size;
+ }
+
+ return reinterpret_cast<T *>(index[vector_index]);
+ }
+
+ T &operator[](int idx)
+ {
+ //Need more complex math here to calculate index.
+ valid(idx);
+
+ int vector_index = idx + base;
+ if (vector_index >= size) {
+ vector_index -= size;
+ } else if (vector_index < 0) {
+ vector_index += size;
+ }
+
+ return reinterpret_cast<T &>(*index[vector_index]);
+ }
+
+ wire getWire(int idx)
+ {
+ valid(idx);
+
+ return wire(this, idx);
+ }
+
+ wire zero()
+ {
+ return wire(this, 0);
+ }
+};
+
+#endif // __BASE_TIMEBUF_HH__
+
diff --git a/src/base/trace.cc b/src/base/trace.cc
new file mode 100644
index 000000000..90db7f045
--- /dev/null
+++ b/src/base/trace.cc
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <ctype.h>
+#include <fstream>
+#include <iostream>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "base/misc.hh"
+#include "base/trace.hh"
+#include "base/str.hh"
+
+using namespace std;
+
+namespace Trace {
+const string DefaultName("global");
+FlagVec flags(NumFlags, false);
+
+//
+// This variable holds the output stream for debug information. Other
+// than setting up/redirecting this stream, do *NOT* reference this
+// directly; use DebugOut() (see below) to access this stream for
+// output.
+//
+ostream *dprintf_stream = &cerr;
+
+ObjectMatch ignore;
+
+Log theLog;
+
+Log::Log()
+{
+ size = 0;
+ buffer = NULL;
+}
+
+
+void
+Log::init(int _size)
+{
+ if (buffer != NULL) {
+ fatal("Trace::Log::init called twice!");
+ }
+
+ size = _size;
+
+ buffer = new Record *[size];
+
+ for (int i = 0; i < size; ++i) {
+ buffer[i] = NULL;
+ }
+
+ nextRecPtr = &buffer[0];
+ wrapRecPtr = &buffer[size];
+}
+
+
+Log::~Log()
+{
+ for (int i = 0; i < size; ++i) {
+ delete buffer[i];
+ }
+
+ delete [] buffer;
+}
+
+
+void
+Log::append(Record *rec)
+{
+ // dump record to output stream if there's one open
+ if (dprintf_stream != NULL) {
+ rec->dump(*dprintf_stream);
+ } else {
+ rec->dump(cout);
+ }
+
+ // no buffering: justget rid of it now
+ if (buffer == NULL) {
+ delete rec;
+ return;
+ }
+
+ Record *oldRec = *nextRecPtr;
+
+ if (oldRec != NULL) {
+ // log has wrapped: overwrite
+ delete oldRec;
+ }
+
+ *nextRecPtr = rec;
+
+ if (++nextRecPtr == wrapRecPtr) {
+ nextRecPtr = &buffer[0];
+ }
+}
+
+
+void
+Log::dump(ostream &os)
+{
+ if (buffer == NULL) {
+ return;
+ }
+
+ Record **bufPtr = nextRecPtr;
+
+ if (*bufPtr == NULL) {
+ // next record slot is empty: log must not be full yet.
+ // start dumping from beginning of buffer
+ bufPtr = buffer;
+ }
+
+ do {
+ Record *rec = *bufPtr;
+
+ rec->dump(os);
+
+ if (++bufPtr == wrapRecPtr) {
+ bufPtr = &buffer[0];
+ }
+ } while (bufPtr != nextRecPtr);
+}
+
+PrintfRecord::~PrintfRecord()
+{
+ delete &args;
+}
+
+void
+PrintfRecord::dump(ostream &os)
+{
+ string fmt = "";
+
+ if (!name.empty()) {
+ fmt = "%s: " + fmt;
+ args.prepend(name);
+ }
+
+ if (cycle != (Tick)-1) {
+ fmt = "%7d: " + fmt;
+ args.prepend(cycle);
+ }
+
+ fmt += format;
+
+ args.dump(os, fmt);
+ os.flush();
+}
+
+DataRecord::DataRecord(Tick _cycle, const string &_name,
+ const void *_data, int _len)
+ : Record(_cycle), name(_name), len(_len)
+{
+ data = new uint8_t[len];
+ memcpy(data, _data, len);
+}
+
+DataRecord::~DataRecord()
+{
+ delete [] data;
+}
+
+void
+DataRecord::dump(ostream &os)
+{
+ int c, i, j;
+
+ for (i = 0; i < len; i += 16) {
+ ccprintf(os, "%d: %s: %08x ", cycle, name, i);
+ c = len - i;
+ if (c > 16) c = 16;
+
+ for (j = 0; j < c; j++) {
+ ccprintf(os, "%02x ", data[i + j] & 0xff);
+ if ((j & 0xf) == 7 && j > 0)
+ ccprintf(os, " ");
+ }
+
+ for (; j < 16; j++)
+ ccprintf(os, " ");
+ ccprintf(os, " ");
+
+ for (j = 0; j < c; j++) {
+ int ch = data[i + j] & 0x7f;
+ ccprintf(os,
+ "%c", (char)(isprint(ch) ? ch : ' '));
+ }
+
+ ccprintf(os, "\n");
+
+ if (c < 16)
+ break;
+ }
+}
+} // namespace Trace
+
+//
+// Returns the current output stream for debug information. As a
+// wrapper around Trace::dprintf_stream, this handles cases where debug
+// information is generated in the process of parsing .ini options,
+// before we process the option that sets up the debug output stream
+// itself.
+//
+std::ostream &
+DebugOut()
+{
+ return *Trace::dprintf_stream;
+}
+
+/////////////////////////////////////////////
+//
+// C-linkage functions for invoking from gdb
+//
+/////////////////////////////////////////////
+
+//
+// Dump trace buffer to specified file (cout if NULL)
+//
+extern "C"
+void
+dumpTrace(const char *filename)
+{
+ if (filename != NULL) {
+ ofstream out(filename);
+ Trace::theLog.dump(out);
+ out.close();
+ }
+ else {
+ Trace::theLog.dump(cout);
+ }
+}
+
+
+//
+// Turn on/off trace output to cerr. Typically used when trace output
+// is only going to circular buffer, but you want to see what's being
+// sent there as you step through some code in gdb. This uses the
+// same facility as the "trace to file" feature, and will print error
+// messages rather than clobbering an existing ostream pointer.
+//
+extern "C"
+void
+echoTrace(bool on)
+{
+ if (on) {
+ if (Trace::dprintf_stream != NULL) {
+ cerr << "Already echoing trace to a file... go do a 'tail -f'"
+ << " on that file instead." << endl;
+ } else {
+ Trace::dprintf_stream = &cerr;
+ }
+ } else {
+ if (Trace::dprintf_stream != &cerr) {
+ cerr << "Not echoing trace to cerr." << endl;
+ } else {
+ Trace::dprintf_stream = NULL;
+ }
+ }
+}
+
+extern "C"
+void
+printTraceFlags()
+{
+ using namespace Trace;
+ for (int i = 0; i < numFlagStrings; ++i)
+ if (flags[i])
+ cprintf("%s\n", flagStrings[i]);
+}
+
+void
+tweakTraceFlag(const char *string, bool value)
+{
+ using namespace Trace;
+ std::string str(string);
+
+ for (int i = 0; i < numFlagStrings; ++i) {
+ if (str != flagStrings[i])
+ continue;
+
+ int idx = i;
+
+ if (idx < NumFlags) {
+ flags[idx] = value;
+ } else {
+ idx -= NumFlags;
+ if (idx >= NumCompoundFlags) {
+ ccprintf(cerr, "Invalid compound flag");
+ return;
+ }
+
+ const Flags *flagVec = compoundFlags[idx];
+
+ for (int j = 0; flagVec[j] != -1; ++j) {
+ if (flagVec[j] >= NumFlags) {
+ ccprintf(cerr, "Invalid compound flag");
+ return;
+ }
+ flags[flagVec[j]] = value;
+ }
+ }
+
+ cprintf("flag %s was %s\n", string, value ? "set" : "cleared");
+ return;
+ }
+
+ cprintf("could not find flag %s\n", string);
+}
+
+extern "C"
+void
+setTraceFlag(const char *string)
+{
+ tweakTraceFlag(string, true);
+}
+
+extern "C"
+void
+clearTraceFlag(const char *string)
+{
+ tweakTraceFlag(string, false);
+}
diff --git a/src/base/trace.hh b/src/base/trace.hh
new file mode 100644
index 000000000..5e14f1bff
--- /dev/null
+++ b/src/base/trace.hh
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_TRACE_HH__
+#define __BASE_TRACE_HH__
+
+#include <vector>
+
+#include "base/cprintf.hh"
+#include "base/match.hh"
+#include "sim/host.hh"
+#include "sim/root.hh"
+
+#ifndef TRACING_ON
+#ifndef NDEBUG
+#define TRACING_ON 1
+#else
+#define TRACING_ON 0
+#endif
+#endif
+
+#include "base/traceflags.hh"
+
+namespace Trace {
+
+ typedef std::vector<bool> FlagVec;
+
+ extern FlagVec flags;
+
+#if TRACING_ON
+ const bool On = true;
+#else
+ const bool On = false;
+#endif
+
+ inline bool
+ IsOn(int t)
+ {
+ return flags[t];
+
+ }
+
+ void dump(const uint8_t *data, int count);
+
+ class Record
+ {
+ protected:
+ Tick cycle;
+
+ Record(Tick _cycle)
+ : cycle(_cycle)
+ {
+ }
+
+ public:
+ virtual ~Record() {}
+
+ virtual void dump(std::ostream &) = 0;
+ };
+
+ class PrintfRecord : public Record
+ {
+ private:
+ const char *format;
+ const std::string &name;
+ cp::ArgList &args;
+
+ public:
+ PrintfRecord(const char *_format, cp::ArgList &_args,
+ Tick cycle, const std::string &_name)
+ : Record(cycle), format(_format), name(_name), args(_args)
+ {
+ }
+
+ virtual ~PrintfRecord();
+
+ virtual void dump(std::ostream &);
+ };
+
+ class DataRecord : public Record
+ {
+ private:
+ const std::string &name;
+ uint8_t *data;
+ int len;
+
+ public:
+ DataRecord(Tick cycle, const std::string &name,
+ const void *_data, int _len);
+ virtual ~DataRecord();
+
+ virtual void dump(std::ostream &);
+ };
+
+ class Log
+ {
+ private:
+ int size; // number of records in log
+ Record **buffer; // array of 'size' Record ptrs (circular buf)
+ Record **nextRecPtr; // next slot to use in buffer
+ Record **wrapRecPtr; // &buffer[size], for quick wrap check
+
+ public:
+
+ Log();
+ ~Log();
+
+ void init(int _size);
+
+ void append(Record *); // append trace record to log
+ void dump(std::ostream &); // dump contents to stream
+ };
+
+ extern Log theLog;
+
+ extern ObjectMatch ignore;
+
+ inline void
+ dprintf(const char *format, cp::ArgList &args, Tick cycle,
+ const std::string &name)
+ {
+ if (name.empty() || !ignore.match(name))
+ theLog.append(new Trace::PrintfRecord(format, args, cycle, name));
+ }
+
+ inline void
+ dataDump(Tick cycle, const std::string &name, const void *data, int len)
+ {
+ theLog.append(new Trace::DataRecord(cycle, name, data, len));
+ }
+
+ extern const std::string DefaultName;
+};
+
+// This silly little class allows us to wrap a string in a functor
+// object so that we can give a name() that DPRINTF will like
+struct StringWrap
+{
+ std::string str;
+ StringWrap(const std::string &s) : str(s) {}
+ const std::string &operator()() const { return str; }
+};
+
+inline const std::string &name() { return Trace::DefaultName; }
+std::ostream &DebugOut();
+
+//
+// DPRINTF is a debugging trace facility that allows one to
+// selectively enable tracing statements. To use DPRINTF, there must
+// be a function or functor called name() that returns a const
+// std::string & in the current scope.
+//
+// If you desire that the automatic printing not occur, use DPRINTFR
+// (R for raw)
+//
+
+#if TRACING_ON
+
+#define DTRACE(x) (Trace::IsOn(Trace::x))
+
+#define DCOUT(x) if (Trace::IsOn(Trace::x)) DebugOut()
+
+#define DDUMP(x, data, count) \
+do { \
+ if (Trace::IsOn(Trace::x)) \
+ Trace::dataDump(curTick, name(), data, count); \
+} while (0)
+
+#define __dprintf(cycle, name, format, args...) \
+ Trace::dprintf(format, (*(new cp::ArgList), args), cycle, name)
+
+#define DPRINTF(x, args...) \
+do { \
+ if (Trace::IsOn(Trace::x)) \
+ __dprintf(curTick, name(), args, cp::ArgListNull()); \
+} while (0)
+
+#define DPRINTFR(x, args...) \
+do { \
+ if (Trace::IsOn(Trace::x)) \
+ __dprintf((Tick)-1, std::string(), args, cp::ArgListNull()); \
+} while (0)
+
+#define DPRINTFN(args...) \
+do { \
+ __dprintf(curTick, name(), args, cp::ArgListNull()); \
+} while (0)
+
+#define DPRINTFNR(args...) \
+do { \
+ __dprintf((Tick)-1, string(), args, cp::ArgListNull()); \
+} while (0)
+
+#else // !TRACING_ON
+
+#define DTRACE(x) (false)
+#define DCOUT(x) if (0) DebugOut()
+#define DPRINTF(x, args...) do {} while (0)
+#define DPRINTFR(args...) do {} while (0)
+#define DPRINTFN(args...) do {} while (0)
+#define DPRINTFNR(args...) do {} while (0)
+#define DDUMP(x, data, count) do {} while (0)
+
+#endif // TRACING_ON
+
+#endif // __BASE_TRACE_HH__
diff --git a/src/base/traceflags.py b/src/base/traceflags.py
new file mode 100644
index 000000000..7dbaac60e
--- /dev/null
+++ b/src/base/traceflags.py
@@ -0,0 +1,316 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2004-2005 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#
+# This file generates the header and source files for the flags
+# that control the tracing facility.
+#
+
+import sys
+
+if len(sys.argv) != 2:
+ print "%s: Need argument (basename of cc/hh files)" % sys.argv[0]
+ sys.exit(1)
+
+hhfilename = sys.argv[1] + '.hh'
+ccfilename = sys.argv[1] + '.cc'
+
+#
+# The list of trace flags that can be used to condition DPRINTFs etc.
+# To define a new flag, simply add it to this list.
+#
+baseFlags = [
+ 'TCPIP',
+ 'Bus',
+ 'ScsiDisk',
+ 'ScsiCtrl',
+ 'ScsiNone',
+ 'DMA',
+ 'DMAReadVerbose',
+ 'DMAWriteVerbose',
+ 'TLB',
+ 'SimpleDisk',
+ 'SimpleDiskData',
+ 'Clock',
+ 'Regs',
+ 'MC146818',
+ 'IPI',
+ 'Timer',
+ 'Mbox',
+ 'PCIA',
+ 'PCIDEV',
+ 'PciConfigAll',
+ 'ISP',
+ 'BADADDR',
+ 'Console',
+ 'ConsolePoll',
+ 'ConsoleVerbose',
+ 'AlphaConsole',
+ 'Flow',
+ 'Interrupt',
+ 'Fault',
+ 'Cycle',
+ 'Loader',
+ 'MMU',
+ 'Ethernet',
+ 'EthernetPIO',
+ 'EthernetDMA',
+ 'EthernetData',
+ 'EthernetDesc',
+ 'EthernetIntr',
+ 'EthernetSM',
+ 'EthernetCksum',
+ 'GDBMisc',
+ 'GDBAcc',
+ 'GDBRead',
+ 'GDBWrite',
+ 'GDBSend',
+ 'GDBRecv',
+ 'GDBExtra',
+ 'VtoPhys',
+ 'Printf',
+ 'DebugPrintf',
+ 'Serialize',
+ 'Event',
+ 'PCEvent',
+ 'Syscall',
+ 'SyscallVerbose',
+ 'DiskImage',
+ 'DiskImageRead',
+ 'DiskImageWrite',
+ 'InstExec',
+ 'BPredRAS',
+ 'Cache',
+ 'IIC',
+ 'IICMore',
+ 'MSHR',
+ 'Chains',
+ 'Pipeline',
+ 'Stats',
+ 'StatEvents',
+ 'Context',
+ 'Config',
+ 'Sampler',
+ 'WriteBarrier',
+ 'IdeCtrl',
+ 'IdeDisk',
+ 'Tsunami',
+ 'Uart',
+ 'Split',
+ 'SQL',
+ 'Thread',
+ 'Fetch',
+ 'Decode',
+ 'Rename',
+ 'IEW',
+ 'Commit',
+ 'IQ',
+ 'ROB',
+ 'FreeList',
+ 'RenameMap',
+ 'LDSTQ',
+ 'StoreSet',
+ 'MemDepUnit',
+ 'DynInst',
+ 'FullCPU',
+ 'CommitRate',
+ 'OoOCPU',
+ 'HWPrefetch',
+ 'Stack',
+ 'SimpleCPU',
+ 'Sparc',
+ ]
+
+#
+# "Compound" flags correspond to a set of base flags. These exist
+# solely for convenience in setting them via the command line: if a
+# compound flag is specified, all of the corresponding base flags are
+# set. Compound flags cannot be used directly in DPRINTFs etc.
+# To define a new compound flag, add a new entry to this hash
+# following the existing examples.
+#
+compoundFlagMap = {
+ 'GDBAll' : [ 'GDBMisc', 'GDBAcc', 'GDBRead', 'GDBWrite', 'GDBSend', 'GDBRecv', 'GDBExtra' ],
+ 'ScsiAll' : [ 'ScsiDisk', 'ScsiCtrl', 'ScsiNone' ],
+ 'DiskImageAll' : [ 'DiskImage', 'DiskImageRead', 'DiskImageWrite' ],
+ 'EthernetAll' : [ 'Ethernet', 'EthernetPIO', 'EthernetDMA', 'EthernetData' , 'EthernetDesc', 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ],
+ 'EthernetNoData' : [ 'Ethernet', 'EthernetPIO', 'EthernetDesc', 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ],
+ 'IdeAll' : [ 'IdeCtrl', 'IdeDisk' ],
+ 'FullCPUAll' : [ 'Fetch', 'Decode', 'Rename', 'IEW', 'Commit', 'IQ', 'ROB', 'FreeList', 'RenameMap', 'LDSTQ', 'StoreSet', 'MemDepUnit', 'DynInst', 'FullCPU']
+}
+
+#############################################################
+#
+# Everything below this point generates the appropriate C++
+# declarations and definitions for the trace flags. If you are simply
+# adding or modifying flag definitions, you should not have to change
+# anything below.
+#
+
+import sys
+
+# extract just the compound flag names into a list
+compoundFlags = []
+compoundFlags.extend(compoundFlagMap.keys())
+compoundFlags.sort()
+
+#
+# First generate the header file. This defines the Flag enum
+# and some extern declarations for the .cc file.
+#
+try:
+ hhfile = file(hhfilename, 'w')
+except IOError, e:
+ sys.exit("can't open %s: %s" % (hhfilename, e))
+
+# file header boilerplate
+print >>hhfile, '''
+/*
+ * DO NOT EDIT THIS FILE!
+ *
+ * Automatically generated from traceflags.py
+ */
+
+#ifndef __BASE_TRACE_FLAGS_HH__
+#define __BASE_TRACE_FLAGS_HH__
+
+namespace Trace {
+
+enum Flags {
+''',
+
+# Generate the enum. Base flags come first, then compound flags.
+idx = 0
+for flag in baseFlags:
+ print >>hhfile, ' %s = %d,' % (flag, idx)
+ idx += 1
+
+numBaseFlags = idx
+print >>hhfile, ' NumFlags = %d,' % idx
+
+# put a comment in here to separate base from compound flags
+print >>hhfile, '''
+ // The remaining enum values are *not* valid indices for Trace::flags.
+ // They are "compound" flags, which correspond to sets of base
+ // flags, and are used only by TraceParamContext::setFlags().
+''',
+
+for flag in compoundFlags:
+ print >>hhfile, ' %s = %d,' % (flag, idx)
+ idx += 1
+
+numCompoundFlags = idx - numBaseFlags
+print >>hhfile, ' NumCompoundFlags = %d' % numCompoundFlags
+
+# trailer boilerplate
+print >>hhfile, '''\
+}; // enum Flags
+
+// Array of strings for SimpleEnumParam
+extern const char *flagStrings[];
+extern const int numFlagStrings;
+
+// Array of arraay pointers: for each compound flag, gives the list of
+// base flags to set. Inidividual flag arrays are terminated by -1.
+extern const Flags *compoundFlags[];
+
+/* namespace Trace */ }
+
+#endif // __BASE_TRACE_FLAGS_HH__
+''',
+
+hhfile.close()
+
+#
+#
+# Print out .cc file with array definitions.
+#
+#
+try:
+ ccfile = file(ccfilename, 'w')
+except OSError, e:
+ sys.exit("can't open %s: %s" % (ccfilename, e))
+
+# file header
+print >>ccfile, '''
+/*
+ * DO NOT EDIT THIS FILE!
+ *
+ * Automatically generated from traceflags.pl.
+ */
+
+#include "base/traceflags.hh"
+
+using namespace Trace;
+
+const char *Trace::flagStrings[] =
+{
+''',
+
+# The string array is used by SimpleEnumParam to map the strings
+# provided by the user to enum values.
+for flag in baseFlags:
+ print >>ccfile, ' "%s",' % flag
+
+for flag in compoundFlags:
+ print >>ccfile, ' "%s",' % flag
+
+print >>ccfile, '};\n'
+
+numFlagStrings = len(baseFlags) + len(compoundFlags);
+
+print >>ccfile, 'const int Trace::numFlagStrings = %d;' % numFlagStrings
+print >>ccfile
+
+#
+# Now define the individual compound flag arrays. There is an array
+# for each compound flag listing the component base flags.
+#
+
+for flag in compoundFlags:
+ flags = compoundFlagMap[flag]
+ flags.append('(Flags)-1')
+ print >>ccfile, 'static const Flags %sMap[] =' % flag
+ print >>ccfile, '{ %s };' % (', '.join(flags))
+ print >>ccfile
+
+#
+# Finally the compoundFlags[] array maps the compound flags
+# to their individual arrays/
+#
+print >>ccfile, 'const Flags *Trace::compoundFlags[] ='
+print >>ccfile, '{'
+
+for flag in compoundFlags:
+ print >>ccfile, ' %sMap,' % flag
+
+# file trailer
+print >>ccfile, '};'
+
+ccfile.close()
+
diff --git a/src/base/userinfo.cc b/src/base/userinfo.cc
new file mode 100644
index 000000000..15bd72224
--- /dev/null
+++ b/src/base/userinfo.cc
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include <string>
+
+std::string
+username()
+{
+ struct passwd *pwd = getpwuid(getuid());
+
+ return pwd->pw_name;
+}
diff --git a/src/base/userinfo.hh b/src/base/userinfo.hh
new file mode 100644
index 000000000..d8ebd443c
--- /dev/null
+++ b/src/base/userinfo.hh
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_USERINFO_HH__
+#define __BASE_USERINFO_HH__
+
+#include <string>
+
+std::string username();
+
+#endif // __BASE_USERINFO_HH__