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
This commit is contained in:
Steve Reinhardt
2006-05-22 14:29:33 -04:00
parent 86777c9db1
commit ba2eae5d52
649 changed files with 11034 additions and 266 deletions

69
src/base/bitfield.hh Normal file
View File

@@ -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__

122
src/base/callback.hh Normal file
View File

@@ -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__

141
src/base/chunk_generator.hh Normal file
View File

@@ -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__

213
src/base/circlebuf.cc Normal file
View File

@@ -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;
}

62
src/base/circlebuf.hh Normal file
View File

@@ -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__

View File

@@ -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;
}

View File

@@ -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__

View File

@@ -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__

268
src/base/cprintf.cc Normal file
View File

@@ -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();
}
}

197
src/base/cprintf.hh Normal file
View File

@@ -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__

353
src/base/cprintf_formats.hh Normal file
View File

@@ -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__

114
src/base/crc.cc Normal file
View File

@@ -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);
}

37
src/base/crc.hh Normal file
View File

@@ -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__

29
src/base/date.cc Normal file
View File

@@ -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__;

165
src/base/dbl_list.hh Normal file
View File

@@ -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__

41
src/base/endian.hh Normal file
View File

@@ -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__

195
src/base/fast_alloc.cc Normal file
View File

@@ -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

214
src/base/fast_alloc.hh Normal file
View File

@@ -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__

52
src/base/fenv.hh Normal file
View File

@@ -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__

40
src/base/fifo_buffer.cc Normal file
View File

@@ -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();
}

86
src/base/fifo_buffer.hh Normal file
View File

@@ -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

85
src/base/hashmap.hh Normal file
View File

@@ -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__

85
src/base/hostinfo.cc Normal file
View File

@@ -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;
}

43
src/base/hostinfo.hh Normal file
View File

@@ -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__

273
src/base/hybrid_pred.cc Normal file
View File

@@ -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();
}
}

201
src/base/hybrid_pred.hh Normal file
View File

@@ -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__

207
src/base/inet.cc Normal file
View File

@@ -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 */ }

407
src/base/inet.hh Normal file
View File

@@ -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__

433
src/base/inifile.cc Normal file
View File

@@ -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);
}
}

208
src/base/inifile.hh Normal file
View File

@@ -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__

58
src/base/intmath.cc Normal file
View File

@@ -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;
}
}

230
src/base/intmath.hh Normal file
View File

@@ -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__

174
src/base/kgdb.h Normal file
View File

@@ -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__ */

View File

@@ -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;
}

View File

@@ -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__

519
src/base/loader/coff_sym.h Normal file
View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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__

View File

@@ -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);
}

View File

@@ -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__

View File

@@ -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_ */

View File

@@ -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_ */

View File

@@ -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;
}

View File

@@ -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__

137
src/base/loader/symtab.cc Normal file
View File

@@ -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);
}
}

173
src/base/loader/symtab.hh Normal file
View File

@@ -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__

96
src/base/match.cc Normal file
View File

@@ -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;
}

57
src/base/match.hh Normal file
View File

@@ -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__

124
src/base/misc.cc Normal file
View File

@@ -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;
}

85
src/base/misc.hh Normal file
View File

@@ -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__

201
src/base/mod_num.hh Normal file
View File

@@ -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;
}

110
src/base/mysql.cc Normal file
View File

@@ -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 */ }

423
src/base/mysql.hh Normal file
View File

@@ -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__

129
src/base/output.cc Normal file
View File

@@ -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;
}

61
src/base/output.hh Normal file
View File

@@ -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__

273
src/base/pollevent.cc Normal file
View File

@@ -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);
}

97
src/base/pollevent.hh Normal file
View File

@@ -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__

60
src/base/predictor.hh Normal file
View File

@@ -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__

97
src/base/random.cc Normal file
View File

@@ -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);
}

126
src/base/random.hh Normal file
View File

@@ -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__

83
src/base/range.cc Normal file
View File

@@ -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);

355
src/base/range.hh Normal file
View File

@@ -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__

123
src/base/refcnt.hh Normal file
View File

@@ -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__

1175
src/base/remote_gdb.cc Normal file

File diff suppressed because it is too large Load Diff

209
src/base/remote_gdb.hh Normal file
View File

@@ -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__ */

755
src/base/res_list.hh Normal file
View File

@@ -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__

268
src/base/sat_counter.cc Normal file
View File

@@ -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("");
}

190
src/base/sat_counter.hh Normal file
View File

@@ -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__

178
src/base/sched_list.hh Normal file
View File

@@ -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

111
src/base/socket.cc Normal file
View File

@@ -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;
}

49
src/base/socket.hh Normal file
View File

@@ -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__

356
src/base/statistics.cc Normal file
View File

@@ -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 */ }

2896
src/base/statistics.hh Normal file

File diff suppressed because it is too large Load Diff

169
src/base/stats/events.cc Normal file
View File

@@ -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 */ }

66
src/base/stats/events.hh Normal file
View File

@@ -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__

73
src/base/stats/flags.hh Normal file
View File

@@ -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__

900
src/base/stats/mysql.cc Normal file
View File

@@ -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 */ }

155
src/base/stats/mysql.hh Normal file
View File

@@ -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__

View File

@@ -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__

47
src/base/stats/output.hh Normal file
View File

@@ -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__

93
src/base/stats/statdb.cc Normal file
View File

@@ -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 */ }

74
src/base/stats/statdb.hh Normal file
View File

@@ -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__

736
src/base/stats/text.cc Normal file
View File

@@ -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 */ }

77
src/base/stats/text.hh Normal file
View File

@@ -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__

49
src/base/stats/types.hh Normal file
View File

@@ -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__

41
src/base/stats/visit.cc Normal file
View File

@@ -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 */ }

63
src/base/stats/visit.hh Normal file
View File

@@ -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__

373
src/base/str.cc Normal file
View File

@@ -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;
}

141
src/base/str.hh Normal file
View File

@@ -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__

131
src/base/time.cc Normal file
View File

@@ -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);

65
src/base/time.hh Normal file
View File

@@ -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__

218
src/base/timebuf.hh Normal file
View File

@@ -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__

350
src/base/trace.cc Normal file
View File

@@ -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);
}

231
src/base/trace.hh Normal file
View File

@@ -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__

316
src/base/traceflags.py Normal file
View File

@@ -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()

41
src/base/userinfo.cc Normal file
View File

@@ -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;
}

36
src/base/userinfo.hh Normal file
View File

@@ -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__