Import changeset
Doxyfile: LICENSE: arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: arch/alpha/arguments.cc: arch/alpha/arguments.hh: arch/alpha/ev5.cc: arch/alpha/ev5.hh: arch/alpha/fake_syscall.cc: arch/alpha/faults.cc: arch/alpha/faults.hh: arch/alpha/isa_desc: arch/alpha/isa_traits.hh: arch/alpha/osfpal.cc: arch/alpha/osfpal.hh: arch/alpha/vtophys.cc: arch/alpha/vtophys.hh: arch/isa_parser.py: base/bitfield.hh: base/callback.hh: base/circlebuf.cc: base/circlebuf.hh: base/cprintf.cc: base/cprintf.hh: base/cprintf_formats.hh: base/date.cc: base/dbl_list.hh: base/endian.hh: base/fast_alloc.cc: base/fast_alloc.hh: base/fifo_buffer.cc: base/fifo_buffer.hh: base/hashmap.hh: base/inet.cc: base/inet.hh: base/inifile.cc: base/inifile.hh: base/intmath.cc: base/intmath.h: base/kgdb.h: base/misc.cc: base/misc.hh: base/mod_num.hh: base/object_file.cc: base/object_file.hh: base/pollevent.cc: base/pollevent.hh: base/random.cc: base/random.hh: base/range.hh: base/refcnt.hh: base/remote_gdb.cc: base/remote_gdb.hh: base/res_list.hh: base/sched_list.hh: base/socket.cc: base/socket.hh: base/statistics.cc: base/statistics.hh: base/str.cc: base/str.hh: base/symtab.cc: base/symtab.hh: base/trace.cc: base/trace.hh: dev/alpha_access.h: dev/alpha_console.cc: dev/alpha_console.hh: dev/console.cc: dev/console.hh: dev/disk_image.cc: dev/disk_image.hh: dev/etherbus.cc: dev/etherbus.hh: dev/etherdump.cc: dev/etherdump.hh: dev/etherint.cc: dev/etherint.hh: dev/etherlink.cc: dev/etherlink.hh: dev/etherpkt.hh: dev/ethertap.cc: dev/ethertap.hh: dev/pcireg.h: dev/simple_disk.cc: dev/simple_disk.hh: kern/tru64/tru64.hh: kern/tru64/tru64_syscalls.cc: kern/tru64/tru64_syscalls.hh: sim/async.hh: sim/base_cpu.cc: sim/base_cpu.hh: sim/cache/lzss_compression.cc: sim/cache/lzss_compression.hh: sim/cache/null_compression.hh: sim/debug.cc: sim/debug.hh: sim/eventq.cc: sim/eventq.hh: sim/exec_context.cc: sim/exec_context.hh: sim/exetrace.cc: sim/exetrace.hh: sim/host.hh: sim/hybrid_pred.cc: sim/hybrid_pred.hh: sim/intr_control.cc: sim/intr_control.hh: sim/main.cc: sim/memtest.cc: sim/memtest.hh: sim/op_class.hh: sim/param.cc: sim/param.hh: sim/pc_event.cc: sim/pc_event.hh: sim/predictor.hh: sim/prog.cc: sim/prog.hh: sim/sat_counter.cc: sim/sat_counter.hh: sim/serialize.cc: sim/serialize.hh: sim/sim_events.cc: sim/sim_events.hh: sim/sim_exit.hh: sim/sim_object.cc: sim/sim_object.hh: sim/sim_time.cc: sim/sim_time.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: sim/smt.hh: sim/static_inst.cc: sim/static_inst.hh: sim/std_types.hh: sim/system.cc: sim/system.hh: sim/universe.cc: test/Makefile: test/bitvectest.cc: test/circletest.cc: test/cprintftest.cc: test/foo.ini: test/initest.cc: test/initest.ini: test/lru_test.cc: test/nmtest.cc: test/offtest.cc: test/paramtest.cc: test/rangetest.cc: test/sized_test.cc: test/stattest.cc: test/strnumtest.cc: test/symtest.cc: test/tokentest.cc: test/tracetest.cc: util/rundiff: util/tap/Makefile: util/tap/tap.cc: util/term/Makefile: util/term/term.c: RCS to BitKeeper sim/main.cc: Initial revision sim/main.cc: Added base SMT support to SS3 distribution sim/main.cc: Corrected statistics in sim-smt Added "cnt_*" statistics to sim-smt and sim-outorder Added execution tracing to sim-outorder sim/main.cc: Numerous minor fixes. Implemented Ideal and Random fetch policies. Numerous new statistics. sim/main.cc: A few minor bug fixes to collapsing RUU & "ideal" fetch policy. sim/main.cc: Snapshot of MICRO99 work in progress. Lots of SMT stuff, EIO fixes, etc. sim/main.cc: -> New fetch stage: - Fetch a block at a time - Execute in fetch -> Removed execute from ruu_dispatch() -> Cleaned up sim/main.cc: Added build time-stamp to top of simulation log sim/main.cc: Corrected error in priority rotation routine Added -max:mult option Modified makefile to use egcs compiler Added the -t option bkdwn.pl sim/main.cc: Added memory usage display Fixed #define for number of RS_LINKs sim/main.cc: Should be able to build other simulators (sim-fast, sim-eio, etc.) using "make -f Makefile.orig" (for Alpha at least, not quite for PISA). sim/main.cc: More SMT vs. non-SMT cleanup: 'make sim-X' now works for most X. sim/main.cc: Changed function of Fetch/Decode/Dispatch pipe: a) Fetch only if room in fetch queue b) Decode only if pipe advanced as a result of dispatching a packet c) Dispatch a packet only if: 1) Room for all insns in RUU 2) Room for all insns in LSQ 3) Room for all insns in INT Register File 4) Room for all insns in FP Register File Added ROB structure a) Instruction is placed in RUU & ROB at dispatch b) Instruction is removed from RUU at writeback (except stores) c) Instruction is removed from ROB at commit Added support for counting physical register usage (INT and FP) a) subtract from "free" count at dispatch b) add back when instruction is removed from ROB Added "my_index" field to RUU_station (simplifies reverse-lookups) Removed all remaining ptrace stuff RUU & LSQ now dump squashed instructions instead of marking them squashed - No cost! Reworked commit stage to use ROB instea sim/main.cc: - Added sc_dist1 stat type as a user-transparent special case of distribution with unit-size buckets: saves an unnecessary divide on every sample - Minor changes to compile as C++ code base/fast_alloc.cc: base/fast_alloc.hh: Major reorganization. Split sim-smt.c into multiple files, compile with C++, split ROB & RUU structures, numerous small formatting and performance changes. sim/eventq.cc: sim/eventq.hh: - Replaced SimpleScalar event queue code with smt_eventq.{cc,hh} - Eliminated unused cache:flush option - Initialize bpred history regs and BTB and RAS entries to provide repeatable results - Added reset_spec_state() function: cleans up interface to spec_state.c sim/eventq.cc: sim/eventq.hh: Major reorganization of memory-system code and interface. base/fast_alloc.cc: sim/eventq.cc: sim/eventq.hh: Moved C++ files to .cc/.hh, compile C files with C compiler. base/dbl_list.hh: Initial check-in: doubly-linked list template class. sim/eventq.hh: Added when_created and when_scheduled time-tags for debugging base/fast_alloc.hh: Plug memory leak sim/eventq.cc: Runahead_Prefetch memory-system support, including miss notification events in cache. sim/eventq.cc: sim/eventq.hh: Merged branch "mt-frontend" into trunk of CVS tree Changes include: Multi-threaded Fetch & Decode Correct functionality of branch misprediction fixup (MT only) Improved stats base/intmath.cc: base/intmath.h: Integer math functions. base/fast_alloc.cc: base/fast_alloc.hh: Remove carriage returns. base/intmath.h: Add Min/Max template functions sim/prog.cc: sim/prog.hh: Adding smt-safe and smt-fast. These are functional simulators based on sim-safe and sim-fast. Despite their names, they do not actually don't handle multithreaded programs yet. The runfile functionality was pulled out of sim-smt.cc into its own files. This allows all three simulators to use runfiles. NOTE: There is a lot of duplicated code in these three simulators that should probably be separated out. The macro type definitions in engin.hh are similar to the definitions in smt-safe.cc and smt-fast.cc sim/prog.cc: Add support for loading a kernel with simplescalar. Also add skeleton for loading a disk image to boot from with simplescalar. Hook for loading palcode is in place, but not implemented. Initial parameters passed to kernel at boot time are not passed properly. sim/prog.cc: Only support loading kernel/disk image if we're running FULL_SYSTEM sim/prog.cc: Make loading PAL a separate operation. Also separate kernel loading and disk loading so that it can only be done in FULL_SYSTEM. Finally, we need to also load the console image file. I'm not sure what's in there, maybe some stuff from SRM, but it's needed for proper execution. dev/alpha_console.cc: dev/alpha_console.hh: Console device implementation from simos. This is a simple device that supports the necessary console functions for booting. sim/prog.cc: sim/prog.hh: Separate the kernel loader and the program loader for simplicity since they don't share much code. arch/alpha/alpha_memory.hh: Add this somewhat gross hack to take care of the fact that alpha has the this load locking and conditional store mechanism. sim/prog.cc: Enable asids again. This makes multithreaded programs work again. I guess you could say that this was an accidental commit. Sorry sim/main.cc: Clean up Simplescalar copyright notice. sim/prog.cc: Allow '-' for stdout as well as stdin in run file. dev/alpha_console.cc: dev/alpha_console.hh: sim/prog.cc: arch/alpha/alpha_memory.hh: Replace the interface to the memory system. Basically this change goes away from the model of passing an address, and a number of bytes and getting/setting data. This change rather creates a memory_request packet (a simple struct) that bundles all of the necessary information together to pass into the memory system when making a request. This makes the function call syntax consistent even when you have virtual to physical translation and when you have strange flags like locked, or physical that you need to pass to your memory system. It has the added benefit of allowing the layers to pass data to each other, possibly skipping layers in between. This was necessary for the whacked out behavior that store conditional has on alpha. In addition, the entire memory system is now consistent in that it will return an alignment fault due to an unaligned access. This is necessary to properly model a full alpha system, but changes the behavior of bogus bad path loads and stores that access unaligned data. Because base/fast_alloc.cc: base/fast_alloc.hh: Major enhancement of FastAlloc debug code (uncomment #define in fast_alloc.hh to enable). Can now dump summary of in-use objects by type and address/type of oldest n objects (thank you RTTI!). Should be easier to identify memory leaks now. base/res_list.hh: file res_list.hh was initially added on branch segmented_iq. sim/sat_counter.hh: file sat_counter.hh was initially added on branch segmented_iq. sim/std_types.hh: file std_types.hh was initially added on branch segmented_iq. base/fast_alloc.hh: base/res_list.hh: sim/sat_counter.hh: sim/eventq.cc: sim/eventq.hh: sim/prog.cc: sim/std_types.hh: Merged branch "segmented_iq" -> Objectized the IQ and LSQ -> Implemented Standard, Sezned, and Segmented IQ's -> Major fixes to wrong-path execution (primarily involving data dependencies) base/res_list.hh: g++ is braindead, so I cannot pull template functions out into a .cc file. Instead, pull large functions out of the class definition and inline them. This leads to a much more readable class definition. In addition, since these functions are inlined, youseems to be what is intended anyway. sim/prog.cc: Move some variables to smt_prog so that targets other than sim-smt can use them. sim/main.cc: remove the dlite debugger (for smt at least) dev/alpha_console.cc: sim/eventq.cc: sim/main.cc: I knew I had done this for a reason Change 64 bit types back to long for alpha and replace all instances of stuff like %lld to use FMT64d and the like. The reason this is necessary is because TRU64 does not understand what %lld is and will print out "ld" instead of actually printing the number. So, PLEASE use the FMTxxx stuff instead of sticking %lld, %llx, %016llx and such into the code. sim/main.cc: Don't want FMT64d for things declared 'long': this doesn't work when FMT64d evaluates to "%lld". Just use "%ld" instead. dev/console.cc: dev/console.hh: dev/disk_image.cc: dev/disk_image.hh: dev/pcireg.h: dev/simple_disk.cc: dev/simple_disk.hh: Add several initial devices for full alpha system simulation. Many of these devices are based on SimOS devices dev/alpha_console.cc: dev/alpha_console.hh: Update the alpha_console to take advantage of the simple disk interface sim/eventq.cc: sim/eventq.hh: Make it so you can service events that will happen in the future base/trace.cc: base/trace.hh: This is a simple tracing facility. The idea is that there is a bitvector where each bit represents something that you may want to trace. The end result is that you can at runtime turn on and off different tracing statements in the code so that you only see messages for things that you care about. This is only currently used in the devices framework, but I would like to see it eventually replace the debug, warn, and info functions. sim/intr_control.hh: Initial abstraction for a processor and interrupt controller arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: Add full support for the SYSTEM_EV5 model in smt-safe. With this model, the user should be able to boot Tru64 unix. Several aspects of the memory subsystem were changed to accomidate this ability: - The C memory access functions no longer return an md_fault_type. - The prot_* functions no longer take a memrequest, and no longer return an md_fault type. They now take a single address and a size. This is because the prot_* functions don't need translation abilities, etc. - The prot_* functions will by default fail to work unless they are specifically implemented for the class that you want to use them with. - The unaligned parameter to the READ_* and WRITE_* function calls was added back so that exceptions that occur on STQ_U, LDQ_U, etc get the proper faulting address. - The memory controller now supports adding an arbitrary number of objects at arbitrary memory ranges so that a variety of devices can be accomidated. - The physical_memory class now not only emulates a specific amount of memor base/trace.cc: Check for existence of environment variable dev/console.cc: Temporary fix to get this to compile under Linux. sim/main.cc: Flush stdout before dumping stats. sim/exec_context.cc: sim/exec_context.hh: sim/exetrace.cc: sim/exetrace.hh: sim/main.cc: sim/prog.cc: sim/prog.hh: arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: arch/alpha/fake_syscall.cc: Pull per-cpu variables into cpu_t object as first step toward multiprocessor support. Also encapsulated execution context into a single object. Program loading code also significantly reorganized. Syscall redirection to host machine temporarily broken (must use EIO files for now). arch/alpha/fake_syscall.cc: sim/eventq.cc: sim/exec_context.cc: sim/exetrace.cc: sim/main.cc: sim/prog.cc: Update source tree to deal with shuffling of files and renaming of files. Maybe a tiny bit of style here and there for kicks too. sim/prog.cc: Fix more stuff for reorg. arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: arch/alpha/fake_syscall.cc: base/dbl_list.hh: base/fast_alloc.cc: base/fast_alloc.hh: base/intmath.cc: base/intmath.h: base/res_list.hh: base/trace.cc: base/trace.hh: dev/alpha_console.cc: dev/alpha_console.hh: dev/console.cc: dev/console.hh: dev/disk_image.cc: dev/disk_image.hh: dev/pcireg.h: dev/simple_disk.cc: dev/simple_disk.hh: sim/main.cc: sim/eventq.cc: sim/eventq.hh: sim/exec_context.cc: sim/exec_context.hh: sim/exetrace.cc: sim/exetrace.hh: sim/intr_control.hh: sim/prog.cc: sim/prog.hh: sim/sat_counter.hh: sim/std_types.hh: Some style changes remove all of the $Log$ crap add $Id$ strings to the top of all files. arch/alpha/alpha_memory.cc: Convert memory request objects to have a bitvector of flags. sim/sat_counter.hh: Minor bug-fixes to statistics & options Saturating counter wasn't initializing properly arch/alpha/fake_syscall.cc: Compile on OpenBSD base/fast_alloc.cc: dev/console.cc: dev/disk_image.cc: sim/eventq.cc: sim/eventq.hh: sim/exec_context.hh: sim/exetrace.cc: sim/exetrace.hh: sim/intr_control.hh: sim/prog.cc: sim/sat_counter.hh: Move extern "C" statements out of C++ files and into the C headers with #ifdef __cplusplus guarding the extern. base/str.cc: base/str.hh: My lame old reference counting string class. It's really not too bad. base/intmath.cc: removed unused variable sim/main.cc: add option -inifile to load the config file base/inifile.cc: base/inifile.hh: sim/main.cc: rename configfile to inifile base/intmath.h: Functions to determine if a character is hex, dec, oct. Convert hex to int base/str.cc: base/str.hh: Add a tokenize function. Fix a bug in the CopyRight function Add a const iterator Add a string to number function that will deal with hex, decimal, octal, positive numbers and a few suffixes. Complete with bounds checking and syntax checking base/inifile.cc: base/inifile.hh: Cope with fix in CopyRight function from the String class. Add a find default which whill check for a Default= parameter. Add #include guards dev/alpha_console.cc: style. change assertion sim/sat_counter.hh: Added instruction-type identification methods to dyn_inst Continued work on the segmented IQ: - Stats - Seg0 load mechanisms - "short" dump function - free_slots_last_cycle model improvement Added stats to sat_counter sim/main.cc: Parse .ini file for options in main.cc. sim/main.cc: Reindent following style guide. sim/sat_counter.hh: Updates to the segmented IQ sim/hybrid_pred.hh: Initial check-in sim/predictor.hh: Initial check-in of predictor Mods to predictor stats sim/hybrid_pred.hh: sim/predictor.hh: sim/sat_counter.hh: Class heirarchy fixes sim/predictor.hh: sim/sat_counter.hh: Now the predictors actually work! sim/sat_counter.hh: Final fixes to the SaturatingCounterPred Corrections to the LRP and HMP sim/sat_counter.hh: Bug fixes and predictor mods to segmented IQ during ISCA-2002 work Dumping of queue contents is a little more flexible for debugging arch/alpha/fake_syscall.cc: sim/prog.cc: Updated fake syscall support (for most common syscalls) so we can once again run straight binaries (not just EIO files). sim/sat_counter.hh: Final updates (for now) to the Segmented IQ Cleaning up the fetch stage Speed improvements to the Saturating Counter Predictor Object sim/prog.cc: sim/prog.hh: Fix parameter bug in process_t::dup_fd (causing stdio fd's not to get remapped correctly). base/str.hh: Add forward decl of class ostream base/inifile.cc: base/inifile.hh: Rename members to conform to common style. base/inifile.cc: Oops... looks like CPP_PIPE doesn't work. sim/main.cc: sim/sat_counter.hh: sim/sim_object.cc: sim/sim_object.hh: New configuration scheme based on .ini files and hierarchical descriptions. Currently in a transitional state: only sim_smt CPU, IQ, Cache, Bus, and Mem objects are configured this way. Old mmodel.{hh,cc} completely gone. base/inifile.cc: Fix pipe directionality for Linux: CPP_PIPE works again. sim/sim_object.cc: Updates for INI-file parameters for Seznec and Segmented IQ models Fixed naming of IQ classes sim/sim_object.cc: sim/sim_object.hh: - Minor revisions to ParamContext, SimObjectBuilder, etc. to allow creation of SimObjects outside of configuration hierarchy. - Encapsulated magic boilerplate for object creation in macros to simplify usage and make future changes like this simpler. arch/alpha/fake_syscall.cc: sim/exec_context.cc: sim/exec_context.hh: sim/prog.cc: sim/prog.hh: Rename process_t --> Process, eio_process_t -> EioProcess, live_process_t -> LiveProcess base/str.cc: base/str.hh: flesh out string class base/str.cc: This time commit the right file. base/str.cc: fix Tokenize for the case where the last string is only a single character sim/sim_object.cc: Instantiate Param<String>::showValue(). sim/sim_object.cc: sim/sim_object.hh: - Auto-register global parameter contexts for non-SimObject parameters - added ParamContext::parseAllContexts() - Finish and test enum params (SimpleEnumParam, MappedEnumParam) - Add vector-valued parameters: VectorParam<T>, SimObjectVectorParam, SimpleEnumVectorParam, MappedEnumVectorParam - Factor parsing & displaying functions to share code between scalar and vector parameter objects - Fix bug where a SimObjectClass constructor could be called before the static SimObjectClass::classMap constructor - Add "help" functions to dump parameter descriptions (ParamContext::describeAllContexts() and SimObjectClass::describeAllClasses()) sim/main.cc: Dump out config file parameters on '-h' cmd-line argument. sim/sim_object.cc: sim/sim_object.hh: - Add showType() method to display parameter type as string for help - Change EnumParam types to include specific enum type (avoids casting) sim/sim_object.hh: Minor updates for statistics, new compilers, etc. Moved some options into new options model base/inifile.cc: base/inifile.hh: sim/exetrace.cc: sim/exetrace.hh: sim/main.cc: sim/param.cc: sim/param.hh: sim/prog.cc: sim/prog.hh: sim/sim_object.cc: sim/sim_object.hh: Eliminated old SimpleScalar options package from sim_smt, shifting everything over to new parameter objects fed by .ini-style configuration files. Parameters can be set on command line using '--<sec>:<param>=<value>'. All other cmd-line options are assumed to be config file names, except '-h' prints help msg. Got rid of *_reg_options(), *_check_options(), *_uninit() calls. Moved more initialization into constructors; remaining code is now automagically executed by providing checkParams() and cleanup() methods on ParamContext-derived objects. (See exetrace.cc, for example.) Runfile is gone; processes are initialized as simulation objects. Split parameter code out of sim_object.{cc,hh} into param.{cc,hh}. Moved a bunch of CPU object methods from sim_smt.cc to cpu.cc. smt_reg_stats calls now need to know number of threads. Can be done by explicit argument to global function, or (for backward compatibility) calling CPU object method with same parameters as old global function. Renamed "SimControl" par base/circlebuf.cc: base/circlebuf.hh: Add a circular buffer class that holds string data. You can set the size of the buffer, and basically keep writing to it, and later read the last size bytes from the buffer. kinda like tail -f test/Makefile: test/bitvectest.cc: test/circletest.cc: test/foo.ini: test/initest.cc: test/initest.ini: test/strnumtest.cc: test/tokentest.cc: Add a little bit of test framework and a bunch of initial tests test/paramtest.cc: Move the param test thing to the new test framework, though it doesn't compile right now since I couldn't figure it out base/inifile.cc: Disable pipes for cpp: hangs if cpp output is bigger than kernel pipe buffer. sim/sim_object.cc: Check for accidental redefinition of SimObject class names. base/str.cc: Support exponents in StringToNumber. It should be noted, that while StringToNumber does bounds checking, the bounds checking has not been mathmatically proven, so it could have mistakes. base/range.hh: Simple range class that will parse a range and provides comparison operators base/trace.hh: New tracing options test/Makefile: test/rangetest.cc: add a new test for the Range class sim/exetrace.cc: sim/exetrace.hh: sim/main.cc: Create an ExecutionTrace class that encapsulates the old exe_trace stuff. Convert the last of the old options stuff to the new params and get rid of the old options files. Get rid of the old range files. arch/alpha/fake_syscall.cc: Stupid linuxisms sim/main.cc: sim/sim_object.cc: Output config info to cerr instead of cout. sim/main.cc: Load default.ini if the file exists test/Makefile: test/bitvectest.cc: test/circletest.cc: test/initest.cc: test/paramtest.cc: test/rangetest.cc: test/strnumtest.cc: test/tokentest.cc: Add Id tags sim/sim_object.cc: Bug fix to allow use of "default=" in ini-files sim/prog.cc: Fix for wacky compiler bug base/inifile.cc: Modified some ROB statistic labels to make them more uniform Re-implimented rob-caps arch/alpha/vtophys.cc: arch/alpha/vtophys.hh: Add support for doing virtual to physical translation using the in-memory page table base/kgdb.h: base/remote_gdb.cc: base/remote_gdb.hh: Basic support for remote debugging base/pollevent.cc: base/pollevent.hh: A class abstraction for poll base/socket.cc: base/socket.hh: Support for tcp server sockets base/symtab.cc: base/symtab.hh: simple symbol table loaded from a preprocessed file dev/alpha_access.h: dev/alpha_console.hh: split alpha access into a separate file so that building console code is simpler dev/disk_image.cc: dev/disk_image.hh: use a string for the disk image file name instead of a char * arch/alpha/alpha_memory.cc: Make the MCSR segment check more explicit rearrange base/trace.cc: Make trace stuff use new parameter stuff base/trace.hh: Fix DPRINTF and DPRINTFN macros Add a few new trace flags sim/exetrace.cc: sim/exetrace.hh: Add more features to the exetrace stuff. Make use of the symbol table support. base/remote_gdb.cc: fix DPRINTFs dev/alpha_console.cc: dev/console.cc: dev/console.hh: Change the console framework to use the new pollevent stuff. This adds support for a console that can be attached and detached at runtime via a tcp connection (telnet). There is also a circular buffer integrated into the console so that upon connection, any missed console text is output to the console. In the future, this should easily allow for multiple system consoles to be attached. base/inifile.cc: base/str.hh: Move the string hash function base/symtab.cc: base/symtab.hh: sim/exetrace.cc: Add support to lookup symbols by name, and take advantage of that support for looking up symbols for panic and badaddr base/str.cc: base/str.hh: change to new formatting. naming convention still dosn't match new style dev/console.cc: dev/console.hh: Fix console code so that typed characters are properly handled. When clearing interrupts, be explicit with regards to which ones. arch/alpha/vtophys.cc: a tad bit of error checking sim/exetrace.cc: sim/exetrace.hh: EXE-Trace extensions Disabled "good_mem" memory layer... this still needs to be properly removed base/kgdb.h: Add more kgdb commands base/trace.hh: Tracing for ISP sim/exec_context.cc: sim/exec_context.hh: sim/exetrace.cc: sim/exetrace.hh: sim/prog.cc: sim/prog.hh: Update to BTB functionality Fixed numerous statistics Fixed path of store instructions so that they _all_ go through issue stage Updates to exetrace functionality sim/eventq.cc: sim/eventq.hh: Replaced every-cycle termination checks in sim_main() with events. Added per-thread instruction-count-based event queues to handle termination based on committed instruction count. These are now specified via parameters to the FullCPU object (max_insts_any_thread and max_insts_all_threads) rather than global parameters under the [max] context. Also replaced break_cycle check with DebugBreakEvent. Some cleanup of eventq.{cc,hh}. sim/prog.hh: Don't die if included under FULL_SYSTEM: just skip contents. sim/base_cpu.cc: sim/base_cpu.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: Added SimpleCPU object to do sim_safe type simulation in sim_smt. Created abstract base class BaseCPU as common parent of (detailed) CPU and SimpleCPU. sim/exec_context.cc: sim/exec_context.hh: sim/prog.cc: sim/prog.hh: Register Process object stats using SimObject reg_stats() method rather than indirectly via Thread end exec_context objects. sim/base_cpu.cc: sim/base_cpu.hh: sim/main.cc: sim/sim_object.cc: sim/sim_object.hh: Changes to eliminate the global 'the_cpu' pointer to allow for mutliple CPUs/systems. Specifically: - Add findMaxThreadsPerCPU() and tickAll() static methods to BaseCPU class. - Added generic printExtraOutput() method for all SimObjects, to dump output at the end of simulation that is not covered by stats. Use this hook on CPU object to call dump_floss_reasons(). sim_aux_stats() is now obsolete. - printExtraOutput() takes an ostream& rather than a FILE*, so dump_floss_reasons() had to be converted to C++ I/O. - Fixed a bug in floss_reasons.cc where an additional mem_access_result_t item (MA_NOT_PREDICTED) did not have a corresponding entry in mem_access_result_item_descr. This resulted in "(null)" being printed with sprintf I/O (which no one had noticed, apparently), but caused a segfault using streams. sim/exec_context.hh: sim/main.cc: sim/prog.cc: sim/prog.hh: sim/sat_counter.hh: sim/simple_cpu.cc: Rename many stats to include config hierarchy path, so results from different CPUs/systems can be distinguished. Move stats.c/h into C++... renamed to stats.cc/hh. Added overloads of most stat registration functions to allow 'string' rather than 'char *' stat names & formulas... no more sprintf needed! sim/base_cpu.cc: sim/base_cpu.hh: Add sim_num_insn stats as per-CPU and total number of simulated instructions so we can continue to calculate sim_inst_rate. sim/simple_cpu.cc: Fix sim_num_insn stat for SimpleCPU. sim/simple_cpu.cc: sim/simple_cpu.hh: Move global memory interface objects into SimpleCPU object. Made read/write functions SimpleCPU members for easier access to same. Can now do multiple systems in non-FULL_SYSTEM mode. sim/param.hh: sim/sim_object.cc: sim/sim_object.hh: SimObjects now look in the .ini database first using the object instance name (e.g., sys.cpu0) *then* using the configuration class name (e.g., DetailedCPU). This makes it easier to use a common description but override a few simple things like the workload. base/remote_gdb.cc: dev/console.cc: dev/disk_image.cc: Make ConsoleListener & GDBListener explicitly print which ports they're listening on. arch/alpha/alpha_memory.cc: arch/alpha/ev5.cc: arch/alpha/ev5.hh: arch/alpha/fake_syscall.cc: arch/alpha/vtophys.hh: base/remote_gdb.cc: base/symtab.cc: base/symtab.hh: dev/alpha_console.cc: dev/alpha_console.hh: dev/console.cc: sim/exec_context.cc: sim/exec_context.hh: sim/exetrace.cc: sim/exetrace.hh: sim/main.cc: sim/prog.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: Cleanup of full-system global variables, primarily in simple_cpu.cc, to allow multi-system simulations. (Multiple systems not yet yested though.) Also changes to build sim_smt in full-system mode (though with only SimpleCPU and not the full timing CPU for now). Still to do: minimize changes in SimpleCPU code between full-system and application modes... way too many ifdefs there. Much of the full-system stuff moved into SimpleCPU should be put in a new System object to allow multiprocessor simulations. Converted last remaining modules from C to C++ (mostly in /old). Renamed all .c files to .cc and a few .h files to .hh. Renamed architecture-specific files in arch/$TARGET from $TARGET.{cc,hh,def} to machine.{cc,hh,def} to get rid of pointless intermediate files in object directory. Split exo-specific definitions out of machine.hh into machine_exo.h. Specifics: In machine.def, null resource descriptors must be FUClamd_NA (and not NA) to pass C++ type checking. Enhanced error checking/reporting in bas base/range.hh: Use the templated type for intermediate storage. Added "valid" flag and method to the user can determine if the range parse or assignment was successful. sim/eventq.cc: sim/eventq.hh: Modifications to properly count commited instructions... [no impacts] test/Makefile: test/offtest.cc: New test test/foo.ini: test/initest.cc: add Another piece to the test arch/alpha/ev5.hh: Properly do alternate mode arch/alpha/alpha_memory.cc: arch/alpha/ev5.cc: sim/simple_cpu.cc: arch/alpha/ev5.cc: arch/alpha/isa_traits.hh: base/hashmap.hh: formatting arch/alpha/alpha_memory.cc: C style comment -> C++ style arch/alpha/alpha_memory.cc: more formatting arch/alpha/alpha_memory.cc: Add ALT_MODE support to the tlb lookup and make mode handling more sane test/Makefile: test/symtest.cc: Add a test for the symboltable base/symtab.cc: Avoid some temporary objects base/trace.cc: add a hexdump like dump function for dumping memory base/trace.hh: Add more trace flags Add DUMP which does a hexdump with semantics like DPRINTF flush standard out after a debugging print or dump dev/simple_disk.cc: Add some debugging dumps sim/param.cc: sim/param.hh: sim/sim_object.cc: Because of order of construction, call a function that will return a ParamList that will construct it as soon as it is needed dev/pcireg.h: sim/simple_cpu.cc: sim/simple_cpu.hh: Flesh out the pci configuration space support. Add configuration file support for vendor ID and device ID. Clean up debugging sim/simple_cpu.cc: sim/simple_cpu.hh: Don't execute pmap_scavenge_boot. rename console_panic_addr to panic_addr. change some warn()s to DPRINTF() base/pollevent.cc: base/pollevent.hh: Don't poll every cycle. Use SIGIO to kick a poll off. Make it possible to disable events sim/exetrace.cc: sim/exetrace.hh: sim/simple_cpu.cc: Completely rework the exetrace stuff. Make a clas that holds all of the trace data for a particular cycle. Add a N entry trace log so that one can dump the last N cycles leading up to some sort of crash. When printing a branch instruction, print the target symbol if available instead of the address dev/console.cc: dev/console.hh: sim/simple_cpu.cc: Make console code deal with not being polled every cycle sim/simple_cpu.cc: Don't interrupt while in PAL base/remote_gdb.cc: base/remote_gdb.hh: constify some functions. fix some buffer handling. add some debugging help sim/param.cc: Initialize paramList to NULL sim/exetrace.cc: sim/exetrace.hh: sim/simple_cpu.cc: Rework the execution trace stuff again. Merge the cycle log and the exetrace into one class. Stick the TraceData in the dyn_inst_t class. Put the read_foo and write_foo functions in the dyn_inst_t class. This gets rid of the memaccess namespace. sim/exetrace.cc: sim/exetrace.hh: sim/simple_cpu.cc: Don't worry about which thread to trace right now. Fix that later. Add better support for merged logging and tracing. Make sure that there is a place to put data when there is no log. Make tracing work for non-system. sim/exetrace.hh: tracing() method must not return true if not initialized sim/base_cpu.cc: sim/main.cc: Many fixes to statistics (especially distributions) Many renamed statistics (added CPU name to all except cache stuff) dev/alpha_access.h: dev/alpha_console.cc: dev/alpha_console.hh: dev/console.cc: dev/console.hh: dev/disk_image.cc: dev/disk_image.hh: dev/simple_disk.cc: dev/simple_disk.hh: sim/intr_control.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: style fixes: Make class names follow the ClassName style Indenting based on four spaces sim/param.cc: Added pipetracing (The trace output _should_ be compatible with the original Simplescalar output, making their visualization tools available to us and providing us with a more detailed debugging tool than exetrace) base/trace.hh: Separate disk and disk data add tlaser uart arch/alpha/alpha_memory.cc: arch/alpha/ev5.cc: Make this use C++ instead of void * voodoo base/symtab.cc: base/symtab.hh: sim/exetrace.cc: sim/exetrace.hh: constify sim/param.hh: SimObjects are always pointers. Make this clear, and add the -> operator sim/prog.hh: fix comment dev/pcireg.h: Don't depend on order of #includes sim/exetrace.cc: Make logging work without tracing arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: dev/alpha_console.cc: dev/alpha_console.hh: dev/console.cc: dev/console.hh: dev/disk_image.cc: dev/disk_image.hh: dev/simple_disk.cc: dev/simple_disk.hh: sim/intr_control.cc: sim/intr_control.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: Turn all of the devices and system stuff into SimObjects. Add many extra parameters to have config file flexibility base/sched_list.hh: file sched_list.hh was initially added on branch clustering. dev/console.cc: dev/disk_image.cc: Don't assume variables are initiaized to be zero sim/simple_cpu.cc: don't forget to dump the trace data if we're tracing arch/alpha/ev5.cc: arch/alpha/ev5.hh: sim/simple_cpu.cc: remove md_done_hwrei which was a hack that helped me make the trace output look like what I was able to get out of SimOS. Since we're more advanced than them, it's not needed sim/simple_cpu.cc: Try to make the trace more representative of what's going on. (Mainly around disruptions.) sim/simple_cpu.cc: Disable this code since it uses a hardcoded address. This may be more useful in the future though. sim/simple_cpu.cc: base/statistics.hh: oops base/trace.hh: style base/trace.hh: add tracing to interrupts sim/simple_cpu.cc: Removed old access call in CPUMemInterface and added MemREqs to the pipeline. sim/prog.cc: Give main memory a name to fix statistics. sim/main.cc: sim/serialize.cc: sim/serialize.hh: sim/sim_object.cc: sim/sim_object.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: Added basic infrastructure to do checkpointing. Simple test in SimpleCPU. base/trace.hh: Added support for checkpoint/serialization Added Serilize to list of know flags sim/param.cc: sim/serialize.hh: Added support for checkpoint/serialization Added Serilize to list of know flags Now add implicit SimObjects to the ConfigHierarchy so they can be unserialized. sim/serialize.hh: sim/simple_cpu.cc: Added WH64 implementation and dependencies Added WH64 implementation, and added the ability to do stores of more than 4 bytes, and sett loads to 8 bytes. base/inifile.hh: base/str.hh: Use functors for the hash functions for the hashtable class. Pulled up from the pisa branch with a few modifications. sim/eventq.cc: sim/eventq.hh: sim/serialize.cc: sim/serialize.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: Updated to Hierarchical naming Infrastructure for checkpointing. base/inifile.cc: base/inifile.hh: base/trace.hh: sim/exec_context.hh: sim/exetrace.cc: sim/main.cc: sim/param.cc: sim/param.hh: sim/simple_cpu.cc: test/Makefile: - Merge PISA branch onto HEAD - Tag before merge: HEAD_PRE_BR_PISA_MERGE - Tag after merge: HEAD_POST_BR_PISA_MERGE - Similar tags on PISA branch - Add port to SimpleScalar/PISA - New PISA instructions: itouch spill reload map unmap - Add prefetch implementation - Prefetch cache - Cache buffer (victim/prefetch buffers) - Prefetch queue - itouch instruction - Add functional SLAT implementation sim/main.cc: Make this work in non Linux base/remote_gdb.cc: sim/base_cpu.hh: sim/simple_cpu.cc: Make FULL_SYSTEM work again after the pisa merge. Random cleanups. sim/main.cc: sim/memtest.cc: sim/memtest.hh: Removed rules to make SIM_MEMTEST, added memtest.cc to smt source list Renamed sim_memtest to memtest. Memtest now extends BaseCPU and can be dropped into sim_smt. Still need to add the ability to stop it running without a manual ctrl-C though. Memtest currently does not test copies, just reads and writes. The multiple MSHR/Cache changes broke copying along the way. Just touched main to help debug (needed to give a set random seed). Its back to normal. sim/main.cc: undo erik's mistaken commit arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: arch/alpha/vtophys.cc: base/circlebuf.cc: base/circlebuf.hh: base/inifile.cc: base/inifile.hh: base/pollevent.cc: base/pollevent.hh: base/range.hh: base/remote_gdb.cc: base/str.cc: base/str.hh: base/symtab.cc: base/symtab.hh: base/trace.cc: base/trace.hh: dev/alpha_console.cc: dev/alpha_console.hh: dev/console.cc: dev/console.hh: dev/disk_image.cc: dev/disk_image.hh: dev/simple_disk.cc: dev/simple_disk.hh: sim/base_cpu.cc: sim/base_cpu.hh: sim/eventq.cc: sim/eventq.hh: sim/exec_context.cc: sim/exetrace.cc: sim/exetrace.hh: sim/hybrid_pred.hh: sim/intr_control.cc: sim/intr_control.hh: sim/main.cc: sim/memtest.cc: sim/memtest.hh: sim/param.cc: sim/param.hh: sim/prog.cc: sim/prog.hh: sim/serialize.cc: sim/serialize.hh: sim/sim_object.cc: sim/sim_object.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: test/bitvectest.cc: test/foo.ini: test/initest.cc: test/initest.ini: test/paramtest.cc: test/rangetest.cc: test/strnumtest.cc: test/symtest.cc: test/tokentest.cc: - Get rid of my String class, the Vector class, the bitvector class, and my doubly linked list class. - Convert tokenize, to_number (formerly StringToNumber) and eat_white to function on stl strings. - Change most cases of char * and const char * to string, or const string & - Some formatting and style nits, but not too many. sim/param.cc: test/bitvectest.cc: use resize, not reserve to change the size of the actual vector base/str.hh: fix to_lower dev/console.cc: better tracing sim/memtest.cc: sim/memtest.hh: Added support for CoherenceTest Fixed small error that was leading to a fixed address being used half of the time. sim/exetrace.cc: sim/exetrace.hh: Improvements to EXE-Trace: Displays thread number (optionally) Doesn't display 'count' field (optionally) 'Extended' output lines up nicely sim/memtest.cc: Fixed a print warning in memtest.cc sim/exetrace.hh: sim/main.cc: sim/serialize.cc: sim/serialize.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: - Merge SLAT changes - Add stats to prefetch cache to track cycles lost due to each miss address - Get simple_cpu and FULL_SYSTEM to compile again. I'm not sure these will run correctly (simple_cpu should) but it is an improvement over what's currently available. Split the engine files into generic, cpu-specific and isa-specific files to isolate the various parts of the engine code. This is quite hackish in places due to machine.def (e.g. see comments in execute.cc). Further cleanup is warranted but it compiles and passes smt-test. Later commits will remove unused code. base/trace.hh: sim/param.cc: sim/sim_object.cc: add a new DTRACE macro that tests a trace variable if tracing is on, or evaluates to fals if tracing is off. Avoids #if TRACING_ON/#endif add an option for wheter or not you want the parameter stuff dumped while the simulator is starting sim/exetrace.cc: sim/exetrace.hh: Make the execution trace print the way it did before steve's last change. Also, pass the flags in a more intelligent manner rather than adding new function parameters all over the place. sim/exetrace.hh: sim/simple_cpu.hh: make exetrace work in FULL_SYSTEM after dave's last changes. Exetrace could probably be improved more to remove most of the #ifdef FULL_SYSTEM junk. Not today though base/trace.hh: new trace flags dev/alpha_console.cc: size was too big dev/pcireg.h: new device ID for simos ethernet device dev/disk_image.cc: dev/simple_disk.cc: dev/simple_disk.hh: be smarter about using stl strings sim/pc_event.cc: sim/pc_event.hh: PC based event system sim/simple_cpu.cc: Make all existing pc based stuff use the new pc based events base/trace.cc: base/trace.hh: sim/param.cc: sim/sim_object.cc: If we're not tracing, print out the configuration junk. If we are tracing, the configuration printing is default sim/exetrace.cc: - Fix bogus references to omitCount and includeTnum. base/kgdb.h: base/remote_gdb.cc: base/remote_gdb.hh: TONS of improvements to remote kernel debugging. - Use the pc based events stuff to simulate hardware breakpoints. - Implement the set/clear breakpoint/watchpoint function, though only breakpoints are implemented right now. Both software and hardware breakpoints are implemented as hardware breakpoints. - Fix numerous bugs in single stepping, and make temporary breakpoints use hardware breakpoints instead of software breakpoints. - Add tons of debugging stuff to help with future remote debugger debugging. (No, that was not an accidental doubling.) - Implement part of the query variable function. - Remove old cruft that we don't need. - Improve comments dev/disk_image.cc: dev/disk_image.hh: Copy on write disk support This code uses a hash table to implement copy on write support to disk image blocks. There is also support to write out the table and load it back in. dev/simple_disk.cc: This class uses std::string sim/simple_cpu.hh: don't need these base/circlebuf.cc: base/circlebuf.hh: Add some size information so we can keep track of wheter or not the buffer is empty arch/alpha/vtophys.cc: simplify base/object_file.cc: base/object_file.hh: initial framework for sucking in an object file and figuring out some stuff for it. Support for ecoff and a header for elf. There is nothing for relocations, but the symbol information is available so an external program is no longer required for that. base/symtab.cc: base/symtab.hh: Update some of the symbol table stuff to add support for manual insertion of symbols. This is used by the object file code so that we can read the table from the object file and stick it into the more efficient symtab test/Makefile: test/nmtest.cc: test program for using the symbol table code. Basically allows one to look up a symbol in an object file dev/console.cc: dev/console.hh: Clean up the console code, add an input buffer queue to avoid leaving data in the socket buffer. This allows us to preprocess data as it comes in for things such as telnet support. There is some minimal telnet support in here but it isn't working very well, and isn't enabled by default sim/simple_cpu.cc: sim/simple_cpu.hh: Make the various pc based events part of the CPU object instead of being global sim/simple_cpu.cc: sim/simple_cpu.hh: Do the badaddr stuff far more intelligently. Basically, what we do now is first determine if the address goes to any proper device. If not, the address is bad. If so, ask the device whether the address is any good or not. The default case is that a device will say that all of its addresses are good, but there are some devices that don't follow this paradigm. dev/alpha_console.cc: dev/alpha_console.hh: sim/intr_control.cc: sim/intr_control.hh: sim/universe.cc: Make the tick frequency a global parameter and have all devices work from that Also, make the timer interrupt delay parameterizeable (and make the default shorter). This should make boot happen a little faster base/refcnt.hh: Simple reference counting class. Could be replaced by boost shared_ptr some day. Classes that are reference counted must have exported functions incref() and decref() for manipulating the reference count. This doesn't have the convenience of shared_ptr where the shared classes can be used unmodified, but it also means that the refcnt pointer (the pointer in this code) is the size of a normal pointer for this system. dev/etherbus.cc: dev/etherbus.hh: dev/etherpkt.hh: Initial hack at a ethernet device model and an ethernet bus model. Known to be broken at this point arch/alpha/alpha_memory.cc: sim/simple_cpu.cc: Memory system enhancements: - Functional implementation of load-locked/store-conditional in main_memory object (the functional memory object for non-full-system mode). This code should eventually be extracted out and applied to both main_memory and physical_memory so that it works in full-system mode as well. Moved lock_flag & lock_addr from system registers to control registers so they're available in non-full-system mode. - Moved Alpha unaligned access handling back into machine.def. (It was a flag on the mem request and handled in the memory system, but that approach appears to be unnecessarily complicated.) - Cleanup of AlphaMemoryRequest: down from five constructors to one; Erik's full-word flags are now bits in Nate's flag word. - Eliminate obsolete memory.h functions, and some unused memory_object functions. arch/alpha/vtophys.cc: base/remote_gdb.cc: sim/prog.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: Renamed SimpleCPU::(read|write)_(byte|half|word|qword) to just read & write, overloaded on the type of the 'data' argument. Merged the full-system and non-full-system implementations of these eight original functions into two common template functions. To support this, also renamed (read|write)[1248] on memory_object and derivatives to just read & write, again overloaded on the type of the 'data' argument. Many of these functions could now be condensed into a few template functions (though with a level of indirection so that the interface can remain virtual). I did not do that though. sim/exec_context.hh: sim/pc_event.hh: - Eliminate static SLAT variables when building FULL_SYSTEM base/remote_gdb.cc: sim/simple_cpu.cc: sim/simple_cpu.hh: make it easier to drop into the remote debugger from within the local debugger dev/pcireg.h: Instead of having each pci device define its own sim object to represent the configuration space, just define one TlaserPciDev type and change the configuration regs as needed. base/range.hh: Fix bugs in range parsing code. sim/eventq.hh: Uncomment inlined event check (not sure why it was commented out to begin with). base/str.hh: - Add some missing #includes. - Remove some prefetching stats to shorten log lengths. - Fix perfect cache to work with new coherence mechanism (or at least not fail when there is no coherence protocol). base/range.hh: Consider whether a range object is valid or not when doing range tests. Reorganization & minor documentation of range comparison code. sim/exetrace.hh: Bug fix related to previous commit on range.hh. test/nmtest.cc: Add ability to do lookups by address dev/etherbus.cc: base/statistics.cc: fix sim/simple_cpu.cc: make it so we can change the boot flag sim/simple_cpu.cc: Bit more debugging info base/circlebuf.cc: Must initialize the size dev/console.cc: sim/simple_cpu.cc: better debugging base/remote_gdb.cc: Don't panic if the execution context isn't the same, just don't execute the breakpoint since it probably belongs to another instance sim/memtest.cc: Removed bcopy_in & bcopy_out (needless aliases for prot_write & prot_read, respectively). Made prot_read & prot_write public methods (not protected). Had to change some char arrays to byte_t to keep compiler happy. Renamed strcpy_in and strcpy_out to writeString and readString, respectively, to reduce confusion about the direction they operate. Also some reformatting for style. sim/main.cc: Move some more old simplescalar I/O from stdio to C++ streams. Some reformatting for style in main.cc as well. base/inifile.cc: base/inifile.hh: Pass -D, -U, and -I args to cpp for ini-file processing. Should make use of #defines in .ini files much handier, once we get our parser up to dealing with the resulting whitespace issues. Some reformatting for style as well. sim/main.cc: Pass -D, -U, and -I args to cpp for ini-file processing. Should make use of #defines in .ini files much handier, once we get our parser up to dealing with the resulting whitespace issues. sim/exetrace.cc: sim/exetrace.hh: sim/simple_cpu.cc: Changes to exetrace code to make it somewhat less schizophrenic so that it works under non-full-system SimpleCPU. (Previous code assumed either full-system+simple CPU or non-full-system+detailed CPU.) Also removed a lot of unused code in simple_cpu.cc. base/trace.hh: Added trace flags to display all syscalls or common syscall-related warnings (which are suppressed by default). arch/alpha/fake_syscall.cc: sim/exec_context.cc: sim/exec_context.hh: sim/prog.cc: sim/prog.hh: sim/simple_cpu.cc: Syscall emulation (non-full-system) support for multithreaded apps compiled using Tru64 5.1's pthreads library. More specifically, you can now associate multiple processors with a single LiveProcess object (via their workload parameters). Only one processor will be active initially. The additional processors will be assigned to handle new "virtual processor" threads as they are created by the pthreads user library. Functionality is limited, as we do *not* emulate any kernel scheduling: once a VP thread is created, it is permanently bound to a simulated CPU. However, most of the SPLASH-2 benchmarks seem to run on both uni- and dual-processor targets. Includes total rewrite of syscall emulation (fake_syscall.cc). Only syscalls that have been needed thus far have been re-implemented in the new framework. Others will be moved over on demand. base/trace.cc: Better dump function sim/simple_cpu.cc: The active field of exe_ctx is not used in FULL_SYSTEM sim/eventq.cc: dev/etherbus.cc: more debugging sim/memtest.cc: Added support for mem_cmd.cc Transitioned from enum mem_cmd to class MemCmd sim/eventq.hh: sim/param.hh: sim/serialize.hh: sim/sim_object.hh: test/sized_test.cc: - Fix PISA syscalls to use new memory interface. - Make prefetching a real SimObject and port existing prefetchers to the new framework. base/inet.cc: base/inet.hh: Move functions for networking into a separate file sim/exec_context.cc: sim/simple_cpu.cc: sim/simple_cpu.hh: Add basic support for a quiesce instruction. - Suspend the current thread on quiesce - Resume on interrupt Add an arm instruction that doesn't do anything yet sim/simple_cpu.cc: Added FULL_SYSTEM wrapper to use of "proc" in tick(). Nate, please check to make sure I didn't break it. base/inifile.hh: Added include of vector base/trace.hh: - Create a ScsiDevice base class that represents all of the functions that a SCSI device might want to implement - Clean up the ScsiDisk class: remove unneeded junk and give better names - Create a ScsiNone class that is used when a given target has no device sim/main.cc: Always use the same random seed to make the memory tester repeatable. As the comment says, someday we should make this a parameter. (Do we still need "mysrand()" and "myrand()"?) sim/memtest.cc: sim/memtest.hh: - Get rid of CoherenceTest... MemTest is just as capable. - Lots of new parameters for MemTest. sim/pc_event.cc: Don't execute a pc event twice dev/disk_image.cc: Add a config node of the copy on write disk image base/trace.hh: dev/disk_image.cc: More debugging base/trace.hh: Major update in dma code. - Separate the io callback into a read callback and a write callback - Fix the write callback so that the proper data is written back to the disk and data is copied to the proper place in the data buffer - Use sim_freq for the tick frequency. (There is still no delay) - Remove a bunch of unnecessary code - Make code more concise and remove old cruft - More Debugging (of course) - Formatting fixes - mprotect hack to make sure that dma buffer is not overwritten sim/exec_context.cc: sim/exec_context.hh: Fix broken assertion in main_memory::checkLockedAddrList(). Check for lots of failed store-conditionals and print deadlock warning message. arch/alpha/fake_syscall.cc: Use actual number of CPUs allocated to process (not const 2!). A few additional syscalls for pthreads support (not quite there yet though). sim/prog.cc: sim/prog.hh: Use actual number of CPUs allocated to process (not const 2!). arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: arch/alpha/ev5.cc: arch/alpha/ev5.hh: arch/alpha/fake_syscall.cc: base/remote_gdb.cc: base/remote_gdb.hh: sim/exec_context.cc: sim/exec_context.hh: sim/exetrace.cc: sim/exetrace.hh: sim/pc_event.cc: sim/pc_event.hh: sim/prog.cc: sim/prog.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: exec_context_t -> ExecContext spec_exec_context_t -> SpecExecContext dev/disk_image.cc: quell warnings base/trace.hh: remove more warnings sim/exec_context.cc: sim/exec_context.hh: sim/prog.cc: sim/prog.hh: sim/simple_cpu.cc: remove the Process object from FULL_SYSTEM since it doesn't really make any sense sim/simple_cpu.cc: move SIM_OBJECT junk to the end like other files sim/simple_cpu.cc: sim/simple_cpu.hh: Make it so we can use a memory hierarchy in FULL_SYSTEM SimpleCPU arch/alpha/fake_syscall.cc: sim/base_cpu.cc: sim/base_cpu.hh: sim/exec_context.cc: sim/exec_context.hh: sim/prog.cc: sim/prog.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: - Add pointer from execution context to the CPU it's running on. - Just pass execution context pointer to the syscall emulation code, instead of a bunch of individual field arguments. - A few more exec_context_t -> ExecContext changes for non-full-system. - Rudimentary thread scheduling for non-full-system support of pthreads apps. Hopefully this won't go much farther. sim/exec_context.cc: Oops... fix minor bug from merge. arch/alpha/fake_syscall.cc: sim/base_cpu.cc: sim/base_cpu.hh: sim/exec_context.cc: sim/exec_context.hh: sim/prog.cc: sim/prog.hh: sim/simple_cpu.cc: - We really don't want to build a thread scheduler in the simulator... rip all that out, and replace with some basic synchronization primitives implemented as syscalls. Non-full-system MP apps thus need to be compiled specially to use these primitives, but it's plenty good enough to get SPLASH-2 up and running. These primitives block by suspending the execution context (for efficient simulation). Studies that care about synch operation costs should use user-level LL/SC-based primitives instead. - Implement more than two states (active vs. !active) for an ExecContext. arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: arch/alpha/fake_syscall.cc: arch/alpha/vtophys.cc: base/circlebuf.cc: base/fast_alloc.cc: base/inifile.cc: base/inifile.hh: base/object_file.cc: base/object_file.hh: base/range.hh: base/remote_gdb.cc: base/res_list.hh: base/socket.cc: base/str.cc: base/str.hh: base/symtab.cc: base/symtab.hh: base/trace.cc: dev/alpha_console.cc: dev/alpha_console.hh: dev/console.cc: dev/console.hh: dev/disk_image.cc: dev/disk_image.hh: dev/etherbus.cc: dev/etherbus.hh: dev/simple_disk.hh: sim/base_cpu.cc: sim/base_cpu.hh: sim/eventq.cc: sim/exetrace.cc: sim/exetrace.hh: sim/hybrid_pred.hh: sim/intr_control.cc: sim/intr_control.hh: sim/main.cc: sim/memtest.cc: sim/memtest.hh: sim/param.cc: sim/param.hh: sim/pc_event.hh: sim/prog.cc: sim/prog.hh: sim/sat_counter.hh: sim/serialize.cc: sim/serialize.hh: sim/sim_object.cc: sim/simple_cpu.cc: sim/simple_cpu.hh: sim/universe.cc: First pass at compiling with gcc 3.x. Lots of "std::" in header files, "using namespace std" in source files. (Note policy of not putting "using" statements in headers or before includes in sources.) Still not able to compile with gcc 3.2. Errors: - Can't create an ifstream from a file descriptor anymore (breaks IniFile). - "`class MSHR::MSHRegister' is private" errors in mshr.cc and prefetch_cache.cc: not clear why since it's in the public part of the class declaration. - cpu.cc:879: can't match a reference and 0 (specifically "no match for `bool ? SimObjectParam<PipeTrace*>& : int' operator") - pipetrace.cc: "invalid conversion from `int' to `std::_Ios_Fmtflags'" Warnings: - strstream now deprecated... needs some rewriting in sat_counter.hh and hybrid_pred.hh (need to get all that code out of the headers anyway) - trace.hh macro problem: cpp now says 'pasting "::" and "Event" does not give a valid preprocessing token' - major "implicit typename" issues in base/sized.hh base/trace.hh: Token pasting not necessary. Quiets g++ 3.2 warning base/inifile.cc: base/inifile.hh: Make this compile in g++ 3.2 base/remote_gdb.hh: dev/etherbus.hh: dev/pcireg.h: dev/simple_disk.cc: Make this stuff g++ 3.2 happy base/inifile.cc: Make this still compile in g++ 2.95 arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: dev/alpha_console.cc: dev/alpha_console.hh: sim/serialize.hh: sim/simple_cpu.cc: Added serialization for simple FULL_SYSTEM objects. Working on the hard ones sim/simple_cpu.cc: Make this code actually compile. Fix style while we're at it sim/base_cpu.cc: Fixes to recent updates to maintain gcc 3.2 compatibility (mostly more std:: in header files). test/Makefile: SS -> M5 base/cprintf.cc: base/cprintf.hh: test/Makefile: test/cprintftest.cc: printf replacement that uses C++ io streams and is typesafe Any type that overloads operator<< for use with streams will work with this structure. The format string is backwards compatible with printf style format strings, but the types are not checked, for example, %s doesn't verify that the type being printed is a string, %d doesn't verify that the type being printed is an integer. Instead, the various formats just set up the proper io stream manipulators for printing. So, %#s doesn't mean anything different from %s, but %#x does mean something different from %x. If the type you are printing does't care about the #, then nothing changes. base/cprintf.hh: test/cprintftest.cc: Fix case where there is only a format string, and no arguments base/cprintf.hh: base/cprintf_formats.hh: std:: base/trace.cc: base/trace.hh: Make the tracing stuff use cprintf base/cprintf.cc: Save and restore iostream state dev/etherbus.cc: Rewrite the dma engine support so that it can interact with the dma_interface to the timing memory model. This way, all of the timing of the dma transfers themselves can come from the memory system. Simos copyright removed since this code shares nothing with Simos sim/hybrid_pred.hh: sim/predictor.hh: sim/sat_counter.hh: Fixes to stat names in segmented IQ Changes from strstream to stringstream to remove warnings dev/etherbus.cc: dev/etherbus.hh: dev/etherint.hh: Separate the interface to the bus from the device sim/simple_cpu.cc: Move progress message from SimpleCPU::tick() to new ProgressEvent. (Much more efficient, and available independent of CPU model.) dev/console.cc: dev/console.hh: Added [DoEvents] default so command line --DoEvents:do_events=1 turns on events for all busses Added serlization function headers (not implemented yet). sim/eventq.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: Added [DoEvents] default so command line --DoEvents:do_events=1 turns on events for all busses Added serlization function headers (not implemented yet). Added EventQueue::nextEventTime(), returns time head is scheduled, or sim_cycle if empty. Added support for uniprocessor SimpleCPU with timing memory. arch/alpha/fake_syscall.cc: base/remote_gdb.cc: sim/exec_context.hh: sim/prog.cc: sim/simple_cpu.cc: Get rid of redundant ExecContext PC field. sim/main.cc: Add -n option to suppress loading default.ini. Added a little more help to the help message. sim/main.cc: Oops... make sure we still load it when we don't say '-n'. sim/main.cc: Minor formatting. sim/exetrace.cc: sim/exetrace.hh: Merge full-system & non-full-system exetrace code. base/cprintf.cc: base/cprintf.hh: Previous two commits were (somewhat) broken... this is the real one test/cprintftest.cc: more testing base/remote_gdb.cc: base/remote_gdb.hh: dev/alpha_console.cc: dev/alpha_console.hh: sim/base_cpu.cc: sim/base_cpu.hh: sim/exec_context.cc: sim/exec_context.hh: sim/pc_event.cc: sim/pc_event.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: sim/system.cc: sim/system.hh: Moved a lot of full-system variables out of SimpleCPU so that they can (eventually) be used with the detailed CPU model. Several fields moved into the ExecContext, while a few others moved into a new System object (which replaces the old Kernel object, for now at least). sim/exetrace.cc: sim/pc_event.cc: sim/pc_event.hh: sim/simple_cpu.cc: arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: dev/alpha_console.cc: dev/alpha_console.hh: - Many g++ 3.2 fixes - Added Makefile magic to allow a comprehensive build of all simulator variants on all archtectures. 'make all' or 'make TARGET=<arch> all_flavors' - Added container adaptors and associative_table. Don't use these quite yet -- they are very expensive to compile. Am currently converting them over to boost::mpl. They are used by the new BHGP prefetcher. - Moved md_sysreg_t reg_t entries to isa_traits. PISA does not have these sorts of registers. - Moved ipr accesses to theISAEngineTraits because they are not generally applicable. These are #ifdef FULL_SYSTEM in the simulator code -- eventually this should get worked into the traits structure. base/fifo_buffer.cc: base/fifo_buffer.hh: Initial add of this incredibly usefull utility object arch/alpha/ev5.cc: arch/alpha/vtophys.cc: arch/alpha/vtophys.hh: base/remote_gdb.cc: sim/exec_context.cc: sim/exec_context.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: sim/system.cc: Implement some interval statistics for full system mode. Create a callpal function that is called when a callpal occurs so it's easier to manipulate the statics. Rework the vtophys stuff to make it a bit cleaner. arch/alpha/ev5.cc: arch/alpha/ev5.hh: Keep track of all callpals in the interval stats base/res_list.hh: base/sched_list.hh: sim/eventq.cc: sim/eventq.hh: sim/exetrace.cc: sim/exetrace.hh: sim/hybrid_pred.hh: sim/main.cc: sim/predictor.hh: sim/prog.cc: sim/sat_counter.hh: TA DA!!!! The giant, huge, amazing, i-hope-i-never-have-to-do-that-again, CLUSTERING MERGE!!!! \ base/fifo_buffer.hh: sim/exetrace.hh: Minor adjustments for GCC 3 compatibility Turn ptrace features back on arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: arch/alpha/ev5.cc: arch/alpha/fake_syscall.cc: arch/alpha/vtophys.cc: arch/alpha/vtophys.hh: base/remote_gdb.hh: dev/alpha_console.cc: dev/simple_disk.cc: dev/simple_disk.hh: sim/exec_context.cc: sim/exec_context.hh: sim/exetrace.hh: sim/memtest.cc: sim/memtest.hh: sim/prog.cc: sim/prog.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: sim/system.cc: sim/system.hh: Get rid of almost all old-style object names. This commit is equivalent to running the following script on the current head: #! /bin/sh find \( -name '*.cc' -o -name '*.hh' \) -exec perl -pi -e '\ s/\bmemory_object\b(?!\.hh)/FunctionalMemory/g;\ s/\bvirtual_memory\b(?!\.hh)/VirtualMemory/g;\ s/\bmain_memory\b(?!\.hh)/MainMemory/g;\ s/\bphysical_memory\b(?!\.hh)/PhysicalMemory/g;\ s/\bspec_memory\b(?!\.hh)/SpeculativeMemory/g;\ s/\bMemObj\b(?!\.hh)/TimingMemObj/g;\ s/\bmemory_translation\b(?!\.hh)/AddressTranslator/g;\ s/\balpha_tlb\b(?!\.hh)/AlphaTlb/g;\ s/\balpha_itb\b(?!\.hh)/AlphaItb/g;\ s/\balpha_dtb\b(?!\.hh)/AlphaDtb/g;\ s/\bmemory_controller\b(?!\.hh)/MemoryController/g;\ s/\bstorebuffer_t\b(?!\.hh)/StoreBuffer/g;\ s/\bstorebuffer_entry_t\b(?!\.hh)/StoreBufferEntry/g;\ s/\bcreate_vector_t\b(?!\.hh)/CreateVector/g;\ s/\bcv_spec_state\b(?!\.hh)/CreateVecSpecState/g;\ s/\bspec_state_list\b(?!\.hh)/SpecStateList/g;\ s/\bdyn_inst_t\b(?!\.hh)/DynInst/g;' {} \; arch/alpha/fake_syscall.cc: sim/exec_context.hh: sim/memtest.hh: sim/simple_cpu.cc: Renamed files to better match new object names: base_memory.{cc,hh} --> functional_memory.{cc,hh} mem_obj.{cc,hh} --> timing_mem_obj.{cc,hh} sim/exec_context.cc: sim/exec_context.hh: sim/prog.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: Detailed CPU now compiles in full-system mode (but doesn't run, so I didn't add it to the makefile). SLAT code is now protected by '#ifdef USE_SLAT', since it's not currently compatible with full-system mode. Also, slat.cc is not compiled by default. We will need a makefile option to do '-DUSE_SLAT' and add slat.cc to the source list. CPU::Thread object is gone; these are now just bare SpecExecContexts. Changed all remaining {read,write}_{byte,half,word,qword} sets of methods to just read/write template methods, where possible. sim/system.cc: sim/system.hh: Make the system boot flag a paramter arch/alpha/ev5.hh: sim/intr_control.hh: The ethernet device was interrupting on the wrong interrupt line. Line 0x17 is too high (it's higher than the clock interrupt) and it doesn't correspond with the spl protection in the driver source. To solve this, we hack in support to support multiple interrupts at a single level and have scsi and ethernet share the same interrupt level. dev/etherbus.cc: dev/etherint.hh: Make the bus call back to the ethernet interface when the transfer is complete. This allows the interface to do the next request in the transmit buffer if there is one. dev/etherbus.cc: dev/etherbus.hh: dev/etherdump.cc: dev/etherdump.hh: Add etherdump object which accepts packets and spits them out in tcpdump format for analysis with tcpdump and ethereal. Make the etherbus support the dump object dev/etherint.cc: make the ethernet interface a SimObject that you can refer to dev/etherint.hh: dev/etherlink.cc: dev/etherlink.hh: Add a different connection type between ethernet interfaces. The ether link is a unidirectional fixed bandwidth link. To simulate a full duplex 100MB/s ethernet, you need two etherlinks. It's just much easier to simulate a full duplex link this way. Maybe encapsulate this into another bidirectional link sometime. sim/exec_context.hh: sim/main.cc: sim/simple_cpu.cc: sim/system.cc: Add a halted state to the simulator and only actually exit the simulator when all systems have halted. While we're at it, remove an if statement from the common code path in SimpleCPU::tick sim/exec_context.hh: sim/simple_cpu.cc: IntervalStatsObject -> IntervalStats test/Makefile: Make this work again base/cprintf.hh: #include guard arch/alpha/alpha_memory.cc: arch/alpha/vtophys.cc: base/remote_gdb.cc: dev/alpha_console.cc: dev/console.cc: dev/disk_image.cc: dev/etherbus.cc: dev/simple_disk.cc: sim/eventq.cc: sim/pc_event.cc: sim/simple_cpu.cc: since cprintf properly deals with 64-bit types, stop using FMT* as much as possible base/circlebuf.cc: base/inet.cc: base/inet.hh: base/object_file.cc: base/res_list.hh: convert some stdio stuff to use cprintf/c++ streams dev/console.cc: dev/console.hh: convert some stdio stuff to use cprintf/c++ streams better use of format strings sim/exec_context.hh: sim/exetrace.cc: sim/exetrace.hh: - Make SLAT work with new execution context - Temporarily fix include file problems (circular includes) arch/alpha/alpha_memory.cc: arch/alpha/ev5.cc: arch/alpha/fake_syscall.cc: sim/eventq.hh: sim/hybrid_pred.hh: sim/main.cc: True and false are keywords in C++, don't use TRUE and FALSE This can be done with the following script: #!/bin/sh for each in `find . \( -name '*.cc' -o -name '*.hh' \)`; do perl -pi -e '\ s/\bFALSE\b/false/g;\ s/\bTRUE\b/true/g;' $each done base/cprintf.cc: base/cprintf.hh: test/Makefile: test/cprintftest.cc: Add support for 'terminators' to cprintf. This is esentially a special manipulator that can cause some sort of event to occur when the stream is outputted. (Will be used for panic, fatal, etc.) base/cprintf.cc: base/cprintf.hh: Another cleanup fo the cprintf stuff. This should make it much easier to do panic, etc. sim/simple_cpu.cc: Rename sim_num_refs to SIM:num_refs to match Steve's new naming in the detailed CPU stats. base/cprintf.cc: base/cprintf.hh: Get rid of the reference counting and the pass by value, and come up with a way to remove all of the temporary variables that are created, and only create one. Should make the compiler's burden much less sim/pc_event.hh: quell warning arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: arch/alpha/ev5.cc: arch/alpha/ev5.hh: arch/alpha/fake_syscall.cc: arch/alpha/vtophys.cc: arch/alpha/vtophys.hh: base/inet.cc: base/inet.hh: base/object_file.cc: base/object_file.hh: base/remote_gdb.cc: base/remote_gdb.hh: base/trace.cc: base/trace.hh: dev/alpha_access.h: dev/alpha_console.cc: dev/alpha_console.hh: dev/console.cc: dev/console.hh: dev/disk_image.cc: dev/disk_image.hh: dev/etherpkt.hh: dev/simple_disk.cc: dev/simple_disk.hh: sim/exetrace.hh: sim/memtest.cc: sim/memtest.hh: sim/pc_event.cc: sim/serialize.cc: sim/serialize.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: sim/system.cc: Change byte_t etc. to C99 standard int8_t etc. Other than old/host.h, all other changes were produced by this script: #! /bin/sh find \( -name '*.cc' -o -name '*.hh' -o -name '*.c' -o -name '*.h' -o -name 'machine.def' \) -exec perl -pi -e '\ s/\bbyte_t\b(?!\.hh)/uint8_t/g;\ s/\bsbyte_t\b(?!\.hh)/int8_t/g;\ s/\bhalf_t\b(?!\.hh)/uint16_t/g;\ s/\bshalf_t\b(?!\.hh)/int16_t/g;\ s/\bword_t\b(?!\.hh)/uint32_t/g;\ s/\bsword_t\b(?!\.hh)/int32_t/g;\ s/\bqword_t\b(?!\.hh)/uint64_t/g;\ s/\bsqword_t\b(?!\.hh)/int64_t/g;\ s/\bbool_t\b(?!\.hh)/bool/g;\ s/\bdfloat_t\b(?!\.hh)/double/g;\ s/\bsfloat_t\b(?!\.hh)/float/g;' {} \; sim/simple_cpu.cc: Assume preprocessor can do ANSI '##' token pasting. arch/alpha/fake_syscall.cc: base/misc.cc: base/misc.hh: base/pollevent.cc: base/sched_list.hh: base/socket.cc: base/symtab.cc: dev/console.cc: dev/disk_image.cc: dev/simple_disk.cc: sim/base_cpu.cc: sim/eventq.cc: sim/intr_control.hh: sim/main.cc: sim/memtest.cc: sim/param.cc: sim/serialize.cc: sim/sim_object.cc: sim/simple_cpu.cc: Get closer to removing all FMT64 junk and myfprintf stuff Make panic, flatal, warn use cprintf. Start moving away from the old/misc.(cc|h) files. dev/simple_disk.cc: Get rid of some FMT junk dev/etherdump.cc: dev/pcireg.h: u_int* -> uint* dev/etherdump.cc: sys/time.h instead of time.h arch/alpha/ev5.cc: sim/exec_context.cc: sim/exec_context.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: Do some clean up in the manner that the interval stats object is created Also, use the interval stats range when doing my full-system istats. Finally, don't make the interval stats part of the exec_context since it makes little sense to do so. We're only going to have one interval stats object (at least for now.) base/mod_num.hh: Initial addition of a "modulo-number" class sim/eventq.cc: sim/eventq.hh: convert some stdio to iostream sim/eventq.cc: sim/eventq.hh: sim/main.cc: sim/sim_events.cc: sim/sim_events.hh: sim/simple_cpu.cc: Move some common events into a new sim_events file. Rearrange some other things to move towards having only events in the main loop. sim/eventq.hh: Change protections base/pollevent.cc: base/pollevent.hh: proper destruction dev/console.cc: don't panic on connection error. detach. sim/eventq.cc: sim/eventq.hh: Clean up event queue and add support for priorities sim/eventq.cc: sim/main.cc: sim/memtest.cc: sim/serialize.cc: sim/sim_events.cc: sim/sim_events.hh: Get rid of sim_exit_now and make it an event. Get rid of sim_dump_stats and make it an event. Main loop is now reduced to servicing the event queue, ticking the CPUs, and incrementing sim_cycle sim/simple_cpu.hh: formatting nits base/cprintf.hh: dev/etherdump.cc: dev/etherdump.hh: sim/eventq.hh: sim/sim_events.cc: - ANSI/ISO C++ fixes - Improve SLAT efficiency - Add build_test rule to compile across all archs and options. This builds one simulator from each combination including the optimized Alpha simulator to run smt-test. Please run this before committing. base/misc.cc: make warnings less verbose sim/eventq.hh: Generic function that will delay the calling of a member function until a specified cycle. Has problems if you use it with gcc 2.95, but 3.2 compiles it ok. dev/etherbus.cc: Better debugging dev/etherbus.cc: dev/etherint.cc: dev/etherint.hh: dev/etherlink.cc: dev/etherlink.hh: Rework the EtherInt class to represent a generic Ethernet interface. Any object that wishes to connect to another device and pass ethernet packets must export an ethernet interface. This makes it possible to connect any two objects that have ethernet interfaces. For example, one EtherDev can connect directly to another etherdev, or the two EtherDevs can each attach to one of the interfaces on an EtherLink to get a fixed bandwidth. dev/ethertap.cc: dev/ethertap.hh: util/tap/Makefile: util/tap/tap.cc: The ethertap device and ethertap utility allow a simulator to connect to a real physical ethernet. Currently, the tap utility only works on OpenBSD, but that should be easily fixed. dev/ethertap.cc: dev/ethertap.hh: better bounds checking base/cprintf.hh: change function names in cprintf base/trace.cc: base/trace.hh: Make DPRINTF work more like panic, fatal, warn, etc. Also make it possible to redirect trace output to a file instead of stdout. dev/etherlink.cc: dev/etherlink.hh: Make EtherLink::Link Serializeable arch/alpha/alpha_memory.cc: base/remote_gdb.cc: base/res_list.hh: base/trace.cc: base/trace.hh: dev/console.cc: dev/disk_image.cc: dev/etherbus.cc: dev/etherlink.cc: dev/ethertap.cc: dev/simple_disk.cc: sim/eventq.cc: sim/eventq.hh: sim/pc_event.cc: sim/serialize.cc: sim/simple_cpu.cc: rework DPRINTF to automatically print the cycle and get the name of the object from which it was called. Additionally, while we're at it change 0x%x -> %#x dev/disk_image.cc: sim/pc_event.cc: sim/serialize.cc: dont use c_str() if we don't have to base/trace.cc: Only delete the stream if we created it base/trace.cc: base/trace.hh: Expose ostream to which tracing statements are sent via DebugOut() dev/console.cc: carriage return not necessary arch/alpha/arguments.cc: arch/alpha/arguments.hh: Add support for accessing function arguments from a kernel function. The class behaves somewhat like a random access iterator so that the user can access any argument desired, but to get at the data, the user uses the casting operators to get at the data pointed to by the arguments sim/pc_event.cc: sim/pc_event.hh: inline sim/pc_event.cc: sim/pc_event.hh: sim/system.cc: sim/system.hh: create a pc based event that traps kernel printfs for debugging statements arch/alpha/arguments.hh: rename to CopyData and use void * to avoid compiler problems sim/pc_event.cc: Make Kernel::Printf take AlphaArguments as a parameter so that a user may add initial arguments to another version of the kernel function and then pass an offset arguments class to the function for printing the data. Also, while we're at it, remove the printing of the cycle. That can be done by the caller. base/trace.hh: sim/pc_event.cc: sim/pc_event.hh: sim/system.cc: sim/system.hh: Separate the printf event from the debugging printf event. The kernel will call the debugging printf event m5printf. There is also a raw version m5printfr that indicates to the simulator that it shouldn't print any extra information in the context of this debuggin printf because it would screw up fromatting. sim/pc_event.cc: symmetry arch/alpha/arguments.cc: arch/alpha/arguments.hh: plug huge leak arch/alpha/arguments.hh: Add std:: to list arch/alpha/arguments.hh: make the execution context available dev/etherlink.cc: formatting, typeo, paranoia sim/system.cc: sim/system.hh: enable the mbuf dump code sim/pc_event.cc: sim/pc_event.hh: Add a pc event for the kernel mbuf dump function arch/alpha/fake_syscall.cc: sim/main.cc: I can see no good reason at all for doing setjmp/longjmp arch/alpha/arguments.cc: arch/alpha/arguments.hh: reference count the argument data so that the data doesn't disappear before we're done using it. sim/main.cc: move all signal stuff into main.cc sim/sim_events.cc: Move termination and progress event initialization to sim_events sim/debug.cc: sim/debug.hh: sim/main.cc: sim/pc_event.cc: sim/simple_cpu.cc: Move some of the debug break stuff to its own file Use SIGTRAP to initiate a break and set up the simulator to ignore the signal. This will make gdb automatically stop in these functions, but won't interfere with normal simulator workings. sim/sim_events.cc: Id string sim/sim_events.cc: make g++ 3 happy base/cprintf.cc: base/cprintf.hh: base/misc.cc: base/misc.hh: base/trace.cc: base/trace.hh: - Rename debug rule to dbg so it doesn't interfere with debug.cc. - Reorganize build_test so it generates dependencies correctly. - Remove HashTable from spec_memory and replace with SGI's hash_map extension. - Put cprintf/ArgList in namespace cp so it doesn't interfere with g++ 2.95 std::deque (comma operator gives problems -- this is a g++ 2.95 bug). - Fix FP register decode in dispatch. PISA registers > 31 were being counted as FP registers and using up all of the FP hpysical registers. The code in commit correctly identified FP registers so the bogus FP physical register usage was never cleared, locking up the machine. This is why the SLAT didn't work correctly. Added isa_traits::isFloatingPointRegister and ::isIntegerRegister to do this tracking in a machine-independent way. sim/sim_events.cc: simple way to dump stats on specified cycles sim/eventq.hh: Re-insert assignment of description string into event sim/eventq.cc: If event is the head in remove() return arch/alpha/fake_syscall.cc: Clustering changes.... - clusters can share data using the ClusterSharedInfo structure - Pulled the register info file from the segmented IQ --> dispatch stage (this info can be used by the dispatch stage and any IQ model) - Segmented IQ's share the chain-info-table now base/misc.hh: - Add m5_assert() macro to print the sim_cycle if the assert fails. - Add simple_trace, simple_trace_data and simple_trace_start parameters to generate a sim-safe-like trace for easy comparison with simplescalar results. Needed for PISA debugging. sim/sim_events.hh: remove extra space sim/main.cc: Fix dump() for floss-reasons Segfault can now dump core sim/simple_cpu.cc: sim/simple_cpu.hh: Get rid of obsolete call from misguided thread scheduling experiment. arch/alpha/ev5.cc: arch/alpha/ev5.hh: add new alpha instructions for starting and ending intervals dev/disk_image.cc: dev/disk_image.hh: Make the copy-on-write disk image use hash_map base/callback.hh: Generic callback class and callback queue for random use sim/main.cc: sim/sim_events.cc: sim/sim_exit.hh: Move exit stuff into it's own file. Make an exit callback queue so that generic callbacks can be invoked upon simulator exit dev/disk_image.cc: give a mode that makes sense dev/disk_image.cc: dev/disk_image.hh: Rework the object implementation of the copy-on-write disk image. - Allow a child name and an initial table size to both be specified - Add a read only flag that determines if changes to the image are written back to disk. - If the flag is not read only, and there is no initial image to open, that's ok, just create an initial empty table. - If the table is to be written back to disk, schedule an ExitCallback to write the image back when the simulator exits. base/callback.hh: make this work in g++ 3 base/misc.cc: base/pollevent.cc: base/pollevent.hh: base/trace.hh: sim/pc_event.cc: sim/universe.cc: declare sim_cycle in one place arch/alpha/alpha_memory.cc: dev/alpha_console.cc: more sim_cycle cleanup sim/eventq.hh: fix priority handling in the event queue: if an event is scheduled with a priority once, then don't overwrite the priority if it is subsequently scheduled without a priority dev/console.cc: send a carriage return/newline pair to the output manually since cprintf and friends would interpret this and send out endl dev/console.cc: dev/console.hh: add option to save console output to a file sim/simple_cpu.cc: sim/simple_cpu.hh: Rework cache interface to avoid trying to loop inside of tick(). Should work much more cleanly with timing memory now (even for multiprocessor systems). sim/simple_cpu.cc: a whole bunch of cleanup foo sim/eventq.cc: events can't be scheduled in the past anymore sim/eventq.cc: sim/eventq.hh: create doEventLoop(), this continually cycles through the event queue consuming events until there are none left dev/console.hh: Make this work in g++ 3 sim/sim_events.cc: sim/sim_events.hh: Make the act of ticking all cpus an event. Automatically schedule it every cycle sim/debug.cc: sim/main.cc: sim/sim_events.cc: rearrange code to get rid of sim_smt.cc sim/main.cc: oops. bring back the SIM:cycle stat arch/alpha/ev5.cc: sim/simple_cpu.cc: move the break_ipl check to the point where the IPL is actually set sim/debug.cc: Make the debug break event first in any given cycle sim/simple_cpu.cc: sim/simple_cpu.hh: Split I-cache and D-cache stall cycles out from idle cycles in statistics. sim/prog.hh: - Replace SLAT maps with hash_maps - Add hash<> specializations for md_addr_t, counter_t, etc. - Increase max file descriptors from 15 to 100 (parser00 was running out) sim/simple_cpu.cc: A few baby steps toward full-system detailed CPU. ev5_trap() now sets both PC & NPC (not just NPC). base/misc.cc: base/trace.cc: New memory model Doxyfile: Configuration file for doxygen. Generates documentation in /n/zizzer/z/m5docs. To generate docs, run "doxygen Doxyfile" in the root directory of your copy of the head. To comment your code you use a javadoc like syntax, a cstyle comment with 2 stars at the front (/**). For example /** Everything before the first period is a brief description. This is a detailed description. @param <name> description of parameter to function @retval <name/type> description of function return value. @sa (for see also) generate links to other class/enum/member/etc. */ You should start your files out with a comment like: /** @file Brief description of the file. Detailed description if needed. */ See TimingMemobj.hh for more examples. dev/ethertap.cc: Make this work on OpenBSD sim/main.cc: sim/sim_events.cc: sim/sim_events.hh: sim/sim_exit.hh: Make it possible to set an exit code for the exit event. Also, make exit_now not visible to the rest of the simulator so that people will know to create an exit event. Finally, don't include callback.hh since we don't have to. sim/sim_events.cc: use the SimExitEvent to make sure that we exit at the end of the cycle arch/alpha/fake_syscall.cc: don't use exit_now() create a SimExitEvent() arch/alpha/ev5.cc: arch/alpha/ev5.hh: Add an instruction that causes M5 to exit, allowing processes running under simulation to cause the simulation to terminate sim/simple_cpu.cc: in full system mode, don't panic on an unknown opcode dev/disk_image.cc: dev/disk_image.hh: convert stdio to streams sim/system.cc: remove uneeded include base/cprintf.cc: %p is an integer (more or less) sim/system.cc: sim/serialize.cc: missing include dev/disk_image.cc: cast to correct types for proper interface usage base/circlebuf.cc: base/intmath.h: base/remote_gdb.cc: base/res_list.hh: In c++, we use std::min, std::max, true, and false, not ano of the other junk sim/sim_events.cc: make a local copy of the data since the object can get deleted dev/alpha_console.cc: dev/alpha_console.hh: Added parameter for number of CPUs to console, defualt=1 sim/sim_events.cc: sim/simple_cpu.cc: sim/system.cc: sim/system.hh: use cprintf. general cleanup remove unneeded c_str() calls. base/cprintf.cc: make %% work base/cprintf.cc: handle %% better test/cprintftest.cc: better testing arch/alpha/alpha_memory.cc: convert to use iostream and cprintf instead of stdio and fprintf base/cprintf.cc: more accurately implement formatting for floating point numbers test/cprintftest.cc: more tests base/inifile.cc: base/inifile.hh: base/symtab.cc: base/symtab.hh: dev/disk_image.hh: sim/base_cpu.cc: test/Makefile: convert everything to use hash_map instead of my old hash table junk base/hashmap.hh: base/inifile.hh: dev/disk_image.hh: since people don't agree on where hash_map belongs, pull it into the m5 namespace and include hashmap.hh whenever a hashtable is needed sim/memtest.cc: Move Cache only calls (block_size, hit_latency, etc.) out of TimingMemObject and into CPUMemInterface. Changes to everywhere they were called on a TimingMemObj. sim/param.hh: Fix handling of operator[] for EnumVectorParam classes. Also fix some line wrapping problems caused by adding 'std::'. base/trace.cc: base/trace.hh: Extend trace facility to either print immediately to an ostream or maintain a circular buffer of trace entries (dumpable from debugger by calling dumpTrace()). Also change flags to use SimpleEnumVectorParam so we can just give a list of names instead of a big hex value. sim/exetrace.cc: sim/exetrace.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: Integrate execution trace code into new trace facility. Eliminates the need for a separate execution trace log. Enable instruction tracing using --trace:flags=InstExec. base/misc.cc: Dump trace buffer in panic(). arch/alpha/ev5.cc: arch/alpha/ev5.hh: sim/simple_cpu.cc: set up an annotations.hh file where inline annotation functions that do nothing exist. This allows people to hack in annotations all in one file arch/alpha/ev5.cc: arch/alpha/ev5.hh: intervals are really annotations arch/alpha/ev5.cc: Factor out more annotations arch/alpha/ev5.cc: sim/simple_cpu.cc: Make an Annotate namespace, and add a DumpStats method to it dev/disk_image.cc: sim/main.cc: sim/sim_events.cc: sim/sim_exit.hh: Normalize exit-related function names. Move exitNow() prototype to simexit.hh. base/misc.cc: base/trace.cc: base/trace.hh: sim/eventq.cc: sim/eventq.hh: sim/exetrace.cc: sim/exetrace.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: Minor cleanup on new tracing code: - namespace cleanup - fix bug in Trace::Log::dump - added new RawDumpRecord to put raw data in trace buffer (call Trace::rawDump, was Trace::dump) - added --trace:flags=All to set all trace flag bits - added --trace:dump_on_exit option to dump trace buffer on normal exit - DPRINTF now requires 'const char *' for format (not string) so it doesn't go away by the time buffer is dumped sim/sat_counter.hh: sim/serialize.hh: foo(void) --> foo() This commit is equivalent to doing the following in the sim directory: perl -pi -e 's/\(void\)/()/' *.cc *.hh sim/base_cpu.hh: sim/eventq.cc: sim/hybrid_pred.cc: sim/hybrid_pred.hh: sim/memtest.cc: sim/predictor.hh: sim/sat_counter.cc: sim/sat_counter.hh: Move dump() and reg_stats() implementations out of header files. Clean up #includes. sim/exec_context.hh: sim/exetrace.cc: sim/exetrace.hh: sim/main.cc: Clean up identification and handling of prefetches and no-ops. Added is_data_prefettch() method to DynInst. (One of these days we'll have to change all those functions to isFoo() style.) Changes nop count statistic... we were only counting Alpha UNOPs before, not all Alpha NOP forms. sim/pc_event.cc: sim/simple_cpu.cc: - Strip opt binaries after build - Update Makefile for new source files - Fix BHGP prefetcher to use compressed addresses - Fix FULL_SYSTEM compile problems (missing header includes) base/inifile.cc: Make it possible to override variables in the inifile and on the command line sim/simple_cpu.cc: sim/simple_cpu.hh: - Make the SLAT useable with SimpleCPU for quick and easy debugging. This required refactoring some of the traits classes which should make them marginally more independent. - Fix bogus assert in the SLAT code. Alias load/store values should only be assumed equivalent in non-spec mode. sim/simple_cpu.cc: - Must send the saved address to the SLAT for all memory operations because execution could have overwritten the base register. sim/simple_cpu.cc: sim/simple_cpu.hh: Added Parameter for CPU identification number in Full System Primary CPU ID is 0, which is the default value Modified to start all CPU's in Halted status except the primary CPU dev/alpha_console.cc: Added comments to code for needed implementation in order to boot second CPU dev/alpha_console.cc: sim/exec_context.cc: sim/exec_context.hh: sim/simple_cpu.cc: sim/system.cc: sim/system.hh: Added array of Execution Contexts to system.hh Used when trying to launch another CPU Added cpu_id to Full System ExecContext Fixed the launch in alpha_console.cc to access the correct exe_ctx dev/alpha_console.cc: sim/simple_cpu.cc: Fixed initializtion and launch of the second processor Added a gdb-alpha debug port for non-primary processor Cleaned up the .ini file of unneeded disk images sim/simple_cpu.cc: Add cpu_id (see Ron's recent commit) to full-system detailed CPU. base/trace.cc: Fix bug in calling dumpTrace() on partially filled trace buffer. test/Makefile: test/lru_test.cc: - Replace BHGP associative table with something simpler. - Add lru_test to test out new AssociativeTable class. Doxyfile: Only create documentation for documnented classes dev/alpha_access.h: dev/alpha_console.cc: dev/alpha_console.hh: cleanup and formatting sim/simple_cpu.cc: Fix bus queueing delay and idle stats. Slight change to one scheduling case. Set req->time in SimpleCPU so delays are correctly computed. sim/simple_cpu.cc: Don't do an icache fetch if we had an ITLB miss. arch/alpha/alpha_memory.cc: dev/alpha_console.cc: sim/serialize.cc: sim/serialize.hh: Replace include of inifile.hh in serialize.hh with forward decl of class IniFile. Requires adding explicit include of inifile.hh in several .cc files. sim/eventq.hh: Get rid of needless include of inifile.hh. sim/main.cc: base/inifile.cc: base/inifile.hh: Check for unreferenced parameters to detect obsolete settings and typos. A warning for an unreferenced parameter section can be suppressed by adding a 'unref_section_ok=y' parameter to the section. Warnings for any unreferenced parameters within a section can be suppressed by adding a 'unref_entries_ok=y' parameter to the section. (The value doesn't matter; the presence of the parameter is all that is tested.) By default any unreferenced parameter or parameter section warnings will cause the simulator to terminate. Use the '-u' command-line option to suppress this behavior (at your own risk!). dev/alpha_access.h: dev/alpha_console.cc: dev/alpha_console.hh: dev/console.cc: dev/console.hh: dev/disk_image.cc: dev/disk_image.hh: dev/etherbus.cc: dev/etherbus.hh: dev/etherdump.cc: dev/etherdump.hh: dev/etherint.hh: dev/etherlink.cc: dev/etherlink.hh: dev/etherpkt.hh: dev/ethertap.cc: dev/ethertap.hh: dev/pcireg.h: dev/simple_disk.cc: dev/simple_disk.hh: sim/eventq.hh: sim/serialize.hh: sim/sim_object.hh: Add some Doxygen comments. Mostly putting in markers for the file and classes Also some minor formatting fixes here and there arch/alpha/ev5.cc: Reindent to 4 spaces (plus a few other very minor formatting changes). arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: Reindent. sim/eventq.hh: Don't even bother with the description unless TRACING_ON is defined. Not a big deal at this point, since TRACING_ON is currently hardcoded to 1 in base/trace.hh. base/remote_gdb.cc: base/trace.hh: sim/eventq.cc: sim/eventq.hh: sim/system.cc: Clarify debugging defines: - DEBUG is either defined or not, but is not given a value. It should be tested with #ifdef. - TRACING_ON is always defined, either with a 0 or 1 value. It should always be tested with #if. Automatically set TRACING_ON value according to whether DEBUG is defined. Added -Wundef to warnings to catch '#if DEBUG' cases. (Yes, '#if DEBUG' does the right thing if DEBUG is not defined, but the same is not true for '#ifdef TRACING_ON' if TRACING_ON is defined to 0.) In the long run, perhaps the uses of TRACING_ON outside of the trace package itself should be converted to use DEBUG. sim/pc_event.cc: Looks like a lot of device code has never been compiled w/o TRACING_ON set; fix up several warnings (mostly unused variables). sim/pc_event.cc: Oops... needs to compile w/o FULL_SYSTEM too. base/trace.hh: sim/main.cc: sim/param.cc: sim/param.hh: sim/sim_object.cc: Fix up parameter printing controls. Parameters are always printed by default; new command-line parameter '-q' turns this off. Old system was broken in two ways: there was no way to turn off printing in the optimized binary, and controlling printing with a trace flag bit (specified as an .ini parameter) meant that parameters parsed *before* trace:flags never got printed. Also added code to print the names of unspecified parameters as comments in the output. base/remote_gdb.cc: base/trace.hh: A couple more changes to get full-system to compile w/o tracing. sim/simple_cpu.hh: sim/simple_cpu.cc: - Add stats for simple SLAT profiling sim/simple_cpu.cc: Extend HAVE_TSL protection so it can compile without TSL base/trace.cc: Need to update flag strings to match enum... yuck. sim/system.cc: sim/system.hh: Build global list of system objects. Add gdb-callable printSystems() function so we can find system object pointers from inside debugger. sim/eventq.cc: sim/simple_cpu.cc: base/pollevent.cc: base/pollevent.hh: Move pollQueue handling into main event loop so it works regardless of the CPU model. arch/alpha/ev5.cc: Protect IPRs etc. from being modified on misspeculated paths. arch/alpha/ev5.hh: Eliminate some unused macros. arch/alpha/alpha_memory.cc: Don't update IPRs for TLB misses on misspeculated instructions. Set req.flags PHYSICAL and UNCACHEABLE bits as appropriate based on results of translation. sim/param.cc: Move ConfigHierarchy::Node definition into separate file so it can be included only where necessary. arch/alpha/fake_syscall.cc: arch/alpha/vtophys.cc: arch/alpha/vtophys.hh: base/circlebuf.cc: base/circlebuf.hh: base/cprintf.hh: base/fifo_buffer.cc: base/fifo_buffer.hh: base/inifile.cc: base/inifile.hh: base/misc.hh: base/mod_num.hh: base/pollevent.cc: base/remote_gdb.cc: base/sched_list.hh: base/socket.cc: base/socket.hh: base/str.cc: base/str.hh: base/symtab.cc: dev/alpha_access.h: dev/etherint.cc: sim/base_cpu.cc: sim/base_cpu.hh: sim/debug.cc: sim/hybrid_pred.cc: sim/hybrid_pred.hh: sim/param.cc: sim/param.hh: sim/pc_event.cc: sim/predictor.hh: sim/sat_counter.cc: sim/sim_object.cc: sim/simple_cpu.hh: test/cprintftest.cc: test/lru_test.cc: test/nmtest.cc: test/offtest.cc: test/sized_test.cc: test/symtest.cc: util/tap/tap.cc: Add CVS Id tags dev/alpha_console.cc: dev/alpha_console.hh: Get rid of pmask field in MemReq; move address mask into devices by adding to common base class FunctionalMemory. base/inifile.cc: Don't complain if "unref_section_ok" or "unref_entries_ok" are not referenced. base/inifile.cc: Add functionality to "unref_entries_ok": Now, the RHS is parsed for a list of unreferenced entries, only these will be "OK" Note that this will not be needed very often... base/trace.cc: sim/exetrace.cc: Make trace cycle number position and format consistent between DPRINTF trace records and exetrace records. sim/debug.cc: Add "debug" parameter context for global debug options. Add parameter "debug:break_cycles" to set DebugBreakEvent(s) from ini file/command line. sim/pc_event.cc: sim/system.hh: sched_break_pc() now sets a breakpoint on *all* systems. Use sched_break_pc_sys() to set a breakpoint on just one system. sim/debug.cc: sim/pc_event.cc: base/cprintf_formats.hh: using namespace std dev/alpha_console.cc: sim/exec_context.cc: sim/exec_context.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: arch/alpha/fake_syscall.cc: sim/prog.cc: use accessor functions to set/get status to prepare to not call SimpleCPU::tick if there is nothing to do sim/simple_cpu.cc: no more simplescalar here base/trace.hh: Only set TRACING_ON according to DEBUG if it hasn't already been set on the command line. base/trace.cc: If compiled with TRACING_ON=0, give an error if the user tries to turn on tracing. sim/main.cc: Get rid of do-nothing segfault handler... if you get a segfault in an exit handler, you end up with an infinite recursion. arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: arch/alpha/ev5.cc: arch/alpha/ev5.hh: sim/exec_context.cc: sim/exec_context.hh: sim/pc_event.cc: sim/simple_cpu.cc: sim/simple_cpu.hh: Full-system detailed CPU almost almost there. Big reorganization of virtual address translation code, so we can tell an access is uncached soon enough to suppress it if it's on the wrong path: translation is its own step now, not hidden inside the (former) VirtualMemory object. Also a few other changes to avoid bad things on misspeculated paths. This commit results in *very* small changes in IPCs and MSIPCs (a few tenths of a percent max on the tests) because some wrong-path instructions get handled a little differently. sim/main.cc: Put quotes around args with spaces when echoing command line. sim/pc_event.cc: Process PC Events just before fetching the relevant instruction instead of just after the previous instruction. Keeps us from missing events when we take off on misspeculated paths. ** Detailed CPU now gets to single-user prompt!! ** sim/base_cpu.hh: sim/eventq.hh: sim/main.cc: sim/sim_events.cc: sim/sim_events.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: get rid of the TickAllEvent and make it so each cpu has its own tick event. In the process, the implementation of the virtual functin tick() got moved into a non virtual function _tick() so that the tick event could be CPU specific and you wouldn't pay the virtual function call overhead. This is another step towards being able to not tick a cpu if it has nothing to do sim/base_cpu.hh: sim/simple_cpu.hh: Now that tick is called via an event, we no longer need a virtual function sim/base_cpu.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: clean up the tick event stuff and get rid of the TickEvent template class and just make one for each class since you may want a different process() function anyway base/trace.cc: base/trace.hh: sim/base_cpu.hh: sim/pc_event.cc: sim/pc_event.hh: Fix up branch predictor's return address stack when we do a SkipFuncEvent. Since there's no easy way to figure out what thread ID we're on from the SkipFuncEvent, we just fix thread 0's RAS... will need to fix this when we get SMT full-system up. Also: - Moved RAS tracing stuff to DPRINTFs; added BranchPredRAS trace flag. - Made BadAddrEvent derive from SkipFuncEvent to eliminate code duplication. base/trace.cc: sim/eventq.cc: sim/eventq.hh: sim/serialize.cc: Create a flags bitvector in the event to store flags. Holds what used to be squashed and scheduled, and also contains a new flag for auto delete. The auto delete flag will make the eventq responsible for calling delete on an event. This makes 'delete this' unnecessary in the process() function. This is most beneficial for events that get squashed since process() never gets called, and one might want to have the data reclaimed. To use the autodelete functionality with squash, a few events were cleaned up and reorganized sim/exec_context.cc: sim/exec_context.hh: sim/pc_event.cc: sim/simple_cpu.cc: Add thread_num field to ExecContext so it knows which CPU thread context it represents. Need this for the SkipFuncEvent RAS fixup, but seems generally useful. dev/etherdump.cc: use time.h instead of sys/time.h sim/simple_cpu.cc: sim/simple_cpu.hh: move the tick schedule() to where it's needed dev/alpha_console.cc: dev/alpha_console.hh: sim/base_cpu.cc: sim/base_cpu.hh: sim/exec_context.cc: sim/exec_context.hh: sim/intr_control.cc: sim/intr_control.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: get rid of the processor SimObject and move all of the interrupt stuff into BaseCPU since it really is part of the CPU anyway sim/exec_context.hh: fix store conditional sim/exec_context.hh: clean up conditional store so that it's more understandable sim/base_cpu.cc: sim/base_cpu.hh: move interrupt set/clear routines into the .cc file and make them virtual so that CPUs derived from BaseCPU can modify the behaviour of the interrupt routine. base/trace.cc: base/trace.hh: New trace flags generation via perl script. Now if you want to add a flag you just type it once (in the script) and all the C++ is generated automagically. Also supports "compound" flags that can be specified on the command line and map to multiple regular flags. Switched trace flags from 64-bit bitmap to vector<bool> for scalability. base/trace.cc: comment out the offending assign since it is commented as not needed base/trace.cc: Get rid of useless code. sim/base_cpu.cc: sim/base_cpu.hh: change variable name to avoid confusion arch/alpha/ev5.cc: sim/simple_cpu.cc: Remove a bunch of istats stuff and insert some annotations for where they were. sim/debug.cc: add a function to force stats to be dumped from the debugger sim/base_cpu.hh: sim/exec_context.cc: sim/exec_context.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: Don't schedule tickEvent until it is known that there will be something to do test/Makefile: Make tests compile again test/Makefile: Make the whole build process for tests a bit simpler util/tap/Makefile: make this build again, clean stuff up sim/exec_context.cc: sim/simple_cpu.cc: make stuff compile when not FULL_SYSTEM sim/main.cc: Add the name of the execution host to the output sim/main.cc: Don't free() data returned by getenv. besides, free() is a function, not an operator like sizeof sim/eventq.cc: That assertion should have never been committed sim/simple_cpu.cc: don't tick here sim/eventq.cc: the squashed flag should be cleared once the event has actually been processed sim/simple_cpu.cc: we can get here with a dcache miss as well. sim/simple_cpu.cc: only schedule the event if it is not already scheduled. arch/alpha/fake_syscall.cc: Zero out syscall arg buffer to avoid copying garbage into simulator space. sim/exec_context.hh: Translation in non fullsystem mode. And use the FALRU class to implement FA LRU caches. sim/base_cpu.hh: sim/exec_context.cc: sim/simple_cpu.cc: sim/simple_cpu.hh: Reorganize code a bit so that multiple CPUs can properly work with the new tick as event stuff. arch/alpha/arguments.hh: base/cprintf.hh: base/refcnt.hh: dev/etherpkt.hh: Make a refcounted base class that contains the refcounting stuff and make everything use it sim/main.cc: don't print out the host if we didn't find one dev/alpha_console.cc: dev/alpha_console.hh: s/memreq/MemReq/ base/trace.cc: Add support to echo trace output (DPRINTF etc.) to cerr as well as the trace buffer. From gdb, call "echoTrace(1)" to enable, or "echoTrace(0)" to disable. As a side effect, semantics of setting both trace:bufsize and trace:file are different now (will buffer and send to file, where old version would just buffer), but I doubt anyone ever did that anyway. See comments in file for more details. sim/base_cpu.cc: sim/base_cpu.hh: sim/debug.cc: sim/eventq.cc: sim/eventq.hh: sim/memtest.cc: sim/memtest.hh: sim/sim_events.cc: sim/sim_events.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: Revamp event debug/tracing structure. - virtual const char *description() method replaces description string constructor argument. Lets us associate a fixed description string with each class of events with basically no overhead. - virtual void trace(char *action) method lets event subclasses customize tracing DPRINTF call to put in additional information. Currently only used by WritebackEvent (to print sequence number of associated instruction). dev/etherbus.cc: dev/etherbus.hh: dev/etherlink.cc: dev/etherlink.hh: dev/ethertap.hh: Fix up full-system events for new debug structure. base/trace.cc: Looks like g++ 3 doesn't like "string = bool ? string : char*". sim/simple_cpu.cc: the caches currently won't completion events for UNCACHEABLE accesses, so don't send any. Warning, this is a HACK! dev/etherdump.cc: sim/main.cc: cleanup includes, and remove some #ifdef cruft for BFD sim/sim_exit.hh: Added GDB-callable exitNow() using char * sim/sim_events.hh: Need to include eventq.hh here. test/Makefile: There are no OPT_FLAGS arch/alpha/fake_syscall.cc: dev/etherdump.cc: sim/eventq.cc: sim/main.cc: sim/memtest.cc: sim/serialize.cc: sim/sim_events.cc: sim/sim_time.hh: sim/simple_cpu.cc: sim/system.cc: Get rid of sim.h & sim_smt.hh. Most of what was in those was obsolete anyway. Move needed externs into universe.hh & stats.hh, plus new header file sim_time.hh. sim/memtest.cc: sim/memtest.hh: Update memtest cpu to new tickEvent stuff base/remote_gdb.cc: Adding returns to make insure happy. sim/simple_cpu.cc: Rework Interporcessor Interrupts to properly signal second CPU, and unsuspend it sim/intr_control.hh: Fix clock interrupt to signal both proccesors correctly in MP system sim/system.cc: Fix seg fault in single proccesor mode from last commit, MP now boots with 2 CPUs sim/simple_cpu.cc: sim/system.cc: sim/system.hh: Changes to genaralize the interupt scheme to variable number of proccessors base/misc.cc: only dump the trace buffer if tracing is turned on base/str.cc: properly deal with the case where there is only one string in the list base/cprintf.cc: base/cprintf.hh: Add csprintf() to print to a string (sort of like sprintf()) base/cprintf.cc: be consistent about resetting parameters to original values base/cprintf.cc: cleanup base/statistics.cc: base/statistics.hh: Finally commit my new stats package and stop tinkering with it. This new stats package has support for all sorts of stuff. Documentation will appear in the code in a future commit. test/Makefile: test/stattest.cc: add tests for the statistics package. This exercises all sorts of different capabilities of the stats package and can be used for examples. util/rundiff: rundiff utility Normal diff reads in all of both input files and tries to generate a minimal diff, for super long trace files, this is bad because it takes forever and you run out of memory. rundiff is designed to scan the input files and compare only 2000 lines at a time. This way memory won't run out and a user can use fifos for input files. sim/exetrace.cc: Print all reg results as 0x%016x. arch/alpha/fake_syscall.cc: base/misc.cc: base/misc.hh: base/pollevent.cc: base/pollevent.hh: base/statistics.hh: base/trace.cc: base/trace.hh: dev/alpha_console.cc: dev/etherbus.cc: dev/etherdump.cc: dev/etherdump.hh: dev/etherlink.cc: dev/etherlink.hh: dev/ethertap.cc: sim/base_cpu.cc: sim/base_cpu.hh: sim/debug.cc: sim/eventq.cc: sim/eventq.hh: sim/exec_context.hh: sim/exetrace.hh: sim/hybrid_pred.hh: sim/main.cc: sim/memtest.cc: sim/memtest.hh: sim/pc_event.cc: sim/prog.hh: sim/sat_counter.hh: sim/serialize.cc: sim/sim_events.cc: sim/sim_events.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: sim/universe.cc: test/nmtest.cc: test/stattest.cc: test/symtest.cc: Global variable renaming. Basically equivalent to the following perl: s/\btick_t\b/Tick/g; s/\bsim_cycle\b/curTick/g; s/\bcounter_t\b/Counter/g; s/\bsim_freq\b/ticksPerSecond/g; dev/console.cc: dev/etherbus.cc: dev/etherdump.cc: dev/etherlink.cc: dev/ethertap.cc: Get rid of some explicit externs (use header files!). dev/ethertap.cc: Include for panic(). arch/alpha/alpha_memory.cc: sim/exec_context.hh: Various bug fixes. Charge all writebacks to thread 0 sim/eventq.cc: sim/eventq.hh: sim/main.cc: rework the event loop a bit so that we can prepare for dealing with asynchronous events properly. arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: base/refcnt.hh: dev/alpha_console.cc: dev/alpha_console.hh: sim/exec_context.hh: sim/memtest.cc: sim/memtest.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: Initial move to reference counting MemReq objects. Switched to STL containers for storage in the memory hierarchy. sim/exec_context.hh: Fix LL/SC and got 1-6 CPUs working by fixing clock interrupt sim/simple_cpu.cc: Add the IIC as a selectable cache tag. Fix translation for now with a quick hack. sim/exec_context.hh: Put detection logic on failed Store Conditionals to help detect deadlock situations util/term/Makefile: util/term/term.c: Whittle down netcat to the bare minimum to connect to another machine and add the proper stuff to do some terminal handling to make this utility sufficient for connecting to m5 to get a console util/term/Makefile: add an install target base/pollevent.cc: sim/async.hh: sim/main.cc: Don't create events in signal handlers since it really isn't safe. I'm not positive if some bugs I've seen were caused by this, but we may as well be safe base/pollevent.cc: base/pollevent.hh: dev/console.cc: dev/console.hh: sim/async.hh: sim/main.cc: - clean up the pollevent stuff and just do the poll whenever requested since we will request it with the proper frequency - add an alarm to poll once every second in addition to waiting for sigio - remove all of the telnet crap since I'm never planning on implementing it - fix detaching and re-attaching of consoles base/pollevent.cc: base/pollevent.hh: sim/main.cc: only handle/raise SIGALRM if we're polling sim/memtest.cc: sim/cache/lzss_compression.hh: sim/cache/null_compression.hh: Initial check in of Compression stuff and IIC subblocking. base/remote_gdb.cc: Get rid of needless extern. arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: arch/alpha/ev5.cc: arch/alpha/ev5.hh: arch/alpha/fake_syscall.cc: dev/alpha_console.cc: dev/alpha_console.hh: sim/exec_context.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: Rename fault type and fault codes as follows: s/md_fault_type/Fault/g; s/md_fault_none/No_Fault/g; s/md_fault_mcheck/Machine_Check_Fault/g; s/md_fault_opdec/Unimplemented_Opcode_Fault/g; s/md_fault_alignment/Alignment_Fault/g; s/md_fault_overflow/Integer_Overflow_Fault/g; s/md_fault_reset/Reset_Fault/g; s/md_fault_arith/Arithmetic_Fault/g; s/md_fault_interrupt/Interrupt_Fault/g; s/md_fault_ndtb_miss/Ndtb_Miss_Fault/g; s/md_fault_pdtb_miss/Pdtb_Miss_Fault/g; s/md_fault_dtb_fault/Dtb_Fault_Fault/g; s/md_fault_dtb_acv/Dtb_Acv_Fault/g; s/md_fault_itb_miss/Itb_Miss_Fault/g; s/md_fault_itb_fault/Itb_Fault_Fault/g; s/md_fault_itb_acv/Itb_Acv_Fault/g; s/md_fault_fen/Fen_Fault/g; s/md_fault_pal/Pal_Fault/g; s/md_fault_NUM/Num_Faults/g; Also changed 'enum md_fault_type' to just 'Fault' where possible. sim/exec_context.cc: sim/exec_context.hh: Add a constructor to specify a memory without a process sim/eventq.hh: clean up a bit. When events are resecheduled or removed from the schedule, they are no longer squashed. (Only scheduled events can be squashed.) sim/simple_cpu.hh: check to see if the tick event was squashed. If it was squashed, then it must be rescheduled since squashed events are scheduled. sim/exec_context.cc: sim/exec_context.hh: This new constructor is only for non FULL_SYSTEM base/statistics.cc: base/statistics.hh: test/stattest.cc: Remove unused variable dumpStats -> dump initStats -> init use const string & instead of const char * make Base constructor explicit more consistent formatting widths sim/main.cc: sim/sim_events.cc: make the new stats package useable in the simulator base/statistics.cc: base/statistics.hh: test/stattest.cc: create two standard stats that are to be used for calculations: elapsedTicks - is the number of ticks that has elapsed during this simulation. Currently, this is just curTick, but this may change when we have checkpointing. elapsedSeconds - is the number of simulated seconds that have elapsed during the simulation. Currently, this is just elapsedTicks / ticksPerSecond. sim/main.cc: Need to initialize stats much sooner so that SimObject constructors can register statistics base/statistics.cc: - use the stat_print_descriptions variable that the old stats package provides this is just a quick hack for now. When the old stats package goes away, we'll move this. - Fix the sorting algorithm so it works as I had intended - Make the output field widths equivalent to the old stats package base/statistics.cc: clean up memory sim/sim_events.cc: sim/sim_events.hh: Use autodelete sim/sim_events.cc: oops. didn't mean to commit this part util/tap/Makefile: call it m5tap instead of ethertap sim/exec_context.hh: Get rid of a couple of unnecessary forward class declarations. sim/memtest.cc: sim/memtest.hh: Adds compression to the memory hierarchy as well as using ExecContext to access memory. Added a few related config files. base/cprintf.cc: Default fill char is space, regardless of what stream fill char is. sim/exetrace.cc: Convert some of the hairier format things to ccprintf. base/statistics.cc: try getting the sorting a bit better arch/alpha/arguments.hh: base/refcnt.hh: base/statistics.hh: dev/etherpkt.hh: s/refcounted/RefCounted/ s/refcnt/RefCountingPtr/ arch/alpha/fake_syscall.cc: Zero out register files for newly created threads to make non-full-system MP runs deterministic. sim/exetrace.cc: Don't trace the results of NOPs or prefetches (for easier comparison with traces from new decoder). sim/exetrace.cc: Don't trace branch link values written back to R31 either. Also put a ifdef TARGET_ALPHA around this hack. sim/exetrace.cc: Need another ifdef TARGET_ALPHA... arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: arch/alpha/arguments.cc: arch/alpha/ev5.cc: arch/alpha/ev5.hh: arch/alpha/fake_syscall.cc: arch/alpha/vtophys.cc: arch/alpha/vtophys.hh: base/object_file.hh: base/remote_gdb.cc: base/remote_gdb.hh: base/symtab.cc: base/symtab.hh: dev/alpha_console.cc: dev/simple_disk.cc: dev/simple_disk.hh: sim/base_cpu.cc: sim/base_cpu.hh: sim/exec_context.cc: sim/exec_context.hh: sim/exetrace.hh: sim/memtest.cc: sim/memtest.hh: sim/pc_event.cc: sim/pc_event.hh: sim/prog.cc: sim/prog.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: sim/system.cc: sim/system.hh: test/nmtest.cc: test/symtest.cc: Massive renaming to (almost) eliminate all md_* and MD_* names in preparation for total exorcism of machine.def. Most of the changes in this commit were performed with the following perl script (perl -pi <script> <files>). A small amount of manual fixup was needed to (mostly getting rid of the Addr typedefs in the various memory objects now that the former md_addr_t has that name). # rename machine-dependent types and constants (will be moving into ISA traits object) s/md_addr_t/Addr/g; s/md_intreg_t/IntReg/g; s/md_gpr_t/IntRegFile/g; s/md_fpreg_t/FloatReg/g; s/md_fpr_t/FloatRegFile/g; s/md_ctrlreg_t/MiscReg/g; s/md_ctrl_t/MiscRegFile/g; s/md_ipr_t/InternalProcReg/g; s/md_anyreg_t/AnyReg/g; s/md_inst_t/MachInst/g; s/regs_t/RegFile/g; # manually fix declaration in old/regs.h and a few forward decls s/struct RegFile/RegFile/g; s/MD_NUM_IREGS/NumIntRegs/g; s/MD_NUM_FREGS/NumFloatRegs/g; s/MD_NUM_CREGS/NumMiscRegs/g; s/MD_IPR_NUM/NumInternalProcRegs/g; s/MD_TOTAL_REGS/TotalNumRegs/g; s/MD_REG_ZERO/ZeroReg/g; base/statistics.hh: test/stattest.cc: Create a functor() wrapper for the stats package. This wrapper makes it possible to write an actual function or functor that is evaluated in a Formula base/statistics.hh: test/stattest.cc: Implement operator += for formulas. This allows us to build a formula without knowing all variables involved at compile time sim/sim_object.cc: sim/sim_object.hh: Make a different regStats pass for the new stats package base/statistics.cc: base/statistics.hh: sim/main.cc: Move simulator specific stuff to its own file. rename elapsedFoo to simFoo so it's clear we're talking about what's been simulated. Use the functor method to get the time. sim/base_cpu.cc: sim/base_cpu.hh: sim/main.cc: sim/simple_cpu.cc: sim/simple_cpu.hh: Convert instruction counting to new stats package. Convert the rest of SimpleCPU to new stats Do a bit of cleanup while we're at it base/cprintf.cc: attempt to deal with the badbit problem sim/base_cpu.hh: sim/simple_cpu.cc: no need for reg_stats to be pure virtual base/statistics.cc: base/statistics.hh: sim/simple_cpu.hh: test/stattest.cc: change names of stat classes so they are simpler base/statistics.cc: no unregestering stats base/statistics.cc: base/statistics.hh: sim/main.cc: test/stattest.cc: make it so that none of the constructors for the various stats objects take any parameters so that users may put them in arrays and stuff. Instead provide initialization functions for the objects that needed parameters, and provide a way to verify that all statistics that need initialization do get initialized. sim/cache/lzss_compression.hh: Compression fixes. Added trivial data support to the IIC. Set the max write size in the compressed memory to 1024 bytes sim/memtest.cc: sim/memtest.hh: Added 'percent_uncacheable' option to MemTest base/statistics.cc: base/statistics.hh: keep track of more data in distributions use a struct to pass data to the display function take underflow and overflow out of the array base/statistics.cc: support for printing vector totals sim/memtest.cc: sim/memtest.hh: Fix uncacheables to go to their own memory space. sim/memtest.cc: Change default percentage of uncacheables to 10% base/statistics.cc: base/statistics.hh: Correctly calculate vector totals. When a formula operates on vectors, it is incorrect to do calculate the formula for each vector element, and then sum the final formula vector. The correct way is to sum the individual vectors at the leaves of the expression tree. And then perform the calculation as if it were on scalar values. Assume we have vectors A, and B, and X = A * B The old way would have been: total(X) = total(A * B) The new way is total(X) = total(A) * total(B) Per thread miss rates are and example of something that would be calculated incorrectly. If you were to sum all of the miss rates, you could get a number greater than one. Calculating the overall miss rate should just be overall misses / overall accesses base/statistics.cc: base/statistics.hh: Create a #define STAT_DISPLAY_COMPAT that makes the new stat package output match the old one. arch/isa_parser.py: arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: arch/alpha/arguments.cc: arch/alpha/ev5.cc: arch/alpha/ev5.hh: arch/alpha/fake_syscall.cc: arch/alpha/isa_desc: arch/alpha/isa_traits.hh: arch/alpha/vtophys.cc: arch/alpha/vtophys.hh: base/bitfield.hh: base/circlebuf.hh: base/object_file.hh: base/remote_gdb.cc: base/symtab.hh: dev/alpha_console.cc: dev/console.cc: sim/base_cpu.cc: sim/base_cpu.hh: sim/exec_context.cc: sim/exec_context.hh: sim/exetrace.cc: sim/exetrace.hh: sim/main.cc: sim/op_class.hh: sim/pc_event.cc: sim/pc_event.hh: sim/prog.cc: sim/prog.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: sim/static_inst.cc: sim/static_inst.hh: sim/system.cc: sim/system.hh: New ISA description system. No more machine.def! Instructions are now decoded into StaticInst objects, and all static instruction properties (including execution behavior) are associated with those objects. Extended documentation in progress. Currently supports Alpha only; PISA will not compile. Use END_OF_MACHINE_DOT_DEF tag to extract previous version. arch/isa_parser.py: Make it more obvious that you shouldn't edit decoder.cc, and harder to do so accidentally. arch/alpha/isa_desc: base/statistics.cc: sim/exec_context.hh: make stuff compile in g++ 3.x fix some bad formatting Doxyfile: Put generated docs in local directory docs/doxygen. Don't bother generating LaTeX, and a few other minor tweaks. arch/isa_parser.py: arch/alpha/isa_desc: - Decouple isa_desc operand types from C++ types. - Handle signed operand writebacks. - Add a few comments to suppress doxygen warnings on decoder.cc. sim/static_inst.cc: sim/static_inst.hh: Add some basic decode cache hash-table stats dumping (ifdef'd out). sim/static_inst.cc: Make it compile w/gcc3. sim/static_inst.cc: ostream doesn't seem to exist in 2.95 arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: TLB statistics arch/alpha/ev5.cc: always pass the execution context to an annotation arch/alpha/ev5.cc: revert a bunch of crap from the last commit that I didn't want yet. arch/isa_parser.py: make it so that the ext source directory is grabbed from the right place arch/alpha/alpha_memory.cc: arch/alpha/ev5.cc: arch/alpha/isa_desc: arch/alpha/vtophys.cc: base/remote_gdb.cc: dev/alpha_console.cc: sim/exec_context.hh: sim/simple_cpu.cc: get rid of MD_IPR_foo and call it IPR_foo add some comments to describe what the various PALtemp registers do formatting sim/base_cpu.cc: sim/base_cpu.hh: sim/exec_context.cc: sim/exec_context.hh: sim/simple_cpu.cc: Keep a list of execution contexts in BaseCPU Provide a mechanism to register per execution context statistics. base/socket.cc: base/remote_gdb.cc: dev/console.cc: dev/ethertap.cc: don't panic if accept fails sim/simple_cpu.cc: sim/simple_cpu.hh: keep track of fraction of cycles that are idle base/statistics.hh: make proxy nodes work better in formulas. (Now totals should work). sim/op_class.hh: Document OpClass enum. sim/op_class.hh: Need to document file for file members (enum, globals, etc.) to be extracted arch/alpha/faults.cc: arch/alpha/faults.hh: arch/alpha/isa_traits.hh: Move Fault into its own file, and provide a function to get the string name of a fault arch/alpha/ev5.cc: arch/alpha/ev5.hh: arch/alpha/osfpal.cc: arch/alpha/osfpal.hh: move PAL code defines and such into their own file. Also provide a function to get the name of a PAL code arch/alpha/osfpal.cc: make this actually compile and add it to the makefile kern/tru64/tru64.hh: dummy class for differentiating Tru64 kern/tru64/tru64_syscalls.cc: kern/tru64/tru64_syscalls.hh: Stuff on tru64 system calls arch/alpha/ev5.cc: arch/alpha/isa_desc: sim/exec_context.cc: sim/exec_context.hh: Add a bunch of full system statistics base/statistics.cc: base/statistics.hh: sim/sim_events.cc: support for printing stats to a file. For now we will continue to print to standard out so that the whole regression thing doesn't break. While we're at it, move the Stat param context to the new stats package sim/exec_context.hh: sim/main.cc: sim/simple_cpu.cc: sim/simple_cpu.hh: Today saw the wholesale slaughter of greened's code. When we asked the accused, Erik Hallnor, why he did it he responded, 'Because I was bored. And the underlying prefetch cache was soon to be 2 generations out of date.' sim/base_cpu.hh: sim/exec_context.cc: added a std::vector and using namespace std arch/alpha/fake_syscall.cc: Avoid conflicts with #defines in headers arch/alpha/fake_syscall.cc: I think this is what steve had in mind. base/endian.hh: get rid of the simplescalar endianness junk and make it a bit simpler base/cprintf.cc: base/cprintf.hh: base/cprintf_formats.hh: base/statistics.cc: test/cprintftest.cc: Break out the cprintf formatting stuff into per-type formatting so that we can do special formatting based on type. This makes %c work correctly for integer types. It also allows me to add a workaround for string format widths. Finally, it allows me to accept stringstream directly as an argument without having to use the .str() member. Doxyfile: Update Doxyfile to new version of doxygen and to use the newly install graphviz package. Doxyfile: Remove . from the file paths, instead of .. base/cprintf.cc: base/cprintf_formats.hh: base/statistics.cc: test/cprintftest.cc: Fix printing of strings. Seems that I just can't do what I want with templates. They're too smart for they're own good. Fix format field widths for floating point numbers. Remove some .str()'s that are no longer needed because cprintf supports them. base/statistics.cc: base/statistics.hh: test/stattest.cc: Make internal design a bit more consistent. Re-work Bins and Vectors and how they work together to remove a level of indirection. base/statistics.cc: base/statistics.hh: revert that last change base/statistics.cc: base/statistics.hh: test/stattest.cc: let's try this again. This time we'll make DistStat classes initialize their bins. Also add a test for this base/statistics.hh: Proxy -> VectorProxy Doxyfile: Don't hide undocumented classes. This helps when tracking includes through the new graphs. Doxyfile: Make things run faster until documentation errors are gone sim/prog.cc: sim/simple_cpu.cc: Change declarations to match defenitions. dev/alpha_access.h: dev/alpha_console.cc: dev/alpha_console.hh: dev/console.cc: dev/console.hh: dev/disk_image.cc: dev/disk_image.hh: dev/etherbus.cc: dev/etherbus.hh: dev/etherdump.cc: dev/etherdump.hh: dev/etherint.hh: dev/etherlink.cc: dev/etherlink.hh: dev/etherpkt.hh: dev/ethertap.cc: dev/ethertap.hh: dev/pcireg.h: dev/simple_disk.cc: dev/simple_disk.hh: sim/eventq.hh: sim/serialize.hh: sim/sim_object.hh: sim/simple_cpu.cc: Removal of 1200 doxygen warnings. The 600 left are mostly from StaticInstBase and decoder.cc. I basically un-documented the partially documented code by changing /** to /*. arch/alpha/ev5.cc: Add FULL_SYSTEM protection to match header file. Doxyfile: dev/alpha_console.hh: dev/etherint.hh: dev/simple_disk.hh: sim/simple_cpu.cc: sim/static_inst.hh: sim/cache/null_compression.hh: Down to 464 warnings, all in static_inst.hh or decoder.cc. Punt on the template instantiation thing by making them invisible to doxygen. arch/alpha/alpha_memory.cc: base/statistics.cc: base/statistics.hh: sim/simple_cpu.cc: test/stattest.cc: New way of specifying information about printing stats. old way: stat.setFormat(name, ...); new way: stat .name(...) .desc(...) .prereq(...) . . ; This allows you to specify any information about the stats, and do it in any order. It also cleans up the kinda crufty setFormat interfaces. LICENSE: This is the M5 license as agreed upon by the original M5 authors, and blessed by the University of Michigan technology transfer office. OK by Doug Hockstad <dhocksta@umich.edu> base/statistics.hh: missing_math is only for stats, so move it into its own place base/statistics.cc: test/stattest.cc: Fix stats sorting base/statistics.cc: base/statistics.hh: test/stattest.cc: Fix description printing stuff. Add a flag to the test script to turn descriptions on/off base/str.hh: wrapper to convert values to strings via stringstream base/statistics.hh: nitpick base/statistics.cc: base/statistics.hh: test/stattest.cc: Rework the printing of statistics to make the PrintOne function not need to know about the stats themselves. Also remove the overloading of function names for getting and setting parameters. base/statistics.cc: duh base/statistics.cc: Changes for _name issues base/statistics.cc: base/statistics.hh: Reorganize the base Stat class a bit and clean up handling of data base/statistics.cc: base/statistics.hh: Rework the stat printing stuff a bit so that the formatting parts need to know as little as possible about the type of stat being printed. base/statistics.hh: maybe not all vector stats will be registered in the future. (VectorProxies) base/statistics.hh: test/stattest.cc: VectorDistribution stat. To be used for per-thread distributions. Still need to implement total and zero() arch/alpha/isa_traits.hh: sim/static_inst.hh: don't use stdint.h, use either inttypes.h or host.h sim/main.cc: unneeded arch/alpha/isa_desc: only linux seems to support the rounding mode stuff right now base/statistics.hh: test/stattest.cc: VectorStandardDeviation and VectorAverageDeviation base/statistics.cc: just make sure the size is correct base/statistics.hh: use pointers internally instead of references arch/alpha/faults.cc: base/bitfield.hh: sim/cache/lzss_compression.hh: sim/cache/null_compression.hh: sim/op_class.hh: sim/sim_time.hh: sim/static_inst.cc: sim/static_inst.hh: test/stattest.cc: consistent $Id$ tags test/bitvectest.cc: test/circletest.cc: test/cprintftest.cc: test/initest.cc: test/lru_test.cc: test/nmtest.cc: test/offtest.cc: test/paramtest.cc: test/rangetest.cc: test/sized_test.cc: test/stattest.cc: test/strnumtest.cc: test/symtest.cc: test/tokentest.cc: arch/isa_parser.py: arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: arch/alpha/arguments.cc: arch/alpha/arguments.hh: arch/isa_parser.py: arch/alpha/faults.cc: arch/alpha/faults.hh: arch/alpha/isa_traits.hh: arch/alpha/osfpal.cc: arch/alpha/osfpal.hh: arch/alpha/vtophys.cc: arch/alpha/vtophys.hh: util/tap/tap.cc: base/bitfield.hh: base/callback.hh: base/circlebuf.cc: base/circlebuf.hh: base/cprintf.cc: base/cprintf.hh: base/cprintf_formats.hh: base/date.cc: base/dbl_list.hh: base/endian.hh: base/fifo_buffer.cc: base/fifo_buffer.hh: base/hashmap.hh: base/inet.cc: base/inet.hh: base/inifile.cc: base/inifile.hh: base/intmath.cc: base/intmath.h: base/misc.cc: base/misc.hh: base/mod_num.hh: base/object_file.cc: base/object_file.hh: base/pollevent.cc: base/pollevent.hh: base/range.hh: base/refcnt.hh: base/remote_gdb.hh: base/res_list.hh: base/sched_list.hh: base/socket.cc: base/socket.hh: base/statistics.cc: base/statistics.hh: base/str.cc: base/str.hh: base/symtab.cc: base/symtab.hh: base/trace.cc: base/trace.hh: dev/alpha_access.h: dev/alpha_console.cc: dev/alpha_console.hh: dev/disk_image.cc: dev/disk_image.hh: dev/etherbus.cc: dev/etherbus.hh: dev/etherdump.cc: dev/etherdump.hh: dev/etherint.cc: dev/etherint.hh: dev/etherlink.cc: dev/etherlink.hh: dev/etherpkt.hh: dev/ethertap.cc: dev/ethertap.hh: dev/pcireg.h: dev/simple_disk.cc: dev/simple_disk.hh: kern/tru64/tru64.hh: kern/tru64/tru64_syscalls.cc: kern/tru64/tru64_syscalls.hh: sim/cache/null_compression.hh: sim/async.hh: sim/debug.cc: sim/debug.hh: sim/eventq.cc: sim/eventq.hh: sim/exetrace.cc: sim/exetrace.hh: sim/intr_control.cc: sim/intr_control.hh: sim/memtest.cc: sim/memtest.hh: sim/op_class.hh: sim/param.cc: sim/param.hh: sim/pc_event.cc: sim/pc_event.hh: sim/predictor.hh: sim/sat_counter.cc: sim/sat_counter.hh: sim/serialize.cc: sim/serialize.hh: sim/sim_events.cc: sim/sim_events.hh: sim/sim_exit.hh: sim/sim_object.cc: sim/sim_object.hh: sim/sim_time.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: sim/static_inst.cc: sim/static_inst.hh: sim/std_types.hh: sim/system.cc: sim/system.hh: sim/universe.cc: sim/exec_context.cc: sim/exec_context.hh: license base/date.cc: move test/stattest.cc: remove dave's scary container stuff sim/base_cpu.cc: sim/base_cpu.hh: sim/simple_cpu.cc: rename the exec context list xc to contexts arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: arch/alpha/fake_syscall.cc: dev/alpha_console.cc: sim/exec_context.hh: sim/memtest.cc: sim/prog.cc: sim/prog.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: sim/system.cc: sim/system.hh: s/exe_ctx/xc/g sim/base_cpu.cc: Can't assume that context[0] exists. sim/cache/lzss_compression.cc: sim/cache/lzss_compression.hh: Our compression code free and clear. arch/alpha/fake_syscall.cc: base/range.hh: base/statistics.hh: sim/param.cc: sim/sim_object.cc: Changes to build with g++-3.3. Mostly added a bunch of includes of assert.h (not sure why older versions didn't need this). Also fixed up a couple other new warnings. arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: arch/alpha/ev5.cc: arch/alpha/fake_syscall.cc: arch/alpha/isa_traits.hh: arch/alpha/vtophys.cc: arch/alpha/vtophys.hh: dev/alpha_console.hh: dev/console.cc: dev/console.hh: dev/disk_image.cc: dev/etherdump.cc: dev/simple_disk.cc: sim/simple_cpu.cc: sim/system.cc: sim/system.hh: a little style sim/eventq.cc: sim/main.cc: sim/prog.cc: sim/simple_cpu.cc: sim/smt.hh: smt.h -> smt.hh add license base/statistics.hh: missing_math.hh isn't really needed I guess arch/alpha/arguments.hh: arch/alpha/fake_syscall.cc: arch/alpha/isa_traits.hh: base/hashmap.hh: base/inet.cc: base/inet.hh: base/misc.cc: base/pollevent.cc: base/socket.cc: base/statistics.hh: base/symtab.cc: base/symtab.hh: base/trace.hh: dev/alpha_console.hh: dev/etherlink.hh: dev/etherpkt.hh: sim/eventq.hh: sim/exec_context.hh: sim/exetrace.hh: sim/host.hh: sim/main.cc: sim/param.hh: sim/serialize.hh: sim/sim_object.cc: sim/simple_cpu.cc: sim/static_inst.hh: sim/universe.cc: test/stattest.cc: Get rid of simplescalar host.h file and create our own host.hh file that has less junk. (with our license.) While we're at it, we consolidate all of the hashtable junk into one file hashmap.hh. (use this file if you need a hash_map.) Doxyfile: Avoid infinite recursion on build/src link. arch/alpha/isa_desc: sim/static_inst.hh: Add comments to get rid of doxygen warnings (and occasionally, as an accidental side effect, make the code more maintainable). Doxyfile: Turn off information messages and route error messages to stderr. arch/isa_parser.py: arch/alpha/isa_desc: sim/static_inst.hh: - Add some comments clarifying the semantics of StaticInst flags. - Make minor tweaks to the ISA description code to make corner cases consistent with the above comments :-). - Get rid of insn_counting code... instruction mix doesn't really change through the pipeline, and the overall mix can already be derived from existing stats. Plus it keeps changing when the ISA flags change even though the pipeline doesn't care. sim/hybrid_pred.cc: sim/hybrid_pred.hh: So said Steve Raasch:xi "I know that the following files should be under our license" base/fast_alloc.cc: base/fast_alloc.hh: David Wood said I could have my own code back :-). sim/sim_object.cc: sim/sim_object.hh: create a regFormulas pass that will go AFTER the regStats pass. sim/base_cpu.cc: sim/base_cpu.hh: sim/debug.cc: sim/eventq.cc: sim/exec_context.hh: sim/exetrace.cc: sim/exetrace.hh: sim/hybrid_pred.cc: sim/hybrid_pred.hh: sim/intr_control.hh: sim/main.cc: sim/memtest.cc: sim/memtest.hh: sim/op_class.hh: sim/param.cc: sim/param.hh: sim/pc_event.hh: sim/predictor.hh: sim/prog.cc: sim/prog.hh: sim/sat_counter.cc: sim/sat_counter.hh: sim/serialize.cc: sim/serialize.hh: sim/sim_object.hh: sim/sim_time.hh: sim/simple_cpu.hh: sim/smt.hh: sim/static_inst.cc: sim/static_inst.hh: sim/std_types.hh: sim/system.cc: style police base/statistics.cc: base/statistics.hh: test/stattest.cc: initial cut at a 2d vector stat base/statistics.cc: base/statistics.hh: Added a std:: and removed an unused bool arch/alpha/fake_syscall.cc: sim/base_cpu.cc: sim/base_cpu.hh: sim/prog.cc: sim/prog.hh: Steve Reinhardt says "I wrote these myself from scratch" base/date.cc: I probably changed this to a string in the first place, but it should be a const char * sim/main.cc: make this compile again base/random.cc: base/random.hh: sim/main.cc: Get rid of the Simplescalar random number junk. Since I didn't realize that we didn't even use it until after I wrote a simple replacement, I figure I'll commit the replacement in case we ever need it. base/str.hh: sim/main.cc: quote may be more generally useful sim/main.cc: sim/sim_object.cc: sim/sim_object.hh: Make the old stats package a bit more self contained to prepare for future extrication sim/main.cc: sim/sim_time.cc: sim/sim_time.hh: consolidate all of the time handling stuff sim/base_cpu.cc: sim/base_cpu.hh: sim/main.cc: sim/smt.hh: instead of initializing max_threads_per_cpu in main(), we turn it into a static function and initialize it upon the first call Users of this should beware that all CPUs must be built before this function can be used. sim/main.cc: sim/universe.cc: sim_running_systems makes more sense in universe.cc sim/main.cc: this is not a simplescalar file, use our copyright say that the simulator is M5 and display our copyright cleanup change a few things here and there to use our style use endl instead of "\n" (for future portablility) sim/async.hh: sim/main.cc: sim/system.cc: sim/system.hh: sim/universe.cc: - Clean up a few simplescalar comments from main.cc that Nate missed. - Add some comments and some doxygen documentation. - Move sim_running_systems to static System::numSystemsRunning. arch/alpha/ev5.cc: Update num_running_systems to System::numSystemsRunning for full-sys too. sim/base_cpu.cc: sim/base_cpu.hh: sim/smt.hh: instead of polling all CPUs to find out the max number of threads across all CPUs, just have the CPUs themselves update the variable as they are created. arch/alpha/isa_desc: First pass at fixing cvtst... not tested. arch/alpha/ev5.cc: base/statistics.cc: base/statistics.hh: arch/alpha/isa_desc: Just use the TYPEFUNC not FULLFUNC arch/alpha/ev5.cc: base/statistics.cc: base/statistics.hh: committing from the wrong directory is a bad thing arch/alpha/isa_desc: I hope a final solution for the cmptxx issue. base/statistics.cc: All printable stats must first be initialized, so throw an assertion if they are not. This ought to help in debugging a bit. base/statistics.cc: base/statistics.hh: Two new flags: nozero, and nonan. This will supress printing stats if they are zero or NAN. For example, it will cause vector elements to be skipped if there is no value, or it will cause distribution buckets to be skipped. (or an entire scalar stat to be skipped.) This can be used in conjunction with prereq. The difference with prereq, is that prereq just checks if the other stat has ANY values, and won't selectively ignore individual vector elements. base/statistics.hh: this does not belong here arch/alpha/isa_desc: Just happened to notice small insidious bug in itofs. arch/isa_parser.py: New isa description language feature: multiple constants can be provided for a decode statement, e.g.: decode OP { 0, 1: foo(); 2, 3: bar(); } Documentation update included at no extra charge. sim/param.hh: this can be const sim/exec_context.cc: be more terse arch/alpha/isa_desc: Revamp decoding of IEEE FP instructions (opcode 0x16). I think we've got all the bases covered now. Also implemented cvtql/v & cvtql/sv (actually the same instruction from M5's perspective). arch/isa_parser.py: - If isa_desc defines the global Python variable rcs_id, echo it into the output decoder.cc. - Only print last three components of ISA description path name in output. - Add RCS id string to this file. arch/alpha/isa_desc: Add RCS id string. arch/isa_parser.py: Get it right. arch/isa_parser.py: Oone more little glitch... kern/tru64/tru64_syscalls.cc: kern/tru64/tru64_syscalls.hh: add support for mach syscalls. base/trace.cc: base/trace.hh: Some reorganization and cleanup. Add the ability to ignore trace output from certain sources. The option is --trace:ignore. It takes a space separated list of SimObjects to ignore. The SimObject is listed in the normal dotted herarchy notation. (e.g. system0.cpu0.DL1) If an object is specified, the *all* child objects are ignored as well. You can use a wildcard (*) to match any object. To ignore all trace statements from system1: --trace:ignore"system1" To ignore all DL1 statements: --trace:ignore="*.*.DL1" sim/main.cc: Try the HOST varilable if HOSTNAME isn't found sim/exetrace.cc: sim/exetrace.hh: Minor tweeks to instruction execution tracing: - add a correct-path sequence number to all instructions - add colon characters to help delimit the instruction disassembly arch/alpha/ev5.cc: Move all of the kernel statistics into the .cc file while I am still messing around with them. Add support for tracking context switches, and mode switches. More detailed tracking of ipl changes. Don't display zeroes for stats such as syscalls, ipls, faults, since zeroes are very common and there are a ton of stats. base/hashmap.hh: don't forget about the hash_multimap oh, and string is used in here base/str.cc: convert strings that represent bool values to a bool arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: arch/alpha/ev5.cc: rework the tlb lookup code so that it uses a map instead of a linear search. base/statistics.cc: a tiny bit of debugging assistance arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: sim/exec_context.hh: No need for these functions to be virtual. Given that, they don't need to have the same interface. This eliminates a useless check in an expensive function. arch/alpha/isa_desc: This is an quick fix for the SimpleSclar-FP-Ops-Don't-Work-Right bug The SS_COMPATIBLE_FP #define at the top of the file forces the precision to match SS. This will change the precision for ALL CPU's. Nate will be making a change shortly so that this not done for Full System arch/alpha/alpha_memory.cc: use i-> instead of (*i). (what was I thinking?) also try to do i-> only once if it can be helped. base/remote_gdb.cc: sim/simple_cpu.cc: Move remote debugger code to where it belongs clean it up a tad while we're at it. arch/alpha/isa_desc: Changes for the SS FP bug: SS-style FP done only if SS_COMPATIBLE_FP is defined in the makefile arch/alpha/isa_traits.hh: sim/memtest.cc: sim/memtest.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: sim/cache/lzss_compression.cc: sim/cache/lzss_compression.hh: The new memory hierarchy. There is still some more changes to come, but this works now. IIC compression is broken, but no one else cares. DMA coherence might be broken (no way to test atm). There are doxygen warnings that I will clear up when I can stay connected for more than 3 minutes. Doxyfile: Turn Graphics back on since we have squashed the warnings. base/misc.hh: Add #include <assert.h> for those who use m5_assert() macro. Somehow g++ 3.3 is pickier about this than 3.2. sim/exetrace.hh: sim/simple_cpu.cc: sim/std_types.hh: Style fixes... mostly changing 'struct foo_bar' to 'FooBar' for some older parts of the code. Doxyfile: Always have a detailed section. sim/host.hh: Get rid of an old simplescalar comment (plus improve some other comments). base/statistics.cc: base/statistics.hh: provide a way to get at the subdesc base/statistics.hh: Make it possible to counte a sample more than once base/statistics.cc: print the right value base/statistics.cc: base/statistics.hh: A bit of debugging support base/statistics.cc: base/statistics.hh: be more consistent base/statistics.hh: use the correct axis base/statistics.hh: remove dead code sim/main.cc: sim/param.cc: sim/param.hh: sim/sim_object.cc: Stats now sent by default to a file called "m5.stats". Get the old behavior back by saying "--stats:file=cerr" on cmd line. Parameters and config-file stuff also sent to stats file where they belong. A few informational messages are sent to both cerr and to the stats file. Default output is pretty minimal now. arch/alpha/faults.cc: base/bitfield.hh: base/random.cc: base/random.hh: sim/static_inst.cc: test/stattest.cc: Fix RCS Id strings. sim/base_cpu.hh: sim/main.cc: Check if user forgot to specify any CPUs and print a meaningful error message (not just "improperly exited event loop!"). base/statistics.cc: base/statistics.hh: Make subsequent calls to flags() add more flags instead of change them. Also add the concept of a reserved flag that the user is not allowed to set. (Basically for passing around extra parameters in the stats package.) sim/debug.cc: sim/param.cc: sim/param.hh: sim/prog.cc: sim/sim_events.cc: Check that VectorParam objects are valid before we let them be referenced. Fix up a few places where we were just referencing them w/o checking. Also some const cleanup on Param object methods. sim/sim_object.cc: sim/sim_object.hh: Print SimObject class name when complaining about missing/broekn params. base/inifile.cc: Add "-undef" to cpp flags to not define system-specific macros. (A '#define linux 1' was giving me trouble.) base/statistics.hh: add support fo subnaming in the y direction for 2d vectors. make the printing of it pretty and compatible with the old style. also, suppress printing of a total for 2d vector if they x dimension is just 1. base/statistics.cc: rework a lot of the stuff between #ifdef STAT_DISPLAY_COMPAT so it's neater and also more accurate. add support for printing subdescriptions. LICENSE: arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: arch/alpha/arguments.cc: arch/alpha/arguments.hh: arch/alpha/fake_syscall.cc: arch/alpha/faults.cc: arch/alpha/faults.hh: arch/alpha/isa_traits.hh: arch/alpha/osfpal.cc: arch/alpha/osfpal.hh: arch/alpha/vtophys.cc: arch/alpha/vtophys.hh: base/bitfield.hh: base/callback.hh: base/circlebuf.cc: base/circlebuf.hh: base/cprintf.cc: base/cprintf.hh: base/cprintf_formats.hh: base/date.cc: base/dbl_list.hh: base/endian.hh: base/fast_alloc.cc: base/fast_alloc.hh: base/fifo_buffer.cc: base/fifo_buffer.hh: base/hashmap.hh: base/inet.cc: base/inet.hh: base/inifile.cc: base/inifile.hh: base/intmath.cc: base/misc.cc: base/misc.hh: base/mod_num.hh: base/object_file.cc: base/object_file.hh: base/pollevent.cc: base/pollevent.hh: base/random.cc: base/random.hh: base/range.hh: base/refcnt.hh: base/remote_gdb.hh: base/res_list.hh: base/sched_list.hh: base/socket.cc: base/socket.hh: base/statistics.cc: base/statistics.hh: base/str.cc: base/str.hh: base/symtab.cc: base/symtab.hh: base/trace.cc: base/trace.hh: dev/alpha_console.cc: dev/alpha_console.hh: dev/disk_image.cc: dev/disk_image.hh: dev/etherbus.cc: dev/etherbus.hh: dev/etherdump.cc: dev/etherdump.hh: dev/etherint.cc: dev/etherint.hh: dev/etherlink.cc: dev/etherlink.hh: dev/etherpkt.hh: dev/ethertap.cc: dev/ethertap.hh: dev/simple_disk.cc: dev/simple_disk.hh: kern/tru64/tru64.hh: kern/tru64/tru64_syscalls.cc: kern/tru64/tru64_syscalls.hh: sim/async.hh: sim/base_cpu.cc: sim/base_cpu.hh: sim/debug.cc: sim/debug.hh: sim/eventq.cc: sim/eventq.hh: sim/exec_context.cc: sim/exec_context.hh: sim/exetrace.cc: sim/exetrace.hh: sim/host.hh: sim/hybrid_pred.cc: sim/hybrid_pred.hh: sim/intr_control.cc: sim/intr_control.hh: sim/main.cc: sim/memtest.cc: sim/memtest.hh: sim/op_class.hh: sim/param.cc: sim/param.hh: sim/pc_event.cc: sim/pc_event.hh: sim/predictor.hh: sim/prog.cc: sim/prog.hh: sim/sat_counter.cc: sim/sat_counter.hh: sim/serialize.cc: sim/serialize.hh: sim/sim_events.cc: sim/sim_events.hh: sim/sim_exit.hh: sim/sim_object.cc: sim/sim_object.hh: sim/cache/lzss_compression.cc: sim/cache/lzss_compression.hh: sim/cache/null_compression.hh: sim/sim_time.cc: sim/sim_time.hh: sim/simple_cpu.cc: sim/simple_cpu.hh: sim/smt.hh: sim/static_inst.cc: sim/static_inst.hh: sim/std_types.hh: sim/system.cc: sim/system.hh: sim/universe.cc: test/bitvectest.cc: test/circletest.cc: test/cprintftest.cc: test/initest.cc: test/lru_test.cc: test/nmtest.cc: test/offtest.cc: test/paramtest.cc: test/rangetest.cc: test/sized_test.cc: test/stattest.cc: test/strnumtest.cc: test/symtest.cc: test/tokentest.cc: util/tap/tap.cc: arch/isa_parser.py: Add attribution to license. sim/cache/lzss_compression.cc: sim/cache/lzss_compression.hh: Extend the compression algorithm to handle upto 4096 byte blocks. Improve compression of single bytes that can be sign extended. sim/cache/lzss_compression.hh: Remove some todos that I've already done. sim/hybrid_pred.cc: sim/hybrid_pred.hh: sim/memtest.cc: sim/prog.cc: sim/sat_counter.cc: sim/memtest.hh: sim/predictor.hh: sim/prog.hh: sim/sat_counter.hh: the new stats package. voila. the move to bitkeeper can go on, figuring what's happening can happen later. base/trace.cc: test/Makefile: test/cprintftest.cc: test/tracetest.cc: separate the context stuff for tracing from the actual tracing facility to make it easier to test. Add a test for tracing --HG-- extra : convert_revision : 28dd3568b0714296345f8a5cba282f0b937ce725
This commit is contained in:
parent
a06eab767e
commit
92638f9a65
162 changed files with 38124 additions and 0 deletions
25
LICENSE
Normal file
25
LICENSE
Normal file
|
@ -0,0 +1,25 @@
|
|||
Copyright (c) 2000-2003 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.
|
661
arch/alpha/alpha_memory.cc
Normal file
661
arch/alpha/alpha_memory.cc
Normal file
|
@ -0,0 +1,661 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 <vector>
|
||||
|
||||
#include "alpha_memory.hh"
|
||||
#include "ev5.hh"
|
||||
#include "exec_context.hh"
|
||||
#include "trace.hh"
|
||||
#include "inifile.hh"
|
||||
#include "str.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Alpha TLB
|
||||
//
|
||||
AlphaTlb::AlphaTlb(const string &name, int s)
|
||||
: SimObject(name), size(s), nlu(0)
|
||||
{
|
||||
table = new AlphaISA::PTE[size];
|
||||
memset(table, 0, sizeof(AlphaISA::PTE[size]));
|
||||
}
|
||||
|
||||
AlphaTlb::~AlphaTlb()
|
||||
{
|
||||
if (table)
|
||||
delete [] table;
|
||||
}
|
||||
|
||||
// look up an entry in the TLB
|
||||
AlphaISA::PTE *
|
||||
AlphaTlb::lookup(Addr vpn, uint8_t asn) const
|
||||
{
|
||||
DPRINTF(TLB, "lookup %#x\n", vpn);
|
||||
|
||||
PageTable::const_iterator i = lookupTable.find(vpn);
|
||||
if (i == lookupTable.end())
|
||||
return NULL;
|
||||
|
||||
while (i->first == vpn) {
|
||||
int index = i->second;
|
||||
AlphaISA::PTE *pte = &table[index];
|
||||
assert(pte->valid);
|
||||
if (vpn == pte->tag && (pte->asma || pte->asn == asn))
|
||||
return pte;
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
// not found...
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AlphaTlb::checkCacheability(MemReqPtr req)
|
||||
{
|
||||
// in Alpha, cacheability is controlled by upper-level bits of the
|
||||
// physical address
|
||||
if (req->paddr & PA_UNCACHED_BIT) {
|
||||
if (PA_IPR_SPACE(req->paddr)) {
|
||||
// IPR memory space not implemented
|
||||
if (!req->xc->misspeculating())
|
||||
panic("IPR memory space not implemented! PA=%x\n", req->paddr);
|
||||
} else {
|
||||
// mark request as uncacheable
|
||||
req->flags |= UNCACHEABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// insert a new TLB entry
|
||||
void
|
||||
AlphaTlb::insert(Addr vaddr, AlphaISA::PTE &pte)
|
||||
{
|
||||
if (table[nlu].valid) {
|
||||
Addr oldvpn = table[nlu].tag;
|
||||
PageTable::iterator i = lookupTable.find(oldvpn);
|
||||
|
||||
if (i == lookupTable.end())
|
||||
panic("TLB entry not found in lookupTable");
|
||||
|
||||
int index;
|
||||
while ((index = i->second) != nlu) {
|
||||
if (table[index].tag != oldvpn)
|
||||
panic("TLB entry not found in lookupTable");
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn);
|
||||
|
||||
lookupTable.erase(i);
|
||||
}
|
||||
|
||||
Addr vpn = VA_VPN(vaddr);
|
||||
DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vpn, pte.ppn);
|
||||
|
||||
table[nlu] = pte;
|
||||
table[nlu].tag = vpn;
|
||||
table[nlu].valid = true;
|
||||
|
||||
lookupTable.insert(make_pair(vpn, nlu));
|
||||
nextnlu();
|
||||
}
|
||||
|
||||
void
|
||||
AlphaTlb::flushAll()
|
||||
{
|
||||
memset(table, 0, sizeof(AlphaISA::PTE[size]));
|
||||
lookupTable.clear();
|
||||
nlu = 0;
|
||||
}
|
||||
|
||||
void
|
||||
AlphaTlb::flushProcesses()
|
||||
{
|
||||
PageTable::iterator i = lookupTable.begin();
|
||||
PageTable::iterator end = lookupTable.end();
|
||||
while (i != end) {
|
||||
int index = i->second;
|
||||
AlphaISA::PTE *pte = &table[index];
|
||||
assert(pte->valid);
|
||||
|
||||
if (!pte->asma) {
|
||||
DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, pte->tag, pte->ppn);
|
||||
pte->valid = false;
|
||||
lookupTable.erase(i);
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AlphaTlb::flushAddr(Addr vaddr, uint8_t asn)
|
||||
{
|
||||
Addr vpn = VA_VPN(vaddr);
|
||||
|
||||
PageTable::iterator i = lookupTable.find(vpn);
|
||||
if (i == lookupTable.end())
|
||||
return;
|
||||
|
||||
while (i->first == vpn) {
|
||||
int index = i->second;
|
||||
AlphaISA::PTE *pte = &table[index];
|
||||
assert(pte->valid);
|
||||
|
||||
if (vpn == pte->tag && (pte->asma || pte->asn == asn)) {
|
||||
DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vpn, pte->ppn);
|
||||
|
||||
// invalidate this entry
|
||||
pte->valid = false;
|
||||
|
||||
lookupTable.erase(i);
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AlphaTlb::serialize()
|
||||
{
|
||||
nameOut();
|
||||
|
||||
paramOut("size", size);
|
||||
paramOut("nlu", nlu);
|
||||
|
||||
stringstream buf;
|
||||
for (int i = 0; i < size; i++) {
|
||||
buf.str("");
|
||||
ccprintf(buf, "pte%02d.valid", i);
|
||||
paramOut(buf.str(), table[i].valid);
|
||||
|
||||
buf.str("");
|
||||
ccprintf(buf, "pte%02d.tag", i);
|
||||
paramOut(buf.str(), table[i].tag);
|
||||
|
||||
buf.str("");
|
||||
ccprintf(buf, "pte%02d.ppn", i);
|
||||
paramOut(buf.str(), table[i].ppn);
|
||||
|
||||
buf.str("");
|
||||
ccprintf(buf, "pte%02d.xre", i);
|
||||
paramOut(buf.str(), table[i].xre);
|
||||
|
||||
buf.str("");
|
||||
ccprintf(buf, "pte%02d.xwe", i);
|
||||
paramOut(buf.str(), table[i].xwe);
|
||||
|
||||
buf.str("");
|
||||
ccprintf(buf, "pte%02d.fonr", i);
|
||||
paramOut(buf.str(), table[i].fonr);
|
||||
|
||||
buf.str("");
|
||||
ccprintf(buf, "pte%02d.fonw", i);
|
||||
paramOut(buf.str(), table[i].fonw);
|
||||
|
||||
buf.str("");
|
||||
ccprintf(buf, "pte%02d.asma", i);
|
||||
paramOut(buf.str(), table[i].asma);
|
||||
|
||||
buf.str("");
|
||||
ccprintf(buf, "pte%02d.asn", i);
|
||||
paramOut(buf.str(), table[i].asn);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AlphaTlb::unserialize(IniFile &db, const string &category, ConfigNode *node)
|
||||
{
|
||||
string data;
|
||||
stringstream buf;
|
||||
|
||||
db.findDefault(category,"size",data);
|
||||
to_number(data,size);
|
||||
db.findDefault(category,"nlu",data);
|
||||
to_number(data,nlu);
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
buf.str("");
|
||||
ccprintf(buf, "pte%02d.valid", i);
|
||||
db.findDefault(category, buf.str(), data);
|
||||
to_number(data, table[i].valid);
|
||||
|
||||
buf.str("");
|
||||
ccprintf(buf, "pte%02d.tag", i);
|
||||
db.findDefault(category, buf.str(), data);
|
||||
to_number(data, table[i].tag);
|
||||
|
||||
buf.str("");
|
||||
ccprintf(buf, "pte%02d.ppn", i);
|
||||
db.findDefault(category, buf.str(), data);
|
||||
to_number(data, table[i].ppn);
|
||||
|
||||
buf.str("");
|
||||
ccprintf(buf, "pte%02d.xre", i);
|
||||
db.findDefault(category, buf.str(), data);
|
||||
to_number(data, table[i].xre);
|
||||
|
||||
buf.str("");
|
||||
ccprintf(buf, "pte%02d.xwe", i);
|
||||
db.findDefault(category, buf.str(), data);
|
||||
to_number(data, table[i].xwe);
|
||||
|
||||
buf.str("");
|
||||
ccprintf(buf, "pte%02d.fonr", i);
|
||||
db.findDefault(category, buf.str(), data);
|
||||
to_number(data, table[i].fonr);
|
||||
|
||||
buf.str("");
|
||||
ccprintf(buf, "pte%02d.fonw", i);
|
||||
db.findDefault(category, buf.str(), data);
|
||||
to_number(data, table[i].fonw);
|
||||
|
||||
buf.str("");
|
||||
ccprintf(buf, "pte%02d.asma", i);
|
||||
db.findDefault(category, buf.str(), data);
|
||||
to_number(data, table[i].asma);
|
||||
|
||||
buf.str("");
|
||||
ccprintf(buf, "pte%02d.asn", i);
|
||||
db.findDefault(category, buf.str(), data);
|
||||
to_number(data, table[i].asn);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Alpha ITB
|
||||
//
|
||||
AlphaItb::AlphaItb(const std::string &name, int size)
|
||||
: AlphaTlb(name, size)
|
||||
{}
|
||||
|
||||
|
||||
void
|
||||
AlphaItb::regStats()
|
||||
{
|
||||
hits
|
||||
.name(name() + ".hits")
|
||||
.desc("ITB hits");
|
||||
misses
|
||||
.name(name() + ".misses")
|
||||
.desc("ITB misses");
|
||||
acv
|
||||
.name(name() + ".acv")
|
||||
.desc("ITB acv");
|
||||
accesses
|
||||
.name(name() + ".accesses")
|
||||
.desc("ITB accesses");
|
||||
|
||||
accesses = hits + misses;
|
||||
}
|
||||
|
||||
void
|
||||
AlphaItb::fault(Addr pc, ExecContext *xc) const
|
||||
{
|
||||
uint64_t *ipr = xc->regs.ipr;
|
||||
|
||||
if (!xc->misspeculating()) {
|
||||
ipr[AlphaISA::IPR_ITB_TAG] = pc;
|
||||
ipr[AlphaISA::IPR_IFAULT_VA_FORM] =
|
||||
ipr[AlphaISA::IPR_IVPTBR] | (VA_VPN(pc) << 3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Fault
|
||||
AlphaItb::translate(MemReqPtr req) const
|
||||
{
|
||||
InternalProcReg *ipr = req->xc->regs.ipr;
|
||||
|
||||
if (PC_PAL(req->vaddr)) {
|
||||
// strip off PAL PC marker (lsb is 1)
|
||||
req->paddr = (req->vaddr & ~3) & PA_IMPL_MASK;
|
||||
hits++;
|
||||
return No_Fault;
|
||||
}
|
||||
|
||||
// verify that this is a good virtual address
|
||||
if (!validVirtualAddress(req->vaddr)) {
|
||||
fault(req->vaddr, req->xc);
|
||||
acv++;
|
||||
return Itb_Acv_Fault;
|
||||
}
|
||||
|
||||
// Check for "superpage" mapping: when SP<1> is set, and
|
||||
// VA<42:41> == 2, VA<39:13> maps directly to PA<39:13>.
|
||||
if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) &&
|
||||
VA_SPACE(req->vaddr) == 2) {
|
||||
// only valid in kernel mode
|
||||
if (ICM_CM(ipr[AlphaISA::IPR_ICM]) != AlphaISA::mode_kernel) {
|
||||
fault(req->vaddr, req->xc);
|
||||
acv++;
|
||||
return Itb_Acv_Fault;
|
||||
}
|
||||
|
||||
req->flags |= PHYSICAL;
|
||||
}
|
||||
|
||||
if (req->flags & PHYSICAL) {
|
||||
req->paddr = req->vaddr & PA_IMPL_MASK;
|
||||
} else {
|
||||
// not a physical address: need to look up pte
|
||||
|
||||
AlphaISA::PTE *pte = lookup(VA_VPN(req->vaddr),
|
||||
DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
|
||||
|
||||
if (!pte) {
|
||||
fault(req->vaddr, req->xc);
|
||||
misses++;
|
||||
return Itb_Fault_Fault;
|
||||
}
|
||||
|
||||
req->paddr = PA_PFN2PA(pte->ppn) + VA_POFS(req->vaddr & ~3);
|
||||
|
||||
// check permissions for this access
|
||||
if (!(pte->xre & (1 << ICM_CM(ipr[AlphaISA::IPR_ICM])))) {
|
||||
// instruction access fault
|
||||
fault(req->vaddr, req->xc);
|
||||
acv++;
|
||||
return Itb_Acv_Fault;
|
||||
}
|
||||
}
|
||||
|
||||
checkCacheability(req);
|
||||
|
||||
hits++;
|
||||
return No_Fault;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Alpha DTB
|
||||
//
|
||||
AlphaDtb::AlphaDtb(const std::string &name, int size)
|
||||
: AlphaTlb(name, size)
|
||||
{}
|
||||
|
||||
void
|
||||
AlphaDtb::regStats()
|
||||
{
|
||||
read_hits
|
||||
.name(name() + ".read_hits")
|
||||
.desc("DTB read hits")
|
||||
;
|
||||
|
||||
read_misses
|
||||
.name(name() + ".read_misses")
|
||||
.desc("DTB read misses")
|
||||
;
|
||||
|
||||
read_acv
|
||||
.name(name() + ".read_acv")
|
||||
.desc("DTB read access violations")
|
||||
;
|
||||
|
||||
read_accesses
|
||||
.name(name() + ".read_accesses")
|
||||
.desc("DTB read accesses")
|
||||
;
|
||||
|
||||
write_hits
|
||||
.name(name() + ".write_hits")
|
||||
.desc("DTB write hits")
|
||||
;
|
||||
|
||||
write_misses
|
||||
.name(name() + ".write_misses")
|
||||
.desc("DTB write misses")
|
||||
;
|
||||
|
||||
write_acv
|
||||
.name(name() + ".write_acv")
|
||||
.desc("DTB write access violations")
|
||||
;
|
||||
|
||||
write_accesses
|
||||
.name(name() + ".write_accesses")
|
||||
.desc("DTB write accesses")
|
||||
;
|
||||
|
||||
hits
|
||||
.name(name() + ".hits")
|
||||
.desc("DTB hits")
|
||||
;
|
||||
|
||||
misses
|
||||
.name(name() + ".misses")
|
||||
.desc("DTB misses")
|
||||
;
|
||||
|
||||
acv
|
||||
.name(name() + ".acv")
|
||||
.desc("DTB access violations")
|
||||
;
|
||||
|
||||
accesses
|
||||
.name(name() + ".accesses")
|
||||
.desc("DTB accesses")
|
||||
;
|
||||
|
||||
hits = read_hits + write_hits;
|
||||
misses = read_misses + write_misses;
|
||||
acv = read_acv + write_acv;
|
||||
accesses = read_accesses + write_accesses;
|
||||
}
|
||||
|
||||
void
|
||||
AlphaDtb::fault(Addr vaddr, uint64_t flags, ExecContext *xc) const
|
||||
{
|
||||
uint64_t *ipr = xc->regs.ipr;
|
||||
|
||||
// set fault address and flags
|
||||
if (!xc->misspeculating() && !xc->regs.intrlock) {
|
||||
// set VA register with faulting address
|
||||
ipr[AlphaISA::IPR_VA] = vaddr;
|
||||
|
||||
// set MM_STAT register flags
|
||||
ipr[AlphaISA::IPR_MM_STAT] = (((xc->regs.opcode & 0x3f) << 11)
|
||||
| ((xc->regs.ra & 0x1f) << 6)
|
||||
| (flags & 0x3f));
|
||||
|
||||
// set VA_FORM register with faulting formatted address
|
||||
ipr[AlphaISA::IPR_VA_FORM] =
|
||||
ipr[AlphaISA::IPR_MVPTBR] | (VA_VPN(vaddr) << 3);
|
||||
|
||||
// lock these registers until the VA register is read
|
||||
xc->regs.intrlock = true;
|
||||
}
|
||||
}
|
||||
|
||||
Fault
|
||||
AlphaDtb::translate(MemReqPtr req, bool write) const
|
||||
{
|
||||
RegFile *regs = &req->xc->regs;
|
||||
Addr pc = regs->pc;
|
||||
InternalProcReg *ipr = regs->ipr;
|
||||
|
||||
if (write)
|
||||
write_accesses++;
|
||||
else
|
||||
read_accesses++;
|
||||
|
||||
AlphaISA::md_mode_type mode =
|
||||
(AlphaISA::md_mode_type)DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]);
|
||||
|
||||
if (PC_PAL(pc)) {
|
||||
mode = (req->flags & ALTMODE) ? (AlphaISA::md_mode_type)
|
||||
(ALT_MODE_AM(ipr[AlphaISA::IPR_ALT_MODE]))
|
||||
: AlphaISA::mode_kernel;
|
||||
}
|
||||
|
||||
// verify that this is a good virtual address
|
||||
if (!validVirtualAddress(req->vaddr)) {
|
||||
fault(req->vaddr,
|
||||
((write ? MM_STAT_WR_MASK : 0) | MM_STAT_BAD_VA_MASK |
|
||||
MM_STAT_ACV_MASK),
|
||||
req->xc);
|
||||
|
||||
if (write) { write_acv++; } else { read_acv++; }
|
||||
return Dtb_Fault_Fault;
|
||||
}
|
||||
|
||||
// Check for "superpage" mapping: when SP<1> is set, and
|
||||
// VA<42:41> == 2, VA<39:13> maps directly to PA<39:13>.
|
||||
if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) && VA_SPACE(req->vaddr) == 2) {
|
||||
// only valid in kernel mode
|
||||
if (DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]) != AlphaISA::mode_kernel) {
|
||||
fault(req->vaddr,
|
||||
((write ? MM_STAT_WR_MASK : 0) | MM_STAT_ACV_MASK),
|
||||
req->xc);
|
||||
if (write) { write_acv++; } else { read_acv++; }
|
||||
return Dtb_Acv_Fault;
|
||||
}
|
||||
|
||||
req->flags |= PHYSICAL;
|
||||
}
|
||||
|
||||
if (req->flags & PHYSICAL) {
|
||||
req->paddr = req->vaddr & PA_IMPL_MASK;
|
||||
} else {
|
||||
// not a physical address: need to look up pte
|
||||
|
||||
AlphaISA::PTE *pte = lookup(VA_VPN(req->vaddr),
|
||||
DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
|
||||
|
||||
if (!pte) {
|
||||
// page fault
|
||||
fault(req->vaddr,
|
||||
((write ? MM_STAT_WR_MASK : 0) | MM_STAT_DTB_MISS_MASK),
|
||||
req->xc);
|
||||
if (write) { write_misses++; } else { read_misses++; }
|
||||
return (req->flags & VPTE) ? Pdtb_Miss_Fault : Ndtb_Miss_Fault;
|
||||
}
|
||||
|
||||
req->paddr = PA_PFN2PA(pte->ppn) | VA_POFS(req->vaddr);
|
||||
|
||||
if (write) {
|
||||
if (!(pte->xwe & MODE2MASK(mode))) {
|
||||
// declare the instruction access fault
|
||||
fault(req->vaddr, MM_STAT_WR_MASK | MM_STAT_ACV_MASK |
|
||||
(pte->fonw ? MM_STAT_FONW_MASK : 0),
|
||||
req->xc);
|
||||
write_acv++;
|
||||
return Dtb_Fault_Fault;
|
||||
}
|
||||
if (pte->fonw) {
|
||||
fault(req->vaddr, MM_STAT_WR_MASK | MM_STAT_FONW_MASK,
|
||||
req->xc);
|
||||
write_acv++;
|
||||
return Dtb_Fault_Fault;
|
||||
}
|
||||
} else {
|
||||
if (!(pte->xre & MODE2MASK(mode))) {
|
||||
fault(req->vaddr,
|
||||
MM_STAT_ACV_MASK | (pte->fonr ? MM_STAT_FONR_MASK : 0),
|
||||
req->xc);
|
||||
read_acv++;
|
||||
return Dtb_Acv_Fault;
|
||||
}
|
||||
if (pte->fonr) {
|
||||
fault(req->vaddr, MM_STAT_FONR_MASK, req->xc);
|
||||
read_acv++;
|
||||
return Dtb_Fault_Fault;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkCacheability(req);
|
||||
|
||||
if (write)
|
||||
write_hits++;
|
||||
else
|
||||
read_hits++;
|
||||
|
||||
return No_Fault;
|
||||
}
|
||||
|
||||
AlphaISA::PTE &
|
||||
AlphaTlb::index()
|
||||
{
|
||||
AlphaISA::PTE *pte = &table[nlu];
|
||||
nextnlu();
|
||||
|
||||
return *pte;
|
||||
}
|
||||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaItb)
|
||||
|
||||
Param<int> size;
|
||||
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(AlphaItb)
|
||||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaItb)
|
||||
|
||||
INIT_PARAM_DFLT(size, "TLB size", 48)
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(AlphaItb)
|
||||
|
||||
|
||||
CREATE_SIM_OBJECT(AlphaItb)
|
||||
{
|
||||
return new AlphaItb(getInstanceName(), size);
|
||||
}
|
||||
|
||||
REGISTER_SIM_OBJECT("AlphaITB", AlphaItb)
|
||||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaDtb)
|
||||
|
||||
Param<int> size;
|
||||
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(AlphaDtb)
|
||||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaDtb)
|
||||
|
||||
INIT_PARAM_DFLT(size, "TLB size", 64)
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(AlphaDtb)
|
||||
|
||||
|
||||
CREATE_SIM_OBJECT(AlphaDtb)
|
||||
{
|
||||
return new AlphaDtb(getInstanceName(), size);
|
||||
}
|
||||
|
||||
REGISTER_SIM_OBJECT("AlphaDTB", AlphaDtb)
|
126
arch/alpha/alpha_memory.hh
Normal file
126
arch/alpha/alpha_memory.hh
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 __ALPHA_MEMORY_HH__
|
||||
#define __ALPHA_MEMORY_HH__
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "mem_req.hh"
|
||||
#include "sim_object.hh"
|
||||
#include "statistics.hh"
|
||||
|
||||
class ExecContext;
|
||||
|
||||
class AlphaTlb : public SimObject
|
||||
{
|
||||
protected:
|
||||
typedef std::multimap<Addr, int> PageTable;
|
||||
PageTable lookupTable; // Quick lookup into page table
|
||||
|
||||
AlphaISA::PTE *table; // the Page Table
|
||||
int size; // TLB Size
|
||||
int nlu; // not last used entry (for replacement)
|
||||
|
||||
void nextnlu() { if (++nlu >= size) nlu = 0; }
|
||||
AlphaISA::PTE *lookup(Addr vpn, uint8_t asn) const;
|
||||
|
||||
public:
|
||||
AlphaTlb(const std::string &name, int size);
|
||||
virtual ~AlphaTlb();
|
||||
|
||||
int getsize() const { return size; }
|
||||
|
||||
AlphaISA::PTE &index();
|
||||
void insert(Addr vaddr, AlphaISA::PTE &pte);
|
||||
|
||||
void flushAll();
|
||||
void flushProcesses();
|
||||
void flushAddr(Addr addr, uint8_t asn);
|
||||
|
||||
// static helper functions... really EV5 VM traits
|
||||
static bool validVirtualAddress(Addr vaddr) {
|
||||
// unimplemented bits must be all 0 or all 1
|
||||
Addr unimplBits = vaddr & VA_UNIMPL_MASK;
|
||||
return (unimplBits == 0) || (unimplBits == VA_UNIMPL_MASK);
|
||||
}
|
||||
|
||||
static void checkCacheability(MemReqPtr req);
|
||||
|
||||
// Checkpointing
|
||||
virtual void serialize();
|
||||
virtual void unserialize(IniFile &db, const std::string &category,
|
||||
ConfigNode *node);
|
||||
|
||||
};
|
||||
|
||||
class AlphaItb : public AlphaTlb
|
||||
{
|
||||
protected:
|
||||
mutable Statistics::Scalar<> hits;
|
||||
mutable Statistics::Scalar<> misses;
|
||||
mutable Statistics::Scalar<> acv;
|
||||
mutable Statistics::Formula accesses;
|
||||
|
||||
protected:
|
||||
void fault(Addr pc, ExecContext *xc) const;
|
||||
|
||||
public:
|
||||
AlphaItb(const std::string &name, int size);
|
||||
virtual void regStats();
|
||||
|
||||
Fault translate(MemReqPtr req) const;
|
||||
};
|
||||
|
||||
class AlphaDtb : public AlphaTlb
|
||||
{
|
||||
protected:
|
||||
mutable Statistics::Scalar<> read_hits;
|
||||
mutable Statistics::Scalar<> read_misses;
|
||||
mutable Statistics::Scalar<> read_acv;
|
||||
mutable Statistics::Scalar<> read_accesses;
|
||||
mutable Statistics::Scalar<> write_hits;
|
||||
mutable Statistics::Scalar<> write_misses;
|
||||
mutable Statistics::Scalar<> write_acv;
|
||||
mutable Statistics::Scalar<> write_accesses;
|
||||
Statistics::Formula hits;
|
||||
Statistics::Formula misses;
|
||||
Statistics::Formula acv;
|
||||
Statistics::Formula accesses;
|
||||
|
||||
protected:
|
||||
void fault(Addr pc, uint64_t flags, ExecContext *xc) const;
|
||||
|
||||
public:
|
||||
AlphaDtb(const std::string &name, int size);
|
||||
virtual void regStats();
|
||||
|
||||
Fault translate(MemReqPtr req, bool write) const;
|
||||
};
|
||||
|
||||
#endif // __ALPHA_MEMORY_HH__
|
64
arch/alpha/arguments.cc
Normal file
64
arch/alpha/arguments.cc
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "arguments.hh"
|
||||
#include "exec_context.hh"
|
||||
#include "physical_memory.hh"
|
||||
#include "vtophys.hh"
|
||||
|
||||
AlphaArguments::Data::~Data()
|
||||
{
|
||||
while (!data.empty()) {
|
||||
delete [] data.front();
|
||||
data.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
AlphaArguments::Data::alloc(size_t size)
|
||||
{
|
||||
char *buf = new char[size];
|
||||
data.push_back(buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
AlphaArguments::getArg(bool fp)
|
||||
{
|
||||
if (number < 6) {
|
||||
if (fp)
|
||||
return xc->regs.floatRegFile.q[16 + number];
|
||||
else
|
||||
return xc->regs.intRegFile[16 + number];
|
||||
} else {
|
||||
Addr sp = xc->regs.intRegFile[30];
|
||||
Addr paddr = vtophys(xc, sp + (number-6) * sizeof(uint64_t));
|
||||
return xc->physmem->phys_read_qword(paddr);
|
||||
}
|
||||
}
|
||||
|
143
arch/alpha/arguments.hh
Normal file
143
arch/alpha/arguments.hh
Normal file
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 __ARGUMENTS_HH__
|
||||
#define __ARGUMENTS_HH__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "host.hh"
|
||||
#include "kernel.hh"
|
||||
#include "refcnt.hh"
|
||||
|
||||
class ExecContext;
|
||||
|
||||
class AlphaArguments
|
||||
{
|
||||
protected:
|
||||
ExecContext *xc;
|
||||
int number;
|
||||
uint64_t getArg(bool fp = false);
|
||||
|
||||
protected:
|
||||
class Data : public RefCounted
|
||||
{
|
||||
public:
|
||||
Data(){}
|
||||
~Data();
|
||||
|
||||
private:
|
||||
std::list<char *> data;
|
||||
|
||||
public:
|
||||
char *alloc(size_t size);
|
||||
};
|
||||
|
||||
RefCountingPtr<Data> data;
|
||||
|
||||
public:
|
||||
AlphaArguments(ExecContext *ctx, int n = 0)
|
||||
: xc(ctx), number(n), data(NULL)
|
||||
{ assert(number >= 0); data = new Data;}
|
||||
AlphaArguments(const AlphaArguments &args)
|
||||
: xc(args.xc), number(args.number), data(args.data) {}
|
||||
~AlphaArguments() {}
|
||||
|
||||
ExecContext *getExecContext() const { return xc; }
|
||||
|
||||
const AlphaArguments &operator=(const AlphaArguments &args) {
|
||||
xc = args.xc;
|
||||
number = args.number;
|
||||
data = args.data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
AlphaArguments &operator++() {
|
||||
++number;
|
||||
assert(number >= 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
AlphaArguments operator++(int) {
|
||||
AlphaArguments args = *this;
|
||||
++number;
|
||||
assert(number >= 0);
|
||||
return args;
|
||||
}
|
||||
|
||||
AlphaArguments &operator--() {
|
||||
--number;
|
||||
assert(number >= 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
AlphaArguments operator--(int) {
|
||||
AlphaArguments args = *this;
|
||||
--number;
|
||||
assert(number >= 0);
|
||||
return args;
|
||||
}
|
||||
|
||||
const AlphaArguments &operator+=(int index) {
|
||||
number += index;
|
||||
assert(number >= 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const AlphaArguments &operator-=(int index) {
|
||||
number -= index;
|
||||
assert(number >= 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
AlphaArguments operator[](int index) {
|
||||
return AlphaArguments(xc, index);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
operator T() {
|
||||
assert(sizeof(T) <= sizeof(uint64_t));
|
||||
T data = static_cast<T>(getArg());
|
||||
return data;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
operator T *() {
|
||||
T *buf = (T *)data->alloc(sizeof(T));
|
||||
Kernel::CopyData(xc, buf, getArg(), sizeof(T));
|
||||
return buf;
|
||||
}
|
||||
|
||||
operator char *() {
|
||||
char *buf = data->alloc(2048);
|
||||
Kernel::CopyString(xc, buf, getArg(), 2048);
|
||||
return buf;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __ARGUMENTS_HH__
|
571
arch/alpha/ev5.cc
Normal file
571
arch/alpha/ev5.cc
Normal file
|
@ -0,0 +1,571 @@
|
|||
/* $Id$ */
|
||||
|
||||
#include "alpha_memory.hh"
|
||||
#include "annotation.hh"
|
||||
#ifdef DEBUG
|
||||
#include "debug.hh"
|
||||
#endif
|
||||
#include "exec_context.hh"
|
||||
#include "sim_events.hh"
|
||||
#include "isa_traits.hh"
|
||||
#include "remote_gdb.hh"
|
||||
#include "kgdb.h" // for ALPHA_KENTRY_IF
|
||||
#include "osfpal.hh"
|
||||
|
||||
#ifdef FULL_SYSTEM
|
||||
|
||||
#ifndef SYSTEM_EV5
|
||||
#error This code is only valid for EV5 systems
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
//
|
||||
void
|
||||
AlphaISA::swap_palshadow(RegFile *regs, bool use_shadow)
|
||||
{
|
||||
if (regs->pal_shadow == use_shadow)
|
||||
panic("swap_palshadow: wrong PAL shadow state");
|
||||
|
||||
regs->pal_shadow = use_shadow;
|
||||
|
||||
for (int i = 0; i < NumIntRegs; i++) {
|
||||
if (reg_redir[i]) {
|
||||
IntReg temp = regs->intRegFile[i];
|
||||
regs->intRegFile[i] = regs->palregs[i];
|
||||
regs->palregs[i] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Machine dependent functions
|
||||
//
|
||||
void
|
||||
AlphaISA::init(void *mem, RegFile *regs)
|
||||
{
|
||||
ipr_init(mem, regs);
|
||||
}
|
||||
|
||||
void
|
||||
m5_exit()
|
||||
{
|
||||
static SimExitEvent event("m5_exit instruction encountered");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// alpha exceptions - value equals trap address, update with MD_FAULT_TYPE
|
||||
//
|
||||
Addr
|
||||
AlphaISA::fault_addr[Num_Faults] = {
|
||||
0x0000, /* No_Fault */
|
||||
0x0001, /* Reset_Fault */
|
||||
0x0401, /* Machine_Check_Fault */
|
||||
0x0501, /* Arithmetic_Fault */
|
||||
0x0101, /* Interrupt_Fault */
|
||||
0x0201, /* Ndtb_Miss_Fault */
|
||||
0x0281, /* Pdtb_Miss_Fault */
|
||||
0x0301, /* Alignment_Fault */
|
||||
0x0381, /* Dtb_Fault_Fault */
|
||||
0x0381, /* Dtb_Acv_Fault */
|
||||
0x0181, /* Itb_Miss_Fault */
|
||||
0x0181, /* Itb_Fault_Fault */
|
||||
0x0081, /* Itb_Acv_Fault */
|
||||
0x0481, /* Unimplemented_Opcode_Fault */
|
||||
0x0581, /* Fen_Fault */
|
||||
0x2001, /* Pal_Fault */
|
||||
0x0501, /* Integer_Overflow_Fault: maps to Arithmetic_Fault */
|
||||
};
|
||||
|
||||
const int AlphaISA::reg_redir[AlphaISA::NumIntRegs] = {
|
||||
/* 0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 8 */ 1, 1, 1, 1, 1, 1, 1, 0,
|
||||
/* 16 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 24 */ 0, 1, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
//
|
||||
void
|
||||
AlphaISA::ipr_init(void *mem, RegFile *regs)
|
||||
{
|
||||
uint64_t *ipr = regs->ipr;
|
||||
|
||||
bzero((char *)ipr, NumInternalProcRegs * sizeof(InternalProcReg));
|
||||
ipr[IPR_PAL_BASE] = PAL_BASE;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExecContext::ev5_trap(Fault fault)
|
||||
{
|
||||
assert(!misspeculating());
|
||||
kernelStats.fault(fault);
|
||||
|
||||
if (fault == Arithmetic_Fault)
|
||||
panic("Arithmetic traps are unimplemented!");
|
||||
|
||||
AlphaISA::InternalProcReg *ipr = regs.ipr;
|
||||
|
||||
// exception restart address
|
||||
if (fault != Interrupt_Fault || !PC_PAL(regs.pc))
|
||||
ipr[AlphaISA::IPR_EXC_ADDR] = regs.pc;
|
||||
|
||||
if (fault == Pal_Fault || fault == Arithmetic_Fault /* ||
|
||||
fault == Interrupt_Fault && !PC_PAL(regs.pc) */) {
|
||||
// traps... skip faulting instruction
|
||||
ipr[AlphaISA::IPR_EXC_ADDR] += 4;
|
||||
}
|
||||
|
||||
if (!PC_PAL(regs.pc))
|
||||
AlphaISA::swap_palshadow(®s, true);
|
||||
|
||||
regs.pc = ipr[AlphaISA::IPR_PAL_BASE] + AlphaISA::fault_addr[fault];
|
||||
regs.npc = regs.pc + sizeof(MachInst);
|
||||
|
||||
Annotate::Ev5Trap(this, fault);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AlphaISA::intr_post(RegFile *regs, Fault fault, Addr pc)
|
||||
{
|
||||
InternalProcReg *ipr = regs->ipr;
|
||||
bool use_pc = (fault == No_Fault);
|
||||
|
||||
if (fault == Arithmetic_Fault)
|
||||
panic("arithmetic faults NYI...");
|
||||
|
||||
// compute exception restart address
|
||||
if (use_pc || fault == Pal_Fault || fault == Arithmetic_Fault) {
|
||||
// traps... skip faulting instruction
|
||||
ipr[IPR_EXC_ADDR] = regs->pc + 4;
|
||||
} else {
|
||||
// fault, post fault at excepting instruction
|
||||
ipr[IPR_EXC_ADDR] = regs->pc;
|
||||
}
|
||||
|
||||
// jump to expection address (PAL PC bit set here as well...)
|
||||
if (!use_pc)
|
||||
regs->npc = ipr[IPR_PAL_BASE] + fault_addr[fault];
|
||||
else
|
||||
regs->npc = ipr[IPR_PAL_BASE] + pc;
|
||||
|
||||
// that's it! (orders of magnitude less painful than x86)
|
||||
}
|
||||
|
||||
bool AlphaISA::check_interrupts = false;
|
||||
|
||||
Fault
|
||||
ExecContext::hwrei()
|
||||
{
|
||||
uint64_t *ipr = regs.ipr;
|
||||
|
||||
if (!PC_PAL(regs.pc))
|
||||
return Unimplemented_Opcode_Fault;
|
||||
|
||||
kernelStats.hwrei();
|
||||
|
||||
regs.npc = ipr[AlphaISA::IPR_EXC_ADDR];
|
||||
|
||||
if (!misspeculating()) {
|
||||
if ((ipr[AlphaISA::IPR_EXC_ADDR] & 1) == 0)
|
||||
AlphaISA::swap_palshadow(®s, false);
|
||||
|
||||
AlphaISA::check_interrupts = true;
|
||||
}
|
||||
|
||||
// FIXME: XXX check for interrupts? XXX
|
||||
return No_Fault;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
ExecContext::readIpr(int idx, Fault &fault)
|
||||
{
|
||||
uint64_t *ipr = regs.ipr;
|
||||
uint64_t retval = 0; // return value, default 0
|
||||
|
||||
switch (idx) {
|
||||
case AlphaISA::IPR_PALtemp0:
|
||||
case AlphaISA::IPR_PALtemp1:
|
||||
case AlphaISA::IPR_PALtemp2:
|
||||
case AlphaISA::IPR_PALtemp3:
|
||||
case AlphaISA::IPR_PALtemp4:
|
||||
case AlphaISA::IPR_PALtemp5:
|
||||
case AlphaISA::IPR_PALtemp6:
|
||||
case AlphaISA::IPR_PALtemp7:
|
||||
case AlphaISA::IPR_PALtemp8:
|
||||
case AlphaISA::IPR_PALtemp9:
|
||||
case AlphaISA::IPR_PALtemp10:
|
||||
case AlphaISA::IPR_PALtemp11:
|
||||
case AlphaISA::IPR_PALtemp12:
|
||||
case AlphaISA::IPR_PALtemp13:
|
||||
case AlphaISA::IPR_PALtemp14:
|
||||
case AlphaISA::IPR_PALtemp15:
|
||||
case AlphaISA::IPR_PALtemp16:
|
||||
case AlphaISA::IPR_PALtemp17:
|
||||
case AlphaISA::IPR_PALtemp18:
|
||||
case AlphaISA::IPR_PALtemp19:
|
||||
case AlphaISA::IPR_PALtemp20:
|
||||
case AlphaISA::IPR_PALtemp21:
|
||||
case AlphaISA::IPR_PALtemp22:
|
||||
case AlphaISA::IPR_PALtemp23:
|
||||
case AlphaISA::IPR_PAL_BASE:
|
||||
|
||||
case AlphaISA::IPR_IVPTBR:
|
||||
case AlphaISA::IPR_DC_MODE:
|
||||
case AlphaISA::IPR_MAF_MODE:
|
||||
case AlphaISA::IPR_ISR:
|
||||
case AlphaISA::IPR_EXC_ADDR:
|
||||
case AlphaISA::IPR_IC_PERR_STAT:
|
||||
case AlphaISA::IPR_DC_PERR_STAT:
|
||||
case AlphaISA::IPR_MCSR:
|
||||
case AlphaISA::IPR_ASTRR:
|
||||
case AlphaISA::IPR_ASTER:
|
||||
case AlphaISA::IPR_SIRR:
|
||||
case AlphaISA::IPR_ICSR:
|
||||
case AlphaISA::IPR_ICM:
|
||||
case AlphaISA::IPR_DTB_CM:
|
||||
case AlphaISA::IPR_IPLR:
|
||||
case AlphaISA::IPR_INTID:
|
||||
case AlphaISA::IPR_PMCTR:
|
||||
// no side-effect
|
||||
retval = ipr[idx];
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_VA:
|
||||
// SFX: unlocks interrupt status registers
|
||||
retval = ipr[idx];
|
||||
regs.intrlock = false;
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_VA_FORM:
|
||||
case AlphaISA::IPR_MM_STAT:
|
||||
case AlphaISA::IPR_IFAULT_VA_FORM:
|
||||
case AlphaISA::IPR_EXC_MASK:
|
||||
case AlphaISA::IPR_EXC_SUM:
|
||||
retval = ipr[idx];
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_DTB_PTE:
|
||||
{
|
||||
AlphaISA::PTE &pte = dtb->index();
|
||||
|
||||
retval |= ((u_int64_t)pte.ppn & ULL(0x7ffffff)) << 32;
|
||||
retval |= ((u_int64_t)pte.xre & ULL(0xf)) << 8;
|
||||
retval |= ((u_int64_t)pte.xwe & ULL(0xf)) << 12;
|
||||
retval |= ((u_int64_t)pte.fonr & ULL(0x1)) << 1;
|
||||
retval |= ((u_int64_t)pte.fonw & ULL(0x1))<< 2;
|
||||
retval |= ((u_int64_t)pte.asma & ULL(0x1)) << 4;
|
||||
retval |= ((u_int64_t)pte.asn & ULL(0x7f)) << 57;
|
||||
}
|
||||
break;
|
||||
|
||||
// write only registers
|
||||
case AlphaISA::IPR_HWINT_CLR:
|
||||
case AlphaISA::IPR_SL_XMIT:
|
||||
case AlphaISA::IPR_DC_FLUSH:
|
||||
case AlphaISA::IPR_IC_FLUSH:
|
||||
case AlphaISA::IPR_ALT_MODE:
|
||||
case AlphaISA::IPR_DTB_IA:
|
||||
case AlphaISA::IPR_DTB_IAP:
|
||||
case AlphaISA::IPR_ITB_IA:
|
||||
case AlphaISA::IPR_ITB_IAP:
|
||||
fault = Unimplemented_Opcode_Fault;
|
||||
break;
|
||||
|
||||
default:
|
||||
// invalid IPR
|
||||
fault = Unimplemented_Opcode_Fault;
|
||||
break;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// Cause the simulator to break when changing to the following IPL
|
||||
int break_ipl = -1;
|
||||
#endif
|
||||
|
||||
Fault
|
||||
ExecContext::setIpr(int idx, uint64_t val)
|
||||
{
|
||||
uint64_t *ipr = regs.ipr;
|
||||
|
||||
if (misspeculating())
|
||||
return No_Fault;
|
||||
|
||||
switch (idx) {
|
||||
case AlphaISA::IPR_PALtemp0:
|
||||
case AlphaISA::IPR_PALtemp1:
|
||||
case AlphaISA::IPR_PALtemp2:
|
||||
case AlphaISA::IPR_PALtemp3:
|
||||
case AlphaISA::IPR_PALtemp4:
|
||||
case AlphaISA::IPR_PALtemp5:
|
||||
case AlphaISA::IPR_PALtemp6:
|
||||
case AlphaISA::IPR_PALtemp7:
|
||||
case AlphaISA::IPR_PALtemp8:
|
||||
case AlphaISA::IPR_PALtemp9:
|
||||
case AlphaISA::IPR_PALtemp10:
|
||||
case AlphaISA::IPR_PALtemp11:
|
||||
case AlphaISA::IPR_PALtemp12:
|
||||
case AlphaISA::IPR_PALtemp13:
|
||||
case AlphaISA::IPR_PALtemp14:
|
||||
case AlphaISA::IPR_PALtemp15:
|
||||
case AlphaISA::IPR_PALtemp16:
|
||||
case AlphaISA::IPR_PALtemp17:
|
||||
case AlphaISA::IPR_PALtemp18:
|
||||
case AlphaISA::IPR_PALtemp19:
|
||||
case AlphaISA::IPR_PALtemp20:
|
||||
case AlphaISA::IPR_PALtemp21:
|
||||
case AlphaISA::IPR_PALtemp22:
|
||||
case AlphaISA::IPR_PAL_BASE:
|
||||
case AlphaISA::IPR_IC_PERR_STAT:
|
||||
case AlphaISA::IPR_DC_PERR_STAT:
|
||||
case AlphaISA::IPR_CC_CTL:
|
||||
case AlphaISA::IPR_CC:
|
||||
case AlphaISA::IPR_PMCTR:
|
||||
// write entire quad w/ no side-effect
|
||||
ipr[idx] = val;
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_PALtemp23:
|
||||
// write entire quad w/ no side-effect
|
||||
ipr[idx] = val;
|
||||
kernelStats.context(ipr[idx]);
|
||||
Annotate::Context(this);
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_DTB_PTE:
|
||||
// write entire quad w/ no side-effect, tag is forthcoming
|
||||
ipr[idx] = val;
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_EXC_ADDR:
|
||||
// second least significant bit in PC is always zero
|
||||
ipr[idx] = val & ~2;
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_ASTRR:
|
||||
case AlphaISA::IPR_ASTER:
|
||||
// only write least significant four bits - privilege mask
|
||||
ipr[idx] = val & 0xf;
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_IPLR:
|
||||
#ifdef DEBUG
|
||||
if (break_ipl != -1 && break_ipl == (val & 0x1f))
|
||||
debug_break();
|
||||
#endif
|
||||
|
||||
// only write least significant five bits - interrupt level
|
||||
ipr[idx] = val & 0x1f;
|
||||
kernelStats.swpipl(ipr[idx]);
|
||||
Annotate::IPL(this, val & 0x1f);
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_DTB_CM:
|
||||
Annotate::ChangeMode(this, (val & 0x18) != 0);
|
||||
kernelStats.mode((val & 0x18) != 0);
|
||||
|
||||
case AlphaISA::IPR_ICM:
|
||||
// only write two mode bits - processor mode
|
||||
ipr[idx] = val & 0x18;
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_ALT_MODE:
|
||||
// only write two mode bits - processor mode
|
||||
ipr[idx] = val & 0x18;
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_MCSR:
|
||||
// more here after optimization...
|
||||
ipr[idx] = val;
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_SIRR:
|
||||
// only write software interrupt mask
|
||||
ipr[idx] = val & 0x7fff0;
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_ICSR:
|
||||
ipr[idx] = val & ULL(0xffffff0300);
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_IVPTBR:
|
||||
case AlphaISA::IPR_MVPTBR:
|
||||
ipr[idx] = val & ULL(0xffffffffc0000000);
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_DC_TEST_CTL:
|
||||
ipr[idx] = val & 0x1ffb;
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_DC_MODE:
|
||||
case AlphaISA::IPR_MAF_MODE:
|
||||
ipr[idx] = val & 0x3f;
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_ITB_ASN:
|
||||
ipr[idx] = val & 0x7f0;
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_DTB_ASN:
|
||||
ipr[idx] = val & ULL(0xfe00000000000000);
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_EXC_SUM:
|
||||
case AlphaISA::IPR_EXC_MASK:
|
||||
// any write to this register clears it
|
||||
ipr[idx] = 0;
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_INTID:
|
||||
case AlphaISA::IPR_SL_RCV:
|
||||
case AlphaISA::IPR_MM_STAT:
|
||||
case AlphaISA::IPR_ITB_PTE_TEMP:
|
||||
case AlphaISA::IPR_DTB_PTE_TEMP:
|
||||
// read-only registers
|
||||
return Unimplemented_Opcode_Fault;
|
||||
|
||||
case AlphaISA::IPR_HWINT_CLR:
|
||||
case AlphaISA::IPR_SL_XMIT:
|
||||
case AlphaISA::IPR_DC_FLUSH:
|
||||
case AlphaISA::IPR_IC_FLUSH:
|
||||
// the following are write only
|
||||
ipr[idx] = val;
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_DTB_IA:
|
||||
// really a control write
|
||||
ipr[idx] = 0;
|
||||
|
||||
dtb->flushAll();
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_DTB_IAP:
|
||||
// really a control write
|
||||
ipr[idx] = 0;
|
||||
|
||||
dtb->flushProcesses();
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_DTB_IS:
|
||||
// really a control write
|
||||
ipr[idx] = val;
|
||||
|
||||
dtb->flushAddr(val, DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_DTB_TAG: {
|
||||
struct AlphaISA::PTE pte;
|
||||
|
||||
// FIXME: granularity hints NYI...
|
||||
if (DTB_PTE_GH(ipr[AlphaISA::IPR_DTB_PTE]) != 0)
|
||||
panic("PTE GH field != 0");
|
||||
|
||||
// write entire quad
|
||||
ipr[idx] = val;
|
||||
|
||||
// construct PTE for new entry
|
||||
pte.ppn = DTB_PTE_PPN(ipr[AlphaISA::IPR_DTB_PTE]);
|
||||
pte.xre = DTB_PTE_XRE(ipr[AlphaISA::IPR_DTB_PTE]);
|
||||
pte.xwe = DTB_PTE_XWE(ipr[AlphaISA::IPR_DTB_PTE]);
|
||||
pte.fonr = DTB_PTE_FONR(ipr[AlphaISA::IPR_DTB_PTE]);
|
||||
pte.fonw = DTB_PTE_FONW(ipr[AlphaISA::IPR_DTB_PTE]);
|
||||
pte.asma = DTB_PTE_ASMA(ipr[AlphaISA::IPR_DTB_PTE]);
|
||||
pte.asn = DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]);
|
||||
|
||||
// insert new TAG/PTE value into data TLB
|
||||
dtb->insert(val, pte);
|
||||
}
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_ITB_PTE: {
|
||||
struct AlphaISA::PTE pte;
|
||||
|
||||
// FIXME: granularity hints NYI...
|
||||
if (ITB_PTE_GH(val) != 0)
|
||||
panic("PTE GH field != 0");
|
||||
|
||||
// write entire quad
|
||||
ipr[idx] = val;
|
||||
|
||||
// construct PTE for new entry
|
||||
pte.ppn = ITB_PTE_PPN(val);
|
||||
pte.xre = ITB_PTE_XRE(val);
|
||||
pte.xwe = 0;
|
||||
pte.fonr = ITB_PTE_FONR(val);
|
||||
pte.fonw = ITB_PTE_FONW(val);
|
||||
pte.asma = ITB_PTE_ASMA(val);
|
||||
pte.asn = ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]);
|
||||
|
||||
// insert new TAG/PTE value into data TLB
|
||||
itb->insert(ipr[AlphaISA::IPR_ITB_TAG], pte);
|
||||
}
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_ITB_IA:
|
||||
// really a control write
|
||||
ipr[idx] = 0;
|
||||
|
||||
itb->flushAll();
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_ITB_IAP:
|
||||
// really a control write
|
||||
ipr[idx] = 0;
|
||||
|
||||
itb->flushProcesses();
|
||||
break;
|
||||
|
||||
case AlphaISA::IPR_ITB_IS:
|
||||
// really a control write
|
||||
ipr[idx] = val;
|
||||
|
||||
itb->flushAddr(val, ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]));
|
||||
break;
|
||||
|
||||
default:
|
||||
// invalid IPR
|
||||
return Unimplemented_Opcode_Fault;
|
||||
}
|
||||
|
||||
// no error...
|
||||
return No_Fault;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for special simulator handling of specific PAL calls.
|
||||
* If return value is false, actual PAL call will be suppressed.
|
||||
*/
|
||||
bool
|
||||
ExecContext::simPalCheck(int palFunc)
|
||||
{
|
||||
kernelStats.callpal(palFunc);
|
||||
|
||||
switch (palFunc) {
|
||||
case PAL::halt:
|
||||
if (!misspeculating()) {
|
||||
setStatus(Halted);
|
||||
if (--System::numSystemsRunning == 0)
|
||||
new SimExitEvent("all cpus halted");
|
||||
}
|
||||
break;
|
||||
|
||||
case PAL::bpt:
|
||||
case PAL::bugchk:
|
||||
if (system->remoteGDB->trap(ALPHA_KENTRY_IF))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // FULL_SYSTEM
|
104
arch/alpha/ev5.hh
Normal file
104
arch/alpha/ev5.hh
Normal file
|
@ -0,0 +1,104 @@
|
|||
/* $Id$ */
|
||||
|
||||
#ifndef __EV5_H__
|
||||
#define __EV5_H__
|
||||
|
||||
#ifndef SYSTEM_EV5
|
||||
#error This code is only valid for EV5 systems
|
||||
#endif
|
||||
|
||||
#include "isa_traits.hh"
|
||||
|
||||
void m5_exit();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
#define MODE2MASK(X) (1 << (X))
|
||||
|
||||
// Alpha IPR register accessors
|
||||
#define PC_PAL(X) ((X) & 0x1)
|
||||
#define MCSR_SP(X) (((X) >> 1) & 0x3)
|
||||
|
||||
#define ICSR_SDE(X) (((X) >> 30) & 0x1)
|
||||
#define ICSR_SPE(X) (((X) >> 28) & 0x3)
|
||||
#define ICSR_FPE(X) (((X) >> 26) & 0x1)
|
||||
|
||||
#define ALT_MODE_AM(X) (((X) >> 3) & 0x3)
|
||||
|
||||
#define DTB_CM_CM(X) (((X) >> 3) & 0x3)
|
||||
#define DTB_ASN_ASN(X) (((X) >> 57) & 0x7f)
|
||||
#define DTB_PTE_PPN(X) (((X) >> 32) & 0x07ffffff)
|
||||
#define DTB_PTE_XRE(X) (((X) >> 8) & 0xf)
|
||||
#define DTB_PTE_XWE(X) (((X) >> 12) & 0xf)
|
||||
#define DTB_PTE_FONR(X) (((X) >> 1) & 0x1)
|
||||
#define DTB_PTE_FONW(X) (((X) >> 2) & 0x1)
|
||||
#define DTB_PTE_GH(X) (((X) >> 5) & 0x3)
|
||||
#define DTB_PTE_ASMA(X) (((X) >> 4) & 0x1)
|
||||
|
||||
#define ICM_CM(X) (((X) >> 3) & 0x3)
|
||||
#define ITB_ASN_ASN(X) (((X) >> 4) & 0x7f)
|
||||
#define ITB_PTE_PPN(X) (((X) >> 32) & 0x07ffffff)
|
||||
#define ITB_PTE_XRE(X) (((X) >> 8) & 0xf)
|
||||
#define ITB_PTE_FONR(X) (((X) >> 1) & 0x1)
|
||||
#define ITB_PTE_FONW(X) (((X) >> 2) & 0x1)
|
||||
#define ITB_PTE_GH(X) (((X) >> 5) & 0x3)
|
||||
#define ITB_PTE_ASMA(X) (((X) >> 4) & 0x1)
|
||||
|
||||
#define VA_UNIMPL_MASK ULL(0xfffff80000000000)
|
||||
#define VA_IMPL_MASK ULL(0x000007ffffffffff)
|
||||
#define VA_IMPL(X) ((X) & VA_IMPL_MASK)
|
||||
#define VA_VPN(X) (VA_IMPL(X) >> 13)
|
||||
#define VA_SPACE(X) (((X) >> 41) & 0x3)
|
||||
#define VA_POFS(X) ((X) & 0x1fff)
|
||||
|
||||
#define PA_IMPL_MASK ULL(0xffffffffff)
|
||||
#define PA_UNCACHED_BIT ULL(0x8000000000)
|
||||
#define PA_IPR_SPACE(X) ((X) >= ULL(0xFFFFF00000))
|
||||
|
||||
#define PA_PFN2PA(X) ((X) << 13)
|
||||
|
||||
|
||||
#define MM_STAT_BAD_VA_MASK 0x0020
|
||||
#define MM_STAT_DTB_MISS_MASK 0x0010
|
||||
#define MM_STAT_FONW_MASK 0x0008
|
||||
#define MM_STAT_FONR_MASK 0x0004
|
||||
#define MM_STAT_ACV_MASK 0x0002
|
||||
#define MM_STAT_WR_MASK 0x0001
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
// VPTE size for HW_LD/HW_ST
|
||||
#define HW_VPTE ((inst >> 11) & 0x1)
|
||||
|
||||
// QWORD size for HW_LD/HW_ST
|
||||
#define HW_QWORD ((inst >> 12) & 0x1)
|
||||
|
||||
// ALT mode for HW_LD/HW_ST
|
||||
#define HW_ALT (((inst >> 14) & 0x1) ? ALTMODE : 0)
|
||||
|
||||
// LOCK/COND mode for HW_LD/HW_ST
|
||||
#define HW_LOCK (((inst >> 10) & 0x1) ? LOCKED : 0)
|
||||
#define HW_COND (((inst >> 10) & 0x1) ? LOCKED : 0)
|
||||
|
||||
// PHY size for HW_LD/HW_ST
|
||||
#define HW_PHY (((inst >> 15) & 0x1) ? PHYSICAL : 0)
|
||||
|
||||
// OFFSET for HW_LD/HW_ST
|
||||
#define HW_OFS (inst & 0x3ff)
|
||||
|
||||
|
||||
#define PAL_BASE 0x4000
|
||||
|
||||
#endif //__EV5_H__
|
1736
arch/alpha/fake_syscall.cc
Normal file
1736
arch/alpha/fake_syscall.cc
Normal file
File diff suppressed because it is too large
Load diff
61
arch/alpha/faults.cc
Normal file
61
arch/alpha/faults.cc
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "faults.hh"
|
||||
|
||||
namespace {
|
||||
const char *
|
||||
fault_name[Num_Faults] = {
|
||||
"none",
|
||||
"reset",
|
||||
"mchk",
|
||||
"arith",
|
||||
"interrupt",
|
||||
"dtb_miss_single",
|
||||
"dtb_miss_double",
|
||||
"unalign",
|
||||
"dfault",
|
||||
"dfault",
|
||||
"itbmiss",
|
||||
"itbmiss",
|
||||
"iaccvio",
|
||||
"opdec",
|
||||
"fen",
|
||||
"pal",
|
||||
};
|
||||
}
|
||||
|
||||
const char *
|
||||
FaultName(int index)
|
||||
{
|
||||
if (index < 0 || index >= Num_Faults)
|
||||
return 0;
|
||||
|
||||
return fault_name[index];
|
||||
}
|
||||
|
56
arch/alpha/faults.hh
Normal file
56
arch/alpha/faults.hh
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 __FAULTS_HH__
|
||||
#define __FAULTS_HH__
|
||||
|
||||
enum Fault {
|
||||
No_Fault,
|
||||
Reset_Fault, // processor reset
|
||||
Machine_Check_Fault, // machine check (also internal S/W fault)
|
||||
Arithmetic_Fault, // FP exception
|
||||
Interrupt_Fault, // external interrupt
|
||||
Ndtb_Miss_Fault, // DTB miss
|
||||
Pdtb_Miss_Fault, // nested DTB miss
|
||||
Alignment_Fault, // unaligned access
|
||||
Dtb_Fault_Fault, // DTB page fault
|
||||
Dtb_Acv_Fault, // DTB access violation
|
||||
Itb_Miss_Fault, // ITB miss
|
||||
Itb_Fault_Fault, // ITB page fault
|
||||
Itb_Acv_Fault, // ITB access violation
|
||||
Unimplemented_Opcode_Fault, // invalid/unimplemented instruction
|
||||
Fen_Fault, // FP not-enabled fault
|
||||
Pal_Fault, // call_pal S/W interrupt
|
||||
Integer_Overflow_Fault,
|
||||
Num_Faults // number of faults
|
||||
};
|
||||
|
||||
const char *
|
||||
FaultName(int index);
|
||||
|
||||
#endif // __FAULTS_HH__
|
2427
arch/alpha/isa_desc
Normal file
2427
arch/alpha/isa_desc
Normal file
File diff suppressed because it is too large
Load diff
282
arch/alpha/isa_traits.hh
Normal file
282
arch/alpha/isa_traits.hh
Normal file
|
@ -0,0 +1,282 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 __ISA_TRAITS_HH__
|
||||
#define __ISA_TRAITS_HH__
|
||||
|
||||
#include "host.hh"
|
||||
#include "faults.hh"
|
||||
#include "misc.hh"
|
||||
|
||||
class CPU;
|
||||
class IniFile;
|
||||
|
||||
#define TARGET_ALPHA
|
||||
|
||||
template <class ISA> class StaticInst;
|
||||
template <class ISA> class StaticInstPtr;
|
||||
|
||||
class AlphaISA
|
||||
{
|
||||
public:
|
||||
|
||||
typedef uint32_t MachInst;
|
||||
typedef uint64_t Addr;
|
||||
typedef uint8_t RegIndex;
|
||||
|
||||
enum {
|
||||
MemoryEnd = 0xffffffffffffffffULL,
|
||||
|
||||
NumIntRegs = 32,
|
||||
NumFloatRegs = 32,
|
||||
NumMiscRegs = 32,
|
||||
|
||||
MaxRegsOfAnyType = 32,
|
||||
// Static instruction parameters
|
||||
MaxInstSrcRegs = 3,
|
||||
MaxInstDestRegs = 2,
|
||||
|
||||
// semantically meaningful register indices
|
||||
ZeroReg = 31, // architecturally meaningful
|
||||
// the rest of these depend on the ABI
|
||||
StackPointerReg = 30,
|
||||
GlobalPointerReg = 29,
|
||||
ReturnAddressReg = 26,
|
||||
ReturnValueReg = 0,
|
||||
ArgumentReg0 = 16,
|
||||
ArgumentReg1 = 17,
|
||||
ArgumentReg2 = 18,
|
||||
ArgumentReg3 = 19,
|
||||
ArgumentReg4 = 20,
|
||||
ArgumentReg5 = 21,
|
||||
|
||||
LogVMPageSize = 13, // 8K bytes
|
||||
VMPageSize = (1 << LogVMPageSize),
|
||||
|
||||
BranchPredAddrShiftAmt = 2, // instructions are 4-byte aligned
|
||||
|
||||
WordBytes = 4,
|
||||
HalfwordBytes = 2,
|
||||
ByteBytes = 1,
|
||||
DepNA = 0,
|
||||
};
|
||||
|
||||
// These enumerate all the registers for dependence tracking.
|
||||
enum DependenceTags {
|
||||
// 0..31 are the integer regs 0..31
|
||||
// 32..63 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag)
|
||||
FP_Base_DepTag = 32,
|
||||
Ctrl_Base_DepTag = 64,
|
||||
Fpcr_DepTag = 64, // floating point control register
|
||||
Uniq_DepTag = 65,
|
||||
IPR_Base_DepTag = 66
|
||||
};
|
||||
|
||||
typedef uint64_t IntReg;
|
||||
typedef IntReg IntRegFile[NumIntRegs];
|
||||
|
||||
// floating point register file entry type
|
||||
typedef union {
|
||||
uint64_t q;
|
||||
double d;
|
||||
} FloatReg;
|
||||
|
||||
typedef union {
|
||||
uint64_t q[NumFloatRegs]; // integer qword view
|
||||
double d[NumFloatRegs]; // double-precision floating point view
|
||||
} FloatRegFile;
|
||||
|
||||
// control register file contents
|
||||
typedef uint64_t MiscReg;
|
||||
typedef struct {
|
||||
uint64_t fpcr; // floating point condition codes
|
||||
uint64_t uniq; // process-unique register
|
||||
bool lock_flag; // lock flag for LL/SC
|
||||
Addr lock_addr; // lock address for LL/SC
|
||||
} MiscRegFile;
|
||||
|
||||
#ifdef FULL_SYSTEM
|
||||
|
||||
typedef uint64_t InternalProcReg;
|
||||
|
||||
#include "isa_fullsys_traits.hh"
|
||||
|
||||
#else
|
||||
enum {
|
||||
NumInternalProcRegs = 0
|
||||
};
|
||||
#endif
|
||||
|
||||
enum {
|
||||
TotalNumRegs =
|
||||
NumIntRegs + NumFloatRegs + NumMiscRegs + NumInternalProcRegs
|
||||
};
|
||||
|
||||
typedef union {
|
||||
IntReg intreg;
|
||||
FloatReg fpreg;
|
||||
MiscReg ctrlreg;
|
||||
} AnyReg;
|
||||
|
||||
struct RegFile {
|
||||
IntRegFile intRegFile; // (signed) integer register file
|
||||
FloatRegFile floatRegFile; // floating point register file
|
||||
MiscRegFile miscRegs; // control register file
|
||||
Addr pc; // program counter
|
||||
Addr npc; // next-cycle program counter
|
||||
#ifdef FULL_SYSTEM
|
||||
IntReg palregs[NumIntRegs]; // PAL shadow registers
|
||||
InternalProcReg ipr[NumInternalProcRegs]; // internal processor regs
|
||||
int intrlock; // interrupt register lock flag
|
||||
int intrflag; // interrupt flag
|
||||
bool pal_shadow; // using pal_shadow registers
|
||||
#endif // FULL_SYSTEM
|
||||
// Are these architectural, or just for convenience?
|
||||
uint8_t opcode, ra; // current instruction details (for intr's)
|
||||
};
|
||||
|
||||
static StaticInstPtr<AlphaISA> decodeInst(MachInst);
|
||||
|
||||
enum annotes {
|
||||
ANNOTE_NONE = 0,
|
||||
// An impossible number for instruction annotations
|
||||
ITOUCH_ANNOTE = 0xffffffff,
|
||||
};
|
||||
|
||||
#if 0
|
||||
static inline Addr
|
||||
extractInstructionPrefetchTarget(const MachInst &IR, Addr PC) {
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline bool isCallerSaveIntegerRegister(unsigned int reg) {
|
||||
panic("register classification not implemented");
|
||||
return (reg >= 1 && reg <= 8 || reg >= 22 && reg <= 25 || reg == 27);
|
||||
}
|
||||
|
||||
static inline bool isCalleeSaveIntegerRegister(unsigned int reg) {
|
||||
panic("register classification not implemented");
|
||||
return (reg >= 9 && reg <= 15);
|
||||
}
|
||||
|
||||
static inline bool isCallerSaveFloatRegister(unsigned int reg) {
|
||||
panic("register classification not implemented");
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool isCalleeSaveFloatRegister(unsigned int reg) {
|
||||
panic("register classification not implemented");
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline Addr alignAddress(const Addr &addr,
|
||||
unsigned int nbytes) {
|
||||
return (addr & ~(nbytes - 1));
|
||||
}
|
||||
|
||||
// Instruction address compression hooks
|
||||
static inline Addr realPCToFetchPC(const Addr &addr) {
|
||||
return addr;
|
||||
}
|
||||
|
||||
static inline Addr fetchPCToRealPC(const Addr &addr) {
|
||||
return addr;
|
||||
}
|
||||
|
||||
// the size of "fetched" instructions (not necessarily the size
|
||||
// of real instructions for PISA)
|
||||
static inline size_t fetchInstSize() {
|
||||
return sizeof(MachInst);
|
||||
}
|
||||
|
||||
static inline MachInst makeRegisterCopy(int dest, int src) {
|
||||
panic("makeRegisterCopy not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Machine operations
|
||||
|
||||
static void saveMachineReg(AnyReg &savereg, const RegFile ®_file,
|
||||
int regnum);
|
||||
|
||||
static void restoreMachineReg(RegFile ®s, const AnyReg ®,
|
||||
int regnum);
|
||||
|
||||
#if 0
|
||||
static void serializeSpecialRegs(const Serializeable::Proxy &proxy,
|
||||
const RegFile ®s);
|
||||
|
||||
static void unserializeSpecialRegs(IniFile &db,
|
||||
const std::string &category,
|
||||
ConfigNode *node,
|
||||
RegFile ®s);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
typedef AlphaISA TheISA;
|
||||
|
||||
typedef TheISA::MachInst MachInst;
|
||||
typedef TheISA::Addr Addr;
|
||||
typedef TheISA::RegIndex RegIndex;
|
||||
typedef TheISA::IntReg IntReg;
|
||||
typedef TheISA::IntRegFile IntRegFile;
|
||||
typedef TheISA::FloatReg FloatReg;
|
||||
typedef TheISA::FloatRegFile FloatRegFile;
|
||||
typedef TheISA::MiscReg MiscReg;
|
||||
typedef TheISA::MiscRegFile MiscRegFile;
|
||||
typedef TheISA::AnyReg AnyReg;
|
||||
typedef TheISA::RegFile RegFile;
|
||||
|
||||
const int NumIntRegs = TheISA::NumIntRegs;
|
||||
const int NumFloatRegs = TheISA::NumFloatRegs;
|
||||
const int NumMiscRegs = TheISA::NumMiscRegs;
|
||||
const int TotalNumRegs = TheISA::TotalNumRegs;
|
||||
const int VMPageSize = TheISA::VMPageSize;
|
||||
const int LogVMPageSize = TheISA::LogVMPageSize;
|
||||
const int ZeroReg = TheISA::ZeroReg;
|
||||
const int StackPointerReg = TheISA::StackPointerReg;
|
||||
const int GlobalPointerReg = TheISA::GlobalPointerReg;
|
||||
const int ReturnAddressReg = TheISA::ReturnAddressReg;
|
||||
const int ReturnValueReg = TheISA::ReturnValueReg;
|
||||
const int ArgumentReg0 = TheISA::ArgumentReg0;
|
||||
const int ArgumentReg1 = TheISA::ArgumentReg1;
|
||||
const int BranchPredAddrShiftAmt = TheISA::BranchPredAddrShiftAmt;
|
||||
|
||||
#ifdef FULL_SYSTEM
|
||||
typedef TheISA::InternalProcReg InternalProcReg;
|
||||
const int NumInternalProcRegs = TheISA::NumInternalProcRegs;
|
||||
const int NumInterruptLevels = TheISA::NumInterruptLevels;
|
||||
|
||||
// more stuff that should be imported here, but I'm too tired to do it
|
||||
// right now...
|
||||
#include "ev5.hh"
|
||||
#endif
|
||||
|
||||
#endif // __ALPHA_ISA_H__
|
304
arch/alpha/osfpal.cc
Normal file
304
arch/alpha/osfpal.cc
Normal file
|
@ -0,0 +1,304 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "osfpal.hh"
|
||||
|
||||
namespace {
|
||||
const char *strings[PAL::NumCodes] = {
|
||||
// Priviledged PAL instructions
|
||||
"halt", // 0x00
|
||||
"cflush", // 0x01
|
||||
"draina", // 0x02
|
||||
0, // 0x03
|
||||
0, // 0x04
|
||||
0, // 0x05
|
||||
0, // 0x06
|
||||
0, // 0x07
|
||||
0, // 0x08
|
||||
"cserve", // 0x09
|
||||
"swppal", // 0x0a
|
||||
0, // 0x0b
|
||||
0, // 0x0c
|
||||
"wripir", // 0x0d
|
||||
0, // 0x0e
|
||||
0, // 0x0f
|
||||
"rdmces", // 0x10
|
||||
"wrmces", // 0x11
|
||||
0, // 0x12
|
||||
0, // 0x13
|
||||
0, // 0x14
|
||||
0, // 0x15
|
||||
0, // 0x16
|
||||
0, // 0x17
|
||||
0, // 0x18
|
||||
0, // 0x19
|
||||
0, // 0x1a
|
||||
0, // 0x1b
|
||||
0, // 0x1c
|
||||
0, // 0x1d
|
||||
0, // 0x1e
|
||||
0, // 0x1f
|
||||
0, // 0x20
|
||||
0, // 0x21
|
||||
0, // 0x22
|
||||
0, // 0x23
|
||||
0, // 0x24
|
||||
0, // 0x25
|
||||
0, // 0x26
|
||||
0, // 0x27
|
||||
0, // 0x28
|
||||
0, // 0x29
|
||||
0, // 0x2a
|
||||
"wrfen", // 0x2b
|
||||
0, // 0x2c
|
||||
"wrvptptr", // 0x2d
|
||||
0, // 0x2e
|
||||
0, // 0x2f
|
||||
"swpctx", // 0x30
|
||||
"wrval", // 0x31
|
||||
"rdval", // 0x32
|
||||
"tbi", // 0x33
|
||||
"wrent", // 0x34
|
||||
"swpipl", // 0x35
|
||||
"rdps", // 0x36
|
||||
"wrkgp", // 0x37
|
||||
"wrusp", // 0x38
|
||||
"wrperfmon", // 0x39
|
||||
"rdusp", // 0x3a
|
||||
0, // 0x3b
|
||||
"whami", // 0x3c
|
||||
"retsys", // 0x3d
|
||||
"wtint", // 0x3e
|
||||
"rti", // 0x3f
|
||||
0, // 0x40
|
||||
0, // 0x41
|
||||
0, // 0x42
|
||||
0, // 0x43
|
||||
0, // 0x44
|
||||
0, // 0x45
|
||||
0, // 0x46
|
||||
0, // 0x47
|
||||
0, // 0x48
|
||||
0, // 0x49
|
||||
0, // 0x4a
|
||||
0, // 0x4b
|
||||
0, // 0x4c
|
||||
0, // 0x4d
|
||||
0, // 0x4e
|
||||
0, // 0x4f
|
||||
0, // 0x50
|
||||
0, // 0x51
|
||||
0, // 0x52
|
||||
0, // 0x53
|
||||
0, // 0x54
|
||||
0, // 0x55
|
||||
0, // 0x56
|
||||
0, // 0x57
|
||||
0, // 0x58
|
||||
0, // 0x59
|
||||
0, // 0x5a
|
||||
0, // 0x5b
|
||||
0, // 0x5c
|
||||
0, // 0x5d
|
||||
0, // 0x5e
|
||||
0, // 0x5f
|
||||
0, // 0x60
|
||||
0, // 0x61
|
||||
0, // 0x62
|
||||
0, // 0x63
|
||||
0, // 0x64
|
||||
0, // 0x65
|
||||
0, // 0x66
|
||||
0, // 0x67
|
||||
0, // 0x68
|
||||
0, // 0x69
|
||||
0, // 0x6a
|
||||
0, // 0x6b
|
||||
0, // 0x6c
|
||||
0, // 0x6d
|
||||
0, // 0x6e
|
||||
0, // 0x6f
|
||||
0, // 0x70
|
||||
0, // 0x71
|
||||
0, // 0x72
|
||||
0, // 0x73
|
||||
0, // 0x74
|
||||
0, // 0x75
|
||||
0, // 0x76
|
||||
0, // 0x77
|
||||
0, // 0x78
|
||||
0, // 0x79
|
||||
0, // 0x7a
|
||||
0, // 0x7b
|
||||
0, // 0x7c
|
||||
0, // 0x7d
|
||||
0, // 0x7e
|
||||
0, // 0x7f
|
||||
|
||||
// Unpriviledged PAL instructions
|
||||
"bpt", // 0x80
|
||||
"bugchk", // 0x81
|
||||
0, // 0x82
|
||||
"callsys", // 0x83
|
||||
0, // 0x84
|
||||
0, // 0x85
|
||||
"imb", // 0x86
|
||||
0, // 0x87
|
||||
0, // 0x88
|
||||
0, // 0x89
|
||||
0, // 0x8a
|
||||
0, // 0x8b
|
||||
0, // 0x8c
|
||||
0, // 0x8d
|
||||
0, // 0x8e
|
||||
0, // 0x8f
|
||||
0, // 0x90
|
||||
0, // 0x91
|
||||
"urti", // 0x92
|
||||
0, // 0x93
|
||||
0, // 0x94
|
||||
0, // 0x95
|
||||
0, // 0x96
|
||||
0, // 0x97
|
||||
0, // 0x98
|
||||
0, // 0x99
|
||||
0, // 0x9a
|
||||
0, // 0x9b
|
||||
0, // 0x9c
|
||||
0, // 0x9d
|
||||
"rdunique", // 0x9e
|
||||
"wrunique", // 0x9f
|
||||
0, // 0xa0
|
||||
0, // 0xa1
|
||||
0, // 0xa2
|
||||
0, // 0xa3
|
||||
0, // 0xa4
|
||||
0, // 0xa5
|
||||
0, // 0xa6
|
||||
0, // 0xa7
|
||||
0, // 0xa8
|
||||
0, // 0xa9
|
||||
"gentrap", // 0xaa
|
||||
0, // 0xab
|
||||
0, // 0xac
|
||||
0, // 0xad
|
||||
"clrfen", // 0xae
|
||||
0, // 0xaf
|
||||
0, // 0xb0
|
||||
0, // 0xb1
|
||||
0, // 0xb2
|
||||
0, // 0xb3
|
||||
0, // 0xb4
|
||||
0, // 0xb5
|
||||
0, // 0xb6
|
||||
0, // 0xb7
|
||||
0, // 0xb8
|
||||
0, // 0xb9
|
||||
0, // 0xba
|
||||
0, // 0xbb
|
||||
0, // 0xbc
|
||||
0, // 0xbd
|
||||
"nphalt", // 0xbe
|
||||
#if 0
|
||||
0, // 0xbf
|
||||
0, // 0xc0
|
||||
0, // 0xc1
|
||||
0, // 0xc2
|
||||
0, // 0xc3
|
||||
0, // 0xc4
|
||||
0, // 0xc5
|
||||
0, // 0xc6
|
||||
0, // 0xc7
|
||||
0, // 0xc8
|
||||
0, // 0xc9
|
||||
0, // 0xca
|
||||
0, // 0xcb
|
||||
0, // 0xcc
|
||||
0, // 0xcd
|
||||
0, // 0xce
|
||||
0, // 0xcf
|
||||
0, // 0xd0
|
||||
0, // 0xd1
|
||||
0, // 0xd2
|
||||
0, // 0xd3
|
||||
0, // 0xd4
|
||||
0, // 0xd5
|
||||
0, // 0xd6
|
||||
0, // 0xd7
|
||||
0, // 0xd8
|
||||
0, // 0xd9
|
||||
0, // 0xda
|
||||
0, // 0xdb
|
||||
0, // 0xdc
|
||||
0, // 0xdd
|
||||
0, // 0xde
|
||||
0, // 0xdf
|
||||
0, // 0xe0
|
||||
0, // 0xe1
|
||||
0, // 0xe2
|
||||
0, // 0xe3
|
||||
0, // 0xe4
|
||||
0, // 0xe5
|
||||
0, // 0xe6
|
||||
0, // 0xe7
|
||||
0, // 0xe8
|
||||
0, // 0xe9
|
||||
0, // 0xea
|
||||
0, // 0xeb
|
||||
0, // 0xec
|
||||
0, // 0xed
|
||||
0, // 0xee
|
||||
0, // 0xef
|
||||
0, // 0xf0
|
||||
0, // 0xf1
|
||||
0, // 0xf2
|
||||
0, // 0xf3
|
||||
0, // 0xf4
|
||||
0, // 0xf5
|
||||
0, // 0xf6
|
||||
0, // 0xf7
|
||||
0, // 0xf8
|
||||
0, // 0xf9
|
||||
0, // 0xfa
|
||||
0, // 0xfb
|
||||
0, // 0xfc
|
||||
0, // 0xfd
|
||||
0, // 0xfe
|
||||
0 // 0xff
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
const char *
|
||||
PAL::name(int index)
|
||||
{
|
||||
if (index > NumCodes || index < 0)
|
||||
return 0;
|
||||
|
||||
return strings[index];
|
||||
}
|
79
arch/alpha/osfpal.hh
Normal file
79
arch/alpha/osfpal.hh
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 __OSFPAL_HH__
|
||||
#define __OSFPAL_HH__
|
||||
|
||||
struct PAL
|
||||
{
|
||||
enum {
|
||||
// Privileged PAL functions
|
||||
halt = 0x00,
|
||||
cflush = 0x01,
|
||||
draina = 0x02,
|
||||
cserve = 0x09,
|
||||
swppal = 0x0a,
|
||||
wripir = 0x0d,
|
||||
rdmces = 0x10,
|
||||
wrmces = 0x11,
|
||||
wrfen = 0x2b,
|
||||
wrvptptr = 0x2d,
|
||||
swpctx = 0x30,
|
||||
wrval = 0x31,
|
||||
rdval = 0x32,
|
||||
tbi = 0x33,
|
||||
wrent = 0x34,
|
||||
swpipl = 0x35,
|
||||
rdps = 0x36,
|
||||
wrkgp = 0x37,
|
||||
wrusp = 0x38,
|
||||
wrperfmon = 0x39,
|
||||
rdusp = 0x3a,
|
||||
whami = 0x3c,
|
||||
retsys = 0x3d,
|
||||
wtint = 0x3e,
|
||||
rti = 0x3f,
|
||||
|
||||
// unprivileged pal functions
|
||||
bpt = 0x80,
|
||||
bugchk = 0x81,
|
||||
callsys = 0x83,
|
||||
imb = 0x86,
|
||||
urti = 0x92,
|
||||
rdunique = 0x9e,
|
||||
wrunique = 0x9f,
|
||||
gentrap = 0xaa,
|
||||
clrfen = 0xae,
|
||||
nphalt = 0xbe,
|
||||
NumCodes
|
||||
};
|
||||
|
||||
static const char *name(int index);
|
||||
};
|
||||
|
||||
#endif // __OSFPAL_HH__
|
123
arch/alpha/vtophys.cc
Normal file
123
arch/alpha/vtophys.cc
Normal file
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "pmap.h"
|
||||
|
||||
#include "exec_context.hh"
|
||||
#include "physical_memory.hh"
|
||||
#include "trace.hh"
|
||||
#include "vtophys.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
inline Addr
|
||||
level3_index(Addr vaddr)
|
||||
{ return (vaddr >> ALPHA_PGSHIFT) & PTEMASK; }
|
||||
|
||||
inline Addr
|
||||
level2_index(Addr vaddr)
|
||||
{ return (vaddr >> (ALPHA_PGSHIFT + NPTEPG_SHIFT)) & PTEMASK; }
|
||||
|
||||
inline Addr
|
||||
level1_index(Addr vaddr)
|
||||
{ return (vaddr >> (ALPHA_PGSHIFT + 2 * NPTEPG_SHIFT)) & PTEMASK; }
|
||||
|
||||
Addr
|
||||
kernel_pte_lookup(PhysicalMemory *pmem, Addr ptbr, Addr vaddr)
|
||||
{
|
||||
uint64_t level1_map = ptbr;
|
||||
Addr level1_pte = level1_map + (level1_index(vaddr) << PTESHIFT);
|
||||
|
||||
uint64_t level1 = pmem->phys_read_qword(level1_pte);
|
||||
if (!entry_valid(level1)) {
|
||||
DPRINTF(VtoPhys, "level 1 PTE not valid, va = %#\n", vaddr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t level2_map = PMAP_PTE_PA(level1);
|
||||
Addr level2_pte = level2_map + (level2_index(vaddr) << PTESHIFT);
|
||||
uint64_t level2 = pmem->phys_read_qword(level2_pte);
|
||||
if (!entry_valid(level2)) {
|
||||
DPRINTF(VtoPhys, "level 2 PTE not valid, va = %#x\n", vaddr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t level3_map = PMAP_PTE_PA(level2);
|
||||
Addr level3_pte = level3_map + (level3_index(vaddr) << PTESHIFT);
|
||||
|
||||
return level3_pte;
|
||||
}
|
||||
|
||||
Addr
|
||||
vtophys(PhysicalMemory *xc, Addr vaddr)
|
||||
{
|
||||
Addr paddr = 0;
|
||||
if (vaddr < ALPHA_K0SEG_BASE)
|
||||
DPRINTF(VtoPhys, "vtophys: invalid vaddr %#x", vaddr);
|
||||
else if (vaddr < ALPHA_K1SEG_BASE)
|
||||
paddr = ALPHA_K0SEG_TO_PHYS(vaddr);
|
||||
else
|
||||
panic("vtophys: ptbr is not set on virtual lookup");
|
||||
|
||||
DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr);
|
||||
|
||||
return paddr;
|
||||
}
|
||||
|
||||
Addr
|
||||
vtophys(ExecContext *xc, Addr vaddr)
|
||||
{
|
||||
Addr ptbr = xc->regs.ipr[AlphaISA::IPR_PALtemp20];
|
||||
Addr paddr = 0;
|
||||
if (vaddr < ALPHA_K0SEG_BASE) {
|
||||
DPRINTF(VtoPhys, "vtophys: invalid vaddr %#x", vaddr);
|
||||
} else if (vaddr < ALPHA_K1SEG_BASE) {
|
||||
paddr = ALPHA_K0SEG_TO_PHYS(vaddr);
|
||||
} else {
|
||||
if (!ptbr)
|
||||
panic("vtophys: ptbr is not set on virtual lookup");
|
||||
|
||||
Addr pte = kernel_pte_lookup(xc->physmem, ptbr, vaddr);
|
||||
uint64_t entry = xc->physmem->phys_read_qword(pte);
|
||||
if (pte && entry_valid(entry))
|
||||
paddr = PMAP_PTE_PA(entry) | (vaddr & PGOFSET);
|
||||
}
|
||||
|
||||
DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr);
|
||||
|
||||
return paddr;
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
vtomem(ExecContext *xc, Addr vaddr, size_t len)
|
||||
{
|
||||
Addr paddr = vtophys(xc, vaddr);
|
||||
return xc->physmem->dma_addr(paddr, len);
|
||||
}
|
46
arch/alpha/vtophys.hh
Normal file
46
arch/alpha/vtophys.hh
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 __VTOPHYS_H__
|
||||
#define __VTOPHYS_H__
|
||||
|
||||
#include "pmap.h"
|
||||
|
||||
inline bool entry_valid(uint64_t entry)
|
||||
{ return (entry & ALPHA_PTE_VALID) != 0; }
|
||||
|
||||
class ExecContext;
|
||||
class PhysicalMemory;
|
||||
|
||||
Addr kernel_pte_lookup(PhysicalMemory *pmem, Addr ptbr, Addr vaddr);
|
||||
Addr vtophys(PhysicalMemory *xc, Addr vaddr);
|
||||
Addr vtophys(ExecContext *xc, Addr vaddr);
|
||||
uint8_t *vtomem(ExecContext *xc, Addr vaddr, size_t len);
|
||||
|
||||
#endif // __VTOPHYS_H__
|
||||
|
1446
arch/isa_parser.py
Normal file
1446
arch/isa_parser.py
Normal file
File diff suppressed because it is too large
Load diff
69
base/bitfield.hh
Normal file
69
base/bitfield.hh
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 __BITFIELD_HH
|
||||
#define __BITFIELD_HH
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
/**
|
||||
* 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
|
56
base/callback.hh
Normal file
56
base/callback.hh
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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>
|
||||
|
||||
class Callback {
|
||||
public:
|
||||
virtual ~Callback() {}
|
||||
virtual void process() = 0;
|
||||
};
|
||||
|
||||
class CallbackQueue
|
||||
{
|
||||
protected:
|
||||
std::list<Callback *> callbacks;
|
||||
|
||||
public:
|
||||
void add(Callback *callback) { callbacks.push_back(callback); }
|
||||
bool empty() const { return callbacks.empty(); }
|
||||
void processOne() {
|
||||
Callback *c = callbacks.front();
|
||||
callbacks.pop_front();
|
||||
c->process();
|
||||
}
|
||||
void processAll() { while (!empty()) processOne(); }
|
||||
};
|
||||
|
||||
#endif // __CALLBACK_HH__
|
187
base/circlebuf.cc
Normal file
187
base/circlebuf.cc
Normal file
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "cprintf.hh"
|
||||
#include "circlebuf.hh"
|
||||
#include "intmath.h"
|
||||
|
||||
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::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;
|
||||
}
|
59
base/circlebuf.hh
Normal file
59
base/circlebuf.hh
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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__
|
||||
|
||||
|
||||
class CircleBuf
|
||||
{
|
||||
protected:
|
||||
char *buf;
|
||||
bool rollover;
|
||||
int buflen;
|
||||
int size;
|
||||
int start;
|
||||
int stop;
|
||||
|
||||
public:
|
||||
explicit CircleBuf(int l);
|
||||
~CircleBuf();
|
||||
|
||||
bool empty() { return size == 0; }
|
||||
void dump();
|
||||
void flush();
|
||||
void read(char *b, int len);
|
||||
void read(int fd, int len);
|
||||
void read(int fd);
|
||||
void readall(int fd);
|
||||
void write(char b);
|
||||
void write(const char *b);
|
||||
void write(const char *b, int len);
|
||||
};
|
||||
|
||||
#endif // __CIRCLEBUF_HH__
|
277
base/cprintf.cc
Normal file
277
base/cprintf.cc
Normal file
|
@ -0,0 +1,277 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "cprintf.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace cp {
|
||||
|
||||
void
|
||||
ArgList::dump(const string &format)
|
||||
{
|
||||
const char *p = format.c_str();
|
||||
|
||||
stream->fill(' ');
|
||||
stream->flags((ios::fmtflags)0);
|
||||
|
||||
Format fmt;
|
||||
|
||||
while (*p) {
|
||||
switch (*p) {
|
||||
case '%': {
|
||||
if (p[1] == '%') {
|
||||
*stream << '%';
|
||||
p += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (objects.empty())
|
||||
format_invalid(*stream);
|
||||
|
||||
Base *data = objects.front();
|
||||
|
||||
fmt.clear();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
ios::fmtflags saved_flags = stream->flags();
|
||||
char old_fill = stream->fill();
|
||||
int old_precision = stream->precision();
|
||||
|
||||
data->process(*stream, fmt);
|
||||
|
||||
stream->flags(saved_flags);
|
||||
stream->fill(old_fill);
|
||||
stream->precision(old_precision);
|
||||
|
||||
delete data;
|
||||
objects.pop_front();
|
||||
++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;
|
||||
}
|
||||
|
||||
ios::iostate state = stream->rdstate();
|
||||
if (state) {
|
||||
#if 0
|
||||
cout << "stream->rdstate() == " << state << endl;
|
||||
if (state & ios::badbit)
|
||||
cout << "stream is bad!\n";
|
||||
if (state & ios::eofbit)
|
||||
cout << "stream at eof!\n";
|
||||
if (state & ios::failbit)
|
||||
cout << "stream failed!\n";
|
||||
if (state & ios::goodbit)
|
||||
cout << "stream is good!!\n";
|
||||
#endif
|
||||
stream->clear();
|
||||
}
|
||||
}
|
||||
|
||||
while (!objects.empty()) {
|
||||
Base *data = objects.front();
|
||||
data->process(*stream, fmt);
|
||||
delete data;
|
||||
objects.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
string
|
||||
ArgList::dumpToString(const string &format)
|
||||
{
|
||||
stringstream ss;
|
||||
|
||||
dump(ss, format);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
}
|
197
base/cprintf.hh
Normal file
197
base/cprintf.hh
Normal file
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace cp {
|
||||
|
||||
#include "cprintf_formats.hh"
|
||||
|
||||
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:
|
||||
format_invalid(out);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::list<Base *> list_t;
|
||||
|
||||
protected:
|
||||
list_t objects;
|
||||
std::ostream *stream;
|
||||
|
||||
public:
|
||||
ArgList() : stream(&std::cout) {}
|
||||
|
||||
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__
|
354
base/cprintf_formats.hh
Normal file
354
base/cprintf_formats.hh
Normal file
|
@ -0,0 +1,354 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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__
|
||||
|
||||
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() { }
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
inline void
|
||||
format_invalid(std::ostream &out)
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
out << "format invalid!!!" << endl;
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{ format_invalid(out); }
|
||||
|
||||
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); }
|
||||
|
||||
#if 0
|
||||
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); }
|
||||
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)
|
||||
{ format_invalid(out); }
|
||||
|
||||
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); }
|
||||
|
||||
#endif // __CPRINTF_FORMATS_HH__
|
29
base/date.cc
Normal file
29
base/date.cc
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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
base/dbl_list.hh
Normal file
165
base/dbl_list.hh
Normal file
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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
base/endian.hh
Normal file
41
base/endian.hh
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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__
|
191
base/fast_alloc.cc
Normal file
191
base/fast_alloc.cc
Normal file
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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.
|
||||
*/
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma implementation
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include "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
|
203
base/fast_alloc.hh
Normal file
203
base/fast_alloc.hh
Normal file
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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
|
||||
|
||||
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 // __FAST_ALLOC_H__
|
40
base/fifo_buffer.cc
Normal file
40
base/fifo_buffer.cc
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "fifo_buffer.hh"
|
||||
|
||||
template<class T>
|
||||
void
|
||||
FifoBuffer<T>::dump(void)
|
||||
{
|
||||
if (buffer->count() > 0)
|
||||
for (iterator i=buffer->tail(); i.notnull(); i=i.prev())
|
||||
i->dump();
|
||||
}
|
||||
|
||||
|
93
base/fifo_buffer.hh
Normal file
93
base/fifo_buffer.hh
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "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(void) { return buffer->head(); }
|
||||
iterator tail(void) { return buffer->tail(); }
|
||||
|
||||
unsigned count(void) {return buffer->count();}
|
||||
unsigned free_slots(void) {return buffer->num_free();}
|
||||
|
||||
T * peek(void)
|
||||
{
|
||||
if (count() > 0) {
|
||||
return tail().data_ptr();
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
T remove(void)
|
||||
{
|
||||
assert(buffer->count() > 0);
|
||||
T rval = *buffer->tail();
|
||||
buffer->remove_tail();
|
||||
return rval;
|
||||
}
|
||||
|
||||
void dump(void);
|
||||
|
||||
~FifoBuffer() { delete buffer; }
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
83
base/hashmap.hh
Normal file
83
base/hashmap.hh
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "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 {
|
||||
template<>
|
||||
struct hash<uint64_t> {
|
||||
size_t operator()(uint64_t r) const {
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<Counter> {
|
||||
size_t operator()(Counter r) const {
|
||||
return r;
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<std::string> {
|
||||
size_t operator()(const std::string &s) const {
|
||||
return(__stl_hash_string(s.c_str()));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif // __HASHMAP_HH__
|
161
base/inet.cc
Normal file
161
base/inet.cc
Normal file
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "cprintf.hh"
|
||||
#include "host.hh"
|
||||
#include "inet.hh"
|
||||
|
||||
using namespace::std;
|
||||
string
|
||||
eaddr_string(const uint8_t a[6])
|
||||
{
|
||||
stringstream stream;
|
||||
ccprintf(stream, "%x:%x:%x:%x:%x:%x", a[0], a[1], a[2], a[3], a[4], a[5]);
|
||||
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
/***********************************************************************
|
||||
This section of code taken from NetBSD
|
||||
***********************************************************************/
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
This is the end of the NetBSD code
|
||||
***********************************************************************/
|
37
base/inet.hh
Normal file
37
base/inet.hh
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 __INET_HH__
|
||||
#define __INET_HH__
|
||||
|
||||
#include "host.hh"
|
||||
|
||||
uint32_t crc32be(const uint8_t *buf, size_t len);
|
||||
uint32_t crc32le(const uint8_t *buf, size_t len);
|
||||
std::string eaddr_string(const uint8_t a[6]);
|
||||
#endif // __INET_HH__
|
437
base/inifile.cc
Normal file
437
base/inifile.cc
Normal file
|
@ -0,0 +1,437 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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
|
||||
// #define CPP_PIPE
|
||||
|
||||
|
||||
#ifdef USE_CPP
|
||||
#include <sys/signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#if __GNUC__ >= 3
|
||||
#include <ext/stdio_filebuf.h>
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "inifile.hh"
|
||||
#include "str.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
IniFile::IniFile()
|
||||
{}
|
||||
|
||||
IniFile::~IniFile()
|
||||
{
|
||||
ConfigTable::iterator i = table.begin();
|
||||
ConfigTable::iterator end = table.end();
|
||||
|
||||
while (i != end) {
|
||||
delete (*i).second;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_CPP
|
||||
bool
|
||||
IniFile::loadCPP(const string &file, vector<char *> &cppArgs)
|
||||
{
|
||||
int fd[2];
|
||||
|
||||
#ifdef CPP_PIPE
|
||||
if (pipe(fd) == -1)
|
||||
return false;
|
||||
#else
|
||||
char tempfile[] = "/tmp/configXXXXXX";
|
||||
fd[0] = fd[1] = mkstemp(tempfile);
|
||||
#endif
|
||||
|
||||
int pid = fork();
|
||||
|
||||
if (pid == -1)
|
||||
return 1;
|
||||
|
||||
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];
|
||||
|
||||
args[nextArg++] = filename;
|
||||
args[nextArg++] = NULL;
|
||||
|
||||
close(STDOUT_FILENO);
|
||||
if (dup2(fd[1], STDOUT_FILENO) == -1)
|
||||
return 1;
|
||||
|
||||
execvp("g++", args);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int retval;
|
||||
waitpid(pid, &retval, 0);
|
||||
|
||||
// check for normal completion of CPP
|
||||
if (!WIFEXITED(retval) || WEXITSTATUS(retval) != 0)
|
||||
return false;
|
||||
|
||||
#ifdef CPP_PIPE
|
||||
close(fd[1]);
|
||||
#else
|
||||
lseek(fd[0], 0, SEEK_SET);
|
||||
#endif
|
||||
|
||||
bool status = false;
|
||||
|
||||
#if __GNUC__ >= 3
|
||||
using namespace __gnu_cxx;
|
||||
stdio_filebuf<char> fbuf(fd[0], ios_base::in, true,
|
||||
static_cast<stdio_filebuf<char>::int_type>(BUFSIZ));
|
||||
|
||||
if (fbuf.is_open()) {
|
||||
istream f(&fbuf);
|
||||
status = load(f);
|
||||
}
|
||||
|
||||
#else
|
||||
ifstream f(fd[0]);
|
||||
if (f.is_open())
|
||||
status = load(f);
|
||||
#endif
|
||||
|
||||
#ifndef CPP_PIPE
|
||||
unlink(tempfile);
|
||||
#endif
|
||||
|
||||
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)
|
||||
{
|
||||
EntryTable::iterator ei = table.find(entryName);
|
||||
|
||||
if (ei == table.end()) {
|
||||
// new entry
|
||||
table[entryName] = new Entry(value);
|
||||
}
|
||||
else {
|
||||
// override old entry
|
||||
ei->second->setValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 §ionName)
|
||||
{
|
||||
ConfigTable::iterator ci = table.find(sectionName);
|
||||
|
||||
if (ci != table.end()) {
|
||||
return ci->second;
|
||||
}
|
||||
else {
|
||||
// new entry
|
||||
Section *sec = new Section();
|
||||
table[sectionName] = sec;
|
||||
return sec;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
IniFile::Section *
|
||||
IniFile::findSection(const string §ionName) const
|
||||
{
|
||||
ConfigTable::const_iterator ci = table.find(sectionName);
|
||||
|
||||
return (ci == table.end()) ? NULL : ci->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);
|
||||
|
||||
offset = rest.find('=');
|
||||
if (offset == string::npos) // no '='found
|
||||
return false;
|
||||
|
||||
string entryName = rest.substr(0, offset);
|
||||
string value = rest.substr(offset + 1);
|
||||
|
||||
eat_white(sectionName);
|
||||
eat_white(entryName);
|
||||
eat_white(value);
|
||||
|
||||
Section *s = addSection(sectionName);
|
||||
s->addEntry(entryName, value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
string::size_type offset = line.find('=');
|
||||
string entryName = line.substr(0, offset);
|
||||
string value = line.substr(offset + 1);
|
||||
|
||||
eat_white(entryName);
|
||||
eat_white(value);
|
||||
|
||||
section->addEntry(entryName, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IniFile::find(const string §ionName, 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::findDefault(const string &_section, const string &entry,
|
||||
string &value) const
|
||||
{
|
||||
string section = _section;
|
||||
while (!find(section, entry, value)) {
|
||||
if (!find(section, "default", section))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
IniFile::Section::printUnreferenced(const string §ionName)
|
||||
{
|
||||
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 (ConfigTable::iterator ci = table.begin();
|
||||
ci != table.end(); ++ci) {
|
||||
const string §ionName = ci->first;
|
||||
Section *section = ci->second;
|
||||
|
||||
if (!section->isReferenced()) {
|
||||
if (section->findEntry("unref_section_ok") == NULL) {
|
||||
cerr << "Section " << sectionName << " not referenced."
|
||||
<< endl;
|
||||
unref = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
#if 0
|
||||
if (section->findEntry("unref_entries_ok") == NULL) {
|
||||
bool unrefEntries = section->printUnreferenced(sectionName);
|
||||
unref = unref || unrefEntries;
|
||||
}
|
||||
#else
|
||||
if (section->printUnreferenced(sectionName)) {
|
||||
unref = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return unref;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
IniFile::Section::dump(const string §ionName)
|
||||
{
|
||||
for (EntryTable::iterator ei = table.begin();
|
||||
ei != table.end(); ++ei) {
|
||||
cout << sectionName << ": " << (*ei).first << " => "
|
||||
<< (*ei).second << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IniFile::dump()
|
||||
{
|
||||
for (ConfigTable::iterator ci = table.begin();
|
||||
ci != table.end(); ++ci) {
|
||||
ci->second->dump(ci->first);
|
||||
}
|
||||
}
|
111
base/inifile.hh
Normal file
111
base/inifile.hh
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "hashmap.hh"
|
||||
|
||||
class IniFile
|
||||
{
|
||||
protected:
|
||||
class Entry
|
||||
{
|
||||
std::string value;
|
||||
mutable bool referenced;
|
||||
|
||||
public:
|
||||
Entry(const std::string &v)
|
||||
: value(v), referenced(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool isReferenced() { return referenced; }
|
||||
|
||||
const std::string &getValue() const;
|
||||
|
||||
void setValue(const std::string &v) { value = v; }
|
||||
};
|
||||
|
||||
class Section
|
||||
{
|
||||
typedef m5::hash_map<std::string, Entry *> EntryTable;
|
||||
|
||||
EntryTable table;
|
||||
mutable bool referenced;
|
||||
|
||||
public:
|
||||
Section()
|
||||
: table(), referenced(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool isReferenced() { return referenced; }
|
||||
|
||||
void addEntry(const std::string &entryName, const std::string &value);
|
||||
Entry *findEntry(const std::string &entryName) const;
|
||||
|
||||
bool printUnreferenced(const std::string §ionName);
|
||||
void dump(const std::string §ionName);
|
||||
};
|
||||
|
||||
typedef m5::hash_map<std::string, Section *> ConfigTable;
|
||||
|
||||
protected:
|
||||
ConfigTable table;
|
||||
|
||||
Section *addSection(const std::string §ionName);
|
||||
Section *findSection(const std::string §ionName) const;
|
||||
|
||||
bool load(std::istream &f);
|
||||
|
||||
public:
|
||||
IniFile();
|
||||
~IniFile();
|
||||
|
||||
bool loadCPP(const std::string &file, std::vector<char *> &cppFlags);
|
||||
bool load(const std::string &file);
|
||||
|
||||
bool add(const std::string &s);
|
||||
|
||||
bool find(const std::string §ion, const std::string &entry,
|
||||
std::string &value) const;
|
||||
bool findDefault(const std::string §ion, const std::string &entry,
|
||||
std::string &value) const;
|
||||
|
||||
bool printUnreferenced();
|
||||
|
||||
void dump();
|
||||
};
|
||||
|
||||
#endif // __INIFILE_HH__
|
58
base/intmath.cc
Normal file
58
base/intmath.cc
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "intmath.h"
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
123
base/intmath.h
Normal file
123
base/intmath.h
Normal file
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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_H__
|
||||
#define __INTMATH_H__
|
||||
|
||||
// Returns the prime number one less than n.
|
||||
int PrevPrime(int n);
|
||||
|
||||
// Determine if a number is prime
|
||||
inline bool
|
||||
IsPrime(int n)
|
||||
{
|
||||
int 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;
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
LeastSigBit(unsigned n)
|
||||
{ return n & ~(n - 1); }
|
||||
|
||||
inline bool
|
||||
IsPowerOf2(unsigned n)
|
||||
{ return n != 0 && LeastSigBit(n) == n; }
|
||||
|
||||
inline int
|
||||
FloorLog2(unsigned x)
|
||||
{
|
||||
if (x == 0)
|
||||
return -1;
|
||||
|
||||
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
|
||||
CeilLog2(unsigned n)
|
||||
{ return FloorLog2(n-1)+1; }
|
||||
|
||||
inline unsigned
|
||||
FloorPow2(unsigned n)
|
||||
{ return 1 << FloorLog2(n); }
|
||||
|
||||
inline unsigned
|
||||
CeilPow2(unsigned n)
|
||||
{ return 1 << CeilLog2(n); }
|
||||
|
||||
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_H__
|
203
base/kgdb.h
Normal file
203
base/kgdb.h
Normal file
|
@ -0,0 +1,203 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
* 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
|
||||
|
||||
/*
|
||||
* MMCSR Fault Type Codes. [OSF/1 PALcode Specific]
|
||||
*/
|
||||
|
||||
#define ALPHA_MMCSR_INVALTRANS 0
|
||||
#define ALPHA_MMCSR_ACCESS 1
|
||||
#define ALPHA_MMCSR_FOR 2
|
||||
#define ALPHA_MMCSR_FOE 3
|
||||
#define ALPHA_MMCSR_FOW 4
|
||||
|
||||
/*
|
||||
* Instruction Fault Type Codes. [OSF/1 PALcode Specific]
|
||||
*/
|
||||
|
||||
#define ALPHA_IF_CODE_BPT 0
|
||||
#define ALPHA_IF_CODE_BUGCHK 1
|
||||
#define ALPHA_IF_CODE_GENTRAP 2
|
||||
#define ALPHA_IF_CODE_FEN 3
|
||||
#define ALPHA_IF_CODE_OPDEC 4
|
||||
|
||||
#define BKPT_INST 0x00000080 // breakpoint instruction
|
||||
#define BKPT_SIZE (4) // size of breakpoint inst
|
||||
|
||||
#define IS_BREAKPOINT_TRAP(type, code) ((type) == ALPHA_KENTRY_IF && \
|
||||
(code) == ALPHA_IF_CODE_BPT)
|
||||
#define IS_WATCHPOINT_TRAP(type, code) 0
|
||||
|
||||
|
||||
#endif /* __KGDB_H__ */
|
97
base/misc.cc
Normal file
97
base/misc.cc
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "host.hh"
|
||||
#include "cprintf.hh"
|
||||
#include "misc.hh"
|
||||
#include "universe.hh"
|
||||
#include "trace.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void
|
||||
__panic(const string &format, cp::ArgList &args, const char *func,
|
||||
const char *file, int line)
|
||||
{
|
||||
string fmt = "panic: " + format + " [%s:%s, line %d]\n";
|
||||
args.append(func);
|
||||
args.append(file);
|
||||
args.append(line);
|
||||
args.dump(cerr, fmt);
|
||||
|
||||
delete &args;
|
||||
|
||||
#if TRACING_ON
|
||||
// dump trace buffer, if there is one
|
||||
Trace::theLog.dump(cerr);
|
||||
#endif
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
void
|
||||
__fatal(const string &format, cp::ArgList &args, const char *func,
|
||||
const char *file, int line)
|
||||
{
|
||||
long mem_usage();
|
||||
|
||||
string fmt = "fatal: " + format + " [%s:%s, line %d]\n"
|
||||
"\n%d\nMemory Usage: %ld KBytes\n";
|
||||
|
||||
args.append(func);
|
||||
args.append(file);
|
||||
args.append(line);
|
||||
args.append(curTick);
|
||||
args.append(mem_usage());
|
||||
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;
|
||||
#ifdef VERBOSE_WARN
|
||||
fmt += " [%s:%s, line %d]\n";
|
||||
args.append(func);
|
||||
args.append(file);
|
||||
args.append(line);
|
||||
#else
|
||||
fmt += "\n";
|
||||
#endif
|
||||
args.dump(cerr, fmt);
|
||||
|
||||
delete &args;
|
||||
}
|
76
base/misc.hh
Normal file
76
base/misc.hh
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "cprintf.hh"
|
||||
|
||||
//
|
||||
// This implements a cprintf based panic
|
||||
//
|
||||
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
|
||||
//
|
||||
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
base/mod_num.hh
Normal file
201
base/mod_num.hh
Normal file
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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;
|
||||
}
|
||||
|
||||
|
173
base/object_file.cc
Normal file
173
base/object_file.cc
Normal file
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "cprintf.hh"
|
||||
#include "ecoff.hh"
|
||||
#include "object_file.hh"
|
||||
#include "symtab.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
ObjectFile::ObjectFile()
|
||||
: descriptor(-1), data(NULL)
|
||||
{}
|
||||
|
||||
ObjectFile::ObjectFile(string file)
|
||||
: descriptor(-1), data(NULL)
|
||||
{ open(file); }
|
||||
|
||||
ObjectFile::~ObjectFile()
|
||||
{ close(); }
|
||||
|
||||
bool
|
||||
ObjectFile::open(string file_name)
|
||||
{
|
||||
close();
|
||||
|
||||
name = file_name;
|
||||
|
||||
descriptor = ::open(name.c_str(), O_RDONLY);
|
||||
if (descriptor < 0)
|
||||
return false;
|
||||
|
||||
len = (size_t)::lseek(descriptor, 0, SEEK_END);
|
||||
|
||||
data = (uint8_t *)::mmap(NULL, len, PROT_READ, MAP_SHARED, descriptor, 0);
|
||||
if (data == MAP_FAILED)
|
||||
return false;
|
||||
|
||||
postOpen();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ObjectFile::close()
|
||||
{
|
||||
if (descriptor >= 0)
|
||||
::close(descriptor);
|
||||
|
||||
if (data)
|
||||
::munmap(data, len);
|
||||
}
|
||||
|
||||
void
|
||||
EcoffObject::postOpen()
|
||||
{
|
||||
exec = &(((EcoffExecHeader *)data)->f);
|
||||
aout = &(((EcoffExecHeader *)data)->a);
|
||||
|
||||
text_off = aout->text_start;
|
||||
data_off = aout->data_start;
|
||||
bss_off = aout->bss_start;
|
||||
|
||||
text_size = aout->tsize;
|
||||
data_size = aout->dsize;
|
||||
bss_size = aout->bsize;
|
||||
}
|
||||
|
||||
bool
|
||||
EcoffObject::loadGlobals(SymbolTable *symtab)
|
||||
{
|
||||
if (!symtab)
|
||||
return false;
|
||||
|
||||
if (exec->f_magic != ALPHAMAGIC) {
|
||||
cprintf("wrong magic\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
EcoffSymHeader *syms = (EcoffSymHeader *)(data + exec->f_symptr);
|
||||
if (syms->magic != ECOFF_SYM_MAGIC) {
|
||||
cprintf("bad symbol header magic\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
EcoffExtSymEntry *ext_syms =
|
||||
(EcoffExtSymEntry *)(data + syms->cbExtOffset);
|
||||
|
||||
char *ext_strings = (char *)(data + syms->cbSsExtOffset);
|
||||
for (int i = 0; i < syms->iextMax; i++) {
|
||||
EcoffSymEntry *entry = &(ext_syms[i].asym);
|
||||
if (entry->iss != -1)
|
||||
symtab->insert(entry->value, ext_strings + entry->iss);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
EcoffObject::loadLocals(SymbolTable *symtab)
|
||||
{
|
||||
if (!symtab)
|
||||
return false;
|
||||
|
||||
if (exec->f_magic != ALPHAMAGIC) {
|
||||
cprintf("wrong magic\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
EcoffSymHeader *syms = (EcoffSymHeader *)(data + exec->f_symptr);
|
||||
if (syms->magic != ECOFF_SYM_MAGIC) {
|
||||
cprintf("bad symbol header magic\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
EcoffSymEntry *local_syms = (EcoffSymEntry *)(data + syms->cbSymOffset);
|
||||
char *local_strings = (char *)(data + syms->cbSsOffset);
|
||||
EcoffFileDesc *fdesc = (EcoffFileDesc *)(data + syms->cbFdOffset);
|
||||
|
||||
for (int i = 0; i < syms->ifdMax; i++) {
|
||||
EcoffSymEntry *entry =
|
||||
(EcoffSymEntry *)(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 == 1 || entry[j].st == 6)
|
||||
if (entry[j].iss != -1)
|
||||
symtab->insert(entry[j].value, strings + entry[j].iss);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < syms->isymMax; i++) {
|
||||
EcoffSymEntry *entry = &(local_syms[i]);
|
||||
if (entry->st == 6)
|
||||
if (entry->st == 1 || entry->st == 6)
|
||||
symtab->insert(entry->value, local_strings + entry->iss);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
92
base/object_file.hh
Normal file
92
base/object_file.hh
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "ecoff.hh"
|
||||
#include "isa_traits.hh" // for Addr
|
||||
|
||||
class SymbolTable;
|
||||
|
||||
class ObjectFile
|
||||
{
|
||||
protected:
|
||||
std::string name;
|
||||
int descriptor;
|
||||
uint8_t *data;
|
||||
size_t len;
|
||||
|
||||
public:
|
||||
ObjectFile();
|
||||
explicit ObjectFile(std::string file);
|
||||
virtual ~ObjectFile();
|
||||
|
||||
bool open(std::string file);
|
||||
void close();
|
||||
|
||||
virtual bool loadGlobals(SymbolTable *symtab) = 0;
|
||||
virtual bool loadLocals(SymbolTable *symtab) = 0;
|
||||
virtual void postOpen() = 0;
|
||||
|
||||
protected:
|
||||
Addr text_off;
|
||||
Addr data_off;
|
||||
Addr bss_off;
|
||||
|
||||
size_t text_size;
|
||||
size_t data_size;
|
||||
size_t bss_size;
|
||||
|
||||
public:
|
||||
Addr textOffset() const { return text_off; }
|
||||
Addr dataOffset() const { return data_off; }
|
||||
Addr bssOffset() const { return bss_off; }
|
||||
|
||||
size_t textSize() const { return text_size; }
|
||||
size_t dataSize() const { return data_size; }
|
||||
size_t bssSize() const { return bss_size; }
|
||||
};
|
||||
|
||||
class EcoffObject : public ObjectFile
|
||||
{
|
||||
protected:
|
||||
EcoffFileHeader *exec;
|
||||
EcoffAOutHeader *aout;
|
||||
|
||||
public:
|
||||
EcoffObject() {}
|
||||
explicit EcoffObject(std::string file) { open(file); }
|
||||
virtual ~EcoffObject() {}
|
||||
|
||||
virtual bool loadGlobals(SymbolTable *symtab);
|
||||
virtual bool loadLocals(SymbolTable *symtab);
|
||||
virtual void postOpen();
|
||||
};
|
||||
|
||||
#endif // __OBJECT_FILE_HH__
|
254
base/pollevent.cc
Normal file
254
base/pollevent.cc
Normal file
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "async.hh"
|
||||
#include "host.hh"
|
||||
#include "misc.hh"
|
||||
#include "pollevent.hh"
|
||||
#include "universe.hh"
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//
|
||||
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 = 0;
|
||||
|
||||
if (sigaction(SIGIO, &act, &oldio) == -1)
|
||||
panic("could not do sigaction");
|
||||
|
||||
act.sa_handler = handleALRM;
|
||||
sigemptyset(&act.sa_mask);
|
||||
act.sa_flags = 0;
|
||||
|
||||
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);
|
||||
}
|
||||
|
89
base/pollevent.hh
Normal file
89
base/pollevent.hh
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "universe.hh"
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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__
|
79
base/random.cc
Normal file
79
base/random.cc
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "param.hh"
|
||||
#include "random.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class RandomContext : public ParamContext
|
||||
{
|
||||
public:
|
||||
RandomContext(const string &_iniSection)
|
||||
: ::ParamContext(_iniSection) {}
|
||||
~RandomContext();
|
||||
|
||||
void checkParams();
|
||||
};
|
||||
|
||||
RandomContext paramContext("random");
|
||||
|
||||
Param<unsigned>
|
||||
seed(¶mContext, "seed", "seed to random number generator", 1);
|
||||
|
||||
void
|
||||
RandomContext::checkParams()
|
||||
{
|
||||
::srandom(seed);
|
||||
}
|
||||
|
||||
long
|
||||
getLong()
|
||||
{
|
||||
return random();
|
||||
}
|
||||
|
||||
// idea for generating a double from erand48
|
||||
double
|
||||
getDouble()
|
||||
{
|
||||
union {
|
||||
uint32_t _long[2];
|
||||
uint16_t _short[4];
|
||||
};
|
||||
|
||||
_long[0] = random();
|
||||
_long[1] = random();
|
||||
|
||||
return ldexp((double) _short[0], -48) +
|
||||
ldexp((double) _short[1], -32) +
|
||||
ldexp((double) _short[2], -16);
|
||||
}
|
100
base/random.hh
Normal file
100
base/random.hh
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 __RANDOM_HH__
|
||||
#define __RANDOM_HH__
|
||||
|
||||
#include "host.hh"
|
||||
|
||||
long getLong();
|
||||
double getDouble();
|
||||
|
||||
template <typename T>
|
||||
struct Random;
|
||||
|
||||
struct Random<int8_t>
|
||||
{
|
||||
static int8_t get()
|
||||
{ return getLong() & (int8_t)-1; }
|
||||
};
|
||||
|
||||
struct Random<uint8_t>
|
||||
{
|
||||
uint8_t get()
|
||||
{ return getLong() & (uint8_t)-1; }
|
||||
};
|
||||
|
||||
struct Random<int16_t>
|
||||
{
|
||||
int16_t get()
|
||||
{ return getLong() & (int16_t)-1; }
|
||||
};
|
||||
|
||||
struct Random<uint16_t>
|
||||
{
|
||||
uint16_t get()
|
||||
{ return getLong() & (uint16_t)-1; }
|
||||
};
|
||||
|
||||
struct Random<int32_t>
|
||||
{
|
||||
int32_t get()
|
||||
{ return (int32_t)getLong(); }
|
||||
};
|
||||
|
||||
struct Random<uint32_t>
|
||||
{
|
||||
uint32_t get()
|
||||
{ return (uint32_t)getLong(); }
|
||||
};
|
||||
|
||||
struct Random<int64_t>
|
||||
{
|
||||
int64_t get()
|
||||
{ return (int64_t)getLong() << 32 || (uint64_t)getLong(); }
|
||||
};
|
||||
|
||||
struct Random<uint64_t>
|
||||
{
|
||||
uint64_t get()
|
||||
{ return (uint64_t)getLong() << 32 || (uint64_t)getLong(); }
|
||||
};
|
||||
|
||||
struct Random<float>
|
||||
{
|
||||
float get()
|
||||
{ return getDouble(); }
|
||||
};
|
||||
|
||||
struct Random<double>
|
||||
{
|
||||
double get()
|
||||
{ return getDouble(); }
|
||||
};
|
||||
|
||||
#endif // __RANDOM_HH__
|
260
base/range.hh
Normal file
260
base/range.hh
Normal file
|
@ -0,0 +1,260 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 __RANGE_HH__
|
||||
#define __RANGE_HH__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "str.hh"
|
||||
#include "intmath.h"
|
||||
|
||||
template<class T>
|
||||
class Range
|
||||
{
|
||||
private:
|
||||
bool valid;
|
||||
|
||||
public:
|
||||
T start;
|
||||
T end;
|
||||
|
||||
public:
|
||||
Range() {}
|
||||
|
||||
Range(const Range &r) { operator=(r); }
|
||||
|
||||
Range(const T& s, const T& e)
|
||||
: start(s), end(e)
|
||||
{
|
||||
valid = (start <= end);
|
||||
}
|
||||
|
||||
Range(const std::string &s) { valid = parse(s); }
|
||||
|
||||
~Range() {}
|
||||
|
||||
int compare(const T &p);
|
||||
bool parse(const std::string &s);
|
||||
const Range &operator=(const Range &r);
|
||||
|
||||
bool isValid() const { return valid; }
|
||||
};
|
||||
|
||||
|
||||
template<class T>
|
||||
inline int
|
||||
Range<T>::compare(const T &p)
|
||||
{
|
||||
assert(isValid());
|
||||
|
||||
if (p < start)
|
||||
return -1;
|
||||
else if (p > end)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Parse a range string
|
||||
//
|
||||
// Ranges are in the following format:
|
||||
// <range> := {<start_val>}:{<end>}
|
||||
// <end> := <end_val> | +<delta>
|
||||
template<class T>
|
||||
inline bool
|
||||
Range<T>::parse(const std::string &str)
|
||||
{
|
||||
std::vector<std::string> values;
|
||||
tokenize(values, str, ':');
|
||||
|
||||
T thestart, theend;
|
||||
|
||||
if (values.size() != 2)
|
||||
return false;
|
||||
|
||||
std::string s = values[0];
|
||||
std::string e = values[1];
|
||||
|
||||
if (!to_number(s, thestart))
|
||||
return false;
|
||||
|
||||
bool increment = (e[0] == '+');
|
||||
if (increment)
|
||||
e = e.substr(1);
|
||||
|
||||
if (!to_number(e, theend))
|
||||
return false;
|
||||
|
||||
if (increment)
|
||||
theend += thestart;
|
||||
|
||||
start = thestart;
|
||||
end = theend;
|
||||
|
||||
if (start > end)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
inline const Range<T> &
|
||||
Range<T>::operator=(const Range<T> &r)
|
||||
{
|
||||
if (this != &r) {
|
||||
start = r.start;
|
||||
end = r.end;
|
||||
|
||||
valid = r.valid;
|
||||
}
|
||||
else {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline std::ostream &
|
||||
operator<<(std::ostream &o, const Range<T> &r)
|
||||
{
|
||||
// don't currently support output of invalid ranges
|
||||
assert(r.isValid());
|
||||
o << r.start << ":" << r.end;
|
||||
return o;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
//
|
||||
// Compare two ranges
|
||||
//
|
||||
template<class T>
|
||||
inline bool
|
||||
operator==(const Range<T> &l, const Range<T> &r)
|
||||
{
|
||||
// ranges must both be valid to be equal
|
||||
return (l.isValid() && r.isValid() &&
|
||||
(l.start == r.start) && (l.end == r.end));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline bool
|
||||
operator!=(const Range<T> &l, const Range<T> &r)
|
||||
{
|
||||
// for symmetry with ==, an invalid range is not equal to any other
|
||||
return (!l.isValid() || !r.isValid() ||
|
||||
(l.start != r.start) || (l.end != r.end));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
//
|
||||
// Compare position to a range
|
||||
//
|
||||
// - 'pos == range' indicates that position pos is within the given range.
|
||||
// This test always returns false if the range is invalid.
|
||||
//
|
||||
// - 'pos < range' and 'pos > range' indicate that the position is
|
||||
// before the start of or after the end of the range, respectively.
|
||||
// The range must be valid for these comparisons to be made.
|
||||
//
|
||||
// All other comparisons do the obvious thing based on these definitions.
|
||||
//
|
||||
//
|
||||
|
||||
//
|
||||
// Basic comparisons
|
||||
//
|
||||
template<class T>
|
||||
inline bool
|
||||
operator==(const T &pos, const Range<T> &range)
|
||||
{ return range.isValid() && pos >= range.start && pos <= range.end; }
|
||||
|
||||
template<class T>
|
||||
inline bool
|
||||
operator<(const T &pos, const Range<T> &range)
|
||||
{ assert(range.isValid()); return pos < range.start; }
|
||||
|
||||
template<class T>
|
||||
inline bool
|
||||
operator>(const T &pos, const Range<T> &range)
|
||||
{ assert(range.isValid()); return pos > range.end; }
|
||||
|
||||
//
|
||||
// Derived comparisons
|
||||
//
|
||||
template<class T>
|
||||
inline bool
|
||||
operator<=(const T &pos, const Range<T> &range)
|
||||
{ assert(range.isValid()); return pos <= range.end; }
|
||||
|
||||
template<class T>
|
||||
inline bool
|
||||
operator>=(const T &pos, const Range<T> &range)
|
||||
{ assert(range.isValid()); return pos >= range.start; }
|
||||
|
||||
template<class T>
|
||||
inline bool
|
||||
operator!=(const T &pos, const Range<T> &range)
|
||||
{ return !(pos == range); }
|
||||
|
||||
//
|
||||
// Define symmetric comparisons based on above
|
||||
//
|
||||
template<class T>
|
||||
inline bool
|
||||
operator>(const Range<T> &range, const T &pos)
|
||||
{ return pos < range; }
|
||||
|
||||
template<class T>
|
||||
inline bool
|
||||
operator<(const Range<T> &range, const T &pos)
|
||||
{ return pos > range; }
|
||||
|
||||
template<class T>
|
||||
inline bool
|
||||
operator<=(const Range<T> &range, const T &pos)
|
||||
{ return pos >= range; }
|
||||
|
||||
template<class T>
|
||||
inline bool
|
||||
operator>=(const Range<T> &range, const T &pos)
|
||||
{ return pos <= range; }
|
||||
|
||||
template<class T>
|
||||
inline bool
|
||||
operator==(const Range<T> &range, const T &pos)
|
||||
{ return (pos == range); }
|
||||
|
||||
template<class T>
|
||||
inline bool
|
||||
operator!=(const Range<T> &range, const T &pos)
|
||||
{ return (pos != range); }
|
||||
|
||||
#endif // __RANGE_HH__
|
122
base/refcnt.hh
Normal file
122
base/refcnt.hh
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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__
|
||||
|
||||
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
|
||||
{
|
||||
private:
|
||||
T *data;
|
||||
|
||||
void copy(T *d) {
|
||||
data = d;
|
||||
if (data)
|
||||
data->incref();
|
||||
}
|
||||
void del() {
|
||||
if (data)
|
||||
data->decref();
|
||||
}
|
||||
|
||||
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) {
|
||||
if (data != p) {
|
||||
del();
|
||||
copy(p);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
RefCountingPtr &operator=(const RefCountingPtr& r) {
|
||||
if (data != r.data) {
|
||||
del();
|
||||
copy(r.data);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
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__
|
1150
base/remote_gdb.cc
Normal file
1150
base/remote_gdb.cc
Normal file
File diff suppressed because it is too large
Load diff
189
base/remote_gdb.hh
Normal file
189
base/remote_gdb.hh
Normal file
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "kgdb.h"
|
||||
#include "pc_event.hh"
|
||||
#include "pollevent.hh"
|
||||
#include "socket.hh"
|
||||
|
||||
class System;
|
||||
class ExecContext;
|
||||
class PhysicalMemory;
|
||||
|
||||
class RemoteGDB
|
||||
{
|
||||
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;
|
||||
|
||||
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 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:
|
||||
HardBreakpoint(RemoteGDB *_gdb, Addr addr);
|
||||
|
||||
int refcount;
|
||||
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);
|
||||
};
|
||||
|
||||
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();
|
||||
};
|
||||
|
||||
#endif /* __REMOTE_GDB_H__ */
|
756
base/res_list.hh
Normal file
756
base/res_list.hh
Normal file
|
@ -0,0 +1,756 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "cprintf.hh"
|
||||
#include "std_types.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)
|
||||
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__
|
176
base/sched_list.hh
Normal file
176
base/sched_list.hh
Normal file
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "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 (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>
|
||||
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
|
114
base/socket.cc
Normal file
114
base/socket.cc
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "host.hh"
|
||||
#include "misc.hh"
|
||||
#include "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!");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#if !defined(__OpenBSD__) && !defined(linux)
|
||||
typedef int socklen_t;
|
||||
#endif
|
||||
|
||||
// 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
base/socket.hh
Normal file
49
base/socket.hh
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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__
|
823
base/statistics.cc
Normal file
823
base/statistics.cc
Normal file
|
@ -0,0 +1,823 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 <iostream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "cprintf.hh"
|
||||
#include "intmath.h"
|
||||
#include "misc.hh"
|
||||
#include "statistics.hh"
|
||||
#include "str.hh"
|
||||
#include "universe.hh"
|
||||
|
||||
#ifdef __M5_NAN
|
||||
float
|
||||
__nan()
|
||||
{
|
||||
union {
|
||||
uint32_t ui;
|
||||
float f;
|
||||
} nan;
|
||||
|
||||
nan.ui = 0x7fc00000;
|
||||
return nan.f;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef STAT_DEBUG
|
||||
static int total_stats = 0;
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
// This is a hack to get this parameter from the old stats package.
|
||||
namespace Statistics {
|
||||
bool PrintDescriptions = true;
|
||||
|
||||
namespace Detail {
|
||||
struct SubData
|
||||
{
|
||||
string name;
|
||||
string desc;
|
||||
};
|
||||
|
||||
struct StatData
|
||||
{
|
||||
StatData();
|
||||
~StatData();
|
||||
|
||||
bool init;
|
||||
bool print;
|
||||
string name;
|
||||
vector<SubData> *subdata;
|
||||
string desc;
|
||||
int precision;
|
||||
FormatFlags flags;
|
||||
const Stat *prereq;
|
||||
};
|
||||
|
||||
StatData::StatData()
|
||||
: init(false), print(false), subdata(NULL), precision(-1), flags(none),
|
||||
prereq(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
StatData::~StatData()
|
||||
{
|
||||
if (subdata)
|
||||
delete subdata;
|
||||
}
|
||||
|
||||
class Database
|
||||
{
|
||||
private:
|
||||
Database(const Database &) {}
|
||||
|
||||
private:
|
||||
typedef list<Stat *> list_t;
|
||||
typedef map<const Stat *, StatData *> map_t;
|
||||
|
||||
list_t allStats;
|
||||
list_t printStats;
|
||||
map_t map;
|
||||
|
||||
public:
|
||||
Database();
|
||||
~Database();
|
||||
|
||||
void dump(ostream &stream);
|
||||
|
||||
StatData *find(const Stat *stat);
|
||||
void check();
|
||||
void regStat(Stat *stat);
|
||||
StatData *print(Stat *stat);
|
||||
};
|
||||
|
||||
Database::Database()
|
||||
{}
|
||||
|
||||
Database::~Database()
|
||||
{}
|
||||
|
||||
void
|
||||
Database::dump(ostream &stream)
|
||||
{
|
||||
list_t::iterator i = printStats.begin();
|
||||
list_t::iterator end = printStats.end();
|
||||
|
||||
while (i != end) {
|
||||
Stat *stat = *i;
|
||||
if (stat->dodisplay())
|
||||
stat->display(stream);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
StatData *
|
||||
Database::find(const Stat *stat)
|
||||
{
|
||||
map_t::const_iterator i = map.find(stat);
|
||||
|
||||
if (i == map.end())
|
||||
return NULL;
|
||||
|
||||
return (*i).second;
|
||||
}
|
||||
|
||||
void
|
||||
Database::check()
|
||||
{
|
||||
list_t::iterator i = allStats.begin();
|
||||
list_t::iterator end = allStats.end();
|
||||
|
||||
while (i != end) {
|
||||
Stat *stat = *i;
|
||||
StatData *data = find(stat);
|
||||
if (!data || !data->init) {
|
||||
#ifdef STAT_DEBUG
|
||||
cprintf("this is stat number %d\n",(*i)->number);
|
||||
#endif
|
||||
panic("Not all stats have been initialized");
|
||||
}
|
||||
|
||||
if (data->print) {
|
||||
if (data->name.empty())
|
||||
panic("all printable stats must be named");
|
||||
|
||||
list_t::iterator j = printStats.insert(printStats.end(), *i);
|
||||
inplace_merge(printStats.begin(), j,
|
||||
printStats.end(), Stat::less);
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Database::regStat(Stat *stat)
|
||||
{
|
||||
if (map.find(stat) != map.end())
|
||||
panic("shouldn't register stat twice!");
|
||||
|
||||
allStats.push_back(stat);
|
||||
|
||||
StatData *data = new StatData;
|
||||
bool success = (map.insert(make_pair(stat, data))).second;
|
||||
assert(map.find(stat) != map.end());
|
||||
assert(success && "this should never fail");
|
||||
}
|
||||
|
||||
bool
|
||||
Stat::less(Stat *stat1, Stat *stat2)
|
||||
{
|
||||
const string &name1 = stat1->myname();
|
||||
const string &name2 = stat2->myname();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
StatData *
|
||||
Database::print(Stat *stat)
|
||||
{
|
||||
StatData *data = find(stat);
|
||||
assert(data);
|
||||
|
||||
data->print = true;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
Database &
|
||||
StatDB()
|
||||
{
|
||||
static Database db;
|
||||
return db;
|
||||
}
|
||||
|
||||
Stat::Stat(bool reg)
|
||||
{
|
||||
#if 0
|
||||
// This assert can help you find that pesky stat.
|
||||
assert(this != (void *)0xbffff5c0);
|
||||
#endif
|
||||
|
||||
if (reg)
|
||||
StatDB().regStat(this);
|
||||
#ifdef STAT_DEBUG
|
||||
number = ++total_stats;
|
||||
cprintf("I'm stat number %d\n",number);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
Stat::setInit()
|
||||
{ mydata()->init = true; }
|
||||
|
||||
StatData *
|
||||
Stat::mydata()
|
||||
{
|
||||
StatData *data = StatDB().find(this);
|
||||
assert(data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
const StatData *
|
||||
Stat::mydata() const
|
||||
{
|
||||
StatData *data = StatDB().find(this);
|
||||
assert(data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
const SubData *
|
||||
Stat::mysubdata(int index) const
|
||||
{
|
||||
assert(index >= 0);
|
||||
if (index >= size())
|
||||
return NULL;
|
||||
|
||||
const StatData *data = this->mydata();
|
||||
if (!data->subdata || data->subdata->size() <= index)
|
||||
return NULL;
|
||||
|
||||
return &(*data->subdata)[index];
|
||||
}
|
||||
|
||||
SubData *
|
||||
Stat::mysubdata_create(int index)
|
||||
{
|
||||
int size = this->size();
|
||||
assert(index >= 0 && (size == 0 || size > 0 && index < size));
|
||||
|
||||
StatData *data = this->mydata();
|
||||
if (!data->subdata) {
|
||||
if (!data->subdata) {
|
||||
if (size == 0)
|
||||
size = index + 1;
|
||||
|
||||
data->subdata = new vector<SubData>(size);
|
||||
}
|
||||
} else if (data->subdata->size() <= index)
|
||||
data->subdata->resize(index + 1);
|
||||
|
||||
SubData *sd = &(*data->subdata)[index];
|
||||
assert(sd);
|
||||
|
||||
return sd;
|
||||
}
|
||||
|
||||
string
|
||||
Stat::myname() const
|
||||
{ return mydata()->name; }
|
||||
|
||||
string
|
||||
Stat::mysubname(int index) const
|
||||
{
|
||||
const SubData *sd = mysubdata(index);
|
||||
return sd ? sd->name : "";
|
||||
}
|
||||
|
||||
string
|
||||
Stat::mydesc() const
|
||||
{ return mydata()->desc; }
|
||||
|
||||
string
|
||||
Stat::mysubdesc(int index) const
|
||||
{
|
||||
const SubData *sd = mysubdata(index);
|
||||
return sd ? sd->desc : "";
|
||||
}
|
||||
|
||||
int
|
||||
Stat::myprecision() const
|
||||
{ return mydata()->precision; }
|
||||
|
||||
FormatFlags
|
||||
Stat::myflags() const
|
||||
{ return mydata()->flags; }
|
||||
|
||||
bool
|
||||
Stat::dodisplay() const
|
||||
{ return !mydata()->prereq || !mydata()->prereq->zero(); }
|
||||
|
||||
StatData *
|
||||
Stat::print()
|
||||
{
|
||||
StatData *data = StatDB().print(this);
|
||||
assert(data && data->init);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
Stat &
|
||||
Stat::name(const string &name)
|
||||
{
|
||||
print()->name = name;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Stat &
|
||||
Stat::desc(const string &desc)
|
||||
{
|
||||
print()->desc = desc;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Stat &
|
||||
Stat::precision(int precision)
|
||||
{
|
||||
print()->precision = precision;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Stat &
|
||||
Stat::flags(FormatFlags flags)
|
||||
{
|
||||
if (flags & __reserved)
|
||||
panic("Cannot set reserved flags!\n");
|
||||
|
||||
print()->flags |= flags;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Stat &
|
||||
Stat::prereq(const Stat &prereq)
|
||||
{
|
||||
print()->prereq = &prereq;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Stat &
|
||||
Stat::subname(int index, const string &name)
|
||||
{
|
||||
print();
|
||||
mysubdata_create(index)->name = name;
|
||||
return *this;
|
||||
}
|
||||
Stat &
|
||||
Stat::subdesc(int index, const string &desc)
|
||||
{
|
||||
print();
|
||||
mysubdata_create(index)->desc = desc;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
ScalarStat::zero() const
|
||||
{
|
||||
return val() == 0.0;
|
||||
}
|
||||
|
||||
bool
|
||||
VectorStat::zero() const
|
||||
{
|
||||
return val()[0] == 0.0;
|
||||
}
|
||||
|
||||
string
|
||||
ValueToString(result_t value, int precision)
|
||||
{
|
||||
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 {
|
||||
#ifndef STAT_DISPLAY_COMPAT
|
||||
val << "no value";
|
||||
#else
|
||||
val << "<err: div-0>";
|
||||
#endif
|
||||
}
|
||||
|
||||
return val.str();
|
||||
}
|
||||
|
||||
void
|
||||
PrintOne(ostream &stream, result_t value,
|
||||
const string &name, const string &desc, int precision,
|
||||
FormatFlags flags, result_t pdf = NAN, result_t cdf = NAN)
|
||||
{
|
||||
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);
|
||||
|
||||
#ifdef STAT_DISPLAY_COMPAT
|
||||
if (flags & __substat) {
|
||||
ccprintf(stream, "%32s%12s%10s%10s", name,
|
||||
ValueToString(value, precision),
|
||||
pdfstr, cdfstr);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
ccprintf(stream, "%-40s%12s%10s%10s", name,
|
||||
ValueToString(value, precision), pdfstr, cdfstr);
|
||||
}
|
||||
|
||||
if (PrintDescriptions) {
|
||||
if (!desc.empty())
|
||||
ccprintf(stream, " # %s", desc);
|
||||
}
|
||||
stream << endl;
|
||||
}
|
||||
|
||||
void
|
||||
ScalarStat::display(ostream &stream) const
|
||||
{
|
||||
PrintOne(stream, val(), myname(), mydesc(), myprecision(), myflags());
|
||||
}
|
||||
|
||||
void
|
||||
VectorStat::display(ostream &stream) const
|
||||
{
|
||||
bool have_subname = false;
|
||||
bool have_subdesc = false;
|
||||
int size = this->size();
|
||||
for (int i = 0; i < size; ++i) {
|
||||
if (!mysubname(i).empty())
|
||||
have_subname = true;
|
||||
if (!mysubdesc(i).empty())
|
||||
have_subdesc = true;
|
||||
}
|
||||
|
||||
vector<string> *subnames = 0;
|
||||
vector<string> *subdescs = 0;
|
||||
if (have_subname) {
|
||||
subnames = new vector<string>(size);
|
||||
for (int i = 0; i < size; ++i)
|
||||
(*subnames)[i] = mysubname(i);
|
||||
}
|
||||
if (have_subdesc) {
|
||||
subdescs = new vector<string>(size);
|
||||
for (int i = 0; i < size; ++i)
|
||||
(*subdescs)[i] = mysubdesc(i);
|
||||
}
|
||||
|
||||
VectorDisplay(stream, myname(), subnames, mydesc(), subdescs,
|
||||
myprecision(), myflags(), val(), total());
|
||||
}
|
||||
|
||||
#ifndef STAT_DISPLAY_COMPAT
|
||||
#define NAMESEP "::"
|
||||
#else
|
||||
#define NAMESEP "_"
|
||||
#endif
|
||||
|
||||
#ifndef STAT_DISPLAY_COMPAT
|
||||
void
|
||||
VectorDisplay(std::ostream &stream,
|
||||
const std::string &myname,
|
||||
const std::vector<std::string> *mysubnames,
|
||||
const std::string &mydesc,
|
||||
const std::vector<std::string> *mysubdescs,
|
||||
int myprecision, FormatFlags myflags,
|
||||
const rvec_t &vec, result_t mytotal)
|
||||
{
|
||||
int _size = vec.size();
|
||||
result_t _total = 0.0;
|
||||
result_t _pdf, _cdf = 0.0;
|
||||
|
||||
if (myflags & (pdf | cdf)) {
|
||||
for (int i = 0; i < _size; ++i) {
|
||||
_total += vec[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (_size == 1) {
|
||||
PrintOne(stream, vec[0], myname, mydesc, myprecision, myflags);
|
||||
} else {
|
||||
for (int i = 0; i < _size; ++i) {
|
||||
string subname;
|
||||
if (mysubnames) {
|
||||
subname = (*mysubnames)[i];
|
||||
if (subname.empty())
|
||||
continue;
|
||||
} else {
|
||||
subname = to_string(i);
|
||||
}
|
||||
|
||||
string name = myname + NAMESEP + subname;
|
||||
if (!(myflags & pdf))
|
||||
PrintOne(stream, vec[i], name, mydesc, myprecision, myflags);
|
||||
else {
|
||||
_pdf = vec[i] / _total;
|
||||
_cdf += _pdf;
|
||||
PrintOne(stream, vec[i], name, mydesc, myprecision, myflags,
|
||||
_pdf, _cdf);
|
||||
}
|
||||
}
|
||||
|
||||
if (myflags & total)
|
||||
PrintOne(stream, mytotal, myname + NAMESEP + "total",
|
||||
mydesc, myprecision, myflags);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void
|
||||
VectorDisplay(std::ostream &stream,
|
||||
const std::string &myname,
|
||||
const std::vector<std::string> *mysubnames,
|
||||
const std::string &mydesc,
|
||||
const std::vector<std::string> *mysubdescs,
|
||||
int myprecision, FormatFlags myflags,
|
||||
const rvec_t &vec, result_t mytotal)
|
||||
{
|
||||
int _size = vec.size();
|
||||
result_t _total = 0.0;
|
||||
result_t _pdf, _cdf = 0.0;
|
||||
|
||||
if (myflags & (pdf | cdf)) {
|
||||
for (int i = 0; i < _size; ++i) {
|
||||
_total += vec[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (_size == 1) {
|
||||
PrintOne(stream, vec[0], myname, mydesc, myprecision, myflags);
|
||||
} else {
|
||||
if (myflags & total)
|
||||
PrintOne(stream, mytotal, myname, mydesc, myprecision, myflags);
|
||||
|
||||
if (myflags & dist) {
|
||||
ccprintf(stream, "%s.start_dist\n", myname);
|
||||
for (int i = 0; i < _size; ++i) {
|
||||
string subname, subdesc;
|
||||
subname = to_string(i);
|
||||
if (mysubnames) {
|
||||
if (!subname.empty()) {
|
||||
subname = (*mysubnames)[i];
|
||||
}
|
||||
}
|
||||
if (mysubdescs) {
|
||||
subdesc = (*mysubdescs)[i];
|
||||
}
|
||||
if (!(myflags & (pdf | cdf))) {
|
||||
PrintOne(stream, vec[i], subname, subdesc, myprecision,
|
||||
myflags | __substat);
|
||||
} else {
|
||||
if (_total) {
|
||||
_pdf = vec[i] / _total;
|
||||
_cdf += _pdf;
|
||||
} else {
|
||||
_pdf = _cdf = 0.0;
|
||||
}
|
||||
if (!(myflags & cdf)) {
|
||||
PrintOne(stream, vec[i], subname, subdesc, myprecision,
|
||||
myflags | __substat, _pdf);
|
||||
} else {
|
||||
PrintOne(stream, vec[i], subname, subdesc, myprecision,
|
||||
myflags | __substat, _pdf, _cdf);
|
||||
}
|
||||
}
|
||||
}
|
||||
ccprintf(stream, "%s.end_dist\n", myname);
|
||||
} else {
|
||||
for (int i = 0; i < _size; ++i) {
|
||||
string subname;
|
||||
if (mysubnames) {
|
||||
subname = (*mysubnames)[i];
|
||||
if (subname.empty())
|
||||
continue;
|
||||
} else {
|
||||
subname = to_string(i);
|
||||
}
|
||||
|
||||
string name = myname + NAMESEP + subname;
|
||||
if (!(myflags & pdf)) {
|
||||
PrintOne(stream, vec[i], name, mydesc, myprecision,
|
||||
myflags);
|
||||
} else {
|
||||
if (_total) {
|
||||
_pdf = vec[i] / _total;
|
||||
_cdf += _pdf;
|
||||
} else {
|
||||
_pdf = _cdf = 0.0;
|
||||
}
|
||||
_pdf = vec[i] / _total;
|
||||
_cdf += _pdf;
|
||||
PrintOne(stream, vec[i], name, mydesc, myprecision,
|
||||
myflags, _pdf, _cdf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef STAT_DISPLAY_COMPAT
|
||||
void
|
||||
DistDisplay(ostream &stream, const string &name, const string &desc,
|
||||
int precision, FormatFlags flags,
|
||||
result_t min_val, result_t max_val,
|
||||
result_t underflow, result_t overflow,
|
||||
const rvec_t &vec, int min, int max, int bucket_size, int size);
|
||||
{
|
||||
assert(size == vec.size());
|
||||
|
||||
result_t total = 0.0;
|
||||
result_t pdf, cdf = 0.0;
|
||||
|
||||
total += underflow;
|
||||
for (int i = 0; i < size; ++i)
|
||||
total += vec[i];
|
||||
total += overflow;
|
||||
|
||||
pdf = underflow / total;
|
||||
cdf += pdf;
|
||||
|
||||
PrintOne(stream, underflow, name + NAMESEP + "underflow", desc,
|
||||
precision, myflags, pdf, cdf);
|
||||
|
||||
for (int i = 0; i < size; ++i) {
|
||||
stringstream namestr;
|
||||
namestr << name;
|
||||
|
||||
int low = i * bucket_size + min;
|
||||
int high = ::std::min((i + 1) * bucket_size + min - 1, max);
|
||||
namestr << low;
|
||||
if (low < high)
|
||||
namestr << "-" << high;
|
||||
|
||||
pdf = vec[i] / total;
|
||||
cdf += pdf;
|
||||
PrintOne(stream, vec[i], namestr.str(), desc, precision, myflags,
|
||||
pdf, cdf);
|
||||
}
|
||||
|
||||
pdf = overflow / total;
|
||||
cdf += pdf;
|
||||
PrintOne(stream, overflow, name + NAMESEP + "overflow", desc,
|
||||
precision, myflags, pdf, cdf);
|
||||
PrintOne(stream, total, name + NAMESEP + "total", desc,
|
||||
precision, myflags);
|
||||
}
|
||||
#else
|
||||
void
|
||||
DistDisplay(ostream &stream, const string &name, const string &desc,
|
||||
int precision, FormatFlags flags,
|
||||
result_t min_val, result_t max_val,
|
||||
result_t underflow, result_t overflow,
|
||||
const rvec_t &vec, int min, int max, int bucket_size, int size)
|
||||
{
|
||||
assert(size == vec.size());
|
||||
string blank;
|
||||
|
||||
result_t total = 0.0;
|
||||
|
||||
total += underflow;
|
||||
for (int i = 0; i < size; ++i)
|
||||
total += vec[i];
|
||||
total += overflow;
|
||||
|
||||
ccprintf(stream, "%-42s", name + ".start_dist");
|
||||
if (PrintDescriptions && !desc.empty())
|
||||
ccprintf(stream, " # %s", desc);
|
||||
stream << endl;
|
||||
|
||||
PrintOne(stream, total, name + ".samples", blank, precision, flags);
|
||||
PrintOne(stream, min_val, name + ".min_value", blank, precision, flags);
|
||||
|
||||
if (underflow > 0)
|
||||
PrintOne(stream, min_val, name + ".underflows", blank, precision,
|
||||
flags);
|
||||
|
||||
int _min;
|
||||
result_t _pdf, _cdf, mypdf, mycdf;
|
||||
|
||||
_cdf = 0.0;
|
||||
for (int i = 0; i < size; ++i) {
|
||||
if (flags & nozero && vec[i] == 0.0 ||
|
||||
flags & nonan && isnan(vec[i]))
|
||||
return;
|
||||
|
||||
_min = i * bucket_size + min;
|
||||
_pdf = vec[i] / total * 100.0;
|
||||
_cdf += _pdf;
|
||||
|
||||
mypdf = (flags & pdf) ? _pdf : NAN;
|
||||
mycdf = (flags & cdf) ? _cdf : NAN;
|
||||
|
||||
PrintOne(stream, vec[i], ValueToString(_min, 0), blank, precision,
|
||||
flags | __substat, mypdf, mycdf);
|
||||
}
|
||||
|
||||
if (overflow > 0)
|
||||
PrintOne(stream, overflow, name + ".overflows", blank, precision,
|
||||
flags);
|
||||
PrintOne(stream, max_val, name + ".max_value", blank, precision, flags);
|
||||
ccprintf(stream, "%s.end_dist\n\n", name);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
FancyDisplay(ostream &stream, const string &name, const string &desc,
|
||||
int precision, FormatFlags flags, result_t mean,
|
||||
result_t variance)
|
||||
{
|
||||
result_t stdev = isnan(variance) ? NAN : sqrt(variance);
|
||||
PrintOne(stream, mean, name + NAMESEP + "mean", desc, precision, flags);
|
||||
PrintOne(stream, stdev, name + NAMESEP + "stdev", desc, precision, flags);
|
||||
}
|
||||
|
||||
BinBase::BinBase(size_t size)
|
||||
: memsize(CeilPow2(size)), mem(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
BinBase::~BinBase()
|
||||
{
|
||||
if (mem)
|
||||
delete [] mem;
|
||||
}
|
||||
|
||||
char *
|
||||
BinBase::memory()
|
||||
{
|
||||
if (!mem) {
|
||||
mem = new char[memsize];
|
||||
memset(mem, 0, memsize);
|
||||
}
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
} // namespace Detail
|
||||
|
||||
void
|
||||
check()
|
||||
{
|
||||
Detail::StatDB().check();
|
||||
}
|
||||
|
||||
void
|
||||
dump(ostream &stream)
|
||||
{
|
||||
Detail::StatDB().dump(stream);
|
||||
}
|
||||
|
||||
} // namespace Statistics
|
1682
base/statistics.hh
Normal file
1682
base/statistics.hh
Normal file
File diff suppressed because it is too large
Load diff
332
base/str.cc
Normal file
332
base/str.cc
Normal file
|
@ -0,0 +1,332 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "intmath.h"
|
||||
#include "str.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
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 (ignore) {
|
||||
if (last == first) {
|
||||
while (last == first)
|
||||
last = s.find_first_of(token, ++first);
|
||||
|
||||
if (last == string::npos) {
|
||||
v.push_back(s);
|
||||
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));
|
||||
}
|
||||
|
||||
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 T hexmax = maxnum & (((T)1 << (sizeof(T) * 8 - 4)) - 1);
|
||||
static const T octmax = maxnum & (((T)1 << (sizeof(T) * 8 - 3)) - 1);
|
||||
static const T signmax =
|
||||
(sign) ? maxnum & (((T)1 << (sizeof(T) * 8 - 1)) - 1) : maxnum;
|
||||
static const T decmax = signmax / 10 - 1;
|
||||
|
||||
#if 0
|
||||
cout << "maxnum = 0x" << hex << maxnum << "\n"
|
||||
<< "sign = 0x" << hex << sign << "\n"
|
||||
<< "hexmax = 0x" << hex << hexmax << "\n"
|
||||
<< "octmax = 0x" << hex << octmax << "\n"
|
||||
<< "signmax = 0x" << hex << signmax << "\n"
|
||||
<< "decmax = 0x" << hex << 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;
|
||||
retval *= 10;
|
||||
retval += c - '0';
|
||||
if (sign && (retval & ((T)1 << (sizeof(T) * 8 - 1))))
|
||||
return false;
|
||||
}
|
||||
|
||||
c = value[last];
|
||||
if (IsDec(c)) {
|
||||
|
||||
if (retval > decmax) return false;
|
||||
retval *= 10;
|
||||
retval += c - '0';
|
||||
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;
|
||||
}
|
127
base/str.hh
Normal file
127
base/str.hh
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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;
|
||||
}
|
||||
|
||||
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>
|
||||
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__
|
133
base/symtab.cc
Normal file
133
base/symtab.cc
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "host.hh"
|
||||
#include "misc.hh"
|
||||
#include "str.hh"
|
||||
#include "symtab.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool
|
||||
SymbolTable::insert(Addr address, string symbol)
|
||||
{
|
||||
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) {
|
||||
cerr << "Can't open symbol table file " << filename << endl;
|
||||
fatal("file error");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool
|
||||
SymbolTable::findSymbol(Addr address, string &symbol) const
|
||||
{
|
||||
ATable::const_iterator i = addrTable.find(address);
|
||||
if (i == addrTable.end())
|
||||
return false;
|
||||
|
||||
symbol = (*i).second;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SymbolTable::findAddress(const string &symbol, Addr &address) const
|
||||
{
|
||||
STable::const_iterator i = symbolTable.find(symbol);
|
||||
if (i == symbolTable.end())
|
||||
return false;
|
||||
|
||||
address = (*i).second;
|
||||
return true;
|
||||
}
|
||||
|
||||
string
|
||||
SymbolTable::find(Addr addr) const
|
||||
{
|
||||
string s;
|
||||
findSymbol(addr, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
Addr
|
||||
SymbolTable::find(const string &symbol) const
|
||||
{
|
||||
Addr a = 0;
|
||||
findAddress(symbol, a);
|
||||
return a;
|
||||
}
|
59
base/symtab.hh
Normal file
59
base/symtab.hh
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "hashmap.hh"
|
||||
#include "isa_traits.hh" // for Addr
|
||||
|
||||
class SymbolTable
|
||||
{
|
||||
private:
|
||||
typedef m5::hash_map<Addr, std::string> ATable;
|
||||
typedef m5::hash_map<std::string, Addr> STable;
|
||||
|
||||
ATable addrTable;
|
||||
STable symbolTable;
|
||||
|
||||
public:
|
||||
SymbolTable() {}
|
||||
SymbolTable(const std::string &file) { load(file); }
|
||||
~SymbolTable() {}
|
||||
|
||||
bool insert(Addr address, std::string symbol);
|
||||
bool load(const std::string &file);
|
||||
|
||||
bool findSymbol(Addr address, std::string &symbol) const;
|
||||
bool findAddress(const std::string &symbol, Addr &address) const;
|
||||
|
||||
std::string find(Addr addr) const;
|
||||
Addr find(const std::string &symbol) const;
|
||||
};
|
||||
|
||||
#endif // __SYMTAB_HH__
|
325
base/trace.cc
Normal file
325
base/trace.cc
Normal file
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "misc.hh"
|
||||
#include "trace.hh"
|
||||
#include "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 = NULL;
|
||||
|
||||
int dprintf_ignore_size;
|
||||
vector<string> dprintf_ignore;
|
||||
vector<vector<string> > ignore_tokens;
|
||||
vector<int> ignore_size;
|
||||
|
||||
bool
|
||||
dprintf_ignore_name(const string &name)
|
||||
{
|
||||
vector<string> name_tokens;
|
||||
tokenize(name_tokens, name, '.');
|
||||
int ntsize = name_tokens.size();
|
||||
|
||||
for (int i = 0; i < dprintf_ignore_size; ++i) {
|
||||
bool match = true;
|
||||
int jstop = ignore_size[i];
|
||||
for (int j = 0; j < jstop; ++j) {
|
||||
if (j >= ntsize)
|
||||
break;
|
||||
|
||||
const string &ignore = ignore_tokens[i][j];
|
||||
if (ignore != "*" && ignore != name_tokens[j]) {
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (match == true)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
RawDataRecord::RawDataRecord(Tick _cycle,
|
||||
const uint8_t *_data, int _len)
|
||||
: Record(_cycle), len(_len)
|
||||
{
|
||||
data = new uint8_t[len];
|
||||
memcpy(data, _data, len);
|
||||
}
|
||||
|
||||
|
||||
RawDataRecord::~RawDataRecord()
|
||||
{
|
||||
delete [] data;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RawDataRecord::dump(ostream &os)
|
||||
{
|
||||
int c, i, j;
|
||||
|
||||
for (i = 0; i < len; i += 16) {
|
||||
ccprintf(os, "%08x ", 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()
|
||||
{
|
||||
if (Trace::dprintf_stream)
|
||||
return *Trace::dprintf_stream;
|
||||
else
|
||||
return cerr;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
218
base/trace.hh
Normal file
218
base/trace.hh
Normal file
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 __TRACE_HH__
|
||||
#define __TRACE_HH__
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "cprintf.hh"
|
||||
#include "host.hh"
|
||||
#include "universe.hh"
|
||||
|
||||
#ifndef TRACING_ON
|
||||
#ifdef DEBUG
|
||||
#define TRACING_ON 1
|
||||
#else
|
||||
#define TRACING_ON 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "trace_flags.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 RawDataRecord : public Record
|
||||
{
|
||||
private:
|
||||
uint8_t *data;
|
||||
int len;
|
||||
|
||||
public:
|
||||
RawDataRecord(Tick cycle, const uint8_t *_data, int _len);
|
||||
virtual ~RawDataRecord();
|
||||
|
||||
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 int dprintf_ignore_size;
|
||||
|
||||
bool
|
||||
dprintf_ignore_name(const std::string &name);
|
||||
|
||||
inline void
|
||||
dprintf(const char *format, cp::ArgList &args, Tick cycle,
|
||||
const std::string &name)
|
||||
{
|
||||
if (!dprintf_ignore_size || name.empty() || !dprintf_ignore_name(name))
|
||||
theLog.append(new Trace::PrintfRecord(format, args, cycle, name));
|
||||
}
|
||||
|
||||
inline void
|
||||
rawDump(const uint8_t *data, int len)
|
||||
{
|
||||
theLog.append(new Trace::RawDataRecord(curTick, data, len));
|
||||
}
|
||||
|
||||
extern const std::string DefaultName;
|
||||
};
|
||||
|
||||
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 { \
|
||||
using namespace Trace; \
|
||||
if (Trace::IsOn(Trace::x)) \
|
||||
rawDump(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, string(), args, cp::ArgListNull()); \
|
||||
} while (0)
|
||||
|
||||
#define DPRINTFN(args...) \
|
||||
do { \
|
||||
__dprintf(curTick, name(), 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 DDUMP(x, data, count) do {} while(0)
|
||||
|
||||
#endif // TRACING_ON
|
||||
|
||||
#endif // __TRACE_HH__
|
79
dev/alpha_access.h
Normal file
79
dev/alpha_access.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 __ALPHA_ACCESS_H__
|
||||
#define __ALPHA_ACCESS_H__
|
||||
|
||||
/* @file
|
||||
* System Console Memory Mapped Register Definition
|
||||
*/
|
||||
|
||||
#define ALPHA_ACCESS_VERSION (1291+1) /* CH++*/
|
||||
|
||||
#ifdef CONSOLE
|
||||
typedef uint32 UINT32;
|
||||
typedef uint64 UINT64;
|
||||
#else
|
||||
typedef uint32_t UINT32;
|
||||
typedef uint64_t UINT64;
|
||||
#endif
|
||||
|
||||
// This structure hacked up from simos
|
||||
struct AlphaAccess
|
||||
{
|
||||
UINT32 last_offset; // 00: must be first field
|
||||
UINT32 version; // 04:
|
||||
UINT32 numCPUs; // 08:
|
||||
UINT32 align0; // 0C: Placeholder for alignment
|
||||
UINT64 mem_size; // 10:
|
||||
UINT64 cpuClock; // 18: MHz
|
||||
UINT32 intrClockFrequency; // 20: Hz
|
||||
UINT32 align1; // 24: Placeholder for alignment
|
||||
|
||||
// Loaded kernel
|
||||
UINT64 kernStart; // 28:
|
||||
UINT64 kernEnd; // 30:
|
||||
UINT64 entryPoint; // 38:
|
||||
|
||||
// console disk stuff
|
||||
UINT64 diskUnit; // 40:
|
||||
UINT64 diskCount; // 48:
|
||||
UINT64 diskPAddr; // 50:
|
||||
UINT64 diskBlock; // 58:
|
||||
UINT64 diskOperation; // 60:
|
||||
|
||||
// console simple output stuff
|
||||
UINT64 outputChar; // 68:
|
||||
|
||||
// MP boot
|
||||
UINT64 bootStrapImpure; // 70:
|
||||
UINT32 bootStrapCPU; // 78:
|
||||
UINT32 align2; // 7C: Dummy placeholder for alignment
|
||||
};
|
||||
|
||||
#endif // __ALPHA_ACCESS_H__
|
273
dev/alpha_console.cc
Normal file
273
dev/alpha_console.cc
Normal file
|
@ -0,0 +1,273 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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
|
||||
* System Console Definition
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "alpha_console.hh"
|
||||
#include "base_cpu.hh"
|
||||
#include "console.hh"
|
||||
#include "exec_context.hh"
|
||||
#include "memory_control.hh"
|
||||
#include "simple_disk.hh"
|
||||
#include "tlaser_clock.hh"
|
||||
#include "system.hh"
|
||||
#include "trace.hh"
|
||||
#include "inifile.hh"
|
||||
#include "str.hh" // for to_number()
|
||||
|
||||
using namespace std;
|
||||
|
||||
AlphaConsole::AlphaConsole(const string &name, SimConsole *cons,
|
||||
SimpleDisk *d, int size, System *system,
|
||||
BaseCPU *cpu, TlaserClock *clock, int num_cpus,
|
||||
Addr addr, Addr mask, MemoryController *mmu)
|
||||
: MmapDevice(name, addr, mask, mmu), disk(d), console(cons)
|
||||
{
|
||||
consoleData = new uint8_t[size];
|
||||
memset(consoleData, 0, size);
|
||||
|
||||
alphaAccess->last_offset = size - 1;
|
||||
alphaAccess->kernStart = system->getKernelStart();
|
||||
alphaAccess->kernEnd = system->getKernelEnd();
|
||||
alphaAccess->entryPoint = system->getKernelEntry();
|
||||
|
||||
alphaAccess->version = ALPHA_ACCESS_VERSION;
|
||||
alphaAccess->numCPUs = num_cpus;
|
||||
alphaAccess->mem_size = system->physmem->getSize();
|
||||
alphaAccess->cpuClock = cpu->getFreq() / 1000000;
|
||||
alphaAccess->intrClockFrequency = clock->frequency();
|
||||
|
||||
alphaAccess->diskUnit = 1;
|
||||
}
|
||||
|
||||
Fault
|
||||
AlphaConsole::read(MemReqPtr req, uint8_t *data)
|
||||
{
|
||||
memset(data, 0, req->size);
|
||||
|
||||
if (req->size == sizeof(uint32_t)) {
|
||||
Addr daddr = req->paddr & addr_mask;
|
||||
*(uint32_t *)data = *(uint32_t *)(consoleData + daddr);
|
||||
|
||||
#if 0
|
||||
DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n",
|
||||
daddr, *(uint32_t *)data);
|
||||
#endif
|
||||
}
|
||||
|
||||
return No_Fault;
|
||||
}
|
||||
|
||||
Fault
|
||||
AlphaConsole::write(MemReqPtr req, const uint8_t *data)
|
||||
{
|
||||
uint64_t val;
|
||||
|
||||
switch (req->size) {
|
||||
case sizeof(uint32_t):
|
||||
val = *(uint32_t *)data;
|
||||
break;
|
||||
case sizeof(uint64_t):
|
||||
val = *(uint64_t *)data;
|
||||
break;
|
||||
default:
|
||||
return Machine_Check_Fault;
|
||||
}
|
||||
|
||||
Addr paddr = req->paddr & addr_mask;
|
||||
|
||||
if (paddr == offsetof(AlphaAccess, diskUnit)) {
|
||||
alphaAccess->diskUnit = val;
|
||||
return No_Fault;
|
||||
}
|
||||
|
||||
if (paddr == offsetof(AlphaAccess, diskCount)) {
|
||||
alphaAccess->diskCount = val;
|
||||
return No_Fault;
|
||||
}
|
||||
|
||||
if (paddr == offsetof(AlphaAccess, diskPAddr)) {
|
||||
alphaAccess->diskPAddr = val;
|
||||
return No_Fault;
|
||||
}
|
||||
|
||||
if (paddr == offsetof(AlphaAccess, diskBlock)) {
|
||||
alphaAccess->diskBlock = val;
|
||||
return No_Fault;
|
||||
}
|
||||
|
||||
if (paddr == offsetof(AlphaAccess, diskOperation)) {
|
||||
if (val == 0x13)
|
||||
disk->read(alphaAccess->diskPAddr, alphaAccess->diskBlock,
|
||||
alphaAccess->diskCount);
|
||||
else
|
||||
panic("Invalid disk operation!");
|
||||
|
||||
return No_Fault;
|
||||
}
|
||||
|
||||
if (paddr == offsetof(AlphaAccess, outputChar)) {
|
||||
console->simple((char)(val & 0xff));
|
||||
return No_Fault;
|
||||
}
|
||||
|
||||
if (paddr == offsetof(AlphaAccess, bootStrapImpure)) {
|
||||
alphaAccess->bootStrapImpure = val;
|
||||
return No_Fault;
|
||||
}
|
||||
|
||||
if (paddr == offsetof(AlphaAccess, bootStrapCPU)) {
|
||||
warn("%d: Trying to launch another CPU!", curTick);
|
||||
int cpu = val;
|
||||
assert(cpu > 0 && "Must not access primary cpu");
|
||||
|
||||
ExecContext *other_xc = req->xc->system->xc_array[cpu];
|
||||
other_xc->regs.intRegFile[16] = cpu;
|
||||
other_xc->regs.ipr[TheISA::IPR_PALtemp16] = cpu;
|
||||
other_xc->regs.intRegFile[0] = cpu;
|
||||
other_xc->regs.intRegFile[30] = alphaAccess->bootStrapImpure;
|
||||
other_xc->setStatus(ExecContext::Active); //Start the cpu
|
||||
return No_Fault;
|
||||
}
|
||||
|
||||
return No_Fault;
|
||||
}
|
||||
|
||||
void
|
||||
AlphaConsole::serialize()
|
||||
{
|
||||
nameOut();
|
||||
// assumes full AlphaAccess size
|
||||
// might have unnecessary fields here
|
||||
paramOut("last_offset",alphaAccess->last_offset);
|
||||
paramOut("version",alphaAccess->version);
|
||||
paramOut("numCPUs",alphaAccess->numCPUs);
|
||||
paramOut("mem_size",alphaAccess->mem_size);
|
||||
paramOut("cpuClock",alphaAccess->cpuClock);
|
||||
paramOut("intrClockFrequency",alphaAccess->intrClockFrequency);
|
||||
paramOut("kernStart",alphaAccess->kernStart);
|
||||
paramOut("kernEnd",alphaAccess->kernEnd);
|
||||
paramOut("entryPoint",alphaAccess->entryPoint);
|
||||
paramOut("diskUnit",alphaAccess->diskUnit);
|
||||
paramOut("diskCount",alphaAccess->diskCount);
|
||||
paramOut("diskPAddr",alphaAccess->diskPAddr);
|
||||
paramOut("diskBlock",alphaAccess->diskBlock);
|
||||
paramOut("diskOperation",alphaAccess->diskOperation);
|
||||
paramOut("outputChar",alphaAccess->outputChar);
|
||||
paramOut("bootStrapImpure",alphaAccess->bootStrapImpure);
|
||||
paramOut("bootStrapCPU",alphaAccess->bootStrapCPU);
|
||||
}
|
||||
|
||||
void
|
||||
AlphaConsole::unserialize(IniFile &db, const std::string &category,
|
||||
ConfigNode *node)
|
||||
{
|
||||
string data;
|
||||
db.findDefault(category,"last_offset",data);
|
||||
to_number(data,alphaAccess->last_offset);
|
||||
db.findDefault(category,"version",data);
|
||||
to_number(data,alphaAccess->version);
|
||||
db.findDefault(category,"numCPUs",data);
|
||||
to_number(data,alphaAccess->numCPUs);
|
||||
db.findDefault(category,"mem_size",data);
|
||||
to_number(data,alphaAccess->mem_size);
|
||||
db.findDefault(category,"cpuClock",data);
|
||||
to_number(data,alphaAccess->cpuClock);
|
||||
db.findDefault(category,"intrClockFrequency",data);
|
||||
to_number(data,alphaAccess->intrClockFrequency);
|
||||
db.findDefault(category,"kernStart",data);
|
||||
to_number(data,alphaAccess->kernStart);
|
||||
db.findDefault(category,"kernEnd",data);
|
||||
to_number(data,alphaAccess->kernEnd);
|
||||
db.findDefault(category,"entryPoint",data);
|
||||
to_number(data,alphaAccess->entryPoint);
|
||||
db.findDefault(category,"diskUnit",data);
|
||||
to_number(data,alphaAccess->diskUnit);
|
||||
db.findDefault(category,"diskCount",data);
|
||||
to_number(data,alphaAccess->diskCount);
|
||||
db.findDefault(category,"diskPAddr",data);
|
||||
to_number(data,alphaAccess->diskPAddr);
|
||||
db.findDefault(category,"diskBlock",data);
|
||||
to_number(data,alphaAccess->diskBlock);
|
||||
db.findDefault(category,"diskOperation",data);
|
||||
to_number(data,alphaAccess->diskOperation);
|
||||
db.findDefault(category,"outputChar",data);
|
||||
to_number(data,alphaAccess->outputChar);
|
||||
db.findDefault(category,"bootStrapImpure",data);
|
||||
to_number(data,alphaAccess->bootStrapImpure);
|
||||
db.findDefault(category,"bootStrapCPU",data);
|
||||
to_number(data,alphaAccess->bootStrapCPU);
|
||||
|
||||
}
|
||||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
|
||||
|
||||
SimObjectParam<SimConsole *> sim_console;
|
||||
SimObjectParam<SimpleDisk *> disk;
|
||||
Param<int> size;
|
||||
Param<int> num_cpus;
|
||||
SimObjectParam<MemoryController *> mmu;
|
||||
Param<Addr> addr;
|
||||
Param<Addr> mask;
|
||||
SimObjectParam<System *> system;
|
||||
SimObjectParam<BaseCPU *> cpu;
|
||||
SimObjectParam<TlaserClock *> clock;
|
||||
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
|
||||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaConsole)
|
||||
|
||||
INIT_PARAM(sim_console, "The Simulator Console"),
|
||||
INIT_PARAM(disk, "Simple Disk"),
|
||||
INIT_PARAM_DFLT(size, "AlphaConsole size", sizeof(AlphaAccess)),
|
||||
INIT_PARAM_DFLT(num_cpus, "Number of CPU's", 1),
|
||||
INIT_PARAM(mmu, "Memory Controller"),
|
||||
INIT_PARAM(addr, "Device Address"),
|
||||
INIT_PARAM(mask, "Address Mask"),
|
||||
INIT_PARAM(system, "system object"),
|
||||
INIT_PARAM(cpu, "Processor"),
|
||||
INIT_PARAM(clock, "Turbolaser Clock")
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(AlphaConsole)
|
||||
|
||||
CREATE_SIM_OBJECT(AlphaConsole)
|
||||
{
|
||||
return new AlphaConsole(getInstanceName(), sim_console,
|
||||
disk, size, system,
|
||||
cpu, clock, num_cpus,
|
||||
addr, mask, mmu);
|
||||
}
|
||||
|
||||
REGISTER_SIM_OBJECT("AlphaConsole", AlphaConsole)
|
108
dev/alpha_console.hh
Normal file
108
dev/alpha_console.hh
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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
|
||||
* System Console Interface
|
||||
*/
|
||||
|
||||
#ifndef __ALPHA_CONSOLE_HH__
|
||||
#define __ALPHA_CONSOLE_HH__
|
||||
|
||||
#include "host.hh"
|
||||
#include "alpha_access.h"
|
||||
#include "mmap_device.hh"
|
||||
|
||||
class BaseCPU;
|
||||
class SimConsole;
|
||||
class System;
|
||||
class TlaserClock;
|
||||
class SimpleDisk;
|
||||
|
||||
/*
|
||||
* Memory mapped interface to the system console. This device
|
||||
* represents a shared data region between the OS Kernel and the
|
||||
* System Console.
|
||||
*
|
||||
* The system console is a small standalone program that is initially
|
||||
* run when the system boots. It contains the necessary code to
|
||||
* access the boot disk, to read/write from the console, and to pass
|
||||
* boot parameters to the kernel.
|
||||
*
|
||||
* This version of the system console is very different from the one
|
||||
* that would be found in a real system. Many of the functions use
|
||||
* some sort of backdoor to get their job done. For example, reading
|
||||
* from the boot device on a real system would require a minimal
|
||||
* device driver to access the disk controller, but since we have a
|
||||
* simulator here, we are able to bypass the disk controller and
|
||||
* access the disk image directly. There are also some things like
|
||||
* reading the kernel off the disk image into memory that are normally
|
||||
* taken care of by the console that are now taken care of by the
|
||||
* simulator.
|
||||
*
|
||||
* These shortcuts are acceptable since the system console is
|
||||
* primarily used doing boot before the kernel has loaded its device
|
||||
* drivers.
|
||||
*/
|
||||
class AlphaConsole : public MmapDevice
|
||||
{
|
||||
protected:
|
||||
union {
|
||||
AlphaAccess *alphaAccess;
|
||||
uint8_t *consoleData;
|
||||
};
|
||||
|
||||
/** the disk must be accessed from the console */
|
||||
SimpleDisk *disk;
|
||||
|
||||
/** the system console (the terminal) is accessable from the console */
|
||||
SimConsole *console;
|
||||
|
||||
public:
|
||||
/** Standard Constructor */
|
||||
AlphaConsole(const std::string &name, SimConsole *cons,
|
||||
SimpleDisk *d, int size,
|
||||
System *system, BaseCPU *cpu,
|
||||
TlaserClock *clock, int num_cpus,
|
||||
Addr addr, Addr mask, MemoryController *mmu);
|
||||
|
||||
public:
|
||||
/**
|
||||
* memory mapped reads and writes
|
||||
*/
|
||||
virtual Fault read(MemReqPtr req, uint8_t *data);
|
||||
virtual Fault write(MemReqPtr req, const uint8_t *data);
|
||||
|
||||
/**
|
||||
* standard serialization routines for checkpointing
|
||||
*/
|
||||
virtual void serialize();
|
||||
virtual void unserialize(IniFile &db, const std::string &category,
|
||||
ConfigNode *node);
|
||||
};
|
||||
|
||||
#endif // __ALPHA_CONSOLE_HH__
|
478
dev/console.cc
Normal file
478
dev/console.cc
Normal file
|
@ -0,0 +1,478 @@
|
|||
/* $Id$ */
|
||||
|
||||
/* @file
|
||||
* User Console Definitions
|
||||
*/
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/termios.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "misc.hh"
|
||||
#include "ev5.hh"
|
||||
|
||||
#include "console.hh"
|
||||
#include "socket.hh"
|
||||
#include "trace.hh"
|
||||
#include "memory_control.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// check whether an int is pending
|
||||
inline bool
|
||||
IntPending(int status, int mask)
|
||||
{ return (status & mask) != 0; }
|
||||
|
||||
inline bool
|
||||
IntTransition(int ostaus, int omask, int nstatus, int nmask)
|
||||
{ return IntPending(ostaus, omask) != IntPending(nstatus, nmask); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
|
||||
SimConsole::Event::Event(SimConsole *c, int fd, int e)
|
||||
: PollEvent(fd, e), cons(c)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SimConsole::Event::process(int revent)
|
||||
{
|
||||
if (revent & POLLIN)
|
||||
cons->data();
|
||||
else if (revent & POLLNVAL)
|
||||
cons->detach();
|
||||
}
|
||||
|
||||
SimConsole::SimConsole(const string &name, const string &file, int num)
|
||||
: SimObject(name), event(NULL), number(num), in_fd(-1), out_fd(-1),
|
||||
listener(NULL), txbuf(16384), rxbuf(16384), outfile(NULL),
|
||||
intr_status(0), intr_enable(0), intr(NULL)
|
||||
{
|
||||
if (!file.empty())
|
||||
outfile = new ofstream(file.c_str());
|
||||
|
||||
if (outfile)
|
||||
outfile->setf(ios::unitbuf);
|
||||
}
|
||||
|
||||
SimConsole::~SimConsole()
|
||||
{
|
||||
close();
|
||||
|
||||
if (outfile)
|
||||
delete outfile;
|
||||
}
|
||||
|
||||
void
|
||||
SimConsole::close()
|
||||
{
|
||||
if (in_fd != -1)
|
||||
::close(in_fd);
|
||||
|
||||
if (out_fd != in_fd && out_fd != -1)
|
||||
::close(out_fd);
|
||||
}
|
||||
|
||||
void
|
||||
SimConsole::attach(int in, int out, ConsoleListener *l)
|
||||
{
|
||||
in_fd = in;
|
||||
out_fd = out;
|
||||
listener = l;
|
||||
|
||||
event = new Event(this, in, POLLIN);
|
||||
pollQueue.schedule(event);
|
||||
|
||||
stringstream stream;
|
||||
ccprintf(stream, "==== Simplescalar slave console: Console %d ====",
|
||||
number);
|
||||
// we need an actual carriage return followed by a newline for the
|
||||
// terminal
|
||||
stream << "\r\n";
|
||||
|
||||
write((const uint8_t *)stream.str().c_str(), stream.str().size());
|
||||
|
||||
|
||||
DPRINTFN("attach console %d\n", number);
|
||||
|
||||
txbuf.readall(out);
|
||||
}
|
||||
|
||||
void
|
||||
SimConsole::detach()
|
||||
{
|
||||
close();
|
||||
in_fd = -1;
|
||||
out_fd = -1;
|
||||
|
||||
pollQueue.remove(event);
|
||||
|
||||
if (listener) {
|
||||
listener->add(this);
|
||||
listener = NULL;
|
||||
}
|
||||
|
||||
DPRINTFN("detach console %d\n", number);
|
||||
}
|
||||
|
||||
void
|
||||
SimConsole::data()
|
||||
{
|
||||
uint8_t buf[1024];
|
||||
int len;
|
||||
|
||||
len = read(buf, sizeof(buf));
|
||||
if (len) {
|
||||
rxbuf.write((char *)buf, len);
|
||||
raiseInt(ReceiveInterrupt);
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
SimConsole::read(uint8_t *buf, size_t len)
|
||||
{
|
||||
if (in_fd < 0)
|
||||
panic("SimConsole(read): Console not properly attached.\n");
|
||||
|
||||
size_t ret;
|
||||
do {
|
||||
ret = ::read(in_fd, buf, len);
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
|
||||
|
||||
if (ret < 0)
|
||||
DPRINTFN("SimConsole(read): Read failed.\n");
|
||||
|
||||
if (ret <= 0) {
|
||||
detach();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Console output.
|
||||
size_t
|
||||
SimConsole::write(const uint8_t *buf, size_t len)
|
||||
{
|
||||
if (out_fd < 0)
|
||||
panic("SimConsole(write): Console not properly attached.\n");
|
||||
|
||||
size_t ret;
|
||||
for (;;) {
|
||||
ret = ::write(out_fd, buf, len);
|
||||
|
||||
if (ret >= 0)
|
||||
break;
|
||||
|
||||
if (errno != EINTR)
|
||||
detach();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// ConfigureTerm turns off all character processing by the host OS so
|
||||
// the launched OS can control it.
|
||||
//
|
||||
// We ignore anything except stdin; the sconsole program runs this
|
||||
// same code on the ttys for the slave consoles before connecting.
|
||||
//
|
||||
void
|
||||
SimConsole::configTerm()
|
||||
{
|
||||
struct termios ios;
|
||||
|
||||
if (isatty(out_fd)) {
|
||||
if (tcgetattr(out_fd, &ios) < 0) {
|
||||
panic( "tcgetattr\n");
|
||||
}
|
||||
ios.c_iflag &= ~(ISTRIP|ICRNL|IGNCR|ICRNL|IXOFF|IXON);
|
||||
ios.c_oflag &= ~(OPOST);
|
||||
ios.c_oflag &= (ONLCR);
|
||||
ios.c_lflag &= ~(ISIG|ICANON|ECHO);
|
||||
ios.c_cc[VMIN] = 1;
|
||||
ios.c_cc[VTIME] = 0;
|
||||
if (tcsetattr(out_fd, TCSANOW, &ios) < 0) {
|
||||
panic( "tcsetattr\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// console i/o
|
||||
//
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Console input.
|
||||
// Returns -1 if there is no character pending, otherwise returns the
|
||||
// char. Calling this function clears the input int (if no further
|
||||
// chars are pending).
|
||||
//
|
||||
int
|
||||
SimConsole::in()
|
||||
{
|
||||
if (rxbuf.empty()) {
|
||||
clearInt(ReceiveInterrupt);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char c;
|
||||
rxbuf.read(&c, 1);
|
||||
|
||||
DPRINTF(Console, "in: \'%c\' %#02x status: %#x\n",
|
||||
isprint(c) ? c : ' ', c, intr_status);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Console output.
|
||||
// NOTE: this very rudimentary device generates a TX int as soon as
|
||||
// a character is output, since it has unlimited TX buffer capacity.
|
||||
//
|
||||
// Console output.
|
||||
// Uses sim_console_out to perform functionality similar to 'write'
|
||||
void
|
||||
SimConsole::out(char c)
|
||||
{
|
||||
txbuf.write(c);
|
||||
|
||||
if (out_fd >= 0)
|
||||
write(c);
|
||||
|
||||
if (outfile)
|
||||
outfile->write(&c, 1);
|
||||
|
||||
raiseInt(TransmitInterrupt);
|
||||
|
||||
DPRINTF(Console, "out: \'%c\' %#02x status: %#x\n",
|
||||
isprint(c) ? c : ' ', (int)c, intr_status);
|
||||
}
|
||||
|
||||
// Simple console output used by Alpha firmware (not by the OS) -
|
||||
// outputs the character to console n, and doesn't raise any
|
||||
// interrupts
|
||||
void
|
||||
SimConsole::simple(char c)
|
||||
{
|
||||
txbuf.write(c);
|
||||
|
||||
if (out_fd >= 0)
|
||||
write(c);
|
||||
|
||||
if (outfile)
|
||||
outfile->write(&c, 1);
|
||||
|
||||
DPRINTF(Console, "simple char: \'%c\' %#02x\n",
|
||||
isprint(c) ? c : ' ', (int)c);
|
||||
}
|
||||
|
||||
// Read the current interrupt status of this console.
|
||||
int
|
||||
SimConsole::intStatus()
|
||||
{
|
||||
#if 0
|
||||
DPRINTF(Console, "interrupt %d status: %#x\n",
|
||||
number, intr_status);
|
||||
#endif
|
||||
|
||||
return intr_status;
|
||||
}
|
||||
|
||||
int
|
||||
SimConsole::clearInt(int i)
|
||||
{
|
||||
int old_status = intr_status;
|
||||
intr_status &= ~i;
|
||||
if (IntTransition(old_status, intr_enable, intr_status, intr_enable) &&
|
||||
intr)
|
||||
intr->clear(TheISA::INTLEVEL_IRQ0);
|
||||
return old_status;
|
||||
}
|
||||
|
||||
void
|
||||
SimConsole::raiseInt(int i)
|
||||
{
|
||||
int old = intr_status;
|
||||
intr_status |= i;
|
||||
if (IntTransition(old, intr_enable, intr_status, intr_enable) && intr)
|
||||
intr->post(TheISA::INTLEVEL_IRQ0);
|
||||
}
|
||||
|
||||
void
|
||||
SimConsole::initInt(IntrControl *i)
|
||||
{
|
||||
if (intr)
|
||||
panic("Console has already been initialized.");
|
||||
|
||||
// note: intr_status and intr_enable will normally be 0, since
|
||||
// cs is statically allocated. When restoring from a checkpoint,
|
||||
// these fields will be set, so don't touch them here.
|
||||
intr = i; // interrupt handler
|
||||
}
|
||||
|
||||
// Set the interrupt enable bits.
|
||||
void
|
||||
SimConsole::setInt(int bits)
|
||||
{
|
||||
int old_enable;
|
||||
|
||||
if (bits & ~(TransmitInterrupt | ReceiveInterrupt))
|
||||
panic("An interrupt was not set!");
|
||||
|
||||
old_enable = intr_enable;
|
||||
intr_enable |= bits;
|
||||
|
||||
if (IntTransition(intr_status, old_enable, intr_status, intr_enable) &&
|
||||
intr) {
|
||||
if (IntPending(intr_status, intr_enable))
|
||||
intr->post(TheISA::INTLEVEL_IRQ0);
|
||||
else
|
||||
intr->clear(TheISA::INTLEVEL_IRQ0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SimConsole::serialize()
|
||||
{
|
||||
panic("Unimplemented");
|
||||
}
|
||||
|
||||
void
|
||||
SimConsole::unserialize(IniFile &db, const std::string &category,
|
||||
ConfigNode *node)
|
||||
{
|
||||
panic("Unimplemented");
|
||||
}
|
||||
|
||||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimConsole)
|
||||
|
||||
SimObjectParam<ConsoleListener *> listener;
|
||||
SimObjectParam<IntrControl *> intr_control;
|
||||
Param<string> output;
|
||||
Param<int> number;
|
||||
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(SimConsole)
|
||||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(SimConsole)
|
||||
|
||||
INIT_PARAM(listener, "console listener"),
|
||||
INIT_PARAM(intr_control, "interrupt controller"),
|
||||
INIT_PARAM_DFLT(output, "file to dump output to", ""),
|
||||
INIT_PARAM_DFLT(number, "console number", 0)
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(SimConsole)
|
||||
|
||||
CREATE_SIM_OBJECT(SimConsole)
|
||||
{
|
||||
SimConsole *console = new SimConsole(getInstanceName(), output, number);
|
||||
((ConsoleListener *)listener)->add(console);
|
||||
((SimConsole *)console)->initInt(intr_control);
|
||||
((SimConsole *)console)->setInt(SimConsole::TransmitInterrupt |
|
||||
SimConsole::ReceiveInterrupt);
|
||||
|
||||
return console;
|
||||
}
|
||||
|
||||
REGISTER_SIM_OBJECT("SimConsole", SimConsole)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
|
||||
ConsoleListener::ConsoleListener(const string &name)
|
||||
: SimObject(name), event(NULL)
|
||||
{}
|
||||
|
||||
ConsoleListener::~ConsoleListener()
|
||||
{
|
||||
if (event)
|
||||
delete event;
|
||||
}
|
||||
|
||||
void
|
||||
ConsoleListener::Event::process(int revent)
|
||||
{
|
||||
listener->accept();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// socket creation and console attach
|
||||
//
|
||||
|
||||
void
|
||||
ConsoleListener::listen(int port)
|
||||
{
|
||||
while (!listener.listen(port, true)) {
|
||||
DPRINTF(Console, ": can't bind address console port %d inuse PID %d\n",
|
||||
port, getpid());
|
||||
port++;
|
||||
}
|
||||
|
||||
cerr << "Listening for console connection on port " << port << endl;
|
||||
event = new Event(this, listener.getfd(), POLLIN);
|
||||
pollQueue.schedule(event);
|
||||
}
|
||||
|
||||
void
|
||||
ConsoleListener::add(SimConsole *cons)
|
||||
{ ConsoleList.push_back(cons);}
|
||||
|
||||
void
|
||||
ConsoleListener::accept()
|
||||
{
|
||||
if (!listener.islistening())
|
||||
panic("%s: cannot accept a connection if we're not listening!",
|
||||
name());
|
||||
|
||||
int sfd = listener.accept(true);
|
||||
if (sfd != -1) {
|
||||
iter_t i = ConsoleList.begin();
|
||||
iter_t end = ConsoleList.end();
|
||||
if (i == end) {
|
||||
close(sfd);
|
||||
} else {
|
||||
(*i)->attach(sfd, this);
|
||||
i = ConsoleList.erase(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(ConsoleListener)
|
||||
|
||||
Param<int> port;
|
||||
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(ConsoleListener)
|
||||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(ConsoleListener)
|
||||
|
||||
INIT_PARAM_DFLT(port, "listen port", 3456)
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(ConsoleListener)
|
||||
|
||||
CREATE_SIM_OBJECT(ConsoleListener)
|
||||
{
|
||||
ConsoleListener *listener = new ConsoleListener(getInstanceName());
|
||||
listener->listen(port);
|
||||
|
||||
return listener;
|
||||
}
|
||||
|
||||
REGISTER_SIM_OBJECT("ConsoleListener", ConsoleListener)
|
147
dev/console.hh
Normal file
147
dev/console.hh
Normal file
|
@ -0,0 +1,147 @@
|
|||
/* $Id$ */
|
||||
|
||||
/* @file
|
||||
* User Console Interface
|
||||
*/
|
||||
|
||||
#ifndef __CONSOLE_HH__
|
||||
#define __CONSOLE_HH__
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "circlebuf.hh"
|
||||
#include "intr_control.hh"
|
||||
#include "pollevent.hh"
|
||||
#include "socket.hh"
|
||||
#include "sim_object.hh"
|
||||
|
||||
class ConsoleListener;
|
||||
class SimConsole : public SimObject
|
||||
{
|
||||
protected:
|
||||
class Event : public PollEvent
|
||||
{
|
||||
protected:
|
||||
SimConsole *cons;
|
||||
|
||||
public:
|
||||
Event(SimConsole *c, int fd, int e);
|
||||
void process(int revent);
|
||||
};
|
||||
|
||||
friend class Event;
|
||||
Event *event;
|
||||
|
||||
protected:
|
||||
int number;
|
||||
int in_fd;
|
||||
int out_fd;
|
||||
|
||||
protected:
|
||||
ConsoleListener *listener;
|
||||
|
||||
public:
|
||||
SimConsole(const std::string &name, const std::string &file, int num);
|
||||
~SimConsole();
|
||||
|
||||
protected:
|
||||
CircleBuf txbuf;
|
||||
CircleBuf rxbuf;
|
||||
std::ostream *outfile;
|
||||
|
||||
public:
|
||||
///////////////////////
|
||||
// Terminal Interface
|
||||
|
||||
void attach(int fd, ConsoleListener *l = NULL) { attach(fd, fd, l); }
|
||||
void attach(int in, int out, ConsoleListener *l = NULL);
|
||||
void detach();
|
||||
|
||||
void data();
|
||||
|
||||
void close();
|
||||
void read(uint8_t &c) { read(&c, 1); }
|
||||
size_t read(uint8_t *buf, size_t len);
|
||||
void write(uint8_t c) { write(&c, 1); }
|
||||
size_t write(const uint8_t *buf, size_t len);
|
||||
|
||||
void configTerm();
|
||||
|
||||
protected:
|
||||
// interrupt status/enable
|
||||
int intr_status;
|
||||
int intr_enable;
|
||||
|
||||
// interrupt handle
|
||||
IntrControl *intr;
|
||||
|
||||
public:
|
||||
/////////////////
|
||||
// OS interface
|
||||
|
||||
// Input a character from the console. Returns the character (if
|
||||
// any) or -1 if there is no character pending on this console. If
|
||||
// no further characters are pending, the (input) interrupt is
|
||||
// cleared.
|
||||
int in();
|
||||
|
||||
// Output a character to the console. This never fails, as this
|
||||
// device doesn't model finite buffering capacity.
|
||||
void out(char c);
|
||||
void simple(char c);
|
||||
|
||||
enum {
|
||||
TransmitInterrupt = 1,
|
||||
ReceiveInterrupt = 2
|
||||
};
|
||||
|
||||
// Read the current interrupt status of this console.
|
||||
int intStatus();
|
||||
|
||||
// Set the interrupt enable bits.
|
||||
int clearInt(int i);
|
||||
void raiseInt(int i);
|
||||
|
||||
void initInt(IntrControl *i);
|
||||
void setInt(int bits);
|
||||
|
||||
virtual void serialize();
|
||||
virtual void unserialize(IniFile &db, const std::string &category,
|
||||
ConfigNode *node);
|
||||
};
|
||||
|
||||
class ConsoleListener : public SimObject
|
||||
{
|
||||
protected:
|
||||
class Event : public PollEvent
|
||||
{
|
||||
protected:
|
||||
ConsoleListener *listener;
|
||||
|
||||
public:
|
||||
Event(ConsoleListener *l, int fd, int e)
|
||||
: PollEvent(fd, e), listener(l) {}
|
||||
void process(int revent);
|
||||
};
|
||||
|
||||
friend class Event;
|
||||
Event *event;
|
||||
|
||||
typedef std::list<SimConsole *> list_t;
|
||||
typedef list_t::iterator iter_t;
|
||||
list_t ConsoleList;
|
||||
|
||||
protected:
|
||||
ListenSocket listener;
|
||||
|
||||
public:
|
||||
ConsoleListener(const std::string &name);
|
||||
~ConsoleListener();
|
||||
|
||||
void add(SimConsole *cons);
|
||||
|
||||
void accept();
|
||||
void listen(int port);
|
||||
};
|
||||
|
||||
#endif // __CONSOLE_HH__
|
427
dev/disk_image.cc
Normal file
427
dev/disk_image.cc
Normal file
|
@ -0,0 +1,427 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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
|
||||
* Disk Image Definitions
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include "disk_image.hh"
|
||||
#include "misc.hh"
|
||||
#include "trace.hh"
|
||||
#include "sim_exit.hh"
|
||||
#include "callback.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Raw Disk image
|
||||
//
|
||||
RawDiskImage::RawDiskImage(const string &name, const string &filename,
|
||||
bool rd_only)
|
||||
: DiskImage(name), disk_size(0)
|
||||
{ open(filename, rd_only); }
|
||||
|
||||
RawDiskImage::~RawDiskImage()
|
||||
{ close(); }
|
||||
|
||||
void
|
||||
RawDiskImage::open(const string &filename, bool rd_only)
|
||||
{
|
||||
if (!filename.empty()) {
|
||||
initialized = true;
|
||||
readonly = rd_only;
|
||||
file = filename;
|
||||
|
||||
ios::openmode mode = ios::in | ios::binary;
|
||||
if (!readonly)
|
||||
mode |= ios::out;
|
||||
stream.open(file.c_str(), mode);
|
||||
if (!stream.is_open())
|
||||
panic("Error opening %s", filename);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RawDiskImage::close()
|
||||
{
|
||||
stream.close();
|
||||
}
|
||||
|
||||
off_t
|
||||
RawDiskImage::size() const
|
||||
{
|
||||
if (disk_size == 0) {
|
||||
if (!stream.is_open())
|
||||
panic("file not open!\n");
|
||||
stream.seekg(0, ios::end);
|
||||
disk_size = stream.tellg();
|
||||
}
|
||||
|
||||
return disk_size / SectorSize;
|
||||
}
|
||||
|
||||
off_t
|
||||
RawDiskImage::read(uint8_t *data, off_t offset) const
|
||||
{
|
||||
if (!initialized)
|
||||
panic("RawDiskImage not initialized");
|
||||
|
||||
if (!stream.is_open())
|
||||
panic("file not open!\n");
|
||||
|
||||
if (stream.seekg(offset * SectorSize, ios::beg) < 0)
|
||||
panic("Could not seek to location in file");
|
||||
|
||||
off_t pos = stream.tellg();
|
||||
stream.read((char *)data, SectorSize);
|
||||
|
||||
DPRINTF(DiskImageRead, "read: offset=%d\n", (uint64_t)offset);
|
||||
DDUMP(DiskImageRead, data, SectorSize);
|
||||
|
||||
return stream.tellg() - pos;
|
||||
}
|
||||
|
||||
off_t
|
||||
RawDiskImage::write(const uint8_t *data, off_t offset)
|
||||
{
|
||||
if (!initialized)
|
||||
panic("RawDiskImage not initialized");
|
||||
|
||||
if (readonly)
|
||||
panic("Cannot write to a read only disk image");
|
||||
|
||||
if (!stream.is_open())
|
||||
panic("file not open!\n");
|
||||
|
||||
if (stream.seekp(offset * SectorSize, ios::beg) < 0)
|
||||
panic("Could not seek to location in file");
|
||||
|
||||
DPRINTF(DiskImageWrite, "write: offset=%d\n", (uint64_t)offset);
|
||||
DDUMP(DiskImageWrite, data, SectorSize);
|
||||
|
||||
off_t pos = stream.tellp();
|
||||
stream.write((const char *)data, SectorSize);
|
||||
return stream.tellp() - pos;
|
||||
}
|
||||
|
||||
DEFINE_SIM_OBJECT_CLASS_NAME("DiskImage", DiskImage)
|
||||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(RawDiskImage)
|
||||
|
||||
Param<string> image_file;
|
||||
Param<bool> read_only;
|
||||
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(RawDiskImage)
|
||||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(RawDiskImage)
|
||||
|
||||
INIT_PARAM(image_file, "disk image file"),
|
||||
INIT_PARAM_DFLT(read_only, "read only image", false)
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(RawDiskImage)
|
||||
|
||||
|
||||
CREATE_SIM_OBJECT(RawDiskImage)
|
||||
{
|
||||
return new RawDiskImage(getInstanceName(), image_file, read_only);
|
||||
}
|
||||
|
||||
REGISTER_SIM_OBJECT("RawDiskImage", RawDiskImage)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copy on Write Disk image
|
||||
//
|
||||
const int CowDiskImage::VersionMajor = 1;
|
||||
const int CowDiskImage::VersionMinor = 0;
|
||||
|
||||
CowDiskImage::CowDiskImage(const string &name, DiskImage *kid, int hash_size)
|
||||
: DiskImage(name), child(kid), table(NULL)
|
||||
{ init(hash_size); }
|
||||
|
||||
class CowDiskCallback : public Callback
|
||||
{
|
||||
private:
|
||||
CowDiskImage *image;
|
||||
|
||||
public:
|
||||
CowDiskCallback(CowDiskImage *i) : image(i) {}
|
||||
void process() { image->save(); delete this; }
|
||||
};
|
||||
|
||||
CowDiskImage::CowDiskImage(const string &name, DiskImage *kid, int hash_size,
|
||||
const string &file, bool read_only)
|
||||
: DiskImage(name), filename(file), child(kid), table(NULL)
|
||||
{
|
||||
if (!open()) {
|
||||
assert(!read_only && "why have a non-existent read only file?");
|
||||
init(hash_size);
|
||||
}
|
||||
|
||||
if (!read_only)
|
||||
registerExitCallback(new CowDiskCallback(this));
|
||||
}
|
||||
|
||||
CowDiskImage::~CowDiskImage()
|
||||
{
|
||||
SectorTable::iterator i = table->begin();
|
||||
SectorTable::iterator end = table->end();
|
||||
|
||||
while (i != end) {
|
||||
delete (*i).second;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SafeRead(ifstream &stream, void *data, int count)
|
||||
{
|
||||
stream.read((char *)data, count);
|
||||
if (!stream.is_open())
|
||||
panic("file not open");
|
||||
|
||||
if (stream.eof())
|
||||
panic("premature end-of-file");
|
||||
|
||||
if (stream.bad() || stream.fail())
|
||||
panic("error reading cowdisk image");
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
SafeRead(ifstream &stream, T &data)
|
||||
{ SafeRead(stream, &data, sizeof(data)); }
|
||||
|
||||
bool
|
||||
CowDiskImage::open()
|
||||
{
|
||||
ifstream stream(filename.c_str());
|
||||
if (!stream.is_open())
|
||||
return false;
|
||||
|
||||
if (stream.fail() || stream.bad())
|
||||
panic("Error opening %s", filename);
|
||||
|
||||
uint64_t magic;
|
||||
SafeRead(stream, magic);
|
||||
|
||||
if (memcmp(&magic, "COWDISK!", sizeof(magic)) != 0)
|
||||
panic("Could not open %s: Invalid magic", filename);
|
||||
|
||||
uint32_t major, minor;
|
||||
SafeRead(stream, major);
|
||||
SafeRead(stream, minor);
|
||||
|
||||
if (major != VersionMajor && minor != VersionMinor)
|
||||
panic("Could not open %s: invalid version %d.%d != %d.%d",
|
||||
filename, major, minor, VersionMajor, VersionMinor);
|
||||
|
||||
uint64_t sector_count;
|
||||
SafeRead(stream, sector_count);
|
||||
table = new SectorTable(sector_count);
|
||||
|
||||
|
||||
for (uint64_t i = 0; i < sector_count; i++) {
|
||||
uint64_t offset;
|
||||
SafeRead(stream, offset);
|
||||
|
||||
Sector *sector = new Sector;
|
||||
SafeRead(stream, sector, sizeof(Sector));
|
||||
|
||||
assert(table->find(offset) == table->end());
|
||||
(*table)[offset] = sector;
|
||||
}
|
||||
|
||||
stream.close();
|
||||
|
||||
initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CowDiskImage::init(int hash_size)
|
||||
{
|
||||
table = new SectorTable(hash_size);
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
void
|
||||
SafeWrite(ofstream &stream, const void *data, int count)
|
||||
{
|
||||
stream.write((const char *)data, count);
|
||||
if (!stream.is_open())
|
||||
panic("file not open");
|
||||
|
||||
if (stream.eof())
|
||||
panic("premature end-of-file");
|
||||
|
||||
if (stream.bad() || stream.fail())
|
||||
panic("error reading cowdisk image");
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
SafeWrite(ofstream &stream, const T &data)
|
||||
{ SafeWrite(stream, &data, sizeof(data)); }
|
||||
|
||||
void
|
||||
CowDiskImage::save()
|
||||
{
|
||||
if (!initialized)
|
||||
panic("RawDiskImage not initialized");
|
||||
|
||||
ofstream stream(filename.c_str());
|
||||
if (!stream.is_open() || stream.fail() || stream.bad())
|
||||
panic("Error opening %s", filename);
|
||||
|
||||
uint64_t magic;
|
||||
memcpy(&magic, "COWDISK!", sizeof(magic));
|
||||
SafeWrite(stream, magic);
|
||||
|
||||
SafeWrite(stream, (uint32_t)VersionMajor);
|
||||
SafeWrite(stream, (uint32_t)VersionMinor);
|
||||
SafeWrite(stream, (uint64_t)table->size());
|
||||
|
||||
uint64_t size = table->size();
|
||||
SectorTable::iterator iter = table->begin();
|
||||
SectorTable::iterator end = table->end();
|
||||
|
||||
for (uint64_t i = 0; i < size; i++) {
|
||||
if (iter == end)
|
||||
panic("Incorrect Table Size during save of COW disk image");
|
||||
|
||||
SafeWrite(stream, (uint64_t)(*iter).first);
|
||||
SafeWrite(stream, (*iter).second->data, sizeof(Sector));
|
||||
++iter;
|
||||
}
|
||||
|
||||
stream.close();
|
||||
}
|
||||
|
||||
void
|
||||
CowDiskImage::writeback()
|
||||
{
|
||||
SectorTable::iterator i = table->begin();
|
||||
SectorTable::iterator end = table->end();
|
||||
|
||||
while (i != end) {
|
||||
child->write((*i).second->data, (*i).first);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
off_t
|
||||
CowDiskImage::size() const
|
||||
{ return child->size(); }
|
||||
|
||||
off_t
|
||||
CowDiskImage::read(uint8_t *data, off_t offset) const
|
||||
{
|
||||
if (!initialized)
|
||||
panic("CowDiskImage not initialized");
|
||||
|
||||
if (offset > size())
|
||||
panic("access out of bounds");
|
||||
|
||||
SectorTable::const_iterator i = table->find(offset);
|
||||
if (i == table->end())
|
||||
return child->read(data, offset);
|
||||
else {
|
||||
memcpy(data, (*i).second->data, SectorSize);
|
||||
DPRINTF(DiskImageRead, "read: offset=%d\n", (uint64_t)offset);
|
||||
DDUMP(DiskImageRead, data, SectorSize);
|
||||
return SectorSize;
|
||||
}
|
||||
}
|
||||
|
||||
off_t
|
||||
CowDiskImage::write(const uint8_t *data, off_t offset)
|
||||
{
|
||||
if (!initialized)
|
||||
panic("RawDiskImage not initialized");
|
||||
|
||||
if (offset > size())
|
||||
panic("access out of bounds");
|
||||
|
||||
SectorTable::iterator i = table->find(offset);
|
||||
if (i == table->end()) {
|
||||
Sector *sector = new Sector;
|
||||
memcpy(sector, data, SectorSize);
|
||||
table->insert(make_pair(offset, sector));
|
||||
} else {
|
||||
memcpy((*i).second->data, data, SectorSize);
|
||||
}
|
||||
|
||||
DPRINTF(DiskImageWrite, "write: offset=%d\n", (uint64_t)offset);
|
||||
DDUMP(DiskImageWrite, data, SectorSize);
|
||||
|
||||
return SectorSize;
|
||||
}
|
||||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(CowDiskImage)
|
||||
|
||||
SimObjectParam<DiskImage *> child;
|
||||
Param<string> image_file;
|
||||
Param<int> table_size;
|
||||
Param<bool> read_only;
|
||||
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(CowDiskImage)
|
||||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(CowDiskImage)
|
||||
|
||||
INIT_PARAM(child, "child image"),
|
||||
INIT_PARAM_DFLT(image_file, "disk image file", ""),
|
||||
INIT_PARAM_DFLT(table_size, "initial table size", 65536),
|
||||
INIT_PARAM_DFLT(read_only, "don't write back to the copy-on-write file",
|
||||
true)
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(CowDiskImage)
|
||||
|
||||
|
||||
CREATE_SIM_OBJECT(CowDiskImage)
|
||||
{
|
||||
if (((string)image_file).empty())
|
||||
return new CowDiskImage(getInstanceName(), child, table_size);
|
||||
else
|
||||
return new CowDiskImage(getInstanceName(), child, table_size,
|
||||
image_file, read_only);
|
||||
}
|
||||
|
||||
REGISTER_SIM_OBJECT("CowDiskImage", CowDiskImage)
|
130
dev/disk_image.hh
Normal file
130
dev/disk_image.hh
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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
|
||||
* Disk Image Interfaces
|
||||
*/
|
||||
|
||||
#ifndef __DISK_IMAGE_HH__
|
||||
#define __DISK_IMAGE_HH__
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "hashmap.hh"
|
||||
#include "sim_object.hh"
|
||||
|
||||
#define SectorSize (512)
|
||||
|
||||
/*
|
||||
* Basic interface for accessing a disk image.
|
||||
*/
|
||||
class DiskImage : public SimObject
|
||||
{
|
||||
protected:
|
||||
bool initialized;
|
||||
|
||||
public:
|
||||
DiskImage(const std::string &name) : SimObject(name), initialized(false) {}
|
||||
virtual ~DiskImage() {}
|
||||
|
||||
virtual off_t size() const = 0;
|
||||
|
||||
virtual off_t read(uint8_t *data, off_t offset) const = 0;
|
||||
virtual off_t write(const uint8_t *data, off_t offset) = 0;
|
||||
};
|
||||
|
||||
/*
|
||||
* Specialization for accessing a raw disk image
|
||||
*/
|
||||
class RawDiskImage : public DiskImage
|
||||
{
|
||||
protected:
|
||||
mutable std::fstream stream;
|
||||
std::string file;
|
||||
bool readonly;
|
||||
mutable off_t disk_size;
|
||||
|
||||
public:
|
||||
RawDiskImage(const std::string &name, const std::string &filename,
|
||||
bool rd_only);
|
||||
~RawDiskImage();
|
||||
|
||||
void close();
|
||||
void open(const std::string &filename, bool rd_only = false);
|
||||
|
||||
virtual off_t size() const;
|
||||
|
||||
virtual off_t read(uint8_t *data, off_t offset) const;
|
||||
virtual off_t write(const uint8_t *data, off_t offset);
|
||||
};
|
||||
|
||||
/*
|
||||
* Specialization for accessing a copy-on-write disk image layer.
|
||||
* A copy-on-write(COW) layer must be stacked on top of another disk
|
||||
* image layer this layer can be another CowDiskImage, or a
|
||||
* RawDiskImage.
|
||||
*
|
||||
* This object is designed to provide a mechanism for persistant
|
||||
* changes to a main disk image, or to provide a place for temporary
|
||||
* changes to the image to take place that later may be thrown away.
|
||||
*/
|
||||
class CowDiskImage : public DiskImage
|
||||
{
|
||||
public:
|
||||
static const int VersionMajor;
|
||||
static const int VersionMinor;
|
||||
|
||||
protected:
|
||||
struct Sector {
|
||||
uint8_t data[SectorSize];
|
||||
};
|
||||
typedef m5::hash_map<uint64_t, Sector *> SectorTable;
|
||||
|
||||
protected:
|
||||
std::string filename;
|
||||
DiskImage *child;
|
||||
SectorTable *table;
|
||||
|
||||
public:
|
||||
CowDiskImage(const std::string &name, DiskImage *kid, int hash_size);
|
||||
CowDiskImage(const std::string &name, DiskImage *kid, int hash_size,
|
||||
const std::string &filename, bool read_only);
|
||||
~CowDiskImage();
|
||||
|
||||
void init(int hash_size);
|
||||
bool open();
|
||||
void save();
|
||||
void writeback();
|
||||
|
||||
virtual off_t size() const;
|
||||
|
||||
virtual off_t read(uint8_t *data, off_t offset) const;
|
||||
virtual off_t write(const uint8_t *data, off_t offset);
|
||||
};
|
||||
|
||||
#endif // __DISK_IMAGE_HH__
|
128
dev/etherbus.cc
Normal file
128
dev/etherbus.cc
Normal file
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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
|
||||
* Device module for modelling an ethernet hub
|
||||
*/
|
||||
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "etherbus.hh"
|
||||
#include "etherdump.hh"
|
||||
#include "etherint.hh"
|
||||
#include "etherpkt.hh"
|
||||
#include "trace.hh"
|
||||
#include "universe.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
EtherBus::EtherBus(const string &name, double rate, bool loop,
|
||||
EtherDump *packet_dump)
|
||||
: SimObject(name), ticks_per_byte(rate), loopback(loop),
|
||||
event(&mainEventQueue, this),
|
||||
sender(0), dump(packet_dump)
|
||||
{ }
|
||||
|
||||
void
|
||||
EtherBus::txDone()
|
||||
{
|
||||
devlist_t::iterator i = devlist.begin();
|
||||
devlist_t::iterator end = devlist.end();
|
||||
|
||||
DPRINTF(Ethernet, "ethernet packet received: length=%d\n", packet->length);
|
||||
DDUMP(EthernetData, packet->data, packet->length);
|
||||
|
||||
while (i != end) {
|
||||
if (loopback || *i != sender)
|
||||
(*i)->sendPacket(packet);
|
||||
++i;
|
||||
}
|
||||
|
||||
sender->sendDone();
|
||||
|
||||
if (dump)
|
||||
dump->dump(packet);
|
||||
|
||||
sender = 0;
|
||||
packet = 0;
|
||||
}
|
||||
|
||||
void
|
||||
EtherBus::reg(EtherInt *dev)
|
||||
{ devlist.push_back(dev); }
|
||||
|
||||
bool
|
||||
EtherBus::send(EtherInt *sndr, PacketPtr pkt)
|
||||
{
|
||||
if (busy()) {
|
||||
DPRINTF(Ethernet, "ethernet packet not sent, bus busy\n", curTick);
|
||||
return false;
|
||||
}
|
||||
|
||||
DPRINTF(Ethernet, "ethernet packet sent: length=%d\n", pkt->length);
|
||||
DDUMP(EthernetData, pkt->data, pkt->length);
|
||||
|
||||
packet = pkt;
|
||||
sender = sndr;
|
||||
int delay = (int)ceil(((double)pkt->length * ticks_per_byte) + 1.0);
|
||||
DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n",
|
||||
delay, ticks_per_byte);
|
||||
event.schedule(curTick + delay);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherBus)
|
||||
|
||||
Param<bool> loopback;
|
||||
Param<int> speed;
|
||||
SimObjectParam<EtherDump *> packet_dump;
|
||||
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(EtherBus)
|
||||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(EtherBus)
|
||||
|
||||
INIT_PARAM_DFLT(loopback,
|
||||
"send the packet back to the interface from which it came",
|
||||
true),
|
||||
INIT_PARAM_DFLT(speed, "bus speed in bits per second", 100000000),
|
||||
INIT_PARAM_DFLT(packet_dump, "object to dump network packets to", NULL)
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(EtherBus)
|
||||
|
||||
CREATE_SIM_OBJECT(EtherBus)
|
||||
{
|
||||
double rate = ((double)ticksPerSecond * 8.0) / (double)speed;
|
||||
return new EtherBus(getInstanceName(), rate, loopback, packet_dump);
|
||||
}
|
||||
|
||||
REGISTER_SIM_OBJECT("EtherBus", EtherBus)
|
79
dev/etherbus.hh
Normal file
79
dev/etherbus.hh
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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
|
||||
* Device module for modelling an ethernet hub
|
||||
*/
|
||||
|
||||
#ifndef __ETHERBUS_H__
|
||||
#define __ETHERBUS_H__
|
||||
|
||||
#include "eventq.hh"
|
||||
#include "etherpkt.hh"
|
||||
#include "sim_object.hh"
|
||||
|
||||
class EtherDump;
|
||||
class EtherInt;
|
||||
class EtherBus : public SimObject
|
||||
{
|
||||
protected:
|
||||
typedef std::list<EtherInt *> devlist_t;
|
||||
devlist_t devlist;
|
||||
double ticks_per_byte;
|
||||
bool loopback;
|
||||
|
||||
protected:
|
||||
class DoneEvent : public Event
|
||||
{
|
||||
protected:
|
||||
EtherBus *bus;
|
||||
|
||||
public:
|
||||
DoneEvent(EventQueue *q, EtherBus *b)
|
||||
: Event(q), bus(b) {}
|
||||
virtual void process() { bus->txDone(); }
|
||||
virtual const char *description() { return "ethernet bus completion"; }
|
||||
};
|
||||
|
||||
DoneEvent event;
|
||||
PacketPtr packet;
|
||||
EtherInt *sender;
|
||||
EtherDump *dump;
|
||||
|
||||
public:
|
||||
EtherBus(const std::string &name, double ticks_per_byte, bool loopback,
|
||||
EtherDump *dump);
|
||||
virtual ~EtherBus() {}
|
||||
|
||||
void txDone();
|
||||
void reg(EtherInt *dev);
|
||||
bool busy() const { return (bool)packet; }
|
||||
bool send(EtherInt *sender, PacketPtr packet);
|
||||
};
|
||||
|
||||
#endif // __ETHERBUS_H__
|
138
dev/etherdump.cc
Normal file
138
dev/etherdump.cc
Normal file
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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
|
||||
* Simple object for creating a simple pcap style packet trace
|
||||
*/
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "universe.hh"
|
||||
#include "etherdump.hh"
|
||||
#include "universe.hh"
|
||||
|
||||
using std::string;
|
||||
|
||||
EtherDump::EtherDump(const string &name, const string &file)
|
||||
: SimObject(name)
|
||||
{
|
||||
if (!file.empty()) {
|
||||
stream.open(file.c_str());
|
||||
if (stream.is_open())
|
||||
init();
|
||||
}
|
||||
}
|
||||
|
||||
#define DLT_EN10MB 1 // Ethernet (10Mb)
|
||||
#define TCPDUMP_MAGIC 0xa1b2c3d4
|
||||
#define PCAP_VERSION_MAJOR 2
|
||||
#define PCAP_VERSION_MINOR 4
|
||||
|
||||
struct pcap_file_header {
|
||||
uint32_t magic;
|
||||
uint16_t version_major;
|
||||
uint16_t version_minor;
|
||||
int32_t thiszone; // gmt to local correction
|
||||
uint32_t sigfigs; // accuracy of timestamps
|
||||
uint32_t snaplen; // max length saved portion of each pkt
|
||||
uint32_t linktype; // data link type (DLT_*)
|
||||
};
|
||||
|
||||
struct pcap_pkthdr {
|
||||
struct timeval ts; // time stamp
|
||||
uint32_t caplen; // length of portion present
|
||||
uint32_t len; // length this packet (off wire)
|
||||
};
|
||||
|
||||
void
|
||||
EtherDump::init()
|
||||
{
|
||||
curtime = time(NULL);
|
||||
s_freq = ticksPerSecond;
|
||||
us_freq = ticksPerSecond / ULL(1000000);
|
||||
|
||||
struct pcap_file_header hdr;
|
||||
hdr.magic = TCPDUMP_MAGIC;
|
||||
hdr.version_major = PCAP_VERSION_MAJOR;
|
||||
hdr.version_minor = PCAP_VERSION_MINOR;
|
||||
|
||||
hdr.thiszone = -5 * 3600;
|
||||
hdr.snaplen = 1500;
|
||||
hdr.sigfigs = 0;
|
||||
hdr.linktype = DLT_EN10MB;
|
||||
|
||||
stream.write(reinterpret_cast<char *>(&hdr), sizeof(hdr));
|
||||
|
||||
/*
|
||||
* output an empty packet with the current time so that we know
|
||||
* when the simulation began. This allows us to correlate packets
|
||||
* to sim_cycles.
|
||||
*/
|
||||
pcap_pkthdr pkthdr;
|
||||
pkthdr.ts.tv_sec = curtime;
|
||||
pkthdr.ts.tv_usec = 0;
|
||||
pkthdr.caplen = 0;
|
||||
pkthdr.len = 0;
|
||||
stream.write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
|
||||
|
||||
stream.flush();
|
||||
}
|
||||
|
||||
void
|
||||
EtherDump::dumpPacket(PacketPtr packet)
|
||||
{
|
||||
pcap_pkthdr pkthdr;
|
||||
pkthdr.ts.tv_sec = curtime + (curTick / s_freq);
|
||||
pkthdr.ts.tv_usec = (curTick / us_freq) % ULL(1000000);
|
||||
pkthdr.caplen = packet->length;
|
||||
pkthdr.len = packet->length;
|
||||
stream.write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
|
||||
stream.write(reinterpret_cast<char *>(packet->data), packet->length);
|
||||
stream.flush();
|
||||
}
|
||||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherDump)
|
||||
|
||||
Param<string> file;
|
||||
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(EtherDump)
|
||||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(EtherDump)
|
||||
|
||||
INIT_PARAM_DFLT(file, "file to dump packets to", "")
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(EtherDump)
|
||||
|
||||
CREATE_SIM_OBJECT(EtherDump)
|
||||
{
|
||||
return new EtherDump(getInstanceName(), file);
|
||||
}
|
||||
|
||||
REGISTER_SIM_OBJECT("EtherDump", EtherDump)
|
60
dev/etherdump.hh
Normal file
60
dev/etherdump.hh
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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
|
||||
* Simple object for creating a simple pcap style packet trace
|
||||
*/
|
||||
|
||||
#ifndef __ETHERDUMP_H__
|
||||
#define __ETHERDUMP_H__
|
||||
|
||||
#include <fstream>
|
||||
#include "etherpkt.hh"
|
||||
#include "sim_object.hh"
|
||||
|
||||
/*
|
||||
* Simple object for creating a simple pcap style packet trace
|
||||
*/
|
||||
class EtherDump : public SimObject
|
||||
{
|
||||
private:
|
||||
std::ofstream stream;
|
||||
void dumpPacket(PacketPtr packet);
|
||||
void init();
|
||||
|
||||
Tick curtime;
|
||||
Tick s_freq;
|
||||
Tick us_freq;
|
||||
|
||||
public:
|
||||
EtherDump(const std::string &name, const std::string &file);
|
||||
|
||||
inline void dump(PacketPtr pkt) { if (stream.is_open()) dumpPacket(pkt); }
|
||||
};
|
||||
|
||||
#endif // __ETHERDUMP_H__
|
44
dev/etherint.cc
Normal file
44
dev/etherint.cc
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "etherint.hh"
|
||||
#include "misc.hh"
|
||||
#include "sim_object.hh"
|
||||
|
||||
void
|
||||
EtherInt::setPeer(EtherInt *p)
|
||||
{
|
||||
if (peer && peer != p)
|
||||
panic("You cannot change the peer once it is set.\n"
|
||||
"Current peer=%s Desired peer=%s", peer->name(), p->name());
|
||||
|
||||
peer = p;
|
||||
}
|
||||
|
||||
DEFINE_SIM_OBJECT_CLASS_NAME("EtherInt", EtherInt)
|
||||
|
63
dev/etherint.hh
Normal file
63
dev/etherint.hh
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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
|
||||
* Class representing the actual interface between two ethernet
|
||||
* components.
|
||||
*/
|
||||
|
||||
#ifndef __ETHERINT_HH__
|
||||
#define __ETHERINT_HH__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "etherpkt.hh"
|
||||
#include "sim_object.hh"
|
||||
|
||||
/*
|
||||
* Class representing the actual interface between two ethernet
|
||||
* components. These components are intended to attach to another
|
||||
* ethernet interface on one side and whatever device on the other.
|
||||
*/
|
||||
class EtherInt : public SimObject
|
||||
{
|
||||
protected:
|
||||
EtherInt *peer;
|
||||
|
||||
public:
|
||||
EtherInt(const std::string &name) : SimObject(name), peer(NULL) {}
|
||||
virtual ~EtherInt() {}
|
||||
|
||||
void setPeer(EtherInt *p);
|
||||
virtual bool recvPacket(PacketPtr packet) = 0;
|
||||
void recvDone() { peer->sendDone(); }
|
||||
bool sendPacket(PacketPtr packet) { return peer->recvPacket(packet); }
|
||||
virtual void sendDone() = 0;
|
||||
};
|
||||
|
||||
#endif // __ETHERINT_HH__
|
148
dev/etherlink.cc
Normal file
148
dev/etherlink.cc
Normal file
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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
|
||||
* Device module for modelling a fixed bandwidth full duplex ethernet link
|
||||
*/
|
||||
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "etherlink.hh"
|
||||
#include "etherdump.hh"
|
||||
#include "etherint.hh"
|
||||
#include "etherpkt.hh"
|
||||
#include "trace.hh"
|
||||
#include "universe.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
EtherLink::EtherLink(const std::string &name, EtherInt *i1, EtherInt *i2,
|
||||
Tick speed, EtherDump *dump)
|
||||
: SimObject(name)
|
||||
{
|
||||
double rate = ((double)ticksPerSecond * 8.0) / (double)speed;
|
||||
|
||||
link1 = new Link(name + ".link1", rate, dump);
|
||||
link2 = new Link(name + ".link2", rate, dump);
|
||||
|
||||
int1 = new Interface(name + ".int1", link1, link2);
|
||||
int2 = new Interface(name + ".int2", link2, link1);
|
||||
|
||||
int1->setPeer(i1);
|
||||
i1->setPeer(int1);
|
||||
int2->setPeer(i2);
|
||||
i2->setPeer(int2);
|
||||
}
|
||||
|
||||
EtherLink::~EtherLink()
|
||||
{
|
||||
delete link1;
|
||||
delete link2;
|
||||
|
||||
delete int1;
|
||||
delete int2;
|
||||
}
|
||||
|
||||
EtherLink::Interface::Interface(const std::string &name, Link *tx, Link *rx)
|
||||
: EtherInt(name), txlink(tx)
|
||||
{
|
||||
tx->setTxInt(this);
|
||||
rx->setRxInt(this);
|
||||
}
|
||||
|
||||
EtherLink::Link::Link(const std::string &name, double rate, EtherDump *d)
|
||||
: Serializeable(name), txint(NULL), rxint(NULL), ticks_per_byte(rate),
|
||||
dump(d), event(&mainEventQueue, this)
|
||||
{}
|
||||
|
||||
void
|
||||
EtherLink::Link::txDone()
|
||||
{
|
||||
rxint->sendPacket(packet);
|
||||
|
||||
if (dump)
|
||||
dump->dump(packet);
|
||||
|
||||
DPRINTF(Ethernet, "EtherLink packet received: len=%d\n", packet->length);
|
||||
DDUMP(EthernetData, packet->data, packet->length);
|
||||
|
||||
packet = 0;
|
||||
assert(!busy());
|
||||
|
||||
txint->sendDone();
|
||||
}
|
||||
|
||||
bool
|
||||
EtherLink::Link::transmit(PacketPtr pkt)
|
||||
{
|
||||
if (busy()) {
|
||||
DPRINTF(Ethernet, "EtherLink packet not sent, link busy\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
DPRINTF(Ethernet, "EtherLink packet sent: len=%d\n", pkt->length);
|
||||
DDUMP(EthernetData, pkt->data, pkt->length);
|
||||
|
||||
packet = pkt;
|
||||
int delay = (int)ceil(((double)pkt->length * ticks_per_byte) + 1.0);
|
||||
DPRINTF(Ethernet, "EtherLink scheduling packet: delay=%d, (rate=%f)\n",
|
||||
delay, ticks_per_byte);
|
||||
event.schedule(curTick + delay);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherLink)
|
||||
|
||||
SimObjectParam<EtherInt *> interface1;
|
||||
SimObjectParam<EtherInt *> interface2;
|
||||
Param<int> link_speed;
|
||||
SimObjectParam<EtherDump *> packet_dump;
|
||||
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(EtherLink)
|
||||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(EtherLink)
|
||||
|
||||
INIT_PARAM(interface1, "interface 1"),
|
||||
INIT_PARAM(interface2, "interface 2"),
|
||||
INIT_PARAM_DFLT(link_speed, "link speed in bits per second", 100000000),
|
||||
INIT_PARAM_DFLT(packet_dump, "object to dump network packets to", NULL)
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(EtherLink)
|
||||
|
||||
CREATE_SIM_OBJECT(EtherLink)
|
||||
{
|
||||
return new EtherLink(getInstanceName(), interface1, interface2, link_speed,
|
||||
packet_dump);
|
||||
}
|
||||
|
||||
REGISTER_SIM_OBJECT("EtherLink", EtherLink)
|
123
dev/etherlink.hh
Normal file
123
dev/etherlink.hh
Normal file
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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
|
||||
* Device module for modelling a fixed bandwidth full duplex ethernet link
|
||||
*/
|
||||
|
||||
#ifndef __ETHERLINK_HH__
|
||||
#define __ETHERLINK_HH__
|
||||
|
||||
#include "host.hh"
|
||||
#include "eventq.hh"
|
||||
#include "etherint.hh"
|
||||
#include "etherpkt.hh"
|
||||
#include "sim_object.hh"
|
||||
|
||||
class EtherDump;
|
||||
|
||||
/*
|
||||
* Model for a fixed bandwidth full duplex ethernet link
|
||||
*/
|
||||
class EtherLink : public SimObject
|
||||
{
|
||||
protected:
|
||||
class Interface;
|
||||
|
||||
/*
|
||||
* Model for a single uni-directional link
|
||||
*/
|
||||
class Link : public Serializeable {
|
||||
protected:
|
||||
Interface *txint;
|
||||
Interface *rxint;
|
||||
|
||||
double ticks_per_byte;
|
||||
EtherDump *dump;
|
||||
|
||||
protected:
|
||||
/*
|
||||
* Transfer is complete
|
||||
*/
|
||||
class DoneEvent : public Event
|
||||
{
|
||||
protected:
|
||||
Link *link;
|
||||
|
||||
public:
|
||||
DoneEvent(EventQueue *q, Link *l)
|
||||
: Event(q), link(l) {}
|
||||
virtual void process() { link->txDone(); }
|
||||
virtual const char *description()
|
||||
{ return "ethernet link completion"; }
|
||||
};
|
||||
|
||||
friend class DoneEvent;
|
||||
DoneEvent event;
|
||||
PacketPtr packet;
|
||||
|
||||
void txDone();
|
||||
|
||||
public:
|
||||
Link(const std::string &name, double rate, EtherDump *dump);
|
||||
~Link() {}
|
||||
|
||||
bool busy() const { return (bool)packet; }
|
||||
bool transmit(PacketPtr packet);
|
||||
|
||||
void setTxInt(Interface *i) { assert(!txint); txint = i; }
|
||||
void setRxInt(Interface *i) { assert(!rxint); rxint = i; }
|
||||
};
|
||||
|
||||
/*
|
||||
* Interface at each end of the link
|
||||
*/
|
||||
class Interface : public EtherInt
|
||||
{
|
||||
private:
|
||||
Link *txlink;
|
||||
|
||||
public:
|
||||
Interface(const std::string &name, Link *txlink, Link *rxlink);
|
||||
bool recvPacket(PacketPtr packet) { return txlink->transmit(packet); }
|
||||
void sendDone() { }
|
||||
};
|
||||
|
||||
Link *link1;
|
||||
Link *link2;
|
||||
|
||||
EtherInt *int1;
|
||||
EtherInt *int2;
|
||||
|
||||
public:
|
||||
EtherLink(const std::string &name, EtherInt *i1, EtherInt *i2,
|
||||
Tick speed, EtherDump *dump);
|
||||
virtual ~EtherLink();
|
||||
};
|
||||
|
||||
#endif // __ETHERLINK_HH__
|
65
dev/etherpkt.hh
Normal file
65
dev/etherpkt.hh
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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
|
||||
* Reference counted class containing ethernet packet data
|
||||
*/
|
||||
|
||||
#ifndef __ETHERPKT_HH__
|
||||
#define __ETHERPKT_HH__
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "host.hh"
|
||||
|
||||
#include "refcnt.hh"
|
||||
|
||||
/*
|
||||
* Reference counted class containing ethernet packet data
|
||||
*/
|
||||
class EtherPacket : public RefCounted
|
||||
{
|
||||
public:
|
||||
uint8_t *data;
|
||||
int length;
|
||||
|
||||
public:
|
||||
EtherPacket() : data(NULL), length(0) {}
|
||||
EtherPacket(std::auto_ptr<uint8_t> d, int l)
|
||||
: data(d.release()), length(l) {}
|
||||
~EtherPacket() { if (data) delete [] data; }
|
||||
|
||||
public:
|
||||
bool IsUnicast() { return data[0] == 0x00; }
|
||||
bool IsMulticast() { return data[0] == 0x01; }
|
||||
bool IsBroadcast() { return data[0] == 0xff; }
|
||||
};
|
||||
|
||||
typedef RefCountingPtr<EtherPacket> PacketPtr;
|
||||
|
||||
#endif // __ETHERPKT_HH__
|
295
dev/ethertap.cc
Normal file
295
dev/ethertap.cc
Normal file
|
@ -0,0 +1,295 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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
|
||||
* Interface to connect a simulated ethernet device to the real world
|
||||
*/
|
||||
|
||||
#if defined(__OpenBSD__)
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <deque>
|
||||
#include <string>
|
||||
|
||||
#include "etherdump.hh"
|
||||
#include "etherint.hh"
|
||||
#include "etherpkt.hh"
|
||||
#include "ethertap.hh"
|
||||
#include "pollevent.hh"
|
||||
#include "socket.hh"
|
||||
#include "trace.hh"
|
||||
#include "misc.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
*/
|
||||
class TapListener
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
*/
|
||||
class Event : public PollEvent
|
||||
{
|
||||
protected:
|
||||
TapListener *listener;
|
||||
|
||||
public:
|
||||
Event(TapListener *l, int fd, int e)
|
||||
: PollEvent(fd, e), listener(l) {}
|
||||
|
||||
virtual void process(int revent) { listener->accept(); }
|
||||
};
|
||||
|
||||
friend class Event;
|
||||
Event *event;
|
||||
|
||||
protected:
|
||||
ListenSocket listener;
|
||||
EtherTap *tap;
|
||||
int port;
|
||||
|
||||
public:
|
||||
TapListener(EtherTap *t, int p)
|
||||
: event(NULL), tap(t), port(p) {}
|
||||
~TapListener() { if (event) delete event; }
|
||||
|
||||
void accept();
|
||||
void listen();
|
||||
};
|
||||
|
||||
void
|
||||
TapListener::listen()
|
||||
{
|
||||
while (!listener.listen(port, true)) {
|
||||
DPRINTF(Ethernet, "TapListener(listen): Can't bind port %d\n", port);
|
||||
port++;
|
||||
}
|
||||
|
||||
ccprintf(cerr, "Listening for tap connection on port %d\n", port);
|
||||
event = new Event(this, listener.getfd(), POLLIN|POLLERR);
|
||||
pollQueue.schedule(event);
|
||||
}
|
||||
|
||||
void
|
||||
TapListener::accept()
|
||||
{
|
||||
if (!listener.islistening())
|
||||
panic("TapListener(accept): cannot accept if we're not listening!");
|
||||
|
||||
int sfd = listener.accept(true);
|
||||
if (sfd != -1)
|
||||
tap->attach(sfd);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
class TapEvent : public PollEvent
|
||||
{
|
||||
protected:
|
||||
EtherTap *tap;
|
||||
|
||||
public:
|
||||
TapEvent(EtherTap *_tap, int fd, int e)
|
||||
: PollEvent(fd, e), tap(_tap) {}
|
||||
virtual void process(int revent) { tap->process(revent); }
|
||||
};
|
||||
|
||||
EtherTap::EtherTap(const string &name, EtherDump *d, int port, int bufsz)
|
||||
: EtherInt(name), event(NULL), socket(-1), buflen(bufsz), dump(d),
|
||||
txEvent(this)
|
||||
{
|
||||
buffer = new char[buflen];
|
||||
listener = new TapListener(this, port);
|
||||
listener->listen();
|
||||
}
|
||||
|
||||
EtherTap::~EtherTap()
|
||||
{
|
||||
if (event)
|
||||
delete event;
|
||||
if (buffer)
|
||||
delete [] buffer;
|
||||
|
||||
delete listener;
|
||||
}
|
||||
|
||||
void
|
||||
EtherTap::attach(int fd)
|
||||
{
|
||||
if (socket != -1)
|
||||
close(fd);
|
||||
|
||||
buffer_offset = 0;
|
||||
data_len = 0;
|
||||
socket = fd;
|
||||
DPRINTF(Ethernet, "EtherTap attached\n");
|
||||
event = new TapEvent(this, socket, POLLIN|POLLERR);
|
||||
pollQueue.schedule(event);
|
||||
}
|
||||
|
||||
void
|
||||
EtherTap::detach()
|
||||
{
|
||||
DPRINTF(Ethernet, "EtherTap detached\n");
|
||||
delete event;
|
||||
close(socket);
|
||||
socket = -1;
|
||||
}
|
||||
|
||||
bool
|
||||
EtherTap::recvPacket(PacketPtr packet)
|
||||
{
|
||||
if (dump)
|
||||
dump->dump(packet);
|
||||
|
||||
DPRINTF(Ethernet, "EtherTap output len=%d\n", packet->length);
|
||||
DDUMP(EthernetData, packet->data, packet->length);
|
||||
u_int32_t len = htonl(packet->length);
|
||||
write(socket, &len, sizeof(len));
|
||||
write(socket, packet->data, packet->length);
|
||||
|
||||
recvDone();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
EtherTap::sendDone()
|
||||
{}
|
||||
|
||||
void
|
||||
EtherTap::process(int revent)
|
||||
{
|
||||
if (revent & POLLERR) {
|
||||
detach();
|
||||
return;
|
||||
}
|
||||
|
||||
char *data = buffer + sizeof(u_int32_t);
|
||||
if (!(revent & POLLIN))
|
||||
return;
|
||||
|
||||
if (buffer_offset < data_len + sizeof(u_int32_t)) {
|
||||
int len = read(socket, buffer + buffer_offset, buflen - buffer_offset);
|
||||
if (len == 0) {
|
||||
detach();
|
||||
return;
|
||||
}
|
||||
|
||||
buffer_offset += len;
|
||||
|
||||
if (data_len == 0)
|
||||
data_len = ntohl(*(u_int32_t *)buffer);
|
||||
|
||||
DPRINTF(Ethernet, "Received data from peer: len=%d buffer_offset=%d "
|
||||
"data_len=%d\n", len, buffer_offset, data_len);
|
||||
}
|
||||
|
||||
while (data_len != 0 && buffer_offset >= data_len + sizeof(u_int32_t)) {
|
||||
PacketPtr packet;
|
||||
packet = new EtherPacket;
|
||||
packet->data = new uint8_t[data_len];
|
||||
packet->length = data_len;
|
||||
memcpy(packet->data, data, data_len);
|
||||
|
||||
buffer_offset -= data_len + sizeof(u_int32_t);
|
||||
assert(buffer_offset >= 0);
|
||||
if (buffer_offset > 0) {
|
||||
memmove(buffer, data + data_len, buffer_offset);
|
||||
data_len = ntohl(*(u_int32_t *)buffer);
|
||||
} else
|
||||
data_len = 0;
|
||||
|
||||
DPRINTF(Ethernet, "EtherTap input len=%d\n", packet->length);
|
||||
DDUMP(EthernetData, packet->data, packet->length);
|
||||
if (!sendPacket(packet)) {
|
||||
DPRINTF(Ethernet, "bus busy...buffer for retransmission\n");
|
||||
packetBuffer.push(packet);
|
||||
if (!txEvent.scheduled())
|
||||
txEvent.schedule(curTick + 1000);
|
||||
} else if (dump)
|
||||
dump->dump(packet);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EtherTap::retransmit()
|
||||
{
|
||||
if (packetBuffer.empty())
|
||||
return;
|
||||
|
||||
PacketPtr packet = packetBuffer.front();
|
||||
if (sendPacket(packet)) {
|
||||
if (dump)
|
||||
dump->dump(packet);
|
||||
DPRINTF(Ethernet, "EtherTap retransmit\n");
|
||||
packetBuffer.front() = NULL;
|
||||
packetBuffer.pop();
|
||||
}
|
||||
|
||||
if (!packetBuffer.empty() && !txEvent.scheduled())
|
||||
txEvent.schedule(curTick + 1000);
|
||||
}
|
||||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherTap)
|
||||
|
||||
SimObjectParam<EtherInt *> peer;
|
||||
SimObjectParam<EtherDump *> packet_dump;
|
||||
Param<uint16_t> port;
|
||||
Param<uint16_t> bufsz;
|
||||
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(EtherTap)
|
||||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(EtherTap)
|
||||
|
||||
INIT_PARAM_DFLT(peer, "peer interface", NULL),
|
||||
INIT_PARAM_DFLT(packet_dump, "object to dump network packets to", NULL),
|
||||
INIT_PARAM_DFLT(port, "tap port", 3500),
|
||||
INIT_PARAM_DFLT(bufsz, "tap buffer size", 10000)
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(EtherTap)
|
||||
|
||||
|
||||
CREATE_SIM_OBJECT(EtherTap)
|
||||
{
|
||||
EtherTap *tap = new EtherTap(getInstanceName(), packet_dump, port, bufsz);
|
||||
|
||||
if (peer) {
|
||||
tap->setPeer(peer);
|
||||
peer->setPeer(tap);
|
||||
}
|
||||
|
||||
return tap;
|
||||
}
|
||||
|
||||
REGISTER_SIM_OBJECT("EtherTap", EtherTap)
|
101
dev/ethertap.hh
Normal file
101
dev/ethertap.hh
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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
|
||||
* Interface to connect a simulated ethernet device to the real world
|
||||
*/
|
||||
|
||||
#ifndef __ETHERTAP_HH__
|
||||
#define __ETHERTAP_HH__
|
||||
|
||||
#include <queue>
|
||||
#include <string>
|
||||
|
||||
#include "etherint.hh"
|
||||
#include "etherpkt.hh"
|
||||
#include "eventq.hh"
|
||||
#include "pollevent.hh"
|
||||
#include "sim_object.hh"
|
||||
|
||||
/*
|
||||
* Interface to connect a simulated ethernet device to the real world
|
||||
*/
|
||||
class EtherTap : public EtherInt
|
||||
{
|
||||
protected:
|
||||
friend class TapEvent;
|
||||
TapEvent *event;
|
||||
|
||||
protected:
|
||||
friend class TapListener;
|
||||
TapListener *listener;
|
||||
int socket;
|
||||
char *buffer;
|
||||
int buflen;
|
||||
int32_t buffer_offset;
|
||||
int32_t data_len;
|
||||
|
||||
EtherDump *dump;
|
||||
|
||||
void attach(int fd);
|
||||
void detach();
|
||||
|
||||
protected:
|
||||
std::string device;
|
||||
std::queue<PacketPtr> packetBuffer;
|
||||
|
||||
void process(int revent);
|
||||
void enqueue(EtherPacket *packet);
|
||||
void retransmit();
|
||||
|
||||
/*
|
||||
*/
|
||||
class TxEvent : public Event
|
||||
{
|
||||
protected:
|
||||
EtherTap *tap;
|
||||
|
||||
public:
|
||||
TxEvent(EtherTap *_tap)
|
||||
: Event(&mainEventQueue), tap(_tap) {}
|
||||
void process() { tap->retransmit(); }
|
||||
virtual const char *description() { return "retransmit event"; }
|
||||
};
|
||||
|
||||
friend class TxEvent;
|
||||
TxEvent txEvent;
|
||||
|
||||
public:
|
||||
EtherTap(const std::string &name, EtherDump *dump, int port, int bufsz);
|
||||
virtual ~EtherTap();
|
||||
|
||||
virtual bool recvPacket(PacketPtr packet);
|
||||
virtual void sendDone();
|
||||
};
|
||||
|
||||
#endif // __ETHERTAP_HH__
|
175
dev/pcireg.h
Normal file
175
dev/pcireg.h
Normal file
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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
|
||||
* Device register definitions for a device's PCI config space
|
||||
*/
|
||||
|
||||
#ifndef __PCIREG_H__
|
||||
#define __PCIREG_H__
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
union PCIConfig {
|
||||
uint8_t data[64];
|
||||
|
||||
struct hdr {
|
||||
uint16_t vendor;
|
||||
uint16_t device;
|
||||
uint16_t command;
|
||||
uint16_t status;
|
||||
uint8_t revision;
|
||||
uint8_t progIF;
|
||||
uint8_t subClassCode;
|
||||
uint8_t classCode;
|
||||
uint8_t cacheLineSize;
|
||||
uint8_t latencyTimer;
|
||||
uint8_t headerType;
|
||||
uint8_t bist;
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint32_t baseAddr0;
|
||||
uint32_t baseAddr1;
|
||||
uint32_t baseAddr2;
|
||||
uint32_t baseAddr3;
|
||||
uint32_t baseAddr4;
|
||||
uint32_t baseAddr5;
|
||||
uint32_t cardbusCIS;
|
||||
uint16_t subsystemVendorID;
|
||||
uint16_t subsystemID;
|
||||
uint32_t expansionROM;
|
||||
uint32_t reserved0;
|
||||
uint32_t reserved1;
|
||||
uint8_t interruptLine;
|
||||
uint8_t interruptPin;
|
||||
uint8_t minimumGrant;
|
||||
uint8_t maximumLatency;
|
||||
} pci0;
|
||||
|
||||
struct {
|
||||
uint32_t baseAddr0;
|
||||
uint32_t baseAddr1;
|
||||
uint8_t priBusNum;
|
||||
uint8_t secBusNum;
|
||||
uint8_t subBusNum;
|
||||
uint8_t secLatency;
|
||||
uint8_t ioBase;
|
||||
uint8_t minimumGrantioLimit;
|
||||
uint16_t secStatus;
|
||||
uint16_t memBase;
|
||||
uint16_t memLimit;
|
||||
uint16_t prefetchMemBase;
|
||||
uint16_t prefetchMemLimit;
|
||||
uint32_t prfBaseUpper32;
|
||||
uint32_t prfLimitUpper32;
|
||||
uint16_t ioBaseUpper16;
|
||||
uint16_t ioLimitUpper16;
|
||||
uint32_t reserved0;
|
||||
uint32_t expansionROM;
|
||||
uint8_t interruptLine;
|
||||
uint8_t interruptPin;
|
||||
uint16_t bridgeControl;
|
||||
} pci1;
|
||||
};
|
||||
} hdr;
|
||||
};
|
||||
|
||||
// Common PCI offsets
|
||||
#define PCI_VENDOR_ID 0x00 // Vendor ID ro
|
||||
#define PCI_DEVICE_ID 0x02 // Device ID ro
|
||||
#define PCI_COMMAND 0x04 // Command rw
|
||||
#define PCI_STATUS 0x06 // Status rw
|
||||
#define PCI_REVISION_ID 0x08 // Revision ID ro
|
||||
#define PCI_CLASS_CODE 0x09 // Class Code ro
|
||||
#define PCI_SUB_CLASS_CODE 0x0A // Sub Class Code ro
|
||||
#define PCI_BASE_CLASS_CODE 0x0B // Base Class Code ro
|
||||
#define PCI_CACHE_LINE_SIZE 0x0C // Cache Line Size ro+
|
||||
#define PCI_LATENCY_TIMER 0x0D // Latency Timer ro+
|
||||
#define PCI_HEADER_TYPE 0x0E // Header Type ro
|
||||
#define PCI_BIST 0x0F // Built in self test rw
|
||||
|
||||
// Type 0 PCI offsets
|
||||
#define PCI0_BASE_ADDR0 0x10 // Base Address 0 rw
|
||||
#define PCI0_BASE_ADDR1 0x14 // Base Address 1 rw
|
||||
#define PCI0_BASE_ADDR2 0x18 // Base Address 2 rw
|
||||
#define PCI0_BASE_ADDR3 0x1C // Base Address 3 rw
|
||||
#define PCI0_BASE_ADDR4 0x20 // Base Address 4 rw
|
||||
#define PCI0_BASE_ADDR5 0x24 // Base Address 5 rw
|
||||
#define PCI0_CIS 0x28 // CardBus CIS Pointer ro
|
||||
#define PCI0_SUB_VENDOR_ID 0x2C // Sub-Vendor ID ro
|
||||
#define PCI0_SUB_SYSTEM_ID 0x2E // Sub-System ID ro
|
||||
#define PCI0_ROM_BASE_ADDR 0x30 // Expansion ROM Base Address rw
|
||||
#define PCI0_RESERVED0 0x34
|
||||
#define PCI0_RESERVED1 0x38
|
||||
#define PCI0_INTERRUPT_LINE 0x3C // Interrupt Line rw
|
||||
#define PCI0_INTERRUPT_PIN 0x3D // Interrupt Pin ro
|
||||
#define PCI0_MINIMUM_GRANT 0x3E // Maximum Grant ro
|
||||
#define PCI0_MAXIMUM_LATENCY 0x3F // Maximum Latency ro
|
||||
|
||||
// Type 1 PCI offsets
|
||||
#define PCI1_BASE_ADDR0 0x10 // Base Address 0 rw
|
||||
#define PCI1_BASE_ADDR1 0x14 // Base Address 1 rw
|
||||
#define PCI1_PRI_BUS_NUM 0x18 // Primary Bus Number rw
|
||||
#define PCI1_SEC_BUS_NUM 0x19 // Secondary Bus Number rw
|
||||
#define PCI1_SUB_BUS_NUM 0x1A // Subordinate Bus Number rw
|
||||
#define PCI1_SEC_LAT_TIMER 0x1B // Secondary Latency Timer ro+
|
||||
#define PCI1_IO_BASE 0x1C // I/O Base rw
|
||||
#define PCI1_IO_LIMIT 0x1D // I/O Limit rw
|
||||
#define PCI1_SECONDARY_STATUS 0x1E // Secondary Status rw
|
||||
#define PCI1_MEM_BASE 0x20 // Memory Base rw
|
||||
#define PCI1_MEM_LIMIT 0x22 // Memory Limit rw
|
||||
#define PCI1_PRF_MEM_BASE 0x24 // Prefetchable Memory Base rw
|
||||
#define PCI1_PRF_MEM_LIMIT 0x26 // Prefetchable Memory Limit rw
|
||||
#define PCI1_PRF_BASE_UPPER 0x28 // Prefetchable Base Upper 32 rw
|
||||
#define PCI1_PRF_LIMIT_UPPER 0x2C // Prefetchable Limit Upper 32 rw
|
||||
#define PCI1_IO_BASE_UPPER 0x30 // I/O Base Upper 16 bits rw
|
||||
#define PCI1_IO_LIMIT_UPPER 0x32 // I/O Limit Upper 16 bits rw
|
||||
#define PCI1_RESERVED 0x34 // Reserved ro
|
||||
#define PCI1_ROM_BASE_ADDR 0x38 // Expansion ROM Base Address rw
|
||||
#define PCI1_INTR_LINE 0x3C // Interrupt Line rw
|
||||
#define PCI1_INTR_PIN 0x3D // Interrupt Pin ro
|
||||
#define PCI1_BRIDGE_CTRL 0x3E // Bridge Control rw
|
||||
|
||||
// Device specific offsets
|
||||
#define PCI_DEVICE_SPECIFIC 0x40 // 192 bytes
|
||||
|
||||
// Some Vendor IDs
|
||||
#define PCI_VENDOR_DEC 0x1011
|
||||
#define PCI_VENDOR_NCR 0x101A
|
||||
#define PCI_VENDOR_QLOGIC 0x1077
|
||||
#define PCI_VENDOR_SIMOS 0x1291
|
||||
|
||||
// Some Product IDs
|
||||
#define PCI_PRODUCT_DEC_PZA 0x0008
|
||||
#define PCI_PRODUCT_NCR_810 0x0001
|
||||
#define PCI_PRODUCT_QLOGIC_ISP1020 0x1020
|
||||
#define PCI_PRODUCT_SIMOS_SIMOS 0x1291
|
||||
#define PCI_PRODUCT_SIMOS_ETHER 0x1292
|
||||
|
||||
#endif // __PCIREG_H__
|
108
dev/simple_disk.cc
Normal file
108
dev/simple_disk.cc
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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
|
||||
* Simple disk interface for the system console
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "disk_image.hh"
|
||||
#include "misc.hh"
|
||||
#include "physical_memory.hh"
|
||||
#include "simple_disk.hh"
|
||||
#include "trace.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
SimpleDisk::SimpleDisk(const string &name, PhysicalMemory *pmem,
|
||||
DiskImage *img)
|
||||
: SimObject(name), physmem(pmem), image(img)
|
||||
{}
|
||||
|
||||
SimpleDisk::~SimpleDisk()
|
||||
{}
|
||||
|
||||
|
||||
void
|
||||
SimpleDisk::read(Addr addr, baddr_t block, int count) const
|
||||
{
|
||||
uint8_t *data = physmem->dma_addr(addr, count);
|
||||
if (!data)
|
||||
panic("dma out of range! read addr=%#x count=%d\n", addr, count);
|
||||
|
||||
if (count & (SectorSize - 1))
|
||||
panic("Not reading a multiple of a sector (count = %d)", count);
|
||||
|
||||
for (int i = 0, j = 0; i < count; i += SectorSize, j++)
|
||||
image->read(data + i, block + j);
|
||||
|
||||
DPRINTF(SimpleDisk, "read block=%#x len=%d\n", (uint64_t)block, count);
|
||||
DDUMP(SimpleDiskData, data, count);
|
||||
}
|
||||
|
||||
void
|
||||
SimpleDisk::write(Addr addr, baddr_t block, int count)
|
||||
{
|
||||
panic("unimplemented!\n");
|
||||
|
||||
#if 0
|
||||
uint8_t *data = physmem->dma_addr(addr, count);
|
||||
if (!data)
|
||||
panic("dma out of range! write addr=%#x count=%d\n", addr, count);
|
||||
|
||||
image->write(data, block, count);
|
||||
#endif
|
||||
}
|
||||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleDisk)
|
||||
|
||||
SimObjectParam<PhysicalMemory *> physmem;
|
||||
SimObjectParam<DiskImage *> disk;
|
||||
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(SimpleDisk)
|
||||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleDisk)
|
||||
|
||||
INIT_PARAM(physmem, "Physical Memory"),
|
||||
INIT_PARAM(disk, "Disk Image")
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(SimpleDisk)
|
||||
|
||||
CREATE_SIM_OBJECT(SimpleDisk)
|
||||
{
|
||||
return new SimpleDisk(getInstanceName(), physmem, disk);
|
||||
}
|
||||
|
||||
REGISTER_SIM_OBJECT("SimpleDisk", SimpleDisk)
|
60
dev/simple_disk.hh
Normal file
60
dev/simple_disk.hh
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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
|
||||
* Simple disk interface for the system console
|
||||
*/
|
||||
|
||||
#ifndef __SIMPLE_DISK_HH__
|
||||
#define __SIMPLE_DISK_HH__
|
||||
|
||||
#include "physical_memory.hh"
|
||||
#include "sim_object.hh"
|
||||
|
||||
class DiskImage;
|
||||
|
||||
/*
|
||||
* Trivial interface to a disk image used by the System Console
|
||||
*/
|
||||
class SimpleDisk : public SimObject
|
||||
{
|
||||
public:
|
||||
typedef uint64_t baddr_t;
|
||||
|
||||
protected:
|
||||
PhysicalMemory *physmem;
|
||||
DiskImage *image;
|
||||
|
||||
public:
|
||||
SimpleDisk(const std::string &name, PhysicalMemory *pmem, DiskImage *img);
|
||||
~SimpleDisk();
|
||||
|
||||
void read(Addr addr, baddr_t block, int count) const;
|
||||
void write(Addr addr, baddr_t block, int count);
|
||||
};
|
||||
#endif // __SIMPLE_DISK_HH__
|
34
kern/tru64/tru64.hh
Normal file
34
kern/tru64/tru64.hh
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 __TRU64_HH__
|
||||
#define __TRU64_HH__
|
||||
|
||||
class Tru64 {};
|
||||
|
||||
#endif // __TRU64_HH__
|
438
kern/tru64/tru64_syscalls.cc
Normal file
438
kern/tru64/tru64_syscalls.cc
Normal file
|
@ -0,0 +1,438 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "tru64_syscalls.hh"
|
||||
|
||||
namespace {
|
||||
const char *
|
||||
standard_strings[SystemCalls<Tru64>::StandardNumber] = {
|
||||
"syscall", // 0
|
||||
"exit", // 1
|
||||
"fork", // 2
|
||||
"read", // 3
|
||||
"write", // 4
|
||||
"old_open", // 5
|
||||
"close", // 6
|
||||
"wait4", // 7
|
||||
"old_creat", // 8
|
||||
"link", // 9
|
||||
|
||||
"unlink", // 10
|
||||
"execv", // 11
|
||||
"chdir", // 12
|
||||
"fchdir", // 13
|
||||
"mknod", // 14
|
||||
"chmod", // 15
|
||||
"chown", // 16
|
||||
"obreak", // 17
|
||||
"pre_F64_getfsstat", // 18
|
||||
"lseek", // 19
|
||||
|
||||
"getpid", // 20
|
||||
"mount", // 21
|
||||
"unmount", // 22
|
||||
"setuid", // 23
|
||||
"getuid", // 24
|
||||
"exec_with_loader", // 25
|
||||
"ptrace", // 26
|
||||
"recvmsg", // 27
|
||||
"sendmsg", // 28
|
||||
"recvfrom", // 29
|
||||
|
||||
"accept", // 30
|
||||
"getpeername", // 31
|
||||
"getsockname", // 32
|
||||
"access", // 33
|
||||
"chflags", // 34
|
||||
"fchflags", // 35
|
||||
"sync", // 36
|
||||
"kill", // 37
|
||||
"old_stat", // 38
|
||||
"setpgid", // 39
|
||||
|
||||
"old_lstat", // 40
|
||||
"dup", // 41
|
||||
"pipe", // 42
|
||||
"set_program_attributes", // 43
|
||||
"profil", // 44
|
||||
"open", // 45
|
||||
"obsolete_osigaction", // 46
|
||||
"getgid", // 47
|
||||
"sigprocmask", // 48
|
||||
"getlogin", // 49
|
||||
|
||||
"setlogin", // 50
|
||||
"acct", // 51
|
||||
"sigpending", // 52
|
||||
"classcntl", // 53
|
||||
"ioctl", // 54
|
||||
"reboot", // 55
|
||||
"revoke", // 56
|
||||
"symlink", // 57
|
||||
"readlink", // 58
|
||||
"execve", // 59
|
||||
|
||||
"umask", // 60
|
||||
"chroot", // 61
|
||||
"old_fstat", // 62
|
||||
"getpgrp", // 63
|
||||
"getpagesize", // 64
|
||||
"mremap", // 65
|
||||
"vfork", // 66
|
||||
"pre_F64_stat", // 67
|
||||
"pre_F64_lstat", // 68
|
||||
"sbrk", // 69
|
||||
|
||||
"sstk", // 70
|
||||
"mmap", // 71
|
||||
"ovadvise", // 72
|
||||
"munmap", // 73
|
||||
"mprotect", // 74
|
||||
"madvise", // 75
|
||||
"old_vhangup", // 76
|
||||
"kmodcall", // 77
|
||||
"mincore", // 78
|
||||
"getgroups", // 79
|
||||
|
||||
"setgroups", // 80
|
||||
"old_getpgrp", // 81
|
||||
"setpgrp", // 82
|
||||
"setitimer", // 83
|
||||
"old_wait", // 84
|
||||
"table", // 85
|
||||
"getitimer", // 86
|
||||
"gethostname", // 87
|
||||
"sethostname", // 88
|
||||
"getdtablesize", // 89
|
||||
|
||||
"dup2", // 90
|
||||
"pre_F64_fstat", // 91
|
||||
"fcntl", // 92
|
||||
"select", // 93
|
||||
"poll", // 94
|
||||
"fsync", // 95
|
||||
"setpriority", // 96
|
||||
"socket", // 97
|
||||
"connect", // 98
|
||||
"old_accept", // 99
|
||||
|
||||
"getpriority", // 100
|
||||
"old_send", // 101
|
||||
"old_recv", // 102
|
||||
"sigreturn", // 103
|
||||
"bind", // 104
|
||||
"setsockopt", // 105
|
||||
"listen", // 106
|
||||
"plock", // 107
|
||||
"old_sigvec", // 108
|
||||
"old_sigblock", // 109
|
||||
|
||||
"old_sigsetmask", // 110
|
||||
"sigsuspend", // 111
|
||||
"sigstack", // 112
|
||||
"old_recvmsg", // 113
|
||||
"old_sendmsg", // 114
|
||||
"obsolete_vtrcae", // 115
|
||||
"gettimeofday", // 116
|
||||
"getrusage", // 117
|
||||
"getsockopt", // 118
|
||||
"numa_syscalls", // 119
|
||||
|
||||
"readv", // 120
|
||||
"writev", // 121
|
||||
"settimeofday", // 122
|
||||
"fchown", // 123
|
||||
"fchmod", // 124
|
||||
"old_recvfrom", // 125
|
||||
"setreuid", // 126
|
||||
"setregid", // 127
|
||||
"rename", // 128
|
||||
"truncate", // 129
|
||||
|
||||
"ftruncate", // 130
|
||||
"flock", // 131
|
||||
"setgid", // 132
|
||||
"sendto", // 133
|
||||
"shutdown", // 134
|
||||
"socketpair", // 135
|
||||
"mkdir", // 136
|
||||
"rmdir", // 137
|
||||
"utimes", // 138
|
||||
"obsolete_42_sigreturn", // 139
|
||||
|
||||
"adjtime", // 140
|
||||
"old_getpeername", // 141
|
||||
"gethostid", // 142
|
||||
"sethostid", // 143
|
||||
"getrlimit", // 144
|
||||
"setrlimit", // 145
|
||||
"old_killpg", // 146
|
||||
"setsid", // 147
|
||||
"quotactl", // 148
|
||||
"oldquota", // 149
|
||||
|
||||
"old_getsockname", // 150
|
||||
"pread", // 151
|
||||
"pwrite", // 152
|
||||
"pid_block", // 153
|
||||
"pid_unblock", // 154
|
||||
"signal_urti", // 155
|
||||
"sigaction", // 156
|
||||
"sigwaitprim", // 157
|
||||
"nfssvc", // 158
|
||||
"getdirentries", // 159
|
||||
|
||||
"pre_F64_statfs", // 160
|
||||
"pre_F64_fstatfs", // 161
|
||||
0, // 162
|
||||
"async_daemon", // 163
|
||||
"getfh", // 164
|
||||
"getdomainname", // 165
|
||||
"setdomainname", // 166
|
||||
0, // 167
|
||||
0, // 168
|
||||
"exportfs", // 169
|
||||
|
||||
0, // 170
|
||||
0, // 171
|
||||
0, // 172
|
||||
0, // 173
|
||||
0, // 174
|
||||
0, // 175
|
||||
0, // 176
|
||||
0, // 177
|
||||
0, // 178
|
||||
0, // 179
|
||||
|
||||
0, // 180
|
||||
"alt_plock", // 181
|
||||
0, // 182
|
||||
0, // 183
|
||||
"getmnt", // 184
|
||||
0, // 185
|
||||
0, // 186
|
||||
"alt_sigpending", // 187
|
||||
"alt_setsid", // 188
|
||||
0, // 189
|
||||
|
||||
0, // 190
|
||||
0, // 191
|
||||
0, // 192
|
||||
0, // 193
|
||||
0, // 194
|
||||
0, // 195
|
||||
0, // 196
|
||||
0, // 197
|
||||
0, // 198
|
||||
"swapon", // 199
|
||||
|
||||
"msgctl", // 200
|
||||
"msgget", // 201
|
||||
"msgrcv", // 202
|
||||
"msgsnd", // 203
|
||||
"semctl", // 204
|
||||
"semget", // 205
|
||||
"semop", // 206
|
||||
"uname", // 207
|
||||
"lchown", // 208
|
||||
"shmat", // 209
|
||||
|
||||
"shmctl", // 210
|
||||
"shmdt", // 211
|
||||
"shmget", // 212
|
||||
"mvalid", // 213
|
||||
"getaddressconf", // 214
|
||||
"msleep", // 215
|
||||
"mwakeup", // 216
|
||||
"msync", // 217
|
||||
"signal", // 218
|
||||
"utc_gettime", // 219
|
||||
|
||||
"utc_adjtime", // 220
|
||||
0, // 221
|
||||
"security", // 222
|
||||
"kloadcall", // 223
|
||||
"stat", // 224
|
||||
"lstat", // 225
|
||||
"fstat", // 226
|
||||
"statfs", // 227
|
||||
"fstatfs", // 228
|
||||
"getfsstat", // 229
|
||||
|
||||
"gettimeofday64", // 230
|
||||
"settimeofday64", // 231
|
||||
0, // 232
|
||||
"getpgid", // 233
|
||||
"getsid", // 234
|
||||
"sigaltstack", // 235
|
||||
"waitid", // 236
|
||||
"priocntlset", // 237
|
||||
"sigsendset", // 238
|
||||
"set_speculative", // 239
|
||||
|
||||
"msfs_syscall", // 240
|
||||
"sysinfo", // 241
|
||||
"uadmin", // 242
|
||||
"fuser", // 243
|
||||
"proplist_syscall", // 244
|
||||
"ntp_adjtime", // 245
|
||||
"ntp_gettime", // 246
|
||||
"pathconf", // 247
|
||||
"fpathconf", // 248
|
||||
"sync2", // 249
|
||||
|
||||
"uswitch", // 250
|
||||
"usleep_thread", // 251
|
||||
"audcntl", // 252
|
||||
"audgen", // 253
|
||||
"sysfs", // 254
|
||||
"subsys_info", // 255
|
||||
"getsysinfo", // 256
|
||||
"setsysinfo", // 257
|
||||
"afs_syscall", // 258
|
||||
"swapctl", // 259
|
||||
|
||||
"memcntl", // 260
|
||||
"fdatasync", // 261
|
||||
"oflock", // 262
|
||||
"_F64_readv", // 263
|
||||
"_F64_writev", // 264
|
||||
"cdslxlate", // 265
|
||||
"sendfile", // 266
|
||||
};
|
||||
|
||||
const char *
|
||||
mach_strings[SystemCalls<Tru64>::MachNumber] = {
|
||||
0, // 0
|
||||
0, // 1
|
||||
0, // 2
|
||||
0, // 3
|
||||
0, // 4
|
||||
0, // 5
|
||||
0, // 6
|
||||
0, // 7
|
||||
0, // 8
|
||||
0, // 9
|
||||
|
||||
"task_self", // 10
|
||||
"thread_reply", // 11
|
||||
"task_notify", // 12
|
||||
"thread_self", // 13
|
||||
0, // 14
|
||||
0, // 15
|
||||
0, // 16
|
||||
0, // 17
|
||||
0, // 18
|
||||
0, // 19
|
||||
|
||||
"msg_send_trap", // 20
|
||||
"msg_receive_trap", // 21
|
||||
"msg_rpc_trap", // 22
|
||||
0, // 23
|
||||
"nxm_block", // 24
|
||||
"nxm_unblock", // 25
|
||||
0, // 26
|
||||
0, // 27
|
||||
0, // 28
|
||||
"nxm_thread_destroy", // 29
|
||||
|
||||
"lw_wire", // 30
|
||||
"lw_unwire", // 31
|
||||
"nxm_thread_create", // 32
|
||||
"nxm_task_init", // 33
|
||||
0, // 34
|
||||
"nxm_idle", // 35
|
||||
"nxm_wakeup_idle", // 36
|
||||
"nxm_set_pthid", // 37
|
||||
"nxm_thread_kill", // 38
|
||||
"nxm_thread_block", // 39
|
||||
|
||||
"nxm_thread_wakeup", // 40
|
||||
"init_process", // 41
|
||||
"nxm_get_binding", // 42
|
||||
"map_fd", // 43
|
||||
"nxm_resched", // 44
|
||||
"nxm_set_cancel", // 45
|
||||
"nxm_set_binding", // 46
|
||||
"stack_create", // 47
|
||||
"nxm_get_state", // 48
|
||||
"nxm_thread_suspend", // 49
|
||||
|
||||
"nxm_thread_resume", // 50
|
||||
"nxm_signal_check", // 51
|
||||
"htg_unix_syscall", // 52
|
||||
0, // 53
|
||||
0, // 54
|
||||
"host_self", // 55
|
||||
"host_priv_self", // 56
|
||||
0, // 57
|
||||
0, // 58
|
||||
"swtch_pri", // 59
|
||||
|
||||
"swtch", // 60
|
||||
"thread_switch", // 61
|
||||
"semop_fast", // 62
|
||||
"nxm_pshared_init", // 63
|
||||
"nxm_pshared_block", // 64
|
||||
"nxm_pshared_unblock", // 65
|
||||
"nxm_pshared_destroy", // 66
|
||||
"nxm_swtch_pri", // 67
|
||||
"lw_syscall", // 68
|
||||
0, // 69
|
||||
|
||||
"mach_sctimes_0", // 70
|
||||
"mach_sctimes_1", // 71
|
||||
"mach_sctimes_2", // 72
|
||||
"mach_sctimes_3", // 73
|
||||
"mach_sctimes_4", // 74
|
||||
"mach_sctimes_5", // 75
|
||||
"mach_sctimes_6", // 76
|
||||
"mach_sctimes_7", // 77
|
||||
"mach_sctimes_8", // 78
|
||||
"mach_sctimes_9", // 79
|
||||
|
||||
"mach_sctimes_10", // 80
|
||||
"mach_sctimes_11", // 81
|
||||
"mach_sctimes_port_alloc_dealloc", // 82
|
||||
};
|
||||
}
|
||||
|
||||
const char *
|
||||
SystemCalls<Tru64>::name(int num)
|
||||
{
|
||||
if (num >= Number)
|
||||
return 0;
|
||||
else if (num >= StandardNumber)
|
||||
return mach_strings[num - StandardNumber];
|
||||
else if (num >= 0)
|
||||
return standard_strings[num];
|
||||
else if (num > -MachNumber)
|
||||
return mach_strings[-num];
|
||||
else
|
||||
return 0;
|
||||
}
|
355
kern/tru64/tru64_syscalls.hh
Normal file
355
kern/tru64/tru64_syscalls.hh
Normal file
|
@ -0,0 +1,355 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 __TRU64_SYSCALLS_HH__
|
||||
#define __TRU64_SYSCALLS_HH__
|
||||
|
||||
#include "syscalls.hh"
|
||||
#include "tru64.hh"
|
||||
|
||||
struct SystemCalls<Tru64>
|
||||
{
|
||||
enum {
|
||||
syscall = 0,
|
||||
exit = 1,
|
||||
fork = 2,
|
||||
read = 3,
|
||||
write = 4,
|
||||
old_open = 5,
|
||||
close = 6,
|
||||
wait4 = 7,
|
||||
old_creat = 8,
|
||||
link = 9,
|
||||
unlink = 10,
|
||||
execv = 11,
|
||||
chdir = 12,
|
||||
fchdir = 13,
|
||||
mknod = 14,
|
||||
chmod = 15,
|
||||
chown = 16,
|
||||
obreak = 17,
|
||||
pre_F64_getfsstat = 18,
|
||||
lseek = 19,
|
||||
getpid = 20,
|
||||
mount = 21,
|
||||
unmount = 22,
|
||||
setuid = 23,
|
||||
getuid = 24,
|
||||
exec_with_loader = 25,
|
||||
ptrace = 26,
|
||||
recvmsg = 27,
|
||||
sendmsg = 28,
|
||||
recvfrom = 29,
|
||||
accept = 30,
|
||||
getpeername = 31,
|
||||
getsockname = 32,
|
||||
access = 33,
|
||||
chflags = 34,
|
||||
fchflags = 35,
|
||||
sync = 36,
|
||||
kill = 37,
|
||||
old_stat = 38,
|
||||
setpgid = 39,
|
||||
old_lstat = 40,
|
||||
dup = 41,
|
||||
pipe = 42,
|
||||
set_program_attributes = 43,
|
||||
profil = 44,
|
||||
open = 45,
|
||||
obsolete_osigaction = 46,
|
||||
getgid = 47,
|
||||
sigprocmask = 48,
|
||||
getlogin = 49,
|
||||
setlogin = 50,
|
||||
acct = 51,
|
||||
sigpending = 52,
|
||||
classcntl = 53,
|
||||
ioctl = 54,
|
||||
reboot = 55,
|
||||
revoke = 56,
|
||||
symlink = 57,
|
||||
readlink = 58,
|
||||
execve = 59,
|
||||
umask = 60,
|
||||
chroot = 61,
|
||||
old_fstat = 62,
|
||||
getpgrp = 63,
|
||||
getpagesize = 64,
|
||||
mremap = 65,
|
||||
vfork = 66,
|
||||
pre_F64_stat = 67,
|
||||
pre_F64_lstat = 68,
|
||||
sbrk = 69,
|
||||
sstk = 70,
|
||||
mmap = 71,
|
||||
ovadvise = 72,
|
||||
munmap = 73,
|
||||
mprotect = 74,
|
||||
madvise = 75,
|
||||
old_vhangup = 76,
|
||||
kmodcall = 77,
|
||||
mincore = 78,
|
||||
getgroups = 79,
|
||||
setgroups = 80,
|
||||
old_getpgrp = 81,
|
||||
setpgrp = 82,
|
||||
setitimer = 83,
|
||||
old_wait = 84,
|
||||
table = 85,
|
||||
getitimer = 86,
|
||||
gethostname = 87,
|
||||
sethostname = 88,
|
||||
getdtablesize = 89,
|
||||
dup2 = 90,
|
||||
pre_F64_fstat = 91,
|
||||
fcntl = 92,
|
||||
select = 93,
|
||||
poll = 94,
|
||||
fsync = 95,
|
||||
setpriority = 96,
|
||||
socket = 97,
|
||||
connect = 98,
|
||||
old_accept = 99,
|
||||
getpriority = 100,
|
||||
old_send = 101,
|
||||
old_recv = 102,
|
||||
sigreturn = 103,
|
||||
bind = 104,
|
||||
setsockopt = 105,
|
||||
listen = 106,
|
||||
plock = 107,
|
||||
old_sigvec = 108,
|
||||
old_sigblock = 109,
|
||||
old_sigsetmask = 110,
|
||||
sigsuspend = 111,
|
||||
sigstack = 112,
|
||||
old_recvmsg = 113,
|
||||
old_sendmsg = 114,
|
||||
obsolete_vtrcae = 115,
|
||||
gettimeofday = 116,
|
||||
getrusage = 117,
|
||||
getsockopt = 118,
|
||||
numa_syscalls = 119,
|
||||
readv = 120,
|
||||
writev = 121,
|
||||
settimeofday = 122,
|
||||
fchown = 123,
|
||||
fchmod = 124,
|
||||
old_recvfrom = 125,
|
||||
setreuid = 126,
|
||||
setregid = 127,
|
||||
rename = 128,
|
||||
truncate = 129,
|
||||
ftruncate = 130,
|
||||
flock = 131,
|
||||
setgid = 132,
|
||||
sendto = 133,
|
||||
shutdown = 134,
|
||||
socketpair = 135,
|
||||
mkdir = 136,
|
||||
rmdir = 137,
|
||||
utimes = 138,
|
||||
obsolete_42_sigreturn = 139,
|
||||
adjtime = 140,
|
||||
old_getpeername = 141,
|
||||
gethostid = 142,
|
||||
sethostid = 143,
|
||||
getrlimit = 144,
|
||||
setrlimit = 145,
|
||||
old_killpg = 146,
|
||||
setsid = 147,
|
||||
quotactl = 148,
|
||||
oldquota = 149,
|
||||
old_getsockname = 150,
|
||||
pread = 151,
|
||||
pwrite = 152,
|
||||
pid_block = 153,
|
||||
pid_unblock = 154,
|
||||
signal_urti = 155,
|
||||
sigaction = 156,
|
||||
sigwaitprim = 157,
|
||||
nfssvc = 158,
|
||||
getdirentries = 159,
|
||||
pre_F64_statfs = 160,
|
||||
pre_F64_fstatfs = 161,
|
||||
async_daemon = 163,
|
||||
getfh = 164,
|
||||
getdomainname = 165,
|
||||
setdomainname = 166,
|
||||
exportfs = 169,
|
||||
alt_plock = 181,
|
||||
getmnt = 184,
|
||||
alt_sigpending = 187,
|
||||
alt_setsid = 188,
|
||||
swapon = 199,
|
||||
msgctl = 200,
|
||||
msgget = 201,
|
||||
msgrcv = 202,
|
||||
msgsnd = 203,
|
||||
semctl = 204,
|
||||
semget = 205,
|
||||
semop = 206,
|
||||
uname = 207,
|
||||
lchown = 208,
|
||||
shmat = 209,
|
||||
shmctl = 210,
|
||||
shmdt = 211,
|
||||
shmget = 212,
|
||||
mvalid = 213,
|
||||
getaddressconf = 214,
|
||||
msleep = 215,
|
||||
mwakeup = 216,
|
||||
msync = 217,
|
||||
signal = 218,
|
||||
utc_gettime = 219,
|
||||
utc_adjtime = 220,
|
||||
security = 222,
|
||||
kloadcall = 223,
|
||||
stat = 224,
|
||||
lstat = 225,
|
||||
fstat = 226,
|
||||
statfs = 227,
|
||||
fstatfs = 228,
|
||||
getfsstat = 229,
|
||||
gettimeofday64 = 230,
|
||||
settimeofday64 = 231,
|
||||
getpgid = 233,
|
||||
getsid = 234,
|
||||
sigaltstack = 235,
|
||||
waitid = 236,
|
||||
priocntlset = 237,
|
||||
sigsendset = 238,
|
||||
set_speculative = 239,
|
||||
msfs_syscall = 240,
|
||||
sysinfo = 241,
|
||||
uadmin = 242,
|
||||
fuser = 243,
|
||||
proplist_syscall = 244,
|
||||
ntp_adjtime = 245,
|
||||
ntp_gettime = 246,
|
||||
pathconf = 247,
|
||||
fpathconf = 248,
|
||||
sync2 = 249,
|
||||
uswitch = 250,
|
||||
usleep_thread = 251,
|
||||
audcntl = 252,
|
||||
audgen = 253,
|
||||
sysfs = 254,
|
||||
subsys_info = 255,
|
||||
getsysinfo = 256,
|
||||
setsysinfo = 257,
|
||||
afs_syscall = 258,
|
||||
swapctl = 259,
|
||||
memcntl = 260,
|
||||
fdatasync = 261,
|
||||
oflock = 262,
|
||||
_F64_readv = 263,
|
||||
_F64_writev = 264,
|
||||
cdslxlate = 265,
|
||||
sendfile = 266,
|
||||
StandardNumber
|
||||
};
|
||||
|
||||
enum {
|
||||
task_self = 10,
|
||||
thread_reply = 11,
|
||||
task_notify = 12,
|
||||
thread_self = 13,
|
||||
msg_send_trap = 20,
|
||||
msg_receive_trap = 21,
|
||||
msg_rpc_trap = 22,
|
||||
nxm_block = 24,
|
||||
nxm_unblock = 25,
|
||||
nxm_thread_destroy = 29,
|
||||
lw_wire = 30,
|
||||
lw_unwire = 31,
|
||||
nxm_thread_create = 32,
|
||||
nxm_task_init = 33,
|
||||
nxm_idle = 35,
|
||||
nxm_wakeup_idle = 36,
|
||||
nxm_set_pthid = 37,
|
||||
nxm_thread_kill = 38,
|
||||
nxm_thread_block = 39,
|
||||
nxm_thread_wakeup = 40,
|
||||
init_process = 41,
|
||||
nxm_get_binding = 42,
|
||||
map_fd = 43,
|
||||
nxm_resched = 44,
|
||||
nxm_set_cancel = 45,
|
||||
nxm_set_binding = 46,
|
||||
stack_create = 47,
|
||||
nxm_get_state = 48,
|
||||
nxm_thread_suspend = 49,
|
||||
nxm_thread_resume = 50,
|
||||
nxm_signal_check = 51,
|
||||
htg_unix_syscall = 52,
|
||||
host_self = 55,
|
||||
host_priv_self = 56,
|
||||
swtch_pri = 59,
|
||||
swtch = 60,
|
||||
thread_switch = 61,
|
||||
semop_fast = 62,
|
||||
nxm_pshared_init = 63,
|
||||
nxm_pshared_block = 64,
|
||||
nxm_pshared_unblock = 65,
|
||||
nxm_pshared_destroy = 66,
|
||||
nxm_swtch_pri = 67,
|
||||
lw_syscall = 68,
|
||||
mach_sctimes_0 = 70,
|
||||
mach_sctimes_1 = 71,
|
||||
mach_sctimes_2 = 72,
|
||||
mach_sctimes_3 = 73,
|
||||
mach_sctimes_4 = 74,
|
||||
mach_sctimes_5 = 75,
|
||||
mach_sctimes_6 = 76,
|
||||
mach_sctimes_7 = 77,
|
||||
mach_sctimes_8 = 78,
|
||||
mach_sctimes_9 = 79,
|
||||
mach_sctimes_10 = 80,
|
||||
mach_sctimes_11 = 81,
|
||||
mach_sctimes_port_alloc_dealloc = 82,
|
||||
MachNumber
|
||||
};
|
||||
|
||||
static const int Number = StandardNumber + MachNumber;
|
||||
|
||||
static const char *name(int num);
|
||||
|
||||
static bool validSyscallNumber(int num) {
|
||||
return -MachNumber < num && num < StandardNumber;
|
||||
}
|
||||
|
||||
static int convert(int syscall_num) {
|
||||
if (!validSyscallNumber(syscall_num))
|
||||
return -1;
|
||||
|
||||
return syscall_num < 0 ? StandardNumber - syscall_num : syscall_num;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __TRU64_SYSCALLS_HH__
|
49
sim/async.hh
Normal file
49
sim/async.hh
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 __ASYNC_HH__
|
||||
#define __ASYNC_HH__
|
||||
|
||||
///
|
||||
/// @file sim/async.hh
|
||||
/// This file defines flags used to handle asynchronous simulator events.
|
||||
///
|
||||
|
||||
/// @name Asynchronous event flags.
|
||||
/// To avoid races, signal handlers simply set these flags, which are
|
||||
/// then checked in the main event loop. Defined in main.cc.
|
||||
/// @note See the PollQueue object (in pollevent.hh) for the use of async_io and async_alarm.
|
||||
//@{
|
||||
extern volatile bool async_event; ///< Some asynchronous event has happened.
|
||||
extern volatile bool async_dump; ///< Async request to dump stats.
|
||||
extern volatile bool async_exit; ///< Async request to exit simulator.
|
||||
extern volatile bool async_io; ///< Async I/O request (SIGIO).
|
||||
extern volatile bool async_alarm; ///< Async alarm event (SIGALRM).
|
||||
//@}
|
||||
|
||||
#endif // __ASYNC_HH__
|
158
sim/base_cpu.cc
Normal file
158
sim/base_cpu.cc
Normal file
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 <iostream>
|
||||
|
||||
#include "base_cpu.hh"
|
||||
#include "cprintf.hh"
|
||||
#include "stats.hh"
|
||||
#include "exec_context.hh"
|
||||
#include "misc.hh"
|
||||
#include "sim_events.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
vector<BaseCPU *> BaseCPU::cpuList;
|
||||
|
||||
// This variable reflects the max number of threads in any CPU. Be
|
||||
// careful to only use it once all the CPUs that you care about have
|
||||
// been initialized
|
||||
int maxThreadsPerCPU = 1;
|
||||
|
||||
#ifdef FULL_SYSTEM
|
||||
BaseCPU::BaseCPU(const string &_name, int _number_of_threads,
|
||||
Counter max_insts_any_thread,
|
||||
Counter max_insts_all_threads,
|
||||
System *_system, int num, Tick freq)
|
||||
: SimObject(_name), number(num), frequency(freq),
|
||||
number_of_threads(_number_of_threads), system(_system)
|
||||
#else
|
||||
BaseCPU::BaseCPU(const string &_name, int _number_of_threads,
|
||||
Counter max_insts_any_thread,
|
||||
Counter max_insts_all_threads)
|
||||
: SimObject(_name), number_of_threads(_number_of_threads)
|
||||
#endif
|
||||
{
|
||||
// add self to global list of CPUs
|
||||
cpuList.push_back(this);
|
||||
|
||||
if (number_of_threads > maxThreadsPerCPU)
|
||||
maxThreadsPerCPU = number_of_threads;
|
||||
|
||||
// allocate per-thread instruction-based event queues
|
||||
comInsnEventQueue = new (EventQueue *)[number_of_threads];
|
||||
for (int i = 0; i < number_of_threads; ++i)
|
||||
comInsnEventQueue[i] = new EventQueue("instruction-based event queue");
|
||||
|
||||
//
|
||||
// set up instruction-count-based termination events, if any
|
||||
//
|
||||
if (max_insts_any_thread != 0)
|
||||
for (int i = 0; i < number_of_threads; ++i)
|
||||
new SimExitEvent(comInsnEventQueue[i], max_insts_any_thread,
|
||||
"a thread reached the max instruction count");
|
||||
|
||||
if (max_insts_all_threads != 0) {
|
||||
// allocate & initialize shared downcounter: each event will
|
||||
// decrement this when triggered; simulation will terminate
|
||||
// when counter reaches 0
|
||||
int *counter = new int;
|
||||
*counter = number_of_threads;
|
||||
for (int i = 0; i < number_of_threads; ++i)
|
||||
new CountedExitEvent(comInsnEventQueue[i],
|
||||
"all threads reached the max instruction count",
|
||||
max_insts_all_threads, *counter);
|
||||
}
|
||||
|
||||
#ifdef FULL_SYSTEM
|
||||
memset(interrupts, 0, sizeof(interrupts));
|
||||
intstatus = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
BaseCPU::regStats()
|
||||
{
|
||||
int size = contexts.size();
|
||||
if (size > 1) {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
stringstream namestr;
|
||||
ccprintf(namestr, "%s.ctx%d", name(), i);
|
||||
contexts[i]->regStats(namestr.str());
|
||||
}
|
||||
} else if (size == 1)
|
||||
contexts[0]->regStats(name());
|
||||
}
|
||||
|
||||
#ifdef FULL_SYSTEM
|
||||
void
|
||||
BaseCPU::post_interrupt(int int_num, int index)
|
||||
{
|
||||
DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
|
||||
|
||||
if (int_num < 0 || int_num >= NumInterruptLevels)
|
||||
panic("int_num out of bounds\n");
|
||||
|
||||
if (index < 0 || index >= sizeof(uint8_t) * 8)
|
||||
panic("int_num out of bounds\n");
|
||||
|
||||
AlphaISA::check_interrupts = 1;
|
||||
interrupts[int_num] |= 1 << index;
|
||||
intstatus |= (ULL(1) << int_num);
|
||||
}
|
||||
|
||||
void
|
||||
BaseCPU::clear_interrupt(int int_num, int index)
|
||||
{
|
||||
DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
|
||||
|
||||
if (int_num < 0 || int_num >= NumInterruptLevels)
|
||||
panic("int_num out of bounds\n");
|
||||
|
||||
if (index < 0 || index >= sizeof(uint8_t) * 8)
|
||||
panic("int_num out of bounds\n");
|
||||
|
||||
interrupts[int_num] &= ~(1 << index);
|
||||
if (interrupts[int_num] == 0)
|
||||
intstatus &= ~(ULL(1) << int_num);
|
||||
}
|
||||
|
||||
void
|
||||
BaseCPU::clear_interrupts()
|
||||
{
|
||||
DPRINTF(Interrupt, "Interrupts all cleared\n");
|
||||
|
||||
memset(interrupts, 0, sizeof(interrupts));
|
||||
intstatus = 0;
|
||||
}
|
||||
|
||||
#endif // FULL_SYSTEM
|
||||
|
||||
DEFINE_SIM_OBJECT_CLASS_NAME("BaseCPU", BaseCPU)
|
122
sim/base_cpu.hh
Normal file
122
sim/base_cpu.hh
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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_CPU_HH__
|
||||
#define __BASE_CPU_HH__
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "eventq.hh"
|
||||
#include "sim_object.hh"
|
||||
|
||||
#include "isa_traits.hh" // for Addr
|
||||
|
||||
#ifdef FULL_SYSTEM
|
||||
class System;
|
||||
#endif
|
||||
|
||||
class BranchPred;
|
||||
class ExecContext;
|
||||
|
||||
class BaseCPU : public SimObject
|
||||
{
|
||||
#ifdef FULL_SYSTEM
|
||||
protected:
|
||||
int number;
|
||||
Tick frequency;
|
||||
uint8_t interrupts[NumInterruptLevels];
|
||||
uint64_t intstatus;
|
||||
|
||||
public:
|
||||
virtual void post_interrupt(int int_num, int index);
|
||||
virtual void clear_interrupt(int int_num, int index);
|
||||
virtual void clear_interrupts();
|
||||
|
||||
bool check_interrupt(int int_num) const {
|
||||
if (int_num > NumInterruptLevels)
|
||||
panic("int_num out of bounds\n");
|
||||
|
||||
return interrupts[int_num] != 0;
|
||||
}
|
||||
|
||||
bool check_interrupts() const { return intstatus != 0; }
|
||||
uint64_t intr_status() const { return intstatus; }
|
||||
|
||||
Tick getFreq() const { return frequency; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
std::vector<ExecContext *> contexts;
|
||||
|
||||
public:
|
||||
virtual void execCtxStatusChg() {}
|
||||
|
||||
public:
|
||||
|
||||
#ifdef FULL_SYSTEM
|
||||
BaseCPU(const std::string &_name, int _number_of_threads,
|
||||
Counter max_insts_any_thread, Counter max_insts_all_threads,
|
||||
System *_system,
|
||||
int num, Tick freq);
|
||||
#else
|
||||
BaseCPU(const std::string &_name, int _number_of_threads,
|
||||
Counter max_insts_any_thread = 0,
|
||||
Counter max_insts_all_threads = 0);
|
||||
#endif
|
||||
|
||||
virtual ~BaseCPU() {}
|
||||
|
||||
virtual void regStats();
|
||||
|
||||
/// Number of threads we're actually simulating (<= SMT_MAX_THREADS).
|
||||
/// This is a constant for the duration of the simulation.
|
||||
int number_of_threads;
|
||||
|
||||
/// Vector of per-thread instruction-based event queues. Used for
|
||||
/// scheduling events based on number of instructions committed by
|
||||
/// a particular thread.
|
||||
EventQueue **comInsnEventQueue;
|
||||
|
||||
#ifdef FULL_SYSTEM
|
||||
System *system;
|
||||
#endif
|
||||
|
||||
virtual bool filterThisInstructionPrefetch(int thread_number,
|
||||
short asid, Addr prefetchTarget) const { return true; }
|
||||
|
||||
/// Return pointer to CPU's branch predictor (NULL if none).
|
||||
virtual BranchPred *getBranchPred() { return NULL; };
|
||||
|
||||
private:
|
||||
static std::vector<BaseCPU *> cpuList; //!< Static global cpu list
|
||||
|
||||
public:
|
||||
static int numSimulatedCPUs() { return cpuList.size(); }
|
||||
};
|
||||
|
||||
#endif // __BASE_CPU_HH__
|
166
sim/cache/lzss_compression.cc
vendored
Normal file
166
sim/cache/lzss_compression.cc
vendored
Normal file
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "lzss_compression.hh"
|
||||
|
||||
#include "misc.hh" //for fatal
|
||||
|
||||
int
|
||||
LZSSCompression::findSubString(uint8_t *src, int front, int back, int size)
|
||||
{
|
||||
int subSize = 0;
|
||||
int max_length = 2048;
|
||||
if (size - back < max_length) {
|
||||
max_length = size - back;
|
||||
}
|
||||
for (int i = 0; i < max_length; ++i) {
|
||||
if (src[front+i] != src[back+i]) {
|
||||
return subSize;
|
||||
}
|
||||
++subSize;
|
||||
}
|
||||
return subSize;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
for (int j = 0; j < i; ++j) {
|
||||
int sub_size = findSubString(src, j, i, size);
|
||||
if (sub_size >= L) {
|
||||
L = sub_size;
|
||||
P = j;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
100
sim/cache/lzss_compression.hh
vendored
Normal file
100
sim/cache/lzss_compression.hh
vendored
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 "host.hh" // for uint8_t
|
||||
|
||||
/**
|
||||
* Simple LZSS compression scheme.
|
||||
*/
|
||||
class LZSSCompression
|
||||
{
|
||||
/**
|
||||
* Finds the longest substrings that start at the given offsets.
|
||||
* @param src The source block that we search for substrings.
|
||||
* @param front The smaller offset.
|
||||
* @param back The larger offset.
|
||||
* @param size The size of the source block.
|
||||
* @return The size of the longest substring.
|
||||
*/
|
||||
int findSubString(uint8_t *src, int front, int back, int size);
|
||||
|
||||
/**
|
||||
* 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__
|
72
sim/cache/null_compression.hh
vendored
Normal file
72
sim/cache/null_compression.hh
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 __NULL_COMPRESSION_HH__
|
||||
#define __NULL_COMPRESSION_HH__
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file defines a doNothing compression algorithm.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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 //__NULL_COMPRESSION_HH__
|
137
sim/debug.cc
Normal file
137
sim/debug.cc
Normal file
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "debug.hh"
|
||||
#include "eventq.hh"
|
||||
#include "param.hh"
|
||||
#include "sim_events.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void
|
||||
debug_break()
|
||||
{
|
||||
kill(getpid(), SIGTRAP);
|
||||
}
|
||||
|
||||
//
|
||||
// Debug event: place a breakpoint on the process function and
|
||||
// schedule the event to break at a particular cycle
|
||||
//
|
||||
class DebugBreakEvent : public Event
|
||||
{
|
||||
public:
|
||||
|
||||
DebugBreakEvent(EventQueue *q, Tick _when);
|
||||
|
||||
void process(); // process event
|
||||
virtual const char *description();
|
||||
};
|
||||
|
||||
//
|
||||
// constructor: schedule at specified time
|
||||
//
|
||||
DebugBreakEvent::DebugBreakEvent(EventQueue *q, Tick _when)
|
||||
: Event(q)
|
||||
{
|
||||
schedule(_when, -20000);
|
||||
}
|
||||
|
||||
//
|
||||
// handle debug event: set debugger breakpoint on this function
|
||||
//
|
||||
void
|
||||
DebugBreakEvent::process()
|
||||
{
|
||||
debug_break();
|
||||
delete this;
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
DebugBreakEvent::description()
|
||||
{
|
||||
return "debug break";
|
||||
}
|
||||
|
||||
//
|
||||
// Parameter context for global debug options
|
||||
//
|
||||
class DebugContext : public ParamContext
|
||||
{
|
||||
public:
|
||||
DebugContext(const string &_iniSection)
|
||||
: ParamContext(_iniSection) {}
|
||||
void checkParams();
|
||||
};
|
||||
|
||||
DebugContext debugParams("debug");
|
||||
|
||||
VectorParam<Tick> break_cycles(&debugParams, "break_cycles",
|
||||
"cycle(s) to create breakpoint events");
|
||||
|
||||
void
|
||||
DebugContext::checkParams()
|
||||
{
|
||||
if (break_cycles.isValid()) {
|
||||
vector<Tick> &cycles = break_cycles;
|
||||
|
||||
vector<Tick>::iterator i = cycles.begin();
|
||||
vector<Tick>::iterator end = cycles.end();
|
||||
|
||||
for (; i < end; ++i)
|
||||
new DebugBreakEvent(&mainEventQueue, *i);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// handy function to schedule DebugBreakEvent on main event queue
|
||||
// (callable from debugger)
|
||||
//
|
||||
extern "C" void sched_break_cycle(Tick when)
|
||||
{
|
||||
new DebugBreakEvent(&mainEventQueue, when);
|
||||
}
|
||||
|
||||
extern "C" void dump_stats()
|
||||
{
|
||||
new DumpStatsEvent();
|
||||
}
|
||||
|
||||
extern "C" void eventq_dump()
|
||||
{
|
||||
mainEventQueue.dump();
|
||||
}
|
||||
|
34
sim/debug.hh
Normal file
34
sim/debug.hh
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 __DEBUG_HH__
|
||||
#define __DEBUG_HH__
|
||||
|
||||
void debug_break();
|
||||
|
||||
#endif // __DEBUG_HH__
|
212
sim/eventq.cc
Normal file
212
sim/eventq.cc
Normal file
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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 <assert.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include "smt.hh"
|
||||
#include "misc.hh"
|
||||
|
||||
#include "eventq.hh"
|
||||
#include "trace.hh"
|
||||
#include "universe.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
const string Event::defaultName("event");
|
||||
|
||||
//
|
||||
// Main Event Queue
|
||||
//
|
||||
// Events on this queue are processed at the *beginning* of each
|
||||
// cycle, before the pipeline simulation is performed.
|
||||
//
|
||||
EventQueue mainEventQueue("Main Event Queue");
|
||||
|
||||
void
|
||||
EventQueue::insert(Event *event)
|
||||
{
|
||||
if (head == NULL || event->when() < head->when() ||
|
||||
(event->when() == head->when() &&
|
||||
event->priority() <= head->priority())) {
|
||||
event->next = head;
|
||||
head = event;
|
||||
} else {
|
||||
Event *prev = head;
|
||||
Event *curr = head->next;
|
||||
|
||||
while (curr) {
|
||||
if (event->when() <= curr->when() &&
|
||||
(event->when() < curr->when() ||
|
||||
event->priority() <= curr->priority()))
|
||||
break;
|
||||
|
||||
prev = curr;
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
event->next = curr;
|
||||
prev->next = event;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EventQueue::remove(Event *event)
|
||||
{
|
||||
if (head == NULL)
|
||||
return;
|
||||
|
||||
if (head == event){
|
||||
head = event->next;
|
||||
return;
|
||||
}
|
||||
|
||||
Event *prev = head;
|
||||
Event *curr = head->next;
|
||||
while (curr && curr != event) {
|
||||
prev = curr;
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
if (curr == event)
|
||||
prev->next = curr->next;
|
||||
}
|
||||
|
||||
void
|
||||
EventQueue::serviceOne()
|
||||
{
|
||||
Event *event = head;
|
||||
event->clearFlags(Event::Scheduled);
|
||||
head = event->next;
|
||||
|
||||
// handle action
|
||||
if (!event->squashed())
|
||||
event->process();
|
||||
else
|
||||
event->clearFlags(Event::Squashed);
|
||||
|
||||
if (event->getFlags(Event::AutoDelete))
|
||||
delete event;
|
||||
}
|
||||
|
||||
void
|
||||
EventQueue::nameChildren()
|
||||
{
|
||||
int j = 0;
|
||||
|
||||
Event *event = head;
|
||||
while (event) {
|
||||
stringstream stream;
|
||||
ccprintf(stream, "%s.event%d", name(), j++);
|
||||
event->setName(stream.str());
|
||||
|
||||
event = event->next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EventQueue::serialize()
|
||||
{
|
||||
string objects = "";
|
||||
|
||||
Event *event = head;
|
||||
while (event) {
|
||||
objects += event->name();
|
||||
objects += " ";
|
||||
event->serialize();
|
||||
|
||||
event = event->next;
|
||||
}
|
||||
nameOut("Serialized");
|
||||
paramOut("objects",objects);
|
||||
}
|
||||
|
||||
void
|
||||
EventQueue::dump()
|
||||
{
|
||||
cprintf("============================================================\n");
|
||||
cprintf("EventQueue Dump (cycle %d)\n", curTick);
|
||||
cprintf("------------------------------------------------------------\n");
|
||||
|
||||
if (empty())
|
||||
cprintf("<No Events>\n");
|
||||
else {
|
||||
Event *event = head;
|
||||
while (event) {
|
||||
event->dump();
|
||||
event = event->next;
|
||||
}
|
||||
}
|
||||
|
||||
cprintf("============================================================\n");
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
Event::description()
|
||||
{
|
||||
return "generic";
|
||||
}
|
||||
|
||||
#if TRACING_ON
|
||||
void
|
||||
Event::trace(const char *action)
|
||||
{
|
||||
// This DPRINTF is unconditional because calls to this function
|
||||
// are protected by an 'if (DTRACE(Event))' in the inlined Event
|
||||
// methods.
|
||||
//
|
||||
// This is just a default implementation for derived classes where
|
||||
// it's not worth doing anything special. If you want to put a
|
||||
// more informative message in the trace, override this method on
|
||||
// the particular subclass where you have the information that
|
||||
// needs to be printed.
|
||||
DPRINTFN("%s event %s @ %d\n", description(), action, when());
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
Event::dump()
|
||||
{
|
||||
#if TRACING_ON
|
||||
cprintf(" Created: %d\n", when_created);
|
||||
#endif
|
||||
if (scheduled()) {
|
||||
#if TRACING_ON
|
||||
cprintf(" Scheduled at %d\n", when_scheduled);
|
||||
#endif
|
||||
cprintf(" Scheduled for %d\n", when());
|
||||
}
|
||||
else {
|
||||
cprintf(" Not Scheduled\n");
|
||||
}
|
||||
}
|
351
sim/eventq.hh
Normal file
351
sim/eventq.hh
Normal file
|
@ -0,0 +1,351 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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
|
||||
* EventQueue interfaces
|
||||
*/
|
||||
|
||||
#ifndef __EVENTQ_HH__
|
||||
#define __EVENTQ_HH__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "host.hh" // for Tick
|
||||
|
||||
#include "fast_alloc.hh"
|
||||
#include "serialize.hh"
|
||||
#include "trace.hh"
|
||||
|
||||
class EventQueue; // forward declaration
|
||||
|
||||
/*
|
||||
* An item on an event queue. The action caused by a given
|
||||
* event is specified by deriving a subclass and overriding the
|
||||
* process() member function.
|
||||
*/
|
||||
class Event : public Serializeable, public FastAlloc
|
||||
{
|
||||
friend class EventQueue;
|
||||
|
||||
private:
|
||||
/// queue to which this event belongs (though it may or may not be
|
||||
/// scheduled on this queue yet)
|
||||
EventQueue *queue;
|
||||
|
||||
Event *next;
|
||||
|
||||
Tick _when; //!< timestamp when event should be processed
|
||||
int _priority; //!< event priority
|
||||
char _flags;
|
||||
|
||||
protected:
|
||||
enum Flags {
|
||||
None = 0x0,
|
||||
Squashed = 0x1,
|
||||
Scheduled = 0x2,
|
||||
AutoDelete = 0x4
|
||||
};
|
||||
|
||||
bool getFlags(Flags f) const { return (_flags & f) == f; }
|
||||
void setFlags(Flags f) { _flags |= f; }
|
||||
void clearFlags(Flags f) { _flags &= ~f; }
|
||||
|
||||
protected:
|
||||
EventQueue *theQueue() const { return queue; }
|
||||
|
||||
#if TRACING_ON
|
||||
Tick when_created; //!< Keep track of creation time For debugging
|
||||
Tick when_scheduled; //!< Keep track of creation time For debugging
|
||||
|
||||
virtual void trace(const char *action); //!< trace event activity
|
||||
#else
|
||||
void trace(const char *) {}
|
||||
#endif
|
||||
|
||||
unsigned annotated_value;
|
||||
|
||||
public:
|
||||
|
||||
static const std::string defaultName;
|
||||
|
||||
/*
|
||||
* Event constructor
|
||||
* @param queue that the event gets scheduled on
|
||||
*/
|
||||
Event(EventQueue *q, int p = 0)
|
||||
: Serializeable(defaultName), queue(q), next(NULL),
|
||||
_priority(p), _flags(None),
|
||||
#if TRACING_ON
|
||||
when_created(curTick), when_scheduled(0),
|
||||
#endif
|
||||
annotated_value(0)
|
||||
{
|
||||
}
|
||||
|
||||
~Event() {}
|
||||
|
||||
/// Determine if the current event is scheduled
|
||||
bool scheduled() const { return getFlags(Scheduled); }
|
||||
|
||||
/// Schedule the event with the current priority or default priority
|
||||
void schedule(Tick t);
|
||||
|
||||
/// Schedule the event with a specific priority
|
||||
void schedule(Tick t, int priority);
|
||||
|
||||
/// Reschedule the event with the current priority
|
||||
void reschedule(Tick t);
|
||||
|
||||
/// Reschedule the event with a specific priority
|
||||
void reschedule(Tick t, int priority);
|
||||
|
||||
/// Remove the event from the current schedule
|
||||
void deschedule();
|
||||
|
||||
/// Return a C string describing the event. This string should
|
||||
/// *not* be dynamically allocated; just a const char array
|
||||
/// describing the event class.
|
||||
virtual const char *description();
|
||||
|
||||
/// Dump the current event data
|
||||
void dump();
|
||||
|
||||
/*
|
||||
* This member function is invoked when the event is processed
|
||||
* (occurs). There is no default implementation; each subclass
|
||||
* must provide its own implementation. The event is not
|
||||
* automatically deleted after it is processed (to allow for
|
||||
* statically allocated event objects).
|
||||
*
|
||||
* If the AutoDestroy flag is set, the object is deleted once it
|
||||
* is processed.
|
||||
*/
|
||||
virtual void process() = 0;
|
||||
|
||||
void annotate(unsigned value) { annotated_value = value; };
|
||||
unsigned annotation() { return annotated_value; }
|
||||
|
||||
/// Squash the current event
|
||||
void squash() { setFlags(Squashed); }
|
||||
|
||||
/// Check whether the event is squashed
|
||||
bool squashed() { return getFlags(Squashed); }
|
||||
|
||||
/// Get the time that the event is scheduled
|
||||
Tick when() const { return _when; }
|
||||
|
||||
/// Get the event priority
|
||||
int priority() const { return _priority; }
|
||||
|
||||
struct priority_compare :
|
||||
public std::binary_function<Event *, Event *, bool>
|
||||
{
|
||||
bool operator()(const Event *l, const Event *r) const {
|
||||
return l->when() >= r->when() || l->priority() >= r->priority();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template <class T, void (T::* F)()>
|
||||
void
|
||||
DelayFunction(Tick when, T *object)
|
||||
{
|
||||
class DelayEvent : public Event
|
||||
{
|
||||
private:
|
||||
T *object;
|
||||
|
||||
public:
|
||||
DelayEvent(Tick when, T *o)
|
||||
: Event(&mainEventQueue), object(o)
|
||||
{ setFlags(AutoDestroy); schedule(when); }
|
||||
void process() { (object->*F)(); }
|
||||
const char *description() { return "delay"; }
|
||||
};
|
||||
|
||||
new DelayEvent(when, object);
|
||||
}
|
||||
|
||||
/*
|
||||
* Queue of events sorted in time order
|
||||
*/
|
||||
class EventQueue : public Serializeable
|
||||
{
|
||||
private:
|
||||
Event *head;
|
||||
|
||||
void insert(Event *event);
|
||||
void remove(Event *event);
|
||||
|
||||
public:
|
||||
|
||||
// constructor
|
||||
EventQueue(const std::string &n)
|
||||
: Serializeable(n), head(NULL)
|
||||
{}
|
||||
|
||||
// schedule the given event on this queue
|
||||
void schedule(Event *ev);
|
||||
void deschedule(Event *ev);
|
||||
void reschedule(Event *ev);
|
||||
|
||||
Tick nextTick() { return head->when(); }
|
||||
void serviceOne();
|
||||
|
||||
// process all events up to the given timestamp. we inline a
|
||||
// quick test to see if there are any events to process; if so,
|
||||
// call the internal out-of-line version to process them all.
|
||||
void serviceEvents(Tick when) {
|
||||
while (!empty()) {
|
||||
if (nextTick() > when)
|
||||
break;
|
||||
|
||||
assert(head->when() >= when && "event scheduled in the past");
|
||||
serviceOne();
|
||||
}
|
||||
}
|
||||
|
||||
// default: process all events up to 'now' (curTick)
|
||||
void serviceEvents() { serviceEvents(curTick); }
|
||||
|
||||
// return true if no events are queued
|
||||
bool empty() { return head == NULL; }
|
||||
|
||||
void dump();
|
||||
|
||||
Tick nextEventTime() { return empty() ? curTick : head->when(); }
|
||||
|
||||
virtual void nameChildren();
|
||||
virtual void serialize();
|
||||
};
|
||||
|
||||
|
||||
//////////////////////
|
||||
//
|
||||
// inline functions
|
||||
//
|
||||
// can't put these inside declaration due to circular dependence
|
||||
// between Event and EventQueue classes.
|
||||
//
|
||||
//////////////////////
|
||||
|
||||
// schedule at specified time (place on event queue specified via
|
||||
// constructor)
|
||||
inline void
|
||||
Event::schedule(Tick t)
|
||||
{
|
||||
assert(!scheduled());
|
||||
setFlags(Scheduled);
|
||||
#if TRACING_ON
|
||||
when_scheduled = curTick;
|
||||
#endif
|
||||
_when = t;
|
||||
queue->schedule(this);
|
||||
}
|
||||
|
||||
inline void
|
||||
Event::schedule(Tick t, int p)
|
||||
{
|
||||
_priority = p;
|
||||
schedule(t);
|
||||
}
|
||||
|
||||
inline void
|
||||
Event::deschedule()
|
||||
{
|
||||
assert(scheduled());
|
||||
|
||||
clearFlags(Squashed);
|
||||
clearFlags(Scheduled);
|
||||
queue->deschedule(this);
|
||||
}
|
||||
|
||||
inline void
|
||||
Event::reschedule(Tick t)
|
||||
{
|
||||
assert(scheduled());
|
||||
clearFlags(Squashed);
|
||||
|
||||
#if TRACING_ON
|
||||
when_scheduled = curTick;
|
||||
#endif
|
||||
_when = t;
|
||||
queue->reschedule(this);
|
||||
}
|
||||
|
||||
inline void
|
||||
Event::reschedule(Tick t, int p)
|
||||
{
|
||||
_priority = p;
|
||||
reschedule(t);
|
||||
}
|
||||
|
||||
inline void
|
||||
EventQueue::schedule(Event *event)
|
||||
{
|
||||
insert(event);
|
||||
if (DTRACE(Event))
|
||||
event->trace("scheduled");
|
||||
}
|
||||
|
||||
inline void
|
||||
EventQueue::deschedule(Event *event)
|
||||
{
|
||||
remove(event);
|
||||
if (DTRACE(Event))
|
||||
event->trace("descheduled");
|
||||
}
|
||||
|
||||
inline void
|
||||
EventQueue::reschedule(Event *event)
|
||||
{
|
||||
remove(event);
|
||||
insert(event);
|
||||
if (DTRACE(Event))
|
||||
event->trace("rescheduled");
|
||||
}
|
||||
|
||||
|
||||
//////////////////////
|
||||
//
|
||||
// Main Event Queue
|
||||
//
|
||||
// Events on this queue are processed at the *beginning* of each
|
||||
// cycle, before the pipeline simulation is performed.
|
||||
//
|
||||
// defined in eventq.cc
|
||||
//
|
||||
//////////////////////
|
||||
extern EventQueue mainEventQueue;
|
||||
|
||||
#endif // __EVENTQ_HH__
|
106
sim/exec_context.cc
Normal file
106
sim/exec_context.cc
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright (c) 2003 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_cpu.hh"
|
||||
#include "exec_context.hh"
|
||||
|
||||
#ifdef FULL_SYSTEM
|
||||
#include "system.hh"
|
||||
#else
|
||||
#include "prog.hh"
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
// constructor
|
||||
#ifdef FULL_SYSTEM
|
||||
ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
|
||||
AlphaItb *_itb, AlphaDtb *_dtb,
|
||||
FunctionalMemory *_mem, int _cpu_id)
|
||||
: kernelStats(this, _cpu), cpu(_cpu), thread_num(_thread_num), mem(_mem),
|
||||
itb(_itb), dtb(_dtb), cpu_id(_cpu_id), system(_sys),
|
||||
memCtrl(_sys->memCtrl), physmem(_sys->physmem)
|
||||
{
|
||||
memset(®s, 0, sizeof(RegFile));
|
||||
_status = Active;
|
||||
func_exe_insn = 0;
|
||||
storeCondFailures = 0;
|
||||
system->registerExecContext(this);
|
||||
}
|
||||
#else
|
||||
ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
|
||||
Process *_process, int _asid)
|
||||
: cpu(_cpu), thread_num(_thread_num), process(_process), asid (_asid)
|
||||
{
|
||||
|
||||
// Register with process object. Our 'active' will be set by the
|
||||
// process iff we're the initial context. Others are reserved for
|
||||
// dynamically created threads.
|
||||
process->registerExecContext(this);
|
||||
|
||||
mem = process->getMemory();
|
||||
|
||||
func_exe_insn = 0;
|
||||
storeCondFailures = 0;
|
||||
}
|
||||
|
||||
ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
|
||||
FunctionalMemory *_mem, int _asid)
|
||||
: cpu(_cpu), thread_num(_thread_num), process(NULL), mem(_mem),
|
||||
asid(_asid)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ExecContext::setStatus(Status new_status)
|
||||
{
|
||||
#ifdef FULL_SYSTEM
|
||||
if (status() == new_status)
|
||||
return;
|
||||
|
||||
// Don't change the status from active if there are pending interrupts
|
||||
if (new_status == Suspended && cpu->check_interrupts()) {
|
||||
assert(status() == Active);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
_status = new_status;
|
||||
cpu->execCtxStatusChg();
|
||||
}
|
||||
|
||||
void
|
||||
ExecContext::regStats(const string &name)
|
||||
{
|
||||
#ifdef FULL_SYSTEM
|
||||
kernelStats.regStats(name + ".kern");
|
||||
#endif
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue